Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/spi nor flash wp hold pins #58365

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions drivers/flash/spi_nor.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2018 Savoir-Faire Linux.
* Copyright (c) 2020 Peter Bigot Consulting, LLC
* Copyright (c) 2023 Intercreate, Inc.
*
* This driver is heavily inspired from the spi_flash_w25qxxdv.c SPI NOR driver.
*
Expand Down Expand Up @@ -62,6 +63,14 @@ LOG_MODULE_REGISTER(spi_nor, CONFIG_FLASH_LOG_LEVEL);
#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

#define DEV_CFG(_dev_) ((const struct spi_nor_config * const) (_dev_)->config)

/* Build-time data associated with the device. */
struct spi_nor_config {
/* Devicetree SPI configuration */
Expand Down Expand Up @@ -102,6 +111,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 @@ -824,6 +842,12 @@ static int spi_nor_write_protection_set(const struct device *dev,
{
int ret;

#if ANY_INST_HAS_WP_GPIOS
if (DEV_CFG(dev)->wp && write_protect == false) {
gpio_pin_set_dt(DEV_CFG(dev)->wp, 0);
}
#endif

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

Expand All @@ -833,6 +857,12 @@ static int spi_nor_write_protection_set(const struct device *dev,
ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_ULBPR);
}

#if ANY_INST_HAS_WP_GPIOS
if (DEV_CFG(dev)->wp && write_protect == true) {
gpio_pin_set_dt(DEV_CFG(dev)->wp, 1);
}
#endif

return ret;
}

Expand Down Expand Up @@ -1306,6 +1336,31 @@ static int spi_nor_init(const struct device *dev)
k_sem_init(&driver_data->sem, 1, K_SEM_MAX_LIMIT);
}

#if ANY_INST_HAS_WP_GPIOS
if (DEV_CFG(dev)->wp) {
if (!device_is_ready(DEV_CFG(dev)->wp->port)) {
LOG_ERR("Write-protect pin not ready");
return -ENODEV;
}
if (gpio_pin_configure_dt(DEV_CFG(dev)->wp, GPIO_OUTPUT_ACTIVE)) {
LOG_ERR("Write-protect pin failed to set active");
return -ENODEV;
}
}
#endif /* ANY_INST_HAS_WP_GPIOS */
#if ANY_INST_HAS_HOLD_GPIOS
if (DEV_CFG(dev)->hold) {
if (!device_is_ready(DEV_CFG(dev)->hold->port)) {
LOG_ERR("Hold pin not ready");
return -ENODEV;
}
if (gpio_pin_configure_dt(DEV_CFG(dev)->hold, GPIO_OUTPUT_INACTIVE)) {
LOG_ERR("Hold pin failed to set inactive");
return -ENODEV;
}
}
#endif /* ANY_INST_HAS_HOLD_GPIOS */

return spi_nor_configure(dev);
}

Expand Down Expand Up @@ -1402,6 +1457,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),
Expand Down Expand Up @@ -1431,6 +1501,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
61 changes: 61 additions & 0 deletions tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2023 Intercreate, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Build test for jedec,spi-nor compatible (drivers/flash/spi_nor.c)
*/

/ {
aliases {
spi-flash0 = &mx25v1635fzui;
};
};

/delete-node/ &mx25r64;

&pinctrl {
spi0_default: spi0_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 9)>,
<NRF_PSEL(SPIM_MOSI, 0, 11)>,
<NRF_PSEL(SPIM_MISO, 0, 12)>;
};
};

spi0_sleep: spi0_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 9)>,
<NRF_PSEL(SPIM_MOSI, 0, 11)>,
<NRF_PSEL(SPIM_MISO, 0, 12)>;
low-power-enable;
};
};
};

&spi0 {
compatible = "nordic,nrf-spim";
status = "okay";
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; // mx25v16
pinctrl-0 = <&spi0_default>;
pinctrl-1 = <&spi0_sleep>;
pinctrl-names = "default", "sleep";

mx25v1635fzui: mx25v1635fzui@0 {
compatible = "jedec,spi-nor";
status = "okay";
reg = <0>;
spi-max-frequency = <8000000>; // chip supports 80Mhz, SPI0 supports 8MHz
size = <0x1000000>; // bits
has-dpd;
t-enter-dpd = <10000>;
t-exit-dpd = <45000>;
jedec-id = [ C2 23 15 ];
sfdp-bfp = [
e5 20 f1 ff ff ff ff 00 44 eb 08 6b 08 3b 04 bb
ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52
10 d8 00 ff 23 72 f1 00 82 ec 04 c2 44 83 48 44
30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff
];
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2023 Intercreate, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Build test for jedec,spi-nor compatible (drivers/flash/spi_nor.c) wp-gpios and hold-gpios
*/

/ {
aliases {
spi-flash0 = &mx25v1635fzui;
};
};

/delete-node/ &mx25r64;

&pinctrl {
spi0_default: spi0_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 9)>,
<NRF_PSEL(SPIM_MOSI, 0, 11)>,
<NRF_PSEL(SPIM_MISO, 0, 12)>;
};
};

spi0_sleep: spi0_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 9)>,
<NRF_PSEL(SPIM_MOSI, 0, 11)>,
<NRF_PSEL(SPIM_MISO, 0, 12)>;
low-power-enable;
};
};
};

&spi0 {
compatible = "nordic,nrf-spim";
status = "okay";
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; // mx25v16
pinctrl-0 = <&spi0_default>;
pinctrl-1 = <&spi0_sleep>;
pinctrl-names = "default", "sleep";

mx25v1635fzui: mx25v1635fzui@0 {
compatible = "jedec,spi-nor";
status = "okay";
reg = <0>;
spi-max-frequency = <8000000>; // chip supports 80Mhz, SPI0 supports 8MHz
size = <0x1000000>; // bits
hold-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
has-dpd;
t-enter-dpd = <10000>;
t-exit-dpd = <45000>;
jedec-id = [ C2 23 15 ];
sfdp-bfp = [
e5 20 f1 ff ff ff ff 00 44 eb 08 6b 08 3b 04 bb
ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52
10 d8 00 ff 23 72 f1 00 82 ec 04 c2 44 83 48 44
30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff
];
};
};
10 changes: 10 additions & 0 deletions tests/drivers/flash/common/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,13 @@ tests:
platform_allow: mr_canhubk3
extra_configs:
- CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME=y
drivers.flash.common.spi_nor:
platform_allow: nrf52840dk_nrf52840
extra_args:
- OVERLAY_CONFIG=boards/nrf52840dk_flash_spi.conf
- DTC_OVERLAY_FILE=boards/nrf52840dk_spi_nor.overlay
drivers.flash.common.spi_nor_wp_hold:
platform_allow: nrf52840dk_nrf52840
extra_args:
- OVERLAY_CONFIG=boards/nrf52840dk_flash_spi.conf
- DTC_OVERLAY_FILE=boards/nrf52840dk_spi_nor_wp_hold.overlay
Loading