1378 lines
40 KiB
Diff
1378 lines
40 KiB
Diff
From 5e602bf86a44299f1928674bec9e0348d92de2f4 Mon Sep 17 00:00:00 2001
|
||
From: Lionel VITTE <lionel.vitte@st.com>
|
||
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 <gabriel.fernandez@st.com> for STMicroelectronics.
|
||
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
|
||
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
|
||
*/
|
||
|
||
#define LOG_CATEGORY UCLASS_CLK
|
||
@@ -11,157 +11,84 @@
|
||
#include <dm.h>
|
||
#include <log.h>
|
||
#include <asm/io.h>
|
||
+#include <dm/device_compat.h>
|
||
#include <linux/clk-provider.h>
|
||
#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 <gabriel.fernandez@st.com> for STMicroelectronics.
|
||
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
|
||
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> 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 <gabriel.fernandez@st.com> for STMicroelectronics.
|
||
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
|
||
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> 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 <configs/stm32mp13_common.h>
|
||
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 <configs/stm32mp15_common.h>
|
||
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
|
||
|