Skip to content
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
2 changes: 1 addition & 1 deletion boards/arm/mimxrt1010_evk/mimxrt1010_evk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ arduino_serial: &lpuart1 {};
&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(16)>;
at25sf128a: at25sf128a@0 {
compatible = "adesto,at25sf128a", "jedec,spi-nor";
compatible = "nxp,imx-flexspi-nor";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be fine to have this be:

compatible = "adesto,at25sf128a", "nxp,imx-flexspi-nor";

Then if somebody has an Adesto-specific driver it'd be picked up. It also makes more clear exactly what the flash chip is. Not required, but suggested.

The same applies to all the other flash device nodes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how this makes the flash chip more clear, but for it to work I think we'd need a compatible something like nxp,imx-flexspi-nor-at25sf128a. Because an Adesto-specific driver would be different for each of the various SoC QSPI peripherals.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that's necessarily true. I'm thinking this would be useful in somebody's out-of-tree application where they didn't care that the underlying peripheral isn't represented in the compatible name, but their needs are such that their dedicated custom driver is preferred over the stock Zephyr one.

The primary purpose of the compatible is to accurately describe the device that's present in hardware, not the driver implementation to talk to that device. Kconfig figures out the best device. QSPI bus devices are perhaps an extreme case of this, but could be supported if we used jedec,qspi-nor and have the vendor-specific drivers all support that compatible, if it weren't for the fact the vendor drivers tend to need vendor-specific devicetree properties.

size = <134217728>;
label = "AT25SF128A";
reg = <0>;
Expand Down
2 changes: 1 addition & 1 deletion boards/arm/mimxrt1015_evk/mimxrt1015_evk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ arduino_serial: &lpuart4 {};
&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(16)>;
at25sf128a: at25sf128a@0 {
compatible = "adesto,at25sf128a", "jedec,spi-nor";
compatible = "nxp,imx-flexspi-nor";
size = <134217728>;
label = "AT25SF128A";
reg = <0>;
Expand Down
2 changes: 1 addition & 1 deletion boards/arm/mimxrt1020_evk/mimxrt1020_evk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ arduino_serial: &lpuart2 {};
&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(8)>;
is25wp064: is25wp064@0 {
compatible = "issi,is25wp064", "jedec,spi-nor";
compatible = "nxp,imx-flexspi-nor";
size = <67108864>;
label = "IS25WP064";
reg = <0>;
Expand Down
7 changes: 5 additions & 2 deletions boards/arm/mimxrt1050_evk/mimxrt1050_evk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,12 @@ arduino_serial: &lpuart3 {};

&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(64)>;
hyperflash0: hyperflash@0 {
compatible = "cypress,s26ks512s";
s26ks512s0: s26ks512s@0 {
compatible = "nxp,imx-flexspi-hyperflash";
size = <DT_SIZE_M(64*8)>;
label = "S26KS512S";
reg = <0>;
spi-max-frequency = <166000000>;
status = "okay";
};
};
Expand Down
4 changes: 2 additions & 2 deletions boards/arm/mimxrt1050_evk/mimxrt1050_evk_qspi.dts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

#include "mimxrt1050_evk.dts"

/delete-node/ &hyperflash0;
/delete-node/ &s26ks512s0;

&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(8)>;
is25wp064: is25wp064@0 {
compatible = "issi,is25wp064", "jedec,spi-nor";
compatible = "nxp,imx-flexspi-nor";
size = <67108864>;
label = "IS25WP064";
reg = <0>;
Expand Down
2 changes: 1 addition & 1 deletion boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ arduino_serial: &lpuart3 {};
&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(8)>;
is25wp064: is25wp064@0 {
compatible = "issi,is25wp064", "jedec,spi-nor";
compatible = "nxp,imx-flexspi-nor";
size = <67108864>;
label = "IS25WP064";
reg = <0>;
Expand Down
7 changes: 5 additions & 2 deletions boards/arm/mimxrt1060_evk/mimxrt1060_evk_hyperflash.dts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
/delete-node/ &is25wp064;
&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(64)>;
hyperflash0: hyperflash@0 {
compatible = "cypress,s26ks512s";
s26ks512s0: s26ks512s@0 {
compatible = "nxp,imx-flexspi-hyperflash";
size = <DT_SIZE_M(64*8)>;
label = "S26KS512S";
reg = <0>;
spi-max-frequency = <166000000>;
status = "okay";
};
};
3 changes: 3 additions & 0 deletions boards/arm/mimxrt1064_evk/Kconfig.defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ config DISK_ACCESS_USDHC1
default y
depends on DISK_ACCESS_USDHC

config FLASH_MCUX_FLEXSPI_NOR
default y if FLASH

config I2C
default y if KSCAN

Expand Down
14 changes: 14 additions & 0 deletions boards/arm/mimxrt1064_evk/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,20 @@ The MIMXRT1064 SoC has four pairs of pinmux/gpio controllers.
+---------------+-----------------+---------------------------+
| GPIO_SD_B0_05 | USDHC1_DATA3 | SD Card |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_05 | FLEXSPIA_DQS | QSPI Flash |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_06 | FLEXSPIA_SS0_B | QSPI Flash |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_07 | FLEXSPIA_SCLK | QSPI Flash |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_08 | FLEXSPIA_DATA00 | QSPI Flash |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_09 | FLEXSPIA_DATA01 | QSPI Flash |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_10 | FLEXSPIA_DATA02 | QSPI Flash |
+---------------+-----------------+---------------------------+
| GPIO_SD_B1_11 | FLEXSPIA_DATA03 | QSPI Flash |
+---------------+-----------------+---------------------------+

System Clock
============
Expand Down
28 changes: 28 additions & 0 deletions boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,34 @@ arduino_i2c: &lpi2c1 {};
};
};

&flexspi {
status = "okay";
ahb-prefetch;
ahb-read-addr-opt;
rx-clock-source = <1>;
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(8)>;
is25wp064: is25wp064@0 {
compatible = "nxp,imx-flexspi-nor";
size = <67108864>;
label = "IS25WP064";
reg = <0>;
spi-max-frequency = <133000000>;
status = "okay";
jedec-id = [9d 70 17];

partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

storage_partition: partition@0 {
label = "storage";
reg = <0x00000000 DT_SIZE_M(8)>;
};
};
};
};

&lpuart1 {
status = "okay";
current-speed = <115200>;
Expand Down
18 changes: 18 additions & 0 deletions boards/arm/mimxrt1064_evk/pinmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,24 @@ static int mimxrt1064_evk_init(const struct device *dev)
imxrt_usdhc_pinmux_cb_register(mimxrt1064_evk_usdhc_pinmux);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay) && CONFIG_FLASH
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_05_FLEXSPIA_DQS, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_06_FLEXSPIA_SS0_B, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_07_FLEXSPIA_SCLK, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_08_FLEXSPIA_DATA00, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_09_FLEXSPIA_DATA01, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_10_FLEXSPIA_DATA02, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_11_FLEXSPIA_DATA03, 1U);

IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_FLEXSPIA_DQS, 0x10F1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_06_FLEXSPIA_SS0_B, 0x10F1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_07_FLEXSPIA_SCLK, 0x10F1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_08_FLEXSPIA_DATA00, 0x10F1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_09_FLEXSPIA_DATA01, 0x10F1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_10_FLEXSPIA_DATA02, 0x10F1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_11_FLEXSPIA_DATA03, 0x10F1U);
#endif

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion boards/arm/mm_swiftio/mm_swiftio.dts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
&flexspi {
reg = <0x402a8000 0x4000>, <0x60000000 DT_SIZE_M(8)>;
is25wp064: is25wp064@0 {
compatible = "issi,is25wp064", "jedec,spi-nor";
compatible = "nxp,imx-flexspi-nor";
size = <67108864>;
label = "IS25WP064";
reg = <0>;
Expand Down
2 changes: 2 additions & 0 deletions drivers/flash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NIOS2_QSPI soc_flash_nios2_qspi.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_GECKO flash_gecko.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 soc_flash_rv32m1.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI flash_mcux_flexspi.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_NOR flash_mcux_flexspi_nor.c)

if(CONFIG_SOC_FLASH_STM32)
if(CONFIG_SOC_SERIES_STM32H7X)
Expand Down
13 changes: 13 additions & 0 deletions drivers/flash/Kconfig.mcux
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,16 @@ config CHECK_BEFORE_READING
devices will crash when reading an erased or wrongly programmed area.

endif # SOC_FLASH_MCUX

if HAS_MCUX_FLEXSPI

config FLASH_MCUX_FLEXSPI_NOR
bool "MCUX FlexSPI NOR driver"
select FLASH_HAS_PAGE_LAYOUT
select FLASH_HAS_DRIVER_ENABLED
select FLASH_MCUX_FLEXSPI

config FLASH_MCUX_FLEXSPI
bool

endif # HAS_MCUX_FLEXSPI
147 changes: 147 additions & 0 deletions drivers/flash/flash_mcux_flexspi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright 2020 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT nxp_imx_flexspi

#include <drivers/flash.h>
#include <logging/log.h>
#include <sys/util.h>
#include "flash_mcux_flexspi.h"

LOG_MODULE_REGISTER(flash_flexspi, CONFIG_FLASH_LOG_LEVEL);

struct flash_flexspi_config {
FLEXSPI_Type *base;
uint8_t *ahb_base;
bool ahb_bufferable;
bool ahb_cacheable;
bool ahb_prefetch;
bool ahb_read_addr_opt;
bool combination_mode;
flexspi_read_sample_clock_t rx_sample_clock;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an enum this could be sizeof(int); some alignment costs might be avoided by moving it above the bool fields.

};

struct flash_flexspi_data {
size_t size[kFLEXSPI_PortCount];
};

int flash_flexspi_update_lut(const struct device *dev, uint32_t index,
const uint32_t *cmd, uint32_t count)
{
const struct flash_flexspi_config *config = dev->config;

FLEXSPI_UpdateLUT(config->base, index, cmd, count);

return 0;
}

int flash_flexspi_set_flash_config(const struct device *dev,
const flexspi_device_config_t *device_config,
flexspi_port_t port)
{
const struct flash_flexspi_config *config = dev->config;
struct flash_flexspi_data *data = dev->data;

if (port >= kFLEXSPI_PortCount) {
LOG_ERR("Invalid port number");
return -EINVAL;
}

data->size[port] = device_config->flashSize * KB(1);

FLEXSPI_SetFlashConfig(config->base,
(flexspi_device_config_t *) device_config,
port);

return 0;
}

int flash_flexspi_reset(const struct device *dev)
{
const struct flash_flexspi_config *config = dev->config;

FLEXSPI_SoftwareReset(config->base);

return 0;
}

int flash_flexspi_transfer(const struct device *dev,
flexspi_transfer_t *transfer)
{
const struct flash_flexspi_config *config = dev->config;
status_t status = FLEXSPI_TransferBlocking(config->base, transfer);

if (status != kStatus_Success) {
LOG_ERR("Transfer error: %d", status);
return -EIO;
}

return 0;
}

void *flash_flexspi_get_ahb_address(const struct device *dev,
flexspi_port_t port, off_t offset)
{
const struct flash_flexspi_config *config = dev->config;
struct flash_flexspi_data *data = dev->data;
int i;

if (port >= kFLEXSPI_PortCount) {
LOG_ERR("Invalid port number");
return NULL;
}

for (i = 0; i < port; i++) {
offset += data->size[port];
}

return config->ahb_base + offset;
}

static int flash_flexspi_init(const struct device *dev)
{
const struct flash_flexspi_config *config = dev->config;
flexspi_config_t flexspi_config;

FLEXSPI_GetDefaultConfig(&flexspi_config);

flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we can't "fix" this sort of thing in edtlib, an alternative is to invert the devicetree property meaning. Something like no-ahb-bufferable in devicetree, and .ahb_bufferable = !DT_INST_PROP(..., no_ahb_bufferable) when initializing config.

Feel free to disregard if you're happier with setting this in .dtsi.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be confusing to tie a property to hardware register field but invert the logic, so keeping this in the dtsi. Thanks for your help

flexspi_config.ahbConfig.enableAHBCachable = config->ahb_cacheable;
flexspi_config.ahbConfig.enableAHBPrefetch = config->ahb_prefetch;
flexspi_config.ahbConfig.enableReadAddressOpt = config->ahb_read_addr_opt;
flexspi_config.enableCombination = config->combination_mode;
flexspi_config.rxSampleClock = config->rx_sample_clock;

FLEXSPI_Init(config->base, &flexspi_config);

return 0;
}

#define FLASH_FLEXSPI(n) \
static const struct flash_flexspi_config \
flash_flexspi_config_##n = { \
.base = (FLEXSPI_Type *) DT_INST_REG_ADDR(n), \
.ahb_base = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(n, 1), \
.ahb_bufferable = DT_INST_PROP(n, ahb_bufferable), \
.ahb_cacheable = DT_INST_PROP(n, ahb_cacheable), \
.ahb_prefetch = DT_INST_PROP(n, ahb_prefetch), \
.ahb_read_addr_opt = DT_INST_PROP(n, ahb_read_addr_opt),\
.combination_mode = DT_INST_PROP(n, combination_mode), \
.rx_sample_clock = DT_INST_PROP(n, rx_clock_source), \
}; \
\
static struct flash_flexspi_data flash_flexspi_data_##n; \
\
DEVICE_DT_INST_DEFINE(n, \
flash_flexspi_init, \
device_pm_control_nop, \
&flash_flexspi_data_##n, \
&flash_flexspi_config_##n, \
POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
NULL);

DT_INST_FOREACH_STATUS_OKAY(FLASH_FLEXSPI)
23 changes: 23 additions & 0 deletions drivers/flash/flash_mcux_flexspi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2020 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <drivers/flash.h>
#include <fsl_flexspi.h>

int flash_flexspi_update_lut(const struct device *dev, uint32_t index,
const uint32_t *cmd, uint32_t count);

int flash_flexspi_set_flash_config(const struct device *dev,
const flexspi_device_config_t *device_config,
flexspi_port_t port);

int flash_flexspi_reset(const struct device *dev);

int flash_flexspi_transfer(const struct device *dev,
flexspi_transfer_t *transfer);

void *flash_flexspi_get_ahb_address(const struct device *dev,
flexspi_port_t port, off_t offset);
Loading