Skip to content

Commit

Permalink
drivers: flash: implement wp-gpios and hold-gpios
Browse files Browse the repository at this point in the history
This commit adds the wp-gpios and hold-gpios found in jedec,spi-nor compatible to spi_nor.c.  The wp-gpios (write protect) is implemented.  The hold-gpios (hold) is only initialized to it's inactive state.

Signed-off-by: J.P. Hutchins <jp@intercreate.io>
  • Loading branch information
JPHutchins committed May 27, 2023
1 parent 1889353 commit d551e5b
Showing 1 changed file with 77 additions and 5 deletions.
82 changes: 77 additions & 5 deletions drivers/flash/spi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,27 @@ LOG_MODULE_REGISTER(spi_nor, CONFIG_FLASH_LOG_LEVEL);
#define SPI_NOR_MAX_ADDR_WIDTH 4

#if DT_INST_NODE_HAS_PROP(0, t_enter_dpd)
#define T_DP_MS DIV_ROUND_UP(DT_INST_PROP(0, t_enter_dpd), NSEC_PER_MSEC)
#define T_DP_MS ceiling_fraction(DT_INST_PROP(0, t_enter_dpd), NSEC_PER_MSEC)
#else /* T_ENTER_DPD */
#define T_DP_MS 0
#endif /* T_ENTER_DPD */
#if DT_INST_NODE_HAS_PROP(0, t_exit_dpd)
#define T_RES1_MS DIV_ROUND_UP(DT_INST_PROP(0, t_exit_dpd), NSEC_PER_MSEC)
#define T_RES1_MS ceiling_fraction(DT_INST_PROP(0, t_exit_dpd), NSEC_PER_MSEC)
#endif /* T_EXIT_DPD */
#if DT_INST_NODE_HAS_PROP(0, dpd_wakeup_sequence)
#define T_DPDD_MS DIV_ROUND_UP(DT_INST_PROP_BY_IDX(0, dpd_wakeup_sequence, 0), NSEC_PER_MSEC)
#define T_CRDP_MS DIV_ROUND_UP(DT_INST_PROP_BY_IDX(0, dpd_wakeup_sequence, 1), NSEC_PER_MSEC)
#define T_RDP_MS DIV_ROUND_UP(DT_INST_PROP_BY_IDX(0, dpd_wakeup_sequence, 2), NSEC_PER_MSEC)
#define T_DPDD_MS ceiling_fraction(DT_INST_PROP_BY_IDX(0, dpd_wakeup_sequence, 0), NSEC_PER_MSEC)
#define T_CRDP_MS ceiling_fraction(DT_INST_PROP_BY_IDX(0, dpd_wakeup_sequence, 1), NSEC_PER_MSEC)
#define T_RDP_MS ceiling_fraction(DT_INST_PROP_BY_IDX(0, dpd_wakeup_sequence, 2), NSEC_PER_MSEC)
#else /* DPD_WAKEUP_SEQUENCE */
#define T_DPDD_MS 0
#endif /* DPD_WAKEUP_SEQUENCE */

#define _INST_HAS_WP_OR(inst) DT_INST_NODE_HAS_PROP(inst, wp_gpios) ||
#define ANY_INST_HAS_WP_GPIOS DT_INST_FOREACH_STATUS_OKAY(_INST_HAS_WP_OR) 0

#define _INST_HAS_HOLD_OR(inst) DT_INST_NODE_HAS_PROP(inst, hold_gpios) ||
#define ANY_INST_HAS_HOLD_GPIOS DT_INST_FOREACH_STATUS_OKAY(_INST_HAS_HOLD_OR) 0

