From 5e602bf86a44299f1928674bec9e0348d92de2f4 Mon Sep 17 00:00:00 2001 From: Lionel VITTE Date: Mon, 3 Jul 2023 10:48:13 +0200 Subject: [PATCH] ARM v2021.10-stm32mp-r2.1-rc1 --- Makefile | 2 +- arch/arm/dts/stm32mp151.dtsi | 4 +- .../mach-stm32mp/cmd_stm32prog/stm32prog.c | 9 +- cmd/pxe_utils.c | 9 +- configs/stm32mp13_defconfig | 2 +- configs/stm32mp15_defconfig | 2 +- drivers/clk/clk-stm32-core.c | 315 ++++++------------ drivers/clk/clk-stm32-core.h | 294 +++++++++++----- drivers/clk/clk-stm32mp13.c | 119 ++++--- drivers/clk/clk.c | 65 ++++ drivers/core/device.c | 4 +- drivers/dfu/dfu_mtd.c | 32 +- include/configs/stm32mp13_st_common.h | 2 +- include/configs/stm32mp15_st_common.h | 2 +- include/dt-bindings/gpio/gpio.h | 3 + include/linux/clk-provider.h | 8 + 16 files changed, 488 insertions(+), 384 deletions(-) diff --git a/Makefile b/Makefile index 9e47e7b097..33c0b433bb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ VERSION = 2021 PATCHLEVEL = 10 SUBLEVEL = -EXTRAVERSION = -stm32mp-r2 +EXTRAVERSION = -stm32mp-r2.1 NAME = # *DOCUMENTATION* diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi index 4a7d413d16..e7e081f781 100644 --- a/arch/arm/dts/stm32mp151.dtsi +++ b/arch/arm/dts/stm32mp151.dtsi @@ -1197,8 +1197,8 @@ usbotg_hs: usb-otg@49000000 { compatible = "st,stm32mp15-hsotg", "snps,dwc2"; reg = <0x49000000 0x10000>; - clocks = <&rcc USBO_K>; - clock-names = "otg"; + clocks = <&rcc USBO_K>, <&usbphyc>; + clock-names = "otg", "utmi"; resets = <&rcc USBO_R>; reset-names = "dwc2"; interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c index f9b502c937..eef002dbe4 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c @@ -1440,8 +1440,11 @@ int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer, if (!data->otp_part) { data->otp_part = memalign(CONFIG_SYS_CACHELINE_SIZE, otp_size); - if (!data->otp_part) + if (!data->otp_part) { + stm32prog_err("OTP write issue %d", -ENOMEM); + return -ENOMEM; + } } if (!offset) @@ -1504,6 +1507,8 @@ int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer, memcpy(buffer, (void *)((u32)data->otp_part + offset), *size); end_otp_read: + if (result) + stm32prog_err("OTP read issue %d", result); log_debug("%s: result %i\n", __func__, result); return result; @@ -1557,6 +1562,8 @@ int stm32prog_otp_start(struct stm32prog_data *data) free(data->otp_part); data->otp_part = NULL; + if (result) + stm32prog_err("OTP write issue %d", result); log_debug("%s: result %i\n", __func__, result); return result; diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c index 45334fc3c7..93e1d91458 100644 --- a/cmd/pxe_utils.c +++ b/cmd/pxe_utils.c @@ -569,7 +569,7 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label) * bootm, and adjust argc appropriately. * * Scenario 3: If there is an fdtcontroladdr specified, pass it along to - * bootm, and adjust argc appropriately. + * bootm, and adjust argc appropriately, unless the image type is fitImage. * * Scenario 4: fdt blob is not available. */ @@ -663,7 +663,10 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label) if (!bootm_argv[3]) bootm_argv[3] = env_get("fdt_addr"); - if (!bootm_argv[3]) + kernel_addr = genimg_get_kernel_addr(bootm_argv[1]); + buf = map_sysmem(kernel_addr, 0); + + if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) bootm_argv[3] = env_get("fdtcontroladdr"); if (bootm_argv[3]) { @@ -672,8 +675,6 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label) bootm_argc = 4; } - kernel_addr = genimg_get_kernel_addr(bootm_argv[1]); - buf = map_sysmem(kernel_addr, 0); /* Try bootm for legacy and FIT format image */ if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID) do_bootm(cmdtp, 0, bootm_argc, bootm_argv); diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig index 2429c3f411..c551b8a0e0 100644 --- a/configs/stm32mp13_defconfig +++ b/configs/stm32mp13_defconfig @@ -8,7 +8,7 @@ CONFIG_ENV_OFFSET=0x900000 CONFIG_ENV_SECT_SIZE=0x40000 CONFIG_DEFAULT_DEVICE_TREE="stm32mp135f-dk" CONFIG_STM32MP13x=y -CONFIG_DDR_CACHEABLE_SIZE=0x10000000 +CONFIG_DDR_CACHEABLE_SIZE=0x8000000 CONFIG_CMD_STM32KEY=y CONFIG_TARGET_ST_STM32MP13x=y CONFIG_ENV_OFFSET_REDUND=0x940000 diff --git a/configs/stm32mp15_defconfig b/configs/stm32mp15_defconfig index b4b2954273..439505c3c7 100644 --- a/configs/stm32mp15_defconfig +++ b/configs/stm32mp15_defconfig @@ -7,7 +7,7 @@ CONFIG_SYS_MEMTEST_END=0xc4000000 CONFIG_ENV_OFFSET=0x900000 CONFIG_ENV_SECT_SIZE=0x40000 CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1" -CONFIG_DDR_CACHEABLE_SIZE=0x10000000 +CONFIG_DDR_CACHEABLE_SIZE=0x8000000 CONFIG_CMD_STM32KEY=y CONFIG_TARGET_ST_STM32MP15x=y CONFIG_ENV_OFFSET_REDUND=0x940000 diff --git a/drivers/clk/clk-stm32-core.c b/drivers/clk/clk-stm32-core.c index 22671a0abc..37e996e78f 100644 --- a/drivers/clk/clk-stm32-core.c +++ b/drivers/clk/clk-stm32-core.c @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - * Author: Gabriel Fernandez for STMicroelectronics. + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. */ #define LOG_CATEGORY UCLASS_CLK @@ -11,157 +11,84 @@ #include #include #include +#include #include #include "clk-stm32-core.h" -int stm32_rcc_init(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base) +int stm32_rcc_init(struct udevice *dev, + const struct stm32_clock_match_data *data) { int i; + u8 *cpt; + struct stm32mp_rcc_priv *priv = dev_get_priv(dev); + fdt_addr_t base = dev_read_addr(dev->parent); + const struct clk_stm32_clock_data *clock_data = data->clock_data; - for (i = 0; i < data->num_clocks; i++) { - const struct clock_config *cfg = &data->tab_clocks[i]; - struct clk *clk = ERR_PTR(-ENOENT); - - if (data->check_security) { - if ((*data->check_security)(base, cfg)) - continue; - } - - if (cfg->func) - clk = (*cfg->func)(NULL, data, base, NULL, cfg); - - if (IS_ERR(clk)) { - log_err("%s: failed to register clock %s\n", __func__, - cfg->name); - - return PTR_ERR(clk); - } - - clk->id = cfg->id; - } - - return 0; -} - -static const struct clk_ops *clk_dev_ops(struct udevice *dev) -{ - return (const struct clk_ops *)dev->driver->ops; -} - -static int stm32_clk_enable(struct clk *clk) -{ - const struct clk_ops *ops; - struct clk *clkp = NULL; - - if (!clk->id || clk_get_by_id(clk->id, &clkp)) - return -ENOENT; - - ops = clk_dev_ops(clkp->dev); - if (!ops->enable) - return 0; - - return ops->enable(clkp); -} - -static int stm32_clk_disable(struct clk *clk) -{ - const struct clk_ops *ops; - struct clk *clkp = NULL; + if (base == FDT_ADDR_T_NONE) + return -EINVAL; - if (!clk->id || clk_get_by_id(clk->id, &clkp)) - return -ENOENT; + priv->base = (void __iomem *)base; - ops = clk_dev_ops(clkp->dev); - if (!ops->disable) - return 0; + /* allocate the counter of user for internal RCC gates, common for several user */ + cpt = kzalloc(clock_data->num_gates, GFP_KERNEL); + if (!cpt) + return -ENOMEM; - return ops->disable(clkp); -} - -static ulong stm32_clk_get_rate(struct clk *clk) -{ - const struct clk_ops *ops; - struct clk *clkp = NULL; - - if (!clk->id || clk_get_by_id(clk->id, &clkp)) - return -ENOENT; + priv->gate_cpt = cpt; - ops = clk_dev_ops(clkp->dev); - if (!ops->get_rate) - return -ENOSYS; + priv->data = clock_data; - return ops->get_rate(clkp); -} - -ulong stm32_clk_set_rate(struct clk *clk, unsigned long clk_rate) -{ - const struct clk_ops *ops; - struct clk *clkp = NULL; - - if (!clk->id || clk_get_by_id(clk->id, &clkp)) - return -ENOENT; - - ops = clk_dev_ops(clkp->dev); - if (!ops->set_rate) - return -ENOSYS; - - return ops->set_rate(clkp, clk_rate); -} - -int clk_stm32_get_by_name(const char *name, struct clk **clkp) -{ - struct udevice *dev; - struct uclass *uc; - int ret; - - ret = uclass_get(UCLASS_CLK, &uc); - if (ret) - return ret; + for (i = 0; i < data->num_clocks; i++) { + const struct clock_config *cfg = &data->tab_clocks[i]; + struct clk *clk = ERR_PTR(-ENOENT); - uclass_foreach_dev(dev, uc) { - if (!strcmp(name, dev->name)) { - struct clk *clk = dev_get_clk_ptr(dev); + if (data->check_security && data->check_security(priv->base, cfg)) + continue; - if (clk) { - *clkp = clk; - return 0; - } - break; + if (cfg->setup) { + clk = cfg->setup(dev, cfg); + clk->id = cfg->id; + } else { + dev_err(dev, "failed to register clock %s\n", cfg->name); + return -ENOENT; } } - return -ENOENT; + return 0; } ulong clk_stm32_get_rate_by_name(const char *name) { - struct clk *clk; + struct udevice *dev; + + if (!uclass_get_device_by_name(UCLASS_CLK, name, &dev)) { + struct clk *clk = dev_get_clk_ptr(dev); - if (!clk_stm32_get_by_name(name, &clk)) return clk_get_rate(clk); + } return 0; } const struct clk_ops stm32_clk_ops = { - .enable = stm32_clk_enable, - .disable = stm32_clk_disable, - .get_rate = stm32_clk_get_rate, - .set_rate = stm32_clk_set_rate, + .enable = ccf_clk_enable, + .disable = ccf_clk_disable, + .get_rate = ccf_clk_get_rate, + .set_rate = ccf_clk_set_rate, }; #define RCC_MP_ENCLRR_OFFSET 4 -static void clk_stm32_endisable_gate(const struct stm32_gate_cfg *gate_cfg, - void __iomem *base, u8 *cpt, int enable) +static void clk_stm32_gate_set_state(void __iomem *base, + const struct clk_stm32_clock_data *data, + u8 *cpt, u16 gate_id, int enable) { + const struct stm32_gate_cfg *gate_cfg = &data->gates[gate_id]; void __iomem *addr = base + gate_cfg->reg_off; u8 set_clr = gate_cfg->set_clr ? RCC_MP_ENCLRR_OFFSET : 0; if (enable) { - if (*cpt++ > 0) + if (cpt[gate_id]++ > 0) return; if (set_clr) @@ -169,7 +96,7 @@ static void clk_stm32_endisable_gate(const struct stm32_gate_cfg *gate_cfg, else writel(readl(addr) | BIT(gate_cfg->bit_idx), addr); } else { - if (--*cpt > 0) + if (--cpt[gate_id] > 0) return; if (set_clr) @@ -179,24 +106,24 @@ static void clk_stm32_endisable_gate(const struct stm32_gate_cfg *gate_cfg, } } -static void clk_stm32_gate_endisable(struct clk *clk, int enable) +static int clk_stm32_gate_enable(struct clk *clk) { struct clk_stm32_gate *stm32_gate = to_clk_stm32_gate(clk); + struct stm32mp_rcc_priv *priv = stm32_gate->priv; - clk_stm32_endisable_gate(stm32_gate->gate, stm32_gate->base, - &stm32_gate->cpt, enable); -} - -static int clk_stm32_gate_enable(struct clk *clk) -{ - clk_stm32_gate_endisable(clk, 1); + clk_stm32_gate_set_state(priv->base, priv->data, priv->gate_cpt, + stm32_gate->gate_id, 1); return 0; } static int clk_stm32_gate_disable(struct clk *clk) { - clk_stm32_gate_endisable(clk, 0); + struct clk_stm32_gate *stm32_gate = to_clk_stm32_gate(clk); + struct stm32mp_rcc_priv *priv = stm32_gate->priv; + + clk_stm32_gate_set_state(priv->base, priv->data, priv->gate_cpt, + stm32_gate->gate_id, 0); return 0; } @@ -215,14 +142,11 @@ U_BOOT_DRIVER(clk_stm32_gate) = { .ops = &clk_stm32_gate_ops, }; -struct clk *clk_stm32_gate_register(struct device *dev, - const char *name, - const char *parent_name, - unsigned long flags, - void __iomem *base, - const struct stm32_gate_cfg *gate_cfg, - spinlock_t *lock) +struct clk *clk_stm32_gate_register(struct udevice *dev, + const struct clock_config *cfg) { + struct stm32mp_rcc_priv *priv = dev_get_priv(dev); + struct stm32_clk_gate_cfg *clk_cfg = cfg->clock_cfg; struct clk_stm32_gate *stm32_gate; struct clk *clk; int ret; @@ -231,13 +155,14 @@ struct clk *clk_stm32_gate_register(struct device *dev, if (!stm32_gate) return ERR_PTR(-ENOMEM); - stm32_gate->base = base; - stm32_gate->gate = gate_cfg; + stm32_gate->priv = priv; + stm32_gate->gate_id = clk_cfg->gate_id; clk = &stm32_gate->clk; - clk->flags = flags; + clk->flags = cfg->flags; - ret = clk_register(clk, UBOOT_DM_CLK_STM32_GATE, name, parent_name); + ret = clk_register(clk, UBOOT_DM_CLK_STM32_GATE, + cfg->name, cfg->parent_name); if (ret) { kfree(stm32_gate); return ERR_PTR(ret); @@ -246,15 +171,13 @@ struct clk *clk_stm32_gate_register(struct device *dev, return clk; } -struct clk *clk_stm32_register_composite(const char *name, - const char * const *parent_names, - int num_parents, - unsigned long flags, - void __iomem *base, - const struct stm32_mux_cfg *mcfg, - const struct stm32_div_cfg *dcfg, - const struct stm32_gate_cfg *gcfg) +struct clk * +clk_stm32_register_composite(struct udevice *dev, + const struct clock_config *cfg) { + struct stm32_clk_composite_cfg *composite = cfg->clock_cfg; + const char *const *parent_names; + int num_parents; struct clk *clk = ERR_PTR(-ENOMEM); struct clk_mux *mux = NULL; struct clk_stm32_gate *gate = NULL; @@ -265,57 +188,73 @@ struct clk *clk_stm32_register_composite(const char *name, const struct clk_ops *gate_ops = NULL; struct clk *div_clk = NULL; const struct clk_ops *div_ops = NULL; + struct stm32mp_rcc_priv *priv = dev_get_priv(dev); + const struct clk_stm32_clock_data *data = priv->data; + + if (composite->mux_id != NO_STM32_MUX) { + const struct stm32_mux_cfg *mux_cfg; - if (mcfg) { mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) goto fail; - mux->reg = base + mcfg->reg_off; - mux->shift = mcfg->shift; - mux->mask = BIT(mcfg->width) - 1; - mux->num_parents = mcfg->num_parents; + mux_cfg = &data->muxes[composite->mux_id]; + + mux->reg = priv->base + mux_cfg->reg_off; + mux->shift = mux_cfg->shift; + mux->mask = BIT(mux_cfg->width) - 1; + mux->num_parents = mux_cfg->num_parents; mux->flags = 0; - mux->parent_names = mcfg->parent_names; + mux->parent_names = mux_cfg->parent_names; mux_clk = &mux->clk; mux_ops = &clk_mux_ops; + + parent_names = mux_cfg->parent_names; + num_parents = mux_cfg->num_parents; + } else { + parent_names = &cfg->parent_name; + num_parents = 1; } - if (dcfg) { + if (composite->div_id != NO_STM32_DIV) { + const struct stm32_div_cfg *div_cfg; + div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) goto fail; - div->reg = base + dcfg->reg_off; - div->shift = dcfg->shift; - div->width = dcfg->width; - div->width = dcfg->width; - div->flags = dcfg->div_flags; - div->table = dcfg->table; + div_cfg = &data->dividers[composite->div_id]; + + div->reg = priv->base + div_cfg->reg_off; + div->shift = div_cfg->shift; + div->width = div_cfg->width; + div->width = div_cfg->width; + div->flags = div_cfg->div_flags; + div->table = div_cfg->table; div_clk = &div->clk; div_ops = &clk_divider_ops; } - if (gcfg) { + if (composite->gate_id != NO_STM32_GATE) { gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) goto fail; - gate->base = base; - gate->gate = gcfg; + gate->priv = priv; + gate->gate_id = composite->gate_id; gate_clk = &gate->clk; gate_ops = &clk_stm32_gate_ops; } - clk = clk_register_composite(NULL, name, + clk = clk_register_composite(NULL, cfg->name, parent_names, num_parents, mux_clk, mux_ops, div_clk, div_ops, gate_clk, gate_ops, - flags); + cfg->flags); if (IS_ERR(clk)) goto fail; @@ -327,49 +266,3 @@ fail: kfree(mux); return ERR_CAST(clk); } - -struct clk *_clk_stm32_gate_register(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base, - spinlock_t *lock, - const struct clock_config *cfg) -{ - struct stm32_clk_gate_cfg *clk_cfg = cfg->clock_cfg; - const struct stm32_gate_cfg *gate_cfg = &data->gates[clk_cfg->gate_id]; - - return clk_stm32_gate_register(dev, cfg->name, cfg->parent_name, - cfg->flags, base, gate_cfg, lock); -} - -struct clk * -_clk_stm32_register_composite(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base, spinlock_t *lock, - const struct clock_config *cfg) -{ - struct stm32_clk_composite_cfg *composite = cfg->clock_cfg; - const struct stm32_mux_cfg *mux_cfg = NULL; - const struct stm32_gate_cfg *gate_cfg = NULL; - const struct stm32_div_cfg *div_cfg = NULL; - const char *const *parent_names; - int num_parents; - - if (composite->mux_id != NO_STM32_MUX) { - mux_cfg = &data->muxes[composite->mux_id]; - parent_names = mux_cfg->parent_names; - num_parents = mux_cfg->num_parents; - } else { - parent_names = &cfg->parent_name; - num_parents = 1; - } - - if (composite->gate_id != NO_STM32_GATE) - gate_cfg = &data->gates[composite->gate_id]; - - if (composite->div_id != NO_STM32_DIV) - div_cfg = &data->dividers[composite->div_id]; - - return clk_stm32_register_composite(cfg->name, parent_names, - num_parents, cfg->flags, base, - mux_cfg, div_cfg, gate_cfg); -} diff --git a/drivers/clk/clk-stm32-core.h b/drivers/clk/clk-stm32-core.h index 79ca27fbaa..53c2b467ab 100644 --- a/drivers/clk/clk-stm32-core.h +++ b/drivers/clk/clk-stm32-core.h @@ -1,42 +1,93 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ /* - * Copyright (C) STMicroelectronics 2020 - All Rights Reserved - * Author: Gabriel Fernandez for STMicroelectronics. + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. */ struct stm32_clock_match_data; +/** + * struct stm32_mux_cfg - multiplexer configuration + * + * @parent_names: array of string names for all possible parents + * @num_parents: number of possible parents + * @reg_off: register controlling multiplexer + * @shift: shift to multiplexer bit field + * @width: width of the multiplexer bit field + * @mux_flags: hardware-specific flags + * @table: array of register values corresponding to the parent + * index + */ struct stm32_mux_cfg { const char * const *parent_names; - u8 num_parents; - u32 reg_off; - u8 shift; - u8 width; - u8 mux_flags; - u32 *table; + u8 num_parents; + u32 reg_off; + u8 shift; + u8 width; + u8 mux_flags; + u32 *table; }; +/** + * struct stm32_gate_cfg - gating configuration + * + * @reg_off: register controlling gate + * @bit_idx: single bit controlling gate + * @gate_flags: hardware-specific flags + * @set_clr: 0 : normal gate, 1 : has a register to clear the gate + */ struct stm32_gate_cfg { - u32 reg_off; - u8 bit_idx; - u8 gate_flags; - u8 set_clr; + u32 reg_off; + u8 bit_idx; + u8 gate_flags; + u8 set_clr; }; +/** + * struct stm32_div_cfg - divider configuration + * + * @reg_off: register containing the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @table: array of value/divider pairs, last entry should have div = 0 + */ struct stm32_div_cfg { - u32 reg_off; - u8 shift; - u8 width; - u8 div_flags; + u32 reg_off; + u8 shift; + u8 width; + u8 div_flags; const struct clk_div_table *table; }; +#define NO_STM32_MUX -1 +#define NO_STM32_DIV -1 +#define NO_STM32_GATE -1 + +/** + * struct stm32_composite_cfg - composite configuration + * + * @mux: index of a multiplexer + * @gate: index of a gate + * @div: index of a divider + */ struct stm32_composite_cfg { int mux; int gate; int div; }; +/** + * struct clock_config - clock configuration + * + * @id: binding id of the clock + * @name: clock name + * @parent_name: name of the clock parent + * @flags: framework-specific flags + * @sec_id: secure id (use to known if the clock is secured or not) + * @clock_cfg: specific clock data configuration + * @setup: specific call back to reister the clock (will use + * clock_cfg data as input) + */ struct clock_config { unsigned long id; const char *name; @@ -45,71 +96,142 @@ struct clock_config { int sec_id; void *clock_cfg; - struct clk *(*func)(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base, - spinlock_t *lock, - const struct clock_config *cfg); + struct clk *(*setup)(struct udevice *dev, + const struct clock_config *cfg); }; -struct stm32_clock_match_data { - unsigned int num_clocks; - const struct clock_config *tab_clocks; - unsigned int maxbinding; - const struct stm32_gate_cfg *gates; - const struct stm32_mux_cfg *muxes; - const struct stm32_div_cfg *dividers; +/** + * struct clk_stm32_clock_data - clock data + * + * @num_gates: number of defined gates + * @gates: array of gate configuration + * @muxes: array of multiplexer configuration + * @dividers: array of divider configuration + */ +struct clk_stm32_clock_data { + unsigned int num_gates; + const struct stm32_gate_cfg *gates; + const struct stm32_mux_cfg *muxes; + const struct stm32_div_cfg *dividers; +}; +/** + * struct stm32_clock_match_data - clock match data + * + * @num_gates: number of clocks + * @tab_clocks: array of clock configuration + * @clock_data: definition of all gates / dividers / multiplexers + * @check_security: call back to check if clock is secured or not + */ +struct stm32_clock_match_data { + unsigned int num_clocks; + const struct clock_config *tab_clocks; + const struct clk_stm32_clock_data *clock_data; int (*check_security)(void __iomem *base, const struct clock_config *cfg); }; -int stm32_rcc_init(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base); +/** + * struct stm32mp_rcc_priv - private struct for stm32mp clocks + * + * @base: base register of RCC driver + * @gate_cpt: array of refcounting for gate with more than one + * clocks as input. See explanation of Peripheral clock enabling + * below. + * @data: data for gate / divider / multiplexer configuration + */ +struct stm32mp_rcc_priv { + void __iomem *base; + u8 *gate_cpt; + const struct clk_stm32_clock_data *data; +}; -#define NO_ID 0xFFFF0000 +int stm32_rcc_init(struct udevice *dev, + const struct stm32_clock_match_data *data); -#define NO_STM32_MUX -1 -#define NO_STM32_DIV -1 -#define NO_STM32_GATE -1 +/** + * STM32 Gate + * + * PCE (Peripheral Clock Enabling) Peripheral + * + * ------------------------------ ---------- + * | | | | + * | | | PERx | + * bus_ck | ----- | | | + * ------------->|------------------| | | ckg_bus_perx | | + * | | AND |-----|---------------->| | + * | -----------| | | | | + * | | ----- | | | + * | | | | | + * | ----- | | | + * Perx_EN |-----|---| GCL | Gating | | | + * | ----- Control | | | + * | | Logic | | | + * | | | | | + * | | ----- | | | + * | -----------| | | ckg_ker_perx | | + * perx_ker_ck | | AND |-----|---------------->| | + * ------------->|------------------| | | | | + * | ----- | | | + * | | | | + * | | | | + * ------------------------------ ---------- + + * Each peripheral requires a bus interface clock, named ckg_bus_perx + * (for peripheral ‘x’). + * Some peripherals (SAI, UART...) need also a dedicated clock for their + * communication interface, this clock is generally asynchronous with respect to + * the bus interface clock, and is named kernel clock (ckg_ker_perx). + + * Both clocks can be gated by one Perx_EN enable bit. + * Then we have to manage a refcounting on gate level to avoid gate if one + * the bus or the Kernel was enable. + * + * Example: + * 1) enable the bus clock + * --> bus_clk ref_counting = 1, gate_ref_count = 1 + * 2) enable the kernel clock + * --> perx_ker_ck ref_counting = 1, gate_ref_count = 2 + * 3) disable kernel clock + *  ---> perx_ker_ck ref_counting = 0, gate_ref_count = 1 + *  ==> then i will not gate because gate_ref_count > 0 + * 4) disable bus clock + * --> bus_clk ref_counting = 0, gate_ref_count = 0 + * ==> then i can gate (write in the register) because + * gate_ref_count = 0 + */ struct clk_stm32_gate { struct clk clk; - void __iomem *base; - const struct stm32_gate_cfg *gate; - u8 cpt; + struct stm32mp_rcc_priv *priv; + int gate_id; }; #define to_clk_stm32_gate(_clk) container_of(_clk, struct clk_stm32_gate, clk) struct clk * -_clk_stm32_gate_register(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base, spinlock_t *lock, - const struct clock_config *cfg); +clk_stm32_gate_register(struct udevice *dev, + const struct clock_config *cfg); struct clk * -_clk_stm32_register_composite(struct device *dev, - const struct stm32_clock_match_data *data, - void __iomem *base, spinlock_t *lock, - const struct clock_config *cfg); +clk_stm32_register_composite(struct udevice *dev, + const struct clock_config *cfg); struct stm32_clk_gate_cfg { int gate_id; }; -#define STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id)\ -{\ - .id = _id,\ - .sec_id = _sec_id,\ - .name = _name,\ - .parent_name = _parent,\ - .flags = _flags,\ - .clock_cfg = &(struct stm32_clk_gate_cfg) {\ - .gate_id = _gate_id,\ - },\ - .func = _clk_stm32_gate_register,\ +#define STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id) \ +{ \ + .id = _id, \ + .sec_id = _sec_id, \ + .name = _name, \ + .parent_name = _parent, \ + .flags = _flags, \ + .clock_cfg = &(struct stm32_clk_gate_cfg) { \ + .gate_id = _gate_id, \ + }, \ + .setup = clk_stm32_gate_register, \ } struct stm32_clk_composite_cfg { @@ -118,39 +240,37 @@ struct stm32_clk_composite_cfg { int div_id; }; -#define STM32_COMPOSITE(_id, _name, _flags, _sec_id,\ - _gate_id, _mux_id, _div_id)\ -{\ - .id = _id,\ - .name = _name,\ - .sec_id = _sec_id,\ - .flags = _flags,\ - .clock_cfg = &(struct stm32_clk_composite_cfg) {\ - .gate_id = _gate_id,\ - .mux_id = _mux_id,\ - .div_id = _div_id,\ - },\ - .func = _clk_stm32_register_composite,\ +#define STM32_COMPOSITE(_id, _name, _flags, _sec_id, \ + _gate_id, _mux_id, _div_id) \ +{ \ + .id = _id, \ + .name = _name, \ + .sec_id = _sec_id, \ + .flags = _flags, \ + .clock_cfg = &(struct stm32_clk_composite_cfg) { \ + .gate_id = _gate_id, \ + .mux_id = _mux_id, \ + .div_id = _div_id, \ + }, \ + .setup = clk_stm32_register_composite, \ } -#define STM32_COMPOSITE_NOMUX(_id, _name, _parent, _flags, _sec_id,\ - _gate_id, _div_id)\ -{\ - .id = _id,\ - .name = _name,\ - .parent_name = _parent,\ - .sec_id = _sec_id,\ - .flags = _flags,\ - .clock_cfg = &(struct stm32_clk_composite_cfg) {\ - .gate_id = _gate_id,\ - .mux_id = NO_STM32_MUX,\ - .div_id = _div_id,\ - },\ - .func = _clk_stm32_register_composite,\ +#define STM32_COMPOSITE_NOMUX(_id, _name, _parent, _flags, _sec_id, \ + _gate_id, _div_id) \ +{ \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .sec_id = _sec_id, \ + .flags = _flags, \ + .clock_cfg = &(struct stm32_clk_composite_cfg) { \ + .gate_id = _gate_id, \ + .mux_id = NO_STM32_MUX, \ + .div_id = _div_id, \ + }, \ + .setup = clk_stm32_register_composite, \ } extern const struct clk_ops stm32_clk_ops; ulong clk_stm32_get_rate_by_name(const char *name); -int clk_stm32_get_by_name(const char *name, struct clk **clkp); - diff --git a/drivers/clk/clk-stm32mp13.c b/drivers/clk/clk-stm32mp13.c index bd82200e55..5174ae53a1 100644 --- a/drivers/clk/clk-stm32mp13.c +++ b/drivers/clk/clk-stm32mp13.c @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - * Author: Gabriel Fernandez for STMicroelectronics. + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. */ #define LOG_CATEGORY UCLASS_CLK @@ -19,10 +19,6 @@ DECLARE_GLOBAL_DATA_PTR; -struct stm32mp1_clk_priv { - fdt_addr_t base; -}; - static const char * const adc12_src[] = { "pll4_r", "ck_per", "pll3_q" }; @@ -176,13 +172,14 @@ enum enum_mux_cfg { MUX_MCO2 }; -#define MUX_CFG(id, src, _offset, _shift, _witdh)[id] = {\ - .num_parents = ARRAY_SIZE(src),\ - .parent_names = src,\ - .reg_off = (_offset),\ - .shift = (_shift),\ - .width = (_witdh),\ -} +#define MUX_CFG(id, src, _offset, _shift, _witdh) \ + [id] = { \ + .num_parents = ARRAY_SIZE(src), \ + .parent_names = (src), \ + .reg_off = (_offset), \ + .shift = (_shift), \ + .width = (_witdh), \ + } static const struct stm32_mux_cfg stm32mp13_muxes[] = { MUX_CFG(MUX_I2C12, i2c12_src, RCC_I2C12CKSELR, 0, 3), @@ -344,11 +341,12 @@ enum enum_gate_cfg { GATE_MDMA }; -#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\ - .reg_off = (_offset),\ - .bit_idx = (_bit_idx),\ - .set_clr = (_offset_clr),\ -} +#define GATE_CFG(id, _offset, _bit_idx, _offset_clr) \ + [id] = { \ + .reg_off = (_offset), \ + .bit_idx = (_bit_idx), \ + .set_clr = (_offset_clr), \ + } static const struct stm32_gate_cfg stm32mp13_gates[] = { GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), @@ -483,13 +481,14 @@ enum enum_div_cfg { LAST_DIV }; -#define DIV_CFG(id, _offset, _shift, _width, _flags, _table)[id] = {\ - .reg_off = _offset,\ - .shift = _shift,\ - .width = _width,\ - .div_flags = _flags,\ - .table = _table,\ -} +#define DIV_CFG(id, _offset, _shift, _width, _flags, _table) \ + [id] = { \ + .reg_off = _offset, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = _flags, \ + .table = _table, \ + } static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = { DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL), @@ -562,10 +561,11 @@ enum securit_clk { SECF_MCO2 }; -#define SECF(_sec_id, _offset, _bit_idx)[_sec_id] = {\ - .offset = _offset,\ - .bit_idx = _bit_idx,\ -} +#define SECF(_sec_id, _offset, _bit_idx) \ + [_sec_id] = { \ + .offset = _offset, \ + .bit_idx = _bit_idx, \ + } static const struct clk_stm32_securiy stm32mp13_security[] = { SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF), @@ -624,15 +624,15 @@ static const struct clk_stm32_securiy stm32mp13_security[] = { SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SECF), }; -#define PCLK(_id, _name, _parent, _flags, _gate_id, _sec_id)\ +#define PCLK(_id, _name, _parent, _flags, _gate_id, _sec_id) \ STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id) -#define TIMER(_id, _name, _parent, _flags, _gate_id, _sec_id)\ - STM32_GATE(_id, _name, _parent, ((_flags) | CLK_SET_RATE_PARENT),\ +#define TIMER(_id, _name, _parent, _flags, _gate_id, _sec_id) \ + STM32_GATE(_id, _name, _parent, ((_flags) | CLK_SET_RATE_PARENT), \ _gate_id, _sec_id) -#define KCLK(_id, _name, _flags, _gate_id, _mux_id, _sec_id)\ - STM32_COMPOSITE(_id, _name, _flags, _sec_id,\ +#define KCLK(_id, _name, _flags, _gate_id, _mux_id, _sec_id) \ + STM32_COMPOSITE(_id, _name, _flags, _sec_id, \ _gate_id, _mux_id, NO_STM32_DIV) static const struct clock_config stm32mp13_clock_cfg[] = { @@ -789,48 +789,45 @@ static int stm32mp13_check_security(void __iomem *base, static const struct stm32_clock_match_data stm32mp13_data = { .tab_clocks = stm32mp13_clock_cfg, .num_clocks = ARRAY_SIZE(stm32mp13_clock_cfg), - .gates = stm32mp13_gates, - .muxes = stm32mp13_muxes, - .dividers = stm32mp13_dividers, - .check_security = &stm32mp13_check_security + .clock_data = &(const struct clk_stm32_clock_data) { + .num_gates = ARRAY_SIZE(stm32mp13_gates), + .gates = stm32mp13_gates, + .muxes = stm32mp13_muxes, + .dividers = stm32mp13_dividers, + }, + .check_security = stm32mp13_check_security, }; static int stm32mp1_clk_probe(struct udevice *dev) { - fdt_addr_t base = dev_read_addr(dev->parent); struct udevice *scmi; - - if (base == FDT_ADDR_T_NONE) - return -EINVAL; + int err; /* force SCMI probe to register all SCMI clocks */ uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi); - stm32_rcc_init(NULL, &stm32mp13_data, (void __iomem *)base); + err = stm32_rcc_init(dev, &stm32mp13_data); + if (err) + return err; -#if defined(DEBUG) - /* display debug information for probe after relocation */ - if (gd->flags & GD_FLG_RELOC) - stm32mp1_clk_dump(priv); -#endif gd->cpu_clk = clk_stm32_get_rate_by_name("ck_mpu"); gd->bus_clk = clk_stm32_get_rate_by_name("ck_axi"); /* DDRPHYC father */ gd->mem_clk = clk_stm32_get_rate_by_name("pll2_r"); -#if defined(CONFIG_DISPLAY_CPUINFO) - if (gd->flags & GD_FLG_RELOC) { - char buf[32]; - - log_info("Clocks:\n"); - log_info("- MPU : %s MHz\n", strmhz(buf, gd->cpu_clk)); - log_info("- AXI : %s MHz\n", strmhz(buf, gd->bus_clk)); - log_info("- PER : %s MHz\n", - strmhz(buf, clk_stm32_get_rate_by_name("ck_per"))); - log_info("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk)); + if (IS_ENABLED(CONFIG_DISPLAY_CPUINFO)) { + if (gd->flags & GD_FLG_RELOC) { + char buf[32]; + + log_info("Clocks:\n"); + log_info("- MPU : %s MHz\n", strmhz(buf, gd->cpu_clk)); + log_info("- AXI : %s MHz\n", strmhz(buf, gd->bus_clk)); + log_info("- PER : %s MHz\n", + strmhz(buf, clk_stm32_get_rate_by_name("ck_per"))); + log_info("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk)); + } } -#endif /* CONFIG_DISPLAY_CPUINFO */ return 0; } @@ -839,6 +836,6 @@ U_BOOT_DRIVER(stm32mp1_clock) = { .name = "stm32mp13_clk", .id = UCLASS_CLK, .ops = &stm32_clk_ops, - .priv_auto = sizeof(struct stm32mp1_clk_priv), + .priv_auto = sizeof(struct stm32mp_rcc_priv), .probe = stm32mp1_clk_probe, }; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index eff0fa134f..a5a3461b66 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -74,3 +74,68 @@ bool clk_dev_binded(struct clk *clk) return false; } + +/* Helper functions for clock ops */ + +ulong ccf_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return clk_get_rate(c); +} + +ulong ccf_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return clk_set_rate(c, rate); +} + +int ccf_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *p; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + + err = clk_get_by_id(parent->id, &p); + if (err) + return err; + + return clk_set_parent(c, p); +} + +static int ccf_clk_endisable(struct clk *clk, bool enable) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return enable ? clk_enable(c) : clk_disable(c); +} + +int ccf_clk_enable(struct clk *clk) +{ + return ccf_clk_endisable(clk, true); +} + +int ccf_clk_disable(struct clk *clk) +{ + return ccf_clk_endisable(clk, false); +} + +const struct clk_ops ccf_clk_ops = { + .set_rate = ccf_clk_set_rate, + .get_rate = ccf_clk_get_rate, + .set_parent = ccf_clk_set_parent, + .enable = ccf_clk_enable, + .disable = ccf_clk_disable, +}; diff --git a/drivers/core/device.c b/drivers/core/device.c index 6f84762ebd..9e470e3076 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -1082,9 +1082,7 @@ bool device_is_compatible(const struct udevice *dev, const char *compat) bool of_machine_is_compatible(const char *compat) { - const void *fdt = gd->fdt_blob; - - return !fdt_node_check_compatible(fdt, 0, compat); + return ofnode_device_is_compatible(ofnode_root(), compat); } int dev_disable_by_path(const char *path) diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c index cce9ce0845..2a160181a1 100644 --- a/drivers/dfu/dfu_mtd.c +++ b/drivers/dfu/dfu_mtd.c @@ -85,27 +85,39 @@ static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu, while (remaining) { if (erase_op.addr + remaining > lim) { - printf("Limit reached 0x%llx while erasing at offset 0x%llx\n", - lim, off); + printf("Limit reached 0x%llx while erasing at offset 0x%llx, remaining 0x%llx\n", + lim, erase_op.addr, remaining); return -EIO; } + /* Skip the block if it is bad, don't erase it again */ + if (mtd_block_isbad(mtd, erase_op.addr)) { + printf("Skipping bad block at 0x%08llx\n", + erase_op.addr); + erase_op.addr += mtd->erasesize; + continue; + } + ret = mtd_erase(mtd, &erase_op); if (ret) { - /* Abort if its not a bad block error */ - if (ret != -EIO) { - printf("Failure while erasing at offset 0x%llx\n", - erase_op.fail_addr); - return 0; + /* If this is not -EIO, we have no idea what to do. */ + if (ret == -EIO) { + printf("Marking bad block at 0x%08llx (%d)\n", + erase_op.fail_addr, ret); + ret = mtd_block_markbad(mtd, erase_op.addr); + } + /* Abort if it is not -EIO or can't mark bad */ + if (ret) { + printf("Failure while erasing at offset 0x%llx (%d)\n", + erase_op.fail_addr, ret); + return ret; } - printf("Skipping bad block at 0x%08llx\n", - erase_op.addr); } else { remaining -= mtd->erasesize; } - /* Continue erase behind bad block */ + /* Continue erase behind the current block */ erase_op.addr += mtd->erasesize; } } diff --git a/include/configs/stm32mp13_st_common.h b/include/configs/stm32mp13_st_common.h index 41681537a2..82a428fe63 100644 --- a/include/configs/stm32mp13_st_common.h +++ b/include/configs/stm32mp13_st_common.h @@ -9,7 +9,7 @@ #define __CONFIG_STM32MP13_ST_COMMON_H__ #define STM32MP_BOARD_EXTRA_ENV \ - "usb_pgood_delay=1000\0" \ + "usb_pgood_delay=2000\0" \ "console=ttySTM0\0" #include diff --git a/include/configs/stm32mp15_st_common.h b/include/configs/stm32mp15_st_common.h index c395f7f986..9865ef5843 100644 --- a/include/configs/stm32mp15_st_common.h +++ b/include/configs/stm32mp15_st_common.h @@ -9,7 +9,7 @@ #define __CONFIG_STM32MP15_ST_COMMON_H__ #define STM32MP_BOARD_EXTRA_ENV \ - "usb_pgood_delay=1000\0" \ + "usb_pgood_delay=2000\0" \ "console=ttySTM0\0" #include diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index c029467e82..5566e58196 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -39,4 +39,7 @@ /* Bit 5 express pull down */ #define GPIO_PULL_DOWN 32 +/* Bit 6 express pull disable */ +#define GPIO_PULL_DISABLE 64 + #endif diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 9d296f240a..26d91d564f 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -254,4 +254,12 @@ const char *clk_hw_get_name(const struct clk *hw); ulong clk_generic_get_rate(struct clk *clk); struct clk *dev_get_clk_ptr(struct udevice *dev); + +ulong ccf_clk_get_rate(struct clk *clk); +ulong ccf_clk_set_rate(struct clk *clk, unsigned long rate); +int ccf_clk_set_parent(struct clk *clk, struct clk *parent); +int ccf_clk_enable(struct clk *clk); +int ccf_clk_disable(struct clk *clk); +extern const struct clk_ops ccf_clk_ops; + #endif /* __LINUX_CLK_PROVIDER_H */ -- 2.25.1