From f226ec1e492740b900b39691517f534d60c1631c Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 7 Feb 2024 14:12:01 +0100 Subject: [PATCH 01/50] stm32mp: cmd_stm32prog: add dependencies with USB_GADGET_DOWNLOAD This patch avoids compilation issue when CONFIG_USB_GADGET is deactivated in defconfig, with undefined reference to run_usb_dnl_gadget and to g_dnl_set_product. Signed-off-by: Patrick Delaunay Reviewed-by: Igor Opaniuk Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig index 8f91db4b46..589276282e 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig @@ -17,6 +17,7 @@ config CMD_STM32PROG config CMD_STM32PROG_USB bool "support stm32prog over USB" depends on CMD_STM32PROG + depends on USB_GADGET_DOWNLOAD default y help activate the command "stm32prog usb" for STM32MP soc family From 0dfd5039177c5fc8dc38e9efc4ce0dd533814084 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 4 Mar 2024 19:25:43 +0100 Subject: [PATCH 02/50] arm: stm32: Enable OHCI HCD support on STM32MP15xx DHSOM The OHCI HCD is mandatory for USB 1.1 FS/LS device support, enable it. This used to be enabled implicitly before, now that implicit dependency disappeared and this got disabled. Enable it manually. Signed-off-by: Marek Vasut Reviewed-by: Patrice Chotard --- configs/stm32mp15_dhcom_basic_defconfig | 2 ++ configs/stm32mp15_dhcor_basic_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/stm32mp15_dhcom_basic_defconfig b/configs/stm32mp15_dhcom_basic_defconfig index eb6e367b90..8442f0bfe9 100644 --- a/configs/stm32mp15_dhcom_basic_defconfig +++ b/configs/stm32mp15_dhcom_basic_defconfig @@ -164,6 +164,8 @@ CONFIG_DM_USB_GADGET=y CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC2=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y diff --git a/configs/stm32mp15_dhcor_basic_defconfig b/configs/stm32mp15_dhcor_basic_defconfig index ab92924a9b..91b64f7537 100644 --- a/configs/stm32mp15_dhcor_basic_defconfig +++ b/configs/stm32mp15_dhcor_basic_defconfig @@ -164,6 +164,8 @@ CONFIG_DM_USB_GADGET=y CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC2=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y From 3171e38194525431169ea0fba8f4471bd35e7c1c Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Wed, 6 Mar 2024 10:50:46 +0100 Subject: [PATCH 03/50] memory: stm32-fmc2-ebi: add MP25 support Add the support of the revision 2 of FMC2 IP. - PCSCNTR register has been removed, - CFGR register has been added, - the bit used to enable the IP has moved from BCR1 to CFGR, - the timeout for CEx deassertion has moved from PCSCNTR to BCRx, - the continuous clock enable has moved from BCR1 to CFGR, - the clk divide ratio has moved from BCR1 to CFGR. The MP1 SoCs have only one signal to manage all the controllers (NWAIT). The MP25 SOC has one RNB signal for the NAND controller and one NWAIT signal for the memory controller. Let's use a platform data structure for parameters that will differ between MP1 and MP25. Signed-off-by: Christophe Kerello Reviewed-by: Patrice Chotard --- drivers/memory/stm32-fmc2-ebi.c | 313 ++++++++++++++++++++++++++++++-- 1 file changed, 301 insertions(+), 12 deletions(-) diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c index a722a3836f..c7db16463e 100644 --- a/drivers/memory/stm32-fmc2-ebi.c +++ b/drivers/memory/stm32-fmc2-ebi.c @@ -22,6 +22,7 @@ #define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1) #define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1) #define FMC2_PCSCNTR 0x20 +#define FMC2_CFGR 0x20 #define FMC2_BWTR1 0x104 #define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1) @@ -44,6 +45,7 @@ #define FMC2_BCR_ASYNCWAIT BIT(15) #define FMC2_BCR_CPSIZE GENMASK(18, 16) #define FMC2_BCR_CBURSTRW BIT(19) +#define FMC2_BCR_CSCOUNT GENMASK(21, 20) #define FMC2_BCR_NBLSET GENMASK(23, 22) /* Register: FMC2_BTRx/FMC2_BWTRx */ @@ -60,6 +62,11 @@ #define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0) #define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16) +/* Register: FMC2_CFGR */ +#define FMC2_CFGR_CLKDIV GENMASK(19, 16) +#define FMC2_CFGR_CCLKEN BIT(20) +#define FMC2_CFGR_FMC2EN BIT(31) + #define FMC2_MAX_EBI_CE 4 #define FMC2_MAX_BANKS 5 @@ -76,6 +83,11 @@ #define FMC2_BCR_MTYP_PSRAM 0x1 #define FMC2_BCR_MTYP_NOR 0x2 +#define FMC2_BCR_CSCOUNT_0 0x0 +#define FMC2_BCR_CSCOUNT_1 0x1 +#define FMC2_BCR_CSCOUNT_64 0x2 +#define FMC2_BCR_CSCOUNT_256 0x3 + #define FMC2_BXTR_EXTMOD_A 0x0 #define FMC2_BXTR_EXTMOD_B 0x1 #define FMC2_BXTR_EXTMOD_C 0x2 @@ -90,6 +102,7 @@ #define FMC2_BTR_CLKDIV_MAX 0xf #define FMC2_BTR_DATLAT_MAX 0xf #define FMC2_PCSCNTR_CSCOUNT_MAX 0xff +#define FMC2_CFGR_CLKDIV_MAX 0xf enum stm32_fmc2_ebi_bank { FMC2_EBI1 = 0, @@ -103,7 +116,8 @@ enum stm32_fmc2_ebi_register_type { FMC2_REG_BCR = 1, FMC2_REG_BTR, FMC2_REG_BWTR, - FMC2_REG_PCSCNTR + FMC2_REG_PCSCNTR, + FMC2_REG_CFGR }; enum stm32_fmc2_ebi_transaction_type { @@ -134,9 +148,27 @@ enum stm32_fmc2_ebi_cpsize { FMC2_CPSIZE_1024 = 1024 }; +enum stm32_fmc2_ebi_cscount { + FMC2_CSCOUNT_0 = 0, + FMC2_CSCOUNT_1 = 1, + FMC2_CSCOUNT_64 = 64, + FMC2_CSCOUNT_256 = 256 +}; + +struct stm32_fmc2_ebi; + +struct stm32_fmc2_ebi_data { + const struct stm32_fmc2_prop *child_props; + unsigned int nb_child_props; + u32 fmc2_enable_reg; + u32 fmc2_enable_bit; + int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi); +}; + struct stm32_fmc2_ebi { struct clk clk; fdt_addr_t io_base; + const struct stm32_fmc2_ebi_data *data; u8 bank_assigned; }; @@ -296,6 +328,24 @@ static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, return DIV_ROUND_UP(nb_clk_cycles, clk_period); } +static u32 stm32_fmc2_ebi_mp25_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, + int cs, u32 setup) +{ + u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup); + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); + u32 clk_period; + + if (cfgr & FMC2_CFGR_CCLKEN) { + clk_period = FIELD_GET(FMC2_CFGR_CLKDIV, cfgr) + 1; + } else { + u32 btr = readl(ebi->io_base + FMC2_BTR(cs)); + + clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1; + } + + return DIV_ROUND_UP(nb_clk_cycles, clk_period); +} + static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg) { switch (reg_type) { @@ -311,6 +361,9 @@ static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg) case FMC2_REG_PCSCNTR: *reg = FMC2_PCSCNTR; break; + case FMC2_REG_CFGR: + *reg = FMC2_CFGR; + break; default: return -EINVAL; } @@ -649,6 +702,26 @@ static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi, return 0; } +static int stm32_fmc2_ebi_mp25_set_clk_period(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs, u32 setup) +{ + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); + u32 val; + + if (cfgr & FMC2_CFGR_CCLKEN) { + val = setup ? clamp_val(setup - 1, 1, FMC2_CFGR_CLKDIV_MAX) : 1; + val = FIELD_PREP(FMC2_CFGR_CLKDIV, val); + clrsetbits_le32(ebi->io_base + FMC2_CFGR, FMC2_CFGR_CLKDIV, val); + } else { + val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1; + val = FIELD_PREP(FMC2_BTR_CLKDIV, val); + clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val); + } + + return 0; +} + static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi, const struct stm32_fmc2_prop *prop, int cs, u32 setup) @@ -689,6 +762,27 @@ static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, return 0; } +static int stm32_fmc2_ebi_mp25_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs, u32 setup) +{ + u32 val; + + if (setup == FMC2_CSCOUNT_0) + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_0); + else if (setup == FMC2_CSCOUNT_1) + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_1); + else if (setup <= FMC2_CSCOUNT_64) + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_64); + else + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_256); + + clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), + FMC2_BCR_CSCOUNT, val); + + return 0; +} + static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { /* st,fmc2-ebi-cs-trans-type must be the first property */ { @@ -854,6 +948,171 @@ static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { }, }; +static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = { + /* st,fmc2-ebi-cs-trans-type must be the first property */ + { + .name = "st,fmc2-ebi-cs-transaction-type", + .mprop = true, + .set = stm32_fmc2_ebi_set_trans_type, + }, + { + .name = "st,fmc2-ebi-cs-cclk-enable", + .bprop = true, + .reg_type = FMC2_REG_CFGR, + .reg_mask = FMC2_CFGR_CCLKEN, + .check = stm32_fmc2_ebi_check_sync_trans, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-mux-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_MUXEN, + .check = stm32_fmc2_ebi_check_mux, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-buswidth", + .reset_val = FMC2_BUSWIDTH_16, + .set = stm32_fmc2_ebi_set_buswidth, + }, + { + .name = "st,fmc2-ebi-cs-waitpol-high", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_WAITPOL, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-waitcfg-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_WAITCFG, + .check = stm32_fmc2_ebi_check_waitcfg, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-wait-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_WAITEN, + .check = stm32_fmc2_ebi_check_sync_trans, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-asyncwait-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_ASYNCWAIT, + .check = stm32_fmc2_ebi_check_async_trans, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-cpsize", + .check = stm32_fmc2_ebi_check_cpsize, + .set = stm32_fmc2_ebi_set_cpsize, + }, + { + .name = "st,fmc2-ebi-cs-byte-lane-setup-ns", + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_bl_setup, + }, + { + .name = "st,fmc2-ebi-cs-address-setup-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_ADDSET_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_setup, + }, + { + .name = "st,fmc2-ebi-cs-address-hold-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_ADDHLD_MAX, + .check = stm32_fmc2_ebi_check_address_hold, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_hold, + }, + { + .name = "st,fmc2-ebi-cs-data-setup-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_DATAST_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_setup, + }, + { + .name = "st,fmc2-ebi-cs-bus-turnaround-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_bus_turnaround, + }, + { + .name = "st,fmc2-ebi-cs-data-hold-ns", + .reg_type = FMC2_REG_BTR, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_hold, + }, + { + .name = "st,fmc2-ebi-cs-clk-period-ns", + .reset_val = FMC2_CFGR_CLKDIV_MAX + 1, + .check = stm32_fmc2_ebi_check_sync_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_mp25_set_clk_period, + }, + { + .name = "st,fmc2-ebi-cs-data-latency-ns", + .check = stm32_fmc2_ebi_check_sync_trans, + .calculate = stm32_fmc2_ebi_mp25_ns_to_clk_period, + .set = stm32_fmc2_ebi_set_data_latency, + }, + { + .name = "st,fmc2-ebi-cs-write-address-setup-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_ADDSET_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_setup, + }, + { + .name = "st,fmc2-ebi-cs-write-address-hold-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_ADDHLD_MAX, + .check = stm32_fmc2_ebi_check_address_hold, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_hold, + }, + { + .name = "st,fmc2-ebi-cs-write-data-setup-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_DATAST_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_setup, + }, + { + .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_bus_turnaround, + }, + { + .name = "st,fmc2-ebi-cs-write-data-hold-ns", + .reg_type = FMC2_REG_BWTR, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_hold, + }, + { + .name = "st,fmc2-ebi-cs-max-low-pulse-ns", + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_mp25_set_max_low_pulse, + }, +}; + static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi, ofnode node, const struct stm32_fmc2_prop *prop, @@ -915,7 +1174,7 @@ static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs) } /* NWAIT signal can not be connected to EBI controller and NAND controller */ -static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) +static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) { unsigned int cs; u32 bcr; @@ -926,16 +1185,19 @@ static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) bcr = readl(ebi->io_base + FMC2_BCR(cs)); if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) && - ebi->bank_assigned & BIT(FMC2_NAND)) - return true; + ebi->bank_assigned & BIT(FMC2_NAND)) { + log_err("NWAIT signal connected to EBI and NAND controllers\n"); + return -EINVAL; + } } - return false; + return 0; } static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi) { - setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN); + setbits_le32(ebi->io_base + ebi->data->fmc2_enable_reg, + ebi->data->fmc2_enable_bit); } static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, @@ -946,8 +1208,8 @@ static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, stm32_fmc2_ebi_disable_bank(ebi, cs); - for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) { - const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i]; + for (i = 0; i < ebi->data->nb_child_props; i++) { + const struct stm32_fmc2_prop *p = &ebi->data->child_props[i]; ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs); if (ret) { @@ -1004,9 +1266,10 @@ static int stm32_fmc2_ebi_parse_dt(struct udevice *dev, return -ENODEV; } - if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) { - dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n"); - return -EINVAL; + if (ebi->data->nwait_used_by_ctrls) { + ret = ebi->data->nwait_used_by_ctrls(ebi); + if (ret) + return ret; } stm32_fmc2_ebi_enable(ebi); @@ -1020,6 +1283,10 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) struct reset_ctl reset; int ret; + ebi->data = (void *)dev_get_driver_data(dev); + if (!ebi->data) + return -EINVAL; + ebi->io_base = dev_read_addr(dev); if (ebi->io_base == FDT_ADDR_T_NONE) return -EINVAL; @@ -1042,8 +1309,30 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) return stm32_fmc2_ebi_parse_dt(dev, ebi); } +static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp1_data = { + .child_props = stm32_fmc2_child_props, + .nb_child_props = ARRAY_SIZE(stm32_fmc2_child_props), + .fmc2_enable_reg = FMC2_BCR1, + .fmc2_enable_bit = FMC2_BCR1_FMC2EN, + .nwait_used_by_ctrls = stm32_fmc2_ebi_nwait_used_by_ctrls, +}; + +static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp25_data = { + .child_props = stm32_fmc2_mp25_child_props, + .nb_child_props = ARRAY_SIZE(stm32_fmc2_mp25_child_props), + .fmc2_enable_reg = FMC2_CFGR, + .fmc2_enable_bit = FMC2_CFGR_FMC2EN, +}; + static const struct udevice_id stm32_fmc2_ebi_match[] = { - {.compatible = "st,stm32mp1-fmc2-ebi"}, + { + .compatible = "st,stm32mp1-fmc2-ebi", + .data = (ulong)&stm32_fmc2_ebi_mp1_data, + }, + { + .compatible = "st,stm32mp25-fmc2-ebi", + .data = (ulong)&stm32_fmc2_ebi_mp25_data, + }, { /* Sentinel */ } }; From a10ee1322ae4aff1d9e1a283e89a90ce230e3aa8 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Wed, 6 Mar 2024 10:50:47 +0100 Subject: [PATCH 04/50] memory: stm32-fmc2-ebi: add MP25 RIF support The FMC2 revision 2 supports security and isolation compliant with the Resource Isolation Framework (RIF). From RIF point of view, the FMC2 is composed of several independent resources, listed below, which can be assigned to different security and compartment domains: - 0: Common FMC_CFGR register. - 1: EBI controller for Chip Select 1. - 2: EBI controller for Chip Select 2. - 3: EBI controller for Chip Select 3. - 4: EBI controller for Chip Select 4. - 5: NAND controller. Signed-off-by: Christophe Kerello Reviewed-by: Patrice Chotard --- drivers/memory/stm32-fmc2-ebi.c | 140 +++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c index c7db16463e..1ce9607785 100644 --- a/drivers/memory/stm32-fmc2-ebi.c +++ b/drivers/memory/stm32-fmc2-ebi.c @@ -23,8 +23,14 @@ #define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1) #define FMC2_PCSCNTR 0x20 #define FMC2_CFGR 0x20 +#define FMC2_SR 0x84 #define FMC2_BWTR1 0x104 #define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1) +#define FMC2_SECCFGR 0x300 +#define FMC2_CIDCFGR0 0x30c +#define FMC2_CIDCFGR(x) ((x) * 0x8 + FMC2_CIDCFGR0) +#define FMC2_SEMCR0 0x310 +#define FMC2_SEMCR(x) ((x) * 0x8 + FMC2_SEMCR0) /* Register: FMC2_BCR1 */ #define FMC2_BCR1_CCLKEN BIT(20) @@ -67,8 +73,23 @@ #define FMC2_CFGR_CCLKEN BIT(20) #define FMC2_CFGR_FMC2EN BIT(31) +/* Register: FMC2_SR */ +#define FMC2_SR_ISOST GENMASK(1, 0) + +/* Register: FMC2_CIDCFGR */ +#define FMC2_CIDCFGR_CFEN BIT(0) +#define FMC2_CIDCFGR_SEMEN BIT(1) +#define FMC2_CIDCFGR_SCID GENMASK(6, 4) +#define FMC2_CIDCFGR_SEMWLC1 BIT(17) + +/* Register: FMC2_SEMCR */ +#define FMC2_SEMCR_SEM_MUTEX BIT(0) +#define FMC2_SEMCR_SEMCID GENMASK(6, 4) + #define FMC2_MAX_EBI_CE 4 #define FMC2_MAX_BANKS 5 +#define FMC2_MAX_RESOURCES 6 +#define FMC2_CID1 1 #define FMC2_BCR_CPSIZE_0 0x0 #define FMC2_BCR_CPSIZE_128 0x1 @@ -163,6 +184,7 @@ struct stm32_fmc2_ebi_data { u32 fmc2_enable_reg; u32 fmc2_enable_bit; int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi); + int (*check_rif)(struct stm32_fmc2_ebi *ebi, u32 resource); }; struct stm32_fmc2_ebi { @@ -170,6 +192,7 @@ struct stm32_fmc2_ebi { fdt_addr_t io_base; const struct stm32_fmc2_ebi_data *data; u8 bank_assigned; + bool access_granted; }; /* @@ -241,6 +264,28 @@ static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi, return -EINVAL; } +static int stm32_fmc2_ebi_mp25_check_cclk(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs) +{ + if (!ebi->access_granted) + return -EACCES; + + return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs); +} + +static int stm32_fmc2_ebi_mp25_check_clk_period(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs) +{ + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); + + if (cfgr & FMC2_CFGR_CCLKEN && !ebi->access_granted) + return -EACCES; + + return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs); +} + static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi, const struct stm32_fmc2_prop *prop, int cs) @@ -960,7 +1005,7 @@ static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = { .bprop = true, .reg_type = FMC2_REG_CFGR, .reg_mask = FMC2_CFGR_CCLKEN, - .check = stm32_fmc2_ebi_check_sync_trans, + .check = stm32_fmc2_ebi_mp25_check_cclk, .set = stm32_fmc2_ebi_set_bit_field, }, { @@ -1058,7 +1103,7 @@ static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = { { .name = "st,fmc2-ebi-cs-clk-period-ns", .reset_val = FMC2_CFGR_CLKDIV_MAX + 1, - .check = stm32_fmc2_ebi_check_sync_trans, + .check = stm32_fmc2_ebi_mp25_check_clk_period, .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, .set = stm32_fmc2_ebi_mp25_set_clk_period, }, @@ -1113,6 +1158,70 @@ static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = { }, }; +static int stm32_fmc2_ebi_mp25_check_rif(struct stm32_fmc2_ebi *ebi, u32 resource) +{ + u32 seccfgr, cidcfgr, semcr; + int cid; + + if (resource >= FMC2_MAX_RESOURCES) + return -EINVAL; + + seccfgr = readl(ebi->io_base + FMC2_SECCFGR); + if (seccfgr & BIT(resource)) { + if (resource) + log_err("resource %d is configured as secure\n", + resource); + + return -EACCES; + } + + cidcfgr = readl(ebi->io_base + FMC2_CIDCFGR(resource)); + if (!(cidcfgr & FMC2_CIDCFGR_CFEN)) + /* CID filtering is turned off: access granted */ + return 0; + + if (!(cidcfgr & FMC2_CIDCFGR_SEMEN)) { + /* Static CID mode */ + cid = FIELD_GET(FMC2_CIDCFGR_SCID, cidcfgr); + if (cid != FMC2_CID1) { + if (resource) + log_err("static CID%d set for resource %d\n", + cid, resource); + + return -EACCES; + } + + return 0; + } + + /* Pass-list with semaphore mode */ + if (!(cidcfgr & FMC2_CIDCFGR_SEMWLC1)) { + if (resource) + log_err("CID1 is block-listed for resource %d\n", + resource); + + return -EACCES; + } + + semcr = readl(ebi->io_base + FMC2_SEMCR(resource)); + if (!(semcr & FMC2_SEMCR_SEM_MUTEX)) { + setbits_le32(ebi->io_base + FMC2_SEMCR(resource), + FMC2_SEMCR_SEM_MUTEX); + semcr = readl(ebi->io_base + FMC2_SEMCR(resource)); + } + + cid = FIELD_GET(FMC2_SEMCR_SEMCID, semcr); + if (cid != FMC2_CID1) { + if (resource) + log_err("resource %d is already used by CID%d\n", + resource, cid); + + return -EACCES; + } + + return 0; +} + static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi, ofnode node, const struct stm32_fmc2_prop *prop, @@ -1196,6 +1305,9 @@ static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi) { + if (!ebi->access_granted) + return; + setbits_le32(ebi->io_base + ebi->data->fmc2_enable_reg, ebi->data->fmc2_enable_bit); } @@ -1249,6 +1361,14 @@ static int stm32_fmc2_ebi_parse_dt(struct udevice *dev, return -EINVAL; } + if (ebi->data->check_rif) { + ret = ebi->data->check_rif(ebi, bank + 1); + if (ret) { + dev_err(dev, "bank access failed: %d\n", bank); + return ret; + } + } + if (bank < FMC2_MAX_EBI_CE) { ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank); if (ret) { @@ -1306,6 +1426,21 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) reset_deassert(&reset); } + /* Check if CFGR register can be modified */ + ebi->access_granted = true; + if (ebi->data->check_rif) { + ret = ebi->data->check_rif(ebi, 0); + if (ret) { + ebi->access_granted = false; + + /* In case of CFGR is secure, just check that the FMC2 is enabled */ + if (readl(ebi->io_base + FMC2_SR) & FMC2_SR_ISOST) { + dev_err(dev, "FMC2 is not ready to be used.\n"); + return -EACCES; + } + } + } + return stm32_fmc2_ebi_parse_dt(dev, ebi); } @@ -1322,6 +1457,7 @@ static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp25_data = { .nb_child_props = ARRAY_SIZE(stm32_fmc2_mp25_child_props), .fmc2_enable_reg = FMC2_CFGR, .fmc2_enable_bit = FMC2_CFGR_FMC2EN, + .check_rif = stm32_fmc2_ebi_mp25_check_rif, }; static const struct udevice_id stm32_fmc2_ebi_match[] = { From f5667d77403fc125bb87b8981de2f575ad2c06e5 Mon Sep 17 00:00:00 2001 From: Christophe Kerello Date: Wed, 6 Mar 2024 10:54:06 +0100 Subject: [PATCH 05/50] mtd: rawnand: stm32_fmc2: add MP25 support FMC2 IP supports up to 4 chip select. On MP1 SoC, only 2 of them are available when on MP25 SoC, the 4 chip select are available. Let's use a platform data structure for parameters that will differ. Signed-off-by: Christophe Kerello Reviewed-by: Patrice Chotard --- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 47 ++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 3528824575..d284b8cbb1 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -34,7 +34,7 @@ #define FMC2_RB_DELAY_US 30 /* Max chip enable */ -#define FMC2_MAX_CE 2 +#define FMC2_MAX_CE 4 /* Timings */ #define FMC2_THIZ 1 @@ -160,6 +160,11 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip) return container_of(chip, struct stm32_fmc2_nand, chip); } +struct stm32_fmc2_nfc_data { + int max_ncs; + struct udevice *(*get_cdev)(struct udevice *dev); +}; + struct stm32_fmc2_nfc { struct nand_hw_control base; struct stm32_fmc2_nand nand; @@ -169,6 +174,7 @@ struct stm32_fmc2_nfc { fdt_addr_t cmd_base[FMC2_MAX_CE]; fdt_addr_t addr_base[FMC2_MAX_CE]; struct clk clk; + const struct stm32_fmc2_nfc_data *data; u8 cs_assigned; int cs_sel; @@ -815,7 +821,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node) } for (i = 0; i < nand->ncs; i++) { - if (cs[i] >= FMC2_MAX_CE) { + if (cs[i] >= nfc->data->max_ncs) { log_err("Invalid reg value: %d\n", nand->cs_used[i]); return -EINVAL; } @@ -906,10 +912,18 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) spin_lock_init(&nfc->controller.lock); init_waitqueue_head(&nfc->controller.wq); - cdev = stm32_fmc2_nfc_get_cdev(dev); - if (!cdev) + nfc->data = (void *)dev_get_driver_data(dev); + if (!nfc->data) return -EINVAL; + if (nfc->data->get_cdev) { + cdev = nfc->data->get_cdev(dev); + if (!cdev) + return -EINVAL; + } else { + cdev = dev->parent; + } + ret = stm32_fmc2_nfc_parse_dt(dev, nfc); if (ret) return ret; @@ -921,7 +935,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) if (dev == cdev) start_region = 1; - for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE; + for (chip_cs = 0, mem_region = start_region; chip_cs < nfc->data->max_ncs; chip_cs++, mem_region += 3) { if (!(nfc->cs_assigned & BIT(chip_cs))) continue; @@ -1033,9 +1047,28 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) return nand_register(0, mtd); } +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp1_data = { + .max_ncs = 2, + .get_cdev = stm32_fmc2_nfc_get_cdev, +}; + +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp25_data = { + .max_ncs = 4, +}; + static const struct udevice_id stm32_fmc2_nfc_match[] = { - { .compatible = "st,stm32mp15-fmc2" }, - { .compatible = "st,stm32mp1-fmc2-nfc" }, + { + .compatible = "st,stm32mp15-fmc2", + .data = (ulong)&stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp1-fmc2-nfc", + .data = (ulong)&stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp25-fmc2-nfc", + .data = (ulong)&stm32_fmc2_nfc_mp25_data, + }, { /* Sentinel */ } }; From 343742661b0500b1873a6e4fcb7bff9d16f955a4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:22 +0100 Subject: [PATCH 06/50] net: dwc_eth_qos: Split STM32 glue into separate file Move STM32 glue code into separate file to contain the STM32 specific code outside of the DWMAC core code. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/Makefile | 1 + drivers/net/dwc_eth_qos.c | 165 --------------------------- drivers/net/dwc_eth_qos.h | 1 + drivers/net/dwc_eth_qos_stm32.c | 196 ++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 165 deletions(-) create mode 100644 drivers/net/dwc_eth_qos_stm32.c diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6677366ebd..dc3404519d 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o +obj-$(CONFIG_DWC_ETH_QOS_STM32) += dwc_eth_qos_stm32.o obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_EEPRO100) += eepro100.o diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 67d80d987f..aa4f815eb4 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -295,58 +295,6 @@ err: #endif } -static int eqos_start_clks_stm32(struct udevice *dev) -{ -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); - int ret; - - debug("%s(dev=%p):\n", __func__, dev); - - ret = clk_enable(&eqos->clk_master_bus); - if (ret < 0) { - pr_err("clk_enable(clk_master_bus) failed: %d\n", ret); - goto err; - } - - ret = clk_enable(&eqos->clk_rx); - if (ret < 0) { - pr_err("clk_enable(clk_rx) failed: %d\n", ret); - goto err_disable_clk_master_bus; - } - - ret = clk_enable(&eqos->clk_tx); - if (ret < 0) { - pr_err("clk_enable(clk_tx) failed: %d\n", ret); - goto err_disable_clk_rx; - } - - if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { - ret = clk_enable(&eqos->clk_ck); - if (ret < 0) { - pr_err("clk_enable(clk_ck) failed: %d\n", ret); - goto err_disable_clk_tx; - } - eqos->clk_ck_enabled = true; - } -#endif - - debug("%s: OK\n", __func__); - return 0; - -#ifdef CONFIG_CLK -err_disable_clk_tx: - clk_disable(&eqos->clk_tx); -err_disable_clk_rx: - clk_disable(&eqos->clk_rx); -err_disable_clk_master_bus: - clk_disable(&eqos->clk_master_bus); -err: - debug("%s: FAILED: %d\n", __func__, ret); - return ret; -#endif -} - static int eqos_stop_clks_tegra186(struct udevice *dev) { #ifdef CONFIG_CLK @@ -365,22 +313,6 @@ static int eqos_stop_clks_tegra186(struct udevice *dev) return 0; } -static int eqos_stop_clks_stm32(struct udevice *dev) -{ -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); - - debug("%s(dev=%p):\n", __func__, dev); - - clk_disable(&eqos->clk_tx); - clk_disable(&eqos->clk_rx); - clk_disable(&eqos->clk_master_bus); -#endif - - debug("%s: OK\n", __func__); - return 0; -} - static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -493,17 +425,6 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) #endif } -static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) -{ -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); - - return clk_get_rate(&eqos->clk_master_bus); -#else - return 0; -#endif -} - static int eqos_set_full_duplex(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1415,57 +1336,6 @@ err_free_reset_eqos: return ret; } -static int eqos_probe_resources_stm32(struct udevice *dev) -{ - struct eqos_priv *eqos = dev_get_priv(dev); - int ret; - phy_interface_t interface; - - debug("%s(dev=%p):\n", __func__, dev); - - interface = eqos->config->interface(dev); - - if (interface == PHY_INTERFACE_MODE_NA) { - pr_err("Invalid PHY interface\n"); - return -EINVAL; - } - - ret = board_interface_eth_init(dev, interface); - if (ret) - return -EINVAL; - - ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); - if (ret) { - pr_err("clk_get_by_name(master_bus) failed: %d\n", ret); - goto err_probe; - } - - ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); - if (ret) { - pr_err("clk_get_by_name(rx) failed: %d\n", ret); - goto err_probe; - } - - ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); - if (ret) { - pr_err("clk_get_by_name(tx) failed: %d\n", ret); - goto err_probe; - } - - /* Get ETH_CLK clocks (optional) */ - ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); - if (ret) - pr_warn("No phy clock provided %d", ret); - - debug("%s: OK\n", __func__); - return 0; - -err_probe: - - debug("%s: returns %d\n", __func__, ret); - return ret; -} - static phy_interface_t eqos_get_interface_tegra186(const struct udevice *dev) { return PHY_INTERFACE_MODE_MII; @@ -1484,12 +1354,6 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) return 0; } -static int eqos_remove_resources_stm32(struct udevice *dev) -{ - debug("%s(dev=%p):\n", __func__, dev); - return 0; -} - static int eqos_probe(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1633,35 +1497,6 @@ static const struct eqos_config __maybe_unused eqos_tegra186_config = { .ops = &eqos_tegra186_ops }; -static struct eqos_ops eqos_stm32_ops = { - .eqos_inval_desc = eqos_inval_desc_generic, - .eqos_flush_desc = eqos_flush_desc_generic, - .eqos_inval_buffer = eqos_inval_buffer_generic, - .eqos_flush_buffer = eqos_flush_buffer_generic, - .eqos_probe_resources = eqos_probe_resources_stm32, - .eqos_remove_resources = eqos_remove_resources_stm32, - .eqos_stop_resets = eqos_null_ops, - .eqos_start_resets = eqos_null_ops, - .eqos_stop_clks = eqos_stop_clks_stm32, - .eqos_start_clks = eqos_start_clks_stm32, - .eqos_calibrate_pads = eqos_null_ops, - .eqos_disable_calibration = eqos_null_ops, - .eqos_set_tx_clk_speed = eqos_null_ops, - .eqos_get_enetaddr = eqos_null_ops, - .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 -}; - -static const struct eqos_config __maybe_unused eqos_stm32_config = { - .reg_access_always_ok = false, - .mdio_wait = 10000, - .swr_wait = 50, - .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, - .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, - .axi_bus_width = EQOS_AXI_WIDTH_64, - .interface = dev_read_phy_mode, - .ops = &eqos_stm32_ops -}; - static const struct udevice_id eqos_ids[] = { #if IS_ENABLED(CONFIG_DWC_ETH_QOS_TEGRA186) { diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index e3222e1e17..a6087f191a 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,4 +290,5 @@ int eqos_null_ops(struct udevice *dev); extern struct eqos_config eqos_imx_config; extern struct eqos_config eqos_rockchip_config; extern struct eqos_config eqos_qcom_config; +extern struct eqos_config eqos_stm32_config; extern struct eqos_config eqos_jh7110_config; diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c new file mode 100644 index 0000000000..cfda757133 --- /dev/null +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024, Marek Vasut + * + * This is code moved from drivers/net/dwc_eth_qos.c , which is: + * Copyright (c) 2016, NVIDIA CORPORATION. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dwc_eth_qos.h" + +static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) +{ +#ifdef CONFIG_CLK + struct eqos_priv *eqos = dev_get_priv(dev); + + return clk_get_rate(&eqos->clk_master_bus); +#else + return 0; +#endif +} + +static int eqos_start_clks_stm32(struct udevice *dev) +{ +#ifdef CONFIG_CLK + struct eqos_priv *eqos = dev_get_priv(dev); + int ret; + + debug("%s(dev=%p):\n", __func__, dev); + + ret = clk_enable(&eqos->clk_master_bus); + if (ret < 0) { + pr_err("clk_enable(clk_master_bus) failed: %d", ret); + goto err; + } + + ret = clk_enable(&eqos->clk_rx); + if (ret < 0) { + pr_err("clk_enable(clk_rx) failed: %d", ret); + goto err_disable_clk_master_bus; + } + + ret = clk_enable(&eqos->clk_tx); + if (ret < 0) { + pr_err("clk_enable(clk_tx) failed: %d", ret); + goto err_disable_clk_rx; + } + + if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { + ret = clk_enable(&eqos->clk_ck); + if (ret < 0) { + pr_err("clk_enable(clk_ck) failed: %d", ret); + goto err_disable_clk_tx; + } + eqos->clk_ck_enabled = true; + } +#endif + + debug("%s: OK\n", __func__); + return 0; + +#ifdef CONFIG_CLK +err_disable_clk_tx: + clk_disable(&eqos->clk_tx); +err_disable_clk_rx: + clk_disable(&eqos->clk_rx); +err_disable_clk_master_bus: + clk_disable(&eqos->clk_master_bus); +err: + debug("%s: FAILED: %d\n", __func__, ret); + return ret; +#endif +} + +static int eqos_stop_clks_stm32(struct udevice *dev) +{ +#ifdef CONFIG_CLK + struct eqos_priv *eqos = dev_get_priv(dev); + + debug("%s(dev=%p):\n", __func__, dev); + + clk_disable(&eqos->clk_tx); + clk_disable(&eqos->clk_rx); + clk_disable(&eqos->clk_master_bus); +#endif + + debug("%s: OK\n", __func__); + return 0; +} + +static int eqos_probe_resources_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + int ret; + phy_interface_t interface; + + debug("%s(dev=%p):\n", __func__, dev); + + interface = eqos->config->interface(dev); + + if (interface == PHY_INTERFACE_MODE_NA) { + pr_err("Invalid PHY interface\n"); + return -EINVAL; + } + + ret = board_interface_eth_init(dev, interface); + if (ret) + return -EINVAL; + + ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); + if (ret) { + pr_err("clk_get_by_name(master_bus) failed: %d", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); + if (ret) { + pr_err("clk_get_by_name(rx) failed: %d", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); + if (ret) { + pr_err("clk_get_by_name(tx) failed: %d", ret); + goto err_probe; + } + + /* Get ETH_CLK clocks (optional) */ + ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); + if (ret) + pr_warn("No phy clock provided %d", ret); + + debug("%s: OK\n", __func__); + return 0; + +err_probe: + + debug("%s: returns %d\n", __func__, ret); + return ret; +} + +static int eqos_remove_resources_stm32(struct udevice *dev) +{ + debug("%s(dev=%p):\n", __func__, dev); + + return 0; +} + +static struct eqos_ops eqos_stm32_ops = { + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, + .eqos_inval_buffer = eqos_inval_buffer_generic, + .eqos_flush_buffer = eqos_flush_buffer_generic, + .eqos_probe_resources = eqos_probe_resources_stm32, + .eqos_remove_resources = eqos_remove_resources_stm32, + .eqos_stop_resets = eqos_null_ops, + .eqos_start_resets = eqos_null_ops, + .eqos_stop_clks = eqos_stop_clks_stm32, + .eqos_start_clks = eqos_start_clks_stm32, + .eqos_calibrate_pads = eqos_null_ops, + .eqos_disable_calibration = eqos_null_ops, + .eqos_set_tx_clk_speed = eqos_null_ops, + .eqos_get_enetaddr = eqos_null_ops, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 +}; + +struct eqos_config __maybe_unused eqos_stm32_config = { + .reg_access_always_ok = false, + .mdio_wait = 10000, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, + .interface = dev_read_phy_mode, + .ops = &eqos_stm32_ops +}; From 85d1de9a1f39a0ff393cd90aec46ce47d40be60c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:23 +0100 Subject: [PATCH 07/50] net: dwc_eth_qos: Rename eqos_stm32_config to eqos_stm32mp15_config The current glue code is specific to STM32MP15xx, the upcoming STM32MP13xx will introduce another entry specific to the STM32MP13xx. Rename the current entry to eqos_stm32mp15_config in preparation for STM32MP13xx addition. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos.c | 2 +- drivers/net/dwc_eth_qos.h | 2 +- drivers/net/dwc_eth_qos_stm32.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index aa4f815eb4..8d106ec0d0 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1507,7 +1507,7 @@ static const struct udevice_id eqos_ids[] = { #if IS_ENABLED(CONFIG_DWC_ETH_QOS_STM32) { .compatible = "st,stm32mp1-dwmac", - .data = (ulong)&eqos_stm32_config + .data = (ulong)&eqos_stm32mp15_config }, #endif #if IS_ENABLED(CONFIG_DWC_ETH_QOS_IMX) diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index a6087f191a..bafd0d339f 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,5 +290,5 @@ int eqos_null_ops(struct udevice *dev); extern struct eqos_config eqos_imx_config; extern struct eqos_config eqos_rockchip_config; extern struct eqos_config eqos_qcom_config; -extern struct eqos_config eqos_stm32_config; +extern struct eqos_config eqos_stm32mp15_config; extern struct eqos_config eqos_jh7110_config; diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index cfda757133..fd29a60498 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -184,7 +184,7 @@ static struct eqos_ops eqos_stm32_ops = { .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 }; -struct eqos_config __maybe_unused eqos_stm32_config = { +struct eqos_config __maybe_unused eqos_stm32mp15_config = { .reg_access_always_ok = false, .mdio_wait = 10000, .swr_wait = 50, From d100c1abb778f408691f983c9bf34ed9b4869493 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:24 +0100 Subject: [PATCH 08/50] net: dwc_eth_qos: Fold board_interface_eth_init into STM32 glue code Move board_interface_eth_init() into eqos_probe_syscfg_stm32() in STM32 driver glue code. The eqos_probe_syscfg_stm32() parses STM32 specific DT properties of this MAC and configures SYSCFG registers accordingly, there is nothing board specific happening in this function, move it into generic driver code instead. Drop the now unused duplicates from board files. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- board/dhelectronics/dh_stm32mp1/board.c | 82 ----------------------- board/st/stm32mp1/stm32mp1.c | 82 ----------------------- drivers/net/dwc_eth_qos_stm32.c | 86 ++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 166 deletions(-) diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index 079dfff038..22af423536 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/board/dhelectronics/dh_stm32mp1/board.c @@ -48,12 +48,10 @@ /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 -#define SYSCFG_PMCSETR 0x04 #define SYSCFG_IOCTRLSETR 0x18 #define SYSCFG_ICNR 0x1C #define SYSCFG_CMPCR 0x20 #define SYSCFG_CMPENSETR 0x24 -#define SYSCFG_PMCCLRR 0x44 #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) #define SYSCFG_BOOTR_BOOTPD_SHIFT 4 @@ -69,16 +67,6 @@ #define SYSCFG_CMPENSETR_MPU_EN BIT(0) -#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) -#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) - -#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) - -#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) -#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 -#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) -#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) - #define KS_CCR 0x08 #define KS_CCR_EEPROM BIT(9) #define KS_BE0 BIT(12) @@ -685,76 +673,6 @@ void board_quiesce_devices(void) #endif } -/* eth init function : weak called in eqos driver */ -int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type) -{ - u8 *syscfg; - u32 value; - bool eth_clk_sel_reg = false; - bool eth_ref_clk_sel_reg = false; - - /* Gigabit Ethernet 125MHz clock selection. */ - eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); - - /* Ethernet 50Mhz RMII clock selection */ - eth_ref_clk_sel_reg = - dev_read_bool(dev, "st,eth-ref-clk-sel"); - - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); - - if (!syscfg) - return -ENODEV; - - switch (interface_type) { - case PHY_INTERFACE_MODE_MII: - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - debug("%s: PHY_INTERFACE_MODE_MII\n", __func__); - break; - case PHY_INTERFACE_MODE_GMII: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; - debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__); - break; - case PHY_INTERFACE_MODE_RMII: - if (eth_ref_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RMII; - debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__); - break; - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RGMII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RGMII; - debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__); - break; - default: - debug("%s: Do not manage %d interface\n", - __func__, interface_type); - /* Do not manage others interfaces */ - return -EINVAL; - } - - /* clear and set ETH configuration bits */ - writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, - syscfg + SYSCFG_PMCCLRR); - writel(value, syscfg + SYSCFG_PMCSETR); - - return 0; -} - #if defined(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, struct bd_info *bd) { diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index a17c314dae..f284b0dfd2 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -52,12 +52,10 @@ /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 -#define SYSCFG_PMCSETR 0x04 #define SYSCFG_IOCTRLSETR 0x18 #define SYSCFG_ICNR 0x1C #define SYSCFG_CMPCR 0x20 #define SYSCFG_CMPENSETR 0x24 -#define SYSCFG_PMCCLRR 0x44 #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) #define SYSCFG_BOOTR_BOOTPD_SHIFT 4 @@ -73,16 +71,6 @@ #define SYSCFG_CMPENSETR_MPU_EN BIT(0) -#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) -#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) - -#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) - -#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) -#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 -#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) -#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) - #define USB_LOW_THRESHOLD_UV 200000 #define USB_WARNING_LOW_THRESHOLD_UV 660000 #define USB_START_LOW_THRESHOLD_UV 1230000 @@ -742,76 +730,6 @@ void board_quiesce_devices(void) setup_led(LEDST_OFF); } -/* eth init function : weak called in eqos driver */ -int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type) -{ - u8 *syscfg; - u32 value; - bool eth_clk_sel_reg = false; - bool eth_ref_clk_sel_reg = false; - - /* Gigabit Ethernet 125MHz clock selection. */ - eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); - - /* Ethernet 50Mhz RMII clock selection */ - eth_ref_clk_sel_reg = - dev_read_bool(dev, "st,eth-ref-clk-sel"); - - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); - - if (!syscfg) - return -ENODEV; - - switch (interface_type) { - case PHY_INTERFACE_MODE_MII: - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_MII\n"); - break; - case PHY_INTERFACE_MODE_GMII: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; - log_debug("PHY_INTERFACE_MODE_GMII\n"); - break; - case PHY_INTERFACE_MODE_RMII: - if (eth_ref_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RMII; - log_debug("PHY_INTERFACE_MODE_RMII\n"); - break; - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RGMII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RGMII; - log_debug("PHY_INTERFACE_MODE_RGMII\n"); - break; - default: - log_debug("Do not manage %d interface\n", - interface_type); - /* Do not manage others interfaces */ - return -EINVAL; - } - - /* clear and set ETH configuration bits */ - writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, - syscfg + SYSCFG_PMCCLRR); - writel(value, syscfg + SYSCFG_PMCSETR); - - return 0; -} - enum env_location env_get_location(enum env_operation op, int prio) { u32 bootmode = get_bootmode(); diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index fd29a60498..7520a136ed 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -24,11 +24,26 @@ #include #include #include +#include #include #include #include "dwc_eth_qos.h" +/* SYSCFG registers */ +#define SYSCFG_PMCSETR 0x04 +#define SYSCFG_PMCCLRR 0x44 + +#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) +#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) + +#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) + +#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) +#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 +#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) +#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) + static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) { #ifdef CONFIG_CLK @@ -108,11 +123,78 @@ static int eqos_stop_clks_stm32(struct udevice *dev) return 0; } +static int eqos_probe_syscfg_stm32(struct udevice *dev, + phy_interface_t interface_type) +{ + bool eth_ref_clk_sel_reg = false; + bool eth_clk_sel_reg = false; + u8 *syscfg; + u32 value; + + /* Gigabit Ethernet 125MHz clock selection. */ + eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); + + /* Ethernet 50Mhz RMII clock selection */ + eth_ref_clk_sel_reg = dev_read_bool(dev, "st,eth-ref-clk-sel"); + + syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); + if (!syscfg) + return -ENODEV; + + switch (interface_type) { + case PHY_INTERFACE_MODE_MII: + value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | + SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + log_debug("PHY_INTERFACE_MODE_MII\n"); + break; + case PHY_INTERFACE_MODE_GMII: + if (eth_clk_sel_reg) + value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | + SYSCFG_PMCSETR_ETH_CLK_SEL; + else + value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; + log_debug("PHY_INTERFACE_MODE_GMII\n"); + break; + case PHY_INTERFACE_MODE_RMII: + if (eth_ref_clk_sel_reg) + value = SYSCFG_PMCSETR_ETH_SEL_RMII | + SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + else + value = SYSCFG_PMCSETR_ETH_SEL_RMII; + log_debug("PHY_INTERFACE_MODE_RMII\n"); + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + if (eth_clk_sel_reg) + value = SYSCFG_PMCSETR_ETH_SEL_RGMII | + SYSCFG_PMCSETR_ETH_CLK_SEL; + else + value = SYSCFG_PMCSETR_ETH_SEL_RGMII; + log_debug("PHY_INTERFACE_MODE_RGMII\n"); + break; + default: + log_debug("Do not manage %d interface\n", + interface_type); + /* Do not manage others interfaces */ + return -EINVAL; + } + + /* clear and set ETH configuration bits */ + writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | + SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, + syscfg + SYSCFG_PMCCLRR); + writel(value, syscfg + SYSCFG_PMCSETR); + + return 0; +} + static int eqos_probe_resources_stm32(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); - int ret; phy_interface_t interface; + int ret; debug("%s(dev=%p):\n", __func__, dev); @@ -123,7 +205,7 @@ static int eqos_probe_resources_stm32(struct udevice *dev) return -EINVAL; } - ret = board_interface_eth_init(dev, interface); + ret = eqos_probe_syscfg_stm32(dev, interface); if (ret) return -EINVAL; From b204c2a9ae7adc3dc65a51df2254d8abc7ae07a3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:25 +0100 Subject: [PATCH 09/50] net: dwc_eth_qos: Scrub ifdeffery Replace ifdef CONFIG_CLK with if (CONFIG_IS_ENABLED(CLK)) to improve code build coverage. Some of the functions printed debug("%s: OK\n", __func__); on exit with and without CLK enabled, some did not, make it consistent and print nothing if CLK is disabled. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos_stm32.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 7520a136ed..d7ec0c9be3 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -46,21 +46,22 @@ static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) { -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); + + if (!CONFIG_IS_ENABLED(CLK)) + return 0; return clk_get_rate(&eqos->clk_master_bus); -#else - return 0; -#endif } static int eqos_start_clks_stm32(struct udevice *dev) { -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); int ret; + if (!CONFIG_IS_ENABLED(CLK)) + return 0; + debug("%s(dev=%p):\n", __func__, dev); ret = clk_enable(&eqos->clk_master_bus); @@ -89,12 +90,10 @@ static int eqos_start_clks_stm32(struct udevice *dev) } eqos->clk_ck_enabled = true; } -#endif debug("%s: OK\n", __func__); return 0; -#ifdef CONFIG_CLK err_disable_clk_tx: clk_disable(&eqos->clk_tx); err_disable_clk_rx: @@ -104,20 +103,20 @@ err_disable_clk_master_bus: err: debug("%s: FAILED: %d\n", __func__, ret); return ret; -#endif } static int eqos_stop_clks_stm32(struct udevice *dev) { -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); + + if (!CONFIG_IS_ENABLED(CLK)) + return 0; debug("%s(dev=%p):\n", __func__, dev); clk_disable(&eqos->clk_tx); clk_disable(&eqos->clk_rx); clk_disable(&eqos->clk_master_bus); -#endif debug("%s: OK\n", __func__); return 0; From 416592e26506f7ff44922b0547b297f5f7e52ad3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:26 +0100 Subject: [PATCH 10/50] net: dwc_eth_qos: Use FIELD_PREP for ETH_SEL bitfield Use FIELD_PREP to configure content of ETH_SEL bitfield in SYSCFG_PMCSETR register. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index d7ec0c9be3..7545026b15 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "dwc_eth_qos.h" @@ -40,9 +41,9 @@ #define SYSCFG_PMCSETR_ETH_SELMII BIT(20) #define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) -#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 -#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) -#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) +#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0x0 +#define SYSCFG_PMCSETR_ETH_SEL_RGMII 0x1 +#define SYSCFG_PMCSETR_ETH_SEL_RMII 0x4 static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) { @@ -142,35 +143,33 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, switch (interface_type) { case PHY_INTERFACE_MODE_MII: - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_GMII_MII); + value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; log_debug("PHY_INTERFACE_MODE_MII\n"); break; case PHY_INTERFACE_MODE_GMII: + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_GMII_MII); if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; + value |= SYSCFG_PMCSETR_ETH_CLK_SEL; log_debug("PHY_INTERFACE_MODE_GMII\n"); break; case PHY_INTERFACE_MODE_RMII: + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_RMII); if (eth_ref_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RMII; + value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; log_debug("PHY_INTERFACE_MODE_RMII\n"); break; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_RGMII); if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RGMII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RGMII; + value |= SYSCFG_PMCSETR_ETH_CLK_SEL; log_debug("PHY_INTERFACE_MODE_RGMII\n"); break; default: From a810aa8da792d2af56c36e70afd9d451cf21fb2d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:27 +0100 Subject: [PATCH 11/50] net: dwc_eth_qos: Move log_debug statements on top of case block Move the log_debug() calls on top of the bit manipulation code. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 7545026b15..38037c4795 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -143,34 +143,34 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, switch (interface_type) { case PHY_INTERFACE_MODE_MII: + log_debug("PHY_INTERFACE_MODE_MII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_MII\n"); break; case PHY_INTERFACE_MODE_GMII: + log_debug("PHY_INTERFACE_MODE_GMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); if (eth_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_GMII\n"); break; case PHY_INTERFACE_MODE_RMII: + log_debug("PHY_INTERFACE_MODE_RMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RMII); if (eth_ref_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_RMII\n"); break; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: + log_debug("PHY_INTERFACE_MODE_RGMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RGMII); if (eth_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_RGMII\n"); break; default: log_debug("Do not manage %d interface\n", From 2e8f75be62bafb7113a4135c278a681c066d8e5a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:28 +0100 Subject: [PATCH 12/50] net: dwc_eth_qos: Use consistent logging prints Use dev_*() only to print all the logs from this glue code, instead of mixing dev_*(), log_*(), pr_*() all in one code. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 52 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 38037c4795..72f65f8054 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -63,36 +63,36 @@ static int eqos_start_clks_stm32(struct udevice *dev) if (!CONFIG_IS_ENABLED(CLK)) return 0; - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); ret = clk_enable(&eqos->clk_master_bus); if (ret < 0) { - pr_err("clk_enable(clk_master_bus) failed: %d", ret); + dev_err(dev, "clk_enable(clk_master_bus) failed: %d\n", ret); goto err; } ret = clk_enable(&eqos->clk_rx); if (ret < 0) { - pr_err("clk_enable(clk_rx) failed: %d", ret); + dev_err(dev, "clk_enable(clk_rx) failed: %d\n", ret); goto err_disable_clk_master_bus; } ret = clk_enable(&eqos->clk_tx); if (ret < 0) { - pr_err("clk_enable(clk_tx) failed: %d", ret); + dev_err(dev, "clk_enable(clk_tx) failed: %d\n", ret); goto err_disable_clk_rx; } if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { ret = clk_enable(&eqos->clk_ck); if (ret < 0) { - pr_err("clk_enable(clk_ck) failed: %d", ret); + dev_err(dev, "clk_enable(clk_ck) failed: %d\n", ret); goto err_disable_clk_tx; } eqos->clk_ck_enabled = true; } - debug("%s: OK\n", __func__); + dev_dbg(dev, "%s: OK\n", __func__); return 0; err_disable_clk_tx: @@ -102,7 +102,8 @@ err_disable_clk_rx: err_disable_clk_master_bus: clk_disable(&eqos->clk_master_bus); err: - debug("%s: FAILED: %d\n", __func__, ret); + dev_dbg(dev, "%s: FAILED: %d\n", __func__, ret); + return ret; } @@ -113,13 +114,14 @@ static int eqos_stop_clks_stm32(struct udevice *dev) if (!CONFIG_IS_ENABLED(CLK)) return 0; - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); clk_disable(&eqos->clk_tx); clk_disable(&eqos->clk_rx); clk_disable(&eqos->clk_master_bus); - debug("%s: OK\n", __func__); + dev_dbg(dev, "%s: OK\n", __func__); + return 0; } @@ -143,20 +145,20 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, switch (interface_type) { case PHY_INTERFACE_MODE_MII: - log_debug("PHY_INTERFACE_MODE_MII\n"); + dev_dbg(dev, "PHY_INTERFACE_MODE_MII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; break; case PHY_INTERFACE_MODE_GMII: - log_debug("PHY_INTERFACE_MODE_GMII\n"); + dev_dbg(dev, "PHY_INTERFACE_MODE_GMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); if (eth_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; case PHY_INTERFACE_MODE_RMII: - log_debug("PHY_INTERFACE_MODE_RMII\n"); + dev_dbg(dev, "PHY_INTERFACE_MODE_RMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RMII); if (eth_ref_clk_sel_reg) @@ -166,15 +168,15 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: - log_debug("PHY_INTERFACE_MODE_RGMII\n"); + dev_dbg(dev, "PHY_INTERFACE_MODE_RGMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RGMII); if (eth_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; default: - log_debug("Do not manage %d interface\n", - interface_type); + dev_dbg(dev, "Do not manage %d interface\n", + interface_type); /* Do not manage others interfaces */ return -EINVAL; } @@ -194,12 +196,12 @@ static int eqos_probe_resources_stm32(struct udevice *dev) phy_interface_t interface; int ret; - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); interface = eqos->config->interface(dev); if (interface == PHY_INTERFACE_MODE_NA) { - pr_err("Invalid PHY interface\n"); + dev_err(dev, "Invalid PHY interface\n"); return -EINVAL; } @@ -209,39 +211,41 @@ static int eqos_probe_resources_stm32(struct udevice *dev) ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); if (ret) { - pr_err("clk_get_by_name(master_bus) failed: %d", ret); + dev_err(dev, "clk_get_by_name(master_bus) failed: %d\n", ret); goto err_probe; } ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); if (ret) { - pr_err("clk_get_by_name(rx) failed: %d", ret); + dev_err(dev, "clk_get_by_name(rx) failed: %d\n", ret); goto err_probe; } ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); if (ret) { - pr_err("clk_get_by_name(tx) failed: %d", ret); + dev_err(dev, "clk_get_by_name(tx) failed: %d\n", ret); goto err_probe; } /* Get ETH_CLK clocks (optional) */ ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); if (ret) - pr_warn("No phy clock provided %d", ret); + dev_warn(dev, "No phy clock provided %d\n", ret); + + dev_dbg(dev, "%s: OK\n", __func__); - debug("%s: OK\n", __func__); return 0; err_probe: - debug("%s: returns %d\n", __func__, ret); + dev_dbg(dev, "%s: returns %d\n", __func__, ret); + return ret; } static int eqos_remove_resources_stm32(struct udevice *dev) { - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); return 0; } From 22265e236538f29e38df2411a12103aeefb3138b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:29 +0100 Subject: [PATCH 13/50] net: dwc_eth_qos: Constify st, eth-* values parsed out of DT Use const bool for the values parsed out of DT. Drop the duplicate assignment of false into those bool variables, assign them directly with the content parsed out of DT. Abbreviate the variable name too. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 72f65f8054..0b13d01346 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -128,17 +128,13 @@ static int eqos_stop_clks_stm32(struct udevice *dev) static int eqos_probe_syscfg_stm32(struct udevice *dev, phy_interface_t interface_type) { - bool eth_ref_clk_sel_reg = false; - bool eth_clk_sel_reg = false; + /* Ethernet 50MHz RMII clock selection. */ + const bool eth_ref_clk_sel = dev_read_bool(dev, "st,eth-ref-clk-sel"); + /* Gigabit Ethernet 125MHz clock selection. */ + const bool eth_clk_sel = dev_read_bool(dev, "st,eth-clk-sel"); u8 *syscfg; u32 value; - /* Gigabit Ethernet 125MHz clock selection. */ - eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); - - /* Ethernet 50Mhz RMII clock selection */ - eth_ref_clk_sel_reg = dev_read_bool(dev, "st,eth-ref-clk-sel"); - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); if (!syscfg) return -ENODEV; @@ -154,14 +150,14 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, dev_dbg(dev, "PHY_INTERFACE_MODE_GMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); - if (eth_clk_sel_reg) + if (eth_clk_sel) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; case PHY_INTERFACE_MODE_RMII: dev_dbg(dev, "PHY_INTERFACE_MODE_RMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RMII); - if (eth_ref_clk_sel_reg) + if (eth_ref_clk_sel) value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; break; case PHY_INTERFACE_MODE_RGMII: @@ -171,7 +167,7 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, dev_dbg(dev, "PHY_INTERFACE_MODE_RGMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RGMII); - if (eth_clk_sel_reg) + if (eth_clk_sel) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; default: From a440d19c6c91938190b329be65e0986e01007304 Mon Sep 17 00:00:00 2001 From: Christophe Roullier Date: Tue, 26 Mar 2024 13:07:30 +0100 Subject: [PATCH 14/50] net: dwc_eth_qos: Add DT parsing for STM32MP13xx platform Manage 2 ethernet instances, select which instance to configure with mask If mask is not present in DT, it is stm32mp15 platform. Signed-off-by: Christophe Roullier Signed-off-by: Marek Vasut # Rework the code Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos_stm32.c | 41 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 0b13d01346..5a20fe5bea 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -33,11 +34,16 @@ /* SYSCFG registers */ #define SYSCFG_PMCSETR 0x04 -#define SYSCFG_PMCCLRR 0x44 +#define SYSCFG_PMCCLRR_MP13 0x08 +#define SYSCFG_PMCCLRR_MP15 0x44 + +#define SYSCFG_PMCSETR_ETH1_MASK GENMASK(23, 16) +#define SYSCFG_PMCSETR_ETH2_MASK GENMASK(31, 24) #define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) #define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) +/* STM32MP15xx specific bit */ #define SYSCFG_PMCSETR_ETH_SELMII BIT(20) #define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) @@ -130,23 +136,30 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, { /* Ethernet 50MHz RMII clock selection. */ const bool eth_ref_clk_sel = dev_read_bool(dev, "st,eth-ref-clk-sel"); + /* SoC is STM32MP13xx with two ethernet MACs */ + const bool is_mp13 = device_is_compatible(dev, "st,stm32mp13-dwmac"); /* Gigabit Ethernet 125MHz clock selection. */ const bool eth_clk_sel = dev_read_bool(dev, "st,eth-clk-sel"); - u8 *syscfg; + struct regmap *regmap; + u32 regmap_mask; u32 value; - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); - if (!syscfg) - return -ENODEV; + regmap = syscon_regmap_lookup_by_phandle(dev, "st,syscon"); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + regmap_mask = dev_read_u32_index_default(dev, "st,syscon", 2, + SYSCFG_PMCSETR_ETH1_MASK); switch (interface_type) { case PHY_INTERFACE_MODE_MII: dev_dbg(dev, "PHY_INTERFACE_MODE_MII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); - value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + if (!is_mp13) /* Select MII mode on STM32MP15xx */ + value |= SYSCFG_PMCSETR_ETH_SELMII; break; - case PHY_INTERFACE_MODE_GMII: + case PHY_INTERFACE_MODE_GMII: /* STM32MP15xx only */ dev_dbg(dev, "PHY_INTERFACE_MODE_GMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); @@ -177,13 +190,15 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, return -EINVAL; } - /* clear and set ETH configuration bits */ - writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, - syscfg + SYSCFG_PMCCLRR); - writel(value, syscfg + SYSCFG_PMCSETR); + /* Shift value at correct ethernet MAC offset in SYSCFG_PMCSETR */ + value <<= ffs(regmap_mask) - ffs(SYSCFG_PMCSETR_ETH1_MASK); - return 0; + /* Update PMCCLRR (clear register) */ + regmap_write(regmap, is_mp13 ? + SYSCFG_PMCCLRR_MP13 : SYSCFG_PMCCLRR_MP15, + regmap_mask); + + return regmap_update_bits(regmap, SYSCFG_PMCSETR, regmap_mask, value); } static int eqos_probe_resources_stm32(struct udevice *dev) From 882b2287a654cb1c86bde24175385220ffeb0cc8 Mon Sep 17 00:00:00 2001 From: Christophe Roullier Date: Tue, 26 Mar 2024 13:07:31 +0100 Subject: [PATCH 15/50] net: dwc_eth_qos: Add support of STM32MP13xx platform Add compatible "st,stm32mp13-dwmac" to manage STM32MP13 boards. Reviewed-by: Patrice Chotard Signed-off-by: Christophe Roullier Signed-off-by: Marek Vasut # Rebase, reshuffle, squash code Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos.c | 4 ++++ drivers/net/dwc_eth_qos.h | 1 + drivers/net/dwc_eth_qos_stm32.c | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 8d106ec0d0..32a5d52165 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1505,6 +1505,10 @@ static const struct udevice_id eqos_ids[] = { }, #endif #if IS_ENABLED(CONFIG_DWC_ETH_QOS_STM32) + { + .compatible = "st,stm32mp13-dwmac", + .data = (ulong)&eqos_stm32mp13_config + }, { .compatible = "st,stm32mp1-dwmac", .data = (ulong)&eqos_stm32mp15_config diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index bafd0d339f..8b3d0d464d 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,5 +290,6 @@ int eqos_null_ops(struct udevice *dev); extern struct eqos_config eqos_imx_config; extern struct eqos_config eqos_rockchip_config; extern struct eqos_config eqos_qcom_config; +extern struct eqos_config eqos_stm32mp13_config; extern struct eqos_config eqos_stm32mp15_config; extern struct eqos_config eqos_jh7110_config; diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 5a20fe5bea..435473f99a 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -279,6 +279,17 @@ static struct eqos_ops eqos_stm32_ops = { .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 }; +struct eqos_config __maybe_unused eqos_stm32mp13_config = { + .reg_access_always_ok = false, + .mdio_wait = 10000, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_32, + .interface = dev_read_phy_mode, + .ops = &eqos_stm32_ops +}; + struct eqos_config __maybe_unused eqos_stm32mp15_config = { .reg_access_always_ok = false, .mdio_wait = 10000, From 1ef28c58d2dbd8c7d65e28ef500bfd359c66c07f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:32 +0100 Subject: [PATCH 16/50] net: dwc_eth_qos: Add support for st, ext-phyclk property The "st,ext-phyclk" property is a unification of "st,eth-clk-sel" and "st,eth-ref-clk-sel" properties. All three properties define ETH CK clock direction, however: - "st,eth-clk-sel" selects clock direction for GMII/RGMII mode - "st,eth-ref-clk-sel" selects clock direction for RMII mode - "st,ext-phyclk" selects clock direction for all RMII/GMII/RGMII modes The "st,ext-phyclk" is the preferrable property to use. Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos_stm32.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 435473f99a..9ee82b54c6 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -140,6 +140,8 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, const bool is_mp13 = device_is_compatible(dev, "st,stm32mp13-dwmac"); /* Gigabit Ethernet 125MHz clock selection. */ const bool eth_clk_sel = dev_read_bool(dev, "st,eth-clk-sel"); + /* Ethernet clock source is RCC. */ + const bool ext_phyclk = dev_read_bool(dev, "st,ext-phyclk"); struct regmap *regmap; u32 regmap_mask; u32 value; @@ -156,6 +158,12 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, dev_dbg(dev, "PHY_INTERFACE_MODE_MII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); + /* + * STM32MP15xx supports both MII and GMII, STM32MP13xx MII only. + * SYSCFG_PMCSETR ETH_SELMII is present only on STM32MP15xx and + * acts as a selector between 0:GMII and 1:MII. As STM32MP13xx + * supports only MII, ETH_SELMII is not present. + */ if (!is_mp13) /* Select MII mode on STM32MP15xx */ value |= SYSCFG_PMCSETR_ETH_SELMII; break; @@ -163,14 +171,25 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, dev_dbg(dev, "PHY_INTERFACE_MODE_GMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); - if (eth_clk_sel) + /* + * If eth_clk_sel is set, use internal ETH_CLKx clock from RCC, + * otherwise use external clock from IO pin (requires matching + * GPIO block AF setting of that pin). + */ + if (eth_clk_sel || ext_phyclk) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; case PHY_INTERFACE_MODE_RMII: dev_dbg(dev, "PHY_INTERFACE_MODE_RMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RMII); - if (eth_ref_clk_sel) + /* + * If eth_ref_clk_sel is set, use internal clock from RCC, + * otherwise use external clock from ETHn_RX_CLK/ETHn_REF_CLK + * IO pin (requires matching GPIO block AF setting of that + * pin). + */ + if (eth_ref_clk_sel || ext_phyclk) value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; break; case PHY_INTERFACE_MODE_RGMII: @@ -180,7 +199,12 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, dev_dbg(dev, "PHY_INTERFACE_MODE_RGMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RGMII); - if (eth_clk_sel) + /* + * If eth_clk_sel is set, use internal ETH_CLKx clock from RCC, + * otherwise use external clock from ETHx_CLK125 pin (requires + * matching GPIO block AF setting of that pin). + */ + if (eth_clk_sel || ext_phyclk) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; default: From 3242dd0ac91ea4fd9cf516f0d196a34ea23367de Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 7 Apr 2024 22:21:07 +0200 Subject: [PATCH 17/50] ARM: stm32: Jump to ep on successful resume in PSCI suspend code In case the system has resumed successfully, the PSCI suspend resume code has to jump to the 'ep' successful resume entry point code path, otherwise the code has to jump to content of the LR register, which points to failed resume code path. To implement this distinction, rewrite LR register stored on stack with 'ep' value in case of a successful resume, which is really in every case unless some catastrophic failure occurred during suspend. Without this change, Linux counts every resume as failed in /sys/power/suspend_stats/fail Signed-off-by: Marek Vasut Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/stm32mp1/psci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/mach-stm32mp/stm32mp1/psci.c b/arch/arm/mach-stm32mp/stm32mp1/psci.c index 8cdeb0ab3f..4f2379df45 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/psci.c +++ b/arch/arm/mach-stm32mp/stm32mp1/psci.c @@ -703,6 +703,8 @@ void __secure psci_system_suspend(u32 __always_unused function_id, { u32 saved_mcudivr, saved_pll3cr, saved_pll4cr, saved_mssckselr; u32 gicd_addr = stm32mp_get_gicd_base_address(); + u32 cpu = psci_get_cpu_id(); + u32 sp = (u32)__secure_stack_end - (cpu << ARM_PSCI_STACK_SHIFT); bool iwdg1_wake = false; bool iwdg2_wake = false; bool other_wake = false; @@ -805,4 +807,16 @@ void __secure psci_system_suspend(u32 __always_unused function_id, writel(SYSCFG_CMPENR_MPUEN, STM32_SYSCFG_BASE + SYSCFG_CMPENSETR); clrbits_le32(STM32_SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); + + /* + * The system has resumed successfully. Rewrite LR register stored + * on stack with 'ep' value, so that on return from this PSCI call, + * the code would jump to that 'ep' resume entry point code path + * instead of the previous 'lr' register content which (e.g. with + * Linux) points to resume failure code path. + * + * See arch/arm/cpu/armv7/psci.S _smc_psci: for the stack layout + * used here, SP-4 is PC, SP-8 is LR, SP-12 is R7, and so on. + */ + writel(ep, sp - 8); } From 97b6c77c20544b4d4bbd470a57822f1230aabb45 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 14 Apr 2024 20:38:31 +0200 Subject: [PATCH 18/50] ARM: stm32: Drop superfluous Makefile entry for ecdsa_romapi.o The source file is in arch/arm/mach-stm32mp/ecdsa_romapi.c and not in arch/arm/mach-stm32mp/stm32mp1/ecdsa_romapi.c . There are two Makefile entries in each subdirectory. Drop the bogus one and keep only the correct one, the one in arch/arm/mach-stm32mp/Makefile . Signed-off-by: Marek Vasut Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/stm32mp1/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-stm32mp/stm32mp1/Makefile b/arch/arm/mach-stm32mp/stm32mp1/Makefile index 857148747e..ebae50f66c 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/Makefile +++ b/arch/arm/mach-stm32mp/stm32mp1/Makefile @@ -8,7 +8,6 @@ obj-y += cpu.o obj-$(CONFIG_STM32MP13X) += stm32mp13x.o obj-$(CONFIG_STM32MP15X) += stm32mp15x.o -obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o ifdef CONFIG_SPL_BUILD obj-y += spl.o obj-y += tzc400.o From b5e7c5da8bf3b40bec36295818f0333c5d918630 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 14 Apr 2024 20:39:29 +0200 Subject: [PATCH 19/50] ARM: stm32: Report OTP-CLOSED instead of rev.? on closed STM32MP15xx SoC revision is only accessible via DBUMCU IDC register, which requires BSEC.DENABLE DBGSWENABLE bit to be set to make the register accessible, otherwise an access to the register triggers bus fault. As BSEC.DBGSWENABLE is zero in case of an OTP-CLOSED system, do NOT set DBGSWENABLE bit as this might open a brief window for timing attacks. Instead, report that this system is OTP-CLOSED and do not report any SoC revision to avoid confusing users. Use an SEC/C abbreviation to avoid growing SOC_NAME_SIZE . Signed-off-by: Marek Vasut Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c b/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c index afc56b02ee..dd99150fbc 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c +++ b/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c @@ -322,8 +322,23 @@ void get_soc_name(char name[SOC_NAME_SIZE]) get_cpu_string_offsets(&type, &pkg, &rev); - snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", - soc_type[type], soc_pkg[pkg], soc_rev[rev]); + if (bsec_dbgswenable()) { + snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", + soc_type[type], soc_pkg[pkg], soc_rev[rev]); + } else { + /* + * SoC revision is only accessible via DBUMCU IDC register, + * which requires BSEC.DENABLE DBGSWENABLE bit to be set to + * make the register accessible, otherwise an access to the + * register triggers bus fault. As BSEC.DBGSWENABLE is zero + * in case of an OTP-CLOSED system, do NOT set DBGSWENABLE + * bit as this might open a brief window for timing attacks. + * Instead, report that this system is OTP-CLOSED and do not + * report any SoC revision to avoid confusing users. + */ + snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s SEC/C", + soc_type[type], soc_pkg[pkg]); + } } static void setup_soc_type_pkg_rev(void) From 73f7fc944cf6e7975bfbe52c219bc973233e93fc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 19 Apr 2024 05:59:05 +0200 Subject: [PATCH 20/50] ARM: stm32: Initialize TAMP_SMCR BKP..PROT fields on STM32MP15xx In case of an OTP-CLOSED STM32MP15xx system, the CPU core 1 cannot be released from endless loop in BootROM only by populating TAMP BKPxR 4 and 5 with magic and branch address and sending SGI0 interrupt from core 0 to core 1 twice. TAMP_SMCR BKP..PROT fields must be initialized as well to release the core 1 from endless loop during the second SGI0 handling on core 1. Initialize TAMP_SMCR to protect the first 32 backup registers, the ones which contain the core 1 magic, branch address and boot information. This requirement seems to be undocumented, therefore it was necessary to trace and analyze the STM32MP15xx BootROM using OpenOCD and objdump. Ultimately, it turns out that a certain BootROM function reads out the TAMP_SMCR register and tests whether the BKP..PROT fields are non-zero. If they are zero, the BootROM code again waits for SGI0 using WFI, else the execution moves forward until it reaches handoff to the TAMP BKPxR 5 branch address. This fixes CPU core 1 release using U-Boot PSCI implementation on an OTP-CLOSED system, i.e. system with fuse 0 bit 6 set. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c b/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c index dd99150fbc..d75ec99d6a 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c +++ b/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c @@ -14,6 +14,7 @@ #include #include #include +#include /* RCC register */ #define RCC_TZCR (STM32_RCC_BASE + 0x00) @@ -41,6 +42,9 @@ #define TZC_REGION_ID_ACCESS0 (STM32_TZC_BASE + 0x114) #define TAMP_CR1 (STM32_TAMP_BASE + 0x00) +#define TAMP_SMCR (STM32_TAMP_BASE + 0x20) +#define TAMP_SMCR_BKPRWDPROT GENMASK(7, 0) +#define TAMP_SMCR_BKPWDPROT GENMASK(23, 16) #define PWR_CR1 (STM32_PWR_BASE + 0x00) #define PWR_MCUCR (STM32_PWR_BASE + 0x14) @@ -136,6 +140,18 @@ static void security_init(void) */ writel(0x0, TAMP_CR1); + /* + * TAMP: Configure non-zero secure protection settings. This is + * checked by BootROM function 35ac on OTP-CLOSED device during + * CPU core 1 release from endless loop. If secure protection + * fields are zero, the core 1 is not released from endless + * loop on second SGI0. + */ + clrsetbits_le32(TAMP_SMCR, + TAMP_SMCR_BKPRWDPROT | TAMP_SMCR_BKPWDPROT, + FIELD_PREP(TAMP_SMCR_BKPRWDPROT, 0x20) | + FIELD_PREP(TAMP_SMCR_BKPWDPROT, 0x20)); + /* GPIOZ: deactivate the security */ writel(BIT(0), RCC_MP_AHB5ENSETR); writel(0x0, GPIOZ_SECCFGR); From 08ceeaa85dcb2e9ddafadd268d268f6afb6e84ae Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 8 Mar 2024 14:50:07 +0100 Subject: [PATCH 21/50] ARM: dts: stm32: Fix partition node name for stm32mp157c-ev1-u-boot Fix flash@0 and nand@0 partition node name with correct offset. Fixes: e91d3c61767b ("arm: dts: stm32: Add partitions in flash0 and nand node for stm32mp15xx-ev1") Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi index 139940bd5d..3515347e91 100644 --- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi @@ -33,11 +33,11 @@ label = "fsbl1"; reg = <0x00000000 0x00040000>; }; - partition@80000 { + partition@40000 { label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@100000 { + partition@80000 { label = "ssbl"; reg = <0x00080000 0x00200000>; }; @@ -58,7 +58,7 @@ label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@100000 { + partition@80000 { label = "fip"; reg = <0x00080000 0x00400000>; }; @@ -112,7 +112,7 @@ label = "fip2"; reg = <0x00600000 0x00400000>; }; - partition@1200000 { + partition@a00000 { label = "UBI"; reg = <0x00a00000 0x3f600000>; }; From 617e1a413ec89f0af99002ca1cdd69434a4a3591 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 8 Mar 2024 14:50:08 +0100 Subject: [PATCH 22/50] ARM: dts: stm32: Fix partition node name for stm32mp15xx-dhcor-u-boot Fix flash@0 partition node name with correct offset. Fixes: 90f992e6a58c ("arm: dts: stm32: Add partitions in flash0 and nand node for stm32mp15xx-dhcom/dhcor") Signed-off-by: Patrice Chotard Reviewed-by: Marek Vasut Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi index 552b35db3c..ba84db679e 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi @@ -42,15 +42,15 @@ label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@500000 { + partition@80000 { label = "uboot"; reg = <0x00080000 0x00160000>; }; - partition@900000 { + partition@1e0000 { label = "env1"; reg = <0x001E0000 0x00010000>; }; - partition@980000 { + partition@1f0000 { label = "env2"; reg = <0x001F0000 0x00010000>; }; From d41ff02aea86ae309e4b9990f7d2c697be7bb8a1 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 8 Mar 2024 14:50:09 +0100 Subject: [PATCH 23/50] ARM: dts: stm32: Fix partition node name for stm32mp15xx-dhcom-u-boot Fix flash@0 partition node name with correct offset. Fixes: 90f992e6a58c ("arm: dts: stm32: Add partitions in flash0 and nand node for stm32mp15xx-dhcom/dhcor") Signed-off-by: Patrice Chotard Reviewed-by: Marek Vasut Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi index 2f70b0690d..1b44561932 100644 --- a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi @@ -106,15 +106,15 @@ label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@500000 { + partition@80000 { label = "uboot"; reg = <0x00080000 0x00160000>; }; - partition@900000 { + partition@1e0000 { label = "env1"; reg = <0x001E0000 0x00010000>; }; - partition@980000 { + partition@1f0000 { label = "env2"; reg = <0x001F0000 0x00010000>; }; From f3901e808902a55d9024b3549c96518857551c3d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Fri, 8 Mar 2024 15:26:13 +0100 Subject: [PATCH 24/50] mmc: stm32_sdmmc2: Add "st,stm32mp25-sdmmc2" compatible Add compatible used for STM32MP25 family. Signed-off-by: Patrick Delaunay Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay Reviewed-by: Jaehoon Chung --- drivers/mmc/stm32_sdmmc2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index a2b111a843..d4982a1428 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/drivers/mmc/stm32_sdmmc2.c @@ -789,6 +789,7 @@ static int stm32_sdmmc2_bind(struct udevice *dev) static const struct udevice_id stm32_sdmmc2_ids[] = { { .compatible = "st,stm32-sdmmc2" }, + { .compatible = "st,stm32mp25-sdmmc2" }, { } }; From e725682d6052cd6871b092bf96258225353dc5cc Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 8 Mar 2024 15:26:14 +0100 Subject: [PATCH 25/50] mmc: stm32_sdmmc2: Fix AARCH64 compilation warnings When building with AARCH64 defconfig, we got warnings, fix them. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay Reviewed-by: Jaehoon Chung --- drivers/mmc/stm32_sdmmc2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index d4982a1428..39ae79ba12 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/drivers/mmc/stm32_sdmmc2.c @@ -220,9 +220,9 @@ static void stm32_sdmmc2_start_data(struct udevice *dev, if (data->flags & MMC_DATA_READ) { data_ctrl |= SDMMC_DCTRL_DTDIR; - idmabase0 = (u32)data->dest; + idmabase0 = (u32)(long)data->dest; } else { - idmabase0 = (u32)data->src; + idmabase0 = (u32)(long)data->src; } /* Set the SDMMC DataLength value */ @@ -463,8 +463,8 @@ retry_cmd: stm32_sdmmc2_start_cmd(dev, cmd, cmdat, &ctx); - dev_dbg(dev, "send cmd %d data: 0x%x @ 0x%x\n", - cmd->cmdidx, data ? ctx.data_length : 0, (unsigned int)data); + dev_dbg(dev, "send cmd %d data: 0x%x @ 0x%p\n", + cmd->cmdidx, data ? ctx.data_length : 0, data); ret = stm32_sdmmc2_end_cmd(dev, cmd, &ctx); From 56adbdfa0e98d43111811cb3473f6bcc46dbd669 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:51 +0200 Subject: [PATCH 26/50] configs: stm32mp13: Enable FASTBOOT Enable FASTBOOT relative flags for stm32mp13_defconfig. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay Reviewed-by: Igor Opaniuk --- configs/stm32mp13_defconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig index c893e272db..db09e63100 100644 --- a/configs/stm32mp13_defconfig +++ b/configs/stm32mp13_defconfig @@ -15,6 +15,7 @@ CONFIG_CMD_STM32PROG=y CONFIG_SYS_LOAD_ADDR=0xc2000000 CONFIG_SYS_MEMTEST_START=0xc0000000 CONFIG_SYS_MEMTEST_END=0xc4000000 +# CONFIG_ANDROID_BOOT_IMAGE is not set CONFIG_FIT=y CONFIG_SYS_BOOTM_LEN=0x2000000 CONFIG_DISTRO_DEFAULTS=y @@ -53,6 +54,13 @@ CONFIG_SYS_MMC_ENV_DEV=-1 CONFIG_ENV_MMC_USE_DT=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0xc0000000 +CONFIG_FASTBOOT_BUF_SIZE=0x02000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_FASTBOOT_CMD_OEM_PARTCONF=y CONFIG_GPIO_HOG=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_STM32F7=y @@ -92,7 +100,6 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720 CONFIG_USB_GADGET_DWC2_OTG=y -CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_ERRNO_STR=y # CONFIG_LMB_USE_MAX_REGIONS is not set CONFIG_LMB_MEMORY_REGIONS=2 From 175eb4fd3ea6ca9f488b81626bc1f254c55edfb2 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:52 +0200 Subject: [PATCH 27/50] configs: stm32mp1: Enable BUTTON_GPIO flag for stm32mp15_defconfig Enable BUTTON_GPIO flag for STM32MP15. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- configs/stm32mp15_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/stm32mp15_defconfig b/configs/stm32mp15_defconfig index 3302b30699..ffe7512650 100644 --- a/configs/stm32mp15_defconfig +++ b/configs/stm32mp15_defconfig @@ -69,6 +69,8 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_SERVERIP=y CONFIG_SERVERIP="192.168.1.1" CONFIG_STM32_ADC=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y From b70eea28fdad40db407b6ff8f5094c92e4be7e6b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:53 +0200 Subject: [PATCH 28/50] configs: stm32mp1: Enable BUTTON_GPIO flag for stm32mp15_basic_defconfig Enable BUTTON_GPIO flag for STM32MP15. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- configs/stm32mp15_basic_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 005f1d55f8..2e22bf8600 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -97,6 +97,8 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_SERVERIP=y CONFIG_SERVERIP="192.168.1.1" CONFIG_STM32_ADC=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 From 30eb9caa1cd9742179e07d964703e393d1fb2bdd Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:54 +0200 Subject: [PATCH 29/50] configs: stm32mp1: Enable BUTTON_GPIO flag for stm32mp15_trusted_defconfig Enable BUTTON_GPIO flag for STM32MP15. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- configs/stm32mp15_trusted_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 84b0854b55..74deaaba2e 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -70,6 +70,8 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_SERVERIP=y CONFIG_SERVERIP="192.168.1.1" CONFIG_STM32_ADC=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y From 2d48ff59ea6d7978e7e5829e46cd5840dbfaf2bd Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:55 +0200 Subject: [PATCH 30/50] configs: stm32mp1: Enable BUTTON_GPIO flag for stm32mp13_defconfig Enable BUTTON_GPIO flag for STM32MP15. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay Reviewed-by: Igor Opaniuk --- configs/stm32mp13_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig index db09e63100..caaabf39ef 100644 --- a/configs/stm32mp13_defconfig +++ b/configs/stm32mp13_defconfig @@ -52,6 +52,8 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SYS_MMC_ENV_DEV=-1 CONFIG_ENV_MMC_USE_DT=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y From 2430da43cb80a4d97daebe9084adf43746daca17 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:56 +0200 Subject: [PATCH 31/50] board: st: stmp32mp1: Use BUTTON UCLASS in board_key_check() Instead of using gpio directly to detect key pressed on button dedicated for fastboot and stm32mprog, make usage of BUTTON UCLASS. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- board/st/stm32mp1/stm32mp1.c | 70 +++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index f284b0dfd2..db15d78237 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -138,45 +140,55 @@ int checkboard(void) static void board_key_check(void) { - ofnode node; - struct gpio_desc gpio; + struct udevice *button1 = NULL, *button2 = NULL; enum forced_boot_mode boot_mode = BOOT_NORMAL; + int ret; + + if (!IS_ENABLED(CONFIG_BUTTON)) + return; if (!IS_ENABLED(CONFIG_FASTBOOT) && !IS_ENABLED(CONFIG_CMD_STM32PROG)) return; - node = ofnode_path("/config"); - if (!ofnode_valid(node)) { - log_debug("no /config node?\n"); - return; - } - if (IS_ENABLED(CONFIG_FASTBOOT)) { - if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0, - &gpio, GPIOD_IS_IN)) { - log_debug("could not find a /config/st,fastboot-gpios\n"); - } else { - udelay(20); - if (dm_gpio_get_value(&gpio)) { - log_notice("Fastboot key pressed, "); - boot_mode = BOOT_FASTBOOT; - } + if (IS_ENABLED(CONFIG_CMD_STM32PROG)) + button_get_by_label("User-1", &button1); - dm_gpio_free(NULL, &gpio); + if (IS_ENABLED(CONFIG_FASTBOOT)) + button_get_by_label("User-2", &button2); + + if (!button1 && !button2) + return; + + if (button2) { + if (button_get_state(button2) == BUTTON_ON) { + log_notice("Fastboot key pressed, "); + boot_mode = BOOT_FASTBOOT; } + /* + * On some boards, same gpio is shared betwwen gpio-keys and + * leds, remove the button device to free the gpio for led + * usage + */ + ret = device_remove(button2, DM_REMOVE_NORMAL); + if (ret) + log_err("Can't remove button2 (%d)\n", ret); } - if (IS_ENABLED(CONFIG_CMD_STM32PROG)) { - if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0, - &gpio, GPIOD_IS_IN)) { - log_debug("could not find a /config/st,stm32prog-gpios\n"); - } else { - udelay(20); - if (dm_gpio_get_value(&gpio)) { - log_notice("STM32Programmer key pressed, "); - boot_mode = BOOT_STM32PROG; - } - dm_gpio_free(NULL, &gpio); + + if (button1) { + if (button_get_state(button1) == BUTTON_ON) { + log_notice("STM32Programmer key pressed, "); + boot_mode = BOOT_STM32PROG; } + /* + * On some boards, same gpio is shared betwwen gpio-keys and + * leds, remove the button device to free the gpio for led + * usage + */ + ret = device_remove(button1, DM_REMOVE_NORMAL); + if (ret) + log_err("Can't remove button1 (%d)\n", ret); } + if (boot_mode != BOOT_NORMAL) { log_notice("entering download mode...\n"); clrsetbits_le32(TAMP_BOOT_CONTEXT, From 485798dd9bf7603ce90cf4c390c2ce746b70d1bc Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:57 +0200 Subject: [PATCH 32/50] ARM: dts: stm32: Add gpio-keys for stm32mp135f-dk-u-boot Add 2 gpio-keys : _ button-user-1 for stm32prog mode activation. _ update button-user's label (defined in kernel DT) to match label requested in board_key_check() for fastboot mode activation. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp135f-dk-u-boot.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi index ba0c02489d..e64ded1346 100644 --- a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi +++ b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi @@ -16,6 +16,19 @@ u-boot,mmc-env-partition = "u-boot-env"; }; + gpio-keys { + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user { + /* update label to match the label requested in board_key_check() */ + label = "User-2"; + }; + }; + leds { led-red { color = ; From 1e26c20662e9a7483e64d609aab286235fe13a3b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:58 +0200 Subject: [PATCH 33/50] ARM: dts: stm32: Don't probe led-red/led-blue at boot for stm32mp135f-dk-u-boot led-red and button dedicated to fastboot share the same gpio GPIOA13. led-blue and button dedicated to stm32prog share the same gpio GPIOA14. Led driver is probed early so the corresponding gpio is taken and configured in output which forbid fastboot and stm32prog button usage. To avoid this, remove the "default-state" property from led-red and led-blue led's node. This will avoid to trigger the led driver probe() to configure the led default state during startup. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp135f-dk-u-boot.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi index e64ded1346..8f42735609 100644 --- a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi +++ b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi @@ -30,10 +30,13 @@ }; leds { + led-blue { + /delete-property/default-state; + }; + led-red { color = ; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; }; }; }; From 6b6e6d93300856df1b93489b37d0e5a023705d86 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:01:59 +0200 Subject: [PATCH 34/50] ARM: dts: stm32: Clean led-red node for stm32mp135f-dk-u-boot Remove "color" property from led-red node which is not supported by U-Boot. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp135f-dk-u-boot.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi index 8f42735609..f004e9840a 100644 --- a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi +++ b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi @@ -35,7 +35,6 @@ }; led-red { - color = ; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; }; }; From bebe5b69964e30b194621b77a91fdd4f339848af Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:00 +0200 Subject: [PATCH 35/50] ARM: dts: stm32: Add gpio-keys for stm32mp157a-dk1-scmi-u-boot Instead of using "st,fastboot-gpios" and "st,stm32prog-gpios", declare 2 gpio-keys. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi index 20728f27ee..5d49b09c35 100644 --- a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi @@ -3,6 +3,7 @@ * Copyright : STMicroelectronics 2022 */ +#include #include "stm32mp15-scmi-u-boot.dtsi" / { @@ -16,8 +17,22 @@ u-boot,error-led = "error"; u-boot,mmc-env-partition = "u-boot-env"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; }; led { From 72ff88ecf53fb193dcf8612211f4f8d2ce239eb1 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:01 +0200 Subject: [PATCH 36/50] ARM: dts: stm32: Don't probe red led at boot for stm32mp157a-dk1-scmi-u-boot red led and button dedicated to fastboot share the same gpio GPIOA13. Led driver is probed early so the corresponding gpio is taken and configured in output which forbid fastboot and stm32prog button usage. To avoid this, remove the "default-state" property from red led node. This will avoid to trigger the led driver probe() to configure the led default state during startup. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi index 5d49b09c35..8760d6c7d9 100644 --- a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi @@ -39,7 +39,6 @@ red { label = "error"; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; status = "okay"; }; }; From 1ca33cbfd96f394ebbeab73d6771bf34c7b2f502 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:02 +0200 Subject: [PATCH 37/50] ARM: dts: stm32: Update red led node for stm32mp157a-dk1-scmi-u-boot As indicated in kernel led dt-bindings, label is a deprecated property, so remove it and use red led node's name instead for u-boot,error-led property. Rename "red" led node's name to "led-red". Remove status property which is useless. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi index 8760d6c7d9..e61814fd66 100644 --- a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi @@ -14,7 +14,7 @@ config { u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "u-boot-env"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; }; @@ -36,10 +36,8 @@ }; led { - red { - label = "error"; + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - status = "okay"; }; }; }; From 13a504ef32da389944858c195f1f7846a5f23169 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:03 +0200 Subject: [PATCH 38/50] ARM: dts: stm32: Add led-blue for stm32mp157a-dk1-scmi-u-boot As indicated in kernel led dt-bindings, label is a deprecated property, so remove it and use blue led node's name instead for u-boot,boot-led property. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi index e61814fd66..a5158fec7e 100644 --- a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi @@ -13,7 +13,7 @@ }; config { - u-boot,boot-led = "heartbeat"; + u-boot,boot-led = "led-blue"; u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "u-boot-env"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; @@ -36,6 +36,10 @@ }; led { + led-blue { + /delete-property/label; + }; + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; }; From 9897951812e91175964bdc984cf0f3291dedb99a Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:04 +0200 Subject: [PATCH 39/50] ARM: dts: stm32: Add gpio-keys for stm32mp157a-dk1-u-boot Instead of using "st,fastboot-gpios" and "st,stm32prog-gpios", declare 2 gpio-keys. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index a16358266a..6bf6136c5f 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -4,6 +4,7 @@ */ #include +#include #include "stm32mp15-u-boot.dtsi" #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" @@ -18,8 +19,6 @@ u-boot,error-led = "error"; u-boot,mmc-env-partition = "fip"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; }; #if defined(CONFIG_STM32MP15X_STM32IMAGE) || defined(CONFIG_SPL) @@ -48,6 +47,22 @@ }; #endif + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + led { red { label = "error"; From 896fe85cbcda73f322f861fc8710280c75daaf60 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:05 +0200 Subject: [PATCH 40/50] ARM: dts: stm32: Don't probe red led at boot for stm32mp157a-dk1-u-boot red led and button dedicated to fastboot share the same gpio GPIOA13. Led driver is probed early so the corresponding gpio is taken and configured in output which forbid fastboot and stm32prog button usage. To avoid this, remove the "default-state" property from red led node. This will avoid to trigger the led driver probe() to configure the led default state during startup. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 6bf6136c5f..ee9b51d42b 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -67,7 +67,6 @@ red { label = "error"; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; status = "okay"; }; }; From 2ec5bd2f041621af592710f57b813ec5cc2bf076 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:06 +0200 Subject: [PATCH 41/50] ARM: dts: stm32: Update red led node for stm32mp157a-dk1-u-boot As indicated in kernel led dt-bindings, label is a deprecated property, so remove it and use red led node's name instead for u-boot,error-led property. Rename red led node's name to led-red. Remove status property which is useless. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index ee9b51d42b..92153b2a65 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -16,7 +16,7 @@ config { u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "fip"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; }; @@ -64,10 +64,8 @@ }; led { - red { - label = "error"; + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - status = "okay"; }; }; }; From dce15ce466fde15eff624c2b47566f80be17b1fb Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:07 +0200 Subject: [PATCH 42/50] ARM: dts: stm32: Update u-boot, boot-led for stm32mp157a-dk1-u-boot As indicated in kernel led dt-bindings, label is a deprecated property, so remove it and use blue led node's name instead for u-boot,boot-led property. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 92153b2a65..f97debaa0e 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -15,7 +15,7 @@ }; config { - u-boot,boot-led = "heartbeat"; + u-boot,boot-led = "led-blue"; u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "fip"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; @@ -64,6 +64,10 @@ }; led { + led-blue { + /delete-property/label; + }; + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; }; From d9f193cd3bae5f68df7218e1dcf42152b07bb4ed Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:08 +0200 Subject: [PATCH 43/50] ARM: dts: stm32: Add gpio-keys for stm32mp157c-ed1-u-boot Add 2 gpio-keys : _ button-user-1 for stm32prog mode activation. _ button-user-2 for fastboot mode activation. Remove proprietary st,fastboot-gpios and st,stm32prog-gpios. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index ef91088aa3..e6a452c9d8 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -4,6 +4,7 @@ */ #include +#include #include "stm32mp15-u-boot.dtsi" #include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" @@ -16,8 +17,6 @@ u-boot,boot-led = "heartbeat"; u-boot,error-led = "error"; u-boot,mmc-env-partition = "fip"; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; }; #if defined(CONFIG_STM32MP15X_STM32IMAGE) || defined(CONFIG_SPL) @@ -43,6 +42,22 @@ }; #endif + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + led { red { label = "error"; From bfdf5ba50a83e7f39fd83549327ba8d99f6a5bc2 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:09 +0200 Subject: [PATCH 44/50] ARM: dts: stm32: Don't probe red led at boot for stm32mp157c-ed1-u-boot red led and button dedicated to fastboot share the same gpio GPIOA13. Led driver is probed early so the corresponding gpio is taken and configured in output which forbid fastboot and stm32prog button usage. To avoid this, remove the "default-state" property from red led node. This will avoid to trigger the led driver probe() to configure the led default state during startup. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index e6a452c9d8..edcbfee0fc 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -62,7 +62,6 @@ red { label = "error"; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; status = "okay"; }; }; From e141749186efe6b7f1ca975edc86f4ff48b14242 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:10 +0200 Subject: [PATCH 45/50] ARM: dts: stm32: Update red led node for stm32mp157c-ed1-u-boot As indicated in kernel led dt-bindings, label is a deprecated property, so remove it and use led node's name instead for u-boot,error-led property. Rename red led node's name to led-red. Remove status property which is useless. Add compatible = "gpio-leds" which is not present in kernel DT. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index edcbfee0fc..09cfe9bc24 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -15,7 +15,7 @@ config { u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "fip"; }; @@ -59,10 +59,10 @@ }; led { - red { - label = "error"; + compatible = "gpio-leds"; + + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - status = "okay"; }; }; }; From e7e209a28ac95fbf349730504dc81bc42fdc97ba Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:11 +0200 Subject: [PATCH 46/50] ARM: dts: stm32: Add led-blue for stm32mp157c-ed1-u-boot The blue led is used to indicate U-Boot entering / exit indication then Linux heartbeat. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index 09cfe9bc24..d93359f967 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -14,7 +14,7 @@ }; config { - u-boot,boot-led = "heartbeat"; + u-boot,boot-led = "led-blue"; u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "fip"; }; @@ -61,6 +61,10 @@ led { compatible = "gpio-leds"; + led-blue { + gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>; + }; + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; }; From 3dfb4edf8df475ad9d0b797e2da6175f4e3e6051 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:12 +0200 Subject: [PATCH 47/50] ARM: dts: stm32: Add gpio-keys for stm32mp157c-ed1-scmi-u-boot Add 2 gpio-keys : _ button-user-1 for stm32prog mode activation. _ button-user-2 for fastboot mode activation. Remove proprietary st,fastboot-gpios and st,stm32prog-gpios. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi index 4d763bd3a2..84920f5349 100644 --- a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi @@ -3,6 +3,7 @@ * Copyright : STMicroelectronics 2022 */ +#include #include "stm32mp15-scmi-u-boot.dtsi" / { @@ -14,8 +15,22 @@ u-boot,boot-led = "heartbeat"; u-boot,error-led = "error"; u-boot,mmc-env-partition = "u-boot-env"; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; }; led { From e43a0d05bfbe0163ceb1c199fccbaed0f2186a21 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:13 +0200 Subject: [PATCH 48/50] ARM: dts: stm32: Don't probe red led at boot for stm32mp157c-ed1-scmi-u-boot red led and button dedicated to fastboot share the same gpio GPIOA13. Led driver is probed early so the corresponding gpio is taken and configured in output which forbid fastboot and stm32prog button usage. To avoid this, remove the "default-state" property from red led node. This will avoid to trigger the led driver probe() to configure the led default state during startup. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi index 84920f5349..2abd512e29 100644 --- a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi @@ -37,7 +37,6 @@ red { label = "error"; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; status = "okay"; }; }; From aaa486c81112d5b432a5ae7c1e5227f1d780a45d Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:14 +0200 Subject: [PATCH 49/50] ARM: dts: stm32: Update red led node for stm32mp157c-ed1-scmi-u-boot As indicated in kernel led dt-bindings, label is a deprecated property, so remove it and use led node's name instead for u-boot,error-led property. Rename red led node's name to led-red. Remove status property which is useless. Add compatible = "gpio-leds"; which is not present in kernel DT. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi index 2abd512e29..b38e816f88 100644 --- a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi @@ -13,7 +13,7 @@ config { u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "u-boot-env"; }; @@ -34,10 +34,10 @@ }; led { - red { - label = "error"; + compatible = "gpio-leds"; + + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - status = "okay"; }; }; }; From b0283b5e3d37daff48b45c3f98d298844603def4 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 9 Apr 2024 17:02:15 +0200 Subject: [PATCH 50/50] ARM: dts: stm32: Add led-blue for stm32mp157c-ed1-scmi-u-boot The blue led is used to indicate U-Boot entering / exit indication then Linux heartbeat. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi index b38e816f88..7c0d1bab11 100644 --- a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi @@ -12,7 +12,7 @@ }; config { - u-boot,boot-led = "heartbeat"; + u-boot,boot-led = "led-blue"; u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "u-boot-env"; }; @@ -36,6 +36,10 @@ led { compatible = "gpio-leds"; + led-blue { + gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>; + }; + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; };