/* Build-time data associated with the device. */
struct spi_nor_config {
/* Devicetree SPI configuration */
Expand Down Expand Up @@ -101,6 +107,15 @@ struct spi_nor_config {
* This information cannot be derived from SFDP.
*/
uint8_t has_lock;

#if ANY_INST_HAS_WP_GPIOS
/* The write-protect GPIO (wp-gpios) */
const struct gpio_dt_spec *wp;
#endif
#if ANY_INST_HAS_HOLD_GPIOS
/* The hold GPIO (hold-gpios) */
const struct gpio_dt_spec *hold;
#endif
};

/**
Expand Down Expand Up @@ -798,8 +813,17 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size)
*/
static int spi_nor_write_protection_set(const struct device *dev, bool write_protect)
{
#if ANY_INST_HAS_WP_GPIOS
const struct spi_nor_config *cfg = dev->config;
#endif
int ret;

#if ANY_INST_HAS_WP_GPIOS
if (cfg->wp) {
gpio_pin_set_dt(cfg->wp, write_protect);
}
#endif

ret = spi_nor_cmd_write(dev, (write_protect) ? SPI_NOR_CMD_WRDI : SPI_NOR_CMD_WREN);

if (IS_ENABLED(DT_INST_PROP(0, requires_ulbpr)) && (ret == 0) && !write_protect) {
Expand Down Expand Up @@ -1220,12 +1244,37 @@ static int spi_nor_configure(const struct device *dev)
*/
static int spi_nor_init(const struct device *dev)
{
#if (ANY_INST_HAS_WP_GPIOS || ANY_INST_HAS_HOLD_GPIOS)
const struct spi_nor_config *cfg = dev->config;
#endif

if (IS_ENABLED(CONFIG_MULTITHREADING)) {
struct spi_nor_data *const driver_data = dev->data;

k_sem_init(&driver_data->sem, 1, K_SEM_MAX_LIMIT);
}

#if ANY_INST_HAS_WP_GPIOS
if (cfg->wp) {
if (!device_is_ready(cfg->wp->port)) {
return -ENODEV;
}
if (gpio_pin_configure_dt(cfg->wp, GPIO_OUTPUT_ACTIVE)) {
return -ENODEV;
}
}
#endif /* ANY_INST_HAS_WP_GPIOS */
#if ANY_INST_HAS_HOLD_GPIOS
if (cfg->hold) {
if (!device_is_ready(cfg->hold->port)) {
return -ENODEV;
}
if (gpio_pin_configure_dt(cfg->hold, GPIO_OUTPUT_INACTIVE)) {
return -ENODEV;
}
}
#endif /* ANY_INST_HAS_HOLD_GPIOS */

return spi_nor_configure(dev);
}

Expand Down Expand Up @@ -1319,6 +1368,21 @@ BUILD_ASSERT(DT_INST_PROP(0, has_lock) == (DT_INST_PROP(0, has_lock) & 0xFF),
"Need support for lock clear beyond SR1");
#endif

#define INST_HAS_WP_GPIO(idx) DT_INST_NODE_HAS_PROP(idx, wp_gpios)

#define INST_WP_GPIO_SPEC(idx) \
IF_ENABLED(INST_HAS_WP_GPIO(idx), (static const struct gpio_dt_spec wp_##idx = \
GPIO_DT_SPEC_INST_GET(idx, wp_gpios);))

#define INST_HAS_HOLD_GPIO(idx) DT_INST_NODE_HAS_PROP(idx, hold_gpios)

#define INST_HOLD_GPIO_SPEC(idx) \
IF_ENABLED(INST_HAS_HOLD_GPIO(idx), (static const struct gpio_dt_spec hold_##idx = \
GPIO_DT_SPEC_INST_GET(idx, hold_gpios);))

INST_WP_GPIO_SPEC(0)
INST_HOLD_GPIO_SPEC(0)

static const struct spi_nor_config spi_nor_config_0 = {
.spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8), CONFIG_SPI_NOR_CS_WAIT_DELAY),
#if !defined(CONFIG_SPI_NOR_SFDP_RUNTIME)
Expand Down Expand Up @@ -1347,6 +1411,14 @@ static const struct spi_nor_config spi_nor_config_0 = {
#endif /* CONFIG_SPI_NOR_SFDP_DEVICETREE */

#endif /* CONFIG_SPI_NOR_SFDP_RUNTIME */

#if DT_INST_NODE_HAS_PROP(0, wp_gpios)
.wp = &wp_0,
#endif

#if DT_INST_NODE_HAS_PROP(0, hold_gpios)
.hold = &hold_0,
#endif
};

static struct spi_nor_data spi_nor_data_0;
Expand Down

0 comments on commit d551e5b

Please sign in to comment.