diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c index 5eee4f3..8577436 100644 --- a/drivers/st/fmc/stm32_fmc2_nand.c +++ b/drivers/st/fmc/stm32_fmc2_nand.c @@ -26,8 +26,10 @@ #define TIMEOUT_US_1_MS 1000U /* FMC2 Compatibility */ -#define DT_FMC2_COMPAT "st,stm32mp15-fmc2" +#define DT_FMC2_EBI_COMPAT "st,stm32mp1-fmc2-ebi" +#define DT_FMC2_NFC_COMPAT "st,stm32mp1-fmc2-nfc" #define MAX_CS 2U +#define MAX_BANK 5U /* FMC2 Controller Registers */ #define FMC2_BCR1 0x00U @@ -793,23 +795,26 @@ int stm32_fmc2_init(void) { - int fmc_node; - int fmc_subnode = 0; + int fmc_ebi_node; + int fmc_nfc_node; + int fmc_flash_node = 0; int nchips = 0; unsigned int i; void *fdt = NULL; const fdt32_t *cuint; struct dt_node_info info; + uintptr_t bank_address[MAX_BANK] = { 0, 0, 0, 0, 0 }; + uint8_t bank_assigned = 0; + uint8_t bank; int ret; if (fdt_get_address(&fdt) == 0) { return -FDT_ERR_NOTFOUND; } - fmc_node = dt_get_node(&info, -1, DT_FMC2_COMPAT); - if (fmc_node == -FDT_ERR_NOTFOUND) { - WARN("No FMC2 node found\n"); - return fmc_node; + fmc_ebi_node = dt_get_node(&info, -1, DT_FMC2_EBI_COMPAT); + if (fmc_ebi_node < 0) { + return fmc_ebi_node; } if (info.status == DT_DISABLED) { @@ -825,27 +830,69 @@ stm32_fmc2.clock_id = (unsigned long)info.clock; stm32_fmc2.reset_id = (unsigned int)info.reset; - cuint = fdt_getprop(fdt, fmc_node, "reg", NULL); + cuint = fdt_getprop(fdt, fmc_ebi_node, "ranges", NULL); if (cuint == NULL) { return -FDT_ERR_BADVALUE; } - cuint += 2; - - for (i = 0U; i < MAX_CS; i++) { - stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*cuint); - stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 2)); - stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 4)); - cuint += 6; + for (i = 0U; i < MAX_BANK; i++) { + bank = fdt32_to_cpu(*cuint); + if ((bank >= MAX_BANK) || ((bank_assigned & BIT(bank)) != 0U)) { + return -FDT_ERR_BADVALUE; + } + bank_assigned |= BIT(bank); + bank_address[bank] = fdt32_to_cpu(*(cuint + 2)); + cuint += 4; } /* Pinctrl initialization */ - if (dt_set_pinctrl_config(fmc_node) != 0) { + if (dt_set_pinctrl_config(fmc_ebi_node) != 0) { return -FDT_ERR_BADVALUE; } + /* Parse NFC controller node */ + fmc_nfc_node = fdt_node_offset_by_compatible(fdt, fmc_ebi_node, + DT_FMC2_NFC_COMPAT); + if (fmc_nfc_node < 0) { + return fmc_nfc_node; + } + + if (fdt_get_status(fmc_nfc_node) == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, fmc_nfc_node, "reg", NULL); + if (cuint == NULL) { + return -FDT_ERR_BADVALUE; + } + + for (i = 0U; i < MAX_CS; i++) { + bank = fdt32_to_cpu(*cuint); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*(cuint + 1)) + + bank_address[bank]; + + bank = fdt32_to_cpu(*(cuint + 3)); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 4)) + + bank_address[bank]; + + bank = fdt32_to_cpu(*(cuint + 6)); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 7)) + + bank_address[bank]; + + cuint += 9; + } + /* Parse flash nodes */ - fdt_for_each_subnode(fmc_subnode, fdt, fmc_node) { + fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { nchips++; } @@ -854,9 +901,9 @@ return -FDT_ERR_BADVALUE; } - fdt_for_each_subnode(fmc_subnode, fdt, fmc_node) { + fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { /* Get chip select */ - cuint = fdt_getprop(fdt, fmc_subnode, "reg", NULL); + cuint = fdt_getprop(fdt, fmc_flash_node, "reg", NULL); if (cuint == NULL) { WARN("Chip select not well defined\n"); return -FDT_ERR_BADVALUE; diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi index 2eb4a39..8f175a6 100644 --- a/fdts/stm32mp151.dtsi +++ b/fdts/stm32mp151.dtsi @@ -264,19 +264,34 @@ status = "disabled"; }; - fmc: nand-controller@58002000 { - compatible = "st,stm32mp15-fmc2"; - reg = <0x58002000 0x1000>, - <0x80000000 0x1000>, - <0x88010000 0x1000>, - <0x88020000 0x1000>, - <0x81000000 0x1000>, - <0x89010000 0x1000>, - <0x89020000 0x1000>; - interrupts = ; + fmc: memory-controller@58002000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "st,stm32mp1-fmc2-ebi"; + reg = <0x58002000 0x1000>; clocks = <&rcc FMC_K>; resets = <&rcc FMC_R>; status = "disabled"; + + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ + <4 0 0x80000000 0x10000000>; /* NAND */ + + nand-controller@4,0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32mp1-fmc2-nfc"; + reg = <4 0x00000000 0x1000>, + <4 0x08010000 0x1000>, + <4 0x08020000 0x1000>, + <4 0x01000000 0x1000>, + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; + status = "disabled"; + }; }; qspi: spi@58003000 { diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts index 50c0b93..c5d12e3 100644 --- a/fdts/stm32mp157c-ev1.dts +++ b/fdts/stm32mp157c-ev1.dts @@ -24,11 +24,16 @@ pinctrl-names = "default"; pinctrl-0 = <&fmc_pins_a>; status = "okay"; - #address-cells = <1>; - #size-cells = <0>; - nand: nand@0 { - reg = <0>; + nand-controller@4,0 { + status = "okay"; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; }; };