Skip to content

Commit 1d59f95

Browse files
TomChang19kartben
authored andcommitted
drivers: flash: npcx: avoid obstruction by eSPI TAF when EC access flash
This commit applies the arbitration when EC and eSPI TAF access flash. Signed-off-by: Tom Chang <[email protected]>
1 parent de3da0e commit 1d59f95

File tree

1 file changed

+99
-6
lines changed

1 file changed

+99
-6
lines changed

drivers/flash/flash_npcx_fiu_nor.c

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
#include <zephyr/logging/log.h>
2424
LOG_MODULE_REGISTER(flash_npcx_fiu_nor, CONFIG_FLASH_LOG_LEVEL);
2525

26+
#if defined(CONFIG_ESPI_TAF)
27+
static const struct device *const espi_dev = DEVICE_DT_GET(DT_NODELABEL(espi0));
28+
#endif
29+
2630
#define BLOCK_64K_SIZE KB(64)
2731
#define BLOCK_4K_SIZE KB(4)
2832

@@ -47,6 +51,8 @@ struct flash_npcx_nor_config {
4751

4852
/* Device data */
4953
struct flash_npcx_nor_data {
54+
/* mutex for flash write and erase operation */
55+
struct k_sem nor_flash_sem;
5056
/* Specific control operation for Quad-SPI Nor Flash */
5157
uint32_t operation;
5258
};
@@ -192,16 +198,32 @@ static int flash_npcx_nor_write_status_regs(const struct device *dev, uint8_t *s
192198
#if defined(CONFIG_FLASH_JESD216_API)
193199
static int flash_npcx_nor_read_jedec_id(const struct device *dev, uint8_t *id)
194200
{
201+
int ret;
202+
195203
if (id == NULL) {
196204
return -EINVAL;
197205
}
198206

199-
return flash_npcx_uma_read(dev, SPI_NOR_CMD_RDID, id, SPI_NOR_MAX_ID_LEN);
207+
#if defined(CONFIG_ESPI_TAF)
208+
if (espi_taf_npcx_block(espi_dev, true) != 0) {
209+
LOG_ERR("TAF LOCK TIMEOUT");
210+
return -ETIMEDOUT;
211+
}
212+
#endif
213+
214+
ret = flash_npcx_uma_read(dev, SPI_NOR_CMD_RDID, id, SPI_NOR_MAX_ID_LEN);
215+
216+
#if defined(CONFIG_ESPI_TAF)
217+
espi_taf_npcx_block(espi_dev, false);
218+
#endif
219+
220+
return ret;
200221
}
201222

202223
static int flash_npcx_nor_read_sfdp(const struct device *dev, off_t addr,
203224
void *data, size_t size)
204225
{
226+
int ret;
205227
uint8_t sfdp_addr[4];
206228
struct npcx_uma_cfg cfg = { .opcode = JESD216_CMD_READ_SFDP,
207229
.tx_buf = sfdp_addr,
@@ -217,8 +239,22 @@ static int flash_npcx_nor_read_sfdp(const struct device *dev, off_t addr,
217239
sfdp_addr[0] = (addr >> 16) & 0xff;
218240
sfdp_addr[1] = (addr >> 8) & 0xff;
219241
sfdp_addr[2] = addr & 0xff;
220-
return flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_WRITE |
242+
243+
#if defined(CONFIG_ESPI_TAF)
244+
if (espi_taf_npcx_block(espi_dev, true) != 0) {
245+
LOG_ERR("TAF LOCK TIMEOUT");
246+
return -ETIMEDOUT;
247+
}
248+
#endif
249+
250+
ret = flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_WRITE |
221251
NPCX_UMA_ACCESS_READ);
252+
253+
#if defined(CONFIG_ESPI_TAF)
254+
espi_taf_npcx_block(espi_dev, false);
255+
#endif
256+
257+
return ret;
222258
}
223259
#endif /* CONFIG_FLASH_JESD216_API */
224260

@@ -260,32 +296,47 @@ static int flash_npcx_nor_read(const struct device *dev, off_t addr,
260296
static int flash_npcx_nor_erase(const struct device *dev, off_t addr, size_t size)
261297
{
262298
const struct flash_npcx_nor_config *config = dev->config;
299+
struct flash_npcx_nor_data *dev_data = dev->data;
263300
int ret = 0;
264301

302+
k_sem_take(&dev_data->nor_flash_sem, K_FOREVER);
303+
265304
/* Out of the region of nor flash device? */
266305
if (!is_within_region(addr, size, 0, config->flash_size)) {
267306
LOG_ERR("Addr %ld, size %d are out of range", addr, size);
268-
return -EINVAL;
307+
ret = -EINVAL;
308+
goto out_nor_erase;
269309
}
270310

271311
/* address must be sector-aligned */
272312
if (!SPI_NOR_IS_SECTOR_ALIGNED(addr)) {
273313
LOG_ERR("Addr %ld is not sector-aligned", addr);
274-
return -EINVAL;
314+
ret = -EINVAL;
315+
goto out_nor_erase;
275316
}
276317

277318
/* size must be a multiple of sectors */
278319
if ((size % BLOCK_4K_SIZE) != 0) {
279320
LOG_ERR("Size %d is not a multiple of sectors", size);
280-
return -EINVAL;
321+
ret = -EINVAL;
322+
goto out_nor_erase;
281323
}
282324

325+
#if defined(CONFIG_ESPI_TAF)
326+
if (espi_taf_npcx_block(espi_dev, true) != 0) {
327+
LOG_ERR("TAF LOCK TIMEOUT");
328+
ret = -ETIMEDOUT;
329+
goto out_nor_erase;
330+
}
331+
#endif
332+
283333
/* Select erase opcode by size */
284334
if (size == config->flash_size) {
285335
flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN);
286336
/* Send chip erase command */
287337
flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_CE);
288-
return flash_npcx_nor_wait_until_ready(dev);
338+
ret = flash_npcx_nor_wait_until_ready(dev);
339+
goto out_nor_erase_unblock;
289340
}
290341

291342
while (size > 0) {
@@ -305,6 +356,12 @@ static int flash_npcx_nor_erase(const struct device *dev, off_t addr, size_t siz
305356
break;
306357
}
307358
}
359+
out_nor_erase_unblock:
360+
#if defined(CONFIG_ESPI_TAF)
361+
espi_taf_npcx_block(espi_dev, false);
362+
#endif
363+
out_nor_erase:
364+
k_sem_give(&dev_data->nor_flash_sem);
308365

309366
return ret;
310367
}
@@ -313,12 +370,16 @@ static int flash_npcx_nor_write(const struct device *dev, off_t addr,
313370
const void *data, size_t size)
314371
{
315372
const struct flash_npcx_nor_config *config = dev->config;
373+
struct flash_npcx_nor_data *dev_data = dev->data;
316374
uint8_t *tx_buf = (uint8_t *)data;
317375
int ret = 0;
318376
size_t sz_write;
319377

378+
k_sem_take(&dev_data->nor_flash_sem, K_FOREVER);
379+
320380
/* Out of the region of nor flash device? */
321381
if (!is_within_region(addr, size, 0, config->flash_size)) {
382+
k_sem_give(&dev_data->nor_flash_sem);
322383
return -EINVAL;
323384
}
324385

@@ -338,20 +399,38 @@ static int flash_npcx_nor_write(const struct device *dev, off_t addr,
338399
}
339400

340401
while (size > 0) {
402+
#if defined(CONFIG_ESPI_TAF)
403+
if (espi_taf_npcx_block(espi_dev, true) != 0) {
404+
LOG_ERR("TAF LOCK TIMEOUT");
405+
k_sem_give(&dev_data->nor_flash_sem);
406+
407+
return -ETIMEDOUT;
408+
}
409+
#endif
341410
/* Start to write */
342411
flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN);
343412
ret = flash_npcx_uma_write_by_addr(dev, SPI_NOR_CMD_PP, tx_buf,
344413
sz_write, addr);
345414
if (ret != 0) {
415+
#if defined(CONFIG_ESPI_TAF)
416+
espi_taf_npcx_block(espi_dev, false);
417+
#endif
346418
break;
347419
}
348420

349421
/* Wait for writing completed */
350422
ret = flash_npcx_nor_wait_until_ready(dev);
351423
if (ret != 0) {
424+
#if defined(CONFIG_ESPI_TAF)
425+
espi_taf_npcx_block(espi_dev, false);
426+
#endif
352427
break;
353428
}
354429

430+
#if defined(CONFIG_ESPI_TAF)
431+
espi_taf_npcx_block(espi_dev, false);
432+
#endif
433+
355434
size -= sz_write;
356435
tx_buf += sz_write;
357436
addr += sz_write;
@@ -363,6 +442,8 @@ static int flash_npcx_nor_write(const struct device *dev, off_t addr,
363442
}
364443
}
365444

445+
k_sem_give(&dev_data->nor_flash_sem);
446+
366447
return ret;
367448
}
368449

@@ -462,7 +543,16 @@ static int flash_npcx_nor_ex_op(const struct device *dev, uint16_t code,
462543
}
463544
#endif
464545

546+
#if defined(CONFIG_ESPI_TAF)
547+
if (espi_taf_npcx_block(espi_dev, true) != 0) {
548+
LOG_ERR("TAF LOCK TIMEOUT");
549+
return -ETIMEDOUT;
550+
}
551+
#endif
465552
ret = flash_npcx_nor_ex_exec_uma(dev, op_in, op_out);
553+
#if defined(CONFIG_ESPI_TAF)
554+
espi_taf_npcx_block(espi_dev, false);
555+
#endif
466556
#ifdef CONFIG_USERSPACE
467557
if (ret == 0 && syscall_trap) {
468558
K_OOPS(k_usermode_to_copy(out, op_out, sizeof(out_copy)));
@@ -532,6 +622,7 @@ static DEVICE_API(flash, flash_npcx_nor_driver_api) = {
532622
static int flash_npcx_nor_init(const struct device *dev)
533623
{
534624
const struct flash_npcx_nor_config *config = dev->config;
625+
struct flash_npcx_nor_data *dev_data = dev->data;
535626
int ret;
536627

537628
if (!IS_ENABLED(CONFIG_FLASH_NPCX_FIU_NOR_INIT)) {
@@ -594,6 +685,8 @@ static int flash_npcx_nor_init(const struct device *dev)
594685
qspi_npcx_fiu_set_spi_size(config->qspi_bus, &config->qspi_cfg);
595686
}
596687

688+
k_sem_init(&dev_data->nor_flash_sem, 1, 1);
689+
597690
return 0;
598691
}
599692

0 commit comments

Comments
 (0)