Lines Matching +full:cs +full:- +full:hold +full:- +full:time
2 * Copyright (c) 2018 Savoir-Faire Linux.
8 * SPDX-License-Identifier: Apache-2.0
36 * * Some devices support a Deep Power-Down mode which reduces current
41 * * PM_DEVICE_STATE_SUSPENDED corresponds to deep-power-down mode;
63 #define DEV_CFG(_dev_) ((const struct spi_nor_config * const) (_dev_)->config)
66 /* MXICY Low-power/high perf mode is second bit in configuration register 2 */
72 /* Build-time data associated with the device. */
92 /* Expected JEDEC ID, from jedec-id property */
96 /* Optional support for entering 32-bit address mode. */
101 /* Length of BFP structure, in 32-bit words. */
105 * (little-endian stored words), from sfdp-bfp property
118 /* The write-protect GPIO (wp-gpios) */
123 /* The hold GPIO (hold-gpios) */
124 const struct gpio_dt_spec hold; member
145 /* exist flags for dts opt-ins */
156 * struct spi_nor_data - Structure for defining the SPI NOR access
162 /* Low 32-bits of uptime counter at which device last entered
163 * deep power-down.
170 /* If set addressed operations should use 32-bit rather than
171 * 24-bit addresses.
174 * explicitly specifies 24-bit or 32-bit addressing.
227 /* Page writes range from sub-ms to 10ms */
246 if (IS_ENABLED(ANY_INST_USE_4B_ADDR_OPCODES) && DEV_CFG(dev)->use_4b_addr_opcodes) { in dev_erase_types()
251 const struct spi_nor_data *data = dev->data; in dev_erase_types()
253 return data->erase_types; in dev_erase_types()
263 const struct spi_nor_data *data = dev->data; in dev_flash_size()
265 return data->flash_size; in dev_flash_size()
267 const struct spi_nor_config *cfg = dev->config; in dev_flash_size()
269 return cfg->flash_size; in dev_flash_size()
281 const struct spi_nor_data *data = dev->data; in dev_page_size()
283 return data->page_size; in dev_page_size()
292 /* Capture the time at which the device entered deep power-down. */
296 const struct spi_nor_config *const driver_config = dev->config; in record_entered_dpd()
298 if (driver_config->dpd_exist) { in record_entered_dpd()
299 struct spi_nor_data *const driver_data = dev->data; in record_entered_dpd()
301 driver_data->ts_enter_dpd = k_uptime_get_32(); in record_entered_dpd()
309 /* Check the current time against the time DPD was entered and delay
314 const struct spi_nor_config *const driver_config = dev->config; in delay_until_exit_dpd_ok()
316 if (driver_config->dpd_exist) { in delay_until_exit_dpd_ok()
317 struct spi_nor_data *const driver_data = dev->data; in delay_until_exit_dpd_ok()
318 int32_t since = (int32_t)(k_uptime_get_32() - driver_data->ts_enter_dpd); in delay_until_exit_dpd_ok()
320 /* If the time is negative the 32-bit counter has wrapped, in delay_until_exit_dpd_ok()
327 /* Subtract time required for DPD to be reached */ in delay_until_exit_dpd_ok()
328 since -= driver_config->t_enter_dpd; in delay_until_exit_dpd_ok()
330 /* Subtract time required in DPD before exit */ in delay_until_exit_dpd_ok()
331 since -= driver_config->t_dpdd_ms; in delay_until_exit_dpd_ok()
333 /* If the adjusted time is negative we have to wait in delay_until_exit_dpd_ok()
337 k_sleep(K_MSEC((uint32_t)-since)); in delay_until_exit_dpd_ok()
349 /* Indicates that addressed access uses a 24-bit address regardless of
354 /* Indicates that addressed access uses a 32-bit address regardless of
380 const struct spi_nor_config *const driver_cfg = dev->config; in spi_nor_access()
381 struct spi_nor_data *const driver_data = dev->data; in spi_nor_access()
402 && driver_data->flag_access_32bit)); in spi_nor_access()
430 return spi_write_dt(&driver_cfg->spi, &tx_set); in spi_nor_access()
433 return spi_transceive_dt(&driver_cfg->spi, &tx_set, &rx_set); in spi_nor_access()
512 /* READ_SFDP requires a 24-bit address followed by a single in read_sfdp()
513 * byte for a wait state. This is effected by using 32-bit in read_sfdp()
514 * address by shifting the 24-bit address up 8 bits. in read_sfdp()
525 const struct spi_nor_config *cfg = dev->config; in enter_dpd()
527 if (cfg->dpd_exist) { in enter_dpd()
540 const struct spi_nor_config *cfg = dev->config; in exit_dpd()
542 if (cfg->dpd_exist) { in exit_dpd()
545 if (cfg->dpd_wakeup_sequence_exist) { in exit_dpd()
550 * control CSn so fake it by writing a known-supported in exit_dpd()
551 * single-byte command, hoping that'll hold the assert in exit_dpd()
558 k_sleep(K_MSEC(cfg->t_rdp_ms)); in exit_dpd()
565 if (cfg->dpd_exist) { in exit_dpd()
566 k_sleep(K_MSEC(cfg->t_exit_dpd)); in exit_dpd()
579 const struct spi_nor_config *cfg = dev->config; in acquire_device()
582 struct spi_nor_data *const driver_data = dev->data; in acquire_device()
584 k_sem_take(&driver_data->sem, K_FOREVER); in acquire_device()
587 (void)pm_device_runtime_get(cfg->spi.bus); in acquire_device()
593 const struct spi_nor_config *cfg = dev->config; in release_device()
595 (void)pm_device_runtime_put(cfg->spi.bus); in release_device()
598 struct spi_nor_data *const driver_data = dev->data; in release_device()
600 k_sem_give(&driver_data->sem); in release_device()
612 * @return the non-negative value of the status register, or an error code.
663 * @return the non-negative value of the configuration register, or an error code.
667 const struct spi_nor_config *cfg = dev->config; in mxicy_rdcr()
668 uint16_t cr = -ENOSYS; in mxicy_rdcr()
670 if (cfg->mxicy_mx25r_power_mode_exist) { in mxicy_rdcr()
695 const struct spi_nor_config *cfg = dev->config; in mxicy_wrcr()
696 int ret = -ENOSYS; in mxicy_wrcr()
703 if (cfg->mxicy_mx25r_power_mode_exist) { in mxicy_wrcr()
736 const struct spi_nor_config *cfg = dev->config; in mxicy_configure()
737 int ret = -ENOSYS; in mxicy_configure()
739 if (cfg->mxicy_mx25r_power_mode_exist) { in mxicy_configure()
740 /* Low-power/high perf mode is second bit in configuration register 2 */ in mxicy_configure()
746 const bool use_high_perf = cfg->mxicy_mx25r_power_mode; in mxicy_configure()
796 return -EINVAL; in spi_nor_read()
801 return -EIO; in spi_nor_read()
806 if (IS_ENABLED(ANY_INST_USE_4B_ADDR_OPCODES) && DEV_CFG(dev)->use_4b_addr_opcodes) { in spi_nor_read()
833 return -EIO; in flash_spi_nor_ex_op()
846 ret = -ENOTSUP; in flash_spi_nor_ex_op()
866 return -EINVAL; in spi_nor_write()
871 return -EIO; in spi_nor_write()
886 if (((addr + to_write - 1U) / page_size) in spi_nor_write()
888 to_write = page_size - (addr % page_size); in spi_nor_write()
898 DEV_CFG(dev)->use_4b_addr_opcodes) { in spi_nor_write()
915 size -= to_write; in spi_nor_write()
946 return -EINVAL; in spi_nor_erase()
949 /* address must be sector-aligned */ in spi_nor_erase()
951 return -EINVAL; in spi_nor_erase()
956 return -EINVAL; in spi_nor_erase()
961 return -EIO; in spi_nor_erase()
976 size -= flash_size; in spi_nor_erase()
986 if ((etp->exp != 0) in spi_nor_erase()
987 && SPI_NOR_IS_ALIGNED(addr, etp->exp) in spi_nor_erase()
988 && (size >= BIT(etp->exp)) in spi_nor_erase()
990 || (etp->exp > bet->exp))) { in spi_nor_erase()
996 DEV_CFG(dev)->use_4b_addr_opcodes) { in spi_nor_erase()
997 ret = spi_nor_cmd_addr_write_4b(dev, bet->cmd, addr, NULL, in spi_nor_erase()
1000 ret = spi_nor_cmd_addr_write(dev, bet->cmd, addr, NULL, 0); in spi_nor_erase()
1002 addr += BIT(bet->exp); in spi_nor_erase()
1003 size -= BIT(bet->exp); in spi_nor_erase()
1007 ret = -EINVAL; in spi_nor_erase()
1037 const struct spi_nor_config *cfg = dev->config; in spi_nor_write_protection_set()
1040 if (DEV_CFG(dev)->wp_gpios_exist && write_protect == false) { in spi_nor_write_protection_set()
1041 gpio_pin_set_dt(&(DEV_CFG(dev)->wp), 0); in spi_nor_write_protection_set()
1048 if (cfg->requires_ulbpr_exist in spi_nor_write_protection_set()
1055 if (DEV_CFG(dev)->wp_gpios_exist && write_protect == true) { in spi_nor_write_protection_set()
1056 gpio_pin_set_dt(&(DEV_CFG(dev)->wp), 1); in spi_nor_write_protection_set()
1069 return -EIO; in spi_nor_sfdp_read()
1089 return -EINVAL; in spi_nor_read_jedec_id()
1093 return -EIO; in spi_nor_read_jedec_id()
1110 * (cleared) if the device is configured for 4-byte (3-byte) addresses
1115 * @param enter_4byte_addr the Enter 4-Byte Addressing bit set from
1119 * @retval -ENOTSUP if 4-byte addressing is supported but not in a way
1122 * @retval 0 if the device is successfully left in 24-bit mode or
1123 * reconfigured to 32-bit mode.
1130 LOG_DBG("Checking enter-4byte-addr %02x", enter_4byte_addr); in spi_nor_set_address_mode()
1140 /* This currently only supports command 0xB7 (Enter 4-Byte in spi_nor_set_address_mode()
1142 * Or when BIT(3) is set where the 4-byte address mode can be entered in spi_nor_set_address_mode()
1147 return -ENOTSUP; in spi_nor_set_address_mode()
1153 /* Enter 4-byte address mode by setting BIT(7) in a register in spi_nor_set_address_mode()
1173 struct spi_nor_data *data = dev->data; in spi_nor_set_address_mode()
1175 data->flag_access_32bit = true; in spi_nor_set_address_mode()
1189 struct spi_nor_data *data = dev->data; in spi_nor_process_bfp()
1190 struct jesd216_erase_type *etp = data->erase_types; in spi_nor_process_bfp()
1193 LOG_INF("%s: %u %ciBy flash", dev->name, in spi_nor_process_bfp()
1201 memset(data->erase_types, 0, sizeof(data->erase_types)); in spi_nor_process_bfp()
1202 for (uint8_t ti = 1; ti <= ARRAY_SIZE(data->erase_types); ++ti) { in spi_nor_process_bfp()
1204 LOG_DBG("Erase %u with %02x", (uint32_t)BIT(etp->exp), etp->cmd); in spi_nor_process_bfp()
1209 data->page_size = jesd216_bfp_page_size(php, bfp); in spi_nor_process_bfp()
1211 data->flash_size = flash_size; in spi_nor_process_bfp()
1215 return -EINVAL; in spi_nor_process_bfp()
1219 LOG_DBG("Page size %u bytes", data->page_size); in spi_nor_process_bfp()
1221 /* If 4-byte addressing is supported, switch to it. */ in spi_nor_process_bfp()
1226 if (IS_ENABLED(ANY_INST_USE_4B_ADDR_OPCODES) && DEV_CFG(dev)->use_4b_addr_opcodes) { in spi_nor_process_bfp()
1227 LOG_DBG("4-byte addressing supported, using it via specific opcodes"); in spi_nor_process_bfp()
1236 LOG_ERR("Unable to enter 4-byte mode: %d\n", rc); in spi_nor_process_bfp()
1248 struct spi_nor_data *dev_data = dev->data; in spi_nor_process_sfdp()
1270 return -EINVAL; in spi_nor_process_sfdp()
1273 LOG_INF("%s: SFDP v %u.%u AP %x with %u PH", dev->name, in spi_nor_process_sfdp()
1274 hp->rev_major, hp->rev_minor, hp->access, 1 + hp->nph); in spi_nor_process_sfdp()
1276 const struct jesd216_param_header *php = hp->phdr; in spi_nor_process_sfdp()
1277 const struct jesd216_param_header *phpe = php + MIN(decl_nph, 1 + hp->nph); in spi_nor_process_sfdp()
1283 (int)(php - hp->phdr), id, php->rev_major, php->rev_minor, in spi_nor_process_sfdp()
1284 php->len_dw, jesd216_param_addr(php)); in spi_nor_process_sfdp()
1288 uint32_t dw[MIN(php->len_dw, 20)]; in spi_nor_process_sfdp()
1306 DEV_CFG(dev)->use_4b_addr_opcodes) { in spi_nor_process_sfdp()
1320 MIN(sizeof(uint32_t) * php->len_dw, sizeof(u2.dw))); in spi_nor_process_sfdp()
1325 struct jesd216_erase_type *etp = &dev_data->erase_types[ei]; in spi_nor_process_sfdp()
1329 etp->exp = 0; in spi_nor_process_sfdp()
1330 etp->cmd = 0; in spi_nor_process_sfdp()
1332 etp->cmd = cmd; in spi_nor_process_sfdp()
1340 LOG_ERR("4-byte addressing not supported"); in spi_nor_process_sfdp()
1341 return -ENOTSUP; in spi_nor_process_sfdp()
1351 const struct spi_nor_config *cfg = dev->config; in spi_nor_process_sfdp()
1353 .len_dw = cfg->bfp_len, in spi_nor_process_sfdp()
1356 rc = spi_nor_process_bfp(dev, &bfp_hdr, cfg->bfp); in spi_nor_process_sfdp()
1368 struct spi_nor_data *data = dev->data; in setup_pages_layout()
1374 for (size_t i = 0; i < ARRAY_SIZE(data->erase_types); ++i) { in setup_pages_layout()
1375 const struct jesd216_erase_type *etp = &data->erase_types[i]; in setup_pages_layout()
1377 if ((etp->cmd != 0) in setup_pages_layout()
1378 && ((exp == 0) || (etp->exp < exp))) { in setup_pages_layout()
1379 exp = etp->exp; in setup_pages_layout()
1384 return -ENOTSUP; in setup_pages_layout()
1395 return -EINVAL; in setup_pages_layout()
1406 data->layout.pages_size = layout_page_size; in setup_pages_layout()
1407 data->layout.pages_count = flash_size / layout_page_size; in setup_pages_layout()
1408 LOG_DBG("layout %zu x %zu By pages", data->layout.pages_count, data->layout.pages_size); in setup_pages_layout()
1410 const struct spi_nor_config *cfg = dev->config; in setup_pages_layout()
1411 const struct flash_pages_layout *layout = &cfg->layout; in setup_pages_layout()
1413 size_t layout_size = layout->pages_size * layout->pages_count; in setup_pages_layout()
1417 flash_size, layout->pages_count, layout->pages_size); in setup_pages_layout()
1418 return -EINVAL; in setup_pages_layout()
1438 const struct spi_nor_config *cfg = dev->config; in spi_nor_configure()
1442 /* Validate bus and CS is ready */ in spi_nor_configure()
1443 if (!spi_is_ready_dt(&cfg->spi)) { in spi_nor_configure()
1444 return -ENODEV; in spi_nor_configure()
1449 if (cfg->reset_gpios_exist) { in spi_nor_configure()
1450 if (!gpio_is_ready_dt(&cfg->reset)) { in spi_nor_configure()
1452 return -ENODEV; in spi_nor_configure()
1454 if (gpio_pin_configure_dt(&cfg->reset, GPIO_OUTPUT_ACTIVE)) { in spi_nor_configure()
1456 return -ENODEV; in spi_nor_configure()
1458 rc = gpio_pin_set_dt(&cfg->reset, 0); in spi_nor_configure()
1465 /* After a soft-reset the flash might be in DPD or busy writing/erasing. in spi_nor_configure()
1474 return -ENODEV; in spi_nor_configure()
1485 return -ENODEV; in spi_nor_configure()
1495 return -ENODEV; in spi_nor_configure()
1504 if (memcmp(jedec_id, cfg->jedec_id, sizeof(jedec_id)) != 0) { in spi_nor_configure()
1507 cfg->jedec_id[0], cfg->jedec_id[1], cfg->jedec_id[2]); in spi_nor_configure()
1508 return -EINVAL; in spi_nor_configure()
1517 if (cfg->has_lock != 0) { in spi_nor_configure()
1524 rc = spi_nor_wrsr(dev, rc & ~cfg->has_lock); in spi_nor_configure()
1531 return -ENODEV; in spi_nor_configure()
1539 if (cfg->enter_4byte_addr != 0) { in spi_nor_configure()
1540 rc = spi_nor_set_address_mode(dev, cfg->enter_4byte_addr); in spi_nor_configure()
1543 LOG_ERR("Unable to enter 4-byte mode: %d\n", rc); in spi_nor_configure()
1544 return -ENODEV; in spi_nor_configure()
1555 return -ENODEV; in spi_nor_configure()
1562 return -ENODEV; in spi_nor_configure()
1568 if (cfg->mxicy_mx25r_power_mode_exist) { in spi_nor_configure()
1607 rc = -ENOSYS; in spi_nor_pm_control()
1622 struct spi_nor_data *const driver_data = dev->data; in spi_nor_init()
1624 k_sem_init(&driver_data->sem, 1, K_SEM_MAX_LIMIT); in spi_nor_init()
1628 if (DEV_CFG(dev)->wp_gpios_exist) { in spi_nor_init()
1629 if (!device_is_ready(DEV_CFG(dev)->wp.port)) { in spi_nor_init()
1630 LOG_ERR("Write-protect pin not ready"); in spi_nor_init()
1631 return -ENODEV; in spi_nor_init()
1633 if (gpio_pin_configure_dt(&(DEV_CFG(dev)->wp), GPIO_OUTPUT_ACTIVE)) { in spi_nor_init()
1634 LOG_ERR("Write-protect pin failed to set active"); in spi_nor_init()
1635 return -ENODEV; in spi_nor_init()
1640 if (DEV_CFG(dev)->hold_gpios_exist) { in spi_nor_init()
1641 if (!device_is_ready(DEV_CFG(dev)->hold.port)) { in spi_nor_init()
1642 LOG_ERR("Hold pin not ready"); in spi_nor_init()
1643 return -ENODEV; in spi_nor_init()
1645 if (gpio_pin_configure_dt(&(DEV_CFG(dev)->hold), GPIO_OUTPUT_INACTIVE)) { in spi_nor_init()
1646 LOG_ERR("Hold pin failed to set inactive"); in spi_nor_init()
1647 return -ENODEV; in spi_nor_init()
1663 const struct spi_nor_data *data = dev->data; in spi_nor_pages_layout()
1665 *layout = &data->layout; in spi_nor_pages_layout()
1667 const struct spi_nor_config *cfg = dev->config; in spi_nor_pages_layout()
1669 *layout = &cfg->layout; in spi_nor_pages_layout()
1712 "jedec,spi-nor size required for non-runtime SFDP page layout"); \
1728 "jedec,spi-nor sfdp-bfp required for devicetree SFDP"); \
1733 "jedec,spi-nor jedec-id required for non-runtime SFDP"); \
1772 #define INIT_HOLD_GPIOS(idx) .hold = GPIO_DT_SPEC_INST_GET_OR(idx, hold_gpios, {0})