summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/dwc_ahsata_priv.h4
-rw-r--r--drivers/button/button-qcom-pmic.c15
-rw-r--r--drivers/clk/Kconfig11
-rw-r--r--drivers/clk/at91/Makefile1
-rw-r--r--drivers/clk/at91/clk-main.c2
-rw-r--r--drivers/clk/at91/clk-sam9x60-pll.c55
-rw-r--r--drivers/clk/at91/pmc.h2
-rw-r--r--drivers/clk/at91/sam9x60.c7
-rw-r--r--drivers/clk/at91/sam9x7.c1085
-rw-r--r--drivers/clk/at91/sama7g5.c6
-rw-r--r--drivers/clk/clk-uclass.c9
-rw-r--r--drivers/clk/clk_fixed_rate.c1
-rw-r--r--drivers/clk/clk_sandbox.c30
-rw-r--r--drivers/clk/clk_sandbox_ccf.c48
-rw-r--r--drivers/clk/clk_scmi.c62
-rw-r--r--drivers/clk/imx/clk-fracn-gppll.c1
-rw-r--r--drivers/clk/qcom/Kconfig24
-rw-r--r--drivers/clk/qcom/Makefile3
-rw-r--r--drivers/clk/qcom/clock-apq8016.c17
-rw-r--r--drivers/clk/qcom/clock-ipq5424.c96
-rw-r--r--drivers/clk/qcom/clock-qcom.c27
-rw-r--r--drivers/clk/qcom/clock-qcom.h27
-rw-r--r--drivers/clk/qcom/clock-qcs615.c163
-rw-r--r--drivers/clk/qcom/clock-qcs8300.c146
-rw-r--r--drivers/clk/qcom/clock-sc7280.c4
-rw-r--r--drivers/clk/qcom/clock-sm8250.c4
-rw-r--r--drivers/clk/renesas/clk-rcar-gen3.c4
-rw-r--r--drivers/clk/renesas/r8a774a1-cpg-mssr.c2
-rw-r--r--drivers/clk/stm32/Kconfig9
-rw-r--r--drivers/clk/stm32/Makefile1
-rw-r--r--drivers/clk/stm32/clk-stm32-core.c73
-rw-r--r--drivers/clk/stm32/clk-stm32-core.h3
-rw-r--r--drivers/clk/stm32/clk-stm32h7.c5
-rw-r--r--drivers/clk/stm32/clk-stm32mp1.c2
-rw-r--r--drivers/clk/stm32/clk-stm32mp13.c1311
-rw-r--r--drivers/clk/stm32/clk-stm32mp25.c782
-rw-r--r--drivers/clk/stm32/stm32mp13_rcc.h93
-rw-r--r--drivers/core/read.c8
-rw-r--r--drivers/crypto/fsl/jr.c25
-rw-r--r--drivers/crypto/fsl/jr.h4
-rw-r--r--drivers/ddr/altera/iossm_mailbox.c2
-rw-r--r--drivers/dfu/dfu_mmc.c2
-rw-r--r--drivers/dfu/dfu_scsi.c7
-rw-r--r--drivers/firmware/ti_sci.c99
-rw-r--r--drivers/firmware/ti_sci.h42
-rw-r--r--drivers/fpga/intel_sdm_mb.c7
-rw-r--r--drivers/gpio/msm_gpio.c2
-rw-r--r--drivers/i2c/designware_i2c.c30
-rw-r--r--drivers/iommu/qcom-hyp-smmu.c1
-rw-r--r--drivers/misc/Kconfig8
-rw-r--r--drivers/misc/rockchip-io-domain.c5
-rw-r--r--drivers/misc/stm32_rcc.c66
-rw-r--r--drivers/mmc/Kconfig4
-rw-r--r--drivers/mmc/am654_sdhci.c5
-rw-r--r--drivers/mmc/mmc.c4
-rw-r--r--drivers/mmc/sdhci-cadence6.c2
-rw-r--r--drivers/mmc/zynq_sdhci.c2
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_nand_mlc.c4
-rw-r--r--drivers/mtd/nand/spi/winbond.c13
-rw-r--r--drivers/net/designware.c2
-rw-r--r--drivers/net/fm/fm.c8
-rw-r--r--drivers/net/fsl-mc/mc.c2
-rw-r--r--drivers/net/mvpp2.c1
-rw-r--r--drivers/net/octeontx/nicvf_main.c2
-rw-r--r--drivers/net/phy/ca_phy.c2
-rw-r--r--drivers/net/phy/cortina.c8
-rw-r--r--drivers/net/zynq_gem.c14
-rw-r--r--drivers/pci/pcie-xilinx-nwl.c7
-rw-r--r--drivers/phy/phy-stm32-usbphyc.c19
-rw-r--r--drivers/phy/phy-zynqmp.c6
-rw-r--r--drivers/phy/qcom/phy-qcom-qmp-ufs.c128
-rw-r--r--drivers/phy/rockchip/phy-rockchip-typec.c2
-rw-r--r--drivers/pinctrl/qcom/Kconfig7
-rw-r--r--drivers/pinctrl/qcom/Makefile1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5424.c322
-rw-r--r--drivers/power/pmic/rk8xx.c2
-rw-r--r--drivers/power/regulator/Kconfig9
-rw-r--r--drivers/power/regulator/act8846.c4
-rw-r--r--drivers/power/regulator/qcom_usb_vbus_regulator.c37
-rw-r--r--drivers/power/regulator/rk8xx.c8
-rw-r--r--drivers/pwm/Kconfig6
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-ti-ehrpwm.c2
-rw-r--r--drivers/pwm/pwm-tiecap.c198
-rw-r--r--drivers/qe/qe.c8
-rw-r--r--drivers/ram/Kconfig4
-rw-r--r--drivers/ram/k3-ddrss/k3-ddrss.c2
-rw-r--r--drivers/ram/octeon/octeon3_lmc.c2
-rw-r--r--drivers/ram/rockchip/Kconfig1
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ddr.c95
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ddr.h6
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ram.c5
-rw-r--r--drivers/remoteproc/ti_k3_r5f_rproc.c6
-rw-r--r--drivers/reset/Kconfig9
-rw-r--r--drivers/reset/Makefile4
-rw-r--r--drivers/reset/stm32-reset.c97
-rw-r--r--drivers/reset/stm32/Kconfig23
-rw-r--r--drivers/reset/stm32/Makefile9
-rw-r--r--drivers/reset/stm32/stm32-reset-core.c92
-rw-r--r--drivers/reset/stm32/stm32-reset-core.h31
-rw-r--r--drivers/reset/stm32/stm32-reset-mp1.c55
-rw-r--r--drivers/reset/stm32/stm32-reset-mp25.c159
-rw-r--r--drivers/reset/stm32/stm32-reset.c43
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/ds1672.c117
-rw-r--r--drivers/serial/serial_mtk.c41
-rw-r--r--drivers/sound/max98088.h50
-rw-r--r--drivers/sound/max98095.h2
-rw-r--r--drivers/tpm/tpm_tis_sandbox.c1
-rw-r--r--drivers/usb/gadget/at91_udc.c1
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c14
-rw-r--r--drivers/usb/gadget/f_sdp.c2
-rw-r--r--drivers/usb/musb-new/musb_core.c2
-rw-r--r--drivers/usb/musb-new/ti-musb.c1
-rw-r--r--drivers/video/bridge/dp501.c2
-rw-r--r--drivers/video/hx8238d.c2
-rw-r--r--drivers/video/zynqmp/zynqmp_dpsub.h2
-rw-r--r--drivers/watchdog/Kconfig17
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/at91sam9_wdt.c55
-rw-r--r--drivers/watchdog/qcom-wdt.c137
-rw-r--r--drivers/watchdog/renesas_wdt.c189
123 files changed, 6095 insertions, 476 deletions
diff --git a/drivers/ata/dwc_ahsata_priv.h b/drivers/ata/dwc_ahsata_priv.h
index 0c2cd5446b5..f2a118420f9 100644
--- a/drivers/ata/dwc_ahsata_priv.h
+++ b/drivers/ata/dwc_ahsata_priv.h
@@ -117,8 +117,8 @@
#define SATA_HOST_GPARAM1R_PHY_TYPE 0x00001000
#define SATA_HOST_GPARAM1R_RETURN_ERR 0x00000400
#define SATA_HOST_GPARAM1R_AHB_ENDIAN_MASK 0x00000300
-#define SATA_HOST_GPARAM1R_S_HADDR 0X00000080
-#define SATA_HOST_GPARAM1R_M_HADDR 0X00000040
+#define SATA_HOST_GPARAM1R_S_HADDR 0x00000080
+#define SATA_HOST_GPARAM1R_M_HADDR 0x00000040
/* Global Parameter 2 Register */
#define SATA_HOST_GPARAM2R_DEV_CP 0x00004000
diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c
index e3bb9bd758a..85addfe32a2 100644
--- a/drivers/button/button-qcom-pmic.c
+++ b/drivers/button/button-qcom-pmic.c
@@ -143,6 +143,21 @@ static int qcom_pwrkey_probe(struct udevice *dev)
priv->base = base;
+ ret = dev_read_u32(dev, "linux,code", &priv->code);
+ if (ret == 0) {
+ /* convert key, if read OK */
+ switch (priv->code) {
+ case KEY_VOLUMEDOWN:
+ priv->code = KEY_DOWN;
+ uc_plat->label = "Volume Down";
+ break;
+ case KEY_VOLUMEUP:
+ priv->code = KEY_UP;
+ uc_plat->label = "Volume Up";
+ break;
+ }
+ }
+
/* Do a sanity check */
ret = pmic_reg_read(priv->pmic, priv->base + REG_TYPE);
if (ret != 0x1 && ret != 0xb) {
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 19aa2ffa539..ef1e5355be8 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -10,6 +10,16 @@ config CLK
feed into other clocks in a tree structure, with multiplexers to
choose the source for each clock.
+config CLK_AUTO_ID
+ bool "Enable support of an unique clock id with several provider"
+ depends on CLK
+ help
+ Add the uclass sequence number of clock provider in the 8 higher bits
+ of the clk id to guaranty an unique clock identifier in clk uclass
+ when several clock providers are present on the device and when
+ default xlate are used.
+ This feature limit each identifier for each clock providers (24 bits).
+
config SPL_CLK
bool "Enable clock support in SPL"
depends on CLK && SPL && SPL_DM
@@ -182,6 +192,7 @@ config CLK_SCMI
bool "Enable SCMI clock driver"
depends on CLK
depends on SCMI_FIRMWARE
+ select CLK_AUTO_ID if CLK_CCF
help
Enable this option if you want to support clock devices exposed
by a SCMI agent based on SCMI clock protocol communication
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index e53dcb4ca7a..6cca861f81c 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o
obj-$(CONFIG_AT91_SAM9X60_USB) += clk-sam9x60-usb.o
obj-$(CONFIG_SAMA7G5) += sama7g5.o
obj-$(CONFIG_SAM9X60) += sam9x60.o
+obj-$(CONFIG_SAM9X7) += sam9x7.o
else
obj-y += compat.o
endif
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 09daae97676..a5186f885f0 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -110,7 +110,7 @@ struct clk *at91_clk_main_rc(void __iomem *reg, const char *name,
struct clk *clk;
int ret;
- if (!reg || !name || !parent_name)
+ if (!reg || !name)
return ERR_PTR(-EINVAL);
main_rc = kzalloc(sizeof(*main_rc), GFP_KERNEL);
diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c
index a30035eb8ce..df8172bccac 100644
--- a/drivers/clk/at91/clk-sam9x60-pll.c
+++ b/drivers/clk/at91/clk-sam9x60-pll.c
@@ -22,6 +22,7 @@
#define UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL "at91-sam9x60-div-pll-clk"
#define UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL "at91-sam9x60-frac-pll-clk"
+#define UBOOT_DM_CLK_AT91_SAM9X60_FIXED_DIV_PLL "at91-sam9x60-fixed-div-pll-clk"
#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
#define PMC_PLL_CTRL1_MUL_MSK GENMASK(31, 24)
@@ -31,9 +32,6 @@
#define UPLL_DIV 2
#define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
-#define FCORE_MIN (600000000)
-#define FCORE_MAX (1200000000)
-
#define PLL_MAX_ID 7
struct sam9x60_pll {
@@ -55,14 +53,15 @@ static inline bool sam9x60_pll_ready(void __iomem *base, int id)
return !!(status & BIT(id));
}
-static long sam9x60_frac_pll_compute_mul_frac(u32 *mul, u32 *frac, ulong rate,
+static long sam9x60_frac_pll_compute_mul_frac(const struct clk_range *core_clk,
+ u32 *mul, u32 *frac, ulong rate,
ulong parent_rate)
{
unsigned long tmprate, remainder;
unsigned long nmul = 0;
unsigned long nfrac = 0;
- if (rate < FCORE_MIN || rate > FCORE_MAX)
+ if (rate < core_clk->min || rate > core_clk->max)
return -ERANGE;
/*
@@ -82,7 +81,7 @@ static long sam9x60_frac_pll_compute_mul_frac(u32 *mul, u32 *frac, ulong rate,
}
/* Check if resulted rate is valid. */
- if (tmprate < FCORE_MIN || tmprate > FCORE_MAX)
+ if (tmprate < core_clk[0].min || tmprate > core_clk[0].max)
return -ERANGE;
*mul = nmul - 1;
@@ -103,8 +102,8 @@ static ulong sam9x60_frac_pll_set_rate(struct clk *clk, ulong rate)
if (!parent_rate)
return 0;
- ret = sam9x60_frac_pll_compute_mul_frac(&nmul, &nfrac, rate,
- parent_rate);
+ ret = sam9x60_frac_pll_compute_mul_frac(pll->characteristics->core_output,
+ &nmul, &nfrac, rate, parent_rate);
if (ret < 0)
return 0;
@@ -142,6 +141,7 @@ static ulong sam9x60_frac_pll_get_rate(struct clk *clk)
void __iomem *base = pll->base;
ulong parent_rate = clk_get_parent_rate(clk);
u32 mul, frac, val;
+ ulong pll_rate;
if (!parent_rate)
return 0;
@@ -151,8 +151,12 @@ static ulong sam9x60_frac_pll_get_rate(struct clk *clk)
pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
mul = (val & pll->layout->mul_mask) >> pll->layout->mul_shift;
frac = (val & pll->layout->frac_mask) >> pll->layout->frac_shift;
+ pll_rate = (parent_rate * (mul + 1) + ((u64)parent_rate * frac >> 22));
+
+ if (pll->layout->div2)
+ pll_rate >>= 1;
- return (parent_rate * (mul + 1) + ((u64)parent_rate * frac >> 22));
+ return pll_rate;
}
static int sam9x60_frac_pll_enable(struct clk *clk)
@@ -163,7 +167,8 @@ static int sam9x60_frac_pll_enable(struct clk *clk)
ulong crate;
crate = sam9x60_frac_pll_get_rate(clk);
- if (crate < FCORE_MIN || crate > FCORE_MAX)
+ if (crate < pll->characteristics->core_output[0].min ||
+ crate > pll->characteristics->core_output[0].max)
return -ERANGE;
pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
@@ -360,6 +365,16 @@ static ulong sam9x60_div_pll_get_rate(struct clk *clk)
return parent_rate / (div + 1);
}
+static ulong sam9x60_fixed_div_pll_get_rate(struct clk *clk)
+{
+ ulong parent_rate = clk_get_parent_rate(clk);
+
+ if (!parent_rate)
+ return 0;
+
+ return parent_rate >> 1;
+}
+
static const struct clk_ops sam9x60_div_pll_ops = {
.enable = sam9x60_div_pll_enable,
.disable = sam9x60_div_pll_disable,
@@ -367,6 +382,12 @@ static const struct clk_ops sam9x60_div_pll_ops = {
.get_rate = sam9x60_div_pll_get_rate,
};
+static const struct clk_ops sam9x60_fixed_div_pll_ops = {
+ .enable = sam9x60_div_pll_enable,
+ .disable = sam9x60_div_pll_disable,
+ .get_rate = sam9x60_fixed_div_pll_get_rate,
+};
+
static struct clk *
sam9x60_clk_register_pll(void __iomem *base, const char *type,
const char *name, const char *parent_name, u8 id,
@@ -407,6 +428,13 @@ sam9x60_clk_register_div_pll(void __iomem *base, const char *name,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical)
{
+ if (layout->div2) {
+ return sam9x60_clk_register_pll(base,
+ UBOOT_DM_CLK_AT91_SAM9X60_FIXED_DIV_PLL, name, parent_name,
+ id, characteristics, layout,
+ CLK_GET_RATE_NOCACHE | (critical ? CLK_IS_CRITICAL : 0));
+ }
+
return sam9x60_clk_register_pll(base,
UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL, name, parent_name, id,
characteristics, layout,
@@ -432,6 +460,13 @@ U_BOOT_DRIVER(at91_sam9x60_div_pll_clk) = {
.flags = DM_FLAG_PRE_RELOC,
};
+U_BOOT_DRIVER(at91_sam9x60_fixed_div_pll_clk) = {
+ .name = UBOOT_DM_CLK_AT91_SAM9X60_FIXED_DIV_PLL,
+ .id = UCLASS_CLK,
+ .ops = &sam9x60_fixed_div_pll_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
U_BOOT_DRIVER(at91_sam9x60_frac_pll_clk) = {
.name = UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL,
.id = UCLASS_CLK,
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index ff464522aa0..580c9964ff4 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -38,6 +38,7 @@ struct clk_pll_characteristics {
struct clk_range input;
int num_output;
const struct clk_range *output;
+ const struct clk_range *core_output;
u16 *icpll;
u8 *out;
u8 upll : 1;
@@ -53,6 +54,7 @@ struct clk_pll_layout {
u8 frac_shift;
u8 div_shift;
u8 endiv_shift;
+ u8 div2;
};
struct clk_programmable_layout {
diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c
index b7d64bdbb3d..e04266a2be2 100644
--- a/drivers/clk/at91/sam9x60.c
+++ b/drivers/clk/at91/sam9x60.c
@@ -112,17 +112,24 @@ static const struct clk_range upll_outputs[] = {
{ .min = 300000000, .max = 500000000 },
};
+/* Fractional PLL core output range. */
+static const struct clk_range core_outputs[] = {
+ { .min = 600000000, .max = 1200000000 },
+};
+
/* PLL characteristics. */
static const struct clk_pll_characteristics apll_characteristics = {
.input = { .min = 12000000, .max = 48000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
+ .core_output = core_outputs,
};
static const struct clk_pll_characteristics upll_characteristics = {
.input = { .min = 12000000, .max = 48000000 },
.num_output = ARRAY_SIZE(upll_outputs),
.output = upll_outputs,
+ .core_output = core_outputs,
.upll = true,
};
diff --git a/drivers/clk/at91/sam9x7.c b/drivers/clk/at91/sam9x7.c
new file mode 100644
index 00000000000..ad9865feff0
--- /dev/null
+++ b/drivers/clk/at91/sam9x7.c
@@ -0,0 +1,1085 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Varshini Rajendran <varshini.rajendran@microchip.com>
+ *
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/at91.h>
+#include <linux/clk-provider.h>
+
+#include "pmc.h"
+
+/**
+ * Clock identifiers to be used in conjunction with macros like
+ * AT91_TO_CLK_ID()
+ *
+ * @ID_MD_SLCK: TD slow clock identifier
+ * @ID_TD_SLCK: MD slow clock identifier
+ * @ID_MAIN_XTAL: Main Xtal clock identifier
+ * @ID_MAIN_RC: Main RC clock identifier
+ * @ID_MAIN_RC_OSC: Main RC Oscillator clock identifier
+ * @ID_MAIN_OSC: Main Oscillator clock identifier
+ * @ID_MAINCK: MAINCK clock identifier
+ * @ID_PLL_U_FRAC: UPLL fractional clock identifier
+ * @ID_PLL_U_DIV: UPLL divider clock identifier
+ * @ID_PLL_A_FRAC: APLL fractional clock identifier
+ * @ID_PLL_A_DIV: APLL divider clock identifier
+ * @ID_PLL_A_2_DIV: PLLA DIV2 divider clock identifier
+ * @ID_PLL_AUDIO_FRAC: Audio PLL fractional clock identifier
+ * @ID_PLL_AUDIO_DIVPMC: Audio PLL divider clock identifier
+ * @ID_PLL_AUDIO_DIVIO: Audio PLL IO divider clock identifier
+ * @ID_PLL_LVDS_FRAC: LVDS PLL fractional clock identifier
+ * @ID_PLL_LVDS_DIV: LVDS PLL divider clock identifier
+
+ * @ID_MCK_DIV: MCK DIV clock identifier
+
+ * @ID_UTMI: UTMI clock identifier
+
+ * @ID_PROG0: Programmable 0 clock identifier
+ * @ID_PROG1: Programmable 1 clock identifier
+
+ * @ID_PCK0: PCK0 system clock identifier
+ * @ID_PCK1: PCK1 system clock identifier
+ * @ID_DDR: DDR system clock identifier
+ * @ID_QSPI: QSPI system clock identifier
+ *
+ * @ID_MCK_PRES: MCK PRES clock identifier
+ *
+ * Note: if changing the values of this enums please sync them with
+ * device tree
+ */
+enum pmc_clk_ids {
+ ID_MD_SLCK = 0,
+ ID_TD_SLCK = 1,
+ ID_MAIN_XTAL = 2,
+ ID_MAIN_RC = 3,
+ ID_MAIN_RC_OSC = 4,
+ ID_MAIN_OSC = 5,
+ ID_MAINCK = 6,
+
+ ID_PLL_U_FRAC = 7,
+ ID_PLL_U_DIV = 8,
+ ID_PLL_A_FRAC = 9,
+ ID_PLL_A_DIV = 10,
+ ID_PLL_A_2_DIV = 11,
+ ID_PLL_AUDIO_FRAC = 12,
+ ID_PLL_AUDIO_DIVPMC = 13,
+ ID_PLL_AUDIO_DIVIO = 14,
+ ID_PLL_LVDS_FRAC = 15,
+ ID_PLL_LVDS_DIV = 16,
+
+ ID_MCK_DIV = 17,
+
+ ID_UTMI = 18,
+
+ ID_PROG0 = 19,
+ ID_PROG1 = 20,
+
+ ID_PCK0 = 21,
+ ID_PCK1 = 22,
+
+ ID_DDR = 23,
+ ID_QSPI = 24,
+
+ ID_MCK_PRES = 25,
+
+ ID_MAX,
+};
+
+/**
+ * PLL type identifiers
+ * @PLL_TYPE_FRAC: fractional PLL identifier
+ * @PLL_TYPE_DIV: divider PLL identifier
+ */
+enum pll_type {
+ PLL_TYPE_FRAC,
+ PLL_TYPE_DIV,
+};
+
+/* Clock names used as parents for multiple clocks. */
+static const char *clk_names[] = {
+ [ID_MAIN_RC] = "main_rc",
+ [ID_MAIN_RC_OSC] = "main_rc_osc",
+ [ID_MAIN_OSC] = "main_osc",
+ [ID_MAINCK] = "mainck",
+ [ID_PLL_U_DIV] = "upll_divpmcck",
+ [ID_PLL_A_DIV] = "plla_divpmcck",
+ [ID_PLL_A_2_DIV] = "plla_div2pmcck",
+ [ID_PLL_AUDIO_DIVPMC] = "pll_audio_divpmcck",
+ [ID_PLL_AUDIO_DIVIO] = "pll_audio_diviock",
+ [ID_PLL_LVDS_DIV] = "pll_lvds_divpmcck",
+ [ID_MCK_PRES] = "mck_pres",
+ [ID_MCK_DIV] = "mck_div",
+};
+
+/* Fractional PLL core output range. */
+static const struct clk_range plla_core_outputs[] = {
+ { .min = 800000000, .max = 1600000000 },
+};
+
+static const struct clk_range upll_core_outputs[] = {
+ { .min = 600000000, .max = 960000000 },
+};
+
+static const struct clk_range lvdspll_core_outputs[] = {
+ { .min = 600000000, .max = 1200000000 },
+};
+
+static const struct clk_range audiopll_core_outputs[] = {
+ { .min = 600000000, .max = 1200000000 },
+};
+
+static const struct clk_range plladiv2_core_outputs[] = {
+ { .min = 800000000, .max = 1600000000 },
+};
+
+/* Fractional PLL output range. */
+static const struct clk_range plla_outputs[] = {
+ { .min = 400000000, .max = 800000000 },
+};
+
+static const struct clk_range upll_outputs[] = {
+ { .min = 300000000, .max = 480000000 },
+};
+
+static const struct clk_range lvdspll_outputs[] = {
+ { .min = 175000000, .max = 550000000 },
+};
+
+static const struct clk_range audiopll_outputs[] = {
+ { .min = 0, .max = 300000000 },
+};
+
+static const struct clk_range plladiv2_outputs[] = {
+ { .min = 200000000, .max = 400000000 },
+};
+
+/* PLL characteristics. */
+static const struct clk_pll_characteristics plla_characteristics = {
+ .input = { .min = 20000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(plla_outputs),
+ .output = plla_outputs,
+ .core_output = plla_core_outputs,
+};
+
+static const struct clk_pll_characteristics upll_characteristics = {
+ .input = { .min = 20000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(upll_outputs),
+ .output = upll_outputs,
+ .core_output = upll_core_outputs,
+ .upll = true,
+};
+
+static const struct clk_pll_characteristics lvdspll_characteristics = {
+ .input = { .min = 20000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(lvdspll_outputs),
+ .output = lvdspll_outputs,
+ .core_output = lvdspll_core_outputs,
+};
+
+static const struct clk_pll_characteristics audiopll_characteristics = {
+ .input = { .min = 20000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(audiopll_outputs),
+ .output = audiopll_outputs,
+ .core_output = audiopll_core_outputs,
+};
+
+static const struct clk_pll_characteristics plladiv2_characteristics = {
+ .input = { .min = 20000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(plladiv2_outputs),
+ .output = plladiv2_outputs,
+ .core_output = plladiv2_core_outputs,
+};
+
+/* Layout for fractional PLLs. */
+static const struct clk_pll_layout pll_layout_frac = {
+ .mul_mask = GENMASK(31, 24),
+ .frac_mask = GENMASK(21, 0),
+ .mul_shift = 24,
+ .frac_shift = 0,
+};
+
+/* Layout for fractional PLL ID PLLA. */
+static const struct clk_pll_layout plla_layout_frac = {
+ .mul_mask = GENMASK(31, 24),
+ .frac_mask = GENMASK(21, 0),
+ .mul_shift = 24,
+ .frac_shift = 0,
+ .div2 = 1,
+};
+
+/* Layout for DIV PLLs. */
+static const struct clk_pll_layout pll_layout_divpmc = {
+ .div_mask = GENMASK(7, 0),
+ .endiv_mask = BIT(29),
+ .div_shift = 0,
+ .endiv_shift = 29,
+};
+
+/* Layout for DIV PLLs. */
+static const struct clk_pll_layout plladiv2_layout_divpmc = {
+ .div_mask = GENMASK(7, 0),
+ .endiv_mask = BIT(29),
+ .div_shift = 0,
+ .endiv_shift = 29,
+ .div2 = 1,
+};
+
+/* Layout for DIVIO dividers. */
+static const struct clk_pll_layout pll_layout_divio = {
+ .div_mask = GENMASK(19, 12),
+ .endiv_mask = BIT(30),
+ .div_shift = 12,
+ .endiv_shift = 30,
+};
+
+/* MCK characteristics. */
+static const struct clk_master_characteristics mck_characteristics = {
+ .output = { .min = 32000000, .max = 266666666 },
+ .divisors = { 1, 2, 4, 3, 5},
+ .have_div3_pres = 1,
+};
+
+/* MCK layout. */
+static const struct clk_master_layout mck_layout = {
+ .mask = 0x373,
+ .pres_shift = 4,
+ .offset = 0x28,
+};
+
+/* Programmable clock layout. */
+static const struct clk_programmable_layout programmable_layout = {
+ .pres_mask = 0xff,
+ .pres_shift = 8,
+ .css_mask = 0x1f,
+ .have_slck_mck = 0,
+ .is_pres_direct = 1,
+};
+
+/* Peripheral clock layout. */
+static const struct clk_pcr_layout sam9x7_pcr_layout = {
+ .offset = 0x88,
+ .cmd = BIT(31),
+ .gckcss_mask = GENMASK(12, 8),
+ .pid_mask = GENMASK(6, 0),
+};
+
+/**
+ * PLL clocks description
+ * @n: clock name
+ * @p: clock parent
+ * @l: clock layout
+ * @t: clock type
+ * @c: pll characteristics
+ * @f: true if clock is fixed and not changeable by driver
+ * @id: clock id corresponding to PLL driver
+ * @cid: clock id corresponding to clock subsystem
+ */
+static const struct {
+ const char *n;
+ const char *p;
+ const struct clk_pll_layout *l;
+ const struct clk_pll_characteristics *c;
+ u8 t;
+ u8 f;
+ u8 id;
+ u8 cid;
+} sam9x7_plls[] = {
+ {
+ .n = "plla_fracck",
+ .p = "mainck",
+ .l = &plla_layout_frac,
+ .c = &plla_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = 1,
+ .id = 0,
+ .cid = ID_PLL_A_FRAC,
+ },
+
+ {
+ .n = "plla_divpmcck",
+ .p = "plla_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &plla_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = 1,
+ .id = 0,
+ .cid = ID_PLL_A_DIV,
+ },
+
+ {
+ .n = "upll_fracck",
+ .p = "main_osc",
+ .l = &pll_layout_frac,
+ .c = &upll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = 1,
+ .id = 1,
+ .cid = ID_PLL_U_FRAC,
+ },
+
+ {
+ .n = "upll_divpmcck",
+ .p = "upll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &upll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = 1,
+ .id = 1,
+ .cid = ID_PLL_U_DIV,
+ },
+
+ {
+ .n = "audiopll_fracck",
+ .p = "main_osc",
+ .l = &pll_layout_frac,
+ .c = &audiopll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = 1,
+ .id = 2,
+ .cid = ID_PLL_AUDIO_FRAC,
+ },
+
+ {
+ .n = "audiopll_divpmcck",
+ .p = "audiopll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &audiopll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = 1,
+ .id = 2,
+ .cid = ID_PLL_AUDIO_DIVPMC,
+ },
+
+ {
+ .n = "audiopll_diviock",
+ .p = "audiopll_fracck",
+ .l = &pll_layout_divio,
+ .c = &audiopll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = 1,
+ .id = 2,
+ .cid = ID_PLL_AUDIO_DIVIO,
+ },
+
+ {
+ .n = "lvdspll_fracck",
+ .p = "main_osc",
+ .l = &pll_layout_frac,
+ .c = &lvdspll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = 1,
+ .id = 3,
+ .cid = ID_PLL_LVDS_FRAC,
+ },
+
+ {
+ .n = "lvdspll_divpmcck",
+ .p = "lvdspll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &lvdspll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = 1,
+ .id = 3,
+ .cid = ID_PLL_LVDS_DIV,
+ },
+
+ {
+ .n = "plla_div2pmcck",
+ .p = "plla_fracck",
+ .l = &plladiv2_layout_divpmc,
+ .c = &plladiv2_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = 1,
+ .id = 4,
+ .cid = ID_PLL_A_2_DIV,
+ },
+
+};
+
+/**
+ * Programmable clock description
+ * @n: clock name
+ * @cid: clock id corresponding to clock subsystem
+ */
+static const struct {
+ const char *n;
+ u8 cid;
+} sam9x7_prog[] = {
+ { .n = "prog0", .cid = ID_PROG0, },
+ { .n = "prog1", .cid = ID_PROG1, },
+};
+
+/* Mux table for programmable clocks. */
+static u32 sam9x7_prog_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, };
+
+/**
+ * System clock description
+ * @n: clock name
+ * @p: parent clock name
+ * @id: clock id corresponding to system clock driver
+ * @cid: clock id corresponding to clock subsystem
+ */
+static const struct {
+ const char *n;
+ const char *p;
+ u8 id;
+ u8 cid;
+} sam9x7_systemck[] = {
+ { .n = "ddrck", .p = "mck_pres", .id = 2, .cid = ID_DDR, },
+ { .n = "pck0", .p = "prog0", .id = 8, .cid = ID_PCK0, },
+ { .n = "pck1", .p = "prog1", .id = 9, .cid = ID_PCK1, },
+};
+
+/**
+ * Peripheral clock description
+ * @n: clock name
+ * @id: clock id
+ */
+static const struct {
+ const char *n;
+ u8 id;
+} sam9x7_periphck[] = {
+ { .n = "pioA_clk", .id = 2, },
+ { .n = "pioB_clk", .id = 3, },
+ { .n = "pioC_clk", .id = 4, },
+ { .n = "flex0_clk", .id = 5, },
+ { .n = "flex1_clk", .id = 6, },
+ { .n = "flex2_clk", .id = 7, },
+ { .n = "flex3_clk", .id = 8, },
+ { .n = "flex6_clk", .id = 9, },
+ { .n = "flex7_clk", .id = 10, },
+ { .n = "flex8_clk", .id = 11, },
+ { .n = "sdmmc0_clk", .id = 12, },
+ { .n = "flex4_clk", .id = 13, },
+ { .n = "flex5_clk", .id = 14, },
+ { .n = "flex9_clk", .id = 15, },
+ { .n = "flex10_clk", .id = 16, },
+ { .n = "tcb0_clk", .id = 17, },
+ { .n = "pwm_clk", .id = 18, },
+ { .n = "adc_clk", .id = 19, },
+ { .n = "dma0_clk", .id = 20, },
+ { .n = "uhphs_clk", .id = 22, },
+ { .n = "udphs_clk", .id = 23, },
+ { .n = "gmac_clk", .id = 24, },
+ { .n = "lcd_clk", .id = 25, },
+ { .n = "sdmmc1_clk", .id = 26, },
+ { .n = "ssc_clk", .id = 28, },
+ { .n = "mcan0_clk", .id = 29, },
+ { .n = "mcan1_clk", .id = 30, },
+ { .n = "flex11_clk", .id = 32, },
+ { .n = "flex12_clk", .id = 33, },
+ { .n = "i2s_clk", .id = 34, },
+ { .n = "qspi_clk", .id = 35, },
+ { .n = "gfx2d_clk", .id = 36, },
+ { .n = "pit64b0_clk", .id = 37, },
+ { .n = "trng_clk", .id = 38, },
+ { .n = "aes_clk", .id = 39, },
+ { .n = "tdes_clk", .id = 40, },
+ { .n = "sha_clk", .id = 41, },
+ { .n = "classd_clk", .id = 42, },
+ { .n = "isi_clk", .id = 43, },
+ { .n = "pioD_clk", .id = 44, },
+ { .n = "tcb1_clk", .id = 45, },
+ { .n = "dbgu_clk", .id = 47, },
+ { .n = "pmecc_clk", .id = 48, },
+ { .n = "mpddr_clk", .id = 49, },
+ { .n = "csi2dc_clk", .id = 52, },
+ { .n = "csi4l_clk", .id = 53, },
+ { .n = "dsi4l_clk", .id = 54, },
+ { .n = "lvdsc_clk", .id = 56, },
+ { .n = "pit64b1_clk", .id = 58, },
+ { .n = "puf_clk", .id = 59, },
+ { .n = "gmactsu_clk", .id = 67, },
+};
+
+/**
+ * Generic clock description
+ * @n: clock name
+ * @ep: extra parents names
+ * @ep_mux_table: extra parents mux table
+ * @ep_clk_mux_table: extra parents clock mux table (for CCF)
+ * @r: clock output range
+ * @ep_count: extra parents count
+ * @id: clock id
+ */
+static const struct {
+ const char *n;
+ const char *ep[8];
+ const char ep_mux_table[8];
+ const char ep_clk_mux_table[8];
+ struct clk_range r;
+ u8 ep_count;
+ u8 id;
+} sam9x7_gck[] = {
+ {
+ .n = "flex0_gclk",
+ .id = 5,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex1_gclk",
+ .id = 6,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex2_gclk",
+ .id = 7,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex3_gclk",
+ .id = 8,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex6_gclk",
+ .id = 9,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex7_gclk",
+ .id = 10,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex8_gclk",
+ .id = 11,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "sdmmc0_gclk",
+ .id = 12,
+ .r = { .max = 105000000 },
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "flex4_gclk",
+ .id = 13,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex5_gclk",
+ .id = 14,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex9_gclk",
+ .id = 15,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex10_gclk",
+ .id = 16,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "tcb0_gclk",
+ .id = 17,
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "adc_gclk",
+ .id = 19,
+ .ep = { "upll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 5, 8, },
+ .ep_clk_mux_table = { ID_PLL_U_DIV, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "gmac_gclk",
+ .id = 24,
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "lcd_gclk",
+ .id = 25,
+ .r = { .max = 75000000 },
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "sdmmc1_gclk",
+ .id = 26,
+ .r = { .max = 105000000 },
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "mcan0_gclk",
+ .id = 29,
+ .r = { .max = 80000000 },
+ .ep = { "upll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 5, 8, },
+ .ep_clk_mux_table = { ID_PLL_U_DIV, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "mcan1_gclk",
+ .id = 30,
+ .r = { .max = 80000000 },
+ .ep = { "upll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 5, 8, },
+ .ep_clk_mux_table = { ID_PLL_U_DIV, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "flex11_gclk",
+ .id = 32,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "flex12_gclk",
+ .id = 33,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "i2s_gclk",
+ .id = 34,
+ .r = { .max = 100000000 },
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "qspi_gclk",
+ .id = 35,
+ .r = { .max = 200000000 },
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "pit64b0_gclk",
+ .id = 37,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "classd_gclk",
+ .id = 42,
+ .r = { .max = 100000000 },
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "tcb1_gclk",
+ .id = 45,
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+ {
+ .n = "dbgu_gclk",
+ .id = 47,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "mipiphy_gclk",
+ .id = 55,
+ .r = { .max = 27000000 },
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "pit64b1_gclk",
+ .id = 58,
+ .ep = { "plla_div2pmcck", },
+ .ep_mux_table = { 8, },
+ .ep_clk_mux_table = { ID_PLL_A_2_DIV, },
+ .ep_count = 1,
+ },
+
+ {
+ .n = "gmac_tsu_gclk",
+ .id = 67,
+ .ep = { "audiopll_divpmcck", "plla_div2pmcck", },
+ .ep_mux_table = { 6, 8, },
+ .ep_clk_mux_table = { ID_PLL_AUDIO_DIVPMC, ID_PLL_A_2_DIV, },
+ .ep_count = 2,
+ },
+
+};
+
+#define prepare_mux_table(_allocs, _index, _dst, _src, _num, _label) \
+ do { \
+ int _i; \
+ (_dst) = kzalloc(sizeof(*(_dst)) * (_num), GFP_KERNEL); \
+ if (!(_dst)) { \
+ ret = -ENOMEM; \
+ goto _label; \
+ } \
+ (_allocs)[(_index)++] = (_dst); \
+ for (_i = 0; _i < (_num); _i++) \
+ (_dst)[_i] = (_src)[_i]; \
+ } while (0)
+
+static int sam9x7_clk_probe(struct udevice *dev)
+{
+ void __iomem *base = (void *)devfdt_get_addr_ptr(dev);
+ unsigned int *clkmuxallocs[64], *muxallocs[64];
+ const char *p[10];
+ unsigned int cm[10], m[10], *tmpclkmux, *tmpmux;
+ struct clk clk, *c;
+ int ret, muxallocindex = 0, clkmuxallocindex = 0, i, j;
+ static const struct clk_range r = { 0, 0 };
+
+ if (!base)
+ return -EINVAL;
+
+ memset(muxallocs, 0, ARRAY_SIZE(muxallocs));
+ memset(clkmuxallocs, 0, ARRAY_SIZE(clkmuxallocs));
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_get_by_id(clk.id, &c);
+ if (ret)
+ return ret;
+
+ clk_names[ID_TD_SLCK] = kmemdup(clk_hw_get_name(c),
+ strlen(clk_hw_get_name(c)) + 1,
+ GFP_KERNEL);
+ if (!clk_names[ID_TD_SLCK])
+ return -ENOMEM;
+
+ ret = clk_get_by_index(dev, 1, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_get_by_id(clk.id, &c);
+ if (ret)
+ return ret;
+
+ clk_names[ID_MD_SLCK] = kmemdup(clk_hw_get_name(c),
+ strlen(clk_hw_get_name(c)) + 1,
+ GFP_KERNEL);
+ if (!clk_names[ID_MD_SLCK])
+ return -ENOMEM;
+
+ ret = clk_get_by_index(dev, 2, &clk);
+ if (ret)
+ return ret;
+
+ clk_names[ID_MAIN_XTAL] = kmemdup(clk_hw_get_name(&clk),
+ strlen(clk_hw_get_name(&clk)) + 1,
+ GFP_KERNEL);
+ if (!clk_names[ID_MAIN_XTAL])
+ return -ENOMEM;
+
+ /* Register main rc oscillator. */
+ c = at91_clk_main_rc(base, clk_names[ID_MAIN_RC_OSC],
+ NULL);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC), c);
+
+ /* Register main oscillator. */
+ c = at91_clk_main_osc(base, clk_names[ID_MAIN_OSC],
+ clk_names[ID_MAIN_XTAL], false);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC), c);
+
+ /* Register mainck. */
+ p[0] = clk_names[ID_MAIN_RC_OSC];
+ p[1] = clk_names[ID_MAIN_OSC];
+ cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC);
+ cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC);
+ prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2,
+ fail);
+ c = at91_clk_sam9x5_main(base, clk_names[ID_MAINCK], p,
+ 2, tmpclkmux, PMC_TYPE_CORE);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK), c);
+
+ /* Register PLL fracs clocks. */
+ for (i = 0; i < ARRAY_SIZE(sam9x7_plls); i++) {
+ if (sam9x7_plls[i].t != PLL_TYPE_FRAC)
+ continue;
+
+ c = sam9x60_clk_register_frac_pll(base, sam9x7_plls[i].n,
+ sam9x7_plls[i].p,
+ sam9x7_plls[i].id,
+ sam9x7_plls[i].c,
+ sam9x7_plls[i].l,
+ sam9x7_plls[i].f);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x7_plls[i].cid), c);
+ }
+
+ /* Register PLL div clocks. */
+ for (i = 0; i < ARRAY_SIZE(sam9x7_plls); i++) {
+ if (sam9x7_plls[i].t != PLL_TYPE_DIV)
+ continue;
+
+ c = sam9x60_clk_register_div_pll(base, sam9x7_plls[i].n,
+ sam9x7_plls[i].p,
+ sam9x7_plls[i].id,
+ sam9x7_plls[i].c,
+ sam9x7_plls[i].l,
+ sam9x7_plls[i].f);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x7_plls[i].cid), c);
+ }
+
+ /* Register MCK pres clock. */
+ p[0] = clk_names[ID_MD_SLCK];
+ p[1] = clk_names[ID_MAINCK];
+ p[2] = clk_names[ID_PLL_A_DIV];
+ p[3] = clk_names[ID_PLL_U_DIV];
+ cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
+ cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
+ cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
+ cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
+ prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 4,
+ fail);
+ c = at91_clk_register_master_pres(base, clk_names[ID_MCK_PRES], p, 4,
+ &mck_layout, &mck_characteristics,
+ tmpclkmux);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK_PRES), c);
+
+ /* Register MCK div clock. */
+ c = at91_clk_register_master_div(base, clk_names[ID_MCK_DIV],
+ clk_names[ID_MCK_PRES],
+ &mck_layout, &mck_characteristics);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK_DIV), c);
+
+ /* Register programmable clocks. */
+ p[0] = clk_names[ID_MD_SLCK];
+ p[1] = clk_names[ID_TD_SLCK];
+ p[2] = clk_names[ID_MAINCK];
+ p[3] = clk_names[ID_MCK_DIV];
+ p[4] = clk_names[ID_PLL_A_DIV];
+ p[5] = clk_names[ID_PLL_U_DIV];
+ p[6] = clk_names[ID_PLL_AUDIO_DIVPMC];
+ cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
+ cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
+ cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
+ cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK_DIV);
+ cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
+ cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
+ cm[6] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_AUDIO_DIVPMC);
+ for (i = 0; i < ARRAY_SIZE(sam9x7_prog); i++) {
+ prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
+ 7, fail);
+
+ c = at91_clk_register_programmable(base, sam9x7_prog[i].n, p,
+ 7, i, &programmable_layout,
+ tmpclkmux,
+ sam9x7_prog_mux_table);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x7_prog[i].cid), c);
+ }
+
+ /* System clocks. */
+ for (i = 0; i < ARRAY_SIZE(sam9x7_systemck); i++) {
+ c = at91_clk_register_system(base, sam9x7_systemck[i].n,
+ sam9x7_systemck[i].p,
+ sam9x7_systemck[i].id);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_SYSTEM, sam9x7_systemck[i].cid),
+ c);
+ }
+
+ /* Peripheral clocks. */
+ for (i = 0; i < ARRAY_SIZE(sam9x7_periphck); i++) {
+ c = at91_clk_register_sam9x5_peripheral(base, &sam9x7_pcr_layout,
+ sam9x7_periphck[i].n,
+ clk_names[ID_MCK_DIV],
+ sam9x7_periphck[i].id,
+ &r);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_PERIPHERAL,
+ sam9x7_periphck[i].id), c);
+ }
+
+ /* Generic clocks. */
+ p[0] = clk_names[ID_MD_SLCK];
+ p[1] = clk_names[ID_TD_SLCK];
+ p[2] = clk_names[ID_MAINCK];
+ p[3] = clk_names[ID_MCK_DIV];
+ m[0] = 0;
+ m[1] = 1;
+ m[2] = 2;
+ m[3] = 3;
+ cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
+ cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
+ cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
+ cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK_DIV);
+ for (i = 0; i < ARRAY_SIZE(sam9x7_gck); i++) {
+ for (j = 0; j < sam9x7_gck[i].ep_count; j++) {
+ p[4 + j] = sam9x7_gck[i].ep[j];
+ m[4 + j] = sam9x7_gck[i].ep_mux_table[j];
+ cm[4 + j] = AT91_TO_CLK_ID(PMC_TYPE_CORE,
+ sam9x7_gck[i].ep_clk_mux_table[j]);
+ }
+ prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
+ 4 + sam9x7_gck[i].ep_count, fail);
+ prepare_mux_table(muxallocs, muxallocindex, tmpmux, m,
+ 4 + sam9x7_gck[i].ep_count, fail);
+
+ c = at91_clk_register_generic(base, &sam9x7_pcr_layout,
+ sam9x7_gck[i].n, p, tmpclkmux,
+ tmpmux, 4 + sam9x7_gck[i].ep_count,
+ sam9x7_gck[i].id,
+ &sam9x7_gck[i].r);
+ if (IS_ERR(c)) {
+ ret = PTR_ERR(c);
+ goto fail;
+ }
+ clk_dm(AT91_TO_CLK_ID(PMC_TYPE_GCK, sam9x7_gck[i].id), c);
+ }
+
+ return 0;
+
+fail:
+ for (i = 0; i < ARRAY_SIZE(muxallocs); i++)
+ kfree(muxallocs[i]);
+
+ for (i = 0; i < ARRAY_SIZE(clkmuxallocs); i++)
+ kfree(clkmuxallocs[i]);
+
+ return ret;
+}
+
+static const struct udevice_id sam9x7_clk_ids[] = {
+ { .compatible = "microchip,sam9x7-pmc" },
+ { /* Sentinel. */ },
+};
+
+U_BOOT_DRIVER(at91_sam9x7_pmc) = {
+ .name = "at91-sam9x7-pmc",
+ .id = UCLASS_CLK,
+ .of_match = sam9x7_clk_ids,
+ .ops = &at91_clk_ops,
+ .probe = sam9x7_clk_probe,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
index 63b2c647467..c0e27828b1a 100644
--- a/drivers/clk/at91/sama7g5.c
+++ b/drivers/clk/at91/sama7g5.c
@@ -158,11 +158,17 @@ static const struct clk_range pll_outputs[] = {
{ .min = 2343750, .max = 1200000000 },
};
+/* Fractional PLL core output range. */
+static const struct clk_range core_outputs[] = {
+ { .min = 600000000, .max = 1200000000 },
+};
+
/* PLL characteristics. */
static const struct clk_pll_characteristics pll_characteristics = {
.input = { .min = 12000000, .max = 50000000 },
.num_output = ARRAY_SIZE(pll_outputs),
.output = pll_outputs,
+ .core_output = core_outputs,
};
/* Layout for fractional PLLs. */
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 2167cd5ad0f..7262e89b512 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -34,6 +34,11 @@ struct clk *dev_get_clk_ptr(struct udevice *dev)
return (struct clk *)dev_get_uclass_priv(dev);
}
+ulong clk_get_id(const struct clk *clk)
+{
+ return (ulong)(clk->id & CLK_ID_MSK);
+}
+
#if CONFIG_IS_ENABLED(OF_PLATDATA)
int clk_get_by_phandle(struct udevice *dev, const struct phandle_1_arg *cells,
struct clk *clk)
@@ -43,7 +48,7 @@ int clk_get_by_phandle(struct udevice *dev, const struct phandle_1_arg *cells,
ret = device_get_by_ofplat_idx(cells->idx, &clk->dev);
if (ret)
return ret;
- clk->id = cells->arg[0];
+ clk->id = CLK_ID(dev, cells->arg[0]);
return 0;
}
@@ -61,7 +66,7 @@ static int clk_of_xlate_default(struct clk *clk,
}
if (args->args_count)
- clk->id = args->args[0];
+ clk->id = CLK_ID(clk->dev, args->args[0]);
else
clk->id = 0;
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index d1da05cc18a..95a77d2e041 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -44,6 +44,7 @@ void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev,
dev_set_uclass_priv(dev, clk);
clk->dev = dev;
+ clk->id = CLK_ID(dev, 0);
clk->enable_count = 0;
}
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index 8dd77f18d90..c8c5a88c52d 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -13,24 +13,26 @@
static ulong sandbox_clk_get_rate(struct clk *clk)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong id = clk_get_id(clk);
if (!priv->probed)
return -ENODEV;
- if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ if (id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
- return priv->rate[clk->id];
+ return priv->rate[id];
}
static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong id = clk_get_id(clk);
if (!priv->probed)
return -ENODEV;
- if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ if (id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
if (!rate)
@@ -43,18 +45,19 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
ulong old_rate;
+ ulong id = clk_get_id(clk);
if (!priv->probed)
return -ENODEV;
- if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ if (id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
if (!rate)
return -EINVAL;
- old_rate = priv->rate[clk->id];
- priv->rate[clk->id] = rate;
+ old_rate = priv->rate[id];
+ priv->rate[id] = rate;
return old_rate;
}
@@ -62,14 +65,15 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
static int sandbox_clk_enable(struct clk *clk)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong id = clk_get_id(clk);
if (!priv->probed)
return -ENODEV;
- if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ if (id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
- priv->enabled[clk->id] = true;
+ priv->enabled[id] = true;
return 0;
}
@@ -77,14 +81,15 @@ static int sandbox_clk_enable(struct clk *clk)
static int sandbox_clk_disable(struct clk *clk)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong id = clk_get_id(clk);
if (!priv->probed)
return -ENODEV;
- if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ if (id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
- priv->enabled[clk->id] = false;
+ priv->enabled[id] = false;
return 0;
}
@@ -92,11 +97,12 @@ static int sandbox_clk_disable(struct clk *clk)
static int sandbox_clk_request(struct clk *clk)
{
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong id = clk_get_id(clk);
- if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ if (id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
- priv->requested[clk->id] = true;
+ priv->requested[id] = true;
return 0;
}
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index f96a15c30b3..9b8036d41aa 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -235,47 +235,47 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
void *base = NULL;
u32 reg;
- clk_dm(SANDBOX_CLK_PLL3,
- sandbox_clk_pllv3(SANDBOX_PLLV3_USB, "pll3_usb_otg", "osc",
- base + 0x10, 0x3));
+ dev_clk_dm(dev, SANDBOX_CLK_PLL3,
+ sandbox_clk_pllv3(SANDBOX_PLLV3_USB, "pll3_usb_otg", "osc",
+ base + 0x10, 0x3));
- clk_dm(SANDBOX_CLK_PLL3_60M,
- sandbox_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8));
+ dev_clk_dm(dev, SANDBOX_CLK_PLL3_60M,
+ sandbox_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8));
- clk_dm(SANDBOX_CLK_PLL3_80M,
- sandbox_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6));
+ dev_clk_dm(dev, SANDBOX_CLK_PLL3_80M,
+ sandbox_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6));
/* The HW adds +1 to the divider value (2+1) is the divider */
reg = (2 << 19);
- clk_dm(SANDBOX_CLK_ECSPI_ROOT,
- sandbox_clk_divider("ecspi_root", "pll3_60m", &reg, 19, 6));
+ dev_clk_dm(dev, SANDBOX_CLK_ECSPI_ROOT,
+ sandbox_clk_divider("ecspi_root", "pll3_60m", &reg, 19, 6));
reg = 0;
- clk_dm(SANDBOX_CLK_ECSPI0,
- sandbox_clk_gate("ecspi0", "ecspi_root", &reg, 0, 0));
+ dev_clk_dm(dev, SANDBOX_CLK_ECSPI0,
+ sandbox_clk_gate("ecspi0", "ecspi_root", &reg, 0, 0));
- clk_dm(SANDBOX_CLK_ECSPI1,
- sandbox_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0));
+ dev_clk_dm(dev, SANDBOX_CLK_ECSPI1,
+ sandbox_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0));
/* Select 'pll3_60m' */
reg = 0;
- clk_dm(SANDBOX_CLK_USDHC1_SEL,
- sandbox_clk_mux("usdhc1_sel", &reg, 16, 1, usdhc_sels,
- ARRAY_SIZE(usdhc_sels)));
+ dev_clk_dm(dev, SANDBOX_CLK_USDHC1_SEL,
+ sandbox_clk_mux("usdhc1_sel", &reg, 16, 1, usdhc_sels,
+ ARRAY_SIZE(usdhc_sels)));
/* Select 'pll3_80m' */
reg = BIT(17);
- clk_dm(SANDBOX_CLK_USDHC2_SEL,
- sandbox_clk_mux("usdhc2_sel", &reg, 17, 1, usdhc_sels,
- ARRAY_SIZE(usdhc_sels)));
+ dev_clk_dm(dev, SANDBOX_CLK_USDHC2_SEL,
+ sandbox_clk_mux("usdhc2_sel", &reg, 17, 1, usdhc_sels,
+ ARRAY_SIZE(usdhc_sels)));
reg = BIT(28) | BIT(24) | BIT(16);
- clk_dm(SANDBOX_CLK_I2C,
- sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels),
- &reg, CLK_SET_RATE_UNGATE));
+ dev_clk_dm(dev, SANDBOX_CLK_I2C,
+ sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels),
+ &reg, CLK_SET_RATE_UNGATE));
- clk_dm(SANDBOX_CLK_I2C_ROOT,
- sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0));
+ dev_clk_dm(dev, SANDBOX_CLK_I2C_ROOT,
+ sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0));
return 0;
}
diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
index af69850cdd8..cfb372e6190 100644
--- a/drivers/clk/clk_scmi.c
+++ b/drivers/clk/clk_scmi.c
@@ -84,26 +84,47 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name,
u32 *attr)
{
+ struct scmi_clock_priv *priv = dev_get_priv(dev);
struct scmi_clk_attribute_in in = {
.clock_id = clkid,
};
- struct scmi_clk_attribute_out out;
- struct scmi_msg msg = {
- .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
- .message_id = SCMI_CLOCK_ATTRIBUTES,
- .in_msg = (u8 *)&in,
- .in_msg_sz = sizeof(in),
- .out_msg = (u8 *)&out,
- .out_msg_sz = sizeof(out),
- };
int ret;
- ret = devm_scmi_process_msg(dev, &msg);
- if (ret)
- return ret;
-
- *name = strdup(out.clock_name);
- *attr = out.attributes;
+ if (priv->version >= 0x20000) {
+ struct scmi_clk_attribute_out_v2 out;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
+ .message_id = SCMI_CLOCK_ATTRIBUTES,
+ .in_msg = (u8 *)&in,
+ .in_msg_sz = sizeof(in),
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ *name = strdup(out.clock_name);
+ *attr = out.attributes;
+ } else {
+ struct scmi_clk_attribute_out out;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
+ .message_id = SCMI_CLOCK_ATTRIBUTES,
+ .in_msg = (u8 *)&in,
+ .in_msg_sz = sizeof(in),
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ *name = strdup(out.clock_name);
+ *attr = out.attributes;
+ }
return 0;
}
@@ -111,7 +132,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name,
static int scmi_clk_gate(struct clk *clk, int enable)
{
struct scmi_clk_state_in in = {
- .clock_id = clk->id,
+ .clock_id = clk_get_id(clk),
.attributes = enable,
};
struct scmi_clk_state_out out;
@@ -176,7 +197,7 @@ static int scmi_clk_disable(struct clk *clk)
static ulong scmi_clk_get_rate(struct clk *clk)
{
struct scmi_clk_rate_get_in in = {
- .clock_id = clk->id,
+ .clock_id = clk_get_id(clk),
};
struct scmi_clk_rate_get_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
@@ -198,7 +219,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
static ulong __scmi_clk_set_rate(struct clk *clk, ulong rate)
{
struct scmi_clk_rate_set_in in = {
- .clock_id = clk->id,
+ .clock_id = clk_get_id(clk),
.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
.rate_lsb = (u32)rate,
.rate_msb = (u32)((u64)rate >> 32),
@@ -257,6 +278,9 @@ static int scmi_clk_probe(struct udevice *dev)
if (!CONFIG_IS_ENABLED(CLK_CCF))
return 0;
+ ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_CLOCK,
+ &priv->version);
+
/* register CCF children: CLK UCLASS, no probed again */
if (device_get_uclass_id(dev->parent) == UCLASS_CLK)
return 0;
@@ -289,7 +313,7 @@ static int scmi_clk_probe(struct udevice *dev)
return ret;
}
- clk_dm(i, &clk_scmi->clk);
+ dev_clk_dm(dev, i, &clk_scmi->clk);
if (CLK_HAS_RESTRICTIONS(attributes)) {
u32 perm;
diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
index 81e19d393cf..b3926564a22 100644
--- a/drivers/clk/imx/clk-fracn-gppll.c
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -10,6 +10,7 @@
#include <dm/devres.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
+#include <linux/bug.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 3ea01f3c969..34e41461e72 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -31,6 +31,14 @@ config CLK_QCOM_IPQ4019
on the Snapdragon IPQ4019 SoC. This driver supports the clocks
and resets exposed by the GCC hardware block.
+config CLK_QCOM_IPQ5424
+ bool "Qualcomm IPQ5424 GCC"
+ select CLK_QCOM
+ help
+ Say Y here to enable support for the Global Clock Controller
+ on the Qualcomm IPQ5424 SoC. This driver supports the clocks
+ and resets exposed by the GCC hardware block.
+
config CLK_QCOM_IPQ9574
bool "Qualcomm IPQ9574 GCC"
select CLK_QCOM
@@ -55,6 +63,22 @@ config CLK_QCOM_QCS404
on the Snapdragon QCS404 SoC. This driver supports the clocks
and resets exposed by the GCC hardware block.
+config CLK_QCOM_QCS615
+ bool "Qualcomm QCS615 GCC"
+ select CLK_QCOM
+ help
+ Say Y here to enable support for the Global Clock Controller
+ on the Snapdragon QCS615 SoC. This driver supports the clocks
+ and resets exposed by the GCC hardware block.
+
+config CLK_QCOM_QCS8300
+ bool "Qualcomm QCS8300 GCC"
+ select CLK_QCOM
+ help
+ Say Y here to enable support for the Global Clock Controller
+ on the Snapdragon QCS8300 SoC. This driver supports the clocks
+ and resets exposed by the GCC hardware block.
+
config CLK_QCOM_SA8775P
bool "Qualcomm SA8775 GCC"
select CLK_QCOM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index e13fc8c1071..b3d95b0faa3 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -7,9 +7,12 @@ obj-$(CONFIG_CLK_QCOM_SDM845) += clock-sdm845.o
obj-$(CONFIG_CLK_QCOM_APQ8016) += clock-apq8016.o
obj-$(CONFIG_CLK_QCOM_APQ8096) += clock-apq8096.o
obj-$(CONFIG_CLK_QCOM_IPQ4019) += clock-ipq4019.o
+obj-$(CONFIG_CLK_QCOM_IPQ5424) += clock-ipq5424.o
obj-$(CONFIG_CLK_QCOM_IPQ9574) += clock-ipq9574.o
obj-$(CONFIG_CLK_QCOM_QCM2290) += clock-qcm2290.o
obj-$(CONFIG_CLK_QCOM_QCS404) += clock-qcs404.o
+obj-$(CONFIG_CLK_QCOM_QCS8300) += clock-qcs8300.o
+obj-$(CONFIG_CLK_QCOM_QCS615) += clock-qcs615.o
obj-$(CONFIG_CLK_QCOM_SA8775P) += clock-sa8775p.o
obj-$(CONFIG_CLK_QCOM_SC7280) += clock-sc7280.o
obj-$(CONFIG_CLK_QCOM_SM6115) += clock-sm6115.o
diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c
index 6a53f900a9e..b7bd9c9a342 100644
--- a/drivers/clk/qcom/clock-apq8016.c
+++ b/drivers/clk/qcom/clock-apq8016.c
@@ -23,10 +23,7 @@
#define APCS_GPLL_ENA_VOTE (0x45000)
#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004)
-#define SDCC_BCR(n) ((n * 0x1000) + 0x41000)
-#define SDCC_CMD_RCGR(n) (((n + 1) * 0x1000) + 0x41004)
-#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018)
-#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C)
+#define SDCC_CMD_RCGR(n) (((n) * 0x1000) + 0x42004)
/* BLSP1 AHB clock (root clock for BLSP) */
#define BLSP1_AHB_CBCR 0x1008
@@ -54,9 +51,13 @@ static struct vote_clk gcc_blsp1_ahb_clk = {
};
static const struct gate_clk apq8016_clks[] = {
- GATE_CLK(GCC_PRNG_AHB_CLK, 0x45004, BIT(8)),
- GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0)),
- GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0)),
+ GATE_CLK_POLLED(GCC_PRNG_AHB_CLK, 0x45004, BIT(8), 0x13004),
+ GATE_CLK_POLLED(GCC_SDCC1_AHB_CLK, 0x4201c, BIT(0), 0x4201c),
+ GATE_CLK_POLLED(GCC_SDCC1_APPS_CLK, 0x42018, BIT(0), 0x42018),
+ GATE_CLK_POLLED(GCC_SDCC2_AHB_CLK, 0x4301c, BIT(0), 0x4301c),
+ GATE_CLK_POLLED(GCC_SDCC2_APPS_CLK, 0x43018, BIT(0), 0x43018),
+ GATE_CLK_POLLED(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0), 0x41008),
+ GATE_CLK_POLLED(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0), 0x41004),
};
/* SDHCI */
@@ -67,12 +68,10 @@ static int apq8016_clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
if (rate == 200000000)
div = 4;
- clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot));
/* 800Mhz/div, gpll0 */
clk_rcg_set_rate_mnd(priv->base, SDCC_CMD_RCGR(slot), div, 0, 0,
CFG_CLK_SRC_GPLL0, 8);
clk_enable_gpll0(priv->base, &gpll0_vote_clk);
- clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot));
return rate;
}
diff --git a/drivers/clk/qcom/clock-ipq5424.c b/drivers/clk/qcom/clock-ipq5424.c
new file mode 100644
index 00000000000..40823a30ead
--- /dev/null
+++ b/drivers/clk/qcom/clock-ipq5424.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock drivers for Qualcomm ipq5424
+ *
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/bug.h>
+#include <linux/bitops.h>
+#include <dt-bindings/clock/qcom,ipq5424-gcc.h>
+#include <dt-bindings/reset/qcom,ipq5424-gcc.h>
+
+#include "clock-qcom.h"
+
+#define GCC_IM_SLEEP_CBCR 0x1834020u
+
+static ulong ipq5424_set_rate(struct clk *clk, ulong rate)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ switch (clk->id) {
+ case GCC_QUPV3_UART1_CLK:
+ clk_rcg_set_rate_mnd(priv->base, priv->data->clks[clk->id].reg,
+ 0, 144, 15625, CFG_CLK_SRC_GPLL0, 16);
+ return rate;
+ case GCC_SDCC1_APPS_CLK:
+ clk_rcg_set_rate_mnd(priv->base, priv->data->clks[clk->id].reg,
+ 5, 0, 0, CFG_CLK_SRC_GPLL2_MAIN, 16);
+ return rate;
+ }
+ return 0;
+}
+
+static const struct gate_clk ipq5424_clks[] = {
+ GATE_CLK(GCC_QUPV3_UART1_CLK, 0x302c, BIT(0)),
+ GATE_CLK(GCC_SDCC1_AHB_CLK, 0x3303c, BIT(0)),
+ GATE_CLK(GCC_SDCC1_APPS_CLK, 0x33004, BIT(1)),
+ GATE_CLK(GCC_IM_SLEEP_CLK, 0x34020, BIT(0)),
+};
+
+static int ipq5424_enable(struct clk *clk)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (clk->id >= ARRAY_SIZE(ipq5424_clks) || !ipq5424_clks[clk->id].reg)
+ return -EINVAL;
+
+ qcom_gate_clk_en(priv, clk->id);
+
+ return 0;
+}
+
+static const struct qcom_reset_map ipq5424_gcc_resets[] = {
+ [GCC_SDCC_BCR] = { 0x33000 },
+};
+
+static struct msm_clk_data ipq5424_gcc_data = {
+ .resets = ipq5424_gcc_resets,
+ .num_resets = ARRAY_SIZE(ipq5424_gcc_resets),
+ .clks = ipq5424_clks,
+ .num_clks = ARRAY_SIZE(ipq5424_clks),
+
+ .enable = ipq5424_enable,
+ .set_rate = ipq5424_set_rate,
+};
+
+static const struct udevice_id gcc_ipq5424_of_match[] = {
+ {
+ .compatible = "qcom,ipq5424-gcc",
+ .data = (ulong)&ipq5424_gcc_data,
+ },
+ { }
+};
+
+static int ipq5424_clk_probe(struct udevice *dev)
+{
+ /* Enable the sleep clock needed for the MMC block reset */
+ writel(BIT(0), GCC_IM_SLEEP_CBCR);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(gcc_ipq5424) = {
+ .name = "gcc_ipq5424",
+ .id = UCLASS_NOP,
+ .of_match = gcc_ipq5424_of_match,
+ .probe = ipq5424_clk_probe,
+ .bind = qcom_cc_bind,
+ .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
+};
diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c
index 7687bbe6a23..6b46d9db744 100644
--- a/drivers/clk/qcom/clock-qcom.c
+++ b/drivers/clk/qcom/clock-qcom.c
@@ -74,6 +74,33 @@ void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk)
} while ((val != BRANCH_ON_VAL) && (val != BRANCH_NOC_FSM_ON_VAL));
}
+int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
+{
+ if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) {
+ log_err("gcc@%#08llx: unknown clock ID %lu!\n",
+ priv->base, id);
+ return -ENOENT;
+ }
+
+ setbits_le32(priv->base + priv->data->clks[id].reg, priv->data->clks[id].en_val);
+ if (priv->data->clks[id].cbcr_reg) {
+ unsigned int count;
+ u32 val;
+
+ for (count = 0; count < 200; count++) {
+ val = readl(priv->base + priv->data->clks[id].cbcr_reg);
+ val &= BRANCH_CHECK_MASK;
+ if (val == BRANCH_ON_VAL || val == BRANCH_NOC_FSM_ON_VAL)
+ break;
+ udelay(1);
+ }
+ if (WARN(count == 200, "WARNING: Clock @ %#lx [%#010x] stuck at off\n",
+ priv->data->clks[id].cbcr_reg, val))
+ return -EBUSY;
+ }
+ return 0;
+}
+
#define APPS_CMD_RCGR_UPDATE BIT(0)
/* Update clock command via CMD_RCGR */
diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h
index f43edea2525..3a4550d8536 100644
--- a/drivers/clk/qcom/clock-qcom.h
+++ b/drivers/clk/qcom/clock-qcom.h
@@ -13,6 +13,7 @@
#define CFG_CLK_SRC_GPLL0 (1 << 8)
#define CFG_CLK_SRC_GPLL0_AUX2 (2 << 8)
#define CFG_CLK_SRC_GPLL2 (2 << 8)
+#define CFG_CLK_SRC_GPLL2_MAIN (2 << 8)
#define CFG_CLK_SRC_GPLL9 (2 << 8)
#define CFG_CLK_SRC_GPLL0_ODD (3 << 8)
#define CFG_CLK_SRC_GPLL6 (4 << 8)
@@ -52,13 +53,20 @@ struct freq_tbl {
struct gate_clk {
uintptr_t reg;
u32 en_val;
+ uintptr_t cbcr_reg;
const char *name;
};
+/*
+ * GATE_CLK() is deprecated: Use GATE_CLK_POLLED() instead to ensure the clock
+ * is running before we start making use of devices or registers.
+ */
#ifdef DEBUG
-#define GATE_CLK(clk, reg, val) [clk] = { reg, val, #clk }
+#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, #clk }
+#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, #clk }
#else
-#define GATE_CLK(clk, reg, val) [clk] = { reg, val, NULL }
+#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, NULL }
+#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, NULL }
#endif
struct qcom_reset_map {
@@ -107,19 +115,6 @@ void clk_rcg_set_rate(phys_addr_t base, uint32_t cmd_rcgr, int div,
int source);
void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled);
-static inline int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
-{
- u32 val;
- if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) {
- log_err("gcc@%#08llx: unknown clock ID %lu!\n",
- priv->base, id);
- return -ENOENT;
- }
-
- val = readl(priv->base + priv->data->clks[id].reg);
- writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg);
-
- return 0;
-}
+int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id);
#endif
diff --git a/drivers/clk/qcom/clock-qcs615.c b/drivers/clk/qcom/clock-qcs615.c
new file mode 100644
index 00000000000..4700baba8c9
--- /dev/null
+++ b/drivers/clk/qcom/clock-qcs615.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock drivers for Qualcomm qcs615
+ *
+ * (C) Copyright 2024 Linaro Ltd.
+ */
+
+#include <linux/types.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/bug.h>
+#include <linux/bitops.h>
+#include <dt-bindings/clock/qcom,qcs615-gcc.h>
+#include "clock-qcom.h"
+
+#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf034
+#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf01c
+#define USB3_PRIM_PHY_AUX_CMD_RCGR 0xf060
+
+#define GCC_QUPV3_WRAP0_S0_CLK_ENA_BIT BIT(10)
+#define GCC_QUPV3_WRAP0_S1_CLK_ENA_BIT BIT(11)
+#define GCC_QUPV3_WRAP0_S2_CLK_ENA_BIT BIT(12)
+#define GCC_QUPV3_WRAP0_S3_CLK_ENA_BIT BIT(13)
+#define GCC_QUPV3_WRAP0_S4_CLK_ENA_BIT BIT(14)
+#define GCC_QUPV3_WRAP0_S5_CLK_ENA_BIT BIT(15)
+
+#define GCC_QUPV3_WRAP1_S0_CLK_ENA_BIT BIT(22)
+#define GCC_QUPV3_WRAP1_S1_CLK_ENA_BIT BIT(23)
+#define GCC_QUPV3_WRAP1_S2_CLK_ENA_BIT BIT(24)
+#define GCC_QUPV3_WRAP1_S3_CLK_ENA_BIT BIT(25)
+#define GCC_QUPV3_WRAP1_S4_CLK_ENA_BIT BIT(26)
+#define GCC_QUPV3_WRAP1_S5_CLK_ENA_BIT BIT(27)
+
+static ulong qcs615_set_rate(struct clk *clk, ulong rate)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (clk->id < priv->data->num_clks)
+ debug("%s: %s, requested rate=%ld\n", __func__,
+ priv->data->clks[clk->id].name, rate);
+
+ switch (clk->id) {
+ case GCC_USB30_PRIM_MOCK_UTMI_CLK:
+ WARN(rate != 19200000, "Unexpected rate for USB30_PRIM_MOCK_UTMI_CLK: %lu\n", rate);
+ clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 0, CFG_CLK_SRC_CXO);
+ return rate;
+ case GCC_USB30_PRIM_MASTER_CLK:
+ WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", rate);
+ clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
+ 5, 0, 0, CFG_CLK_SRC_GPLL0, 8);
+ clk_rcg_set_rate(priv->base, USB3_PRIM_PHY_AUX_CMD_RCGR, 0, 0);
+ return rate;
+ default:
+ return 0;
+ }
+}
+
+static const struct gate_clk qcs615_clks[] = {
+ GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0xf078, BIT(0)),
+ GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0xf010, BIT(0)),
+ GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0xf07c, BIT(0)),
+ GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0xf014, BIT(0)),
+ GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf018, BIT(0)),
+ GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf050, BIT(0)),
+ GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf054, BIT(0)),
+ GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0xf058, BIT(0)),
+ GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, GCC_QUPV3_WRAP0_S0_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, GCC_QUPV3_WRAP0_S1_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP0_S2_CLK, 0x5200c, GCC_QUPV3_WRAP0_S2_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x5200c, GCC_QUPV3_WRAP0_S3_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x5200c, GCC_QUPV3_WRAP0_S4_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x5200c, GCC_QUPV3_WRAP0_S5_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP1_S0_CLK, 0x5200c, GCC_QUPV3_WRAP1_S0_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x5200c, GCC_QUPV3_WRAP1_S1_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP1_S2_CLK, 0x5200c, GCC_QUPV3_WRAP1_S2_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x5200c, GCC_QUPV3_WRAP1_S3_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP1_S4_CLK, 0x5200c, GCC_QUPV3_WRAP1_S4_CLK_ENA_BIT),
+ GATE_CLK(GCC_QUPV3_WRAP1_S5_CLK, 0x5200c, GCC_QUPV3_WRAP1_S5_CLK_ENA_BIT),
+ GATE_CLK(GCC_DISP_HF_AXI_CLK, 0xb038, BIT(0)),
+ GATE_CLK(GCC_DISP_AHB_CLK, 0xb032, BIT(0))
+};
+
+static int qcs615_enable(struct clk *clk)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (priv->data->num_clks < clk->id) {
+ debug("%s: unknown clk id %lu\n", __func__, clk->id);
+ return 0;
+ }
+
+ debug("%s: clk %ld: %s\n", __func__, clk->id, qcs615_clks[clk->id].name);
+
+ switch (clk->id) {
+ case GCC_AGGRE_USB3_PRIM_AXI_CLK:
+ qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK);
+ fallthrough;
+ case GCC_USB30_PRIM_MASTER_CLK:
+ qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
+ qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
+ break;
+ }
+
+ qcom_gate_clk_en(priv, clk->id);
+
+ return 0;
+}
+
+static const struct qcom_reset_map qcs615_gcc_resets[] = {
+ [GCC_EMAC_BCR] = { 0x6000 },
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0xd000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0xd004 },
+ [GCC_USB30_PRIM_BCR] = { 0xf000 },
+ [GCC_USB2_PHY_SEC_BCR] = { 0x50018 },
+ [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50020 },
+ [GCC_USB3PHY_PHY_SEC_BCR] = { 0x5001c },
+ [GCC_PCIE_0_BCR] = { 0x6b000 },
+ [GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+ [GCC_PCIE_PHY_BCR] = { 0x6f000 },
+ [GCC_PCIE_PHY_COM_BCR] = { 0x6f010 },
+ [GCC_UFS_PHY_BCR] = { 0x77000 },
+ [GCC_USB20_SEC_BCR] = { 0xa6000 },
+ [GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { 0x50008 },
+ [GCC_USB3_PHY_PRIM_SP0_BCR] = { 0x50000 },
+ [GCC_SDCC1_BCR] = { 0x12000 },
+ [GCC_SDCC2_BCR] = { 0x14000 }
+};
+
+static const struct qcom_power_map qcs615_gdscs[] = {
+ [UFS_PHY_GDSC] = { 0x77004 },
+ [USB30_PRIM_GDSC] = { 0xf004 },
+};
+
+static struct msm_clk_data sa8775_gcc_data = {
+ .resets = qcs615_gcc_resets,
+ .num_resets = ARRAY_SIZE(qcs615_gcc_resets),
+ .clks = qcs615_clks,
+ .num_clks = ARRAY_SIZE(qcs615_clks),
+
+ .power_domains = qcs615_gdscs,
+ .num_power_domains = ARRAY_SIZE(qcs615_gdscs),
+
+ .enable = qcs615_enable,
+ .set_rate = qcs615_set_rate,
+};
+
+static const struct udevice_id gcc_qcs615_of_match[] = {
+ {
+ .compatible = "qcom,qcs615-gcc",
+ .data = (ulong)&sa8775_gcc_data,
+ },
+ { }
+};
+
+U_BOOT_DRIVER(gcc_qcs615) = {
+ .name = "gcc_qcs615",
+ .id = UCLASS_NOP,
+ .of_match = gcc_qcs615_of_match,
+ .bind = qcom_cc_bind,
+ .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
+};
diff --git a/drivers/clk/qcom/clock-qcs8300.c b/drivers/clk/qcom/clock-qcs8300.c
new file mode 100644
index 00000000000..cd8aecdf788
--- /dev/null
+++ b/drivers/clk/qcom/clock-qcs8300.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024-2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/types.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/bug.h>
+#include <linux/bitops.h>
+#include <dt-bindings/clock/qcom,qcs8300-gcc.h>
+#include "clock-qcom.h"
+
+#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038
+#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020
+
+static ulong qcs8300_set_rate(struct clk *clk, ulong rate)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (clk->id < priv->data->num_clks)
+ debug("%s: %s, requested rate=%ld\n",
+ __func__, priv->data->clks[clk->id].name, rate);
+
+ switch (clk->id) {
+ case GCC_USB30_PRIM_MOCK_UTMI_CLK:
+ WARN(rate != 19200000, "Unexpected rate for USB30_PRIM_MOCK_UTMI_CLK: %lu\n", rate);
+ clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 0, CFG_CLK_SRC_CXO);
+ return rate;
+ case GCC_USB30_PRIM_MASTER_CLK:
+ WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", rate);
+ clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
+ 1, 0, 0, CFG_CLK_SRC_GPLL0_ODD, 8);
+ clk_rcg_set_rate(priv->base, 0xf064, 0, 0);
+ return rate;
+ default:
+ return 0;
+ }
+}
+
+static const struct gate_clk qcs8300_clks[] = {
+ GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x1b088, BIT(0)),
+ GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x1b018, BIT(0)),
+ GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x1b084, BIT(0)),
+ GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x1b020, BIT(0)),
+ GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x1b024, BIT(0)),
+ GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x1b05c, BIT(0)),
+ GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x1b060, BIT(0)),
+ GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x83020, BIT(0)),
+ GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x83018, BIT(0)),
+ GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x830d4, BIT(0)),
+ GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x83064, BIT(0)),
+};
+
+static int qcs8300_enable(struct clk *clk)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (priv->data->num_clks < clk->id) {
+ debug("%s: unknown clk id %lu\n", __func__, clk->id);
+ return 0;
+ }
+
+ debug("%s: clk %ld: %s\n", __func__, clk->id, qcs8300_clks[clk->id].name);
+
+ switch (clk->id) {
+ case GCC_AGGRE_USB3_PRIM_AXI_CLK:
+ qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK);
+ fallthrough;
+ case GCC_USB30_PRIM_MASTER_CLK:
+ qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
+ qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
+ break;
+ }
+
+ qcom_gate_clk_en(priv, clk->id);
+
+ return 0;
+}
+
+static const struct qcom_reset_map qcs8300_gcc_resets[] = {
+ [GCC_EMAC0_BCR] = { 0xb6000 },
+ [GCC_PCIE_0_BCR] = { 0xa9000 },
+ [GCC_PCIE_0_LINK_DOWN_BCR] = { 0xbf000 },
+ [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0xbf008 },
+ [GCC_PCIE_0_PHY_BCR] = { 0xa9144 },
+ [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0xbf00c },
+ [GCC_PCIE_1_BCR] = { 0x77000 },
+ [GCC_PCIE_1_LINK_DOWN_BCR] = { 0xae084 },
+ [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0xae090 },
+ [GCC_PCIE_1_PHY_BCR] = { 0xae08c },
+ [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0xae094 },
+ [GCC_SDCC1_BCR] = { 0x20000 },
+ [GCC_UFS_PHY_BCR] = { 0x83000 },
+ [GCC_USB20_PRIM_BCR] = { 0x1c000 },
+ [GCC_USB2_PHY_PRIM_BCR] = { 0x5c01c },
+ [GCC_USB2_PHY_SEC_BCR] = { 0x5c020 },
+ [GCC_USB30_PRIM_BCR] = { 0x1b000 },
+ [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x5c008 },
+ [GCC_USB3_PHY_PRIM_BCR] = { 0x5c000 },
+ [GCC_USB3_PHY_TERT_BCR] = { 0x5c024 },
+ [GCC_USB3_UNIPHY_MP0_BCR] = { 0x5c00c },
+ [GCC_USB3_UNIPHY_MP1_BCR] = { 0x5c010 },
+ [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x5c004 },
+ [GCC_USB3UNIPHY_PHY_MP0_BCR] = { 0x5c014 },
+ [GCC_USB3UNIPHY_PHY_MP1_BCR] = { 0x5c018 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x76000 },
+ [GCC_VIDEO_BCR] = { 0x34000 },
+};
+
+static const struct qcom_power_map qcs8300_gdscs[] = {
+ [GCC_UFS_PHY_GDSC] = { 0x83004 },
+ [GCC_USB30_PRIM_GDSC] = { 0x1B004 },
+};
+
+static struct msm_clk_data qcs8300_gcc_data = {
+ .resets = qcs8300_gcc_resets,
+ .num_resets = ARRAY_SIZE(qcs8300_gcc_resets),
+ .clks = qcs8300_clks,
+ .num_clks = ARRAY_SIZE(qcs8300_clks),
+
+ .power_domains = qcs8300_gdscs,
+ .num_power_domains = ARRAY_SIZE(qcs8300_gdscs),
+
+ .enable = qcs8300_enable,
+ .set_rate = qcs8300_set_rate,
+};
+
+static const struct udevice_id gcc_qcs8300_of_match[] = {
+ {
+ .compatible = "qcom,qcs8300-gcc",
+ .data = (ulong)&qcs8300_gcc_data,
+ },
+ { }
+};
+
+U_BOOT_DRIVER(gcc_qcs8300) = {
+ .name = "gcc_qcs8300",
+ .id = UCLASS_NOP,
+ .of_match = gcc_qcs8300_of_match,
+ .bind = qcom_cc_bind,
+ .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
+};
diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c
index 9aff8a847ad..47e0ca5f0e5 100644
--- a/drivers/clk/qcom/clock-sc7280.c
+++ b/drivers/clk/qcom/clock-sc7280.c
@@ -205,7 +205,7 @@ static const char *const sc7280_rcg_names[] = {
"GCC_PCIE_1_AUX_CLK_SRC",
};
-static struct msm_clk_data qcs404_gcc_data = {
+static struct msm_clk_data sc7280_gcc_data = {
.resets = sc7280_gcc_resets,
.num_resets = ARRAY_SIZE(sc7280_gcc_resets),
.clks = sc7280_clks,
@@ -225,7 +225,7 @@ static struct msm_clk_data qcs404_gcc_data = {
static const struct udevice_id gcc_sc7280_of_match[] = {
{
.compatible = "qcom,gcc-sc7280",
- .data = (ulong)&qcs404_gcc_data,
+ .data = (ulong)&sc7280_gcc_data,
},
{ }
};
diff --git a/drivers/clk/qcom/clock-sm8250.c b/drivers/clk/qcom/clock-sm8250.c
index 26396847d85..cc481258d22 100644
--- a/drivers/clk/qcom/clock-sm8250.c
+++ b/drivers/clk/qcom/clock-sm8250.c
@@ -360,7 +360,7 @@ static const char *const sm8250_rcg_names[] = {
"GCC_PCIE_2_AUX_CMD_RCGR",
};
-static struct msm_clk_data qcs404_gcc_data = {
+static struct msm_clk_data sm8250_gcc_data = {
.resets = sm8250_gcc_resets,
.num_resets = ARRAY_SIZE(sm8250_gcc_resets),
.clks = sm8250_clks,
@@ -381,7 +381,7 @@ static struct msm_clk_data qcs404_gcc_data = {
static const struct udevice_id gcc_sm8250_of_match[] = {
{
.compatible = "qcom,gcc-sm8250",
- .data = (ulong)&qcs404_gcc_data,
+ .data = (ulong)&sm8250_gcc_data,
},
{}
};
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index 375cc4a4930..5745acf4023 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -68,7 +68,7 @@ static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
if (ret)
return ret;
- if (core->type == CLK_TYPE_GEN3_MDSEL) {
+ if (core->type == CLK_TYPE_GEN3_MDSEL || core->type == CLK_TYPE_GEN4_MDSEL) {
shift = priv->cpg_mode & BIT(core->offset) ? 0 : 16;
parent->dev = clk->dev;
parent->id = core->parent >> shift;
@@ -318,6 +318,8 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
"FIXED");
case CLK_TYPE_GEN3_MDSEL:
+ fallthrough;
+ case CLK_TYPE_GEN4_MDSEL:
shift = priv->cpg_mode & BIT(core->offset) ? 0 : 16;
div = (core->div >> shift) & 0xffff;
rate = gen3_clk_get_rate64(&parent) / div;
diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
index d23041a8026..c8972106d90 100644
--- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
@@ -305,7 +305,7 @@ static const struct mstp_stop_table r8a774a1_mstp_table[] = {
{ 0xD00C7C1F, 0, 0xD00C7C1F, 0 },
{ 0x80000004, 0, 0x80000004, 0 },
{ 0x00DF0006, 0, 0x00DF0006, 0 },
- { 0XC5EACCCE, 0, 0XC5EACCCE, 0 },
+ { 0xC5EACCCE, 0, 0xC5EACCCE, 0 },
{ 0x29E1401C, 0, 0x29E1401C, 0 },
{ 0x00009FF1, 0, 0x00009FF1, 0 },
{ 0xFC4FDFE0, 0, 0xFC4FDFE0, 0 },
diff --git a/drivers/clk/stm32/Kconfig b/drivers/clk/stm32/Kconfig
index c05015efe8b..ea856be1662 100644
--- a/drivers/clk/stm32/Kconfig
+++ b/drivers/clk/stm32/Kconfig
@@ -36,3 +36,12 @@ config CLK_STM32MP13
help
Enable the STM32 clock (RCC) driver. Enable support for
manipulating STM32MP13's on-SoC clocks.
+
+config CLK_STM32MP25
+ bool "Enable RCC clock driver for STM32MP25"
+ depends on ARCH_STM32MP && CLK
+ default y if STM32MP25X
+ select CLK_STM32_CORE
+ help
+ Enable the STM32 clock (RCC) driver. Enable support for
+ manipulating STM32MP25's on-SoC clocks.
diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile
index 20afbc3cfce..56adb8a4bbb 100644
--- a/drivers/clk/stm32/Makefile
+++ b/drivers/clk/stm32/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_CLK_STM32F) += clk-stm32f.o
obj-$(CONFIG_CLK_STM32H7) += clk-stm32h7.o
obj-$(CONFIG_CLK_STM32MP1) += clk-stm32mp1.o
obj-$(CONFIG_CLK_STM32MP13) += clk-stm32mp13.o
+obj-$(CONFIG_CLK_STM32MP25) += clk-stm32mp25.o
diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c
index cad07cc952e..a0ae89d0912 100644
--- a/drivers/clk/stm32/clk-stm32-core.c
+++ b/drivers/clk/stm32/clk-stm32-core.c
@@ -41,12 +41,13 @@ int stm32_rcc_init(struct udevice *dev,
const struct clock_config *cfg = &data->tab_clocks[i];
struct clk *clk = ERR_PTR(-ENOENT);
- if (data->check_security && data->check_security(priv->base, cfg))
+ if (data->check_security && data->check_security(dev, priv->base, cfg))
continue;
if (cfg->setup) {
clk = cfg->setup(dev, cfg);
- clk->id = cfg->id;
+ /* set identifier of clock provider*/
+ dev_clk_dm(dev, cfg->id, clk);
} else {
dev_err(dev, "failed to register clock %s\n", cfg->name);
return -ENOENT;
@@ -69,11 +70,71 @@ ulong clk_stm32_get_rate_by_name(const char *name)
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_endisable(struct clk *clk, bool enable)
+{
+ const struct clk_ops *ops;
+ struct clk *c = NULL;
+
+ if (!clk->id || clk_get_by_id(clk->id, &c))
+ return -ENOENT;
+
+ ops = clk_dev_ops(c->dev);
+ if (!ops->enable || !ops->disable)
+ return 0;
+
+ return enable ? ops->enable(c) : ops->disable(c);
+}
+
+static int stm32_clk_enable(struct clk *clk)
+{
+ return stm32_clk_endisable(clk, true);
+}
+
+static int stm32_clk_disable(struct clk *clk)
+{
+ return stm32_clk_endisable(clk, false);
+}
+
+static ulong stm32_clk_get_rate(struct clk *clk)
+{
+ const struct clk_ops *ops;
+ struct clk *c = NULL;
+
+ if (!clk->id || clk_get_by_id(clk->id, &c))
+ return -ENOENT;
+
+ ops = clk_dev_ops(c->dev);
+ if (!ops->get_rate)
+ return -ENOSYS;
+
+ return ops->get_rate(c);
+}
+
+static ulong stm32_clk_set_rate(struct clk *clk, unsigned long clk_rate)
+{
+ const struct clk_ops *ops;
+ struct clk *c = NULL;
+
+ if (!clk->id || clk_get_by_id(clk->id, &c))
+ return -ENOENT;
+
+ ops = clk_dev_ops(c->dev);
+ if (!ops->set_rate)
+ return -ENOSYS;
+
+ return ops->set_rate(c, clk_rate);
+}
+
const struct clk_ops stm32_clk_ops = {
- .enable = ccf_clk_enable,
- .disable = ccf_clk_disable,
- .get_rate = ccf_clk_get_rate,
- .set_rate = ccf_clk_set_rate,
+ .enable = stm32_clk_enable,
+ .disable = stm32_clk_disable,
+ .get_rate = stm32_clk_get_rate,
+ .set_rate = stm32_clk_set_rate,
};
#define RCC_MP_ENCLRR_OFFSET 4
diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h
index f9ef0702005..baf2a996ef3 100644
--- a/drivers/clk/stm32/clk-stm32-core.h
+++ b/drivers/clk/stm32/clk-stm32-core.h
@@ -127,7 +127,7 @@ 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,
+ int (*check_security)(struct udevice *dev, void __iomem *base,
const struct clock_config *cfg);
};
@@ -144,6 +144,7 @@ struct stm32mp_rcc_priv {
void __iomem *base;
u8 *gate_cpt;
const struct clk_stm32_clock_data *data;
+ struct clk osc_clk[6];
};
int stm32_rcc_init(struct udevice *dev,
diff --git a/drivers/clk/stm32/clk-stm32h7.c b/drivers/clk/stm32/clk-stm32h7.c
index 6acf2ff0a8f..aa3be414a29 100644
--- a/drivers/clk/stm32/clk-stm32h7.c
+++ b/drivers/clk/stm32/clk-stm32h7.c
@@ -114,6 +114,7 @@
#define QSPISRC_PER_CK 3
#define PWR_CR3 0x0c
+#define PWR_CR3_LDOEN BIT(1)
#define PWR_CR3_SCUEN BIT(2)
#define PWR_D3CR 0x18
#define PWR_D3CR_VOS_MASK GENMASK(15, 14)
@@ -375,7 +376,11 @@ int configure_clocks(struct udevice *dev)
clrsetbits_le32(pwr_base + PWR_D3CR, PWR_D3CR_VOS_MASK,
VOS_SCALE_1 << PWR_D3CR_VOS_SHIFT);
/* Lock supply configuration update */
+#if IS_ENABLED(CONFIG_TARGET_STM32H747_DISCO)
+ clrbits_le32(pwr_base + PWR_CR3, PWR_CR3_LDOEN);
+#else
clrbits_le32(pwr_base + PWR_CR3, PWR_CR3_SCUEN);
+#endif
while (!(readl(pwr_base + PWR_D3CR) & PWR_D3CR_VOSREADY))
;
diff --git a/drivers/clk/stm32/clk-stm32mp1.c b/drivers/clk/stm32/clk-stm32mp1.c
index 9cb69a01f7f..823ce132d0b 100644
--- a/drivers/clk/stm32/clk-stm32mp1.c
+++ b/drivers/clk/stm32/clk-stm32mp1.c
@@ -117,7 +117,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define RCC_DSICKSELR 0x924
#define RCC_ADCCKSELR 0x928
#define RCC_MP_APB1ENSETR 0xA00
-#define RCC_MP_APB2ENSETR 0XA08
+#define RCC_MP_APB2ENSETR 0xA08
#define RCC_MP_APB3ENSETR 0xA10
#define RCC_MP_AHB2ENSETR 0xA18
#define RCC_MP_AHB3ENSETR 0xA20
diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c
index 362dba10252..b4d0890f902 100644
--- a/drivers/clk/stm32/clk-stm32mp13.c
+++ b/drivers/clk/stm32/clk-stm32mp13.c
@@ -3,7 +3,6 @@
* Copyright (C) 2022, STMicroelectronics - All Rights Reserved
* Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
*/
-
#define LOG_CATEGORY UCLASS_CLK
#include <clk-uclass.h>
@@ -12,6 +11,22 @@
#include <asm/io.h>
#include <dt-bindings/clock/stm32mp13-clks.h>
#include <linux/clk-provider.h>
+#include <dt-bindings/clock/stm32mp13-clksrc.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/global_data.h>
+#include <clk-uclass.h>
+#include <div64.h>
+#include <dm/device_compat.h>
+#include <init.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <regmap.h>
+#include <spl.h>
+#include <syscon.h>
+#include <time.h>
+#include <vsprintf.h>
+#include <asm/arch/sys_proto.h>
#include "clk-stm32-core.h"
#include "stm32mp13_rcc.h"
@@ -130,46 +145,6 @@ static const char * const usbphy_src[] = {
"ck_hse", "pll4_r", "clk-hse-div2"
};
-enum enum_mux_cfg {
- MUX_I2C12,
- MUX_LPTIM45,
- MUX_SPI23,
- MUX_UART35,
- MUX_UART78,
- MUX_ADC1,
- MUX_ADC2,
- MUX_DCMIPP,
- MUX_ETH1,
- MUX_ETH2,
- MUX_FDCAN,
- MUX_FMC,
- MUX_I2C3,
- MUX_I2C4,
- MUX_I2C5,
- MUX_LPTIM1,
- MUX_LPTIM2,
- MUX_LPTIM3,
- MUX_QSPI,
- MUX_RNG1,
- MUX_SAES,
- MUX_SAI1,
- MUX_SAI2,
- MUX_SDMMC1,
- MUX_SDMMC2,
- MUX_SPDIF,
- MUX_SPI1,
- MUX_SPI4,
- MUX_SPI5,
- MUX_STGEN,
- MUX_UART1,
- MUX_UART2,
- MUX_UART4,
- MUX_UART6,
- MUX_USBO,
- MUX_USBPHY,
- MUX_MCO1,
- MUX_MCO2
-};
#define MUX_CFG(id, src, _offset, _shift, _witdh) \
[id] = { \
@@ -471,15 +446,6 @@ static const struct clk_div_table ck_trace_div_table[] = {
{ 0 },
};
-enum enum_div_cfg {
- DIV_MCO1,
- DIV_MCO2,
- DIV_TRACE,
- DIV_ETH1PTP,
- DIV_ETH2PTP,
- LAST_DIV
-};
-
#define DIV_CFG(id, _offset, _shift, _width, _flags, _table) \
[id] = { \
.reg_off = _offset, \
@@ -489,7 +455,7 @@ enum enum_div_cfg {
.table = _table, \
}
-static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = {
+static const struct stm32_div_cfg stm32mp13_dividers[] = {
DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL),
DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL),
DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table),
@@ -497,7 +463,7 @@ static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = {
DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL),
};
-struct clk_stm32_securiy {
+struct clk_stm32_security {
u16 offset;
u8 bit_idx;
};
@@ -566,7 +532,8 @@ enum securit_clk {
.bit_idx = _bit_idx, \
}
-static const struct clk_stm32_securiy stm32mp13_security[] = {
+#ifdef CONFIG_TFABOOT
+static const struct clk_stm32_security stm32mp13_security[] = {
SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF),
SECF(SECF_LPTIM3, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM3SECF),
SECF(SECF_VREF, RCC_APB3SECSR, RCC_APB3SECSR_VREFSECF),
@@ -622,6 +589,7 @@ static const struct clk_stm32_securiy stm32mp13_security[] = {
SECF(SECF_MCO1, RCC_SECCFGR, RCC_SECCFGR_MCO1SECF),
SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SECF),
};
+#endif
#define PCLK(_id, _name, _parent, _flags, _gate_id, _sec_id) \
STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id)
@@ -635,6 +603,7 @@ static const struct clk_stm32_securiy stm32mp13_security[] = {
_gate_id, _mux_id, NO_STM32_DIV)
static const struct clock_config stm32mp13_clock_cfg[] = {
+#ifndef CONFIG_XPL_BUILD
TIMER(TIM2_K, "tim2_k", "timg1_ck", 0, GATE_TIM2, SECF_NONE),
TIMER(TIM3_K, "tim3_k", "timg1_ck", 0, GATE_TIM3, SECF_NONE),
TIMER(TIM4_K, "tim4_k", "timg1_ck", 0, GATE_TIM4, SECF_NONE),
@@ -649,23 +618,28 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
TIMER(TIM15_K, "tim15_k", "timg3_ck", 0, GATE_TIM15, SECF_TIM15),
TIMER(TIM16_K, "tim16_k", "timg3_ck", 0, GATE_TIM16, SECF_TIM16),
TIMER(TIM17_K, "tim17_k", "timg3_ck", 0, GATE_TIM17, SECF_TIM17),
+#endif
/* Peripheral clocks */
PCLK(SYSCFG, "syscfg", "pclk3", 0, GATE_SYSCFG, SECF_NONE),
PCLK(VREF, "vref", "pclk3", 0, GATE_VREF, SECF_VREF),
+#ifndef CONFIG_XPL_BUILD
PCLK(PMBCTRL, "pmbctrl", "pclk3", 0, GATE_PMBCTRL, SECF_NONE),
PCLK(HDP, "hdp", "pclk3", 0, GATE_HDP, SECF_NONE),
+#endif
PCLK(IWDG2, "iwdg2", "pclk4", 0, GATE_IWDG2APB, SECF_NONE),
PCLK(STGENRO, "stgenro", "pclk4", 0, GATE_STGENRO, SECF_STGENRO),
PCLK(TZPC, "tzpc", "pclk5", 0, GATE_TZC, SECF_TZC),
PCLK(IWDG1, "iwdg1", "pclk5", 0, GATE_IWDG1APB, SECF_IWDG1),
PCLK(BSEC, "bsec", "pclk5", 0, GATE_BSEC, SECF_BSEC),
+#ifndef CONFIG_XPL_BUILD
PCLK(DMA1, "dma1", "ck_mlahb", 0, GATE_DMA1, SECF_NONE),
PCLK(DMA2, "dma2", "ck_mlahb", 0, GATE_DMA2, SECF_NONE),
PCLK(DMAMUX1, "dmamux1", "ck_mlahb", 0, GATE_DMAMUX1, SECF_NONE),
PCLK(DMAMUX2, "dmamux2", "ck_mlahb", 0, GATE_DMAMUX2, SECF_DMAMUX2),
PCLK(ADC1, "adc1", "ck_mlahb", 0, GATE_ADC1, SECF_ADC1),
PCLK(ADC2, "adc2", "ck_mlahb", 0, GATE_ADC2, SECF_ADC2),
+#endif
PCLK(GPIOA, "gpioa", "pclk4", 0, GATE_GPIOA, SECF_NONE),
PCLK(GPIOB, "gpiob", "pclk4", 0, GATE_GPIOB, SECF_NONE),
PCLK(GPIOC, "gpioc", "pclk4", 0, GATE_GPIOC, SECF_NONE),
@@ -681,17 +655,23 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
PCLK(HASH1, "hash1", "ck_axi", 0, GATE_HASH1, SECF_HASH1),
PCLK(BKPSRAM, "bkpsram", "ck_axi", 0, GATE_BKPSRAM, SECF_BKPSRAM),
PCLK(MDMA, "mdma", "ck_axi", 0, GATE_MDMA, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
PCLK(ETH1TX, "eth1tx", "ck_axi", 0, GATE_ETH1TX, SECF_ETH1TX),
PCLK(ETH1RX, "eth1rx", "ck_axi", 0, GATE_ETH1RX, SECF_ETH1RX),
PCLK(ETH1MAC, "eth1mac", "ck_axi", 0, GATE_ETH1MAC, SECF_ETH1MAC),
PCLK(ETH2TX, "eth2tx", "ck_axi", 0, GATE_ETH2TX, SECF_ETH2TX),
PCLK(ETH2RX, "eth2rx", "ck_axi", 0, GATE_ETH2RX, SECF_ETH2RX),
PCLK(ETH2MAC, "eth2mac", "ck_axi", 0, GATE_ETH2MAC, SECF_ETH2MAC),
+#endif
PCLK(CRC1, "crc1", "ck_axi", 0, GATE_CRC1, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
PCLK(USBH, "usbh", "ck_axi", 0, GATE_USBH, SECF_NONE),
+#endif
PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, GATE_DDRPERFM, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
PCLK(ETH1STP, "eth1stp", "ck_axi", 0, GATE_ETH1STP, SECF_ETH1STP),
PCLK(ETH2STP, "eth2stp", "ck_axi", 0, GATE_ETH2STP, SECF_ETH2STP),
+#endif
/* Kernel clocks */
KCLK(SDMMC1_K, "sdmmc1_k", 0, GATE_SDMMC1, MUX_SDMMC1, SECF_SDMMC1),
@@ -702,8 +682,10 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
KCLK(SPI3_K, "spi3_k", 0, GATE_SPI3, MUX_SPI23, SECF_NONE),
KCLK(I2C1_K, "i2c1_k", 0, GATE_I2C1, MUX_I2C12, SECF_NONE),
KCLK(I2C2_K, "i2c2_k", 0, GATE_I2C2, MUX_I2C12, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
KCLK(LPTIM4_K, "lptim4_k", 0, GATE_LPTIM4, MUX_LPTIM45, SECF_NONE),
KCLK(LPTIM5_K, "lptim5_k", 0, GATE_LPTIM5, MUX_LPTIM45, SECF_NONE),
+#endif
KCLK(USART3_K, "usart3_k", 0, GATE_USART3, MUX_UART35, SECF_NONE),
KCLK(UART5_K, "uart5_k", 0, GATE_UART5, MUX_UART35, SECF_NONE),
KCLK(UART7_K, "uart7_k", 0, GATE_UART7, MUX_UART78, SECF_NONE),
@@ -711,20 +693,29 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
KCLK(RNG1_K, "rng1_k", 0, GATE_RNG1, MUX_RNG1, SECF_RNG1),
KCLK(USBPHY_K, "usbphy_k", 0, GATE_USBPHY, MUX_USBPHY, SECF_USBPHY),
KCLK(STGEN_K, "stgen_k", 0, GATE_STGENC, MUX_STGEN, SECF_STGENC),
+#ifndef CONFIG_XPL_BUILD
KCLK(SPDIF_K, "spdif_k", 0, GATE_SPDIF, MUX_SPDIF, SECF_NONE),
+#endif
KCLK(SPI1_K, "spi1_k", 0, GATE_SPI1, MUX_SPI1, SECF_NONE),
KCLK(SPI4_K, "spi4_k", 0, GATE_SPI4, MUX_SPI4, SECF_SPI4),
KCLK(SPI5_K, "spi5_k", 0, GATE_SPI5, MUX_SPI5, SECF_SPI5),
+#ifdef CONFIG_TFABOOT
KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_I2C3),
+#else
+ KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_NONE),
+#endif
KCLK(I2C4_K, "i2c4_k", 0, GATE_I2C4, MUX_I2C4, SECF_I2C4),
KCLK(I2C5_K, "i2c5_k", 0, GATE_I2C5, MUX_I2C5, SECF_I2C5),
+#ifndef CONFIG_XPL_BUILD
KCLK(LPTIM1_K, "lptim1_k", 0, GATE_LPTIM1, MUX_LPTIM1, SECF_NONE),
KCLK(LPTIM2_K, "lptim2_k", 0, GATE_LPTIM2, MUX_LPTIM2, SECF_LPTIM2),
KCLK(LPTIM3_K, "lptim3_k", 0, GATE_LPTIM3, MUX_LPTIM3, SECF_LPTIM3),
+#endif
KCLK(USART1_K, "usart1_k", 0, GATE_USART1, MUX_UART1, SECF_USART1),
KCLK(USART2_K, "usart2_k", 0, GATE_USART2, MUX_UART2, SECF_USART2),
KCLK(UART4_K, "uart4_k", 0, GATE_UART4, MUX_UART4, SECF_NONE),
KCLK(USART6_K, "uart6_k", 0, GATE_USART6, MUX_UART6, SECF_NONE),
+#ifndef CONFIG_XPL_BUILD
KCLK(FDCAN_K, "fdcan_k", 0, GATE_FDCAN, MUX_FDCAN, SECF_NONE),
KCLK(SAI1_K, "sai1_k", 0, GATE_SAI1, MUX_SAI1, SECF_NONE),
KCLK(SAI2_K, "sai2_k", 0, GATE_SAI2, MUX_SAI2, SECF_NONE),
@@ -732,7 +723,9 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
KCLK(ADC2_K, "adc2_k", 0, GATE_ADC2, MUX_ADC2, SECF_ADC2),
KCLK(DCMIPP_K, "dcmipp_k", 0, GATE_DCMIPP, MUX_DCMIPP, SECF_DCMIPP),
KCLK(ADFSDM_K, "adfsdm_k", 0, GATE_ADFSDM, MUX_SAI1, SECF_NONE),
+#endif
KCLK(USBO_K, "usbo_k", 0, GATE_USBO, MUX_USBO, SECF_USBO),
+#ifndef CONFIG_XPL_BUILD
KCLK(ETH1CK_K, "eth1ck_k", 0, GATE_ETH1CK, MUX_ETH1, SECF_ETH1CK),
KCLK(ETH2CK_K, "eth2ck_k", 0, GATE_ETH2CK, MUX_ETH2, SECF_ETH2CK),
KCLK(SAES_K, "saes_k", 0, GATE_SAES, MUX_SAES, SECF_SAES),
@@ -742,6 +735,7 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
GATE_LTDC, SECF_NONE),
STM32_GATE(DTS_K, "dts_k", "ck_lse", 0, GATE_DTS, SECF_NONE),
+#endif
STM32_COMPOSITE(ETH1PTP_K, "eth1ptp_k", CLK_OPS_PARENT_ENABLE |
CLK_SET_RATE_NO_REPARENT, SECF_ETH1CK,
@@ -767,16 +761,30 @@ static const struct clock_config stm32mp13_clock_cfg[] = {
STM32_COMPOSITE_NOMUX(CK_TRACE, "ck_trace", "ck_axi",
CLK_OPS_PARENT_ENABLE, SECF_NONE,
GATE_TRACECK, DIV_TRACE),
+
+#ifdef CONFIG_XPL_BUILD
+ STM32_GATE(AXIDCG, "axidcg", "ck_axi", CLK_IGNORE_UNUSED,
+ GATE_AXIDCG, SECF_NONE),
+ STM32_GATE(DDRC1, "ddrc1", "ck_axi", CLK_IGNORE_UNUSED,
+ GATE_DDRC1, SECF_NONE),
+ STM32_GATE(DDRPHYC, "ddrphyc", "pll2_r", CLK_IGNORE_UNUSED,
+ GATE_DDRPHYC, SECF_NONE),
+ STM32_GATE(DDRCAPB, "ddrcapb", "pclk4", CLK_IGNORE_UNUSED,
+ GATE_DDRCAPB, SECF_NONE),
+ STM32_GATE(DDRPHYCAPB, "ddrphycapb", "pclk4", CLK_IGNORE_UNUSED,
+ GATE_DDRPHYCAPB, SECF_NONE),
+#endif
};
-static int stm32mp13_check_security(void __iomem *base,
+#ifdef CONFIG_TFABOOT
+static int stm32mp13_check_security(struct udevice *dev, void __iomem *base,
const struct clock_config *cfg)
{
int sec_id = cfg->sec_id;
int secured = 0;
if (sec_id != SECF_NONE) {
- const struct clk_stm32_securiy *secf;
+ const struct clk_stm32_security *secf;
secf = &stm32mp13_security[sec_id];
secured = !!(readl(base + secf->offset) & BIT(secf->bit_idx));
@@ -784,6 +792,7 @@ static int stm32mp13_check_security(void __iomem *base,
return secured;
}
+#endif
static const struct stm32_clock_match_data stm32mp13_data = {
.tab_clocks = stm32mp13_clock_cfg,
@@ -794,16 +803,1204 @@ static const struct stm32_clock_match_data stm32mp13_data = {
.muxes = stm32mp13_muxes,
.dividers = stm32mp13_dividers,
},
+#ifdef CONFIG_TFABOOT
.check_security = stm32mp13_check_security,
+#endif
+};
+
+#ifndef CONFIG_TFABOOT
+
+enum stm32mp1_parent_id {
+/*
+ * _HSI, _HSE, _CSI, _LSI, _LSE should not be moved
+ * they are used as index in osc_clk[] as clock reference
+ */
+ _HSI,
+ _HSE,
+ _CSI,
+ _LSI,
+ _LSE,
+ _I2S_CKIN,
+ NB_OSC,
+
+/* other parent source */
+ _HSI_KER = NB_OSC,
+ _HSE_KER,
+ _HSE_KER_DIV2,
+ _CSI_KER,
+ _PLL1_P,
+ _PLL1_Q,
+ _PLL1_R,
+ _PLL2_P,
+ _PLL2_Q,
+ _PLL2_R,
+ _PLL3_P,
+ _PLL3_Q,
+ _PLL3_R,
+ _PLL4_P,
+ _PLL4_Q,
+ _PLL4_R,
+ _ACLK,
+ _PCLK1,
+ _PCLK2,
+ _PCLK3,
+ _PCLK4,
+ _PCLK5,
+ _HCLK6,
+ _HCLK2,
+ _CK_PER,
+ _CK_MPU,
+ _CK_MCU,
+ _DSI_PHY,
+ _USB_PHY_48,
+ _PARENT_NB,
+ _UNKNOWN_ID = 0xff,
+};
+
+#if defined(CONFIG_XPL_BUILD)
+
+#define MAX_HSI_HZ 64000000
+
+/* TIMEOUT */
+#define TIMEOUT_200MS 200000
+#define TIMEOUT_1S 1000000
+
+/* STGEN registers */
+#define STGENC_CNTCR 0x00
+#define STGENC_CNTSR 0x04
+#define STGENC_CNTCVL 0x08
+#define STGENC_CNTCVU 0x0C
+#define STGENC_CNTFID0 0x20
+
+#define STGENC_CNTCR_EN BIT(0)
+
+enum stm32mp1_clksrc_id {
+ CLKSRC_MPU,
+ CLKSRC_AXI,
+ CLKSRC_MLAHB,
+ CLKSRC_PLL12,
+ CLKSRC_PLL3,
+ CLKSRC_PLL4,
+ CLKSRC_RTC,
+ CLKSRC_MCO1,
+ CLKSRC_MCO2,
+ CLKSRC_NB
+};
+
+enum stm32mp1_clkdiv_id {
+ CLKDIV_AXI,
+ CLKDIV_MLAHB,
+ CLKDIV_APB1,
+ CLKDIV_APB2,
+ CLKDIV_APB3,
+ CLKDIV_APB4,
+ CLKDIV_APB5,
+ CLKDIV_APB6,
+ CLKDIV_RTC,
+ CLKDIV_NB
+};
+
+enum stm32mp1_pll_id {
+ _PLL1,
+ _PLL2,
+ _PLL3,
+ _PLL4,
+ _PLL_NB
+};
+
+enum stm32mp1_div_id {
+ _DIV_P,
+ _DIV_Q,
+ _DIV_R,
+ _DIV_NB,
+};
+
+/* define characteristic of PLL according type */
+#define DIVM_MIN 1
+#define DIVM_MAX 63
+#define DIVN_MIN 24
+#define DIVP_MIN 0
+#define DIVP_MAX 127
+#define FRAC_MAX 8192
+
+#define PLL2000_VCO_MIN 992000000
+#define PLL2000_VCO_MAX 2000000000
+
+enum stm32mp1_pllcfg {
+ PLLCFG_M,
+ PLLCFG_N,
+ PLLCFG_P,
+ PLLCFG_Q,
+ PLLCFG_R,
+ PLLCFG_O,
+ PLLCFG_NB
+};
+
+enum stm32mp1_pllcsg {
+ PLLCSG_MOD_PER,
+ PLLCSG_INC_STEP,
+ PLLCSG_SSCG_MODE,
+ PLLCSG_NB
+};
+
+enum stm32mp1_plltype {
+ PLL_800,
+ PLL_1600,
+ PLL_2000,
+ PLL_TYPE_NB
+};
+
+struct stm32mp1_pll {
+ u8 refclk_min;
+ u8 refclk_max;
+ u8 divn_max;
+};
+
+#define REFCLK_SIZE 4
+struct stm32mp1_clk_pll {
+ enum stm32mp1_plltype plltype;
+ u16 rckxselr;
+ u16 pllxcfgr1;
+ u16 pllxcfgr2;
+ u16 pllxfracr;
+ u16 pllxcr;
+ u16 pllxcsgr;
+ u8 refclk[REFCLK_SIZE];
+};
+
+static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
+ [PLL_800] = {
+ .refclk_min = 4,
+ .refclk_max = 16,
+ .divn_max = 99,
+ },
+ [PLL_1600] = {
+ .refclk_min = 8,
+ .refclk_max = 16,
+ .divn_max = 199,
+ },
+ [PLL_2000] = {
+ .refclk_min = 8,
+ .refclk_max = 16,
+ .divn_max = 99,
+ },
+};
+
+#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3, off4, off5, off6,\
+ p1, p2, p3, p4) \
+ [(idx)] = { \
+ .plltype = (type), \
+ .rckxselr = (off1), \
+ .pllxcfgr1 = (off2), \
+ .pllxcfgr2 = (off3), \
+ .pllxfracr = (off4), \
+ .pllxcr = (off5), \
+ .pllxcsgr = (off6), \
+ .refclk[0] = (p1), \
+ .refclk[1] = (p2), \
+ .refclk[2] = (p3), \
+ .refclk[3] = (p4), \
+ }
+
+static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
+ STM32MP1_CLK_PLL(_PLL1, PLL_2000,
+ RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
+ RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
+ _HSI, _HSE, _UNKNOWN_ID, _UNKNOWN_ID),
+ STM32MP1_CLK_PLL(_PLL2, PLL_1600,
+ RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
+ RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
+ _HSI, _HSE, _UNKNOWN_ID, _UNKNOWN_ID),
+ STM32MP1_CLK_PLL(_PLL3, PLL_800,
+ RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
+ RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
+ _HSI, _HSE, _CSI, _UNKNOWN_ID),
+ STM32MP1_CLK_PLL(_PLL4, PLL_800,
+ RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
+ RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
+ _HSI, _HSE, _CSI, _I2S_CKIN),
};
+static ulong stm32mp1_clk_get_fixed(struct stm32mp_rcc_priv *priv, int idx)
+{
+ if (idx >= NB_OSC) {
+ log_debug("clk id %d not found\n", idx);
+ return 0;
+ }
+
+ return clk_get_rate(&priv->osc_clk[idx]);
+}
+
+bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type)
+{
+ /* 650 MHz is always supported */
+ if (opp_id == 1)
+ return true;
+
+ /*
+ * 1000 MHz is supported on STM32MP13xDxx and STM32MP13xFxx,
+ * which all have bit 11 i.e. 0x800 set in CPU ID.
+ */
+ if (opp_id == 2)
+ return !!(cpu_type & BIT(11));
+
+ /* Any other OPP is invalid. */
+ return false;
+}
+
+__weak void board_vddcore_init(u32 voltage_mv)
+{
+}
+
+/*
+ * gets OPP parameters (frequency in KHz and voltage in mV) from
+ * an OPP table subnode. Platform HW support capabilities are also checked.
+ * Returns 0 on success and a negative FDT error code on failure.
+ */
+static int stm32mp1_get_opp(u32 cpu_type, ofnode subnode,
+ u32 *freq_khz, u32 *voltage_mv)
+{
+ u32 opp_hw;
+ u64 read_freq_64;
+ u32 read_voltage_32;
+
+ *freq_khz = 0;
+ *voltage_mv = 0;
+
+ opp_hw = ofnode_read_u32_default(subnode, "opp-supported-hw", 0);
+ if (opp_hw)
+ if (!stm32mp1_supports_opp(opp_hw, cpu_type))
+ return -FDT_ERR_BADVALUE;
+
+ read_freq_64 = ofnode_read_u64_default(subnode, "opp-hz", 0) /
+ 1000ULL;
+ read_voltage_32 = ofnode_read_u32_default(subnode, "opp-microvolt", 0) /
+ 1000U;
+
+ if (!read_voltage_32 || !read_freq_64)
+ return -FDT_ERR_NOTFOUND;
+
+ /* Frequency value expressed in KHz must fit on 32 bits */
+ if (read_freq_64 > U32_MAX)
+ return -FDT_ERR_BADVALUE;
+
+ /* Millivolt value must fit on 16 bits */
+ if (read_voltage_32 > U16_MAX)
+ return -FDT_ERR_BADVALUE;
+
+ *freq_khz = (u32)read_freq_64;
+ *voltage_mv = read_voltage_32;
+
+ return 0;
+}
+
+/*
+ * parses OPP table in DT and finds the parameters for the
+ * highest frequency supported by the HW platform.
+ * Returns 0 on success and a negative FDT error code on failure.
+ */
+int stm32mp1_get_max_opp_freq(struct stm32mp_rcc_priv *priv, u64 *freq_hz)
+{
+ ofnode node, subnode;
+ int ret;
+ u32 freq = 0U, voltage = 0U;
+ u32 cpu_type = get_cpu_type();
+
+ node = ofnode_by_compatible(ofnode_null(), "operating-points-v2");
+ if (!ofnode_valid(node))
+ return -FDT_ERR_NOTFOUND;
+
+ ofnode_for_each_subnode(subnode, node) {
+ unsigned int read_freq;
+ unsigned int read_voltage;
+
+ ret = stm32mp1_get_opp(cpu_type, subnode,
+ &read_freq, &read_voltage);
+ if (ret)
+ continue;
+
+ if (read_freq > freq) {
+ freq = read_freq;
+ voltage = read_voltage;
+ }
+ }
+
+ if (!freq || !voltage)
+ return -FDT_ERR_NOTFOUND;
+
+ *freq_hz = (u64)1000U * freq;
+ board_vddcore_init(voltage);
+
+ return 0;
+}
+
+static int stm32mp1_pll1_opp(struct stm32mp_rcc_priv *priv, int clksrc,
+ u32 *pllcfg, u32 *fracv)
+{
+ u32 post_divm;
+ u32 input_freq;
+ u64 output_freq;
+ u64 freq;
+ u64 vco;
+ u32 divm, divn, divp, frac;
+ int i, ret;
+ u32 diff;
+ u32 best_diff = U32_MAX;
+
+ /* PLL1 is 2000 */
+ const u32 DIVN_MAX = stm32mp1_pll[PLL_2000].divn_max;
+ const u32 POST_DIVM_MIN = stm32mp1_pll[PLL_2000].refclk_min * 1000000U;
+ const u32 POST_DIVM_MAX = stm32mp1_pll[PLL_2000].refclk_max * 1000000U;
+
+ ret = stm32mp1_get_max_opp_freq(priv, &output_freq);
+ if (ret) {
+ log_debug("PLL1 OPP configuration not found (%d).\n", ret);
+ return ret;
+ }
+
+ switch (clksrc) {
+ case CLK_PLL12_HSI:
+ input_freq = stm32mp1_clk_get_fixed(priv, _HSI);
+ break;
+ case CLK_PLL12_HSE:
+ input_freq = stm32mp1_clk_get_fixed(priv, _HSE);
+ break;
+ default:
+ return -EINTR;
+ }
+
+ /* Following parameters have always the same value */
+ pllcfg[PLLCFG_Q] = 0;
+ pllcfg[PLLCFG_R] = 0;
+ pllcfg[PLLCFG_O] = PQR(1, 1, 1);
+
+ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) {
+ post_divm = (u32)(input_freq / (divm + 1));
+ if (post_divm < POST_DIVM_MIN || post_divm > POST_DIVM_MAX)
+ continue;
+
+ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) {
+ freq = output_freq * (divm + 1) * (divp + 1);
+ divn = (u32)((freq / input_freq) - 1);
+ if (divn < DIVN_MIN || divn > DIVN_MAX)
+ continue;
+
+ frac = (u32)(((freq * FRAC_MAX) / input_freq) -
+ ((divn + 1) * FRAC_MAX));
+ /* 2 loops to refine the fractional part */
+ for (i = 2; i != 0; i--) {
+ if (frac > FRAC_MAX)
+ break;
+
+ vco = (post_divm * (divn + 1)) +
+ ((post_divm * (u64)frac) /
+ FRAC_MAX);
+ if (vco < (PLL2000_VCO_MIN / 2) ||
+ vco > (PLL2000_VCO_MAX / 2)) {
+ frac++;
+ continue;
+ }
+ freq = vco / (divp + 1);
+ if (output_freq < freq)
+ diff = (u32)(freq - output_freq);
+ else
+ diff = (u32)(output_freq - freq);
+ if (diff < best_diff) {
+ pllcfg[PLLCFG_M] = divm;
+ pllcfg[PLLCFG_N] = divn;
+ pllcfg[PLLCFG_P] = divp;
+ *fracv = frac;
+
+ if (diff == 0) {
+ return 0;
+ }
+
+ best_diff = diff;
+ }
+ frac++;
+ }
+ }
+ }
+
+ if (best_diff == U32_MAX)
+ return -1;
+
+ return 0;
+}
+
+static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset,
+ u32 mask_on)
+{
+ u32 address = rcc + offset;
+
+ if (enable)
+ setbits_le32(address, mask_on);
+ else
+ clrbits_le32(address, mask_on);
+}
+
+static void stm32mp1_hs_ocs_set(int enable, fdt_addr_t rcc, u32 mask_on)
+{
+ writel(mask_on, rcc + (enable ? RCC_OCENSETR : RCC_OCENCLRR));
+}
+
+static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset,
+ u32 mask_rdy)
+{
+ u32 mask_test = 0;
+ u32 address = rcc + offset;
+ u32 val;
+ int ret;
+
+ if (enable)
+ mask_test = mask_rdy;
+
+ ret = readl_poll_timeout(address, val,
+ (val & mask_rdy) == mask_test,
+ TIMEOUT_1S);
+
+ if (ret)
+ log_err("OSC %x @ %x timeout for enable=%d : 0x%x\n",
+ mask_rdy, address, enable, readl(address));
+
+ return ret;
+}
+
+static void stm32mp1_lse_enable(fdt_addr_t rcc, int bypass, int digbyp,
+ u32 lsedrv)
+{
+ u32 value;
+
+ if (digbyp)
+ setbits_le32(rcc + RCC_BDCR, RCC_BDCR_DIGBYP);
+
+ if (bypass || digbyp)
+ setbits_le32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP);
+
+ /*
+ * warning: not recommended to switch directly from "high drive"
+ * to "medium low drive", and vice-versa.
+ */
+ value = (readl(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK)
+ >> RCC_BDCR_LSEDRV_SHIFT;
+
+ while (value != lsedrv) {
+ if (value > lsedrv)
+ value--;
+ else
+ value++;
+
+ clrsetbits_le32(rcc + RCC_BDCR,
+ RCC_BDCR_LSEDRV_MASK,
+ value << RCC_BDCR_LSEDRV_SHIFT);
+ }
+
+ stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON);
+}
+
+static void stm32mp1_lse_wait(fdt_addr_t rcc)
+{
+ stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY);
+}
+
+static void stm32mp1_lsi_set(fdt_addr_t rcc, int enable)
+{
+ stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION);
+ stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY);
+}
+
+static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int digbyp, int css)
+{
+ if (digbyp)
+ writel(RCC_OCENR_DIGBYP, rcc + RCC_OCENSETR);
+ if (bypass || digbyp)
+ writel(RCC_OCENR_HSEBYP, rcc + RCC_OCENSETR);
+
+ stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON);
+ stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY);
+
+ if (css)
+ writel(RCC_OCENR_HSECSSON, rcc + RCC_OCENSETR);
+}
+
+static void stm32mp1_csi_set(fdt_addr_t rcc, int enable)
+{
+ stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_CSION);
+ stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY);
+}
+
+static void stm32mp1_hsi_set(fdt_addr_t rcc, int enable)
+{
+ stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION);
+ stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY);
+}
+
+static int stm32mp1_set_hsidiv(fdt_addr_t rcc, u8 hsidiv)
+{
+ u32 address = rcc + RCC_OCRDYR;
+ u32 val;
+ int ret;
+
+ clrsetbits_le32(rcc + RCC_HSICFGR,
+ RCC_HSICFGR_HSIDIV_MASK,
+ RCC_HSICFGR_HSIDIV_MASK & hsidiv);
+
+ ret = readl_poll_timeout(address, val,
+ val & RCC_OCRDYR_HSIDIVRDY,
+ TIMEOUT_200MS);
+ if (ret)
+ log_err("HSIDIV failed @ 0x%x: 0x%x\n",
+ address, readl(address));
+
+ return ret;
+}
+
+static int stm32mp1_hsidiv(fdt_addr_t rcc, ulong hsifreq)
+{
+ u8 hsidiv;
+ u32 hsidivfreq = MAX_HSI_HZ;
+
+ for (hsidiv = 0; hsidiv < 4; hsidiv++,
+ hsidivfreq = hsidivfreq / 2)
+ if (hsidivfreq == hsifreq)
+ break;
+
+ if (hsidiv == 4) {
+ log_err("hsi frequency invalid");
+ return -1;
+ }
+
+ if (hsidiv > 0)
+ return stm32mp1_set_hsidiv(rcc, hsidiv);
+
+ return 0;
+}
+
+static void pll_start(struct stm32mp_rcc_priv *priv, int pll_id)
+{
+ clrsetbits_le32((u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr,
+ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
+ RCC_PLLNCR_DIVREN,
+ RCC_PLLNCR_PLLON);
+}
+
+static int pll_output(struct stm32mp_rcc_priv *priv, int pll_id, int output)
+{
+ u32 pllxcr = (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr;
+ u32 val;
+ int ret;
+
+ ret = readl_poll_timeout(pllxcr, val, val & RCC_PLLNCR_PLLRDY,
+ TIMEOUT_200MS);
+
+ if (ret) {
+ log_err("PLL%d start failed @ 0x%x: 0x%x\n",
+ pll_id, pllxcr, readl(pllxcr));
+ return ret;
+ }
+
+ /* start the requested output */
+ setbits_le32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
+
+ return 0;
+}
+
+static int pll_stop(struct stm32mp_rcc_priv *priv, int pll_id)
+{
+ u32 pllxcr = (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr;
+ u32 val;
+
+ /* stop all output */
+ clrbits_le32(pllxcr,
+ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN);
+
+ /* stop PLL */
+ clrbits_le32(pllxcr, RCC_PLLNCR_PLLON);
+
+ /* wait PLL stopped */
+ return readl_poll_timeout(pllxcr, val, (val & RCC_PLLNCR_PLLRDY) == 0,
+ TIMEOUT_200MS);
+}
+
+static void pll_config_output(struct stm32mp_rcc_priv *priv,
+ int pll_id, u32 *pllcfg)
+{
+ fdt_addr_t rcc = (u32)(priv->base);
+ u32 value;
+
+ value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT)
+ & RCC_PLLNCFGR2_DIVP_MASK;
+ value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT)
+ & RCC_PLLNCFGR2_DIVQ_MASK;
+ value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT)
+ & RCC_PLLNCFGR2_DIVR_MASK;
+ writel(value, rcc + stm32mp1_clk_pll[pll_id].pllxcfgr2);
+}
+
+static int pll_config(struct stm32mp_rcc_priv *priv, int pll_id,
+ u32 *pllcfg, u32 fracv)
+{
+ fdt_addr_t rcc = (u32)(priv->base);
+ enum stm32mp1_plltype type = stm32mp1_clk_pll[pll_id].plltype;
+ int src;
+ ulong refclk;
+ u8 ifrge = 0;
+ u32 value;
+
+ src = readl((u32)(priv->base) + stm32mp1_clk_pll[pll_id].rckxselr) & RCC_SELR_SRC_MASK;
+ refclk = stm32mp1_clk_get_fixed(priv, stm32mp1_clk_pll[pll_id].refclk[src]) /
+ (pllcfg[PLLCFG_M] + 1);
+
+ if (refclk < (stm32mp1_pll[type].refclk_min * 1000000) ||
+ refclk > (stm32mp1_pll[type].refclk_max * 1000000)) {
+ log_err("invalid refclk = %x\n", (u32)refclk);
+ return -EINVAL;
+ }
+
+
+ if (type == PLL_800 && refclk >= 8000000)
+ ifrge = 1;
+
+ value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT)
+ & RCC_PLLNCFGR1_DIVN_MASK;
+ value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT)
+ & RCC_PLLNCFGR1_DIVM_MASK;
+ value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT)
+ & RCC_PLLNCFGR1_IFRGE_MASK;
+ writel(value, rcc + stm32mp1_clk_pll[pll_id].pllxcfgr1);
+
+ /* fractional configuration: load sigma-delta modulator (SDM) */
+
+ /* Write into FRACV the new fractional value , and FRACLE to 0 */
+ writel(fracv << RCC_PLLNFRACR_FRACV_SHIFT,
+ rcc + stm32mp1_clk_pll[pll_id].pllxfracr);
+
+ /* Write FRACLE to 1 : FRACV value is loaded into the SDM */
+ setbits_le32(rcc + stm32mp1_clk_pll[pll_id].pllxfracr,
+ RCC_PLLNFRACR_FRACLE);
+
+ pll_config_output(priv, pll_id, pllcfg);
+
+ return 0;
+}
+
+static void pll_csg(struct stm32mp_rcc_priv *priv, int pll_id, u32 *csg)
+{
+ u32 pllxcsg;
+
+ pllxcsg = ((csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
+ RCC_PLLNCSGR_MOD_PER_MASK) |
+ ((csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
+ RCC_PLLNCSGR_INC_STEP_MASK) |
+ ((csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
+ RCC_PLLNCSGR_SSCG_MODE_MASK);
+
+ writel(pllxcsg, (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcsgr);
+
+ setbits_le32((u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL);
+}
+
+static ulong pll_get_fref_ck(struct stm32mp_rcc_priv *priv,
+ int pll_id)
+{
+ u32 selr;
+ int src;
+
+ /* Get current refclk */
+ selr = readl(priv->base + stm32mp1_clk_pll[pll_id].rckxselr);
+ src = selr & RCC_SELR_SRC_MASK;
+
+ return stm32mp1_clk_get_fixed(priv, stm32mp1_clk_pll[pll_id].refclk[src]);
+}
+
+static __maybe_unused int pll_set_rate(struct udevice *dev,
+ int pll_id,
+ int div_id,
+ unsigned long clk_rate)
+{
+ struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
+ unsigned int pllcfg[PLLCFG_NB];
+ ofnode plloff;
+ char name[12];
+ enum stm32mp1_plltype type = stm32mp1_clk_pll[pll_id].plltype;
+ int divm, divn, divy;
+ int ret;
+ ulong fck_ref;
+ u32 fracv;
+ u64 value;
+
+ if (div_id > _DIV_NB)
+ return -EINVAL;
+
+ sprintf(name, "st,pll@%d", pll_id);
+ plloff = dev_read_subnode(dev, name);
+ if (!ofnode_valid(plloff))
+ return -FDT_ERR_NOTFOUND;
+
+ ret = ofnode_read_u32_array(plloff, "cfg",
+ pllcfg, PLLCFG_NB);
+ if (ret < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ fck_ref = pll_get_fref_ck(priv, pll_id);
+
+ divm = pllcfg[PLLCFG_M];
+ /* select output divider = 0: for _DIV_P, 1:_DIV_Q 2:_DIV_R */
+ divy = pllcfg[PLLCFG_P + div_id];
+
+ /* For: PLL1 & PLL2 => VCO is * 2 but ck_pll_y is also / 2
+ * So same final result than PLL2 et 4
+ * with FRACV
+ * Fck_pll_y = Fck_ref * ((DIVN + 1) + FRACV / 2^13)
+ * / (DIVy + 1) * (DIVM + 1)
+ * value = (DIVN + 1) * 2^13 + FRACV / 2^13
+ * = Fck_pll_y (DIVy + 1) * (DIVM + 1) * 2^13 / Fck_ref
+ */
+ value = ((u64)clk_rate * (divy + 1) * (divm + 1)) << 13;
+ value = lldiv(value, fck_ref);
+
+ divn = (value >> 13) - 1;
+ if (divn < DIVN_MIN ||
+ divn > stm32mp1_pll[type].divn_max) {
+ dev_err(dev, "divn invalid = %d", divn);
+ return -EINVAL;
+ }
+ fracv = value - ((divn + 1) << 13);
+ pllcfg[PLLCFG_N] = divn;
+
+ /* reconfigure PLL */
+ pll_stop(priv, pll_id);
+ pll_config(priv, pll_id, pllcfg, fracv);
+ pll_start(priv, pll_id);
+ pll_output(priv, pll_id, pllcfg[PLLCFG_O]);
+
+ return 0;
+}
+
+static int set_clksrc(struct stm32mp_rcc_priv *priv, unsigned int clksrc)
+{
+ u32 address = (u32)(priv->base);
+ u32 mux = (clksrc & MUX_ID_MASK) >> MUX_ID_SHIFT;
+ u32 val;
+ int ret;
+
+ /* List of relevant muxes to keep the size down */
+ if (mux == MUX_PLL12)
+ address += RCC_RCK12SELR;
+ else if (mux == MUX_PLL3)
+ address += RCC_RCK3SELR;
+ else if (mux == MUX_PLL4)
+ address += RCC_RCK4SELR;
+ else if (mux == MUX_MPU)
+ address += RCC_MPCKSELR;
+ else if (mux == MUX_AXI)
+ address += RCC_ASSCKSELR;
+ else if (mux == MUX_MLAHB)
+ address += RCC_MSSCKSELR;
+ else if (mux == MUX_CKPER)
+ address += RCC_CPERCKSELR;
+ else
+ return -EINVAL;
+
+ clrsetbits_le32(address, RCC_SELR_SRC_MASK, clksrc & RCC_SELR_SRC_MASK);
+ ret = readl_poll_timeout(address, val, val & RCC_SELR_SRCRDY,
+ TIMEOUT_200MS);
+ if (ret)
+ log_err("CLKSRC %x start failed @ 0x%x: 0x%x\n",
+ clksrc, address, readl(address));
+
+ return ret;
+}
+
+static void stgen_config(struct stm32mp_rcc_priv *priv)
+{
+ u32 stgenc, cntfid0;
+ ulong rate = clk_get_rate(&priv->osc_clk[_HSI]);
+ stgenc = STM32_STGEN_BASE;
+ cntfid0 = readl(stgenc + STGENC_CNTFID0);
+
+ if (cntfid0 != rate) {
+ u64 counter;
+
+ log_debug("System Generic Counter (STGEN) update\n");
+ clrbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN);
+ counter = (u64)readl(stgenc + STGENC_CNTCVL);
+ counter |= ((u64)(readl(stgenc + STGENC_CNTCVU))) << 32;
+ counter = lldiv(counter * (u64)rate, cntfid0);
+ writel((u32)counter, stgenc + STGENC_CNTCVL);
+ writel((u32)(counter >> 32), stgenc + STGENC_CNTCVU);
+ writel(rate, stgenc + STGENC_CNTFID0);
+ setbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN);
+
+ __asm__ volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (rate));
+
+ /* need to update gd->arch.timer_rate_hz with new frequency */
+ timer_init();
+ }
+}
+
+static int set_clkdiv(unsigned int clkdiv, u32 address)
+{
+ u32 val;
+ int ret;
+
+
+ clrsetbits_le32(address, RCC_DIVR_DIV_MASK, clkdiv & RCC_DIVR_DIV_MASK);
+ ret = readl_poll_timeout(address, val, val & RCC_DIVR_DIVRDY,
+ TIMEOUT_200MS);
+ if (ret)
+ log_err("CLKDIV %x start failed @ 0x%x: 0x%x\n",
+ clkdiv, address, readl(address));
+
+ return ret;
+}
+
+static void set_rtcsrc(struct stm32mp_rcc_priv *priv,
+ unsigned int clksrc,
+ int lse_css)
+{
+ u32 address = (u32)(priv->base) + RCC_BDCR;
+
+ if (readl(address) & RCC_BDCR_RTCCKEN)
+ goto skip_rtc;
+
+ if (clksrc == CLK_RTC_DISABLED)
+ goto skip_rtc;
+
+ clrsetbits_le32(address,
+ RCC_BDCR_RTCSRC_MASK,
+ clksrc << RCC_BDCR_RTCSRC_SHIFT);
+
+ setbits_le32(address, RCC_BDCR_RTCCKEN);
+
+skip_rtc:
+ if (lse_css)
+ setbits_le32(address, RCC_BDCR_LSECSSON);
+}
+
+static void pkcs_config(struct stm32mp_rcc_priv *priv, u32 pkcs)
+{
+ u32 mux = (pkcs & MUX_ID_MASK) >> MUX_ID_SHIFT;
+ u32 address = (u32)(priv->base) + stm32mp13_muxes[mux].reg_off;
+ u32 mask = (BIT(stm32mp13_muxes[mux].width) - 1) << stm32mp13_muxes[mux].shift;
+ u32 value = (pkcs << stm32mp13_muxes[mux].shift) & mask;
+
+ clrsetbits_le32(address, mask, value);
+}
+
+static int stm32mp1_clktree(struct udevice *dev)
+{
+ struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
+ fdt_addr_t rcc = (u32)(priv->base);
+ unsigned int clksrc[CLKSRC_NB];
+ unsigned int clkdiv[CLKDIV_NB];
+ unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
+ unsigned int pllfracv[_PLL_NB];
+ unsigned int pllcsg[_PLL_NB][PLLCSG_NB];
+ bool pllcfg_valid[_PLL_NB];
+ bool pllcsg_set[_PLL_NB];
+ int ret;
+ int i, len;
+ int lse_css = 0;
+ const u32 *pkcs_cell;
+
+ /* check mandatory field */
+ ret = dev_read_u32_array(dev, "st,clksrc", clksrc, CLKSRC_NB);
+ if (ret < 0) {
+ dev_dbg(dev, "field st,clksrc invalid: error %d\n", ret);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ ret = dev_read_u32_array(dev, "st,clkdiv", clkdiv, CLKDIV_NB);
+ if (ret < 0) {
+ dev_dbg(dev, "field st,clkdiv invalid: error %d\n", ret);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ /* check mandatory field in each pll */
+ for (i = 0; i < _PLL_NB; i++) {
+ char name[12];
+ ofnode node;
+
+ sprintf(name, "st,pll@%d", i);
+ node = dev_read_subnode(dev, name);
+ pllcfg_valid[i] = ofnode_valid(node);
+ pllcsg_set[i] = false;
+ if (pllcfg_valid[i]) {
+ dev_dbg(dev, "DT for PLL %d @ %s\n", i, name);
+ ret = ofnode_read_u32_array(node, "cfg",
+ pllcfg[i], PLLCFG_NB);
+ if (ret < 0) {
+ dev_dbg(dev, "field cfg invalid: error %d\n", ret);
+ return -FDT_ERR_NOTFOUND;
+ }
+ pllfracv[i] = ofnode_read_u32_default(node, "frac", 0);
+
+ ret = ofnode_read_u32_array(node, "csg", pllcsg[i],
+ PLLCSG_NB);
+ if (!ret) {
+ pllcsg_set[i] = true;
+ } else if (ret != -FDT_ERR_NOTFOUND) {
+ dev_dbg(dev, "invalid csg node for pll@%d res=%d\n",
+ i, ret);
+ return ret;
+ }
+ } else if (i == _PLL1) {
+ /* use OPP for PLL1 for A7 CPU */
+ dev_dbg(dev, "DT for PLL %d with OPP\n", i);
+ ret = stm32mp1_pll1_opp(priv,
+ clksrc[CLKSRC_PLL12],
+ pllcfg[i],
+ &pllfracv[i]);
+ if (ret) {
+ dev_dbg(dev, "PLL %d with OPP error = %d\n", i, ret);
+ return ret;
+ }
+ pllcfg_valid[i] = true;
+ }
+ }
+
+ dev_dbg(dev, "switch ON osillator\n");
+ /*
+ * switch ON oscillator found in device-tree,
+ * HSI already ON after bootrom
+ */
+ if (clk_valid(&priv->osc_clk[_LSI]))
+ stm32mp1_lsi_set(rcc, 1);
+
+ if (clk_valid(&priv->osc_clk[_LSE])) {
+ int bypass, digbyp;
+ u32 lsedrv;
+ struct udevice *dev = priv->osc_clk[_LSE].dev;
+
+ bypass = dev_read_bool(dev, "st,bypass");
+ digbyp = dev_read_bool(dev, "st,digbypass");
+ lse_css = dev_read_bool(dev, "st,css");
+ lsedrv = dev_read_u32_default(dev, "st,drive",
+ LSEDRV_MEDIUM_HIGH);
+
+ stm32mp1_lse_enable(rcc, bypass, digbyp, lsedrv);
+ }
+
+
+ if (clk_valid(&priv->osc_clk[_HSE])) {
+ int bypass, digbyp, css;
+ struct udevice *dev = priv->osc_clk[_HSE].dev;
+
+ bypass = dev_read_bool(dev, "st,bypass");
+ digbyp = dev_read_bool(dev, "st,digbypass");
+ css = dev_read_bool(dev, "st,css");
+
+ stm32mp1_hse_enable(rcc, bypass, digbyp, css);
+ }
+
+ /* CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
+ * => switch on CSI even if node is not present in device tree
+ */
+ stm32mp1_csi_set(rcc, 1);
+
+ /* come back to HSI */
+ dev_dbg(dev, "come back to HSI\n");
+ set_clksrc(priv, CLK_MPU_HSI);
+ set_clksrc(priv, CLK_AXI_HSI);
+ set_clksrc(priv, CLK_MLAHBS_HSI);
+
+ dev_dbg(dev, "pll stop\n");
+ for (i = 0; i < _PLL_NB; i++)
+ pll_stop(priv, i);
+
+ /* configure HSIDIV */
+ dev_dbg(dev, "configure HSIDIV\n");
+ if (clk_valid(&priv->osc_clk[_HSI])) {
+ stm32mp1_hsidiv(rcc, clk_get_rate(&priv->osc_clk[_HSI]));
+ stgen_config(priv);
+ }
+
+ /* select DIV */
+ dev_dbg(dev, "select DIV\n");
+ /* no ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
+ set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB6], rcc + RCC_APB6DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR);
+ set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR);
+
+ /* no ready bit for RTC */
+ writel(clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK, rcc + RCC_RTCDIVR);
+
+ /* configure PLLs source */
+ dev_dbg(dev, "configure PLLs source\n");
+ set_clksrc(priv, clksrc[CLKSRC_PLL12]);
+ set_clksrc(priv, clksrc[CLKSRC_PLL3]);
+ set_clksrc(priv, clksrc[CLKSRC_PLL4]);
+
+ /* configure and start PLLs */
+ dev_dbg(dev, "configure PLLs\n");
+ for (i = 0; i < _PLL_NB; i++) {
+ if (!pllcfg_valid[i])
+ continue;
+ dev_dbg(dev, "configure PLL %d\n", i);
+ pll_config(priv, i, pllcfg[i], pllfracv[i]);
+ if (pllcsg_set[i])
+ pll_csg(priv, i, pllcsg[i]);
+ pll_start(priv, i);
+ }
+
+ /* wait and start PLLs ouptut when ready */
+ for (i = 0; i < _PLL_NB; i++) {
+ if (!pllcfg_valid[i])
+ continue;
+ dev_dbg(dev, "output PLL %d\n", i);
+ pll_output(priv, i, pllcfg[i][PLLCFG_O]);
+ }
+
+ /* wait LSE ready before to use it */
+ if (clk_valid(&priv->osc_clk[_LSE]))
+ stm32mp1_lse_wait(rcc);
+
+ /* configure with expected clock source */
+ dev_dbg(dev, "CLKSRC\n");
+ set_clksrc(priv, clksrc[CLKSRC_MPU]);
+ set_clksrc(priv, clksrc[CLKSRC_AXI]);
+ set_clksrc(priv, clksrc[CLKSRC_MLAHB]);
+ set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css);
+
+ /* configure PKCK */
+ dev_dbg(dev, "PKCK\n");
+ pkcs_cell = dev_read_prop(dev, "st,pkcs", &len);
+ if (pkcs_cell) {
+ bool ckper_disabled = false;
+
+ for (i = 0; i < len / sizeof(u32); i++) {
+ u32 pkcs = (u32)fdt32_to_cpu(pkcs_cell[i]);
+
+ if (pkcs == CLK_CKPER_DISABLED) {
+ ckper_disabled = true;
+ continue;
+ }
+ pkcs_config(priv, pkcs);
+ }
+ /* CKPER is source for some peripheral clock
+ * (FMC-NAND / QPSI-NOR) and switching source is allowed
+ * only if previous clock is still ON
+ * => deactivated CKPER only after switching clock
+ */
+ if (ckper_disabled)
+ pkcs_config(priv, CLK_CKPER_DISABLED);
+ }
+
+ /* STGEN clock source can change with CLK_STGEN_XXX */
+ stgen_config(priv);
+
+ dev_dbg(dev, "oscillator off\n");
+ /* switch OFF HSI if not found in device-tree */
+ if (!clk_valid(&priv->osc_clk[_HSI]))
+ stm32mp1_hsi_set(rcc, 0);
+
+ /* Software Self-Refresh mode (SSR) during DDR initilialization */
+ clrsetbits_le32((u32)(priv->base) + RCC_DDRITFCR,
+ RCC_DDRITFCR_DDRCKMOD_MASK,
+ RCC_DDRITFCR_DDRCKMOD_SSR <<
+ RCC_DDRITFCR_DDRCKMOD_SHIFT);
+
+ return 0;
+}
+#endif
+
+static int stm32mp1_osc_init(struct udevice *dev)
+{
+ struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
+ fdt_addr_t base = dev_read_addr(dev->parent);
+ struct clk *ck;
+ int i;
+
+ const char *name[NB_OSC] = {
+ [_LSI] = "lsi",
+ [_LSE] = "lse",
+ [_HSI] = "hsi",
+ [_HSE] = "hse",
+ [_CSI] = "csi",
+ [_I2S_CKIN] = "i2s_ckin",
+ };
+
+ const struct {
+ const char *name;
+ const int rate;
+ } fixed_clk[] = {
+ { "bsec", 66625000 },
+ { "ck_axi", 266500000 },
+ { "ck_mlahb", 200000000 },
+ { "ck_mpu", 1000000000 },
+ { "ck_per", 24000000 },
+ { "ck_rtc", 32768 },
+ { "clk-hse-div2", 12000000 },
+ { "pclk1", 100000000 },
+ { "pclk2", 100000000 },
+ { "pclk3", 100000000 },
+ { "pclk4", 133250000 },
+ { "pclk5", 66625000 },
+ { "pclk6", 100000000 },
+ { "pll2_q", 266500000 },
+ { "pll2_r", 533000000 },
+ { "pll3_p", 200000000 },
+ { "pll3_q", 150000000 },
+ { "pll3_r", 200000000 },
+ { "pll4_p", 125000000 },
+ { "pll4_q", 83333333 },
+ { "pll4_r", 75000000 },
+ { "rtcapb", 66625000 },
+ { "timg1_ck", 200000000 },
+ { "timg2_ck", 200000000 },
+ { "timg3_ck", 200000000 },
+ };
+
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->base = (void __iomem *)base;
+
+ for (i = 0; i < NB_OSC; i++) {
+ if (clk_get_by_name(dev, name[i], &priv->osc_clk[i]))
+ dev_dbg(dev, "No source clock \"%s\"\n", name[i]);
+ else
+ dev_dbg(dev, "%s clock rate: %luHz\n",
+ name[i], clk_get_rate(&priv->osc_clk[i]));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(fixed_clk); i++) {
+ ck = clk_register_fixed_rate(NULL, fixed_clk[i].name, fixed_clk[i].rate);
+ if (!ck)
+ dev_dbg(dev, "Cannot register fixed clock \"%s\"\n", fixed_clk[i].name);
+ }
+
+ return 0;
+}
+#endif
+
static int stm32mp1_clk_probe(struct udevice *dev)
{
- struct udevice *scmi;
int err;
+#ifdef CONFIG_TFABOOT
+ struct udevice *scmi;
+
/* force SCMI probe to register all SCMI clocks */
uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi);
+#else
+ err = stm32mp1_osc_init(dev);
+ if (err)
+ return err;
+
+#if defined(CONFIG_XPL_BUILD)
+ /* clock tree init is done only one time, before relocation */
+ if (!(gd->flags & GD_FLG_RELOC))
+ err = stm32mp1_clktree(dev);
+ if (err)
+ dev_err(dev, "clock tree initialization failed (%d)\n", err);
+#endif
+#endif
err = stm32_rcc_init(dev, &stm32mp13_data);
if (err)
@@ -815,6 +2012,7 @@ static int stm32mp1_clk_probe(struct udevice *dev)
/* DDRPHYC father */
gd->mem_clk = clk_stm32_get_rate_by_name("pll2_r");
+#ifndef CONFIG_XPL_BUILD
if (IS_ENABLED(CONFIG_DISPLAY_CPUINFO)) {
if (gd->flags & GD_FLG_RELOC) {
char buf[32];
@@ -827,6 +2025,7 @@ static int stm32mp1_clk_probe(struct udevice *dev)
log_info("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk));
}
}
+#endif
return 0;
}
diff --git a/drivers/clk/stm32/clk-stm32mp25.c b/drivers/clk/stm32/clk-stm32mp25.c
new file mode 100644
index 00000000000..18c0b1cb867
--- /dev/null
+++ b/drivers/clk/stm32/clk-stm32mp25.c
@@ -0,0 +1,782 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/st,stm32mp25-rcc.h>
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <mach/rif.h>
+
+#include "clk-stm32-core.h"
+#include "stm32mp25_rcc.h"
+
+/* Clock security definition */
+#define SECF_NONE -1
+
+#define RCC_REG_SIZE 32
+#define RCC_SECCFGR(x) (((x) / RCC_REG_SIZE) * 0x4 + RCC_SECCFGR0)
+#define RCC_CIDCFGR(x) ((x) * 0x8 + RCC_R0CIDCFGR)
+#define RCC_SEMCR(x) ((x) * 0x8 + RCC_R0SEMCR)
+#define RCC_CID1 1
+
+/* Register: RIFSC_CIDCFGR */
+#define RCC_CIDCFGR_CFEN BIT(0)
+#define RCC_CIDCFGR_SEM_EN BIT(1)
+#define RCC_CIDCFGR_SEMWLC1_EN BIT(17)
+#define RCC_CIDCFGR_SCID_MASK GENMASK(6, 4)
+
+/* Register: RIFSC_SEMCR */
+#define RCC_SEMCR_SEMCID_MASK GENMASK(6, 4)
+
+#define STM32MP25_RIFRCC_DBG_ID 73
+#define STM32MP25_RIFRCC_IS2M_ID 107
+#define STM32MP25_RIFRCC_MCO1_ID 108
+#define STM32MP25_RIFRCC_MCO2_ID 109
+#define STM32MP25_RIFRCC_OSPI1_ID 110
+#define STM32MP25_RIFRCC_OSPI2_ID 111
+
+#define SEC_RIFSC_FLAG BIT(31)
+#define SEC_RIFRCC(_id) (STM32MP25_RIFRCC_##_id##_ID)
+#define SEC_RIFSC(_id) ((_id) | SEC_RIFSC_FLAG)
+
+static const char * const adc12_src[] = {
+ "ck_flexgen_46", "ck_icn_ls_mcu"
+};
+
+static const char * const adc3_src[] = {
+ "ck_flexgen_47", "ck_icn_ls_mcu", "ck_flexgen_46"
+};
+
+static const char * const usb2phy1_src[] = {
+ "ck_flexgen_57", "hse_div2_ck"
+};
+
+static const char * const usb2phy2_src[] = {
+ "ck_flexgen_58", "hse_div2_ck"
+};
+
+static const char * const usb3pciphy_src[] = {
+ "ck_flexgen_34", "hse_div2_ck"
+};
+
+static const char * const dsiblane_src[] = {
+ "txbyteclk", "ck_ker_ltdc"
+};
+
+static const char * const dsiphy_src[] = {
+ "ck_flexgen_28", "hse_ck"
+};
+
+static const char * const lvdsphy_src[] = {
+ "ck_flexgen_32", "hse_ck"
+};
+
+static const char * const dts_src[] = {
+ "hsi_ck", "hse_ck", "msi_ck"
+};
+
+static const char * const mco1_src[] = {
+ "ck_flexgen_61", "ck_obs0"
+};
+
+static const char * const mco2_src[] = {
+ "ck_flexgen_62", "ck_obs1"
+};
+
+enum enum_mux_cfg {
+ MUX_MCO1,
+ MUX_MCO2,
+ MUX_ADC12,
+ MUX_ADC3,
+ MUX_USB2PHY1,
+ MUX_USB2PHY2,
+ MUX_USB3PCIEPHY,
+ MUX_DSIBLANE,
+ MUX_DSIPHY,
+ MUX_LVDSPHY,
+ MUX_DTS,
+ MUX_NB
+};
+
+#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 stm32mp25_muxes[MUX_NB] = {
+ MUX_CFG(MUX_ADC12, adc12_src, RCC_ADC12CFGR, 12, 1),
+ MUX_CFG(MUX_ADC3, adc3_src, RCC_ADC3CFGR, 12, 2),
+ MUX_CFG(MUX_DSIBLANE, dsiblane_src, RCC_DSICFGR, 12, 1),
+ MUX_CFG(MUX_DSIPHY, dsiphy_src, RCC_DSICFGR, 15, 1),
+ MUX_CFG(MUX_DTS, dts_src, RCC_DTSCFGR, 12, 2),
+ MUX_CFG(MUX_MCO1, mco1_src, RCC_MCO1CFGR, 0, 1),
+ MUX_CFG(MUX_MCO2, mco2_src, RCC_MCO2CFGR, 0, 1),
+ MUX_CFG(MUX_LVDSPHY, lvdsphy_src, RCC_LVDSCFGR, 15, 1),
+ MUX_CFG(MUX_USB2PHY1, usb2phy1_src, RCC_USB2PHY1CFGR, 15, 1),
+ MUX_CFG(MUX_USB2PHY2, usb2phy2_src, RCC_USB2PHY2CFGR, 15, 1),
+ MUX_CFG(MUX_USB3PCIEPHY, usb3pciphy_src, RCC_USB3PCIEPHYCFGR, 15, 1),
+};
+
+enum enum_gate_cfg {
+ GATE_ADC12,
+ GATE_ADC3,
+ GATE_ADF1,
+ GATE_CCI,
+ GATE_CRC,
+ GATE_CRYP1,
+ GATE_CRYP2,
+ GATE_CSI,
+ GATE_DBG,
+ GATE_DCMIPP,
+ GATE_DSI,
+ GATE_DTS,
+ GATE_ETH1,
+ GATE_ETH1MAC,
+ GATE_ETH1RX,
+ GATE_ETH1STP,
+ GATE_ETH1TX,
+ GATE_ETH2,
+ GATE_ETH2MAC,
+ GATE_ETH2RX,
+ GATE_ETH2STP,
+ GATE_ETH2TX,
+ GATE_ETHSW,
+ GATE_ETHSWMAC,
+ GATE_ETHSWREF,
+ GATE_ETR,
+ GATE_FDCAN,
+ GATE_GPU,
+ GATE_HASH,
+ GATE_HDP,
+ GATE_I2C1,
+ GATE_I2C2,
+ GATE_I2C3,
+ GATE_I2C4,
+ GATE_I2C5,
+ GATE_I2C6,
+ GATE_I2C7,
+ GATE_I2C8,
+ GATE_I3C1,
+ GATE_I3C2,
+ GATE_I3C3,
+ GATE_I3C4,
+ GATE_IS2M,
+ GATE_IWDG1,
+ GATE_IWDG2,
+ GATE_IWDG3,
+ GATE_IWDG4,
+ GATE_IWDG5,
+ GATE_LPTIM1,
+ GATE_LPTIM2,
+ GATE_LPTIM3,
+ GATE_LPTIM4,
+ GATE_LPTIM5,
+ GATE_LPUART1,
+ GATE_LTDC,
+ GATE_LVDS,
+ GATE_MCO1,
+ GATE_MCO2,
+ GATE_MDF1,
+ GATE_OSPI1,
+ GATE_OSPI2,
+ GATE_OSPIIOM,
+ GATE_PCIE,
+ GATE_PKA,
+ GATE_RNG,
+ GATE_SAES,
+ GATE_SAI1,
+ GATE_SAI2,
+ GATE_SAI3,
+ GATE_SAI4,
+ GATE_SDMMC1,
+ GATE_SDMMC2,
+ GATE_SDMMC3,
+ GATE_SERC,
+ GATE_SPDIFRX,
+ GATE_SPI1,
+ GATE_SPI2,
+ GATE_SPI3,
+ GATE_SPI4,
+ GATE_SPI5,
+ GATE_SPI6,
+ GATE_SPI7,
+ GATE_SPI8,
+ GATE_STGEN,
+ GATE_STM500,
+ GATE_TIM1,
+ GATE_TIM2,
+ GATE_TIM3,
+ GATE_TIM4,
+ GATE_TIM5,
+ GATE_TIM6,
+ GATE_TIM7,
+ GATE_TIM8,
+ GATE_TIM10,
+ GATE_TIM11,
+ GATE_TIM12,
+ GATE_TIM13,
+ GATE_TIM14,
+ GATE_TIM15,
+ GATE_TIM16,
+ GATE_TIM17,
+ GATE_TIM20,
+ GATE_TRACE,
+ GATE_UART4,
+ GATE_UART5,
+ GATE_UART7,
+ GATE_UART8,
+ GATE_UART9,
+ GATE_USART1,
+ GATE_USART2,
+ GATE_USART3,
+ GATE_USART6,
+ GATE_USBH,
+ GATE_USB2PHY1,
+ GATE_USB2PHY2,
+ GATE_USB3DR,
+ GATE_USB3PCIEPHY,
+ GATE_USBTC,
+ GATE_VDEC,
+ GATE_VENC,
+ GATE_VREF,
+ GATE_WWDG1,
+ GATE_WWDG2,
+ GATE_NB
+};
+
+#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 stm32mp25_gates[GATE_NB] = {
+ GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 8, 0),
+ GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 8, 0),
+ GATE_CFG(GATE_OSPI1, RCC_OSPI1CFGR, 1, 0),
+ GATE_CFG(GATE_OSPI2, RCC_OSPI2CFGR, 1, 0),
+ GATE_CFG(GATE_DBG, RCC_DBGCFGR, 8, 0),
+ GATE_CFG(GATE_TRACE, RCC_DBGCFGR, 9, 0),
+ GATE_CFG(GATE_STM500, RCC_STM500CFGR, 1, 0),
+ GATE_CFG(GATE_ETR, RCC_ETRCFGR, 1, 0),
+ GATE_CFG(GATE_IS2M, RCC_IS2MCFGR, 1, 0),
+ GATE_CFG(GATE_TIM1, RCC_TIM1CFGR, 1, 0),
+ GATE_CFG(GATE_TIM2, RCC_TIM2CFGR, 1, 0),
+ GATE_CFG(GATE_TIM3, RCC_TIM3CFGR, 1, 0),
+ GATE_CFG(GATE_TIM4, RCC_TIM4CFGR, 1, 0),
+ GATE_CFG(GATE_TIM5, RCC_TIM5CFGR, 1, 0),
+ GATE_CFG(GATE_TIM6, RCC_TIM6CFGR, 1, 0),
+ GATE_CFG(GATE_TIM7, RCC_TIM7CFGR, 1, 0),
+ GATE_CFG(GATE_TIM8, RCC_TIM8CFGR, 1, 0),
+ GATE_CFG(GATE_TIM10, RCC_TIM10CFGR, 1, 0),
+ GATE_CFG(GATE_TIM11, RCC_TIM11CFGR, 1, 0),
+ GATE_CFG(GATE_TIM12, RCC_TIM12CFGR, 1, 0),
+ GATE_CFG(GATE_TIM13, RCC_TIM13CFGR, 1, 0),
+ GATE_CFG(GATE_TIM14, RCC_TIM14CFGR, 1, 0),
+ GATE_CFG(GATE_TIM15, RCC_TIM15CFGR, 1, 0),
+ GATE_CFG(GATE_TIM16, RCC_TIM16CFGR, 1, 0),
+ GATE_CFG(GATE_TIM17, RCC_TIM17CFGR, 1, 0),
+ GATE_CFG(GATE_TIM20, RCC_TIM20CFGR, 1, 0),
+ GATE_CFG(GATE_LPTIM1, RCC_LPTIM1CFGR, 1, 0),
+ GATE_CFG(GATE_LPTIM2, RCC_LPTIM2CFGR, 1, 0),
+ GATE_CFG(GATE_LPTIM3, RCC_LPTIM3CFGR, 1, 0),
+ GATE_CFG(GATE_LPTIM4, RCC_LPTIM4CFGR, 1, 0),
+ GATE_CFG(GATE_LPTIM5, RCC_LPTIM5CFGR, 1, 0),
+ GATE_CFG(GATE_SPI1, RCC_SPI1CFGR, 1, 0),
+ GATE_CFG(GATE_SPI2, RCC_SPI2CFGR, 1, 0),
+ GATE_CFG(GATE_SPI3, RCC_SPI3CFGR, 1, 0),
+ GATE_CFG(GATE_SPI4, RCC_SPI4CFGR, 1, 0),
+ GATE_CFG(GATE_SPI5, RCC_SPI5CFGR, 1, 0),
+ GATE_CFG(GATE_SPI6, RCC_SPI6CFGR, 1, 0),
+ GATE_CFG(GATE_SPI7, RCC_SPI7CFGR, 1, 0),
+ GATE_CFG(GATE_SPI8, RCC_SPI8CFGR, 1, 0),
+ GATE_CFG(GATE_SPDIFRX, RCC_SPDIFRXCFGR, 1, 0),
+ GATE_CFG(GATE_USART1, RCC_USART1CFGR, 1, 0),
+ GATE_CFG(GATE_USART2, RCC_USART2CFGR, 1, 0),
+ GATE_CFG(GATE_USART3, RCC_USART3CFGR, 1, 0),
+ GATE_CFG(GATE_UART4, RCC_UART4CFGR, 1, 0),
+ GATE_CFG(GATE_UART5, RCC_UART5CFGR, 1, 0),
+ GATE_CFG(GATE_USART6, RCC_USART6CFGR, 1, 0),
+ GATE_CFG(GATE_UART7, RCC_UART7CFGR, 1, 0),
+ GATE_CFG(GATE_UART8, RCC_UART8CFGR, 1, 0),
+ GATE_CFG(GATE_UART9, RCC_UART9CFGR, 1, 0),
+ GATE_CFG(GATE_LPUART1, RCC_LPUART1CFGR, 1, 0),
+ GATE_CFG(GATE_I2C1, RCC_I2C1CFGR, 1, 0),
+ GATE_CFG(GATE_I2C2, RCC_I2C2CFGR, 1, 0),
+ GATE_CFG(GATE_I2C3, RCC_I2C3CFGR, 1, 0),
+ GATE_CFG(GATE_I2C4, RCC_I2C4CFGR, 1, 0),
+ GATE_CFG(GATE_I2C5, RCC_I2C5CFGR, 1, 0),
+ GATE_CFG(GATE_I2C6, RCC_I2C6CFGR, 1, 0),
+ GATE_CFG(GATE_I2C7, RCC_I2C7CFGR, 1, 0),
+ GATE_CFG(GATE_I2C8, RCC_I2C8CFGR, 1, 0),
+ GATE_CFG(GATE_SAI1, RCC_SAI1CFGR, 1, 0),
+ GATE_CFG(GATE_SAI2, RCC_SAI2CFGR, 1, 0),
+ GATE_CFG(GATE_SAI3, RCC_SAI3CFGR, 1, 0),
+ GATE_CFG(GATE_SAI4, RCC_SAI4CFGR, 1, 0),
+ GATE_CFG(GATE_MDF1, RCC_MDF1CFGR, 1, 0),
+ GATE_CFG(GATE_ADF1, RCC_ADF1CFGR, 1, 0),
+ GATE_CFG(GATE_FDCAN, RCC_FDCANCFGR, 1, 0),
+ GATE_CFG(GATE_HDP, RCC_HDPCFGR, 1, 0),
+ GATE_CFG(GATE_ADC12, RCC_ADC12CFGR, 1, 0),
+ GATE_CFG(GATE_ADC3, RCC_ADC3CFGR, 1, 0),
+ GATE_CFG(GATE_ETH1MAC, RCC_ETH1CFGR, 1, 0),
+ GATE_CFG(GATE_ETH1STP, RCC_ETH1CFGR, 4, 0),
+ GATE_CFG(GATE_ETH1, RCC_ETH1CFGR, 5, 0),
+ GATE_CFG(GATE_ETH1TX, RCC_ETH1CFGR, 8, 0),
+ GATE_CFG(GATE_ETH1RX, RCC_ETH1CFGR, 10, 0),
+ GATE_CFG(GATE_ETH2MAC, RCC_ETH2CFGR, 1, 0),
+ GATE_CFG(GATE_ETH2STP, RCC_ETH2CFGR, 4, 0),
+ GATE_CFG(GATE_ETH2, RCC_ETH2CFGR, 5, 0),
+ GATE_CFG(GATE_ETH2TX, RCC_ETH2CFGR, 8, 0),
+ GATE_CFG(GATE_ETH2RX, RCC_ETH2CFGR, 10, 0),
+ GATE_CFG(GATE_USBH, RCC_USBHCFGR, 1, 0),
+ GATE_CFG(GATE_USB2PHY1, RCC_USB2PHY1CFGR, 1, 0),
+ GATE_CFG(GATE_USB2PHY2, RCC_USB2PHY2CFGR, 1, 0),
+ GATE_CFG(GATE_USB3DR, RCC_USB3DRCFGR, 1, 0),
+ GATE_CFG(GATE_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 1, 0),
+ GATE_CFG(GATE_PCIE, RCC_PCIECFGR, 1, 0),
+ GATE_CFG(GATE_USBTC, RCC_UCPDCFGR, 1, 0),
+ GATE_CFG(GATE_ETHSWMAC, RCC_ETHSWCFGR, 1, 0),
+ GATE_CFG(GATE_ETHSW, RCC_ETHSWCFGR, 5, 0),
+ GATE_CFG(GATE_ETHSWREF, RCC_ETHSWCFGR, 21, 0),
+ GATE_CFG(GATE_STGEN, RCC_STGENCFGR, 1, 0),
+ GATE_CFG(GATE_SDMMC1, RCC_SDMMC1CFGR, 1, 0),
+ GATE_CFG(GATE_SDMMC2, RCC_SDMMC2CFGR, 1, 0),
+ GATE_CFG(GATE_SDMMC3, RCC_SDMMC3CFGR, 1, 0),
+ GATE_CFG(GATE_GPU, RCC_GPUCFGR, 1, 0),
+ GATE_CFG(GATE_LTDC, RCC_LTDCCFGR, 1, 0),
+ GATE_CFG(GATE_DSI, RCC_DSICFGR, 1, 0),
+ GATE_CFG(GATE_LVDS, RCC_LVDSCFGR, 1, 0),
+ GATE_CFG(GATE_CSI, RCC_CSICFGR, 1, 0),
+ GATE_CFG(GATE_DCMIPP, RCC_DCMIPPCFGR, 1, 0),
+ GATE_CFG(GATE_CCI, RCC_CCICFGR, 1, 0),
+ GATE_CFG(GATE_VDEC, RCC_VDECCFGR, 1, 0),
+ GATE_CFG(GATE_VENC, RCC_VENCCFGR, 1, 0),
+ GATE_CFG(GATE_RNG, RCC_RNGCFGR, 1, 0),
+ GATE_CFG(GATE_PKA, RCC_PKACFGR, 1, 0),
+ GATE_CFG(GATE_SAES, RCC_SAESCFGR, 1, 0),
+ GATE_CFG(GATE_HASH, RCC_HASHCFGR, 1, 0),
+ GATE_CFG(GATE_CRYP1, RCC_CRYP1CFGR, 1, 0),
+ GATE_CFG(GATE_CRYP2, RCC_CRYP2CFGR, 1, 0),
+ GATE_CFG(GATE_IWDG1, RCC_IWDG1CFGR, 1, 0),
+ GATE_CFG(GATE_IWDG2, RCC_IWDG2CFGR, 1, 0),
+ GATE_CFG(GATE_IWDG3, RCC_IWDG3CFGR, 1, 0),
+ GATE_CFG(GATE_IWDG4, RCC_IWDG4CFGR, 1, 0),
+ GATE_CFG(GATE_IWDG5, RCC_IWDG5CFGR, 1, 0),
+ GATE_CFG(GATE_WWDG1, RCC_WWDG1CFGR, 1, 0),
+ GATE_CFG(GATE_WWDG2, RCC_WWDG2CFGR, 1, 0),
+ GATE_CFG(GATE_VREF, RCC_VREFCFGR, 1, 0),
+ GATE_CFG(GATE_DTS, RCC_DTSCFGR, 1, 0),
+ GATE_CFG(GATE_CRC, RCC_CRCCFGR, 1, 0),
+ GATE_CFG(GATE_SERC, RCC_SERCCFGR, 1, 0),
+ GATE_CFG(GATE_OSPIIOM, RCC_OSPIIOMCFGR, 1, 0),
+ GATE_CFG(GATE_I3C1, RCC_I3C1CFGR, 1, 0),
+ GATE_CFG(GATE_I3C2, RCC_I3C2CFGR, 1, 0),
+ GATE_CFG(GATE_I3C3, RCC_I3C3CFGR, 1, 0),
+ GATE_CFG(GATE_I3C4, RCC_I3C4CFGR, 1, 0),
+};
+
+static int stm32_rcc_get_access(struct udevice *dev, u32 index)
+{
+ fdt_addr_t rcc_base = dev_read_addr(dev->parent);
+ u32 seccfgr, cidcfgr, semcr;
+ int bit, cid;
+
+ bit = index % RCC_REG_SIZE;
+
+ seccfgr = readl(rcc_base + RCC_SECCFGR(index));
+ if (seccfgr & BIT(bit))
+ return -EACCES;
+
+ cidcfgr = readl(rcc_base + RCC_CIDCFGR(index));
+ if (!(cidcfgr & RCC_CIDCFGR_CFEN))
+ /* CID filtering is turned off: access granted */
+ return 0;
+
+ if (!(cidcfgr & RCC_CIDCFGR_SEM_EN)) {
+ /* Static CID mode */
+ cid = FIELD_GET(RCC_CIDCFGR_SCID_MASK, cidcfgr);
+ if (cid != RCC_CID1)
+ return -EACCES;
+ return 0;
+ }
+
+ /* Pass-list with semaphore mode */
+ if (!(cidcfgr & RCC_CIDCFGR_SEMWLC1_EN))
+ return -EACCES;
+
+ semcr = readl(rcc_base + RCC_SEMCR(index));
+
+ cid = FIELD_GET(RCC_SEMCR_SEMCID_MASK, semcr);
+ if (cid != RCC_CID1)
+ return -EACCES;
+
+ return 0;
+}
+
+static int stm32mp25_check_security(struct udevice *dev, void __iomem *base,
+ const struct clock_config *cfg)
+{
+ int ret = 0;
+
+ if (cfg->sec_id != SECF_NONE) {
+ u32 index = (u32)cfg->sec_id;
+
+ if (index & SEC_RIFSC_FLAG)
+ ret = stm32_rifsc_check_access_by_id(dev_ofnode(dev),
+ index & ~SEC_RIFSC_FLAG);
+ else
+ ret = stm32_rcc_get_access(dev, index);
+ }
+
+ return ret;
+}
+#define STM32_COMPOSITE_NODIV(_id, _name, _flags, _sec_id, _gate_id, _mux_id)\
+ STM32_COMPOSITE(_id, _name, _flags, _sec_id, _gate_id, _mux_id, NO_STM32_DIV)
+
+static const struct clock_config stm32mp25_clock_cfg[] = {
+ /* ADC */
+ STM32_GATE(CK_BUS_ADC12, "ck_icn_p_adc12", "ck_icn_ls_mcu", 0, GATE_ADC12,
+ SEC_RIFSC(58)),
+ STM32_COMPOSITE_NODIV(CK_KER_ADC12, "ck_ker_adc12", 0, SEC_RIFSC(58),
+ GATE_ADC12, MUX_ADC12),
+ STM32_GATE(CK_BUS_ADC3, "ck_icn_p_adc3", "ck_icn_ls_mcu", 0, GATE_ADC3, SEC_RIFSC(59)),
+ STM32_COMPOSITE_NODIV(CK_KER_ADC3, "ck_ker_adc3", 0, SEC_RIFSC(59), GATE_ADC3, MUX_ADC3),
+
+ /* ADF */
+ STM32_GATE(CK_BUS_ADF1, "ck_icn_p_adf1", "ck_icn_ls_mcu", 0, GATE_ADF1, SEC_RIFSC(55)),
+ STM32_GATE(CK_KER_ADF1, "ck_ker_adf1", "ck_flexgen_42", 0, GATE_ADF1, SEC_RIFSC(55)),
+
+ /* Camera */
+ /* DCMI */
+ STM32_GATE(CK_BUS_CCI, "ck_icn_p_cci", "ck_icn_ls_mcu", 0, GATE_CCI, SEC_RIFSC(88)),
+
+ /* CSI-HOST */
+ STM32_GATE(CK_BUS_CSI, "ck_icn_p_csi", "ck_icn_apb4", 0, GATE_CSI, SEC_RIFSC(86)),
+ STM32_GATE(CK_KER_CSI, "ck_ker_csi", "ck_flexgen_29", 0, GATE_CSI, SEC_RIFSC(86)),
+ STM32_GATE(CK_KER_CSITXESC, "ck_ker_csitxesc", "ck_flexgen_30", 0, GATE_CSI,
+ SEC_RIFSC(86)),
+
+ /* CSI-PHY */
+ STM32_GATE(CK_KER_CSIPHY, "ck_ker_csiphy", "ck_flexgen_31", 0, GATE_CSI,
+ SEC_RIFSC(86)),
+
+ /* DCMIPP */
+ STM32_GATE(CK_BUS_DCMIPP, "ck_icn_p_dcmipp", "ck_icn_apb4", 0, GATE_DCMIPP,
+ SEC_RIFSC(87)),
+
+ /* CRC */
+ STM32_GATE(CK_BUS_CRC, "ck_icn_p_crc", "ck_icn_ls_mcu", 0, GATE_CRC, SEC_RIFSC(109)),
+
+ /* CRYP */
+ STM32_GATE(CK_BUS_CRYP1, "ck_icn_p_cryp1", "ck_icn_ls_mcu", 0, GATE_CRYP1,
+ SEC_RIFSC(96)),
+ STM32_GATE(CK_BUS_CRYP2, "ck_icn_p_cryp2", "ck_icn_ls_mcu", 0, GATE_CRYP2,
+ SEC_RIFSC(97)),
+
+ /* DBG & TRACE*/
+ /* Trace and debug clocks are managed by SCMI */
+
+ /* Display subsystem */
+ /* LTDC */
+ STM32_GATE(CK_BUS_LTDC, "ck_icn_p_ltdc", "ck_icn_apb4", 0, GATE_LTDC, SEC_RIFSC(80)),
+ STM32_GATE(CK_KER_LTDC, "ck_ker_ltdc", "ck_flexgen_27", CLK_SET_RATE_PARENT, GATE_LTDC,
+ SEC_RIFSC(80)),
+
+ /* DSI */
+ STM32_GATE(CK_BUS_DSI, "ck_icn_p_dsi", "ck_icn_apb4", 0, GATE_DSI, SEC_RIFSC(81)),
+ STM32_COMPOSITE_NODIV(CK_KER_DSIBLANE, "clk_lanebyte", 0, SEC_RIFSC(81),
+ GATE_DSI, MUX_DSIBLANE),
+
+ /* LVDS */
+ STM32_GATE(CK_BUS_LVDS, "ck_icn_p_lvds", "ck_icn_apb4", 0, GATE_LVDS, SEC_RIFSC(84)),
+
+ /* DSI PHY */
+ STM32_COMPOSITE_NODIV(CK_KER_DSIPHY, "ck_ker_dsiphy", 0, SEC_RIFSC(81),
+ GATE_DSI, MUX_DSIPHY),
+
+ /* LVDS PHY */
+ STM32_COMPOSITE_NODIV(CK_KER_LVDSPHY, "ck_ker_lvdsphy", 0, SEC_RIFSC(84),
+ GATE_LVDS, MUX_LVDSPHY),
+
+ /* DTS */
+ STM32_COMPOSITE_NODIV(CK_KER_DTS, "ck_ker_dts", 0, SEC_RIFSC(107), GATE_DTS, MUX_DTS),
+
+ /* ETHERNET */
+ STM32_GATE(CK_BUS_ETH1, "ck_icn_p_eth1", "ck_icn_ls_mcu", 0, GATE_ETH1, SEC_RIFSC(60)),
+ STM32_GATE(CK_ETH1_STP, "ck_ker_eth1stp", "ck_icn_ls_mcu", 0, GATE_ETH1STP,
+ SEC_RIFSC(60)),
+ STM32_GATE(CK_KER_ETH1, "ck_ker_eth1", "ck_flexgen_54", 0, GATE_ETH1, SEC_RIFSC(60)),
+ STM32_GATE(CK_KER_ETH1, "ck_ker_eth1ptp", "ck_flexgen_56", 0, GATE_ETH1, SEC_RIFSC(60)),
+ STM32_GATE(CK_ETH1_MAC, "ck_ker_eth1mac", "ck_icn_ls_mcu", 0, GATE_ETH1MAC,
+ SEC_RIFSC(60)),
+ STM32_GATE(CK_ETH1_TX, "ck_ker_eth1tx", "ck_icn_ls_mcu", 0, GATE_ETH1TX, SEC_RIFSC(60)),
+ STM32_GATE(CK_ETH1_RX, "ck_ker_eth1rx", "ck_icn_ls_mcu", 0, GATE_ETH1RX, SEC_RIFSC(60)),
+
+ STM32_GATE(CK_BUS_ETH2, "ck_icn_p_eth2", "ck_icn_ls_mcu", 0, GATE_ETH2, SEC_RIFSC(61)),
+ STM32_GATE(CK_ETH2_STP, "ck_ker_eth2stp", "ck_icn_ls_mcu", 0, GATE_ETH2STP,
+ SEC_RIFSC(61)),
+ STM32_GATE(CK_KER_ETH2, "ck_ker_eth2", "ck_flexgen_54", 0, GATE_ETH2, SEC_RIFSC(61)),
+ STM32_GATE(CK_KER_ETH2, "ck_ker_eth2ptp", "ck_flexgen_56", 0, GATE_ETH2, SEC_RIFSC(61)),
+ STM32_GATE(CK_ETH2_MAC, "ck_ker_eth2mac", "ck_icn_ls_mcu", 0, GATE_ETH2MAC,
+ SEC_RIFSC(61)),
+ STM32_GATE(CK_ETH2_TX, "ck_ker_eth2tx", "ck_icn_ls_mcu", 0, GATE_ETH2TX, SEC_RIFSC(61)),
+ STM32_GATE(CK_ETH2_RX, "ck_ker_eth2rx", "ck_icn_ls_mcu", 0, GATE_ETH2RX, SEC_RIFSC(61)),
+
+ STM32_GATE(CK_BUS_ETHSW, "ck_icn_p_ethsw", "ck_icn_ls_mcu", 0, GATE_ETHSWMAC,
+ SEC_RIFSC(70)),
+ STM32_GATE(CK_KER_ETHSW, "ck_ker_ethsw", "ck_flexgen_54", 0, GATE_ETHSW,
+ SEC_RIFSC(70)),
+ STM32_GATE(CK_KER_ETHSWREF, "ck_ker_ethswref", "ck_flexgen_60", 0, GATE_ETHSWREF,
+ SEC_RIFSC(70)),
+
+ /* FDCAN */
+ STM32_GATE(CK_BUS_FDCAN, "ck_icn_p_fdcan", "ck_icn_apb2", 0, GATE_FDCAN, SEC_RIFSC(56)),
+ STM32_GATE(CK_KER_FDCAN, "ck_ker_fdcan", "ck_flexgen_26", 0, GATE_FDCAN, SEC_RIFSC(56)),
+
+ /* GPU */
+ STM32_GATE(CK_BUS_GPU, "ck_icn_m_gpu", "ck_flexgen_59", 0, GATE_GPU, SEC_RIFSC(79)),
+ STM32_GATE(CK_KER_GPU, "ck_ker_gpu", "ck_pll3", 0, GATE_GPU, SEC_RIFSC(79)),
+
+ /* HASH */
+ STM32_GATE(CK_BUS_HASH, "ck_icn_p_hash", "ck_icn_ls_mcu", 0, GATE_HASH, SEC_RIFSC(95)),
+
+ /* HDP */
+ STM32_GATE(CK_BUS_HDP, "ck_icn_p_hdp", "ck_icn_apb3", 0, GATE_HDP, SEC_RIFSC(57)),
+
+ /* I2C */
+ STM32_GATE(CK_KER_I2C1, "ck_ker_i2c1", "ck_flexgen_12", 0, GATE_I2C1, SEC_RIFSC(41)),
+ STM32_GATE(CK_KER_I2C2, "ck_ker_i2c2", "ck_flexgen_12", 0, GATE_I2C2, SEC_RIFSC(42)),
+ STM32_GATE(CK_KER_I2C3, "ck_ker_i2c3", "ck_flexgen_13", 0, GATE_I2C3, SEC_RIFSC(43)),
+ STM32_GATE(CK_KER_I2C5, "ck_ker_i2c5", "ck_flexgen_13", 0, GATE_I2C5, SEC_RIFSC(45)),
+ STM32_GATE(CK_KER_I2C4, "ck_ker_i2c4", "ck_flexgen_14", 0, GATE_I2C4, SEC_RIFSC(44)),
+ STM32_GATE(CK_KER_I2C6, "ck_ker_i2c6", "ck_flexgen_14", 0, GATE_I2C6, SEC_RIFSC(46)),
+ STM32_GATE(CK_KER_I2C7, "ck_ker_i2c7", "ck_flexgen_15", 0, GATE_I2C7, SEC_RIFSC(47)),
+ STM32_GATE(CK_KER_I2C8, "ck_ker_i2c8", "ck_flexgen_38", 0, GATE_I2C8, SEC_RIFSC(48)),
+
+ /* I3C */
+ STM32_GATE(CK_KER_I3C1, "ck_ker_i3c1", "ck_flexgen_12", 0, GATE_I3C1, SEC_RIFSC(114)),
+ STM32_GATE(CK_KER_I3C2, "ck_ker_i3c2", "ck_flexgen_12", 0, GATE_I3C2, SEC_RIFSC(115)),
+ STM32_GATE(CK_KER_I3C3, "ck_ker_i3c3", "ck_flexgen_13", 0, GATE_I3C3, SEC_RIFSC(116)),
+ STM32_GATE(CK_KER_I3C4, "ck_ker_i3c4", "ck_flexgen_36", 0, GATE_I3C4, SEC_RIFSC(117)),
+
+ /* I2S */
+ STM32_GATE(CK_BUS_IS2M, "ck_icn_p_is2m", "ck_icn_apb3", 0, GATE_IS2M, SEC_RIFRCC(IS2M)),
+
+ /* IWDG */
+ STM32_GATE(CK_BUS_IWDG1, "ck_icn_p_iwdg1", "ck_icn_apb3", 0, GATE_IWDG1, SEC_RIFSC(98)),
+ STM32_GATE(CK_BUS_IWDG2, "ck_icn_p_iwdg2", "ck_icn_apb3", 0, GATE_IWDG2, SEC_RIFSC(99)),
+ STM32_GATE(CK_BUS_IWDG3, "ck_icn_p_iwdg3", "ck_icn_apb3", 0, GATE_IWDG3, SEC_RIFSC(100)),
+ STM32_GATE(CK_BUS_IWDG4, "ck_icn_p_iwdg4", "ck_icn_apb3", 0, GATE_IWDG4, SEC_RIFSC(101)),
+ STM32_GATE(CK_BUS_IWDG5, "ck_icn_p_iwdg5", "ck_icn_ls_mcu", 0, GATE_IWDG5,
+ SEC_RIFSC(102)),
+
+ /* LPTIM */
+ STM32_GATE(CK_KER_LPTIM1, "ck_ker_lptim1", "ck_flexgen_07", 0, GATE_LPTIM1,
+ SEC_RIFSC(17)),
+ STM32_GATE(CK_KER_LPTIM2, "ck_ker_lptim2", "ck_flexgen_07", 0, GATE_LPTIM2,
+ SEC_RIFSC(18)),
+ STM32_GATE(CK_KER_LPTIM3, "ck_ker_lptim3", "ck_flexgen_40", 0, GATE_LPTIM3,
+ SEC_RIFSC(19)),
+ STM32_GATE(CK_KER_LPTIM4, "ck_ker_lptim4", "ck_flexgen_41", 0, GATE_LPTIM4,
+ SEC_RIFSC(20)),
+ STM32_GATE(CK_KER_LPTIM5, "ck_ker_lptim5", "ck_flexgen_41", 0, GATE_LPTIM5,
+ SEC_RIFSC(21)),
+
+ /* LPUART */
+ STM32_GATE(CK_KER_LPUART1, "ck_ker_lpuart1", "ck_flexgen_39", 0, GATE_LPUART1,
+ SEC_RIFSC(40)),
+
+ /* MCO1 & MCO2 */
+ STM32_COMPOSITE_NODIV(CK_MCO1, "ck_mco1", 0, SEC_RIFRCC(MCO1), GATE_MCO1, MUX_MCO1),
+ STM32_COMPOSITE_NODIV(CK_MCO2, "ck_mco2", 0, SEC_RIFRCC(MCO2), GATE_MCO2, MUX_MCO2),
+
+ /* MDF */
+ STM32_GATE(CK_KER_MDF1, "ck_ker_mdf1", "ck_flexgen_23", 0, GATE_MDF1, SEC_RIFSC(54)),
+
+ /* OCTOSPI */
+ STM32_GATE(CK_BUS_OSPIIOM, "ck_icn_p_ospiiom", "ck_icn_ls_mcu", 0, GATE_OSPIIOM,
+ SEC_RIFSC(111)),
+
+ /* PCIE */
+ STM32_GATE(CK_BUS_PCIE, "ck_icn_p_pcie", "ck_icn_ls_mcu", 0, GATE_PCIE, SEC_RIFSC(68)),
+
+ /* PKA */
+ STM32_GATE(CK_BUS_PKA, "ck_icn_p_pka", "ck_icn_ls_mcu", 0, GATE_PKA, SEC_RIFSC(93)),
+
+ /* RNG */
+ STM32_GATE(CK_BUS_RNG, "ck_icn_p_rng", "ck_icn_ls_mcu", CLK_IGNORE_UNUSED, GATE_RNG,
+ SEC_RIFSC(92)),
+
+ /* SAES */
+ STM32_GATE(CK_BUS_SAES, "ck_icn_p_saes", "ck_icn_ls_mcu", 0, GATE_SAES, SEC_RIFSC(94)),
+
+ /* SAI [1..4] */
+ STM32_GATE(CK_BUS_SAI1, "ck_icn_p_sai1", "ck_icn_apb2", 0, GATE_SAI1, SEC_RIFSC(49)),
+ STM32_GATE(CK_BUS_SAI2, "ck_icn_p_sai2", "ck_icn_apb2", 0, GATE_SAI2, SEC_RIFSC(50)),
+ STM32_GATE(CK_BUS_SAI3, "ck_icn_p_sai3", "ck_icn_apb2", 0, GATE_SAI3, SEC_RIFSC(51)),
+ STM32_GATE(CK_BUS_SAI4, "ck_icn_p_sai4", "ck_icn_apb2", 0, GATE_SAI4, SEC_RIFSC(52)),
+ STM32_GATE(CK_KER_SAI1, "ck_ker_sai1", "ck_flexgen_23", 0, GATE_SAI1, SEC_RIFSC(49)),
+ STM32_GATE(CK_KER_SAI2, "ck_ker_sai2", "ck_flexgen_24", 0, GATE_SAI2, SEC_RIFSC(50)),
+ STM32_GATE(CK_KER_SAI3, "ck_ker_sai3", "ck_flexgen_25", 0, GATE_SAI3, SEC_RIFSC(51)),
+ STM32_GATE(CK_KER_SAI4, "ck_ker_sai4", "ck_flexgen_25", 0, GATE_SAI4, SEC_RIFSC(52)),
+
+ /* SDMMC */
+ STM32_GATE(CK_KER_SDMMC1, "ck_ker_sdmmc1", "ck_flexgen_51", 0, GATE_SDMMC1,
+ SEC_RIFSC(76)),
+ STM32_GATE(CK_KER_SDMMC2, "ck_ker_sdmmc2", "ck_flexgen_52", 0, GATE_SDMMC2,
+ SEC_RIFSC(77)),
+ STM32_GATE(CK_KER_SDMMC3, "ck_ker_sdmmc3", "ck_flexgen_53", 0, GATE_SDMMC3,
+ SEC_RIFSC(78)),
+
+ /* SERC */
+ STM32_GATE(CK_BUS_SERC, "ck_icn_p_serc", "ck_icn_apb3", 0, GATE_SERC, SEC_RIFSC(110)),
+
+ /* SPDIF */
+ STM32_GATE(CK_KER_SPDIFRX, "ck_ker_spdifrx", "ck_flexgen_11", 0, GATE_SPDIFRX,
+ SEC_RIFSC(30)),
+
+ /* SPI */
+ STM32_GATE(CK_KER_SPI1, "ck_ker_spi1", "ck_flexgen_16", 0, GATE_SPI1, SEC_RIFSC(22)),
+ STM32_GATE(CK_KER_SPI2, "ck_ker_spi2", "ck_flexgen_10", 0, GATE_SPI2, SEC_RIFSC(23)),
+ STM32_GATE(CK_KER_SPI3, "ck_ker_spi3", "ck_flexgen_10", 0, GATE_SPI3, SEC_RIFSC(24)),
+ STM32_GATE(CK_KER_SPI4, "ck_ker_spi4", "ck_flexgen_17", 0, GATE_SPI4, SEC_RIFSC(25)),
+ STM32_GATE(CK_KER_SPI5, "ck_ker_spi5", "ck_flexgen_17", 0, GATE_SPI5, SEC_RIFSC(26)),
+ STM32_GATE(CK_KER_SPI6, "ck_ker_spi6", "ck_flexgen_18", 0, GATE_SPI6, SEC_RIFSC(27)),
+ STM32_GATE(CK_KER_SPI7, "ck_ker_spi7", "ck_flexgen_18", 0, GATE_SPI7, SEC_RIFSC(28)),
+ STM32_GATE(CK_KER_SPI8, "ck_ker_spi8", "ck_flexgen_37", 0, GATE_SPI8, SEC_RIFSC(29)),
+
+ /* STGEN */
+ STM32_GATE(CK_KER_STGEN, "ck_ker_stgen", "ck_flexgen_33", CLK_IGNORE_UNUSED, GATE_STGEN,
+ SEC_RIFSC(73)),
+
+ /* Timers */
+ STM32_GATE(CK_KER_TIM2, "ck_ker_tim2", "timg1_ck", 0, GATE_TIM2, SEC_RIFSC(1)),
+ STM32_GATE(CK_KER_TIM3, "ck_ker_tim3", "timg1_ck", 0, GATE_TIM3, SEC_RIFSC(2)),
+ STM32_GATE(CK_KER_TIM4, "ck_ker_tim4", "timg1_ck", 0, GATE_TIM4, SEC_RIFSC(3)),
+ STM32_GATE(CK_KER_TIM5, "ck_ker_tim5", "timg1_ck", 0, GATE_TIM5, SEC_RIFSC(4)),
+ STM32_GATE(CK_KER_TIM6, "ck_ker_tim6", "timg1_ck", 0, GATE_TIM6, SEC_RIFSC(5)),
+ STM32_GATE(CK_KER_TIM7, "ck_ker_tim7", "timg1_ck", 0, GATE_TIM7, SEC_RIFSC(6)),
+ STM32_GATE(CK_KER_TIM10, "ck_ker_tim10", "timg1_ck", 0, GATE_TIM10, SEC_RIFSC(8)),
+ STM32_GATE(CK_KER_TIM11, "ck_ker_tim11", "timg1_ck", 0, GATE_TIM11, SEC_RIFSC(9)),
+ STM32_GATE(CK_KER_TIM12, "ck_ker_tim12", "timg1_ck", 0, GATE_TIM12, SEC_RIFSC(10)),
+ STM32_GATE(CK_KER_TIM13, "ck_ker_tim13", "timg1_ck", 0, GATE_TIM13, SEC_RIFSC(11)),
+ STM32_GATE(CK_KER_TIM14, "ck_ker_tim14", "timg1_ck", 0, GATE_TIM14, SEC_RIFSC(12)),
+
+ STM32_GATE(CK_KER_TIM1, "ck_ker_tim1", "timg2_ck", 0, GATE_TIM1, SEC_RIFSC(0)),
+ STM32_GATE(CK_KER_TIM8, "ck_ker_tim8", "timg2_ck", 0, GATE_TIM8, SEC_RIFSC(7)),
+ STM32_GATE(CK_KER_TIM15, "ck_ker_tim15", "timg2_ck", 0, GATE_TIM15, SEC_RIFSC(13)),
+ STM32_GATE(CK_KER_TIM16, "ck_ker_tim16", "timg2_ck", 0, GATE_TIM16, SEC_RIFSC(14)),
+ STM32_GATE(CK_KER_TIM17, "ck_ker_tim17", "timg2_ck", 0, GATE_TIM17, SEC_RIFSC(15)),
+ STM32_GATE(CK_KER_TIM20, "ck_ker_tim20", "timg2_ck", 0, GATE_TIM20, SEC_RIFSC(20)),
+
+ /* UART/USART */
+ STM32_GATE(CK_KER_USART2, "ck_ker_usart2", "ck_flexgen_08", 0, GATE_USART2,
+ SEC_RIFSC(32)),
+ STM32_GATE(CK_KER_UART4, "ck_ker_uart4", "ck_flexgen_08", 0, GATE_UART4,
+ SEC_RIFSC(34)),
+ STM32_GATE(CK_KER_USART3, "ck_ker_usart3", "ck_flexgen_09", 0, GATE_USART3,
+ SEC_RIFSC(33)),
+ STM32_GATE(CK_KER_UART5, "ck_ker_uart5", "ck_flexgen_09", 0, GATE_UART5,
+ SEC_RIFSC(35)),
+ STM32_GATE(CK_KER_USART1, "ck_ker_usart1", "ck_flexgen_19", 0, GATE_USART1,
+ SEC_RIFSC(31)),
+ STM32_GATE(CK_KER_USART6, "ck_ker_usart6", "ck_flexgen_20", 0, GATE_USART6,
+ SEC_RIFSC(36)),
+ STM32_GATE(CK_KER_UART7, "ck_ker_uart7", "ck_flexgen_21", 0, GATE_UART7,
+ SEC_RIFSC(37)),
+ STM32_GATE(CK_KER_UART8, "ck_ker_uart8", "ck_flexgen_21", 0, GATE_UART8,
+ SEC_RIFSC(38)),
+ STM32_GATE(CK_KER_UART9, "ck_ker_uart9", "ck_flexgen_22", 0, GATE_UART9,
+ SEC_RIFSC(39)),
+
+ /* USB2PHY1 */
+ STM32_COMPOSITE_NODIV(CK_KER_USB2PHY1, "ck_ker_usb2phy1", 0, SEC_RIFSC(63),
+ GATE_USB2PHY1, MUX_USB2PHY1),
+
+ /* USBH */
+ STM32_GATE(CK_BUS_USB2OHCI, "ck_icn_m_usb2ohci", "ck_icn_hsl", 0, GATE_USBH,
+ SEC_RIFSC(63)),
+ STM32_GATE(CK_BUS_USB2EHCI, "ck_icn_m_usb2ehci", "ck_icn_hsl", 0, GATE_USBH,
+ SEC_RIFSC(63)),
+
+ /* USB2PHY2 */
+ STM32_COMPOSITE_NODIV(CK_KER_USB2PHY2EN, "ck_ker_usb2phy2_en", 0, SEC_RIFSC(66),
+ GATE_USB2PHY2, MUX_USB2PHY2),
+
+ /* USB3 PCIe COMBOPHY */
+ STM32_GATE(CK_BUS_USB3PCIEPHY, "ck_icn_p_usb3pciephy", "ck_icn_apb4", 0, GATE_USB3PCIEPHY,
+ SEC_RIFSC(67)),
+
+ STM32_COMPOSITE_NODIV(CK_KER_USB3PCIEPHY, "ck_ker_usb3pciephy", 0, SEC_RIFSC(67),
+ GATE_USB3PCIEPHY, MUX_USB3PCIEPHY),
+
+ /* USB3 DRD */
+ STM32_GATE(CK_BUS_USB3DR, "ck_icn_m_usb3dr", "ck_icn_hsl", 0, GATE_USB3DR,
+ SEC_RIFSC(66)),
+ STM32_GATE(CK_KER_USB2PHY2, "ck_ker_usb2phy2", "ck_flexgen_58", 0, GATE_USB3DR,
+ SEC_RIFSC(66)),
+
+ /* UCPD */
+ STM32_GATE(CK_BUS_USBTC, "ck_icn_p_usbtc", "ck_flexgen_35", 0, GATE_USBTC,
+ SEC_RIFSC(69)),
+ STM32_GATE(CK_KER_USBTC, "ck_ker_usbtc", "ck_flexgen_35", 0, GATE_USBTC,
+ SEC_RIFSC(69)),
+
+ /* VDEC / VENC */
+ STM32_GATE(CK_BUS_VDEC, "ck_icn_p_vdec", "ck_icn_apb4", 0, GATE_VDEC, SEC_RIFSC(89)),
+ STM32_GATE(CK_BUS_VENC, "ck_icn_p_venc", "ck_icn_apb4", 0, GATE_VENC, SEC_RIFSC(90)),
+
+ /* VREF */
+ STM32_GATE(CK_BUS_VREF, "ck_icn_p_vref", "ck_icn_apb3", 0, RCC_VREFCFGR,
+ SEC_RIFSC(106)),
+
+ /* WWDG */
+ STM32_GATE(CK_BUS_WWDG1, "ck_icn_p_wwdg1", "ck_icn_apb3", 0, GATE_WWDG1,
+ SEC_RIFSC(103)),
+ STM32_GATE(CK_BUS_WWDG2, "ck_icn_p_wwdg2", "ck_icn_ls_mcu", 0, GATE_WWDG2,
+ SEC_RIFSC(104)),
+};
+
+static const struct stm32_clock_match_data stm32mp25_data = {
+ .tab_clocks = stm32mp25_clock_cfg,
+ .num_clocks = ARRAY_SIZE(stm32mp25_clock_cfg),
+ .clock_data = &(const struct clk_stm32_clock_data) {
+ .num_gates = ARRAY_SIZE(stm32mp25_gates),
+ .gates = stm32mp25_gates,
+ .muxes = stm32mp25_muxes,
+ },
+ .check_security = stm32mp25_check_security,
+
+};
+
+static int stm32mp25_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;
+
+ /* force SCMI probe to register all SCMI clocks */
+ uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi);
+
+ stm32_rcc_init(dev, &stm32mp25_data);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(stm32mp25_clock) = {
+ .name = "stm32mp25_clk",
+ .id = UCLASS_CLK,
+ .ops = &stm32_clk_ops,
+ .priv_auto = sizeof(struct stm32mp_rcc_priv),
+ .probe = stm32mp25_clk_probe,
+};
diff --git a/drivers/clk/stm32/stm32mp13_rcc.h b/drivers/clk/stm32/stm32mp13_rcc.h
index e7191b428af..b9b44b213c3 100644
--- a/drivers/clk/stm32/stm32mp13_rcc.h
+++ b/drivers/clk/stm32/stm32mp13_rcc.h
@@ -285,4 +285,97 @@
#define RCC_AHB6SECSR_ETH2MACSECF 30
#define RCC_AHB6SECSR_ETH2STPSECF 31
+/* Fields of RCC_BDCR register */
+#define RCC_BDCR_LSEON BIT(0)
+#define RCC_BDCR_LSEBYP BIT(1)
+#define RCC_BDCR_LSERDY BIT(2)
+#define RCC_BDCR_DIGBYP BIT(3)
+#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4)
+#define RCC_BDCR_LSEDRV_SHIFT 4
+#define RCC_BDCR_LSECSSON BIT(8)
+#define RCC_BDCR_RTCCKEN BIT(20)
+#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16)
+#define RCC_BDCR_RTCSRC_SHIFT 16
+
+/* Fields of RCC_RDLSICR register */
+#define RCC_RDLSICR_LSION BIT(0)
+#define RCC_RDLSICR_LSIRDY BIT(1)
+
+/* used for ALL PLLNCR registers */
+#define RCC_PLLNCR_PLLON BIT(0)
+#define RCC_PLLNCR_PLLRDY BIT(1)
+#define RCC_PLLNCR_SSCG_CTRL BIT(2)
+#define RCC_PLLNCR_DIVPEN BIT(4)
+#define RCC_PLLNCR_DIVQEN BIT(5)
+#define RCC_PLLNCR_DIVREN BIT(6)
+#define RCC_PLLNCR_DIVEN_SHIFT 4
+
+/* used for ALL PLLNCFGR1 registers */
+#define RCC_PLLNCFGR1_DIVM_SHIFT 16
+#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16)
+#define RCC_PLLNCFGR1_DIVN_SHIFT 0
+#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0)
+/* only for PLL3 and PLL4 */
+#define RCC_PLLNCFGR1_IFRGE_SHIFT 24
+#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24)
+
+/* used for ALL PLLNCFGR2 registers , using stm32mp1_div_id */
+#define RCC_PLLNCFGR2_SHIFT(div_id) ((div_id) * 8)
+#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVP_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_P)
+#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVQ_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_Q)
+#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8)
+#define RCC_PLLNCFGR2_DIVR_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_R)
+#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16)
+
+/* used for ALL PLLNFRACR registers */
+#define RCC_PLLNFRACR_FRACV_SHIFT 3
+#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3)
+#define RCC_PLLNFRACR_FRACLE BIT(16)
+
+/* used for ALL PLLNCSGR registers */
+#define RCC_PLLNCSGR_INC_STEP_SHIFT 16
+#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16)
+#define RCC_PLLNCSGR_MOD_PER_SHIFT 0
+#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0)
+#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15
+#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15)
+
+/* used for RCC_OCENSETR and RCC_OCENCLRR registers */
+#define RCC_OCENR_HSION BIT(0)
+#define RCC_OCENR_CSION BIT(4)
+#define RCC_OCENR_DIGBYP BIT(7)
+#define RCC_OCENR_HSEON BIT(8)
+#define RCC_OCENR_HSEBYP BIT(10)
+#define RCC_OCENR_HSECSSON BIT(11)
+
+/* Fields of RCC_OCRDYR register */
+#define RCC_OCRDYR_HSIRDY BIT(0)
+#define RCC_OCRDYR_HSIDIVRDY BIT(2)
+#define RCC_OCRDYR_CSIRDY BIT(4)
+#define RCC_OCRDYR_HSERDY BIT(8)
+
+/* Fields of DDRITFCR register */
+#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20)
+#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20
+#define RCC_DDRITFCR_DDRCKMOD_SSR 0
+
+/* Fields of RCC_HSICFGR register */
+#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0)
+
+/* used for MCO related operations */
+#define RCC_MCOCFG_MCOON BIT(12)
+#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4)
+#define RCC_MCOCFG_MCODIV_SHIFT 4
+#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0)
+
+/* used for most of SELR register */
+#define RCC_SELR_SRC_MASK GENMASK(2, 0)
+#define RCC_SELR_SRCRDY BIT(31)
+
+/* used for most of DIVR register : max div for RTC */
+#define RCC_DIVR_DIV_MASK GENMASK(5, 0)
+#define RCC_DIVR_DIVRDY BIT(31)
+
#endif /* STM32MP13_RCC_H */
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 55c19f335ae..c0d7a969db2 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -38,8 +38,8 @@ int dev_read_u32(const struct udevice *dev, const char *propname, u32 *outp)
return ofnode_read_u32(dev_ofnode(dev), propname, outp);
}
-int dev_read_u32_default(const struct udevice *dev, const char *propname,
- int def)
+u32 dev_read_u32_default(const struct udevice *dev, const char *propname,
+ u32 def)
{
return ofnode_read_u32_default(dev_ofnode(dev), propname, def);
}
@@ -62,8 +62,8 @@ int dev_read_s32(const struct udevice *dev, const char *propname, s32 *outp)
return ofnode_read_u32(dev_ofnode(dev), propname, (u32 *)outp);
}
-int dev_read_s32_default(const struct udevice *dev, const char *propname,
- int def)
+s32 dev_read_s32_default(const struct udevice *dev, const char *propname,
+ s32 def)
{
return ofnode_read_u32_default(dev_ofnode(dev), propname, def);
}
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 1d95d2bff27..8f7a821ebf3 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -217,6 +217,13 @@ static int jr_enqueue(uint32_t *desc_addr,
jr->head = (head + 1) & (jr->size - 1);
+ /* Invalidate output ring */
+ start = (unsigned long)jr->output_ring &
+ ~(ARCH_DMA_MINALIGN - 1);
+ end = ALIGN((unsigned long)jr->output_ring + jr->op_size,
+ ARCH_DMA_MINALIGN);
+ invalidate_dcache_range(start, end);
+
sec_out32(&regs->irja, 1);
return 0;
@@ -236,7 +243,6 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam)
#else
uint32_t *addr;
#endif
- unsigned long start, end;
while (sec_in32(&regs->orsf) && CIRC_CNT(jr->head, jr->tail,
jr->size)) {
@@ -244,11 +250,6 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam)
found = 0;
caam_dma_addr_t op_desc;
-
- /* Invalidate output ring */
- start = (unsigned long)jr->output_ring & ~(ARCH_DMA_MINALIGN - 1);
- end = ALIGN((unsigned long)jr->output_ring + jr->op_size, ARCH_DMA_MINALIGN);
- invalidate_dcache_range(start, end);
#ifdef CONFIG_CAAM_64BIT
/* Read the 64 bit Descriptor address from Output Ring.
* The 32 bit hign and low part of the address will
@@ -282,13 +283,8 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam)
}
/* Error condition if match not found */
- if (!found) {
- int slots_full = sec_in32(&regs->orsf);
-
- jr->tail = (jr->tail + slots_full) & (jr->size - 1);
- sec_out32(&regs->orjr, slots_full);
+ if (!found)
return -1;
- }
jr->info[idx].op_done = 1;
callback = (void *)jr->info[idx].callback;
@@ -300,14 +296,14 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam)
*/
if (idx == tail)
do {
- jr->info[tail].op_done = 0;
tail = (tail + 1) & (jr->size - 1);
} while (jr->info[tail].op_done);
jr->tail = tail;
-
+ jr->read_idx = (jr->read_idx + 1) & (jr->size - 1);
sec_out32(&regs->orjr, 1);
+ jr->info[idx].op_done = 0;
callback(status, arg);
}
@@ -382,6 +378,7 @@ static int jr_sw_cleanup(uint8_t sec_idx, struct caam_regs *caam)
jr->head = 0;
jr->tail = 0;
+ jr->read_idx = 0;
jr->write_idx = 0;
memset(jr->info, 0, sizeof(jr->info));
memset(jr->input_ring, 0, jr->size * sizeof(caam_dma_addr_t));
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index 8d5ca03e501..b136cd8d05a 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -83,6 +83,10 @@ struct jobring {
* in-order job completion
*/
int tail;
+ /* Read index of the output ring. It may not match with tail in case
+ * of out of order completetion
+ */
+ int read_idx;
/* Write index to input ring. Would be always equal to head */
int write_idx;
/* Size of the rings. */
diff --git a/drivers/ddr/altera/iossm_mailbox.c b/drivers/ddr/altera/iossm_mailbox.c
index fc09dde3f9e..21f94959a04 100644
--- a/drivers/ddr/altera/iossm_mailbox.c
+++ b/drivers/ddr/altera/iossm_mailbox.c
@@ -41,7 +41,7 @@
/* Offset of Mailbox Read-only Registers */
#define IOSSM_MAILBOX_HEADER_OFFSET 0x0
-#define IOSSM_MEM_INTF_INFO_0_OFFSET 0X200
+#define IOSSM_MEM_INTF_INFO_0_OFFSET 0x200
#define IOSSM_MEM_INTF_INFO_1_OFFSET 0x280
#define IOSSM_MEM_TECHNOLOGY_INTF0_OFFSET 0x210
#define IOSSM_MEM_TECHNOLOGY_INTF1_OFFSET 0x290
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index c19eb919388..a91671755e1 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -117,7 +117,7 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
return -1;
}
- snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d",
+ snprintf(dev_part_str, sizeof(dev_part_str), "%d:%x",
dfu->data.mmc.dev, dfu->data.mmc.part);
ret = fs_set_blk_dev("mmc", dev_part_str, fstype);
diff --git a/drivers/dfu/dfu_scsi.c b/drivers/dfu/dfu_scsi.c
index 9f95194784c..d99b05d23ac 100644
--- a/drivers/dfu/dfu_scsi.c
+++ b/drivers/dfu/dfu_scsi.c
@@ -96,7 +96,7 @@ static int scsi_file_op(enum dfu_op op, struct dfu_entity *dfu, u64 offset, void
return -1;
}
- snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d", dfu->data.scsi.dev,
+ snprintf(dev_part_str, sizeof(dev_part_str), "%d:%x", dfu->data.scsi.dev,
dfu->data.scsi.part);
ret = fs_set_blk_dev("scsi", dev_part_str, fstype);
@@ -342,11 +342,6 @@ int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr, char **argv, int
return -EINVAL;
}
- if (scsi_scan(false)) {
- pr_err("Couldn't init scsi device.\n");
- return -ENODEV;
- }
-
ret = find_scsi_device(dfu->data.scsi.lun, &scsi);
if (ret < 0) {
pr_err("Couldn't find scsi device no. %d.\n", dfu->data.scsi.lun);
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 344df9454b3..8013afef304 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -279,6 +279,101 @@ static int ti_sci_do_xfer(struct ti_sci_info *info,
}
/**
+ * ti_sci_cmd_query_dm_cap() - Command to query DM firmware's capabilities
+ * @handle: Pointer to TI SCI handle
+ * @fw_caps: Pointer to firmware capabilities
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_query_dm_cap(struct ti_sci_handle *handle, u64 *fw_caps)
+{
+ struct ti_sci_query_fw_caps_resp *cap_info;
+ struct ti_sci_msg_hdr hdr;
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ int ret;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+
+ xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_FW_CAPS,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
+ sizeof(*cap_info));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ return ret;
+ }
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret)
+ return ret;
+
+ cap_info = (struct ti_sci_query_fw_caps_resp *)xfer->tx_message.buf;
+
+ *fw_caps = cap_info->fw_caps;
+
+ return 0;
+}
+
+/**
+ * ti_sci_cmd_get_dm_version() - command to get the DM version of the SCI
+ * entity
+ * @handle: Pointer to TI SCI handle
+ * @dm_info: Pointer to DM version information structure
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+
+static int ti_sci_cmd_get_dm_version(struct ti_sci_handle *handle,
+ struct ti_sci_dm_version_info *dm_info)
+{
+ struct ti_sci_msg_dm_resp_version *ver_info;
+ struct ti_sci_msg_hdr hdr;
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ int ret;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle || !dm_info)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+
+ xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_DM_VERSION,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
+ sizeof(*ver_info));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ return ret;
+ }
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret)
+ return ret;
+
+ ver_info = (struct ti_sci_msg_dm_resp_version *)xfer->tx_message.buf;
+
+ dm_info->abi_major = ver_info->abi_major;
+ dm_info->abi_minor = ver_info->abi_minor;
+ dm_info->dm_ver = ver_info->version;
+ dm_info->patch_ver = ver_info->patch_version;
+ dm_info->sub_ver = ver_info->sub_version;
+ strlcpy(dm_info->sci_server_version, ver_info->sci_server_version,
+ sizeof(ver_info->sci_server_version));
+ strlcpy(dm_info->rm_pm_hal_version, ver_info->rm_pm_hal_version,
+ sizeof(ver_info->rm_pm_hal_version));
+
+ return 0;
+}
+
+/**
* ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
* @handle: pointer to TI SCI handle
*
@@ -2624,6 +2719,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
struct ti_sci_dev_ops *dops = &ops->dev_ops;
struct ti_sci_clk_ops *cops = &ops->clk_ops;
struct ti_sci_core_ops *core_ops = &ops->core_ops;
+ struct ti_sci_firmware_ops *fw_ops = &ops->fw_ops;
struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
struct ti_sci_proc_ops *pops = &ops->proc_ops;
struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
@@ -2694,6 +2790,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
fwl_ops->set_fwl_region = ti_sci_cmd_set_fwl_region;
fwl_ops->get_fwl_region = ti_sci_cmd_get_fwl_region;
fwl_ops->change_fwl_owner = ti_sci_cmd_change_fwl_owner;
+
+ fw_ops->get_dm_version = ti_sci_cmd_get_dm_version;
+ fw_ops->query_dm_cap = ti_sci_cmd_query_dm_cap;
}
/**
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index bb8bc7beead..ce50bf6800e 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -26,7 +26,9 @@
#define TI_SCI_MSG_BOARD_CONFIG_RM 0x000c
#define TI_SCI_MSG_BOARD_CONFIG_SECURITY 0x000d
#define TI_SCI_MSG_BOARD_CONFIG_PM 0x000e
+#define TI_SCI_MSG_DM_VERSION 0x000f
#define TISCI_MSG_QUERY_MSMC 0x0020
+#define TI_SCI_MSG_QUERY_FW_CAPS 0x0022
/* Device requests */
#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200
@@ -135,6 +137,46 @@ struct ti_sci_msg_resp_version {
} __packed;
/**
+ * struct ti_sci_msg_dm_resp_version - Response for a message
+ * @hdr: Generic header
+ * @version: Version number of the firmware
+ * @sub_version: Sub-version number of the firmware
+ * @patch_version: Patch version number of the firmware
+ * @abi_major: Major version of the ABI that firmware supports
+ * @abi_minor: Minor version of the ABI that firmware supports
+ * @sci_server_version: String describing the SCI server version
+ * @rm_pm_hal_version: String describing the RM PM HAL version
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a message with message type TI_SCI_MSG_DM_VERSION
+ */
+struct ti_sci_msg_dm_resp_version {
+ struct ti_sci_msg_hdr hdr;
+ u16 version;
+ u8 sub_version;
+ u8 patch_version;
+ u8 abi_major;
+ u8 abi_minor;
+ char rm_pm_hal_version[12];
+ char sci_server_version[26];
+} __packed;
+
+/**
+ * struct ti_sci_query_fw_caps_resp - Response for a message
+ * @hdr: Generic header
+ * @fw_caps: 64-bit value representing the FW/SOC capabilities.
+ *
+ * Response to a message with message type TI_SCI_MSG_QUERY_FW_CAPS
+ */
+struct ti_sci_query_fw_caps_resp {
+ struct ti_sci_msg_hdr hdr;
+ u64 fw_caps;
+} __packed;
+
+/**
* struct ti_sci_msg_req_reboot - Reboot the SoC
* @hdr: Generic Header
* @domain: Domain to be reset, 0 for full SoC reboot.
diff --git a/drivers/fpga/intel_sdm_mb.c b/drivers/fpga/intel_sdm_mb.c
index 5fe4dbdfd32..a2f3b160a73 100644
--- a/drivers/fpga/intel_sdm_mb.c
+++ b/drivers/fpga/intel_sdm_mb.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Intel Corporation <www.intel.com>
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
*/
#include <altera.h>
@@ -9,6 +10,8 @@
#include <watchdog.h>
#include <asm/arch/mailbox_s10.h>
#include <asm/arch/smc_api.h>
+#include <asm/cache.h>
+#include <cpu_func.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/intel-smc.h>
@@ -738,6 +741,8 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
debug("Invoking FPGA_CONFIG_START...\n");
+ flush_dcache_range((unsigned long)rbf_data, (unsigned long)(rbf_data + rbf_size));
+
ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, &arg, 1, NULL, 0);
if (ret) {
@@ -1023,6 +1028,8 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
u32 resp_len = 2;
u32 resp_buf[2];
+ flush_dcache_range((unsigned long)rbf_data, (unsigned long)(rbf_data + rbf_size));
+
debug("Sending MBOX_RECONFIG...\n");
ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RECONFIG, MBOX_CMD_DIRECT, 0,
NULL, 0, &resp_len, resp_buf);
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index 6783fc756f4..7de332c66ae 100644
--- a/drivers/gpio/msm_gpio.c
+++ b/drivers/gpio/msm_gpio.c
@@ -202,7 +202,7 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
if (qcom_is_special_pin(priv->pin_data, gpio))
return msm_gpio_get_value_special(priv, gpio);
- return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
+ return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) & BIT(GPIO_IN));
}
static int msm_gpio_get_function_special(struct msm_gpio_bank *priv,
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index e8c1623d41f..a54976e7889 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -404,7 +404,7 @@ static int i2c_wait_for_bb(struct i2c_regs *i2c_base)
/* Evaluate timeout */
if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB))
- return 1;
+ return -ETIMEDOUT;
}
return 0;
@@ -413,8 +413,10 @@ static int i2c_wait_for_bb(struct i2c_regs *i2c_base)
static int i2c_xfer_init(struct i2c_regs *i2c_base, uchar chip, uint addr,
int alen)
{
- if (i2c_wait_for_bb(i2c_base))
- return 1;
+ int ret = i2c_wait_for_bb(i2c_base);
+
+ if (ret)
+ return ret;
i2c_setaddress(i2c_base, chip);
while (alen) {
@@ -429,6 +431,7 @@ static int i2c_xfer_init(struct i2c_regs *i2c_base, uchar chip, uint addr,
static int i2c_xfer_finish(struct i2c_regs *i2c_base)
{
ulong start_stop_det = get_timer(0);
+ int ret;
while (1) {
if ((readl(&i2c_base->ic_raw_intr_stat) & IC_STOP_DET)) {
@@ -439,9 +442,10 @@ static int i2c_xfer_finish(struct i2c_regs *i2c_base)
}
}
- if (i2c_wait_for_bb(i2c_base)) {
+ ret = i2c_wait_for_bb(i2c_base);
+ if (ret) {
printf("Timed out waiting for bus\n");
- return 1;
+ return ret;
}
i2c_flush_rxfifo(i2c_base);
@@ -464,6 +468,7 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr,
{
unsigned long start_time_rx;
unsigned int active = 0;
+ int ret;
#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
/*
@@ -484,8 +489,9 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr,
addr);
#endif
- if (i2c_xfer_init(i2c_base, dev, addr, alen))
- return 1;
+ ret = i2c_xfer_init(i2c_base, dev, addr, alen);
+ if (ret)
+ return ret;
start_time_rx = get_timer(0);
while (len) {
@@ -510,7 +516,7 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr,
start_time_rx = get_timer(0);
active = 0;
} else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
- return 1;
+ return -ETIMEDOUT;
}
}
@@ -532,6 +538,7 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr,
{
int nb = len;
unsigned long start_time_tx;
+ int ret;
#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
/*
@@ -552,8 +559,9 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr,
addr);
#endif
- if (i2c_xfer_init(i2c_base, dev, addr, alen))
- return 1;
+ ret = i2c_xfer_init(i2c_base, dev, addr, alen);
+ if (ret)
+ return ret;
start_time_tx = get_timer(0);
while (len) {
@@ -569,7 +577,7 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr,
} else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
printf("Timed out. i2c write Failed\n");
- return 1;
+ return -ETIMEDOUT;
}
}
diff --git a/drivers/iommu/qcom-hyp-smmu.c b/drivers/iommu/qcom-hyp-smmu.c
index c1b95bc8b8c..2e51ce4f242 100644
--- a/drivers/iommu/qcom-hyp-smmu.c
+++ b/drivers/iommu/qcom-hyp-smmu.c
@@ -11,6 +11,7 @@
#include <dm.h>
#include <iommu.h>
#include <linux/bitfield.h>
+#include <linux/bug.h>
#include <linux/list.h>
#include <linux/err.h>
#include <lmb.h>
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ffc5868c0dd..8b8f6309ada 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -114,6 +114,14 @@ config ROCKCHIP_IODOMAIN
for the IO-domain setting of the SoC to match the voltage supplied
by the regulators.
+config SPL_ROCKCHIP_IODOMAIN
+ bool "Rockchip IO-domain driver support in SPL"
+ depends on SPL_MISC && SPL_DM_REGULATOR && ARCH_ROCKCHIP
+ help
+ Enable support for IO-domains in Rockchip SoCs in SPL. It is necessary
+ for the IO-domain setting of the SoC to match the voltage supplied
+ by the regulators.
+
config SIFIVE_OTP
bool "SiFive eMemory OTP driver"
depends on MISC
diff --git a/drivers/misc/rockchip-io-domain.c b/drivers/misc/rockchip-io-domain.c
index 025b6049a9f..a0573c52193 100644
--- a/drivers/misc/rockchip-io-domain.c
+++ b/drivers/misc/rockchip-io-domain.c
@@ -344,8 +344,10 @@ static int rockchip_iodomain_probe(struct udevice *dev)
continue;
ret = device_get_supply_regulator(dev, supply_name, &reg);
- if (ret)
+ if (ret) {
+ dev_dbg(dev, "%s: Regulator not found\n", supply_name);
continue;
+ }
ret = regulator_autoset(reg);
if (ret && ret != -EALREADY && ret != -EMEDIUMTYPE &&
@@ -353,6 +355,7 @@ static int rockchip_iodomain_probe(struct udevice *dev)
continue;
uV = regulator_get_value(reg);
+ dev_dbg(dev, "%s: Regulator %s at %d uV\n", supply_name, reg->name, uV);
if (uV <= 0)
continue;
diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c
index 5a6f979f91b..15bf69f7d57 100644
--- a/drivers/misc/stm32_rcc.c
+++ b/drivers/misc/stm32_rcc.c
@@ -14,47 +14,56 @@
#include <dm/device_compat.h>
#include <dm/lists.h>
-struct stm32_rcc_clk stm32_rcc_clk_f42x = {
- .drv_name = "stm32fx_rcc_clock",
+static const struct stm32_rcc stm32_rcc_f42x = {
+ .drv_name_clk = "stm32fx_rcc_clock",
+ .drv_name_rst = "stm32_rcc_reset",
.soc = STM32F42X,
};
-struct stm32_rcc_clk stm32_rcc_clk_f469 = {
- .drv_name = "stm32fx_rcc_clock",
+static const struct stm32_rcc stm32_rcc_f469 = {
+ .drv_name_clk = "stm32fx_rcc_clock",
+ .drv_name_rst = "stm32_rcc_reset",
.soc = STM32F469,
};
-struct stm32_rcc_clk stm32_rcc_clk_f7 = {
- .drv_name = "stm32fx_rcc_clock",
+static const struct stm32_rcc stm32_rcc_f7 = {
+ .drv_name_clk = "stm32fx_rcc_clock",
+ .drv_name_rst = "stm32_rcc_reset",
.soc = STM32F7,
};
-struct stm32_rcc_clk stm32_rcc_clk_h7 = {
- .drv_name = "stm32h7_rcc_clock",
+static const struct stm32_rcc stm32_rcc_h7 = {
+ .drv_name_clk = "stm32h7_rcc_clock",
+ .drv_name_rst = "stm32_rcc_reset",
};
-struct stm32_rcc_clk stm32_rcc_clk_mp1 = {
- .drv_name = "stm32mp1_clk",
- .soc = STM32MP1,
+static const struct stm32_rcc stm32_rcc_mp15 = {
+ .drv_name_clk = "stm32mp1_clk",
+ .drv_name_rst = "stm32mp1_reset",
};
-struct stm32_rcc_clk stm32_rcc_clk_mp13 = {
- .drv_name = "stm32mp13_clk",
- .soc = STM32MP1,
+static const struct stm32_rcc stm32_rcc_mp13 = {
+ .drv_name_clk = "stm32mp13_clk",
+ .drv_name_rst = "stm32mp1_reset",
+};
+
+static const struct stm32_rcc stm32_rcc_mp25 = {
+ .drv_name_clk = "stm32mp25_clk",
+ .drv_name_rst = "stm32mp25_reset",
};
static int stm32_rcc_bind(struct udevice *dev)
{
struct udevice *child;
struct driver *drv;
- struct stm32_rcc_clk *rcc_clk =
- (struct stm32_rcc_clk *)dev_get_driver_data(dev);
+ struct stm32_rcc *rcc_clk =
+ (struct stm32_rcc *)dev_get_driver_data(dev);
int ret;
dev_dbg(dev, "RCC bind\n");
- drv = lists_driver_lookup_name(rcc_clk->drv_name);
+ drv = lists_driver_lookup_name(rcc_clk->drv_name_clk);
if (!drv) {
- dev_err(dev, "Cannot find driver '%s'\n", rcc_clk->drv_name);
+ dev_err(dev, "Cannot find driver '%s'\n", rcc_clk->drv_name_clk);
return -ENOENT;
}
@@ -65,25 +74,24 @@ static int stm32_rcc_bind(struct udevice *dev)
if (ret)
return ret;
- drv = lists_driver_lookup_name("stm32_rcc_reset");
+ drv = lists_driver_lookup_name(rcc_clk->drv_name_rst);
if (!drv) {
dev_err(dev, "Cannot find driver stm32_rcc_reset'\n");
return -ENOENT;
}
- return device_bind_with_driver_data(dev, drv, dev->name,
- rcc_clk->soc,
- dev_ofnode(dev), &child);
+ return device_bind(dev, drv, dev->name, NULL, dev_ofnode(dev), &child);
}
static const struct udevice_id stm32_rcc_ids[] = {
- {.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f42x },
- {.compatible = "st,stm32f469-rcc", .data = (ulong)&stm32_rcc_clk_f469 },
- {.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 },
- {.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 },
- {.compatible = "st,stm32mp1-rcc", .data = (ulong)&stm32_rcc_clk_mp1 },
- {.compatible = "st,stm32mp1-rcc-secure", .data = (ulong)&stm32_rcc_clk_mp1 },
- {.compatible = "st,stm32mp13-rcc", .data = (ulong)&stm32_rcc_clk_mp13 },
+ {.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_f42x },
+ {.compatible = "st,stm32f469-rcc", .data = (ulong)&stm32_rcc_f469 },
+ {.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_f7 },
+ {.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_h7 },
+ {.compatible = "st,stm32mp1-rcc", .data = (ulong)&stm32_rcc_mp15 },
+ {.compatible = "st,stm32mp1-rcc-secure", .data = (ulong)&stm32_rcc_mp15 },
+ {.compatible = "st,stm32mp13-rcc", .data = (ulong)&stm32_rcc_mp13 },
+ {.compatible = "st,stm32mp25-rcc", .data = (ulong)&stm32_rcc_mp25 },
{ }
};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 38867f30a7e..1c9b6898bff 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -528,7 +528,7 @@ config SPL_MMC_SDHCI_ADMA
config MMC_SDHCI_ADMA_FORCE_32BIT
bool "Force 32 bit mode for ADMA on 64 bit platforms"
- depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA
+ depends on MMC_SDHCI_ADMA_HELPERS
help
This forces SDHCI ADMA to be built for 32 bit descriptors, even
on a 64 bit platform where they would otherwise be assumed to
@@ -538,7 +538,7 @@ config MMC_SDHCI_ADMA_FORCE_32BIT
config MMC_SDHCI_ADMA_64BIT
bool "Use SHDCI ADMA with 64 bit descriptors"
- depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA
+ depends on MMC_SDHCI_ADMA_HELPERS
depends on !MMC_SDHCI_ADMA_FORCE_32BIT
default y if DMA_ADDR_T_64BIT
help
diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 0df3568f073..d3c8f94dd0c 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -527,11 +527,16 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
void am654_sdhci_set_control_reg(struct sdhci_host *host)
{
struct mmc *mmc = host->mmc;
+ u32 reg;
+ reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ reg &= ~SDHCI_CTRL_UHS_MASK;
sdhci_set_voltage(host);
if (mmc->selected_mode > MMC_HS_52)
sdhci_set_uhs_timing(host);
+ else
+ sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
}
const struct sdhci_ops am654_sdhci_ops = {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 9421a846e45..2c1f4f9c336 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -3278,8 +3278,8 @@ int mmc_set_bkops_enable(struct mmc *mmc, bool autobkops, bool enable)
__weak int mmc_get_env_dev(void)
{
-#ifdef CONFIG_SYS_MMC_ENV_DEV
- return CONFIG_SYS_MMC_ENV_DEV;
+#ifdef CONFIG_ENV_MMC_DEVICE_INDEX
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
#else
return 0;
#endif
diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c
index a5ed87321ab..9a92b8437a6 100644
--- a/drivers/mmc/sdhci-cadence6.c
+++ b/drivers/mmc/sdhci-cadence6.c
@@ -19,7 +19,7 @@
#include "sdhci-cadence.h"
/* IO Delay Information */
-#define SDHCI_CDNS_HRS07 0X1C
+#define SDHCI_CDNS_HRS07 0x1C
#define SDHCI_CDNS_HRS07_RW_COMPENSATE GENMASK(20, 16)
#define SDHCI_CDNS_HRS07_IDELAY_VAL GENMASK(4, 0)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 0e2bdab4e7e..2375b15539b 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -83,7 +83,7 @@
#define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN 39
#define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL 146
-#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0X77
+#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0x77
struct arasan_sdhci_clk_data {
int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
diff --git a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
index 4430c4e93ee..7779e63fa5d 100644
--- a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
@@ -165,9 +165,9 @@ static void lpc32xx_cmd_ctrl(struct mtd_info *mtd, int cmd,
return;
if (ctrl & NAND_CLE)
- writeb(cmd & 0Xff, &lpc32xx_nand_mlc_registers->cmd);
+ writeb(cmd & 0xff, &lpc32xx_nand_mlc_registers->cmd);
else if (ctrl & NAND_ALE)
- writeb(cmd & 0Xff, &lpc32xx_nand_mlc_registers->addr);
+ writeb(cmd & 0xff, &lpc32xx_nand_mlc_registers->addr);
}
/**
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index dd4ed257a83..16abf89dbbf 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/kernel.h>
#endif
+#include <linux/bitfield.h>
#include <linux/bug.h>
#include <linux/mtd/spinand.h>
@@ -18,6 +19,8 @@
#define WINBOND_CFG_BUF_READ BIT(3)
+#define W25N04KV_STATUS_ECC_5_8_BITFLIPS FIELD_PREP_CONST(STATUS_ECC_MASK, 0x3)
+
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -121,6 +124,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
return -EBADMSG;
case STATUS_ECC_HAS_BITFLIPS:
+ case W25N04KV_STATUS_ECC_5_8_BITFLIPS:
/*
* Let's try to retrieve the real maximum number of bitflips
* in order to avoid forcing the wear-leveling layer to move
@@ -172,6 +176,15 @@ static const struct spinand_info winbond_spinand_table[] = {
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
+ SPINAND_INFO("W25N04KV",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
+ NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
};
static int winbond_spinand_init(struct spinand_device *spinand)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 0f93c25e3fe..fce3ef910cb 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -716,7 +716,7 @@ static int _dw_free_pkt(struct dw_eth_dev *priv)
ulong desc_start = (ulong)desc_p;
ulong desc_end = desc_start +
roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
- ulong data_start = desc_p->dmamac_addr;
+ ulong data_start = dev_bus_to_phys(priv->dev, desc_p->dmamac_addr);
ulong data_end = data_start + roundup(CFG_ETH_BUFSIZE, ARCH_DMA_MINALIGN);
/* Invalidate the descriptor buffer data */
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index a8caa0f0927..146f3f1fbd3 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -410,12 +410,12 @@ int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name)
spi_flash_free(ucode_flash);
}
} else if (src == BOOT_SOURCE_SD_MMC) {
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
u32 blk = CONFIG_SYS_FMAN_FW_ADDR / 512;
- struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+ struct mmc *mmc = find_mmc_device(CONFIG_ENV_MMC_DEVICE_INDEX);
if (!mmc) {
printf("\nMMC cannot find device for ucode\n");
@@ -514,11 +514,11 @@ int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name)
spi_flash_free(ucode_flash);
}
#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_MMC)
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
u32 blk = CONFIG_SYS_FMAN_FW_ADDR / 512;
- struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+ struct mmc *mmc = find_mmc_device(CONFIG_ENV_MMC_DEVICE_INDEX);
if (!mmc)
printf("\nMMC cannot find device for ucode\n");
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index c2869ce4010..86daf0fb2bb 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -45,7 +45,7 @@
#define MC_BUFFER_SIZE (1024 * 1024 * 16)
#define MAGIC_MC 0x4d430100
#define MC_FW_ADDR_MASK_LOW 0xE0000000
-#define MC_FW_ADDR_MASK_HIGH 0X1FFFF
+#define MC_FW_ADDR_MASK_HIGH 0x1FFFF
#define MC_STRUCT_BUFFER_OFFSET 0x01000000
#define MC_OFFSET_DELTA MC_STRUCT_BUFFER_OFFSET
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index ae545fe229c..184c1f9a46a 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -3876,7 +3876,6 @@ mvpp2_rxq_next_desc_get(struct mvpp2_rx_queue *rxq)
int rx_desc = rxq->next_desc_to_proc;
rxq->next_desc_to_proc = MVPP2_QUEUE_NEXT_DESC(rxq, rx_desc);
- prefetch(rxq->descs + rxq->next_desc_to_proc);
return rxq->descs + rx_desc;
}
diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c
index 6e4d0a05121..27d0327c88a 100644
--- a/drivers/net/octeontx/nicvf_main.c
+++ b/drivers/net/octeontx/nicvf_main.c
@@ -279,8 +279,6 @@ int nicvf_cq_handler(struct nicvf *nic, void **ppkt, int *pkt_len)
cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head);
cqe_head++;
cqe_head &= (cq->dmem.q_len - 1);
- /* Initiate prefetch for next descriptor */
- prefetch((struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head));
switch (cq_desc->cqe_type) {
case CQE_TYPE_RX:
diff --git a/drivers/net/phy/ca_phy.c b/drivers/net/phy/ca_phy.c
index 5b2c67d2fda..72d370274a1 100644
--- a/drivers/net/phy/ca_phy.c
+++ b/drivers/net/phy/ca_phy.c
@@ -73,7 +73,7 @@ static void __external_phy_init(struct phy_device *phydev, int reset_phy)
val &= ~(1 << 2);
phy_write(phydev, MDIO_DEVAD_NONE, 27, val);
- /* REG31 write 0X0000, back to page0 */
+ /* REG31 write 0x0000, back to page0 */
phy_write(phydev, MDIO_DEVAD_NONE, 31, 0x0000);
}
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index d043e859bad..be480ecef6c 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -170,10 +170,10 @@ void cs4340_upload_firmware(struct phy_device *phydev)
spi_flash_free(ucode_flash);
}
} else if (src == BOOT_SOURCE_SD_MMC) {
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
u32 cnt = CONFIG_CORTINA_FW_LENGTH / 512;
u32 blk = cortina_fw_addr / 512;
- struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+ struct mmc *mmc = find_mmc_device(CONFIG_ENV_MMC_DEVICE_INDEX);
if (!mmc) {
puts("Failed to find MMC device for Cortina ucode\n");
@@ -223,10 +223,10 @@ void cs4340_upload_firmware(struct phy_device *phydev)
spi_flash_free(ucode_flash);
}
#elif defined(CONFIG_SYS_CORTINA_FW_IN_MMC)
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
u32 cnt = CONFIG_CORTINA_FW_LENGTH / 512;
u32 blk = cortina_fw_addr / 512;
- struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+ struct mmc *mmc = find_mmc_device(CONFIG_ENV_MMC_DEVICE_INDEX);
if (!mmc) {
puts("Failed to find MMC device for Cortina ucode\n");
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 461805ae53f..703e22479d2 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -567,12 +567,14 @@ static int zynq_gem_init(struct udevice *dev)
}
#endif
- ret = clk_get_rate(&priv->tx_clk);
- if (ret != clk_rate) {
- ret = clk_set_rate(&priv->tx_clk, clk_rate);
- if (IS_ERR_VALUE(ret)) {
- dev_err(dev, "failed to set tx clock rate %ld\n", clk_rate);
- return ret;
+ if (priv->interface != PHY_INTERFACE_MODE_MII) {
+ ret = clk_get_rate(&priv->tx_clk);
+ if (ret != clk_rate) {
+ ret = clk_set_rate(&priv->tx_clk, clk_rate);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(dev, "failed to set tx clock rate %ld\n", clk_rate);
+ return ret;
+ }
}
}
diff --git a/drivers/pci/pcie-xilinx-nwl.c b/drivers/pci/pcie-xilinx-nwl.c
index 7ef2bdf57b5..e03ab3be912 100644
--- a/drivers/pci/pcie-xilinx-nwl.c
+++ b/drivers/pci/pcie-xilinx-nwl.c
@@ -303,6 +303,13 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie)
return PTR_ERR(pcie->breg_base);
pcie->phys_breg_base = res.start;
+ ret = dev_read_resource_byname(dev, "pcireg", &res);
+ if (ret)
+ return ret;
+ pcie->pcireg_base = devm_ioremap(dev, res.start, resource_size(&res));
+ if (IS_ERR(pcie->pcireg_base))
+ return PTR_ERR(pcie->pcireg_base);
+
ret = dev_read_resource_byname(dev, "cfg", &res);
if (ret)
return ret;
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c
index 8d643b762f9..fcf8617ee9b 100644
--- a/drivers/phy/phy-stm32-usbphyc.c
+++ b/drivers/phy/phy-stm32-usbphyc.c
@@ -16,7 +16,9 @@
#include <syscon.h>
#include <usb.h>
#include <asm/io.h>
+#include <dm/device.h>
#include <dm/device_compat.h>
+#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/of_access.h>
#include <linux/bitfield.h>
@@ -633,6 +635,7 @@ U_BOOT_DRIVER(stm32_usb_phyc) = {
struct stm32_usbphyc_clk {
bool enable;
+ struct clk clkp;
};
static ulong stm32_usbphyc_clk48_get_rate(struct clk *clk)
@@ -687,9 +690,25 @@ const struct clk_ops usbphyc_clk48_ops = {
.disable = stm32_usbphyc_clk48_disable,
};
+int usbphyc_clk48_probe(struct udevice *dev)
+{
+ struct stm32_usbphyc_clk *priv = dev_get_priv(dev);
+
+ /* prepare clkp to correctly register clock with CCF */
+ priv->clkp.dev = dev;
+ priv->clkp.id = CLK_ID(dev, 0);
+
+ /* Store back pointer to clk from udevice */
+ /* FIXME: This is not allowed...should be allocated by driver model */
+ dev_set_uclass_priv(dev, &priv->clkp);
+
+ return 0;
+}
+
U_BOOT_DRIVER(stm32_usb_phyc_clk) = {
.name = "stm32-usbphyc-clk",
.id = UCLASS_CLK,
.ops = &usbphyc_clk48_ops,
+ .probe = &usbphyc_clk48_probe,
.priv_auto = sizeof(struct stm32_usbphyc_clk),
};
diff --git a/drivers/phy/phy-zynqmp.c b/drivers/phy/phy-zynqmp.c
index 7049e740d56..9649e660220 100644
--- a/drivers/phy/phy-zynqmp.c
+++ b/drivers/phy/phy-zynqmp.c
@@ -138,6 +138,7 @@
#define PROT_BUS_WIDTH_40 0x2
#define PROT_BUS_WIDTH_MASK 0x3
#define PROT_BUS_WIDTH_SHIFT 2
+#define GEM_CLK_CTRL_WIDTH_SHIFT 5
/* Number of GT lanes */
#define NUM_LANES 4
@@ -400,6 +401,7 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy)
{
struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
u32 shift = gtr_phy->lane * PROT_BUS_WIDTH_SHIFT;
+ u32 clk_ctrl_shift = gtr_phy->lane * GEM_CLK_CTRL_WIDTH_SHIFT;
/* Set SGMII protocol TX and RX bus width to 10 bits. */
xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, PROT_BUS_WIDTH_MASK << shift,
@@ -417,9 +419,9 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy)
*/
/* GEM I/O Clock Control */
clrsetbits_le32(ZYNQMP_IOU_SLCR_BASEADDR + IOU_SLCR_GEM_CLK_CTRL,
- 0xf << shift,
+ 0xf << clk_ctrl_shift,
(GEM_CTRL_GEM_SGMII_MODE | GEM_CTRL_GEM_REF_SRC_SEL) <<
- shift);
+ clk_ctrl_shift);
/* Setup signal detect */
clrsetbits_le32(ZYNQMP_IOU_SLCR_BASEADDR + IOU_SLCR_GEM_CTRL,
diff --git a/drivers/phy/qcom/phy-qcom-qmp-ufs.c b/drivers/phy/qcom/phy-qcom-qmp-ufs.c
index 449b9767778..f3c606847fb 100644
--- a/drivers/phy/qcom/phy-qcom-qmp-ufs.c
+++ b/drivers/phy/qcom/phy-qcom-qmp-ufs.c
@@ -86,6 +86,12 @@ enum qphy_reg_layout {
QPHY_LAYOUT_SIZE
};
+static const unsigned int ufsphy_v2_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_START_CTRL] = QPHY_V2_PCS_UFS_PHY_START,
+ [QPHY_PCS_READY_STATUS] = QPHY_V2_PCS_UFS_READY_STATUS,
+ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V2_PCS_UFS_POWER_DOWN_CONTROL,
+};
+
static const unsigned int ufsphy_v3_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_START_CTRL] = QPHY_V3_PCS_UFS_PHY_START,
[QPHY_PCS_READY_STATUS] = QPHY_V3_PCS_UFS_READY_STATUS,
@@ -715,6 +721,98 @@ static const struct qmp_ufs_init_tbl sc7280_ufsphy_hs_g4_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x0f),
};
+static const struct qmp_ufs_init_tbl sm6115_ufsphy_serdes[] = {
+ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00),
+};
+
+static const struct qmp_ufs_init_tbl sm6115_ufsphy_hs_b_serdes[] = {
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44),
+};
+
+static const struct qmp_ufs_init_tbl sm6115_ufsphy_tx[] = {
+ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
+};
+
+static const struct qmp_ufs_init_tbl sm6115_ufsphy_rx[] = {
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5b),
+};
+
+static const struct qmp_ufs_init_tbl sm6115_ufsphy_pcs[] = {
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_PWM_GEAR_BAND, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_SIGDET_CTRL2, 0x6d),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_SYM_RESYNC_CTRL, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_LARGE_AMP_POST_EMP_LVL, 0x12),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_SMALL_AMP_POST_EMP_LVL, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */
+};
+
struct qmp_ufs_offsets {
u16 serdes;
u16 pcs;
@@ -1079,6 +1177,34 @@ static const struct qmp_ufs_cfg sa8775p_ufsphy_cfg = {
.regs = ufsphy_v5_regs_layout,
};
+static const struct qmp_ufs_cfg sm6115_ufsphy_cfg = {
+ .lanes = 1,
+
+ .offsets = &qmp_ufs_offsets,
+
+ .tbls = {
+ .serdes = sm6115_ufsphy_serdes,
+ .serdes_num = ARRAY_SIZE(sm6115_ufsphy_serdes),
+ .tx = sm6115_ufsphy_tx,
+ .tx_num = ARRAY_SIZE(sm6115_ufsphy_tx),
+ .rx = sm6115_ufsphy_rx,
+ .rx_num = ARRAY_SIZE(sm6115_ufsphy_rx),
+ .pcs = sm6115_ufsphy_pcs,
+ .pcs_num = ARRAY_SIZE(sm6115_ufsphy_pcs),
+ },
+ .tbls_hs_b = {
+ .serdes = sm6115_ufsphy_hs_b_serdes,
+ .serdes_num = ARRAY_SIZE(sm6115_ufsphy_hs_b_serdes),
+ },
+ .clk_list = sdm845_ufs_phy_clk_l,
+ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+ .vreg_list = qmp_ufs_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
+ .regs = ufsphy_v2_regs_layout,
+
+ .no_pcs_sw_reset = true,
+};
+
static void qmp_ufs_configure_lane(void __iomem *base,
const struct qmp_ufs_init_tbl tbl[],
int num,
@@ -1469,9 +1595,11 @@ static const struct udevice_id qmp_ufs_ids[] = {
{ .compatible = "qcom,sdm845-qmp-ufs-phy", .data = (ulong)&sdm845_ufsphy_cfg },
{ .compatible = "qcom,sm8150-qmp-ufs-phy", .data = (ulong)&sm8150_ufsphy_cfg },
{ .compatible = "qcom,sm8250-qmp-ufs-phy", .data = (ulong)&sm8250_ufsphy_cfg },
+ { .compatible = "qcom,qcs8300-qmp-ufs-phy", .data = (ulong)&sa8775p_ufsphy_cfg },
{ .compatible = "qcom,sm8550-qmp-ufs-phy", .data = (ulong)&sm8550_ufsphy_cfg },
{ .compatible = "qcom,sm8650-qmp-ufs-phy", .data = (ulong)&sm8650_ufsphy_cfg },
{ .compatible = "qcom,sc7280-qmp-ufs-phy", .data = (ulong)&sc7280_ufsphy_cfg, },
+ { .compatible = "qcom,qcs615-qmp-ufs-phy", .data = (ulong)&sm6115_ufsphy_cfg, },
{ }
};
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index c7459dbc5fc..c48a5cd5267 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -284,7 +284,7 @@ DECLARE_GLOBAL_DATA_PTR;
* clock 0: PLL 0 div 1
* clock 1: PLL 1 div 2
*/
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL_CONFIG 0x30
#define CLK_PLL_MASK 0x33
#define CMN_READY BIT(0)
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index e567cb113a3..21f81b66099 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -27,6 +27,13 @@ config PINCTRL_QCOM_IPQ4019
Say Y here to enable support for pinctrl on the IPQ4019 SoC,
as well as the associated GPIO driver.
+config PINCTRL_QCOM_IPQ5424
+ bool "Qualcomm IPQ5424 Pinctrl"
+ select PINCTRL_QCOM
+ help
+ Say Y here to enable support for pinctrl on the IPQ5424 SoC,
+ as well as the associated GPIO driver.
+
config PINCTRL_QCOM_IPQ9574
bool "Qualcomm IPQ9574 Pinctrl"
select PINCTRL_QCOM
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 6ffc6d48c15..6cb53838e71 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_PINCTRL_QCOM) += pinctrl-qcom.o
obj-$(CONFIG_PINCTRL_QCOM_APQ8016) += pinctrl-apq8016.o
obj-$(CONFIG_PINCTRL_QCOM_IPQ4019) += pinctrl-ipq4019.o
+obj-$(CONFIG_PINCTRL_QCOM_IPQ5424) += pinctrl-ipq5424.o
obj-$(CONFIG_PINCTRL_QCOM_IPQ9574) += pinctrl-ipq9574.o
obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o
obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5424.c b/drivers/pinctrl/qcom/pinctrl-ipq5424.c
new file mode 100644
index 00000000000..cde990a32ef
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5424.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016-2018,2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <dm.h>
+
+#include "pinctrl-qcom.h"
+
+#define MAX_PIN_NAME_LEN 32
+static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
+
+enum ipq5424_functions {
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_tic,
+ msm_mux_audio_pri,
+ msm_mux_audio_pri0,
+ msm_mux_audio_pri1,
+ msm_mux_audio_sec,
+ msm_mux_audio_sec0,
+ msm_mux_audio_sec1,
+ msm_mux_core_voltage,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_cri_trng2,
+ msm_mux_cri_trng3,
+ msm_mux_cxc_clk,
+ msm_mux_cxc_data,
+ msm_mux_dbg_out,
+ msm_mux_gcc_plltest,
+ msm_mux_gcc_tlmm,
+ msm_mux_gpio,
+ msm_mux_i2c0_scl,
+ msm_mux_i2c0_sda,
+ msm_mux_i2c1_scl,
+ msm_mux_i2c1_sda,
+ msm_mux_i2c11,
+ msm_mux_mac0,
+ msm_mux_mac1,
+ msm_mux_mdc_mst,
+ msm_mux_mdc_slv,
+ msm_mux_mdio_mst,
+ msm_mux_mdio_slv,
+ msm_mux_pcie0_clk,
+ msm_mux_pcie0_wake,
+ msm_mux_pcie1_clk,
+ msm_mux_pcie1_wake,
+ msm_mux_pcie2_clk,
+ msm_mux_pcie2_wake,
+ msm_mux_pcie3_clk,
+ msm_mux_pcie3_wake,
+ msm_mux_pll_test,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_prng_rosc2,
+ msm_mux_prng_rosc3,
+ msm_mux_PTA0_0,
+ msm_mux_PTA0_1,
+ msm_mux_PTA0_2,
+ msm_mux_PTA10,
+ msm_mux_PTA11,
+ msm_mux_pwm0,
+ msm_mux_pwm1,
+ msm_mux_pwm2,
+ msm_mux_qdss_cti_trig_in_a0,
+ msm_mux_qdss_cti_trig_out_a0,
+ msm_mux_qdss_cti_trig_in_a1,
+ msm_mux_qdss_cti_trig_out_a1,
+ msm_mux_qdss_cti_trig_in_b0,
+ msm_mux_qdss_cti_trig_out_b0,
+ msm_mux_qdss_cti_trig_in_b1,
+ msm_mux_qdss_cti_trig_out_b1,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qspi_data,
+ msm_mux_resout,
+ msm_mux_rx0,
+ msm_mux_rx1,
+ msm_mux_rx2,
+ msm_mux_sdc_clk,
+ msm_mux_sdc_cmd,
+ msm_mux_sdc_data,
+ msm_mux_spi0_clk,
+ msm_mux_spi0_cs,
+ msm_mux_spi0_miso,
+ msm_mux_spi0_mosi,
+ msm_mux_spi1,
+ msm_mux_spi10,
+ msm_mux_spi11,
+ msm_mux_tsens_max,
+ msm_mux_uart0,
+ msm_mux_uart1,
+ msm_mux_wci_txd,
+ msm_mux_wci_rxd,
+ msm_mux_wsi_clk,
+ msm_mux_wsi_data,
+ msm_mux__,
+};
+
+#define MSM_PIN_FUNCTION(fname) \
+ [msm_mux_##fname] = {#fname, msm_mux_##fname}
+
+static const struct pinctrl_function ipq5424_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_tic),
+ MSM_PIN_FUNCTION(audio_pri),
+ MSM_PIN_FUNCTION(audio_pri0),
+ MSM_PIN_FUNCTION(audio_pri1),
+ MSM_PIN_FUNCTION(audio_sec),
+ MSM_PIN_FUNCTION(audio_sec0),
+ MSM_PIN_FUNCTION(audio_sec1),
+ MSM_PIN_FUNCTION(core_voltage),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cri_trng2),
+ MSM_PIN_FUNCTION(cri_trng3),
+ MSM_PIN_FUNCTION(cxc_clk),
+ MSM_PIN_FUNCTION(cxc_data),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(i2c0_scl),
+ MSM_PIN_FUNCTION(i2c0_sda),
+ MSM_PIN_FUNCTION(i2c1_scl),
+ MSM_PIN_FUNCTION(i2c1_sda),
+ MSM_PIN_FUNCTION(i2c11),
+ MSM_PIN_FUNCTION(mac0),
+ MSM_PIN_FUNCTION(mac1),
+ MSM_PIN_FUNCTION(mdc_mst),
+ MSM_PIN_FUNCTION(mdc_slv),
+ MSM_PIN_FUNCTION(mdio_mst),
+ MSM_PIN_FUNCTION(mdio_slv),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(pcie1_clk),
+ MSM_PIN_FUNCTION(pcie1_wake),
+ MSM_PIN_FUNCTION(pcie2_clk),
+ MSM_PIN_FUNCTION(pcie2_wake),
+ MSM_PIN_FUNCTION(pcie3_clk),
+ MSM_PIN_FUNCTION(pcie3_wake),
+ MSM_PIN_FUNCTION(pll_test),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(PTA0_0),
+ MSM_PIN_FUNCTION(PTA0_1),
+ MSM_PIN_FUNCTION(PTA0_2),
+ MSM_PIN_FUNCTION(PTA10),
+ MSM_PIN_FUNCTION(PTA11),
+ MSM_PIN_FUNCTION(pwm0),
+ MSM_PIN_FUNCTION(pwm1),
+ MSM_PIN_FUNCTION(pwm2),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(resout),
+ MSM_PIN_FUNCTION(rx0),
+ MSM_PIN_FUNCTION(rx1),
+ MSM_PIN_FUNCTION(rx2),
+ MSM_PIN_FUNCTION(sdc_clk),
+ MSM_PIN_FUNCTION(sdc_cmd),
+ MSM_PIN_FUNCTION(sdc_data),
+ MSM_PIN_FUNCTION(spi0_clk),
+ MSM_PIN_FUNCTION(spi0_cs),
+ MSM_PIN_FUNCTION(spi0_miso),
+ MSM_PIN_FUNCTION(spi0_mosi),
+ MSM_PIN_FUNCTION(spi1),
+ MSM_PIN_FUNCTION(spi10),
+ MSM_PIN_FUNCTION(spi11),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(uart0),
+ MSM_PIN_FUNCTION(uart1),
+ MSM_PIN_FUNCTION(wci_txd),
+ MSM_PIN_FUNCTION(wci_rxd),
+ MSM_PIN_FUNCTION(wsi_clk),
+ MSM_PIN_FUNCTION(wsi_data),
+};
+
+typedef unsigned int msm_pin_function[10];
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)\
+ [id] = { msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ }
+
+static const msm_pin_function ipq5424_pin_functions[] = {
+ PINGROUP(0, sdc_data, qspi_data, pwm2, wci_txd, wci_rxd, _, _, _, _),
+ PINGROUP(1, sdc_data, qspi_data, pwm2, wci_txd, wci_rxd, _, _, _, _),
+ PINGROUP(2, sdc_data, qspi_data, pwm2, _, _, _, _, _, _),
+ PINGROUP(3, sdc_data, qspi_data, pwm2, _, _, _, _, _, _),
+ PINGROUP(4, sdc_cmd, qspi_cs, _, _, _, _, _, _, _),
+ PINGROUP(5, sdc_clk, qspi_clk, _, _, _, _, _, _, _),
+ PINGROUP(6, spi0_clk, pwm1, _, cri_trng0, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(7, spi0_cs, pwm1, _, cri_trng1, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(8, spi0_miso, pwm1, wci_txd, wci_rxd, _, cri_trng2, qdss_tracedata_a, _, _),
+ PINGROUP(9, spi0_mosi, pwm1, _, cri_trng3, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(10, uart0, pwm0, spi11, _, wci_txd, wci_rxd, _, qdss_tracedata_a, _),
+ PINGROUP(11, uart0, pwm0, spi1, _, wci_txd, wci_rxd, _, qdss_tracedata_a, _),
+ PINGROUP(12, uart0, pwm0, spi11, _, prng_rosc0, qdss_tracedata_a, _, _, _),
+ PINGROUP(13, uart0, pwm0, spi11, _, prng_rosc1, qdss_tracedata_a, _, _, _),
+ PINGROUP(14, i2c0_scl, tsens_max, _, prng_rosc2, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(15, i2c0_sda, _, prng_rosc3, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(16, core_voltage, i2c1_scl, _, _, _, _, _, _, _),
+ PINGROUP(17, core_voltage, i2c1_sda, _, _, _, _, _, _, _),
+ PINGROUP(18, _, _, _, _, _, _, _, _, _),
+ PINGROUP(19, _, _, _, _, _, _, _, _, _),
+ PINGROUP(20, mdc_slv, atest_char0, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(21, mdio_slv, atest_char1, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(22, mdc_mst, atest_char2, _, _, _, _, _, _, _),
+ PINGROUP(23, mdio_mst, atest_char3, _, _, _, _, _, _, _),
+ PINGROUP(24, pcie0_clk, PTA10, mac0, _, wsi_clk, _, atest_char, qdss_cti_trig_out_a0, _),
+ PINGROUP(25, _, _, _, _, _, _, _, _, _),
+ PINGROUP(26, pcie0_wake, PTA10, mac0, _, wsi_data, _, qdss_cti_trig_in_a0, _, _),
+ PINGROUP(27, pcie1_clk, i2c11, PTA10, wsi_clk, qdss_cti_trig_out_a1, _, _, _, _),
+ PINGROUP(28, _, _, _, _, _, _, _, _, _),
+ PINGROUP(29, pcie1_wake, i2c11, wsi_data, qdss_cti_trig_in_a1, _, _, _, _, _),
+ PINGROUP(30, pcie2_clk, PTA11, mac1, qdss_cti_trig_out_b0, _, _, _, _, _),
+ PINGROUP(31, _, _, _, _, _, _, _, _, _),
+ PINGROUP(32, pcie2_wake, PTA11, mac1, audio_pri0, audio_pri0, qdss_cti_trig_in_b0, _, _, _),
+ PINGROUP(33, pcie3_clk, PTA11, audio_pri1, audio_pri1, qdss_cti_trig_out_b1, _, _, _, _),
+ PINGROUP(34, _, _, _, _, _, _, _, _, _),
+ PINGROUP(35, pcie3_wake, audio_sec1, audio_sec1, qdss_cti_trig_in_b1, _, _, _, _, _),
+ PINGROUP(36, audio_pri, spi1, audio_sec0, audio_sec0, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(37, audio_pri, spi1, rx2, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(38, audio_pri, spi1, pll_test, rx1, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(39, audio_pri, rx0, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(40, PTA0_0, wci_txd, wci_rxd, _, atest_tic, _, _, _, _),
+ PINGROUP(41, PTA0_1, wci_txd, wci_rxd, cxc_data, _, _, _, _, _),
+ PINGROUP(42, PTA0_2, cxc_clk, _, _, _, _, _, _, _),
+ PINGROUP(43, uart1, gcc_plltest, _, _, _, _, _, _, _),
+ PINGROUP(44, uart1, gcc_tlmm, _, _, _, _, _, _, _),
+ PINGROUP(45, spi10, rx2, audio_sec, gcc_plltest, _, qdss_traceclk_a, _, _, _),
+ PINGROUP(46, spi1, rx1, audio_sec, dbg_out, qdss_tracectl_a, _, _, _, _),
+ PINGROUP(47, spi10, rx0, audio_sec, _, _, _, _, _, _),
+ PINGROUP(48, spi10, audio_sec, _, _, _, _, _, _, _),
+ PINGROUP(49, resout, _, _, _, _, _, _, _, _),
+};
+
+static const char *ipq5424_get_function_name(struct udevice *dev,
+ unsigned int selector)
+{
+ return ipq5424_functions[selector].name;
+}
+
+static const char *ipq5424_get_pin_name(struct udevice *dev,
+ unsigned int selector)
+{
+ snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+ return pin_name;
+}
+
+static int ipq5424_get_function_mux(unsigned int pin, unsigned int selector)
+{
+ unsigned int i;
+ const msm_pin_function *func = ipq5424_pin_functions + pin;
+
+ for (i = 0; i < 10; i++)
+ if ((*func)[i] == selector)
+ return i;
+
+ debug("Can't find requested function for pin:selector %u:%u\n",
+ pin, selector);
+
+ return -EINVAL;
+}
+
+static const struct msm_pinctrl_data ipq5424_data = {
+ .pin_data = {
+ .pin_count = 49,
+ },
+ .functions_count = ARRAY_SIZE(ipq5424_functions),
+ .get_function_name = ipq5424_get_function_name,
+ .get_function_mux = ipq5424_get_function_mux,
+ .get_pin_name = ipq5424_get_pin_name,
+};
+
+static const struct udevice_id msm_pinctrl_ids[] = {
+ { .compatible = "qcom,ipq5424-tlmm", .data = (ulong)&ipq5424_data },
+ { /* Sentinal */ }
+};
+
+U_BOOT_DRIVER(pinctrl_ipq5424) = {
+ .name = "pinctrl_ipq5424",
+ .id = UCLASS_NOP,
+ .of_match = msm_pinctrl_ids,
+ .ops = &msm_pinctrl_ops,
+ .bind = msm_pinctrl_bind,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index a14555cf472..3bc696d4caa 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -91,7 +91,7 @@ void rk8xx_off_for_plugin(struct udevice *dev)
static struct reg_data rk806_init_reg[] = {
/* RST_FUN */
- { RK806_REG_SYS_CFG3, GENMASK(7, 6), BIT(7)},
+ { RK806_REG_SYS_CFG3, BIT(7), GENMASK(7, 6)},
};
static struct reg_data rk817_init_reg[] = {
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 7ed435f0202..65b99e89656 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -264,6 +264,15 @@ config REGULATOR_RK8XX
by the PMIC device. This driver is controlled by a device tree node
which includes voltage limits.
+config SPL_REGULATOR_RK8XX
+ bool "Enable driver for RK8XX regulators in SPL"
+ depends on SPL_DM_REGULATOR && SPL_PMIC_RK8XX
+ help
+ Enable support for the regulator functions of the RK8XX PMIC in SPL. The
+ driver implements get/set api for the various BUCKS and LDOs supported
+ by the PMIC device. This driver is controlled by a device tree node
+ which includes voltage limits.
+
config DM_REGULATOR_S2MPS11
bool "Enable driver for S2MPS11 regulator"
depends on DM_REGULATOR && PMIC_S2MPS11
diff --git a/drivers/power/regulator/act8846.c b/drivers/power/regulator/act8846.c
index d3e72da0d35..144032692f6 100644
--- a/drivers/power/regulator/act8846.c
+++ b/drivers/power/regulator/act8846.c
@@ -29,7 +29,7 @@ enum {
REG_SYS0,
REG_SYS1,
REG1_VOL = 0x10,
- REG1_CTL = 0X11,
+ REG1_CTL = 0x11,
REG2_VOL0 = 0x20,
REG2_VOL1,
REG2_CTL,
@@ -41,7 +41,7 @@ enum {
REG4_CTL,
REG5_VOL = 0x50,
REG5_CTL,
- REG6_VOL = 0X58,
+ REG6_VOL = 0x58,
REG6_CTL,
REG7_VOL = 0x60,
REG7_CTL,
diff --git a/drivers/power/regulator/qcom_usb_vbus_regulator.c b/drivers/power/regulator/qcom_usb_vbus_regulator.c
index 2d58ef5e111..07f118d4797 100644
--- a/drivers/power/regulator/qcom_usb_vbus_regulator.c
+++ b/drivers/power/regulator/qcom_usb_vbus_regulator.c
@@ -15,14 +15,33 @@
#include <power/pmic.h>
#include <power/regulator.h>
-#define CMD_OTG 0x50
+enum pm8x50b_vbus {
+ PM8150B,
+ PM8550B,
+};
+
#define OTG_EN BIT(0)
-// The 0 bit in this register's bit field is undocumented
-#define OTG_CFG 0x56
+
#define OTG_EN_SRC_CFG BIT(1)
+struct qcom_otg_regs {
+ u32 otg_cmd;
+ u32 otg_cfg;
+};
struct qcom_usb_vbus_priv {
phys_addr_t base;
+ struct qcom_otg_regs *regs;
+};
+
+static const struct qcom_otg_regs qcom_otg[] = {
+ [PM8150B] = {
+ .otg_cmd = 0x40,
+ .otg_cfg = 0x53,
+ },
+ [PM8550B] = {
+ .otg_cmd = 0x50,
+ .otg_cfg = 0x56,
+ },
};
static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev)
@@ -38,8 +57,9 @@ static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev)
static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev)
{
+ const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)];
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
- int otg_en_reg = priv->base + CMD_OTG;
+ int otg_en_reg = priv->base + regs->otg_cmd;
int ret;
ret = pmic_reg_read(dev->parent, otg_en_reg);
@@ -53,8 +73,9 @@ static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev)
static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable)
{
+ const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)];
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
- int otg_en_reg = priv->base + CMD_OTG;
+ int otg_en_reg = priv->base + regs->otg_cmd;
int ret;
if (enable) {
@@ -76,8 +97,9 @@ static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable)
static int qcom_usb_vbus_regulator_probe(struct udevice *dev)
{
+ const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)];
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
- int otg_cfg_reg = priv->base + OTG_CFG;
+ int otg_cfg_reg = priv->base + regs->otg_cfg;
int ret;
/* Disable HW logic for VBUS enable */
@@ -96,7 +118,8 @@ static const struct dm_regulator_ops qcom_usb_vbus_regulator_ops = {
};
static const struct udevice_id qcom_usb_vbus_regulator_ids[] = {
- { .compatible = "qcom,pm8150b-vbus-reg"},
+ { .compatible = "qcom,pm8150b-vbus-reg", .data = PM8150B },
+ { .compatible = "qcom,pm8550b-vbus-reg", .data = PM8550B },
{ },
};
diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c
index 368675ebb9f..88453bb7bdb 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -16,10 +16,6 @@
#include <power/pmic.h>
#include <power/regulator.h>
-#ifndef CONFIG_XPL_BUILD
-#define ENABLE_DRIVER
-#endif
-
/* Not used or exisit register and configure */
#define NA 0xff
@@ -202,7 +198,7 @@ static const struct rk8xx_reg_info rk818_buck[] = {
{ 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, 0x00, 0x1f },
};
-#ifdef ENABLE_DRIVER
+#if CONFIG_IS_ENABLED(REGULATOR_RK8XX)
static const struct rk8xx_reg_info rk806_nldo[] = {
/* nldo 1 */
{ 500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7},
@@ -454,7 +450,7 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
return ret;
}
-#ifdef ENABLE_DRIVER
+#if CONFIG_IS_ENABLED(REGULATOR_RK8XX)
static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt)
{
const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index de312656746..e4c676d75c2 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -126,3 +126,9 @@ config PWM_TI_EHRPWM
default y
help
PWM driver support for the EHRPWM controller found on TI SOCs.
+
+config PWM_TI_ECAP
+ bool "Enable support for ECAP PWM"
+ depends on DM_PWM && ARCH_OMAP2PLUS
+ help
+ PWM driver support for the ECAP controller found on TI SOCs.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 76305b93bc9..2682c536c6f 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o
obj-$(CONFIG_PWM_STM32) += pwm-stm32.o
obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o
obj-$(CONFIG_PWM_TI_EHRPWM) += pwm-ti-ehrpwm.o
+obj-$(CONFIG_PWM_TI_ECAP) += pwm-tiecap.o
diff --git a/drivers/pwm/pwm-ti-ehrpwm.c b/drivers/pwm/pwm-ti-ehrpwm.c
index 563109ef0f8..135ea3b4321 100644
--- a/drivers/pwm/pwm-ti-ehrpwm.c
+++ b/drivers/pwm/pwm-ti-ehrpwm.c
@@ -399,7 +399,7 @@ static int ti_ehrpwm_of_to_plat(struct udevice *dev)
return -EINVAL;
}
- dev_dbg(dev, "regs=0x%08lx\n", priv->regs);
+ dev_dbg(dev, "regs=0x%08x\n", priv->regs);
return 0;
}
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
new file mode 100644
index 00000000000..cfd6c871b57
--- /dev/null
+++ b/drivers/pwm/pwm-tiecap.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * ECAP PWM driver
+ *
+ * Copyright (C) 2025 BayLibre, SAS
+ * Author: Sukrut Bellary <sbellary@baylibre.com>
+ */
+
+#include <clk.h>
+#include <div64.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <pwm.h>
+#include <asm/io.h>
+
+/* eCAP module registers */
+#define ECAP_PWM_CAP1 0x08
+#define ECAP_PWM_CAP2 0x0C
+#define ECAP_PWM_CAP3 0x10
+#define ECAP_PWM_CAP4 0x14
+
+#define ECAP_PWM_ECCTL2 0x2A
+#define ECAP_PWM_ECCTL2_APWM_POL_LOW BIT(10)
+#define ECAP_PWM_ECCTL2_APWM_MODE BIT(9)
+#define ECAP_PWM_ECCTL2_TSCTR_FREERUN BIT(4)
+#define ECAP_PWM_ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6))
+
+#define NSEC_PER_SEC 1000000000L
+
+enum tiecap_pwm_polarity {
+ TIECAP_PWM_POLARITY_NORMAL,
+ TIECAP_PWM_POLARITY_INVERSED
+};
+
+enum tiecap_pwm_state {
+ TIECAP_APWM_DISABLED,
+ TIECAP_APWM_ENABLED
+};
+
+struct tiecap_pwm_priv {
+ fdt_addr_t regs;
+ u32 clk_rate;
+ enum tiecap_pwm_state pwm_state;
+};
+
+static int tiecap_pwm_set_config(struct udevice *dev, uint channel,
+ uint period_ns, uint duty_ns)
+{
+ struct tiecap_pwm_priv *priv = dev_get_priv(dev);
+ u32 period_cycles, duty_cycles;
+ unsigned long long c;
+ u16 value;
+
+ c = priv->clk_rate;
+ c = c * period_ns;
+ do_div(c, NSEC_PER_SEC);
+ period_cycles = (u32)c;
+
+ if (period_cycles < 1) {
+ period_cycles = 1;
+ duty_cycles = 1;
+ } else {
+ c = priv->clk_rate;
+ c = c * duty_ns;
+ do_div(c, NSEC_PER_SEC);
+ duty_cycles = (u32)c;
+ }
+
+ value = readw(priv->regs + ECAP_PWM_ECCTL2);
+
+ /* Configure APWM mode & disable sync option */
+ value |= ECAP_PWM_ECCTL2_APWM_MODE | ECAP_PWM_ECCTL2_SYNC_SEL_DISA;
+
+ writew(value, priv->regs + ECAP_PWM_ECCTL2);
+
+ if (priv->pwm_state == TIECAP_APWM_DISABLED) {
+ /* Update active registers */
+ writel(duty_cycles, priv->regs + ECAP_PWM_CAP2);
+ writel(period_cycles, priv->regs + ECAP_PWM_CAP1);
+ } else {
+ /* Update shadow registers to configure period and
+ * compare values. This helps current pwm period to
+ * complete on reconfiguring.
+ */
+ writel(duty_cycles, priv->regs + ECAP_PWM_CAP4);
+ writel(period_cycles, priv->regs + ECAP_PWM_CAP3);
+ }
+
+ return 0;
+}
+
+static int tiecap_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
+{
+ struct tiecap_pwm_priv *priv = dev_get_priv(dev);
+ u16 value;
+
+ value = readw(priv->regs + ECAP_PWM_ECCTL2);
+
+ if (enable) {
+ /*
+ * Enable 'Free run Time stamp counter mode' to start counter
+ * and 'APWM mode' to enable APWM output
+ */
+ value |= ECAP_PWM_ECCTL2_TSCTR_FREERUN | ECAP_PWM_ECCTL2_APWM_MODE;
+ priv->pwm_state = TIECAP_APWM_ENABLED;
+ } else {
+ /* Disable 'Free run Time stamp counter mode' to stop counter
+ * and 'APWM mode' to put APWM output to low
+ */
+ value &= ~(ECAP_PWM_ECCTL2_TSCTR_FREERUN | ECAP_PWM_ECCTL2_APWM_MODE);
+ priv->pwm_state = TIECAP_APWM_DISABLED;
+ }
+
+ writew(value, priv->regs + ECAP_PWM_ECCTL2);
+
+ return 0;
+}
+
+static int tiecap_pwm_set_invert(struct udevice *dev, uint channel,
+ bool polarity)
+{
+ struct tiecap_pwm_priv *priv = dev_get_priv(dev);
+ u16 value;
+
+ value = readw(priv->regs + ECAP_PWM_ECCTL2);
+
+ if (polarity == TIECAP_PWM_POLARITY_INVERSED)
+ /* Duty cycle defines LOW period of PWM */
+ value |= ECAP_PWM_ECCTL2_APWM_POL_LOW;
+ else
+ /* Duty cycle defines HIGH period of PWM */
+ value &= ~ECAP_PWM_ECCTL2_APWM_POL_LOW;
+
+ writew(value, priv->regs + ECAP_PWM_ECCTL2);
+
+ return 0;
+}
+
+static int tiecap_pwm_of_to_plat(struct udevice *dev)
+{
+ struct tiecap_pwm_priv *priv = dev_get_priv(dev);
+
+ priv->regs = dev_read_addr(dev);
+ if (priv->regs == FDT_ADDR_T_NONE) {
+ dev_err(dev, "invalid address\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "regs=0x%08x\n", priv->regs);
+
+ return 0;
+}
+
+static int tiecap_pwm_probe(struct udevice *dev)
+{
+ struct tiecap_pwm_priv *priv = dev_get_priv(dev);
+ struct clk clk;
+ int err;
+
+ err = clk_get_by_name(dev, "fck", &clk);
+ if (err) {
+ dev_err(dev, "failed to get clock\n");
+ return err;
+ }
+
+ priv->clk_rate = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(priv->clk_rate) || !priv->clk_rate) {
+ dev_err(dev, "failed to get clock rate\n");
+ if (IS_ERR_VALUE(priv->clk_rate))
+ return priv->clk_rate;
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct pwm_ops tiecap_pwm_ops = {
+ .set_config = tiecap_pwm_set_config,
+ .set_enable = tiecap_pwm_set_enable,
+ .set_invert = tiecap_pwm_set_invert,
+};
+
+static const struct udevice_id tiecap_pwm_ids[] = {
+ { .compatible = "ti,am3352-ecap" },
+ { .compatible = "ti,am33xx-ecap" },
+ { }
+};
+
+U_BOOT_DRIVER(tiecap_pwm) = {
+ .name = "tiecap_pwm",
+ .id = UCLASS_PWM,
+ .of_match = tiecap_pwm_ids,
+ .ops = &tiecap_pwm_ops,
+ .probe = tiecap_pwm_probe,
+ .of_to_plat = tiecap_pwm_of_to_plat,
+ .priv_auto = sizeof(struct tiecap_pwm_priv),
+};
diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c
index 9631337b8d9..69b7de084e5 100644
--- a/drivers/qe/qe.c
+++ b/drivers/qe/qe.c
@@ -243,7 +243,7 @@ void u_qe_init(void)
CFG_SYS_FSL_QSPI_BASE);
if (src == BOOT_SOURCE_SD_MMC) {
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
@@ -252,7 +252,7 @@ void u_qe_init(void)
return;
}
addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
- struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+ struct mmc *mmc = find_mmc_device(CONFIG_ENV_MMC_DEVICE_INDEX);
if (!mmc) {
free(addr);
@@ -277,7 +277,7 @@ void u_qe_init(void)
void *addr = (void *)CONFIG_SYS_QE_FW_ADDR;
#ifdef CONFIG_SYS_QE_FMAN_FW_IN_MMC
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
u32 blk = CONFIG_SYS_QE_FW_ADDR / 512;
@@ -286,7 +286,7 @@ void u_qe_init(void)
return;
}
addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
- struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+ struct mmc *mmc = find_mmc_device(CONFIG_ENV_MMC_DEVICE_INDEX);
if (!mmc) {
printf("\nMMC cannot find device for ucode\n");
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index 39d03e8d3d3..edb8e254d5b 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -1,3 +1,5 @@
+menu "RAM drivers using Driver Model"
+
config RAM
bool "Enable RAM drivers using Driver Model"
depends on DM
@@ -136,3 +138,5 @@ source "drivers/ram/stm32mp1/Kconfig"
source "drivers/ram/starfive/Kconfig"
source "drivers/ram/sunxi/Kconfig"
source "drivers/ram/thead/Kconfig"
+
+endmenu
diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index ff87faf6a22..6590d57ad84 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -35,7 +35,7 @@
#define DDRSS_V2A_CTL_REG_SDRAM_IDX_CALC(x) ((ilog2(x) - 16) << 5)
#define DDRSS_V2A_CTL_REG_SDRAM_IDX_MASK (~(0x1F << 0x5))
-#define DDRSS_V2A_CTL_REG_REGION_IDX_MASK (~(0X1F))
+#define DDRSS_V2A_CTL_REG_REGION_IDX_MASK (~(0x1F))
#define DDRSS_V2A_CTL_REG_REGION_IDX_DEFAULT 0xF
#define DDRSS_ECC_CTRL_REG_DEFAULT 0x0
diff --git a/drivers/ram/octeon/octeon3_lmc.c b/drivers/ram/octeon/octeon3_lmc.c
index eaef0fa5c12..dc4b8f8cf23 100644
--- a/drivers/ram/octeon/octeon3_lmc.c
+++ b/drivers/ram/octeon/octeon3_lmc.c
@@ -8692,7 +8692,7 @@ int init_octeon3_ddr3_interface(struct ddr_priv *priv,
bank_bits = min((int)bank_bits, 4);
spd_package =
- 0XFF & read_spd(&dimm_config_table[0], 0,
+ 0xFF & read_spd(&dimm_config_table[0], 0,
DDR4_SPD_PACKAGE_TYPE);
if (spd_package & 0x80) { // non-monolithic device
is_stacked_die = ((spd_package & 0x73) == 0x11);
diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig
index 67c63ecba04..d707d09c1c8 100644
--- a/drivers/ram/rockchip/Kconfig
+++ b/drivers/ram/rockchip/Kconfig
@@ -15,6 +15,7 @@ if RAM_ROCKCHIP
config RAM_ROCKCHIP_DEBUG
bool "Rockchip ram drivers debugging"
+ depends on DEBUG_UART
default y
help
This enables debugging ram driver API's for the platforms
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c
index 0e37ea93fbc..b275407d4ac 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c
@@ -12,6 +12,7 @@
#include <timer.h>
#include <asm/io.h>
#include <asm/arch/ddr.h>
+#include <dm/device.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
@@ -19,7 +20,8 @@
#include "stm32mp1_ddr.h"
#include "stm32mp1_ddr_regs.h"
-#define RCC_DDRITFCR 0xD8
+#define RCC_DDRITFCR_STM32MP13xx 0x5c0
+#define RCC_DDRITFCR_STM32MP15xx 0xd8
#define RCC_DDRITFCR_DDRCAPBRST (BIT(14))
#define RCC_DDRITFCR_DDRCAXIRST (BIT(15))
@@ -66,9 +68,19 @@ struct reg_desc {
#define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */
#define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */
#define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */
-#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */
-#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */
+#define DDRCTL_REG_PERF_SIZE_STM32MP13xx 11 /* st,ctl-perf */
+#define DDRCTL_REG_PERF_SIZE_STM32MP15xx 17 /* st,ctl-perf */
+#define DDRCTL_REG_PERF_SIZE \
+ (IS_ENABLED(CONFIG_STM32MP15X) ? DDRCTL_REG_PERF_SIZE_STM32MP15xx : \
+ DDRCTL_REG_PERF_SIZE_STM32MP13xx)
+
+#define DDRPHY_REG_REG_SIZE_STM32MP13xx 9 /* st,phy-reg */
+#define DDRPHY_REG_REG_SIZE_STM32MP15xx 11 /* st,phy-reg */
+#define DDRPHY_REG_REG_SIZE \
+ (IS_ENABLED(CONFIG_STM32MP15X) ? DDRPHY_REG_REG_SIZE_STM32MP15xx : \
+ DDRPHY_REG_REG_SIZE_STM32MP13xx)
+
#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */
#define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg)
@@ -142,12 +154,14 @@ static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = {
DDRCTL_REG_PERF(pcfgqos1_0),
DDRCTL_REG_PERF(pcfgwqos0_0),
DDRCTL_REG_PERF(pcfgwqos1_0),
+#if IS_ENABLED(CONFIG_STM32MP15X)
DDRCTL_REG_PERF(pcfgr_1),
DDRCTL_REG_PERF(pcfgw_1),
DDRCTL_REG_PERF(pcfgqos0_1),
DDRCTL_REG_PERF(pcfgqos1_1),
DDRCTL_REG_PERF(pcfgwqos0_1),
DDRCTL_REG_PERF(pcfgwqos1_1),
+#endif
};
#define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg)
@@ -161,8 +175,10 @@ static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = {
DDRPHY_REG_REG(zq0cr1),
DDRPHY_REG_REG(dx0gcr),
DDRPHY_REG_REG(dx1gcr),
+#if IS_ENABLED(CONFIG_STM32MP15X)
DDRPHY_REG_REG(dx2gcr),
DDRPHY_REG_REG(dx3gcr),
+#endif
};
#define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing)
@@ -211,6 +227,7 @@ static const struct reg_desc ddrphy_dyn[] = {
DDRPHY_REG_DYN(dx1dllcr),
DDRPHY_REG_DYN(dx1dqtr),
DDRPHY_REG_DYN(dx1dqstr),
+#if IS_ENABLED(CONFIG_STM32MP15X)
DDRPHY_REG_DYN(dx2gsr0),
DDRPHY_REG_DYN(dx2gsr1),
DDRPHY_REG_DYN(dx2dllcr),
@@ -221,6 +238,7 @@ static const struct reg_desc ddrphy_dyn[] = {
DDRPHY_REG_DYN(dx3dllcr),
DDRPHY_REG_DYN(dx3dqtr),
DDRPHY_REG_DYN(dx3dqstr),
+#endif
};
#define DDRPHY_REG_DYN_SIZE ARRAY_SIZE(ddrphy_dyn)
@@ -287,6 +305,24 @@ const char *base_name[] = {
[DDRPHY_BASE] = "phy",
};
+bool is_stm32mp13_ddrc(const struct ddr_info *priv)
+{
+ if (IS_ENABLED(CONFIG_STM32MP13X) && !IS_ENABLED(CONFIG_STM32MP15X))
+ return true; /* STM32MP13xx only build */
+ else if (!IS_ENABLED(CONFIG_STM32MP13X) && IS_ENABLED(CONFIG_STM32MP15X))
+ return false; /* STM32MP15xx only build */
+
+ /* Combined STM32MP13xx and STM32MP15xx build */
+ return device_is_compatible(priv->dev, "st,stm32mp13-ddr");
+}
+
+static u32 get_rcc_ddritfcr(const struct ddr_info *priv)
+{
+ return priv->rcc + (is_stm32mp13_ddrc(priv) ?
+ RCC_DDRITFCR_STM32MP13xx :
+ RCC_DDRITFCR_STM32MP15xx);
+}
+
static u32 get_base_addr(const struct ddr_info *priv, enum base_type base)
{
if (base == DDRPHY_BASE)
@@ -295,6 +331,21 @@ static u32 get_base_addr(const struct ddr_info *priv, enum base_type base)
return (u32)priv->ctl;
}
+static u32 get_type_size(const struct ddr_info *priv, enum reg_type type)
+{
+ bool is_mp13 = is_stm32mp13_ddrc(priv);
+
+ if (type == REG_PERF)
+ return is_mp13 ? DDRCTL_REG_PERF_SIZE_STM32MP13xx :
+ DDRCTL_REG_PERF_SIZE_STM32MP15xx;
+ else if (type == REGPHY_REG)
+ return is_mp13 ? DDRPHY_REG_REG_SIZE_STM32MP13xx :
+ DDRPHY_REG_REG_SIZE_STM32MP15xx;
+
+ /* Everything else is the default size */
+ return ddr_registers[type].size;
+}
+
static void set_reg(const struct ddr_info *priv,
enum reg_type type,
const void *param)
@@ -304,9 +355,10 @@ static void set_reg(const struct ddr_info *priv,
enum base_type base = ddr_registers[type].base;
u32 base_addr = get_base_addr(priv, base);
const struct reg_desc *desc = ddr_registers[type].desc;
+ u32 size = get_type_size(priv, type);
log_debug("init %s\n", ddr_registers[type].name);
- for (i = 0; i < ddr_registers[type].size; i++) {
+ for (i = 0; i < size; i++) {
ptr = (unsigned int *)(base_addr + desc[i].offset);
if (desc[i].par_offset == INVALID_OFFSET) {
log_err("invalid parameter offset for %s", desc[i].name);
@@ -656,12 +708,13 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
static void stm32mp1_asr_enable(struct ddr_info *priv, const u32 pwrctl)
{
struct stm32mp1_ddrctl *ctl = priv->ctl;
+ u32 rcc_ddritfcr = get_rcc_ddritfcr(priv);
/* SSR is the best we can do. */
if (!(pwrctl & DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE))
return;
- clrsetbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK,
+ clrsetbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK,
RCC_DDRITFCR_DDRCKMOD_ASR);
start_sw_done(ctl);
@@ -691,6 +744,7 @@ __maybe_unused
void stm32mp1_ddr_init(struct ddr_info *priv,
const struct stm32mp1_ddr_config *config)
{
+ u32 rcc_ddritfcr = get_rcc_ddritfcr(priv);
u32 pir;
int ret = -EINVAL;
char bus_width;
@@ -732,12 +786,12 @@ start:
* 1.1 RESETS: presetn, core_ddrc_rstn, aresetn
*/
/* Assert All DDR part */
- setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
- setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
- setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
- setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
- setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
- setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
+ setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBRST);
+ setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAXIRST);
+ setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCORERST);
+ setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYAPBRST);
+ setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYRST);
+ setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYCTLRST);
/* 1.2. start CLOCK */
if (stm32mp1_ddr_clk_enable(priv, config->info.speed))
@@ -746,12 +800,12 @@ start:
/* 1.3. deassert reset */
/* de-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST */
- clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
- clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
+ clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYRST);
+ clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYCTLRST);
/* De-assert presetn once the clocks are active
* and stable via DDRCAPBRST bit
*/
- clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
+ clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBRST);
/* 1.4. wait 128 cycles to permit initialization of end logic */
udelay(2);
@@ -781,9 +835,9 @@ start:
goto start;
/* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */
- clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
- clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
- clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
+ clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCORERST);
+ clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAXIRST);
+ clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYAPBRST);
/* 3. start PHY init by accessing relevant PUBL registers
* (DXGCR, DCR, PTR*, MR*, DTPR*)
@@ -854,9 +908,12 @@ start:
/* Enable auto-self-refresh, which saves a bit of power at runtime. */
stm32mp1_asr_enable(priv, config->c_reg.pwrctl);
- /* enable uMCTL2 AXI port 0 and 1 */
+ /* enable uMCTL2 AXI port 0 */
setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
- setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
+
+ /* enable uMCTL2 AXI port 1 only on STM32MP15xx with 32bit DRAM bus */
+ if (!is_stm32mp13_ddrc(priv))
+ setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
if (INTERACTIVE(STEP_DDR_READY))
goto start;
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h
index 861efff92be..3621e6c9a1b 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.h
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h
@@ -105,12 +105,14 @@ struct stm32mp1_ddrctrl_perf {
u32 pcfgqos1_0;
u32 pcfgwqos0_0;
u32 pcfgwqos1_0;
+#if IS_ENABLED(CONFIG_STM32MP15X)
u32 pcfgr_1;
u32 pcfgw_1;
u32 pcfgqos0_1;
u32 pcfgqos1_1;
u32 pcfgwqos0_1;
u32 pcfgwqos1_1;
+#endif
};
struct stm32mp1_ddrphy_reg {
@@ -123,8 +125,10 @@ struct stm32mp1_ddrphy_reg {
u32 zq0cr1;
u32 dx0gcr;
u32 dx1gcr;
+#if IS_ENABLED(CONFIG_STM32MP15X)
u32 dx2gcr;
u32 dx3gcr;
+#endif
};
struct stm32mp1_ddrphy_timing {
@@ -181,4 +185,6 @@ bool stm32mp1_ddr_interactive(
enum stm32mp1_ddr_interact_step step,
const struct stm32mp1_ddr_config *config);
+bool is_stm32mp13_ddrc(const struct ddr_info *priv);
+
#endif
diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c
index e9cd6229ec4..5f9b91d50e4 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ram.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ram.c
@@ -33,6 +33,7 @@ static const char *const clkname[] = {
int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
{
+ bool is_mp13 = is_stm32mp13_ddrc(priv);
unsigned long ddrphy_clk;
unsigned long ddr_clk;
struct clk clk;
@@ -40,6 +41,10 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
unsigned int idx;
for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) {
+ /* DDRC2 clock are available only on STM32MP15xx */
+ if (is_mp13 && !strcmp(clkname[idx], "ddrc2"))
+ continue;
+
ret = clk_get_by_name(priv->dev, clkname[idx], &clk);
if (!ret)
diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c
index 57268e7f8ff..f4bab6868ee 100644
--- a/drivers/remoteproc/ti_k3_r5f_rproc.c
+++ b/drivers/remoteproc/ti_k3_r5f_rproc.c
@@ -834,8 +834,14 @@ static int k3_r5f_probe(struct udevice *dev)
return 0;
}
+ ret = k3_r5f_proc_request(core);
+ if (ret)
+ return ret;
+
/* Make sure Local reset is asserted. Redundant? */
reset_assert(&core->reset);
+
+ ti_sci_proc_release(&core->tsp);
}
ret = k3_r5f_rproc_configure(core);
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index a0d079c4555..e92bb8a7c39 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -28,13 +28,6 @@ config STI_RESET
Say Y if you want to control reset signals provided by system config
block.
-config STM32_RESET
- bool "Enable the STM32 reset"
- depends on ARCH_STM32 || ARCH_STM32MP
- help
- Support for reset controllers on STMicroelectronics STM32 family SoCs.
- This reset driver is compatible with STM32 F4/F7 and H7 SoCs.
-
config TEGRA_CAR_RESET
bool "Enable Tegra CAR-based reset driver"
depends on TEGRA_CAR
@@ -258,4 +251,6 @@ config RESET_SPACEMIT_K1
help
Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert
is supported.
+
+source "drivers/reset/stm32/Kconfig"
endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 1dd3cd99a14..ee5b009d134 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_DM_RESET) += reset-uclass.o
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
obj-$(CONFIG_STI_RESET) += sti-reset.o
-obj-$(CONFIG_STM32_RESET) += stm32-reset.o
obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o
obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
obj-$(CONFIG_RESET_AIROHA) += reset-airoha.o
@@ -36,3 +35,6 @@ obj-$(CONFIG_RESET_AT91) += reset-at91.o
obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o
obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
+
+obj-$(CONFIG_ARCH_STM32) += stm32/
+obj-$(CONFIG_ARCH_STM32MP) += stm32/
diff --git a/drivers/reset/stm32-reset.c b/drivers/reset/stm32-reset.c
deleted file mode 100644
index 9d4f361b251..00000000000
--- a/drivers/reset/stm32-reset.c
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
- * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics.
- */
-
-#define LOG_CATEGORY UCLASS_RESET
-
-#include <dm.h>
-#include <errno.h>
-#include <log.h>
-#include <malloc.h>
-#include <reset-uclass.h>
-#include <stm32_rcc.h>
-#include <asm/io.h>
-#include <dm/device_compat.h>
-#include <linux/bitops.h>
-
-/* offset of register without set/clear management */
-#define RCC_MP_GCR_OFFSET 0x10C
-
-/* reset clear offset for STM32MP RCC */
-#define RCC_CL 0x4
-
-struct stm32_reset_priv {
- fdt_addr_t base;
-};
-
-static int stm32_reset_assert(struct reset_ctl *reset_ctl)
-{
- struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
- int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
- int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
-
- dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
- reset_ctl->id, bank, offset);
-
- if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
- if (bank != RCC_MP_GCR_OFFSET)
- /* reset assert is done in rcc set register */
- writel(BIT(offset), priv->base + bank);
- else
- clrbits_le32(priv->base + bank, BIT(offset));
- else
- setbits_le32(priv->base + bank, BIT(offset));
-
- return 0;
-}
-
-static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
-{
- struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
- int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
- int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
-
- dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
- reset_ctl->id, bank, offset);
-
- if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
- if (bank != RCC_MP_GCR_OFFSET)
- /* reset deassert is done in rcc clr register */
- writel(BIT(offset), priv->base + bank + RCC_CL);
- else
- setbits_le32(priv->base + bank, BIT(offset));
- else
- clrbits_le32(priv->base + bank, BIT(offset));
-
- return 0;
-}
-
-static const struct reset_ops stm32_reset_ops = {
- .rst_assert = stm32_reset_assert,
- .rst_deassert = stm32_reset_deassert,
-};
-
-static int stm32_reset_probe(struct udevice *dev)
-{
- struct stm32_reset_priv *priv = dev_get_priv(dev);
-
- priv->base = dev_read_addr(dev);
- if (priv->base == FDT_ADDR_T_NONE) {
- /* for MFD, get address of parent */
- priv->base = dev_read_addr(dev->parent);
- if (priv->base == FDT_ADDR_T_NONE)
- return -EINVAL;
- }
-
- return 0;
-}
-
-U_BOOT_DRIVER(stm32_rcc_reset) = {
- .name = "stm32_rcc_reset",
- .id = UCLASS_RESET,
- .probe = stm32_reset_probe,
- .priv_auto = sizeof(struct stm32_reset_priv),
- .ops = &stm32_reset_ops,
-};
diff --git a/drivers/reset/stm32/Kconfig b/drivers/reset/stm32/Kconfig
new file mode 100644
index 00000000000..39dcfa0a9ca
--- /dev/null
+++ b/drivers/reset/stm32/Kconfig
@@ -0,0 +1,23 @@
+config RESET_STM32
+ bool "Enable the STM32 reset"
+ depends on ARCH_STM32
+ default y
+ help
+ Support for reset controllers on STMicroelectronics STM32 family SoCs.
+ This reset driver is compatible with STM32 F4/F7 and H7 SoCs.
+
+config RESET_STM32MP1
+ bool "Enable the STM32MP1 reset"
+ depends on STM32MP13X || STM32MP15X
+ default y
+ help
+ Support for reset controllers on STMicroelectronics STM32MP1 family SoCs.
+ This reset driver is compatible with STM32MP13 and STM32MP15 SoCs.
+
+config RESET_STM32MP25
+ bool "Enable the STM32MP25 reset"
+ depends on STM32MP25X
+ default y
+ help
+ Support for reset controllers on STMicroelectronics STM32MP2 family SoCs.
+ This reset driver is compatible with STM32MP25 SoCs.
diff --git a/drivers/reset/stm32/Makefile b/drivers/reset/stm32/Makefile
new file mode 100644
index 00000000000..c31ae524ba1
--- /dev/null
+++ b/drivers/reset/stm32/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+
+obj-y += stm32-reset-core.o
+
+obj-$(CONFIG_RESET_STM32) += stm32-reset.o
+obj-$(CONFIG_RESET_STM32MP1) += stm32-reset-mp1.o
+obj-$(CONFIG_RESET_STM32MP25) += stm32-reset-mp25.o
diff --git a/drivers/reset/stm32/stm32-reset-core.c b/drivers/reset/stm32/stm32-reset-core.c
new file mode 100644
index 00000000000..7dd92e07e1a
--- /dev/null
+++ b/drivers/reset/stm32/stm32-reset-core.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ * Author(s): Gabriel Fernandez, <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <dm.h>
+#include <reset-uclass.h>
+#include <stm32-reset-core.h>
+#include <stm32_rcc.h>
+#include <dm/device_compat.h>
+#include <linux/iopoll.h>
+
+static int stm32_reset_update(struct reset_ctl *reset_ctl, bool status)
+{
+ struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ const struct stm32_reset_data *data = priv->data;
+ const struct stm32_reset_cfg *ptr_line;
+ fdt_addr_t addr;
+
+ assert(priv->data->get_reset_line);
+
+ ptr_line = priv->data->get_reset_line(reset_ctl);
+ if (!ptr_line)
+ return -EPERM;
+
+ addr = priv->base + ptr_line->offset;
+
+ dev_dbg(reset_ctl->dev, "reset id=%ld offset=0x%x bit=%d status=%d\n",
+ reset_ctl->id, ptr_line->offset, ptr_line->bit_idx, status);
+
+ status = ptr_line->inverted ^ status;
+
+ if (ptr_line->set_clr) {
+ if (!status)
+ addr += data->clear_offset;
+
+ writel(BIT(ptr_line->bit_idx), addr);
+
+ } else {
+ if (status)
+ setbits_le32(addr, BIT(ptr_line->bit_idx));
+ else
+ clrbits_le32(addr, BIT(ptr_line->bit_idx));
+ }
+
+ /* Check deassert */
+ if (!status) {
+ u32 reg;
+
+ return readl_poll_timeout(addr, reg,
+ !(reg & BIT(ptr_line->bit_idx)),
+ data->reset_us);
+ }
+
+ return 0;
+}
+
+static int stm32_reset_assert(struct reset_ctl *reset_ctl)
+{
+ return stm32_reset_update(reset_ctl, true);
+}
+
+static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
+{
+ return stm32_reset_update(reset_ctl, false);
+}
+
+const struct reset_ops stm32_reset_ops = {
+ .rst_assert = stm32_reset_assert,
+ .rst_deassert = stm32_reset_deassert,
+};
+
+int stm32_reset_core_probe(struct udevice *dev,
+ const struct stm32_reset_data *data)
+{
+ struct stm32_reset_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_read_addr(dev);
+ if (priv->base == FDT_ADDR_T_NONE) {
+ /* for MFD, get address of parent */
+ priv->base = dev_read_addr(dev->parent);
+ if (priv->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+ }
+
+ priv->data = data;
+
+ assert(priv->data);
+
+ return 0;
+}
diff --git a/drivers/reset/stm32/stm32-reset-core.h b/drivers/reset/stm32/stm32-reset-core.h
new file mode 100644
index 00000000000..25a1aa152cb
--- /dev/null
+++ b/drivers/reset/stm32/stm32-reset-core.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */
+/*
+ * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
+ * Author(s): Gabriel Fernandez, <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <reset-uclass.h>
+
+struct stm32_reset_cfg {
+ u16 offset;
+ u8 bit_idx;
+ bool set_clr;
+ bool inverted;
+};
+
+struct stm32_reset_data {
+ const struct stm32_reset_cfg * (*get_reset_line)(struct reset_ctl *reset_ctl);
+ u32 clear_offset;
+ u32 reset_us;
+};
+
+struct stm32_reset_priv {
+ fdt_addr_t base;
+ struct stm32_reset_cfg reset_line;
+ const struct stm32_reset_data *data;
+};
+
+extern const struct reset_ops stm32_reset_ops;
+
+int stm32_reset_core_probe(struct udevice *dev,
+ const struct stm32_reset_data *data);
diff --git a/drivers/reset/stm32/stm32-reset-mp1.c b/drivers/reset/stm32/stm32-reset-mp1.c
new file mode 100644
index 00000000000..6863f6e64b7
--- /dev/null
+++ b/drivers/reset/stm32/stm32-reset-mp1.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics.
+ */
+
+#include <dm.h>
+#include <stm32-reset-core.h>
+
+/* Reset clear offset for STM32MP RCC */
+#define RCC_CLR_OFFSET 0x4
+
+/* Offset of register without set/clear management */
+#define RCC_MP_GCR_OFFSET 0x10C
+
+/* Timeout for deassert */
+#define STM32_DEASSERT_TIMEOUT_US 10000
+
+static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_ctl *reset_ctl)
+{
+ struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ struct stm32_reset_cfg *ptr_line = &priv->reset_line;
+ int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
+ int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
+
+ ptr_line->offset = bank;
+ ptr_line->bit_idx = offset;
+ ptr_line->set_clr = true;
+
+ if (ptr_line->offset == RCC_MP_GCR_OFFSET) {
+ ptr_line->set_clr = false;
+ ptr_line->inverted = true;
+ }
+
+ return ptr_line;
+}
+
+static const struct stm32_reset_data stm32mp1_reset_data = {
+ .get_reset_line = stm32_get_reset_line,
+ .clear_offset = RCC_CLR_OFFSET,
+ .reset_us = STM32_DEASSERT_TIMEOUT_US,
+};
+
+static int stm32_reset_probe(struct udevice *dev)
+{
+ return stm32_reset_core_probe(dev, &stm32mp1_reset_data);
+}
+
+U_BOOT_DRIVER(stm32mp25_rcc_reset) = {
+ .name = "stm32mp1_reset",
+ .id = UCLASS_RESET,
+ .probe = stm32_reset_probe,
+ .priv_auto = sizeof(struct stm32_reset_priv),
+ .ops = &stm32_reset_ops,
+};
diff --git a/drivers/reset/stm32/stm32-reset-mp25.c b/drivers/reset/stm32/stm32-reset-mp25.c
new file mode 100644
index 00000000000..91c0336bc58
--- /dev/null
+++ b/drivers/reset/stm32/stm32-reset-mp25.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ * Author(s): Gabriel Fernandez, <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <dm.h>
+#include <stm32-reset-core.h>
+#include <stm32mp25_rcc.h>
+#include <dt-bindings/reset/st,stm32mp25-rcc.h>
+
+/* Reset clear offset for STM32MP RCC */
+#define RCC_CLR_OFFSET 0x4
+
+/* Timeout for deassert */
+#define STM32_DEASSERT_TIMEOUT_US 10000
+
+#define RESET(id, _offset, _bit_idx, _set_clr) \
+ [id] = &(struct stm32_reset_cfg){ \
+ .offset = (_offset), \
+ .bit_idx = (_bit_idx), \
+ .set_clr = (_set_clr), \
+ }
+
+static const struct stm32_reset_cfg *stm32mp25_reset[STM32MP25_LAST_RESET] = {
+ RESET(TIM1_R, RCC_TIM1CFGR, 0, 0),
+ RESET(TIM2_R, RCC_TIM2CFGR, 0, 0),
+ RESET(TIM3_R, RCC_TIM3CFGR, 0, 0),
+ RESET(TIM4_R, RCC_TIM4CFGR, 0, 0),
+ RESET(TIM5_R, RCC_TIM5CFGR, 0, 0),
+ RESET(TIM6_R, RCC_TIM6CFGR, 0, 0),
+ RESET(TIM7_R, RCC_TIM7CFGR, 0, 0),
+ RESET(TIM8_R, RCC_TIM8CFGR, 0, 0),
+ RESET(TIM10_R, RCC_TIM10CFGR, 0, 0),
+ RESET(TIM11_R, RCC_TIM11CFGR, 0, 0),
+ RESET(TIM12_R, RCC_TIM12CFGR, 0, 0),
+ RESET(TIM13_R, RCC_TIM13CFGR, 0, 0),
+ RESET(TIM14_R, RCC_TIM14CFGR, 0, 0),
+ RESET(TIM15_R, RCC_TIM15CFGR, 0, 0),
+ RESET(TIM16_R, RCC_TIM16CFGR, 0, 0),
+ RESET(TIM17_R, RCC_TIM17CFGR, 0, 0),
+ RESET(TIM20_R, RCC_TIM20CFGR, 0, 0),
+ RESET(LPTIM1_R, RCC_LPTIM1CFGR, 0, 0),
+ RESET(LPTIM2_R, RCC_LPTIM2CFGR, 0, 0),
+ RESET(LPTIM3_R, RCC_LPTIM3CFGR, 0, 0),
+ RESET(LPTIM4_R, RCC_LPTIM4CFGR, 0, 0),
+ RESET(LPTIM5_R, RCC_LPTIM5CFGR, 0, 0),
+ RESET(SPI1_R, RCC_SPI1CFGR, 0, 0),
+ RESET(SPI2_R, RCC_SPI2CFGR, 0, 0),
+ RESET(SPI3_R, RCC_SPI3CFGR, 0, 0),
+ RESET(SPI4_R, RCC_SPI4CFGR, 0, 0),
+ RESET(SPI5_R, RCC_SPI5CFGR, 0, 0),
+ RESET(SPI6_R, RCC_SPI6CFGR, 0, 0),
+ RESET(SPI7_R, RCC_SPI7CFGR, 0, 0),
+ RESET(SPI8_R, RCC_SPI8CFGR, 0, 0),
+ RESET(SPDIFRX_R, RCC_SPDIFRXCFGR, 0, 0),
+ RESET(USART1_R, RCC_USART1CFGR, 0, 0),
+ RESET(USART2_R, RCC_USART2CFGR, 0, 0),
+ RESET(USART3_R, RCC_USART3CFGR, 0, 0),
+ RESET(UART4_R, RCC_UART4CFGR, 0, 0),
+ RESET(UART5_R, RCC_UART5CFGR, 0, 0),
+ RESET(USART6_R, RCC_USART6CFGR, 0, 0),
+ RESET(UART7_R, RCC_UART7CFGR, 0, 0),
+ RESET(UART8_R, RCC_UART8CFGR, 0, 0),
+ RESET(UART9_R, RCC_UART9CFGR, 0, 0),
+ RESET(LPUART1_R, RCC_LPUART1CFGR, 0, 0),
+ RESET(IS2M_R, RCC_IS2MCFGR, 0, 0),
+ RESET(I2C1_R, RCC_I2C1CFGR, 0, 0),
+ RESET(I2C2_R, RCC_I2C2CFGR, 0, 0),
+ RESET(I2C3_R, RCC_I2C3CFGR, 0, 0),
+ RESET(I2C4_R, RCC_I2C4CFGR, 0, 0),
+ RESET(I2C5_R, RCC_I2C5CFGR, 0, 0),
+ RESET(I2C6_R, RCC_I2C6CFGR, 0, 0),
+ RESET(I2C7_R, RCC_I2C7CFGR, 0, 0),
+ RESET(I2C8_R, RCC_I2C8CFGR, 0, 0),
+ RESET(SAI1_R, RCC_SAI1CFGR, 0, 0),
+ RESET(SAI2_R, RCC_SAI2CFGR, 0, 0),
+ RESET(SAI3_R, RCC_SAI3CFGR, 0, 0),
+ RESET(SAI4_R, RCC_SAI4CFGR, 0, 0),
+ RESET(MDF1_R, RCC_MDF1CFGR, 0, 0),
+ RESET(MDF2_R, RCC_ADF1CFGR, 0, 0),
+ RESET(FDCAN_R, RCC_FDCANCFGR, 0, 0),
+ RESET(HDP_R, RCC_HDPCFGR, 0, 0),
+ RESET(ADC12_R, RCC_ADC12CFGR, 0, 0),
+ RESET(ADC3_R, RCC_ADC3CFGR, 0, 0),
+ RESET(ETH1_R, RCC_ETH1CFGR, 0, 0),
+ RESET(ETH2_R, RCC_ETH2CFGR, 0, 0),
+ RESET(USBH_R, RCC_USBHCFGR, 0, 0),
+ RESET(USB2PHY1_R, RCC_USB2PHY1CFGR, 0, 0),
+ RESET(USB2PHY2_R, RCC_USB2PHY2CFGR, 0, 0),
+ RESET(USB3DR_R, RCC_USB3DRCFGR, 0, 0),
+ RESET(USB3PCIEPHY_R, RCC_USB3PCIEPHYCFGR, 0, 0),
+ RESET(USBTC_R, RCC_UCPDCFGR, 0, 0),
+ RESET(ETHSW_R, RCC_ETHSWCFGR, 0, 0),
+ RESET(SDMMC1_R, RCC_SDMMC1CFGR, 0, 0),
+ RESET(SDMMC1DLL_R, RCC_SDMMC1CFGR, 16, 0),
+ RESET(SDMMC2_R, RCC_SDMMC2CFGR, 0, 0),
+ RESET(SDMMC2DLL_R, RCC_SDMMC2CFGR, 16, 0),
+ RESET(SDMMC3_R, RCC_SDMMC3CFGR, 0, 0),
+ RESET(SDMMC3DLL_R, RCC_SDMMC3CFGR, 16, 0),
+ RESET(GPU_R, RCC_GPUCFGR, 0, 0),
+ RESET(LTDC_R, RCC_LTDCCFGR, 0, 0),
+ RESET(DSI_R, RCC_DSICFGR, 0, 0),
+ RESET(LVDS_R, RCC_LVDSCFGR, 0, 0),
+ RESET(CSI_R, RCC_CSICFGR, 0, 0),
+ RESET(DCMIPP_R, RCC_DCMIPPCFGR, 0, 0),
+ RESET(CCI_R, RCC_CCICFGR, 0, 0),
+ RESET(VDEC_R, RCC_VDECCFGR, 0, 0),
+ RESET(VENC_R, RCC_VENCCFGR, 0, 0),
+ RESET(WWDG1_R, RCC_WWDG1CFGR, 0, 0),
+ RESET(WWDG2_R, RCC_WWDG2CFGR, 0, 0),
+ RESET(VREF_R, RCC_VREFCFGR, 0, 0),
+ RESET(DTS_R, RCC_DTSCFGR, 0, 0),
+ RESET(CRC_R, RCC_CRCCFGR, 0, 0),
+ RESET(SERC_R, RCC_SERCCFGR, 0, 0),
+ RESET(OSPIIOM_R, RCC_OSPIIOMCFGR, 0, 0),
+ RESET(I3C1_R, RCC_I3C1CFGR, 0, 0),
+ RESET(I3C2_R, RCC_I3C2CFGR, 0, 0),
+ RESET(I3C3_R, RCC_I3C3CFGR, 0, 0),
+ RESET(I3C4_R, RCC_I3C4CFGR, 0, 0),
+ RESET(IWDG2_KER_R, RCC_IWDGC1CFGSETR, 18, 1),
+ RESET(IWDG4_KER_R, RCC_IWDGC2CFGSETR, 18, 1),
+ RESET(RNG_R, RCC_RNGCFGR, 0, 0),
+ RESET(PKA_R, RCC_PKACFGR, 0, 0),
+ RESET(SAES_R, RCC_SAESCFGR, 0, 0),
+ RESET(HASH_R, RCC_HASHCFGR, 0, 0),
+ RESET(CRYP1_R, RCC_CRYP1CFGR, 0, 0),
+ RESET(CRYP2_R, RCC_CRYP2CFGR, 0, 0),
+ RESET(PCIE_R, RCC_PCIECFGR, 0, 0),
+};
+
+static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_ctl *reset_ctl)
+{
+ unsigned long id = reset_ctl->id;
+
+ if (id < STM32MP25_LAST_RESET)
+ return stm32mp25_reset[id];
+
+ return NULL;
+}
+
+static const struct stm32_reset_data stm32mp25_reset_data = {
+ .get_reset_line = stm32_get_reset_line,
+ .clear_offset = RCC_CLR_OFFSET,
+ .reset_us = STM32_DEASSERT_TIMEOUT_US,
+};
+
+static int stm32_reset_probe(struct udevice *dev)
+{
+ return stm32_reset_core_probe(dev, &stm32mp25_reset_data);
+}
+
+U_BOOT_DRIVER(stm32mp25_rcc_reset) = {
+ .name = "stm32mp25_reset",
+ .id = UCLASS_RESET,
+ .probe = stm32_reset_probe,
+ .priv_auto = sizeof(struct stm32_reset_priv),
+ .ops = &stm32_reset_ops,
+};
diff --git a/drivers/reset/stm32/stm32-reset.c b/drivers/reset/stm32/stm32-reset.c
new file mode 100644
index 00000000000..975f67f712a
--- /dev/null
+++ b/drivers/reset/stm32/stm32-reset.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics.
+ */
+
+#include <dm.h>
+#include <stm32-reset-core.h>
+
+/* Timeout for deassert */
+#define STM32_DEASSERT_TIMEOUT_US 10000
+
+static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_ctl *reset_ctl)
+{
+ struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ struct stm32_reset_cfg *ptr_line = &priv->reset_line;
+ int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
+ int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
+
+ ptr_line->offset = bank;
+ ptr_line->bit_idx = offset;
+ ptr_line->set_clr = true;
+
+ return ptr_line;
+}
+
+static const struct stm32_reset_data stm32_reset_data = {
+ .get_reset_line = stm32_get_reset_line,
+ .reset_us = STM32_DEASSERT_TIMEOUT_US,
+};
+
+static int stm32_reset_probe(struct udevice *dev)
+{
+ return stm32_reset_core_probe(dev, &stm32_reset_data);
+}
+
+U_BOOT_DRIVER(stm32_rcc_reset) = {
+ .name = "stm32_rcc_reset",
+ .id = UCLASS_RESET,
+ .probe = stm32_reset_probe,
+ .priv_auto = sizeof(struct stm32_reset_priv),
+ .ops = &stm32_reset_ops,
+};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6467f20422b..79b879d68d1 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -94,6 +94,13 @@ config RTC_DS1374
Support for Dallas Semiconductor (now Maxim) DS1374 and compatible
Real Time Clock devices.
+config RTC_DS1672
+ bool "Enable DS1672 driver"
+ depends on DM_RTC
+ help
+ Support for Dallas Semiconductor (now Maxim) DS1672 compatible
+ Real Time Clock devices.
+
config RTC_DS3231
bool "Enable DS3231 driver"
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 99b5a2a346a..a4ede413cd1 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_RTC_DS1307) += ds1307.o
obj-$(CONFIG_RTC_DS1338) += ds1307.o
obj-$(CONFIG_RTC_DS1337) += ds1337.o
obj-$(CONFIG_RTC_DS1374) += ds1374.o
+obj-$(CONFIG_RTC_DS1672) += ds1672.o
obj-$(CONFIG_RTC_DS3231) += ds3231.o
obj-$(CONFIG_RTC_DS3232) += ds3232.o
obj-$(CONFIG_RTC_EMULATION) += emul_rtc.o
diff --git a/drivers/rtc/ds1672.c b/drivers/rtc/ds1672.c
new file mode 100644
index 00000000000..4705e5abc93
--- /dev/null
+++ b/drivers/rtc/ds1672.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices DS1672 I2C RTC driver
+ *
+ * Copyright 2025 Gateworks Corporation.
+ */
+#include <dm.h>
+#include <i2c.h>
+#include <rtc.h>
+#include <dm/device_compat.h>
+
+/* Registers */
+#define DS1672_REG_CNT_BASE 0
+#define DS1672_REG_CONTROL 4
+#define DS1672_REG_TRICKLE 5
+
+#define DS1672_REG_CONTROL_EOSC 0x80
+
+static int ds1672_read_time(struct udevice *dev, struct rtc_time *tm)
+{
+ time64_t secs;
+ u8 regs[4];
+ int ret;
+
+ ret = dm_i2c_read(dev, DS1672_REG_CONTROL, regs, 1);
+ if (ret)
+ return ret;
+
+ if (regs[0] & DS1672_REG_CONTROL_EOSC) {
+ dev_err(dev, "Oscillator not enabled. Set time to enable.\n");
+ return -EINVAL;
+ }
+
+ ret = dm_i2c_read(dev, DS1672_REG_CNT_BASE, regs, 4);
+ if (ret)
+ return ret;
+ dev_dbg(dev, "raw read: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ regs[0], regs[1], regs[2], regs[3]);
+ secs = ((unsigned long)regs[3] << 24) | (regs[2] << 16) | (regs[1] << 8) | regs[0];
+ rtc_to_tm(secs, tm);
+
+ dev_dbg(dev, "read %lld %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n", secs,
+ tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return 0;
+}
+
+static int ds1672_set_time(struct udevice *dev, const struct rtc_time *tm)
+{
+ time64_t secs = rtc_mktime(tm);
+ u8 regs[5];
+
+ dev_dbg(dev, "set %4d-%02d-%02d (wday=%d) %2d:%02d:%02d %lld\n",
+ tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec,
+ secs);
+
+ if (tm->tm_year < 2000) {
+ dev_err(dev, "year %d (before 2000) not supported\n",
+ tm->tm_year);
+ return -EINVAL;
+ }
+
+ regs[0] = secs & 0x000000ff;
+ regs[1] = (secs & 0x0000ff00) >> 8;
+ regs[2] = (secs & 0x00ff0000) >> 16;
+ regs[3] = (secs & 0xff000000) >> 24;
+ regs[4] = 0; /* set control reg to enable counting */
+
+ return dm_i2c_write(dev, DS1672_REG_CNT_BASE, regs, 5);
+}
+
+static int ds1672_reset(struct udevice *dev)
+{
+ u8 regs[5] = { 0 };
+
+ return dm_i2c_write(dev, DS1672_REG_CNT_BASE, regs, 5);
+}
+
+static int ds1672_read8(struct udevice *dev, unsigned int reg)
+{
+ return dm_i2c_reg_read(dev, reg);
+}
+
+static int ds1672_write8(struct udevice *dev, unsigned int reg, int val)
+{
+ return dm_i2c_reg_write(dev, reg, val);
+}
+
+static const struct rtc_ops ds1672_rtc_ops = {
+ .get = ds1672_read_time,
+ .set = ds1672_set_time,
+ .reset = ds1672_reset,
+ .read8 = ds1672_read8,
+ .write8 = ds1672_write8,
+};
+
+static int ds1672_probe(struct udevice *dev)
+{
+ i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS);
+
+ return 0;
+}
+
+static const struct udevice_id ds1672_of_id[] = {
+ { .compatible = "dallas,ds1672" },
+ { }
+};
+
+U_BOOT_DRIVER(rtc_max313xx) = {
+ .name = "rtc-ds1672",
+ .id = UCLASS_RTC,
+ .probe = ds1672_probe,
+ .of_match = ds1672_of_id,
+ .ops = &ds1672_rtc_ops,
+};
diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
index becf9317076..01cc415efdd 100644
--- a/drivers/serial/serial_mtk.c
+++ b/drivers/serial/serial_mtk.c
@@ -30,16 +30,23 @@ struct mtk_serial_regs {
u32 mcr;
u32 lsr;
u32 msr;
- u32 spr;
- u32 mdr1;
+ u32 scr;
+ u32 autobaud_en;
u32 highspeed;
u32 sample_count;
u32 sample_point;
+ u32 autobaud_reg;
+ u32 ratefix_ad;
+ u32 autobaud_sample;
+ u32 guard;
+ u32 escape_dat;
+ u32 escape_en;
+ u32 sleep_en;
+ u32 dma_en;
+ u32 rxtri_ad;
u32 fracdiv_l;
u32 fracdiv_m;
- u32 escape_en;
- u32 guard;
- u32 rx_sel;
+ u32 fcr_rd;
};
#define thr rbr
@@ -92,10 +99,18 @@ struct mtk_serial_priv {
bool upstream_highspeed_logic;
};
+static const unsigned short fraction_l_mapping[] = {
+ 0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF
+};
+
+static const unsigned short fraction_m_mapping[] = {
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3
+};
+
static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud,
uint clk_rate)
{
- u32 quot, realbaud, samplecount = 1;
+ u32 quot, realbaud, samplecount = 1, fraction, frac_l = 0, frac_m = 0;
/* Special case for low baud clock */
if (baud <= 115200 && clk_rate == 12000000) {
@@ -140,7 +155,13 @@ use_hs3:
writel(3, &priv->regs->highspeed);
quot = DIV_ROUND_UP(clk_rate, 256 * baud);
- samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
+ samplecount = clk_rate / (quot * baud);
+
+ fraction = ((clk_rate * 100) / quot / baud) % 100;
+ fraction = DIV_ROUND_CLOSEST(fraction, 10);
+
+ frac_l = fraction_l_mapping[fraction];
+ frac_m = fraction_m_mapping[fraction];
}
set_baud:
@@ -152,7 +173,11 @@ set_baud:
/* set highspeed mode sample count & point */
writel(samplecount - 1, &priv->regs->sample_count);
- writel((samplecount - 2) >> 1, &priv->regs->sample_point);
+ writel((samplecount >> 1) - 1, &priv->regs->sample_point);
+
+ /* set baudrate fraction compensation */
+ writel(frac_l, &priv->regs->fracdiv_l);
+ writel(frac_m, &priv->regs->fracdiv_m);
}
static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
diff --git a/drivers/sound/max98088.h b/drivers/sound/max98088.h
index b1307a73623..2ca6ca1f734 100644
--- a/drivers/sound/max98088.h
+++ b/drivers/sound/max98088.h
@@ -15,14 +15,14 @@
#define M98088_REG_JACK_STAUS 0x02
#define M98088_REG_BATTERY_VOLTAGE 0x03
#define M98088_REG_IRQ_ENABLE 0x0f
-#define M98088_REG_SYS_CLK 0X10
+#define M98088_REG_SYS_CLK 0x10
#define M98088_REG_DAI1_CLKMODE 0x11
#define M98088_REG_DAI1_CLKCFG_HI 0x12
#define M98088_REG_DAI1_CLKCFG_LO 0x13
#define M98088_REG_DAI1_FORMAT 0x14
#define M98088_REG_DAI1_CLOCK 0x15
#define M98088_REG_DAI1_IOCFG 0x16
-#define M98088_REG_DAI1_TDM 0X17
+#define M98088_REG_DAI1_TDM 0x17
#define M98088_REG_DAI1_FILTERS 0x18
#define M98088_REG_DAI2_CLKMODE 0x19
#define M98088_REG_DAI2_CLKCFG_HI 0x1a
@@ -30,10 +30,10 @@
#define M98088_REG_DAI2_FORMAT 0x1c
#define M98088_REG_DAI2_CLOCK 0x1d
#define M98088_REG_DAI2_IOCFG 0x1e
-#define M98088_REG_DAI2_TDM 0X1f
+#define M98088_REG_DAI2_TDM 0x1f
#define M98088_REG_DAI2_FILTERS 0x20
-#define M98088_REG_SRC 0X21
-#define M98088_REG_MIX_DAC 0X22
+#define M98088_REG_SRC 0x21
+#define M98088_REG_MIX_DAC 0x22
#define M98088_REG_MIX_ADC_LEFT 0x23
#define M98088_REG_MIX_ADC_RIGHT 0x24
#define M98088_REG_MIX_HP_LEFT 0x25
@@ -50,37 +50,37 @@
#define M98088_REG_LVL_DAI1_PLAY_EQ 0x30
#define M98088_REG_LVL_DAI2_PLAY 0x31
#define M98088_REG_LVL_DAI2_PLAY_EQ 0x32
-#define M98088_REG_LVL_ADC_L 0X33
-#define M98088_REG_LVL_ADC_R 0X34
-#define M98088_REG_LVL_MIC1 0X35
-#define M98088_REG_LVL_MIC2 0X36
-#define M98088_REG_LVL_INA 0X37
-#define M98088_REG_LVL_INB 0X38
-#define M98088_REG_LVL_HP_L 0X39
-#define M98088_REG_LVL_HP_R 0X3a
-#define M98088_REG_LVL_REC_L 0X3b
-#define M98088_REG_LVL_REC_R 0X3c
-#define M98088_REG_LVL_SPK_L 0X3d
-#define M98088_REG_LVL_SPK_R 0X3e
+#define M98088_REG_LVL_ADC_L 0x33
+#define M98088_REG_LVL_ADC_R 0x34
+#define M98088_REG_LVL_MIC1 0x35
+#define M98088_REG_LVL_MIC2 0x36
+#define M98088_REG_LVL_INA 0x37
+#define M98088_REG_LVL_INB 0x38
+#define M98088_REG_LVL_HP_L 0x39
+#define M98088_REG_LVL_HP_R 0x3a
+#define M98088_REG_LVL_REC_L 0x3b
+#define M98088_REG_LVL_REC_R 0x3c
+#define M98088_REG_LVL_SPK_L 0x3d
+#define M98088_REG_LVL_SPK_R 0x3e
#define M98088_REG_MICAGC_CFG 0x3f
#define M98088_REG_MICAGC_THRESH 0x40
-#define M98088_REG_SPKDHP 0X41
+#define M98088_REG_SPKDHP 0x41
#define M98088_REG_SPKDHP_THRESH 0x42
#define M98088_REG_SPKALC_COMP 0x43
#define M98088_REG_PWRLMT_CFG 0x44
#define M98088_REG_PWRLMT_TIME 0x45
#define M98088_REG_THDLMT_CFG 0x46
#define M98088_REG_CFG_AUDIO_IN 0x47
-#define M98088_REG_CFG_MIC 0X48
-#define M98088_REG_CFG_LEVEL 0X49
+#define M98088_REG_CFG_MIC 0x48
+#define M98088_REG_CFG_LEVEL 0x49
#define M98088_REG_CFG_BYPASS 0x4a
#define M98088_REG_CFG_JACKDET 0x4b
-#define M98088_REG_PWR_EN_IN 0X4c
+#define M98088_REG_PWR_EN_IN 0x4c
#define M98088_REG_PWR_EN_OUT 0x4d
-#define M98088_REG_BIAS_CNTL 0X4e
-#define M98088_REG_DAC_BIAS1 0X4f
-#define M98088_REG_DAC_BIAS2 0X50
-#define M98088_REG_PWR_SYS 0X51
+#define M98088_REG_BIAS_CNTL 0x4e
+#define M98088_REG_DAC_BIAS1 0x4f
+#define M98088_REG_DAC_BIAS2 0x50
+#define M98088_REG_PWR_SYS 0x51
#define M98088_REG_DAI1_EQ_BASE 0x52
#define M98088_REG_DAI2_EQ_BASE 0x84
#define M98088_REG_DAI1_BIQUAD_BASE 0xb6
diff --git a/drivers/sound/max98095.h b/drivers/sound/max98095.h
index 1521f3f02f9..009164d85d2 100644
--- a/drivers/sound/max98095.h
+++ b/drivers/sound/max98095.h
@@ -176,7 +176,7 @@ enum en_max_audio_interface {
#define M98095_0FF_REV_ID 0xFF
#define M98095_REG_CNT (0xFF+1)
-#define M98095_REG_MAX_CACHED 0X97
+#define M98095_REG_MAX_CACHED 0x97
/* MAX98095 Registers Bit Fields */
diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c
index 2bc7dc87ed3..d7341062b31 100644
--- a/drivers/tpm/tpm_tis_sandbox.c
+++ b/drivers/tpm/tpm_tis_sandbox.c
@@ -221,6 +221,7 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
case 0x72: /* physical set deactivated */
case 0x99: /* startup */
case 0x50: /* self test full */
+ case 0x53: /* self test continue */
case 0x4000000a: /* assert physical presence */
*recv_len = 12;
memset(recvbuf, '\0', *recv_len);
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 86b2cbf3f6a..b3c780a4e35 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -228,7 +228,6 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
}
buf = req->req.buf + req->req.actual;
- prefetch(buf);
total = req->req.length - req->req.actual;
if (ep->ep.maxpacket < total) {
count = ep->ep.maxpacket;
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index f9326f0a7e7..72f68dba3a7 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -521,16 +521,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
static int usba_udc_pullup(struct usb_gadget *gadget, int is_on)
{
struct usba_udc *udc = to_usba_udc(gadget);
- u32 ctrl;
-
- ctrl = usba_readl(udc, CTRL);
+ /*
+ * Some chips don't reliably drive DP/DM lines to high impedance when
+ * using the DETACH/PULLD_DIS bits.
+ * To ensure a reliable disconnect, power cycle the controller instead
+ */
if (is_on)
- ctrl &= ~USBA_DETACH;
+ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
else
- ctrl |= USBA_DETACH;
-
- usba_writel(udc, CTRL, ctrl);
+ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
return 0;
}
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index 36934b1bcf7..647001d8dd0 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -863,7 +863,7 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image,
struct spl_boot_device bootdev = {};
spl_parse_image_header(&spl_image, &bootdev, header);
spl_board_prepare_for_boot();
- jump_to_image_no_args(&spl_image);
+ jump_to_image(&spl_image);
#else
/* In U-Boot, allow jumps to scripts */
cmd_source_script(sdp_func->jmp_address, NULL, NULL);
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index 6375be741ae..a14b127dc37 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -223,8 +223,6 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
struct musb *musb = hw_ep->musb;
void __iomem *fifo = hw_ep->fifo;
- prefetch((u8 *)src);
-
dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n",
'T', hw_ep->epnum, fifo, len, src);
diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c
index ec1baa9337d..967d0953875 100644
--- a/drivers/usb/musb-new/ti-musb.c
+++ b/drivers/usb/musb-new/ti-musb.c
@@ -282,7 +282,6 @@ U_BOOT_DRIVER(ti_musb_peripheral) = {
.ops = &ti_musb_gadget_ops,
.probe = ti_musb_peripheral_probe,
.remove = ti_musb_peripheral_remove,
- .ops = &musb_usb_ops,
.plat_auto = sizeof(struct ti_musb_plat),
.priv_auto = sizeof(struct ti_musb_peripheral),
.flags = DM_FLAG_PRE_RELOC,
diff --git a/drivers/video/bridge/dp501.c b/drivers/video/bridge/dp501.c
index 9937cfe095b..0ad589304aa 100644
--- a/drivers/video/bridge/dp501.c
+++ b/drivers/video/bridge/dp501.c
@@ -99,7 +99,7 @@
#define SD_DB15 0x4F
/* Aux Channel and PCS */
-#define DPCD_REV 0X50
+#define DPCD_REV 0x50
#define MAX_LINK_RATE 0x51
#define MAX_LANE_COUNT 0x52
#define MAX_DOWNSPREAD 0x53
diff --git a/drivers/video/hx8238d.c b/drivers/video/hx8238d.c
index 2491a32810e..f0220e4cc07 100644
--- a/drivers/video/hx8238d.c
+++ b/drivers/video/hx8238d.c
@@ -22,7 +22,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define HX8238D_OUTPUT_CTRL_ADDR 0x01
#define HX8238D_LCD_AC_CTRL_ADDR 0x02
#define HX8238D_POWER_CTRL_1_ADDR 0x03
-#define HX8238D_DATA_CLR_CTRL_ADDR 0X04
+#define HX8238D_DATA_CLR_CTRL_ADDR 0x04
#define HX8238D_FUNCTION_CTRL_ADDR 0x05
#define HX8238D_LED_CTRL_ADDR 0x08
#define HX8238D_CONT_BRIGHT_CTRL_ADDR 0x0A
diff --git a/drivers/video/zynqmp/zynqmp_dpsub.h b/drivers/video/zynqmp/zynqmp_dpsub.h
index 7d2737e31aa..dc549559cae 100644
--- a/drivers/video/zynqmp/zynqmp_dpsub.h
+++ b/drivers/video/zynqmp/zynqmp_dpsub.h
@@ -553,7 +553,7 @@ struct zynqmp_dpsub_priv {
#define DPDMA_DESCRIPTOR_LINE_SIZE_STRIDE_SHIFT 18
#define DPDMA_DESCRIPTOR_SRC_ADDR_WIDTH 32U
#define DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT 16U
-#define DPDMA_CH0_DSCR_STRT_ADDR 0X0204U
+#define DPDMA_CH0_DSCR_STRT_ADDR 0x0204U
#define DPDMA_CH_OFFSET 0x100U
#define DPDMA_CH0_CNTL 0x0218U
#define DPDMA_CH3_CNTL 0x0518U
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 1bb67f50352..45eb9b4d3f9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -29,6 +29,7 @@ config WATCHDOG_TIMEOUT_MSECS
int "Watchdog timeout in msec"
default 128000 if ARCH_MX31 || ARCH_MX5 || ARCH_MX6
default 128000 if ARCH_MX7 || ARCH_VF610
+ default 30000 if ARCH_SNAPDRAGON
default 30000 if ARCH_SOCFPGA
default 16000 if ARCH_SUNXI
default 5376 if ULP_WATCHDOG
@@ -335,6 +336,22 @@ config WDT_K3_RTI_FW_FILE
endif
+config WDT_QCOM
+ bool "Qualcomm watchdog timer support"
+ depends on WDT && ARCH_SNAPDRAGON
+ imply WATCHDOG
+ help
+ Select this to enable Qualcomm watchdog timer, which can be found on
+ some Qualcomm chips.
+
+config WDT_RENESAS
+ bool "Renesas watchdog timer support"
+ depends on WDT && R8A779F0
+ select CLK
+ select CLK_RENESAS
+ help
+ Enables Renesas SoC R8A779F0 watchdog timer support.
+
config WDT_SANDBOX
bool "Enable Watchdog Timer support for Sandbox"
depends on SANDBOX && WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index e6bd4c587af..d52d17e1c90 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
obj-$(CONFIG_WDT_NPCM) += npcm_wdt.o
obj-$(CONFIG_WDT_OCTEONTX) += octeontx_wdt.o
obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
+obj-$(CONFIG_WDT_RENESAS) += renesas_wdt.o
obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o
obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o
obj-$(CONFIG_WDT_SIEMENS_PMIC) += siemens_pmic_wdt.o
@@ -54,3 +55,4 @@ obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o
obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o
obj-$(CONFIG_WDT_XILINX) += xilinx_wwdt.o
obj-$(CONFIG_WDT_ADI) += adi_wdt.o
+obj-$(CONFIG_WDT_QCOM) += qcom-wdt.o
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index c809a8936b8..72e13787448 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -38,7 +38,7 @@ DECLARE_GLOBAL_DATA_PTR;
*/
static int at91_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
{
- struct at91_wdt_priv *priv = dev_get_priv(dev);
+ struct at91_wdt_priv *wdt = dev_get_priv(dev);
u64 timeout;
u32 ticks;
@@ -49,7 +49,7 @@ static int at91_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
ticks = WDT_SEC2TICKS(timeout);
/* Check if disabled */
- if (readl(priv->regs + AT91_WDT_MR) & AT91_WDT_MR_WDDIS) {
+ if (readl(wdt->regs + AT91_WDT_MR) & wdt->wddis) {
printf("sorry, watchdog is disabled\n");
return -1;
}
@@ -60,31 +60,41 @@ static int at91_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
* Since WDV is a 12-bit counter, the maximum period is
* 4096 / 256 = 16 seconds.
*/
- priv->regval = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */
- | AT91_WDT_MR_WDDBGHLT /* disabled in debug mode */
- | AT91_WDT_MR_WDD(0xfff) /* restart at any time */
- | AT91_WDT_MR_WDV(ticks); /* timer value */
- writel(priv->regval, priv->regs + AT91_WDT_MR);
+
+ if (wdt->mode == AT91_WDT_MODE_SAM9260) {
+ wdt->mr = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */
+ | AT91_WDT_MR_WDDBGHLT /* disabled in debug mode */
+ | AT91_WDT_MR_WDD(0xfff) /* restart at any time */
+ | AT91_WDT_MR_WDV(ticks); /* timer value */
+ writel(wdt->mr, wdt->regs + AT91_WDT_MR);
+ } else if (wdt->mode == AT91_WDT_MODE_SAM9X60) {
+ writel(AT91_SAM9X60_WLR_COUNTER(ticks), /* timer value */
+ wdt->regs + AT91_SAM9X60_WLR);
+
+ wdt->mr = AT91_SAM9X60_MR_PERIODRST /* causes watchdog reset */
+ | AT91_SAM9X60_MR_WDDBGHLT; /* disabled in debug mode */
+ writel(wdt->mr, wdt->regs + AT91_WDT_MR);
+ }
return 0;
}
static int at91_wdt_stop(struct udevice *dev)
{
- struct at91_wdt_priv *priv = dev_get_priv(dev);
+ struct at91_wdt_priv *wdt = dev_get_priv(dev);
/* Disable Watchdog Timer */
- priv->regval |= AT91_WDT_MR_WDDIS;
- writel(priv->regval, priv->regs + AT91_WDT_MR);
+ wdt->mr |= wdt->wddis;
+ writel(wdt->mr, wdt->regs + AT91_WDT_MR);
return 0;
}
static int at91_wdt_reset(struct udevice *dev)
{
- struct at91_wdt_priv *priv = dev_get_priv(dev);
+ struct at91_wdt_priv *wdt = dev_get_priv(dev);
- writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, priv->regs + AT91_WDT_CR);
+ writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, wdt->regs + AT91_WDT_CR);
return 0;
}
@@ -96,18 +106,31 @@ static const struct wdt_ops at91_wdt_ops = {
};
static const struct udevice_id at91_wdt_ids[] = {
- { .compatible = "atmel,at91sam9260-wdt" },
+ { .compatible = "atmel,at91sam9260-wdt",
+ .data = AT91_WDT_MODE_SAM9260 },
+ { .compatible = "atmel,sama5d4-wdt",
+ .data = AT91_WDT_MODE_SAM9260 },
+ { .compatible = "microchip,sam9x60-wdt",
+ .data = AT91_WDT_MODE_SAM9X60 },
+ { .compatible = "microchip,sama7g5-wdt",
+ .data = AT91_WDT_MODE_SAM9X60 },
{}
};
static int at91_wdt_probe(struct udevice *dev)
{
- struct at91_wdt_priv *priv = dev_get_priv(dev);
+ struct at91_wdt_priv *wdt = dev_get_priv(dev);
- priv->regs = dev_remap_addr(dev);
- if (!priv->regs)
+ wdt->regs = dev_remap_addr(dev);
+ if (!wdt->regs)
return -EINVAL;
+ wdt->mode = dev_get_driver_data(dev);
+ if (wdt->mode == AT91_WDT_MODE_SAM9260)
+ wdt->wddis = AT91_WDT_MR_WDDIS;
+ else if (wdt->mode == AT91_WDT_MODE_SAM9X60)
+ wdt->wddis = AT91_SAM9X60_MR_WDDIS;
+
debug("%s: Probing wdt%u\n", __func__, dev_seq(dev));
return 0;
diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
new file mode 100644
index 00000000000..adbb5aacdc3
--- /dev/null
+++ b/drivers/watchdog/qcom-wdt.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) Linaro Ltd. 2024
+ *
+ * Authors:
+ * Casey Connolly <casey.connolly@linaro.org>
+ * Paul Sajna <hello@paulsajna.com>
+ *
+ * Derived from linux/drivers/watchdog/qcom-wdt.c
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <wdt.h>
+#include <clk.h>
+
+#include <asm/io.h>
+
+enum wdt_reg {
+ WDT_RST,
+ WDT_EN,
+ WDT_STS,
+ WDT_BARK_TIME,
+ WDT_BITE_TIME,
+};
+
+struct qcom_wdt_match_data {
+ const u32 *offset;
+};
+
+struct qcom_wdt {
+ void __iomem *base;
+ ulong clk_rate;
+ const u32 *layout;
+};
+
+static const u32 reg_offset_data_kpss[] = {
+ [WDT_RST] = 0x4,
+ [WDT_EN] = 0x8,
+ [WDT_STS] = 0xC,
+ [WDT_BARK_TIME] = 0x10,
+ [WDT_BITE_TIME] = 0x14,
+};
+
+static const struct qcom_wdt_match_data match_data_kpss = {
+ .offset = reg_offset_data_kpss,
+};
+
+static void __iomem *wdt_addr(struct qcom_wdt *wdt, enum wdt_reg reg)
+{
+ return wdt->base + wdt->layout[reg];
+}
+
+int qcom_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct qcom_wdt *wdt = dev_get_priv(dev);
+ ulong bark_timeout_s = ((timeout_ms - 1) * wdt->clk_rate) / 1000;
+ ulong bite_timeout_s = (timeout_ms * wdt->clk_rate) / 1000;
+
+ writel(0, wdt_addr(wdt, WDT_EN));
+ writel(BIT(0), wdt_addr(wdt, WDT_RST));
+ writel(bark_timeout_s, wdt_addr(wdt, WDT_BARK_TIME));
+ writel(bite_timeout_s, wdt_addr(wdt, WDT_BITE_TIME));
+ writel(BIT(0), wdt_addr(wdt, WDT_EN));
+ if (readl(wdt_addr(wdt, WDT_EN)) != 1) {
+ dev_err(dev, "Failed to enable Qualcomm watchdog!\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+int qcom_wdt_stop(struct udevice *dev)
+{
+ struct qcom_wdt *wdt = dev_get_priv(dev);
+
+ writel(0, wdt_addr(wdt, WDT_EN));
+ if (readl(wdt_addr(wdt, WDT_EN))) {
+ dev_err(dev, "Failed to disable Qualcomm watchdog!\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int qcom_wdt_reset(struct udevice *dev)
+{
+ struct qcom_wdt *wdt = dev_get_priv(dev);
+
+ writel(1, wdt_addr(wdt, WDT_RST));
+ return 0;
+}
+
+static int qcom_wdt_probe(struct udevice *dev)
+{
+ struct clk clk;
+ long rate;
+ int ret;
+
+ struct qcom_wdt *wdt = dev_get_priv(dev);
+ struct qcom_wdt_match_data *data = (void *)dev_get_driver_data(dev);
+
+ wdt->base = dev_read_addr_ptr(dev);
+ wdt->layout = data->offset;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ rate = clk_get_rate(&clk);
+ if (rate <= 0)
+ return rate < 0 ? (int)rate : -EINVAL;
+
+ wdt->clk_rate = (ulong)rate;
+
+ return 0;
+}
+
+static const struct wdt_ops qcom_wdt_ops = {
+ .start = qcom_wdt_start,
+ .stop = qcom_wdt_stop,
+ .reset = qcom_wdt_reset,
+};
+
+static const struct udevice_id qcom_wdt_ids[] = {
+ { .compatible = "qcom,kpss-wdt", .data = (ulong)&match_data_kpss },
+ {}
+};
+
+U_BOOT_DRIVER(qcom_wdt) = {
+ .name = "qcom_wdt",
+ .id = UCLASS_WDT,
+ .of_match = qcom_wdt_ids,
+ .ops = &qcom_wdt_ops,
+ .probe = qcom_wdt_probe,
+ .priv_auto = sizeof(struct qcom_wdt),
+};
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
new file mode 100644
index 00000000000..046e11915b9
--- /dev/null
+++ b/drivers/watchdog/renesas_wdt.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2025 Red Hat, Inc., Shmuel Leib Melamud <smelamud@redhat.com>
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <wdt.h>
+
+#define usleep_range(a, b) udelay((a))
+
+struct rwdt {
+ u32 cnt;
+ u32 csra;
+ u32 csrb;
+};
+
+#define RWTCSRA_WOVF BIT(4)
+#define RWTCSRA_WRFLG BIT(5)
+#define RWTCSRA_TME BIT(7)
+
+#define CSR_MASK 0xA5A5A500
+#define CNT_MASK 0x5A5A0000
+
+#define MAX_CNT_VALUE 65536
+/*
+ * In probe, clk_rate is checked to be not more than 16 bit * biggest clock
+ * divider (12 bits). d is only a factor to fully utilize the WDT counter and
+ * will not exceed its 16 bits. Thus, no overflow, we stay below 32 bits.
+ */
+#define MUL_BY_CLKS_PER_SEC(p, d) \
+ DIV_ROUND_UP((d) * (p)->clk_rate, clk_divs[(p)->cks])
+
+/* d is 16 bit, clk_divs 12 bit -> no 32 bit overflow */
+#define DIV_BY_CLKS_PER_SEC(p, d) ((d) * clk_divs[(p)->cks] / (p)->clk_rate)
+
+static const unsigned int clk_divs[] = { 1, 4, 16, 32, 64, 128, 1024, 4096 };
+
+struct rwdt_priv {
+ struct rwdt __iomem *wdt;
+ unsigned long clk_rate;
+ u8 cks;
+ struct clk clk;
+};
+
+static void rwdt_wait_cycles(struct rwdt_priv *priv, unsigned int cycles)
+{
+ unsigned int delay;
+
+ delay = DIV_ROUND_UP(cycles * 1000000, priv->clk_rate);
+
+ usleep_range(delay, 2 * delay);
+}
+
+static int rwdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+ struct rwdt_priv *priv = dev_get_priv(dev);
+ u64 max_timeout;
+ u8 val;
+
+ max_timeout = DIV_BY_CLKS_PER_SEC(priv, MAX_CNT_VALUE);
+ timeout = min(max_timeout, timeout / 1000);
+
+ /* Stop the timer before we modify any register */
+ val = readb_relaxed(&priv->wdt->csra) & ~RWTCSRA_TME;
+ writel_relaxed(val | CSR_MASK, &priv->wdt->csra);
+ /* Delay 2 cycles before setting watchdog counter */
+ rwdt_wait_cycles(priv, 2);
+
+ while (readb_relaxed(&priv->wdt->csra) & RWTCSRA_WRFLG)
+ cpu_relax();
+
+ writel_relaxed((MAX_CNT_VALUE - MUL_BY_CLKS_PER_SEC(priv, timeout))
+ | CNT_MASK, &priv->wdt->cnt);
+
+ writel_relaxed(priv->cks | RWTCSRA_TME | CSR_MASK, &priv->wdt->csra);
+
+ return 0;
+}
+
+static int rwdt_stop(struct udevice *dev)
+{
+ struct rwdt_priv *priv = dev_get_priv(dev);
+
+ writel_relaxed(priv->cks | CSR_MASK, &priv->wdt->csra);
+
+ return 0;
+}
+
+static int rwdt_reset(struct udevice *dev)
+{
+ struct rwdt_priv *priv = dev_get_priv(dev);
+ u8 val;
+
+ /* Stop the timer before we modify any register */
+ val = readb_relaxed(&priv->wdt->csra) & ~RWTCSRA_TME;
+ writel_relaxed(val | CSR_MASK, &priv->wdt->csra);
+ /* Delay 2 cycles before setting watchdog counter */
+ rwdt_wait_cycles(priv, 2);
+
+ writel_relaxed(0xffff | CNT_MASK, &priv->wdt->cnt);
+ /* smallest divider to reboot soon */
+ writel_relaxed(0 | CSR_MASK, &priv->wdt->csra);
+
+ readb_poll_timeout(&priv->wdt->csra, val, !(val & RWTCSRA_WRFLG), 100);
+
+ writel_relaxed(RWTCSRA_TME | CSR_MASK, &priv->wdt->csra);
+
+ /* wait 2 cycles, so watchdog will trigger */
+ rwdt_wait_cycles(priv, 2);
+
+ return 0;
+}
+
+static int rwdt_probe(struct udevice *dev)
+{
+ struct rwdt_priv *priv = dev_get_priv(dev);
+ unsigned long clks_per_sec;
+ int ret, i;
+
+ priv->wdt = dev_remap_addr(dev);
+ if (!priv->wdt)
+ return -EINVAL;
+
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&priv->clk);
+ if (ret)
+ return ret;
+
+ priv->clk_rate = clk_get_rate(&priv->clk);
+ if (!priv->clk_rate) {
+ ret = -ENOENT;
+ goto err_clk_disable;
+ }
+
+ /*
+ * Find the largest possible divider that allows clock rate
+ * (clks_per_sec) to stay within 16 bits. In this case, we can still
+ * measure the smallest timeout (1s) and make the largest allowed
+ * timeout as large as possible.
+ */
+ for (i = ARRAY_SIZE(clk_divs) - 1; i >= 0; i--) {
+ clks_per_sec = priv->clk_rate / clk_divs[i];
+ if (clks_per_sec && clks_per_sec < 65536) {
+ priv->cks = i;
+ break;
+ }
+ }
+
+ /* can't find a suitable clock divider */
+ if (i < 0) {
+ ret = -ERANGE;
+ goto err_clk_disable;
+ }
+
+ return 0;
+
+err_clk_disable:
+ clk_disable(&priv->clk);
+
+ return ret;
+}
+
+static const struct wdt_ops rwdt_ops = {
+ .start = rwdt_start,
+ .reset = rwdt_reset,
+ .stop = rwdt_stop,
+};
+
+static const struct udevice_id rwdt_ids[] = {
+ { .compatible = "renesas,rcar-gen2-wdt" },
+ { .compatible = "renesas,rcar-gen3-wdt" },
+ { .compatible = "renesas,rcar-gen4-wdt" },
+ {}
+};
+
+U_BOOT_DRIVER(wdt_renesas) = {
+ .name = "wdt_renesas",
+ .id = UCLASS_WDT,
+ .of_match = rwdt_ids,
+ .ops = &rwdt_ops,
+ .probe = rwdt_probe,
+ .priv_auto = sizeof(struct rwdt_priv),
+};