summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-12-08 13:17:27 -0600
committerTom Rini <[email protected]>2025-12-08 13:17:27 -0600
commit59202e5ae76ef3acb34c4236e43248f1cd3fc642 (patch)
tree30004ced6a059b2c25afb0aca8b049908c2212c3 /drivers
parent8e12d6ccb3cfa84dd275a1b852b2a235de0162b0 (diff)
parent0e0a198a68be71148f5ec27ef86796174f91436f (diff)
Merge tag 'v2026.01-rc4' into next
Prepare v2026.01-rc4
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-uclass.c6
-rw-r--r--drivers/clk/exynos/Kconfig7
-rw-r--r--drivers/clk/exynos/Makefile1
-rw-r--r--drivers/clk/exynos/clk-exynos7870.c929
-rw-r--r--drivers/clk/exynos/clk-pll.c4
-rw-r--r--drivers/clk/exynos/clk-pll.h4
-rw-r--r--drivers/clk/exynos/clk.c99
-rw-r--r--drivers/clk/exynos/clk.h53
-rw-r--r--drivers/clk/renesas/Makefile4
-rw-r--r--drivers/clk/renesas/compound-clock.c92
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/s5p_gpio.c5
-rw-r--r--drivers/mailbox/Kconfig10
-rw-r--r--drivers/mailbox/Makefile1
-rw-r--r--drivers/mailbox/renesas-mfis.c59
-rw-r--r--drivers/mmc/socfpga_dw_mmc.c46
-rw-r--r--drivers/mtd/nand/raw/Kconfig1
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.c11
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.h1
-rw-r--r--drivers/net/dwc_eth_xgmac.c60
-rw-r--r--drivers/net/dwc_eth_xgmac.h1
-rw-r--r--drivers/net/phy/broadcom.c4
-rw-r--r--drivers/net/phy/dp83869.c5
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c4
-rw-r--r--drivers/pinctrl/broadcom/pinctrl-bcm283x.c105
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos.c11
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos.h1
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos7420.c1
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos78x0.c60
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos850.c1
-rw-r--r--drivers/power/domain/ti-power-domain.c2
-rw-r--r--drivers/serial/serial_s5p.c1
-rw-r--r--drivers/soc/samsung/exynos-pmu.c3
-rw-r--r--drivers/spi/Kconfig15
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/cadence_xspi.c449
-rw-r--r--drivers/spi/cadence_xspi.h226
-rw-r--r--drivers/usb/host/Kconfig1
-rw-r--r--drivers/usb/host/xhci.c2
40 files changed, 2218 insertions, 78 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 4a438181ba9..4420651f765 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -594,12 +594,13 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
if (!clk_valid(clk))
return 0;
ops = clk_dev_ops(clk->dev);
+ clk_get_priv(clk, &clkp);
/* Try to find parents which can set rate */
while (!ops->set_rate) {
struct clk *parent;
- if (!(clk->flags & CLK_SET_RATE_PARENT))
+ if (!(clkp->flags & CLK_SET_RATE_PARENT))
return -ENOSYS;
parent = clk_get_parent(clk);
@@ -608,10 +609,9 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
clk = parent;
ops = clk_dev_ops(clk->dev);
+ clk_get_priv(clk, &clkp);
}
- /* get private clock struct used for cache */
- clk_get_priv(clk, &clkp);
/* Clean up cached rates for us and all child clocks */
clk_clean_rate_cache(clkp);
diff --git a/drivers/clk/exynos/Kconfig b/drivers/clk/exynos/Kconfig
index 85ce9d6e241..dcecbd51b5b 100644
--- a/drivers/clk/exynos/Kconfig
+++ b/drivers/clk/exynos/Kconfig
@@ -15,6 +15,13 @@ config CLK_EXYNOS7420
This enables common clock driver support for platforms based
on Samsung Exynos7420 SoC.
+config CLK_EXYNOS7870
+ bool "Clock driver for Samsung's Exynos7870 SoC"
+ select CLK_CCF
+ help
+ This enables common clock driver support for platforms based
+ on Samsung Exynos7870 SoC.
+
config CLK_EXYNOS850
bool "Clock driver for Samsung's Exynos850 SoC"
select CLK_CCF
diff --git a/drivers/clk/exynos/Makefile b/drivers/clk/exynos/Makefile
index 77385864fef..f5d27d87bd2 100644
--- a/drivers/clk/exynos/Makefile
+++ b/drivers/clk/exynos/Makefile
@@ -9,4 +9,5 @@
obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk.o clk-pll.o
obj-$(CONFIG_CLK_EXYNOS7420) += clk-exynos7420.o
+obj-$(CONFIG_CLK_EXYNOS7870) += clk-exynos7870.o
obj-$(CONFIG_CLK_EXYNOS850) += clk-exynos850.o
diff --git a/drivers/clk/exynos/clk-exynos7870.c b/drivers/clk/exynos/clk-exynos7870.c
new file mode 100644
index 00000000000..d01b1c75350
--- /dev/null
+++ b/drivers/clk/exynos/clk-exynos7870.c
@@ -0,0 +1,929 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Samsung Exynos7870 clock driver.
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd.
+ * Author: Kaustabh Chakraborty <[email protected]>
+ */
+
+#include "linux/clk-provider.h"
+#include <dm.h>
+#include <asm/io.h>
+#include <dt-bindings/clock/samsung,exynos7870-cmu.h>
+#include "clk.h"
+
+enum exynos7870_cmu_id {
+ CMU_MIF,
+ CMU_FSYS,
+ CMU_PERI,
+};
+
+/*
+ * Register offsets for CMU_MIF (0x10460000)
+ */
+#define PLL_LOCKTIME_MIF_MEM_PLL 0x0000
+#define PLL_LOCKTIME_MIF_MEDIA_PLL 0x0020
+#define PLL_LOCKTIME_MIF_BUS_PLL 0x0040
+#define PLL_CON0_MIF_MEM_PLL 0x0100
+#define PLL_CON0_MIF_MEDIA_PLL 0x0120
+#define PLL_CON0_MIF_BUS_PLL 0x0140
+#define CLK_CON_GAT_MIF_MUX_MEM_PLL 0x0200
+#define CLK_CON_GAT_MIF_MUX_MEM_PLL_CON 0x0200
+#define CLK_CON_GAT_MIF_MUX_MEDIA_PLL 0x0204
+#define CLK_CON_GAT_MIF_MUX_MEDIA_PLL_CON 0x0204
+#define CLK_CON_GAT_MIF_MUX_BUS_PLL 0x0208
+#define CLK_CON_GAT_MIF_MUX_BUS_PLL_CON 0x0208
+#define CLK_CON_GAT_MIF_MUX_BUSD 0x0220
+#define CLK_CON_MUX_MIF_BUSD 0x0220
+#define CLK_CON_GAT_MIF_MUX_CMU_ISP_VRA 0x0264
+#define CLK_CON_MUX_MIF_CMU_ISP_VRA 0x0264
+#define CLK_CON_GAT_MIF_MUX_CMU_ISP_CAM 0x0268
+#define CLK_CON_MUX_MIF_CMU_ISP_CAM 0x0268
+#define CLK_CON_GAT_MIF_MUX_CMU_ISP_ISP 0x026c
+#define CLK_CON_MUX_MIF_CMU_ISP_ISP 0x026c
+#define CLK_CON_GAT_MIF_MUX_CMU_DISPAUD_BUS 0x0270
+#define CLK_CON_MUX_MIF_CMU_DISPAUD_BUS 0x0270
+#define CLK_CON_GAT_MIF_MUX_CMU_DISPAUD_DECON_VCLK 0x0274
+#define CLK_CON_MUX_MIF_CMU_DISPAUD_DECON_VCLK 0x0274
+#define CLK_CON_GAT_MIF_MUX_CMU_DISPAUD_DECON_ECLK 0x0278
+#define CLK_CON_MUX_MIF_CMU_DISPAUD_DECON_ECLK 0x0278
+#define CLK_CON_GAT_MIF_MUX_CMU_MFCMSCL_MSCL 0x027c
+#define CLK_CON_MUX_MIF_CMU_MFCMSCL_MSCL 0x027c
+#define CLK_CON_GAT_MIF_MUX_CMU_MFCMSCL_MFC 0x0280
+#define CLK_CON_MUX_MIF_CMU_MFCMSCL_MFC 0x0280
+#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_BUS 0x0284
+#define CLK_CON_MUX_MIF_CMU_FSYS_BUS 0x0284
+#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC0 0x0288
+#define CLK_CON_MUX_MIF_CMU_FSYS_MMC0 0x0288
+#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC1 0x028c
+#define CLK_CON_MUX_MIF_CMU_FSYS_MMC1 0x028c
+#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC2 0x0290
+#define CLK_CON_MUX_MIF_CMU_FSYS_MMC2 0x0290
+#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_USB20DRD_REFCLK 0x029c
+#define CLK_CON_MUX_MIF_CMU_FSYS_USB20DRD_REFCLK 0x029c
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_BUS 0x02a0
+#define CLK_CON_MUX_MIF_CMU_PERI_BUS 0x02a0
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_UART1 0x02a4
+#define CLK_CON_MUX_MIF_CMU_PERI_UART1 0x02a4
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_UART2 0x02a8
+#define CLK_CON_MUX_MIF_CMU_PERI_UART2 0x02a8
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_UART0 0x02ac
+#define CLK_CON_MUX_MIF_CMU_PERI_UART0 0x02ac
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI2 0x02b0
+#define CLK_CON_MUX_MIF_CMU_PERI_SPI2 0x02b0
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI1 0x02b4
+#define CLK_CON_MUX_MIF_CMU_PERI_SPI1 0x02b4
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI0 0x02b8
+#define CLK_CON_MUX_MIF_CMU_PERI_SPI0 0x02b8
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI3 0x02bc
+#define CLK_CON_MUX_MIF_CMU_PERI_SPI3 0x02bc
+#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI4 0x02c0
+#define CLK_CON_MUX_MIF_CMU_PERI_SPI4 0x02c0
+#define CLK_CON_GAT_MIF_MUX_CMU_ISP_SENSOR0 0x02c4
+#define CLK_CON_MUX_MIF_CMU_ISP_SENSOR0 0x02c4
+#define CLK_CON_GAT_MIF_MUX_CMU_ISP_SENSOR1 0x02c8
+#define CLK_CON_MUX_MIF_CMU_ISP_SENSOR1 0x02c8
+#define CLK_CON_GAT_MIF_MUX_CMU_ISP_SENSOR2 0x02cc
+#define CLK_CON_MUX_MIF_CMU_ISP_SENSOR2 0x02cc
+#define CLK_CON_DIV_MIF_BUSD 0x0420
+#define CLK_CON_DIV_MIF_APB 0x0424
+#define CLK_CON_DIV_MIF_HSI2C 0x0430
+#define CLK_CON_DIV_MIF_CMU_G3D_SWITCH 0x0460
+#define CLK_CON_DIV_MIF_CMU_ISP_VRA 0x0464
+#define CLK_CON_DIV_MIF_CMU_ISP_CAM 0x0468
+#define CLK_CON_DIV_MIF_CMU_ISP_ISP 0x046c
+#define CLK_CON_DIV_MIF_CMU_DISPAUD_BUS 0x0470
+#define CLK_CON_DIV_MIF_CMU_DISPAUD_DECON_VCLK 0x0474
+#define CLK_CON_DIV_MIF_CMU_DISPAUD_DECON_ECLK 0x0478
+#define CLK_CON_DIV_MIF_CMU_MFCMSCL_MSCL 0x047c
+#define CLK_CON_DIV_MIF_CMU_MFCMSCL_MFC 0x0480
+#define CLK_CON_DIV_MIF_CMU_FSYS_BUS 0x0484
+#define CLK_CON_DIV_MIF_CMU_FSYS_MMC0 0x0488
+#define CLK_CON_DIV_MIF_CMU_FSYS_MMC1 0x048c
+#define CLK_CON_DIV_MIF_CMU_FSYS_MMC2 0x0490
+#define CLK_CON_DIV_MIF_CMU_FSYS_USB20DRD_REFCLK 0x049c
+#define CLK_CON_DIV_MIF_CMU_PERI_BUS 0x04a0
+#define CLK_CON_DIV_MIF_CMU_PERI_UART1 0x04a4
+#define CLK_CON_DIV_MIF_CMU_PERI_UART2 0x04a8
+#define CLK_CON_DIV_MIF_CMU_PERI_UART0 0x04ac
+#define CLK_CON_DIV_MIF_CMU_PERI_SPI2 0x04b0
+#define CLK_CON_DIV_MIF_CMU_PERI_SPI1 0x04b4
+#define CLK_CON_DIV_MIF_CMU_PERI_SPI0 0x04b8
+#define CLK_CON_DIV_MIF_CMU_PERI_SPI3 0x04bc
+#define CLK_CON_DIV_MIF_CMU_PERI_SPI4 0x04c0
+#define CLK_CON_DIV_MIF_CMU_ISP_SENSOR0 0x04c4
+#define CLK_CON_DIV_MIF_CMU_ISP_SENSOR1 0x04c8
+#define CLK_CON_DIV_MIF_CMU_ISP_SENSOR2 0x04cc
+#define CLK_CON_GAT_MIF_WRAP_ADC_IF_OSC_SYS 0x080c
+#define CLK_CON_GAT_MIF_HSI2C_AP_PCLKS 0x0828
+#define CLK_CON_GAT_MIF_HSI2C_CP_PCLKS 0x0828
+#define CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S0 0x0828
+#define CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S1 0x0828
+#define CLK_CON_GAT_MIF_CP_PCLK_HSI2C 0x0840
+#define CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_0 0x0840
+#define CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_1 0x0840
+#define CLK_CON_GAT_MIF_HSI2C_AP_PCLKM 0x0840
+#define CLK_CON_GAT_MIF_HSI2C_CP_PCLKM 0x0840
+#define CLK_CON_GAT_MIF_HSI2C_IPCLK 0x0840
+#define CLK_CON_GAT_MIF_HSI2C_ITCLK 0x0840
+#define CLK_CON_GAT_MIF_CMU_G3D_SWITCH 0x0860
+#define CLK_CON_GAT_MIF_CMU_ISP_VRA 0x0864
+#define CLK_CON_GAT_MIF_CMU_ISP_CAM 0x0868
+#define CLK_CON_GAT_MIF_CMU_ISP_ISP 0x086c
+#define CLK_CON_GAT_MIF_CMU_DISPAUD_BUS 0x0870
+#define CLK_CON_GAT_MIF_CMU_DISPAUD_DECON_VCLK 0x0874
+#define CLK_CON_GAT_MIF_CMU_DISPAUD_DECON_ECLK 0x0878
+#define CLK_CON_GAT_MIF_CMU_MFCMSCL_MSCL 0x087c
+#define CLK_CON_GAT_MIF_CMU_MFCMSCL_MFC 0x0880
+#define CLK_CON_GAT_MIF_CMU_FSYS_BUS 0x0884
+#define CLK_CON_GAT_MIF_CMU_FSYS_MMC0 0x0888
+#define CLK_CON_GAT_MIF_CMU_FSYS_MMC1 0x088c
+#define CLK_CON_GAT_MIF_CMU_FSYS_MMC2 0x0890
+#define CLK_CON_GAT_MIF_CMU_FSYS_USB20DRD_REFCLK 0x089c
+#define CLK_CON_GAT_MIF_CMU_PERI_BUS 0x08a0
+#define CLK_CON_GAT_MIF_CMU_PERI_UART1 0x08a4
+#define CLK_CON_GAT_MIF_CMU_PERI_UART2 0x08a8
+#define CLK_CON_GAT_MIF_CMU_PERI_UART0 0x08ac
+#define CLK_CON_GAT_MIF_CMU_PERI_SPI2 0x08b0
+#define CLK_CON_GAT_MIF_CMU_PERI_SPI1 0x08b4
+#define CLK_CON_GAT_MIF_CMU_PERI_SPI0 0x08b8
+#define CLK_CON_GAT_MIF_CMU_PERI_SPI3 0x08bc
+#define CLK_CON_GAT_MIF_CMU_PERI_SPI4 0x08c0
+#define CLK_CON_GAT_MIF_CMU_ISP_SENSOR0 0x08c4
+#define CLK_CON_GAT_MIF_CMU_ISP_SENSOR1 0x08c8
+#define CLK_CON_GAT_MIF_CMU_ISP_SENSOR2 0x08cc
+
+static const struct samsung_pll_clock mif_pll_clks[] = {
+ PLL(pll_1417x, CLK_FOUT_MIF_BUS_PLL, "fout_mif_bus_pll", "oscclk",
+ PLL_CON0_MIF_BUS_PLL),
+ PLL(pll_1417x, CLK_FOUT_MIF_MEDIA_PLL, "fout_mif_media_pll", "oscclk",
+ PLL_CON0_MIF_MEDIA_PLL),
+ PLL(pll_1417x, CLK_FOUT_MIF_MEM_PLL, "fout_mif_mem_pll", "oscclk",
+ PLL_CON0_MIF_MEM_PLL),
+};
+
+static const struct samsung_gate_clock mif_pll_gate_clks[] = {
+ GATE(CLK_GOUT_MIF_MUX_BUS_PLL_CON,
+ "gout_mif_mux_bus_pll_con", "fout_mif_bus_pll",
+ CLK_CON_GAT_MIF_MUX_BUS_PLL_CON, 12,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_MEDIA_PLL_CON,
+ "gout_mif_mux_media_pll_con", "fout_mif_media_pll",
+ CLK_CON_GAT_MIF_MUX_MEDIA_PLL_CON, 12,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_MEM_PLL_CON,
+ "gout_mif_mux_mem_pll_con", "fout_mif_mem_pll",
+ CLK_CON_GAT_MIF_MUX_MEM_PLL_CON, 12,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_BUS_PLL,
+ "gout_mif_mux_bus_pll", "gout_mif_mux_bus_pll_con",
+ CLK_CON_GAT_MIF_MUX_BUS_PLL, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_MEM_PLL,
+ "gout_mif_mux_mem_pll", "gout_mif_mux_mem_pll_con",
+ CLK_CON_GAT_MIF_MUX_MEM_PLL, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_MEDIA_PLL,
+ "gout_mif_mux_media_pll", "gout_mif_mux_media_pll_con",
+ CLK_CON_GAT_MIF_MUX_MEDIA_PLL, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+};
+
+static const struct samsung_fixed_factor_clock mif_fixed_factor_clks[] = {
+ FFACTOR(0, "ffac_mif_mux_bus_pll_div2", "gout_mif_mux_bus_pll_con",
+ 1, 2, 0),
+ FFACTOR(0, "ffac_mif_mux_media_pll_div2", "gout_mif_mux_media_pll_con",
+ 1, 2, 0),
+ FFACTOR(0, "ffac_mif_mux_mem_pll_div2", "gout_mif_mux_mem_pll_con",
+ 1, 2, 0),
+};
+
+/* List of parent clocks for muxes in CMU_MIF */
+PNAME(mout_mif_busd_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2",
+ "ffac_mif_mux_mem_pll_div2" };
+PNAME(mout_mif_cmu_fsys_bus_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_fsys_mmc0_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_fsys_mmc1_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_fsys_mmc2_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_fsys_usb20drd_refclk_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_peri_bus_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_peri_spi0_p) = { "ffac_mif_mux_bus_pll_div2",
+ "oscclk" };
+PNAME(mout_mif_cmu_peri_spi1_p) = { "ffac_mif_mux_bus_pll_div2",
+ "oscclk" };
+PNAME(mout_mif_cmu_peri_spi2_p) = { "ffac_mif_mux_bus_pll_div2",
+ "oscclk" };
+PNAME(mout_mif_cmu_peri_spi3_p) = { "ffac_mif_mux_bus_pll_div2",
+ "oscclk" };
+PNAME(mout_mif_cmu_peri_spi4_p) = { "ffac_mif_mux_bus_pll_div2",
+ "oscclk" };
+PNAME(mout_mif_cmu_peri_uart2_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_peri_uart0_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+PNAME(mout_mif_cmu_peri_uart1_p) = { "ffac_mif_mux_bus_pll_div2",
+ "ffac_mif_mux_media_pll_div2" };
+
+static const struct samsung_mux_clock mif_mux_clks[] = {
+ MUX(CLK_MOUT_MIF_BUSD,
+ "mout_mif_busd", mout_mif_busd_p,
+ CLK_CON_MUX_MIF_BUSD, 12, 2),
+ MUX(CLK_MOUT_MIF_CMU_FSYS_BUS,
+ "mout_mif_cmu_fsys_bus", mout_mif_cmu_fsys_bus_p,
+ CLK_CON_MUX_MIF_CMU_FSYS_BUS, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_FSYS_MMC0,
+ "mout_mif_cmu_fsys_mmc0", mout_mif_cmu_fsys_mmc0_p,
+ CLK_CON_MUX_MIF_CMU_FSYS_MMC0, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_FSYS_MMC1,
+ "mout_mif_cmu_fsys_mmc1", mout_mif_cmu_fsys_mmc1_p,
+ CLK_CON_MUX_MIF_CMU_FSYS_MMC1, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_FSYS_MMC2,
+ "mout_mif_cmu_fsys_mmc2", mout_mif_cmu_fsys_mmc2_p,
+ CLK_CON_MUX_MIF_CMU_FSYS_MMC2, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_FSYS_USB20DRD_REFCLK,
+ "mout_mif_cmu_fsys_usb20drd_refclk", mout_mif_cmu_fsys_usb20drd_refclk_p,
+ CLK_CON_MUX_MIF_CMU_FSYS_USB20DRD_REFCLK, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_BUS,
+ "mout_mif_cmu_peri_bus", mout_mif_cmu_peri_bus_p,
+ CLK_CON_MUX_MIF_CMU_PERI_BUS, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_SPI0,
+ "mout_mif_cmu_peri_spi0", mout_mif_cmu_peri_spi0_p,
+ CLK_CON_MUX_MIF_CMU_PERI_SPI0, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_SPI1,
+ "mout_mif_cmu_peri_spi1", mout_mif_cmu_peri_spi1_p,
+ CLK_CON_MUX_MIF_CMU_PERI_SPI1, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_SPI2,
+ "mout_mif_cmu_peri_spi2", mout_mif_cmu_peri_spi2_p,
+ CLK_CON_MUX_MIF_CMU_PERI_SPI2, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_SPI3,
+ "mout_mif_cmu_peri_spi3", mout_mif_cmu_peri_spi3_p,
+ CLK_CON_MUX_MIF_CMU_PERI_SPI3, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_SPI4,
+ "mout_mif_cmu_peri_spi4", mout_mif_cmu_peri_spi4_p,
+ CLK_CON_MUX_MIF_CMU_PERI_SPI4, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_UART0,
+ "mout_mif_cmu_peri_uart0", mout_mif_cmu_peri_uart0_p,
+ CLK_CON_MUX_MIF_CMU_PERI_UART0, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_UART1,
+ "mout_mif_cmu_peri_uart1", mout_mif_cmu_peri_uart1_p,
+ CLK_CON_MUX_MIF_CMU_PERI_UART1, 12, 1),
+ MUX(CLK_MOUT_MIF_CMU_PERI_UART2,
+ "mout_mif_cmu_peri_uart2", mout_mif_cmu_peri_uart2_p,
+ CLK_CON_MUX_MIF_CMU_PERI_UART2, 12, 1),
+};
+
+static const struct samsung_gate_clock mif_mux_gate_clks[] = {
+ GATE(CLK_GOUT_MIF_MUX_BUSD,
+ "gout_mif_mux_busd", "mout_mif_busd",
+ CLK_CON_GAT_MIF_MUX_BUSD, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_BUS,
+ "gout_mif_mux_cmu_fsys_bus", "mout_mif_cmu_fsys_bus",
+ CLK_CON_GAT_MIF_MUX_CMU_FSYS_BUS, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_MMC0,
+ "gout_mif_mux_cmu_fsys_mmc0", "mout_mif_cmu_fsys_mmc0",
+ CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC0, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_MMC1,
+ "gout_mif_mux_cmu_fsys_mmc1", "mout_mif_cmu_fsys_mmc1",
+ CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC1, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_MMC2,
+ "gout_mif_mux_cmu_fsys_mmc2", "mout_mif_cmu_fsys_mmc2",
+ CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC2, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_USB20DRD_REFCLK,
+ "gout_mif_mux_cmu_fsys_usb20drd_refclk", "mout_mif_cmu_fsys_usb20drd_refclk",
+ CLK_CON_GAT_MIF_MUX_CMU_FSYS_USB20DRD_REFCLK, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_BUS,
+ "gout_mif_mux_cmu_peri_bus", "mout_mif_cmu_peri_bus",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_BUS, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI0,
+ "gout_mif_mux_cmu_peri_spi0", "mout_mif_cmu_peri_spi0",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI0, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI1,
+ "gout_mif_mux_cmu_peri_spi1", "mout_mif_cmu_peri_spi1",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI1, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI2,
+ "gout_mif_mux_cmu_peri_spi2", "mout_mif_cmu_peri_spi2",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI2, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI3,
+ "gout_mif_mux_cmu_peri_spi3", "mout_mif_cmu_peri_spi3",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI3, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI4,
+ "gout_mif_mux_cmu_peri_spi4", "mout_mif_cmu_peri_spi4",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI4, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_UART0,
+ "gout_mif_mux_cmu_peri_uart0", "mout_mif_cmu_peri_uart0",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_UART0, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_UART1,
+ "gout_mif_mux_cmu_peri_uart1", "mout_mif_cmu_peri_uart1",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_UART1, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_MUX_CMU_PERI_UART2,
+ "gout_mif_mux_cmu_peri_uart2", "mout_mif_cmu_peri_uart2",
+ CLK_CON_GAT_MIF_MUX_CMU_PERI_UART2, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+};
+
+static const struct samsung_div_clock mif_div_clks[] = {
+ DIV(CLK_DOUT_MIF_HSI2C,
+ "dout_mif_hsi2c", "ffac_mif_mux_media_pll_div2",
+ CLK_CON_DIV_MIF_HSI2C, 0, 4),
+ DIV(CLK_DOUT_MIF_BUSD,
+ "dout_mif_busd", "gout_mif_mux_busd",
+ CLK_CON_DIV_MIF_BUSD, 0, 4),
+ DIV(CLK_DOUT_MIF_CMU_FSYS_BUS,
+ "dout_mif_cmu_fsys_bus", "gout_mif_mux_cmu_fsys_bus",
+ CLK_CON_DIV_MIF_CMU_FSYS_BUS, 0, 4),
+ DIV(CLK_DOUT_MIF_CMU_FSYS_MMC0,
+ "dout_mif_cmu_fsys_mmc0", "gout_mif_mux_cmu_fsys_mmc0",
+ CLK_CON_DIV_MIF_CMU_FSYS_MMC0, 0, 10),
+ DIV(CLK_DOUT_MIF_CMU_FSYS_MMC1,
+ "dout_mif_cmu_fsys_mmc1", "gout_mif_mux_cmu_fsys_mmc1",
+ CLK_CON_DIV_MIF_CMU_FSYS_MMC1, 0, 10),
+ DIV(CLK_DOUT_MIF_CMU_FSYS_MMC2,
+ "dout_mif_cmu_fsys_mmc2", "gout_mif_mux_cmu_fsys_mmc2",
+ CLK_CON_DIV_MIF_CMU_FSYS_MMC2, 0, 10),
+ DIV(CLK_DOUT_MIF_CMU_FSYS_USB20DRD_REFCLK,
+ "dout_mif_cmu_fsys_usb20drd_refclk", "gout_mif_mux_cmu_fsys_usb20drd_refclk",
+ CLK_CON_DIV_MIF_CMU_FSYS_USB20DRD_REFCLK, 0, 4),
+ DIV(CLK_DOUT_MIF_CMU_PERI_BUS,
+ "dout_mif_cmu_peri_bus", "gout_mif_mux_cmu_peri_bus",
+ CLK_CON_DIV_MIF_CMU_PERI_BUS, 0, 4),
+ DIV(CLK_DOUT_MIF_CMU_PERI_SPI0,
+ "dout_mif_cmu_peri_spi0", "gout_mif_mux_cmu_peri_spi0",
+ CLK_CON_DIV_MIF_CMU_PERI_SPI0, 0, 6),
+ DIV(CLK_DOUT_MIF_CMU_PERI_SPI1,
+ "dout_mif_cmu_peri_spi1", "gout_mif_mux_cmu_peri_spi1",
+ CLK_CON_DIV_MIF_CMU_PERI_SPI1, 0, 6),
+ DIV(CLK_DOUT_MIF_CMU_PERI_SPI2,
+ "dout_mif_cmu_peri_spi2", "gout_mif_mux_cmu_peri_spi2",
+ CLK_CON_DIV_MIF_CMU_PERI_SPI2, 0, 6),
+ DIV(CLK_DOUT_MIF_CMU_PERI_SPI3,
+ "dout_mif_cmu_peri_spi3", "gout_mif_mux_cmu_peri_spi3",
+ CLK_CON_DIV_MIF_CMU_PERI_SPI3, 0, 6),
+ DIV(CLK_DOUT_MIF_CMU_PERI_SPI4,
+ "dout_mif_cmu_peri_spi4", "gout_mif_mux_cmu_peri_spi4",
+ CLK_CON_DIV_MIF_CMU_PERI_SPI4, 0, 6),
+ DIV(CLK_DOUT_MIF_CMU_PERI_UART0,
+ "dout_mif_cmu_peri_uart0", "gout_mif_mux_cmu_peri_uart0",
+ CLK_CON_DIV_MIF_CMU_PERI_UART0, 0, 4),
+ DIV(CLK_DOUT_MIF_CMU_PERI_UART1,
+ "dout_mif_cmu_peri_uart1", "gout_mif_mux_cmu_peri_uart1",
+ CLK_CON_DIV_MIF_CMU_PERI_UART1, 0, 4),
+ DIV(CLK_DOUT_MIF_CMU_PERI_UART2,
+ "dout_mif_cmu_peri_uart2", "gout_mif_mux_cmu_peri_uart2",
+ CLK_CON_DIV_MIF_CMU_PERI_UART2, 0, 4),
+ DIV(CLK_DOUT_MIF_APB,
+ "dout_mif_apb", "dout_mif_busd",
+ CLK_CON_DIV_MIF_APB, 0, 2),
+};
+
+static const struct samsung_gate_clock mif_gate_clks[] = {
+ GATE(CLK_GOUT_MIF_WRAP_ADC_IF_OSC_SYS,
+ "gout_mif_wrap_adc_if_osc_sys", "oscclk",
+ CLK_CON_GAT_MIF_WRAP_ADC_IF_OSC_SYS, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_HSI2C_AP_PCLKS,
+ "gout_mif_hsi2c_ap_pclks", "dout_mif_apb",
+ CLK_CON_GAT_MIF_HSI2C_AP_PCLKS, 14,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_HSI2C_CP_PCLKS,
+ "gout_mif_hsi2c_cp_pclks", "dout_mif_apb",
+ CLK_CON_GAT_MIF_HSI2C_CP_PCLKS, 15,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_WRAP_ADC_IF_PCLK_S0,
+ "gout_mif_wrap_adc_if_pclk_s0", "dout_mif_apb",
+ CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S0, 20,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_WRAP_ADC_IF_PCLK_S1,
+ "gout_mif_wrap_adc_if_pclk_s1", "dout_mif_apb",
+ CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S1, 21,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_FSYS_BUS,
+ "gout_mif_cmu_fsys_bus", "dout_mif_cmu_fsys_bus",
+ CLK_CON_GAT_MIF_CMU_FSYS_BUS, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_FSYS_MMC0,
+ "gout_mif_cmu_fsys_mmc0", "dout_mif_cmu_fsys_mmc0",
+ CLK_CON_GAT_MIF_CMU_FSYS_MMC0, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_FSYS_MMC1,
+ "gout_mif_cmu_fsys_mmc1", "dout_mif_cmu_fsys_mmc1",
+ CLK_CON_GAT_MIF_CMU_FSYS_MMC1, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_FSYS_MMC2,
+ "gout_mif_cmu_fsys_mmc2", "dout_mif_cmu_fsys_mmc2",
+ CLK_CON_GAT_MIF_CMU_FSYS_MMC2, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_FSYS_USB20DRD_REFCLK,
+ "gout_mif_cmu_fsys_usb20drd_refclk", "dout_mif_cmu_fsys_usb20drd_refclk",
+ CLK_CON_GAT_MIF_CMU_FSYS_USB20DRD_REFCLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_BUS,
+ "gout_mif_cmu_peri_bus", "dout_mif_cmu_peri_bus",
+ CLK_CON_GAT_MIF_CMU_PERI_BUS, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_SPI0,
+ "gout_mif_cmu_peri_spi0", "dout_mif_cmu_peri_spi0",
+ CLK_CON_GAT_MIF_CMU_PERI_SPI0, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_SPI1,
+ "gout_mif_cmu_peri_spi1", "dout_mif_cmu_peri_spi1",
+ CLK_CON_GAT_MIF_CMU_PERI_SPI1, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_SPI2,
+ "gout_mif_cmu_peri_spi2", "dout_mif_cmu_peri_spi2",
+ CLK_CON_GAT_MIF_CMU_PERI_SPI2, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_SPI3,
+ "gout_mif_cmu_peri_spi3", "dout_mif_cmu_peri_spi3",
+ CLK_CON_GAT_MIF_CMU_PERI_SPI3, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_SPI4,
+ "gout_mif_cmu_peri_spi4", "dout_mif_cmu_peri_spi4",
+ CLK_CON_GAT_MIF_CMU_PERI_SPI4, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_UART0,
+ "gout_mif_cmu_peri_uart0", "dout_mif_cmu_peri_uart0",
+ CLK_CON_GAT_MIF_CMU_PERI_UART0, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_UART1,
+ "gout_mif_cmu_peri_uart1", "dout_mif_cmu_peri_uart1",
+ CLK_CON_GAT_MIF_CMU_PERI_UART1, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CMU_PERI_UART2,
+ "gout_mif_cmu_peri_uart2", "dout_mif_cmu_peri_uart2",
+ CLK_CON_GAT_MIF_CMU_PERI_UART2, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CP_PCLK_HSI2C,
+ "gout_mif_cp_pclk_hsi2c", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_CP_PCLK_HSI2C, 6,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CP_PCLK_HSI2C_BAT_0,
+ "gout_mif_cp_pclk_hsi2c_bat_0", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_CP_PCLK_HSI2C_BAT_1,
+ "gout_mif_cp_pclk_hsi2c_bat_1", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_1, 5,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_HSI2C_AP_PCLKM,
+ "gout_mif_hsi2c_ap_pclkm", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_HSI2C_AP_PCLKM, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_HSI2C_CP_PCLKM,
+ "gout_mif_hsi2c_cp_pclkm", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_HSI2C_CP_PCLKM, 1,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_HSI2C_IPCLK,
+ "gout_mif_hsi2c_ipclk", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_HSI2C_IPCLK, 2,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_MIF_HSI2C_ITCLK,
+ "gout_mif_hsi2c_itclk", "dout_mif_hsi2c",
+ CLK_CON_GAT_MIF_HSI2C_ITCLK, 3,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+static const struct samsung_clk_group mif_cmu_clks[] = {
+ { S_CLK_PLL, mif_pll_clks, ARRAY_SIZE(mif_pll_clks) },
+ { S_CLK_GATE, mif_pll_gate_clks, ARRAY_SIZE(mif_pll_gate_clks) },
+ { S_CLK_FFACTOR, mif_fixed_factor_clks, ARRAY_SIZE(mif_fixed_factor_clks) },
+ { S_CLK_MUX, mif_mux_clks, ARRAY_SIZE(mif_mux_clks) },
+ { S_CLK_GATE, mif_mux_gate_clks, ARRAY_SIZE(mif_mux_gate_clks) },
+ { S_CLK_DIV, mif_div_clks, ARRAY_SIZE(mif_div_clks) },
+ { S_CLK_GATE, mif_gate_clks, ARRAY_SIZE(mif_gate_clks) },
+};
+
+static int exynos7870_cmu_mif_probe(struct udevice *dev)
+{
+ return samsung_register_cmu(dev, CMU_MIF, mif_cmu_clks,
+ exynos7870_cmu_mif);
+}
+
+static const struct udevice_id exynos7870_cmu_mif_ids[] = {
+ { .compatible = "samsung,exynos7870-cmu-mif" },
+ { }
+};
+
+SAMSUNG_CLK_OPS(exynos7870_cmu_mif, CMU_MIF);
+
+U_BOOT_DRIVER(exynos7870_cmu_mif) = {
+ .name = "exynos7870-cmu-mif",
+ .id = UCLASS_CLK,
+ .of_match = exynos7870_cmu_mif_ids,
+ .ops = &exynos7870_cmu_mif_clk_ops,
+ .probe = exynos7870_cmu_mif_probe,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+/*
+ * Register offsets for CMU_FSYS (0x13730000)
+ */
+#define PLL_LOCKTIME_FSYS_USB_PLL 0x0000
+#define PLL_CON0_FSYS_USB_PLL 0x0100
+#define CLK_CON_GAT_FSYS_MUX_USB_PLL 0x0200
+#define CLK_CON_GAT_FSYS_MUX_USB_PLL_CON 0x0200
+#define CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER 0x0230
+#define CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER_CON 0x0230
+#define CLK_CON_GAT_FSYS_BUSP3_HCLK 0x0804
+#define CLK_CON_GAT_FSYS_MMC0_ACLK 0x0804
+#define CLK_CON_GAT_FSYS_MMC1_ACLK 0x0804
+#define CLK_CON_GAT_FSYS_MMC2_ACLK 0x0804
+#define CLK_CON_GAT_FSYS_PDMA0_ACLK_PDMA0 0x0804
+#define CLK_CON_GAT_FSYS_PPMU_ACLK 0x0804
+#define CLK_CON_GAT_FSYS_PPMU_PCLK 0x0804
+#define CLK_CON_GAT_FSYS_SROMC_HCLK 0x0804
+#define CLK_CON_GAT_FSYS_UPSIZER_BUS1_ACLK 0x0804
+#define CLK_CON_GAT_FSYS_USB20DRD_ACLK_HSDRD 0x0804
+#define CLK_CON_GAT_FSYS_USB20DRD_HCLK_USB20_CTRL 0x0804
+#define CLK_CON_GAT_FSYS_USB20DRD_HSDRD_REF_CLK 0x0828
+
+static const struct samsung_fixed_rate_clock fsys_fixed_rate_clks[] = {
+ FRATE(0, "frat_fsys_usb20drd_phyclock", 60000000),
+};
+
+static const struct samsung_pll_clock fsys_pll_clks[] = {
+ PLL(pll_1417x, CLK_FOUT_FSYS_USB_PLL, "fout_fsys_usb_pll", "oscclk",
+ PLL_CON0_FSYS_USB_PLL),
+};
+
+static const struct samsung_gate_clock fsys_gate_clks[] = {
+ GATE(CLK_GOUT_FSYS_BUSP3_HCLK,
+ "gout_fsys_busp3_hclk", "bus",
+ CLK_CON_GAT_FSYS_BUSP3_HCLK, 2,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_UPSIZER_BUS1_ACLK,
+ "gout_fsys_upsizer_bus1_aclk", "bus",
+ CLK_CON_GAT_FSYS_UPSIZER_BUS1_ACLK, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_PPMU_ACLK,
+ "gout_fsys_ppmu_aclk", "bus",
+ CLK_CON_GAT_FSYS_PPMU_ACLK, 17,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_PPMU_PCLK,
+ "gout_fsys_ppmu_pclk", "bus",
+ CLK_CON_GAT_FSYS_PPMU_PCLK, 18,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_USB20DRD_HSDRD_REF_CLK,
+ "gout_fsys_usb20drd_hsdrd_ref_clk", "usb20drd",
+ CLK_CON_GAT_FSYS_USB20DRD_HSDRD_REF_CLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MUX_USB20DRD_PHYCLOCK_USER_CON,
+ "gout_fsys_mux_usb20drd_phyclock_user_con", "frat_fsys_usb20drd_phyclock",
+ CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER_CON, 12,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MUX_USB_PLL_CON,
+ "gout_fsys_mux_usb_pll_con", "fout_fsys_usb_pll",
+ CLK_CON_GAT_FSYS_MUX_USB_PLL_CON, 12,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MMC0_ACLK,
+ "gout_fsys_mmc0_aclk", "gout_fsys_busp3_hclk",
+ CLK_CON_GAT_FSYS_MMC0_ACLK, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MMC1_ACLK,
+ "gout_fsys_mmc1_aclk", "gout_fsys_busp3_hclk",
+ CLK_CON_GAT_FSYS_MMC1_ACLK, 9,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MMC2_ACLK,
+ "gout_fsys_mmc2_aclk", "gout_fsys_busp3_hclk",
+ CLK_CON_GAT_FSYS_MMC2_ACLK, 10,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_USB20DRD_ACLK_HSDRD,
+ "gout_fsys_usb20drd_aclk_hsdrd", "gout_fsys_busp3_hclk",
+ CLK_CON_GAT_FSYS_USB20DRD_ACLK_HSDRD, 20,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_SROMC_HCLK,
+ "gout_fsys_sromc_hclk", "gout_fsys_busp3_hclk",
+ CLK_CON_GAT_FSYS_SROMC_HCLK, 6,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_USB20DRD_HCLK_USB20_CTRL,
+ "gout_fsys_usb20drd_hclk_usb20_ctrl", "gout_fsys_busp3_hclk",
+ CLK_CON_GAT_FSYS_USB20DRD_HCLK_USB20_CTRL, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MUX_USB_PLL,
+ "gout_fsys_mux_usb_pll", "gout_fsys_mux_usb_pll_con",
+ CLK_CON_GAT_FSYS_MUX_USB_PLL, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_MUX_USB20DRD_PHYCLOCK_USER,
+ "gout_fsys_mux_usb20drd_phyclock_user", "gout_fsys_mux_usb20drd_phyclock_user_con",
+ CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER, 21,
+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS_PDMA0_ACLK_PDMA0,
+ "gout_fsys_pdma0_aclk_pdma0", "gout_fsys_upsizer_bus1_aclk",
+ CLK_CON_GAT_FSYS_PDMA0_ACLK_PDMA0, 7,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+static const struct samsung_clk_group fsys_cmu_clks[] = {
+ { S_CLK_FRATE, fsys_fixed_rate_clks, ARRAY_SIZE(fsys_fixed_rate_clks) },
+ { S_CLK_PLL, fsys_pll_clks, ARRAY_SIZE(fsys_pll_clks) },
+ { S_CLK_GATE, fsys_gate_clks, ARRAY_SIZE(fsys_gate_clks) },
+};
+
+static int exynos7870_cmu_fsys_probe(struct udevice *dev)
+{
+ return samsung_register_cmu(dev, CMU_FSYS, fsys_cmu_clks,
+ exynos7870_cmu_fsys);
+}
+
+static const struct udevice_id exynos7870_cmu_fsys_ids[] = {
+ { .compatible = "samsung,exynos7870-cmu-fsys" },
+ { }
+};
+
+SAMSUNG_CLK_OPS(exynos7870_cmu_fsys, CMU_FSYS);
+
+U_BOOT_DRIVER(exynos7870_cmu_fsys) = {
+ .name = "exynos7870-cmu-fsys",
+ .id = UCLASS_CLK,
+ .of_match = exynos7870_cmu_fsys_ids,
+ .ops = &exynos7870_cmu_fsys_clk_ops,
+ .probe = exynos7870_cmu_fsys_probe,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+/*
+ * Register offsets for CMU_PERI (0x101f0000)
+ */
+#define CLK_CON_GAT_PERI_PWM_MOTOR_OSCCLK 0x0800
+#define CLK_CON_GAT_PERI_TMU_CLK 0x0800
+#define CLK_CON_GAT_PERI_TMU_CPUCL0_CLK 0x0800
+#define CLK_CON_GAT_PERI_TMU_CPUCL1_CLK 0x0800
+#define CLK_CON_GAT_PERI_BUSP1_PERIC0_HCLK 0x0810
+#define CLK_CON_GAT_PERI_GPIO2_PCLK 0x0810
+#define CLK_CON_GAT_PERI_GPIO5_PCLK 0x0810
+#define CLK_CON_GAT_PERI_GPIO6_PCLK 0x0810
+#define CLK_CON_GAT_PERI_GPIO7_PCLK 0x0810
+#define CLK_CON_GAT_PERI_HSI2C1_IPCLK 0x0810
+#define CLK_CON_GAT_PERI_HSI2C2_IPCLK 0x0810
+#define CLK_CON_GAT_PERI_HSI2C3_IPCLK 0x0810
+#define CLK_CON_GAT_PERI_HSI2C4_IPCLK 0x0810
+#define CLK_CON_GAT_PERI_HSI2C5_IPCLK 0x0810
+#define CLK_CON_GAT_PERI_HSI2C6_IPCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C0_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C1_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C2_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C3_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C4_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C5_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C6_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C7_PCLK 0x0810
+#define CLK_CON_GAT_PERI_I2C8_PCLK 0x0810
+#define CLK_CON_GAT_PERI_MCT_PCLK 0x0810
+#define CLK_CON_GAT_PERI_PWM_MOTOR_PCLK_S0 0x0810
+#define CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL0_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL1_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SFRIF_TMU_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SPI0_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SPI1_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SPI2_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SPI3_PCLK 0x0814
+#define CLK_CON_GAT_PERI_SPI4_PCLK 0x0814
+#define CLK_CON_GAT_PERI_UART0_PCLK 0x0814
+#define CLK_CON_GAT_PERI_UART1_PCLK 0x0814
+#define CLK_CON_GAT_PERI_UART2_PCLK 0x0814
+#define CLK_CON_GAT_PERI_WDT_CPUCL0_PCLK 0x0814
+#define CLK_CON_GAT_PERI_WDT_CPUCL1_PCLK 0x0814
+#define CLK_CON_GAT_PERI_UART1_EXT_UCLK 0x0830
+#define CLK_CON_GAT_PERI_UART2_EXT_UCLK 0x0834
+#define CLK_CON_GAT_PERI_UART0_EXT_UCLK 0x0838
+#define CLK_CON_GAT_PERI_SPI2_SPI_EXT_CLK 0x083c
+#define CLK_CON_GAT_PERI_SPI1_SPI_EXT_CLK 0x0840
+#define CLK_CON_GAT_PERI_SPI0_SPI_EXT_CLK 0x0844
+#define CLK_CON_GAT_PERI_SPI3_SPI_EXT_CLK 0x0848
+#define CLK_CON_GAT_PERI_SPI4_SPI_EXT_CLK 0x084c
+
+static const struct samsung_gate_clock peri_gate_clks[] = {
+ GATE(CLK_GOUT_PERI_PWM_MOTOR_OSCCLK,
+ "gout_peri_pwm_motor_oscclk", "oscclk",
+ CLK_CON_GAT_PERI_PWM_MOTOR_OSCCLK, 2,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_TMU_CLK,
+ "gout_peri_tmu_clk", "oscclk",
+ CLK_CON_GAT_PERI_TMU_CLK, 6,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_TMU_CPUCL0_CLK,
+ "gout_peri_tmu_cpucl0_clk", "oscclk",
+ CLK_CON_GAT_PERI_TMU_CPUCL0_CLK, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_TMU_CPUCL1_CLK,
+ "gout_peri_tmu_cpucl1_clk", "oscclk",
+ CLK_CON_GAT_PERI_TMU_CPUCL1_CLK, 5,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_BUSP1_PERIC0_HCLK,
+ "gout_peri_busp1_peric0_hclk", "bus",
+ CLK_CON_GAT_PERI_BUSP1_PERIC0_HCLK, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_GPIO2_PCLK,
+ "gout_peri_gpio2_pclk", "bus",
+ CLK_CON_GAT_PERI_GPIO2_PCLK, 7,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_GPIO5_PCLK,
+ "gout_peri_gpio5_pclk", "bus",
+ CLK_CON_GAT_PERI_GPIO5_PCLK, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_GPIO6_PCLK,
+ "gout_peri_gpio6_pclk", "bus",
+ CLK_CON_GAT_PERI_GPIO6_PCLK, 9,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_GPIO7_PCLK,
+ "gout_peri_gpio7_pclk", "bus",
+ CLK_CON_GAT_PERI_GPIO7_PCLK, 10,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_HSI2C5_IPCLK,
+ "gout_peri_hsi2c5_ipclk", "bus",
+ CLK_CON_GAT_PERI_HSI2C5_IPCLK, 15,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_HSI2C6_IPCLK,
+ "gout_peri_hsi2c6_ipclk", "bus",
+ CLK_CON_GAT_PERI_HSI2C6_IPCLK, 16,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_MCT_PCLK,
+ "gout_peri_mct_pclk", "bus",
+ CLK_CON_GAT_PERI_MCT_PCLK, 26,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_PWM_MOTOR_PCLK_S0,
+ "gout_peri_pwm_motor_pclk_s0", "bus",
+ CLK_CON_GAT_PERI_PWM_MOTOR_PCLK_S0, 29,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SFRIF_TMU_CPUCL0_PCLK,
+ "gout_peri_sfrif_tmu_cpucl0_pclk", "bus",
+ CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL0_PCLK, 1,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SFRIF_TMU_CPUCL1_PCLK,
+ "gout_peri_sfrif_tmu_cpucl1_pclk", "bus",
+ CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL1_PCLK, 2,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SFRIF_TMU_PCLK,
+ "gout_peri_sfrif_tmu_pclk", "bus",
+ CLK_CON_GAT_PERI_SFRIF_TMU_PCLK, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI0_PCLK,
+ "gout_peri_spi0_pclk", "bus",
+ CLK_CON_GAT_PERI_SPI0_PCLK, 6,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI1_PCLK,
+ "gout_peri_spi1_pclk", "bus",
+ CLK_CON_GAT_PERI_SPI1_PCLK, 5,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI2_PCLK,
+ "gout_peri_spi2_pclk", "bus",
+ CLK_CON_GAT_PERI_SPI2_PCLK, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI3_PCLK,
+ "gout_peri_spi3_pclk", "bus",
+ CLK_CON_GAT_PERI_SPI3_PCLK, 7,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI4_PCLK,
+ "gout_peri_spi4_pclk", "bus",
+ CLK_CON_GAT_PERI_SPI4_PCLK, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_WDT_CPUCL0_PCLK,
+ "gout_peri_wdt_cpucl0_pclk", "bus",
+ CLK_CON_GAT_PERI_WDT_CPUCL0_PCLK, 13,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_WDT_CPUCL1_PCLK,
+ "gout_peri_wdt_cpucl1_pclk", "bus",
+ CLK_CON_GAT_PERI_WDT_CPUCL1_PCLK, 14,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI0_SPI_EXT_CLK,
+ "gout_peri_spi0_spi_ext_clk", "spi0",
+ CLK_CON_GAT_PERI_SPI0_SPI_EXT_CLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI1_SPI_EXT_CLK,
+ "gout_peri_spi1_spi_ext_clk", "spi1",
+ CLK_CON_GAT_PERI_SPI1_SPI_EXT_CLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI2_SPI_EXT_CLK,
+ "gout_peri_spi2_spi_ext_clk", "spi2",
+ CLK_CON_GAT_PERI_SPI2_SPI_EXT_CLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI3_SPI_EXT_CLK,
+ "gout_peri_spi3_spi_ext_clk", "spi3",
+ CLK_CON_GAT_PERI_SPI3_SPI_EXT_CLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_SPI4_SPI_EXT_CLK,
+ "gout_peri_spi4_spi_ext_clk", "spi4",
+ CLK_CON_GAT_PERI_SPI4_SPI_EXT_CLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_UART0_EXT_UCLK,
+ "gout_peri_uart0_ext_uclk", "uart0",
+ CLK_CON_GAT_PERI_UART0_EXT_UCLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_UART1_EXT_UCLK,
+ "gout_peri_uart1_ext_uclk", "uart1",
+ CLK_CON_GAT_PERI_UART1_EXT_UCLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_UART2_EXT_UCLK,
+ "gout_peri_uart2_ext_uclk", "uart2",
+ CLK_CON_GAT_PERI_UART2_EXT_UCLK, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_HSI2C1_IPCLK,
+ "gout_peri_hsi2c1_ipclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_HSI2C1_IPCLK, 11,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_HSI2C2_IPCLK,
+ "gout_peri_hsi2c2_ipclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_HSI2C2_IPCLK, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_HSI2C3_IPCLK,
+ "gout_peri_hsi2c3_ipclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_HSI2C3_IPCLK, 13,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_HSI2C4_IPCLK,
+ "gout_peri_hsi2c4_ipclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_HSI2C4_IPCLK, 14,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C0_PCLK,
+ "gout_peri_i2c0_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C0_PCLK, 21,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C1_PCLK,
+ "gout_peri_i2c1_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C1_PCLK, 23,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C2_PCLK,
+ "gout_peri_i2c2_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C2_PCLK, 22,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C3_PCLK,
+ "gout_peri_i2c3_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C3_PCLK, 20,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C4_PCLK,
+ "gout_peri_i2c4_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C4_PCLK, 17,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C5_PCLK,
+ "gout_peri_i2c5_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C5_PCLK, 18,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C6_PCLK,
+ "gout_peri_i2c6_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C6_PCLK, 19,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C7_PCLK,
+ "gout_peri_i2c7_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C7_PCLK, 24,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_I2C8_PCLK,
+ "gout_peri_i2c8_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_I2C8_PCLK, 25,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_UART0_PCLK,
+ "gout_peri_uart0_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_UART0_PCLK, 10,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_UART1_PCLK,
+ "gout_peri_uart1_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_UART1_PCLK, 11,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_PERI_UART2_PCLK,
+ "gout_peri_uart2_pclk", "gout_peri_busp1_peric0_hclk",
+ CLK_CON_GAT_PERI_UART2_PCLK, 12,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+static const struct samsung_clk_group peri_cmu_clks[] = {
+ { S_CLK_GATE, peri_gate_clks, ARRAY_SIZE(peri_gate_clks) },
+};
+
+static int exynos7870_cmu_peri_probe(struct udevice *dev)
+{
+ return samsung_register_cmu(dev, CMU_PERI, peri_cmu_clks,
+ exynos7870_cmu_peri);
+}
+
+static const struct udevice_id exynos7870_cmu_peri_ids[] = {
+ { .compatible = "samsung,exynos7870-cmu-peri" },
+ { }
+};
+
+SAMSUNG_CLK_OPS(exynos7870_cmu_peri, CMU_PERI);
+
+U_BOOT_DRIVER(exynos7870_cmu_peri) = {
+ .name = "exynos7870-cmu-peri",
+ .id = UCLASS_CLK,
+ .of_match = exynos7870_cmu_peri_ids,
+ .ops = &exynos7870_cmu_peri_clk_ops,
+ .probe = exynos7870_cmu_peri_probe,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/exynos/clk-pll.c b/drivers/clk/exynos/clk-pll.c
index 542d577eaa6..4b67591af10 100644
--- a/drivers/clk/exynos/clk-pll.c
+++ b/drivers/clk/exynos/clk-pll.c
@@ -117,6 +117,7 @@ static struct clk *_samsung_clk_register_pll(void __iomem *base,
switch (pll_clk->type) {
case pll_0822x:
+ case pll_1417x:
drv_name = UBOOT_DM_CLK_SAMSUNG_PLL0822X;
break;
case pll_0831x:
@@ -136,7 +137,8 @@ static struct clk *_samsung_clk_register_pll(void __iomem *base,
return clk;
}
-void samsung_clk_register_pll(void __iomem *base, unsigned int cmu_id,
+void samsung_clk_register_pll(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
const struct samsung_pll_clock *clk_list,
unsigned int nr_clk)
{
diff --git a/drivers/clk/exynos/clk-pll.h b/drivers/clk/exynos/clk-pll.h
index bdc94e7624d..d5dfc8934ba 100644
--- a/drivers/clk/exynos/clk-pll.h
+++ b/drivers/clk/exynos/clk-pll.h
@@ -20,9 +20,11 @@ struct samsung_pll_clock;
enum samsung_pll_type {
pll_0822x,
pll_0831x,
+ pll_1417x,
};
-void samsung_clk_register_pll(void __iomem *base, unsigned int cmu_id,
+void samsung_clk_register_pll(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
const struct samsung_pll_clock *clk_list,
unsigned int nr_clk);
diff --git a/drivers/clk/exynos/clk.c b/drivers/clk/exynos/clk.c
index 943e8bd0189..a2c9f4851da 100644
--- a/drivers/clk/exynos/clk.c
+++ b/drivers/clk/exynos/clk.c
@@ -10,7 +10,62 @@
#include <dm.h>
#include "clk.h"
-static void samsung_clk_register_mux(void __iomem *base, unsigned int cmu_id,
+int samsung_clk_request(struct clk *clk)
+{
+ struct clk *c;
+ int ret;
+
+ ret = clk_get_by_id(clk->id, &c);
+ if (ret)
+ return ret;
+
+ clk->dev = c->dev;
+ return 0;
+}
+
+static void
+samsung_clk_register_fixed_rate(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
+ const struct samsung_fixed_rate_clock *clk_list,
+ unsigned int nr_clk)
+{
+ unsigned int cnt;
+
+ for (cnt = 0; cnt < nr_clk; cnt++) {
+ struct clk *clk;
+ const struct samsung_fixed_rate_clock *m;
+ unsigned long clk_id;
+
+ m = &clk_list[cnt];
+ clk = clk_register_fixed_rate(NULL, m->name, m->fixed_rate);
+ clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
+ clk_dm(clk_id, clk);
+ }
+}
+
+static void
+samsung_clk_register_fixed_factor(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
+ const struct samsung_fixed_factor_clock *clk_list,
+ unsigned int nr_clk)
+{
+ unsigned int cnt;
+
+ for (cnt = 0; cnt < nr_clk; cnt++) {
+ struct clk *clk;
+ const struct samsung_fixed_factor_clock *m;
+ unsigned long clk_id;
+
+ m = &clk_list[cnt];
+ clk = clk_register_fixed_factor(dev, m->name, m->parent_name,
+ m->flags, m->mult, m->div);
+ clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
+ clk_dm(clk_id, clk);
+ }
+}
+
+static void samsung_clk_register_mux(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
const struct samsung_mux_clock *clk_list,
unsigned int nr_clk)
{
@@ -22,15 +77,17 @@ static void samsung_clk_register_mux(void __iomem *base, unsigned int cmu_id,
unsigned long clk_id;
m = &clk_list[cnt];
- clk = clk_register_mux(NULL, m->name, m->parent_names,
- m->num_parents, m->flags, base + m->offset, m->shift,
- m->width, m->mux_flags);
+ clk = clk_register_mux(dev, m->name, m->parent_names,
+ m->num_parents, m->flags,
+ base + m->offset, m->shift, m->width,
+ m->mux_flags);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
clk_dm(clk_id, clk);
}
}
-static void samsung_clk_register_div(void __iomem *base, unsigned int cmu_id,
+static void samsung_clk_register_div(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
const struct samsung_div_clock *clk_list,
unsigned int nr_clk)
{
@@ -42,15 +99,16 @@ static void samsung_clk_register_div(void __iomem *base, unsigned int cmu_id,
unsigned long clk_id;
d = &clk_list[cnt];
- clk = clk_register_divider(NULL, d->name, d->parent_name,
- d->flags, base + d->offset, d->shift,
- d->width, d->div_flags);
+ clk = clk_register_divider(dev, d->name, d->parent_name,
+ d->flags, base + d->offset, d->shift,
+ d->width, d->div_flags);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, d->id);
clk_dm(clk_id, clk);
}
}
-static void samsung_clk_register_gate(void __iomem *base, unsigned int cmu_id,
+static void samsung_clk_register_gate(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
const struct samsung_gate_clock *clk_list,
unsigned int nr_clk)
{
@@ -62,19 +120,21 @@ static void samsung_clk_register_gate(void __iomem *base, unsigned int cmu_id,
unsigned long clk_id;
g = &clk_list[cnt];
- clk = clk_register_gate(NULL, g->name, g->parent_name,
- g->flags, base + g->offset, g->bit_idx,
- g->gate_flags, NULL);
+ clk = clk_register_gate(dev, g->name, g->parent_name,
+ g->flags, base + g->offset, g->bit_idx,
+ g->gate_flags, NULL);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, g->id);
clk_dm(clk_id, clk);
}
}
-typedef void (*samsung_clk_register_fn)(void __iomem *base, unsigned int cmu_id,
- const void *clk_list,
+typedef void (*samsung_clk_register_fn)(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id, const void *clk_list,
unsigned int nr_clk);
static const samsung_clk_register_fn samsung_clk_register_fns[] = {
+ [S_CLK_FRATE] = (samsung_clk_register_fn)samsung_clk_register_fixed_rate,
+ [S_CLK_FFACTOR] = (samsung_clk_register_fn)samsung_clk_register_fixed_factor,
[S_CLK_MUX] = (samsung_clk_register_fn)samsung_clk_register_mux,
[S_CLK_DIV] = (samsung_clk_register_fn)samsung_clk_register_div,
[S_CLK_GATE] = (samsung_clk_register_fn)samsung_clk_register_gate,
@@ -91,16 +151,17 @@ static const samsung_clk_register_fn samsung_clk_register_fns[] = {
* Having the array of clock groups @clk_groups makes it possible to keep a
* correct clocks registration order.
*/
-static void samsung_cmu_register_clocks(void __iomem *base, unsigned int cmu_id,
- const struct samsung_clk_group *clk_groups,
- unsigned int nr_groups)
+static void samsung_cmu_register_clocks(struct udevice *dev, void __iomem *base,
+ unsigned int cmu_id,
+ const struct samsung_clk_group *clk_groups,
+ unsigned int nr_groups)
{
unsigned int i;
for (i = 0; i < nr_groups; i++) {
const struct samsung_clk_group *g = &clk_groups[i];
- samsung_clk_register_fns[g->type](base, cmu_id,
+ samsung_clk_register_fns[g->type](dev, base, cmu_id,
g->clk_list, g->nr_clk);
}
}
@@ -124,7 +185,7 @@ int samsung_cmu_register_one(struct udevice *dev, unsigned int cmu_id,
if (!base)
return -EINVAL;
- samsung_cmu_register_clocks(base, cmu_id, clk_groups, nr_groups);
+ samsung_cmu_register_clocks(dev, base, cmu_id, clk_groups, nr_groups);
return 0;
}
diff --git a/drivers/clk/exynos/clk.h b/drivers/clk/exynos/clk.h
index ed0a395f0f6..c25b7cb59d4 100644
--- a/drivers/clk/exynos/clk.h
+++ b/drivers/clk/exynos/clk.h
@@ -9,10 +9,13 @@
#ifndef __EXYNOS_CLK_H
#define __EXYNOS_CLK_H
+#include <clk.h>
#include <errno.h>
#include <linux/clk-provider.h>
#include "clk-pll.h"
+int samsung_clk_request(struct clk *clk);
+
#define _SAMSUNG_CLK_OPS(_name, _cmu) \
static int _name##_of_xlate(struct clk *clk, \
struct ofnode_phandle_args *args) \
@@ -37,6 +40,7 @@ static const struct clk_ops _name##_clk_ops = { \
.enable = ccf_clk_enable, \
.disable = ccf_clk_disable, \
.of_xlate = _name##_of_xlate, \
+ .request = samsung_clk_request, \
}
/**
@@ -59,6 +63,53 @@ static const struct clk_ops _name##_clk_ops = { \
#define SAMSUNG_TO_CLK_ID(_cmu, _id) (((_cmu) << 8) | ((_id) & 0xff))
/**
+ * struct samsung_fixed_rate_clock - information about fixed-rate clock
+ * @id: platform specific id of the clock
+ * @name: name of this fixed-rate clock
+ * @fixed_rate: fixed clock rate of this clock
+ */
+struct samsung_fixed_rate_clock {
+ unsigned int id;
+ const char *name;
+ unsigned long fixed_rate;
+};
+
+#define FRATE(_id, cname, frate) \
+ { \
+ .id = _id, \
+ .name = cname, \
+ .fixed_rate = frate, \
+ }
+
+/**
+ * struct samsung_fixed_factor_clock - information about fixed-factor clock
+ * @id: platform specific id of the clock
+ * @name: name of this fixed-factor clock
+ * @parent_name: parent clock name
+ * @mult: fixed multiplication factor
+ * @div: fixed division factor
+ * @flags: optional fixed-factor clock flags
+ */
+struct samsung_fixed_factor_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long mult;
+ unsigned long div;
+ unsigned long flags;
+};
+
+#define FFACTOR(_id, cname, pname, m, d, f) \
+ { \
+ .id = _id, \
+ .name = cname, \
+ .parent_name = pname, \
+ .mult = m, \
+ .div = d, \
+ .flags = f, \
+ }
+
+/**
* struct samsung_mux_clock - information about mux clock
* @id: platform specific id of the clock
* @name: name of this mux clock
@@ -206,6 +257,8 @@ struct samsung_pll_clock {
}
enum samsung_clock_type {
+ S_CLK_FRATE,
+ S_CLK_FFACTOR,
S_CLK_MUX,
S_CLK_DIV,
S_CLK_GATE,
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 6c742553091..354035baf2d 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -26,3 +26,7 @@ obj-$(CONFIG_CLK_R8A779H0) += r8a779h0-cpg-mssr.o
obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o
obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
+
+# Temporary stub clock used for SCP compatibility.
+# This is going to be removed once SCP solidifies.
+obj-$(CONFIG_R8A78000) += compound-clock.o
diff --git a/drivers/clk/renesas/compound-clock.c b/drivers/clk/renesas/compound-clock.c
new file mode 100644
index 00000000000..499a2598833
--- /dev/null
+++ b/drivers/clk/renesas/compound-clock.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Marek Vasut <[email protected]>
+ */
+
+#define LOG_CATEGORY UCLASS_CLK
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <linux/clk-provider.h>
+#include <log.h>
+
+struct clk_compound_rate {
+ struct clk clk; /* This clock */
+ struct clk mdlc; /* MDLC parent module clock */
+ struct clk per; /* Peripheral parent clock */
+};
+
+static struct clk_compound_rate *to_clk_compound_rate(struct clk *clk)
+{
+ return (struct clk_compound_rate *)dev_get_plat(clk->dev);
+}
+
+static int clk_compound_rate_enable(struct clk *clk)
+{
+ struct clk_compound_rate *cc = to_clk_compound_rate(clk);
+
+ return clk_enable(&cc->mdlc);
+}
+
+static int clk_compound_rate_disable(struct clk *clk)
+{
+ struct clk_compound_rate *cc = to_clk_compound_rate(clk);
+
+ return clk_disable(&cc->mdlc);
+}
+
+static ulong clk_compound_rate_get_rate(struct clk *clk)
+{
+ struct clk_compound_rate *cc = to_clk_compound_rate(clk);
+
+ return clk_get_rate(&cc->per);
+}
+
+static ulong clk_compound_rate_set_rate(struct clk *clk, ulong rate)
+{
+ return 0; /* Set rate is not forwarded to SCP */
+}
+
+const struct clk_ops clk_compound_rate_ops = {
+ .enable = clk_compound_rate_enable,
+ .disable = clk_compound_rate_disable,
+ .get_rate = clk_compound_rate_get_rate,
+ .set_rate = clk_compound_rate_set_rate,
+};
+
+static int clk_compound_rate_of_to_plat(struct udevice *dev)
+{
+ struct clk_compound_rate *cc = (struct clk_compound_rate *)dev_get_plat(dev);
+ struct clk *clk = &cc->clk;
+ int ret;
+
+ clk->dev = dev;
+ clk->id = CLK_ID(dev, 0);
+ clk->enable_count = 0;
+
+ ret = clk_get_by_index(dev, 0, &cc->mdlc);
+ if (ret)
+ return ret;
+
+ ret = clk_get_by_index(dev, 1, &cc->per);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct udevice_id clk_compound_rate_match[] = {
+ { .compatible = "renesas,compound-clock", },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(renesas_compound_clock) = {
+ .name = "compound-clock",
+ .id = UCLASS_CLK,
+ .of_match = clk_compound_rate_match,
+ .of_to_plat = clk_compound_rate_of_to_plat,
+ .plat_auto = sizeof(struct clk_compound_rate),
+ .ops = &clk_compound_rate_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 142db9e47b8..18ca8ad4cac 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -154,6 +154,14 @@ config DWAPB_GPIO
help
Support for the Designware APB GPIO driver.
+config SPL_DWAPB_GPIO
+ bool "DWAPB GPIO driver in SPL"
+ depends on SPL_DM_GPIO
+ help
+ Support for the Designware APB GPIO driver in SPL.
+
+ If unsure, say N.
+
config AT91_GPIO
bool "AT91 PIO GPIO driver"
depends on ARCH_AT91
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 73c94329e36..910478c0c7a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,12 +4,12 @@
# Wolfgang Denk, DENX Software Engineering, [email protected].
ifndef CONFIG_XPL_BUILD
-obj-$(CONFIG_DWAPB_GPIO) += dwapb_gpio.o
obj-$(CONFIG_AXP_GPIO) += axp_gpio.o
obj-$(CONFIG_DM_74X164) += 74x164_gpio.o
endif
obj-$(CONFIG_$(PHASE_)DM_GPIO) += gpio-uclass.o
+obj-$(CONFIG_$(PHASE_)DWAPB_GPIO) += dwapb_gpio.o
obj-$(CONFIG_$(PHASE_)DM_PCA953X) += pca953x_gpio.o
obj-$(CONFIG_ADI_GPIO) += gpio-adi-adsp.o
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 53dbbe97b5a..c072f146514 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -319,7 +319,7 @@ static int gpio_exynos_bind(struct udevice *parent)
base = dev_read_addr_ptr(parent);
for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
node > 0;
- node = fdt_next_subnode(blob, node), bank++) {
+ node = fdt_next_subnode(blob, node)) {
struct exynos_gpio_plat *plat;
struct udevice *dev;
fdt_addr_t reg;
@@ -341,9 +341,8 @@ static int gpio_exynos_bind(struct udevice *parent)
if (reg != FDT_ADDR_T_NONE)
bank = (struct s5p_gpio_bank *)((ulong)base + reg);
- plat->bank = bank;
-
debug("dev at %p: %s\n", bank, plat->bank_name);
+ plat->bank = bank++;
}
return 0;
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index f9531c1627c..cfd2a3be3fd 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -66,6 +66,16 @@ config K3_SEC_PROXY
Select this driver if your platform has support for this hardware
block.
+config RCAR_MFIS_MBOX
+ bool "Renesas MFIS Multifunctional Interface mailbox driver"
+ depends on DM_MAILBOX && ARCH_RENESAS
+ help
+ This enables support for the Renesas MFIS mailbox module, which
+ provides an interface between the different CPU Cores, such as AP
+ System Core domain and the Realtime Core domain, SCP Core domain
+ and AP System Core domain or Realtime Core domain and AP System
+ Core domain or Realtime Core domain.
+
config ZYNQMP_IPI
bool "Xilinx ZynqMP IPI controller support"
depends on DM_MAILBOX && (ARCH_ZYNQMP || ARCH_VERSAL || ARCH_VERSAL_NET || ARCH_VERSAL2)
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index b54fbdfff15..b3a36691497 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -12,4 +12,5 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o
obj-$(CONFIG_TEGRA_HSP) += tegra-hsp.o
obj-$(CONFIG_K3_SEC_PROXY) += k3-sec-proxy.o
+obj-$(CONFIG_RCAR_MFIS_MBOX) += renesas-mfis.o
obj-$(CONFIG_ZYNQMP_IPI) += zynqmp-ipi.o
diff --git a/drivers/mailbox/renesas-mfis.c b/drivers/mailbox/renesas-mfis.c
new file mode 100644
index 00000000000..1e9e8285974
--- /dev/null
+++ b/drivers/mailbox/renesas-mfis.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2025, Renesas Electronics Corporation.
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/delay.h>
+#include <mailbox-uclass.h>
+
+#define COM 0x0
+#define IIR BIT(0)
+
+struct mfis_priv {
+ void __iomem *tx_base;
+};
+
+static int mfis_send(struct mbox_chan *chan, const void *data)
+{
+ struct mfis_priv *mfis = dev_get_priv(chan->dev);
+
+ writel(IIR, mfis->tx_base + COM);
+
+ /* Give the remote side some time. */
+ mdelay(1);
+
+ writel(0, mfis->tx_base + COM);
+
+ return 0;
+}
+
+struct mbox_ops mfis_mbox_ops = {
+ .send = mfis_send,
+};
+
+static int mfis_mbox_probe(struct udevice *dev)
+{
+ struct mfis_priv *mbox = dev_get_priv(dev);
+
+ mbox->tx_base = dev_read_addr_index_ptr(dev, 0);
+ if (!mbox->tx_base)
+ return -ENODEV;
+
+ return 0;
+}
+
+static const struct udevice_id mfis_mbox_of_match[] = {
+ { .compatible = "renesas,mfis-mbox", },
+ {},
+};
+
+U_BOOT_DRIVER(renesas_mfis) = {
+ .name = "renesas-mfis",
+ .id = UCLASS_MAILBOX,
+ .of_match = mfis_mbox_of_match,
+ .probe = mfis_mbox_probe,
+ .priv_auto = sizeof(struct mfis_priv),
+ .ops = &mfis_mbox_ops,
+};
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index db4e0129c2e..6219284df3e 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -58,17 +58,24 @@ static int socfpga_dwmci_clksel(struct dwmci_host *host)
u32 sdmmc_mask = ((priv->smplsel & 0x7) << SYSMGR_SDMMC_SMPLSEL_SHIFT) |
((priv->drvsel & 0x7) << SYSMGR_SDMMC_DRVSEL_SHIFT);
- ret = clk_get_by_name(priv->dev, "ciu", &priv->mmc_clk_ciu);
- if (ret) {
- debug("%s: Failed to get SDMMC clock from dts\n", __func__);
- return ret;
- }
-
- /* Disable SDMMC clock. */
- ret = clk_disable(&priv->mmc_clk_ciu);
- if (ret) {
- printf("%s: Failed to disable SDMMC clock\n", __func__);
- return ret;
+ if (!IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX) &&
+ !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7M)) {
+ /* Disable SDMMC clock. */
+ clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_PERPLL_EN,
+ CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK);
+ } else {
+ ret = clk_get_by_name(priv->dev, "ciu", &priv->mmc_clk_ciu);
+ if (ret) {
+ debug("%s: Failed to get SDMMC clock from dts\n", __func__);
+ return ret;
+ }
+
+ /* Disable SDMMC clock. */
+ ret = clk_disable(&priv->mmc_clk_ciu);
+ if (ret) {
+ printf("%s: Failed to disable SDMMC clock\n", __func__);
+ return ret;
+ }
}
debug("%s: drvsel %d smplsel %d\n", __func__,
@@ -88,11 +95,18 @@ static int socfpga_dwmci_clksel(struct dwmci_host *host)
readl(socfpga_get_sysmgr_addr() + SYSMGR_SDMMC));
#endif
- /* Enable SDMMC clock */
- ret = clk_enable(&priv->mmc_clk_ciu);
- if (ret) {
- printf("%s: Failed to enable SDMMC clock\n", __func__);
- return ret;
+ if (!IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX) &&
+ !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7M)) {
+ /* Enable SDMMC clock */
+ setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_PERPLL_EN,
+ CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK);
+ } else {
+ /* Enable SDMMC clock */
+ ret = clk_enable(&priv->mmc_clk_ciu);
+ if (ret) {
+ printf("%s: Failed to enable SDMMC clock\n", __func__);
+ return ret;
+ }
}
return 0;
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 1bd33a200c1..5e4d1c0a937 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -212,6 +212,7 @@ config NAND_CADENCE
config NAND_DENALI
bool
select SYS_NAND_SELF_INIT
+ select SYS_NAND_ONFI_DETECTION if TARGET_SOCFPGA_SOC64
imply CMD_NAND
config NAND_DENALI_DT
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
index e500a0fe3f8..1acaa5d0e07 100644
--- a/drivers/mtd/nand/raw/atmel/pmecc.c
+++ b/drivers/mtd/nand/raw/atmel/pmecc.c
@@ -142,6 +142,7 @@ struct atmel_pmecc_caps {
int nstrengths;
int el_offset;
bool correct_erased_chunks;
+ bool clk_ctrl;
};
struct atmel_pmecc_user_conf_cache {
@@ -819,8 +820,7 @@ EXPORT_SYMBOL_GPL(atmel_pmecc_wait_rdy);
static struct atmel_pmecc *
atmel_pmecc_create(struct udevice *dev,
const struct atmel_pmecc_caps *caps,
- int pmecc_res_idx, int errloc_res_idx,
- int timing_res_idx)
+ int pmecc_res_idx, int errloc_res_idx)
{
struct atmel_pmecc *pmecc;
struct resource res;
@@ -838,7 +838,9 @@ atmel_pmecc_create(struct udevice *dev,
ofnode_read_resource(dev->node_, 1, &res);
pmecc->regs.errloc = (void *)res.start;
- pmecc->regs.timing = 0;
+ /* pmecc data setup time */
+ if (caps->clk_ctrl)
+ writel(PMECC_CLK_133MHZ, pmecc->regs.base + ATMEL_PMECC_CLK);
/* Disable all interrupts before registering the PMECC handler. */
writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR);
@@ -884,6 +886,7 @@ static struct atmel_pmecc_caps at91sam9g45_caps = {
.strengths = atmel_pmecc_strengths,
.nstrengths = 5,
.el_offset = 0x8c,
+ .clk_ctrl = true,
};
static struct atmel_pmecc_caps sama5d4_caps = {
@@ -946,7 +949,7 @@ static int atmel_pmecc_probe(struct udevice *dev)
return -EINVAL;
}
- pmecc = atmel_pmecc_create(dev, caps, 0, 1, 2);
+ pmecc = atmel_pmecc_create(dev, caps, 0, 1);
if (IS_ERR(pmecc))
return PTR_ERR(pmecc);
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h
index 43f96b2f168..88b0d18040e 100644
--- a/drivers/mtd/nand/raw/atmel/pmecc.h
+++ b/drivers/mtd/nand/raw/atmel/pmecc.h
@@ -65,7 +65,6 @@ struct atmel_pmecc {
struct {
void __iomem *base;
void __iomem *errloc;
- void __iomem *timing;
} regs;
/* Mutex used for pmecc enable/disable */
diff --git a/drivers/net/dwc_eth_xgmac.c b/drivers/net/dwc_eth_xgmac.c
index d29d871ea8c..458b87af7a2 100644
--- a/drivers/net/dwc_eth_xgmac.c
+++ b/drivers/net/dwc_eth_xgmac.c
@@ -140,9 +140,34 @@ static int xgmac_mdio_wait_idle(struct xgmac_priv *xgmac)
XGMAC_TIMEOUT_100MS, true);
}
+static u32 xgmac_set_clause(struct xgmac_priv *xgmac, int mdio_addr, int mdio_devad,
+ int mdio_reg, bool is_c45)
+{
+ u32 hw_addr;
+ u32 val;
+
+ if (is_c45) {
+ val = readl(&xgmac->mac_regs->mdio_clause_22_port);
+ val &= ~BIT(mdio_addr);
+ writel(val, &xgmac->mac_regs->mdio_clause_22_port);
+ hw_addr = (mdio_addr << XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) |
+ (mdio_reg & XGMAC_MAC_MDIO_REG_ADDR_C45P_MASK);
+ hw_addr |= mdio_devad << XGMAC_MAC_MDIO_ADDRESS_DA_SHIFT;
+ } else {
+ /* Set clause 22 format */
+ val = BIT(mdio_addr);
+ writel(val, &xgmac->mac_regs->mdio_clause_22_port);
+ hw_addr = (mdio_addr << XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) |
+ (mdio_reg & XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK);
+ }
+
+ return hw_addr;
+}
+
static int xgmac_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg)
{
+ bool is_c45 = (mdio_devad != MDIO_DEVAD_NONE);
struct xgmac_priv *xgmac = bus->priv;
u32 val;
u32 hw_addr;
@@ -159,19 +184,16 @@ static int xgmac_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
return ret;
}
- /* Set clause 22 format */
- val = BIT(mdio_addr);
- writel(val, &xgmac->mac_regs->mdio_clause_22_port);
-
- hw_addr = (mdio_addr << XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) |
- (mdio_reg & XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK);
+ hw_addr = xgmac_set_clause(xgmac, mdio_addr, mdio_devad, mdio_reg, is_c45);
val = xgmac->config->config_mac_mdio <<
XGMAC_MAC_MDIO_ADDRESS_CR_SHIFT;
- val |= XGMAC_MAC_MDIO_ADDRESS_SADDR |
- XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_READ |
- XGMAC_MAC_MDIO_ADDRESS_SBUSY;
+ if (!is_c45)
+ val |= XGMAC_MAC_MDIO_ADDRESS_SADDR;
+
+ val |= XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_READ |
+ XGMAC_MAC_MDIO_ADDRESS_SBUSY;
ret = xgmac_mdio_wait_idle(xgmac);
if (ret) {
@@ -203,6 +225,7 @@ static int xgmac_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
static int xgmac_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg, u16 mdio_val)
{
+ bool is_c45 = (mdio_devad != MDIO_DEVAD_NONE);
struct xgmac_priv *xgmac = bus->priv;
u32 val;
u32 hw_addr;
@@ -219,21 +242,18 @@ static int xgmac_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
return ret;
}
- /* Set clause 22 format */
- val = BIT(mdio_addr);
- writel(val, &xgmac->mac_regs->mdio_clause_22_port);
-
- hw_addr = (mdio_addr << XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) |
- (mdio_reg & XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK);
-
- hw_addr |= (mdio_reg >> XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) <<
- XGMAC_MAC_MDIO_ADDRESS_DA_SHIFT;
+ hw_addr = xgmac_set_clause(xgmac, mdio_addr, mdio_devad, mdio_reg, is_c45);
val = (xgmac->config->config_mac_mdio <<
XGMAC_MAC_MDIO_ADDRESS_CR_SHIFT);
- val |= XGMAC_MAC_MDIO_ADDRESS_SADDR |
- mdio_val | XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_WRITE |
+ if (!is_c45) {
+ hw_addr |= (mdio_reg >> XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) <<
+ XGMAC_MAC_MDIO_ADDRESS_DA_SHIFT;
+ val |= XGMAC_MAC_MDIO_ADDRESS_SADDR;
+ }
+
+ val |= mdio_val | XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_WRITE |
XGMAC_MAC_MDIO_ADDRESS_SBUSY;
ret = xgmac_mdio_wait_idle(xgmac);
diff --git a/drivers/net/dwc_eth_xgmac.h b/drivers/net/dwc_eth_xgmac.h
index 259f815f3f2..90c2e22997c 100644
--- a/drivers/net/dwc_eth_xgmac.h
+++ b/drivers/net/dwc_eth_xgmac.h
@@ -109,6 +109,7 @@ struct xgmac_mac_regs {
#define XGMAC_MAC_MDIO_ADDRESS_SBUSY BIT(22)
#define XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK GENMASK(4, 0)
#define XGMAC_MAC_MDIO_DATA_GD_MASK GENMASK(15, 0)
+#define XGMAC_MAC_MDIO_REG_ADDR_C45P_MASK GENMASK(15, 0)
/* MTL Registers */
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 1c02e3efedc..2d93ce0c966 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -176,11 +176,11 @@ static int bcm54210e_config(struct phy_device *phydev)
{
int ret;
- ret = bcm54xx_config_clock_delay(phydev);
+ ret = bcm5461_config(phydev);
if (ret < 0)
return ret;
- ret = bcm5461_config(phydev);
+ ret = bcm54xx_config_clock_delay(phydev);
if (ret < 0)
return ret;
diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
index b6fb5adae1f..c60fbf26a03 100644
--- a/drivers/net/phy/dp83869.c
+++ b/drivers/net/phy/dp83869.c
@@ -5,6 +5,7 @@
*/
#include <phy.h>
+#include <linux/bitfield.h>
#include <linux/compat.h>
#include <malloc.h>
@@ -64,7 +65,7 @@
#define DP83869_RGMII_RX_CLK_DELAY_EN BIT(0)
/* STRAP_STS1 bits */
-#define DP83869_STRAP_OP_MODE_MASK GENMASK(2, 0)
+#define DP83869_STRAP_OP_MODE_MASK GENMASK(11, 9)
#define DP83869_STRAP_STS1_RESERVED BIT(11)
#define DP83869_STRAP_MIRROR_ENABLED BIT(12)
@@ -168,7 +169,7 @@ static int dp83869_set_strapped_mode(struct phy_device *phydev)
if (val < 0)
return val;
- dp83869->mode = val & DP83869_STRAP_OP_MODE_MASK;
+ dp83869->mode = FIELD_GET(DP83869_STRAP_OP_MODE_MASK, val);
return 0;
}
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index 7a88f76fd09..84a3e44ecbc 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -819,6 +819,10 @@ static int am65_cpsw_nuss_bind(struct udevice *dev)
ofnode_for_each_subnode(node, ports_np) {
const char *node_name;
+ /* Ignore disabled ports */
+ if (!ofnode_is_enabled(node))
+ continue;
+
node_name = ofnode_get_name(node);
ret = device_bind_driver_to_node(dev, "am65_cpsw_nuss_port", node_name, node,
diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
index cf9350c151e..4ecc8bac645 100644
--- a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
+++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
@@ -21,6 +21,8 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/gpio.h>
+#include <dt-bindings/pinctrl/bcm2835.h>
+#include <linux/delay.h>
struct bcm283x_pinctrl_priv {
u32 *base_reg;
@@ -54,7 +56,66 @@ static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio)
}
/*
- * bcm283x_pinctrl_set_state: configure pin functions.
+ * bcm2835_gpio_set_pull: Set GPIO pull-up/down resistor for BCM2835
+ * @dev: the pinctrl device
+ * @gpio: the GPIO pin number
+ * @pull: pull setting (BCM2835_PUD_OFF, BCM2835_PUD_DOWN, BCM2835_PUD_UP)
+ */
+static void bcm2835_gpio_set_pull(struct udevice *dev, unsigned int gpio, int pull)
+{
+ struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
+ u32 bank = BCM2835_GPPUDCLK0 + BCM2835_GPIO_COMMON_BANK(gpio);
+ u32 bit = BCM2835_GPIO_COMMON_SHIFT(gpio);
+
+ /* Set required control signal */
+ writel(pull & 0x3, &priv->base_reg[BCM2835_GPPUD]);
+ udelay(1);
+
+ /* Clock the control signal into the GPIO pads */
+ writel(1 << bit, &priv->base_reg[bank]);
+ udelay(1);
+
+ /* Remove the control signal and clock */
+ writel(0, &priv->base_reg[BCM2835_GPPUD]);
+ writel(0, &priv->base_reg[bank]);
+}
+
+/*
+ * bcm2711_gpio_set_pull: Set GPIO pull-up/down resistor for BCM2711
+ * @dev: the pinctrl device
+ * @gpio: the GPIO pin number
+ * @pull: pull setting (BCM2835_PUD_OFF, BCM2835_PUD_DOWN, BCM2835_PUD_UP)
+ */
+static void bcm2711_gpio_set_pull(struct udevice *dev, unsigned int gpio, int pull)
+{
+ struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
+ u32 reg_offset;
+ u32 bit_shift;
+ u32 pull_bits;
+
+ /* Findout which GPIO_PUP_PDN_CNTRL register to use */
+ reg_offset = BCM2711_GPPUD_CNTRL_REG0 + BCM2711_PUD_REG_OFFSET(gpio);
+
+ /* Findout the bit position */
+ bit_shift = BCM2711_PUD_REG_SHIFT(gpio);
+
+ /* Update the 2-bit field for this GPIO */
+ pull_bits = pull & BCM2711_PUD_2711_MASK;
+ clrsetbits_le32(&priv->base_reg[reg_offset],
+ BCM2711_PUD_2711_MASK << bit_shift,
+ pull_bits << bit_shift);
+}
+
+static void bcm283x_gpio_set_pull(struct udevice *dev, unsigned int gpio, int pull)
+{
+ if (device_is_compatible(dev, "brcm,bcm2835-gpio"))
+ bcm2835_gpio_set_pull(dev, gpio, pull);
+ else
+ bcm2711_gpio_set_pull(dev, gpio, pull);
+}
+
+/*
+ * bcm283x_pinctrl_set_state: configure pin functions and pull states.
* @dev: the pinctrl device to be configured.
* @config: the state to be configured.
* @return: 0 in success
@@ -62,8 +123,10 @@ static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio)
int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
{
u32 pin_arr[MAX_PINS_PER_BANK];
+ u32 pull_arr[MAX_PINS_PER_BANK];
int function;
- int i, len, pin_count = 0;
+ int i, len, pin_count = 0, pull_len = 0, pull_count = 0;
+ int pull_value;
if (!dev_read_prop(config, "brcm,pins", &len) || !len ||
len & 0x3 || dev_read_u32_array(config, "brcm,pins", pin_arr,
@@ -82,8 +145,44 @@ int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
return -EINVAL;
}
- for (i = 0; i < pin_count; i++)
+ /* Check if brcm,pull property exists */
+ if (dev_read_prop(config, "brcm,pull", &pull_len) && pull_len > 0) {
+ if (pull_len & 0x3) {
+ debug("Invalid pull array length for pinconfig %s (%d)\n",
+ config->name, pull_len);
+ return -EINVAL;
+ }
+
+ pull_count = pull_len / sizeof(u32);
+
+ if (pull_count != 1 && pull_count != pin_count) {
+ debug("Pull array count (%d) must be 1 or match pin count (%d) for pinconfig %s\n",
+ pull_count, pin_count, config->name);
+ return -EINVAL;
+ }
+
+ if (dev_read_u32_array(config, "brcm,pull", pull_arr, pull_count)) {
+ debug("Failed reading pull array for pinconfig %s\n", config->name);
+ return -EINVAL;
+ }
+
+ /* Validate pull values */
+ for (i = 0; i < pull_count; i++) {
+ if (pull_arr[i] > 2) {
+ debug("Invalid pull value %d for pin %d in pinconfig %s\n",
+ pull_arr[i], pin_arr[i], config->name);
+ return -EINVAL;
+ }
+ }
+ }
+
+ for (i = 0; i < pin_count; i++) {
bcm2835_gpio_set_func_id(dev, pin_arr[i], function);
+ if (pull_count > 0) {
+ pull_value = (pull_count == 1) ? pull_arr[0] : pull_arr[i];
+ bcm283x_gpio_set_pull(dev, pin_arr[i], pull_value);
+ }
+ }
return 0;
}
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c
index b37282fa9d6..4c06b41c7aa 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.c
@@ -7,6 +7,7 @@
#include <log.h>
#include <dm.h>
+#include <dm/lists.h>
#include <errno.h>
#include <asm/io.h>
#include "pinctrl-exynos.h"
@@ -178,3 +179,13 @@ int exynos_pinctrl_probe(struct udevice *dev)
return 0;
}
+
+int exynos_pinctrl_bind(struct udevice *dev)
+{
+ /*
+ * Attempt to bind the Exynos GPIO driver. The GPIOs and
+ * pin controller descriptors are found in the same OF node.
+ */
+ return device_bind_driver_to_node(dev, "gpio_exynos", "gpio-banks",
+ dev_ofnode(dev), NULL);
+}
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.h b/drivers/pinctrl/exynos/pinctrl-exynos.h
index da666777581..73cc2ce4117 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.h
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.h
@@ -97,5 +97,6 @@ void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data *conf,
int exynos_pinctrl_set_state(struct udevice *dev,
struct udevice *config);
int exynos_pinctrl_probe(struct udevice *dev);
+int exynos_pinctrl_bind(struct udevice *dev);
#endif /* __PINCTRL_EXYNOS_H_ */
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos7420.c b/drivers/pinctrl/exynos/pinctrl-exynos7420.c
index 8fdf60715a5..b1d983fd383 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos7420.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos7420.c
@@ -114,4 +114,5 @@ U_BOOT_DRIVER(pinctrl_exynos7420) = {
.priv_auto = sizeof(struct exynos_pinctrl_priv),
.ops = &exynos7420_pinctrl_ops,
.probe = exynos_pinctrl_probe,
+ .bind = exynos_pinctrl_bind,
};
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos78x0.c b/drivers/pinctrl/exynos/pinctrl-exynos78x0.c
index 61b98443daf..04e72173802 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos78x0.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos78x0.c
@@ -45,6 +45,11 @@ static const struct samsung_pin_bank_data exynos78x0_pin_banks2[] = {
EXYNOS_PIN_BANK(4, 0x040, "gpz2"),
};
+/* pin banks of exynos78x0 pin-controller 3 (ESE) */
+static const struct samsung_pin_bank_data exynos78x0_pin_banks3[] = {
+ EXYNOS_PIN_BANK(5, 0x000, "gpc7"),
+};
+
/* pin banks of exynos78x0 pin-controller 4 (FSYS) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks4[] = {
EXYNOS_PIN_BANK(3, 0x000, "gpr0"),
@@ -54,6 +59,11 @@ static const struct samsung_pin_bank_data exynos78x0_pin_banks4[] = {
EXYNOS_PIN_BANK(6, 0x080, "gpr4"),
};
+/* pin banks of exynos78x0 pin-controller 5 (NFC) */
+static const struct samsung_pin_bank_data exynos78x0_pin_banks5[] = {
+ EXYNOS_PIN_BANK(4, 0x000, "gpc2"),
+};
+
/* pin banks of exynos78x0 pin-controller 6 (TOP) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks6[] = {
EXYNOS_PIN_BANK(4, 0x000, "gpb0"),
@@ -77,6 +87,11 @@ static const struct samsung_pin_bank_data exynos78x0_pin_banks6[] = {
EXYNOS_PIN_BANK(5, 0x240, "gpf4"),
};
+/* pin banks of exynos7870 pin-controller 7 (TOUCH) */
+static const struct samsung_pin_bank_data exynos78x0_pin_banks7[] = {
+ EXYNOS_PIN_BANK(3, 0x000, "gpc3"),
+};
+
const struct samsung_pin_ctrl exynos78x0_pin_ctrl[] = {
{
/* pin-controller instance 0 Alive data */
@@ -102,9 +117,53 @@ const struct samsung_pin_ctrl exynos78x0_pin_ctrl[] = {
{/* list terminator */}
};
+/*
+ * In Exynos7870, the CCORE block is named as MIF instead. As the
+ * pinctrl blocks are sorted in lexical order of their names, the
+ * order isn't the same as Exynos7880.
+ */
+const struct samsung_pin_ctrl exynos7870_pin_ctrl[] = {
+ {
+ /* pin-controller instance 0 Alive data */
+ .pin_banks = exynos78x0_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks0),
+ }, {
+ /* pin-controller instance 1 DISPAUD data */
+ .pin_banks = exynos78x0_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks2),
+ }, {
+ /* pin-controller instance 2 ESE data */
+ .pin_banks = exynos78x0_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks3),
+ }, {
+ /* pin-controller instance 3 FSYS data */
+ .pin_banks = exynos78x0_pin_banks4,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks4),
+ }, {
+ /* pin-controller instance 4 MIF data */
+ .pin_banks = exynos78x0_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks1),
+ }, {
+ /* pin-controller instance 5 NFC data */
+ .pin_banks = exynos78x0_pin_banks5,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks5),
+ }, {
+ /* pin-controller instance 6 TOP data */
+ .pin_banks = exynos78x0_pin_banks6,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks6),
+ }, {
+ /* pin-controller instance 7 TOUCH data */
+ .pin_banks = exynos78x0_pin_banks7,
+ .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks7),
+ },
+ {/* list terminator */}
+};
+
static const struct udevice_id exynos78x0_pinctrl_ids[] = {
{ .compatible = "samsung,exynos78x0-pinctrl",
.data = (ulong)exynos78x0_pin_ctrl },
+ { .compatible = "samsung,exynos7870-pinctrl",
+ .data = (ulong)exynos7870_pin_ctrl },
{ }
};
@@ -115,4 +174,5 @@ U_BOOT_DRIVER(pinctrl_exynos78x0) = {
.priv_auto = sizeof(struct exynos_pinctrl_priv),
.ops = &exynos78x0_pinctrl_ops,
.probe = exynos_pinctrl_probe,
+ .bind = exynos_pinctrl_bind,
};
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos850.c b/drivers/pinctrl/exynos/pinctrl-exynos850.c
index 3ec2636e0d8..5bf09ae20ee 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos850.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos850.c
@@ -122,4 +122,5 @@ U_BOOT_DRIVER(pinctrl_exynos850) = {
.priv_auto = sizeof(struct exynos_pinctrl_priv),
.ops = &exynos850_pinctrl_ops,
.probe = exynos_pinctrl_probe,
+ .bind = exynos_pinctrl_bind,
};
diff --git a/drivers/power/domain/ti-power-domain.c b/drivers/power/domain/ti-power-domain.c
index c3519307340..a554e659392 100644
--- a/drivers/power/domain/ti-power-domain.c
+++ b/drivers/power/domain/ti-power-domain.c
@@ -227,7 +227,7 @@ static int ti_pd_get(struct ti_pd *pd)
pd_write(pdctl, pd, PSC_PDCTL);
- return 0;
+ return ti_pd_wait(pd);
}
static int ti_pd_put(struct ti_pd *pd)
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 734780a124a..d46a88610ab 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -258,6 +258,7 @@ static const struct dm_serial_ops s5p_serial_ops = {
static const struct udevice_id s5p_serial_ids[] = {
{ .compatible = "samsung,exynos4210-uart", .data = PORT_S5P },
{ .compatible = "samsung,exynos850-uart", .data = PORT_S5P },
+ { .compatible = "samsung,exynos8895-uart", .data = PORT_S5P },
{ .compatible = "apple,s5l-uart", .data = PORT_S5L },
{ }
};
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 233ad4a908f..0f533bcdae5 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -86,6 +86,9 @@ static int exynos_pmu_probe(struct udevice *dev)
static const struct udevice_id exynos_pmu_ids[] = {
{
+ .compatible = "samsung,exynos7-pmu",
+ },
+ {
.compatible = "samsung,exynos850-pmu",
.data = (ulong)&exynos850_pmu_data
},
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index c88918606d2..2afb15fff1e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -180,6 +180,21 @@ config CADENCE_OSPI_VERSAL
This option is used to enable Versal OSPI DMA operations which
are used for ospi flash read using cadence qspi controller.
+config CADENCE_XSPI
+ bool "Cadence XSPI driver (Experimental feature)"
+ help
+ Important: this feature is experimental so far and tested only
+ on simulated environment.
+
+ Enable the Cadence eXpanded Serial Periheral Interface (xSPI) flash
+ driver. This driver can be used to access the SPI NOR flash on
+ platforms embedding this Cadence IP core up to 8 bit wide bus.
+ xSPI flash controller IP offers three work mode, Auto Command (ACMD)
+ work mode, Software Triggered Instruction Generator (STIG) work mode
+ and Direct work mode. This flash controller able to coomunicate
+ with Flash Memory Devices supporting JESD216 and JESD251 stadards
+ by using the Auto Command work mode.
+
config CF_SPI
bool "ColdFire SPI driver"
depends on M68K
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5129d649f84..d5d1e543588 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -8,6 +8,7 @@ ifdef CONFIG_$(PHASE_)DM_SPI
obj-y += spi-uclass.o
obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
obj-$(CONFIG_CADENCE_OSPI_VERSAL) += cadence_ospi_versal.o
+obj-$(CONFIG_CADENCE_XSPI) += cadence_xspi.o
obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
obj-$(CONFIG_SOFT_SPI) += soft_spi.o
obj-$(CONFIG_SPI_ASPEED_SMC) += spi-aspeed-smc.o
diff --git a/drivers/spi/cadence_xspi.c b/drivers/spi/cadence_xspi.c
new file mode 100644
index 00000000000..717f226b709
--- /dev/null
+++ b/drivers/spi/cadence_xspi.c
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025
+ * Altera Corporation <www.altera.com>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <malloc.h>
+#include <reset.h>
+#include <spi.h>
+#include <spi-mem.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/sizes.h>
+#include <linux/time.h>
+#include "cadence_xspi.h"
+
+static int cdns_xspi_wait_for_controller_idle(struct cdns_xspi_plat *cdns_xspi)
+{
+ u32 ctrl_stat;
+
+ return readl_relaxed_poll_timeout(cdns_xspi->iobase +
+ CDNS_XSPI_CTRL_STATUS_REG,
+ ctrl_stat,
+ !(ctrl_stat &
+ CDNS_XSPI_CTRL_BUSY),
+ 1000);
+}
+
+static int cdns_xspi_wait_for_sdma_complete(struct cdns_xspi_plat *cdns_xspi)
+{
+ u32 irq_status;
+ int ret = 0;
+
+ ret = readl_relaxed_poll_timeout(cdns_xspi->iobase +
+ CDNS_XSPI_INTR_STATUS_REG,
+ irq_status,
+ (irq_status &
+ CDNS_XSPI_SDMA_TRIGGER),
+ 1000);
+
+ if (!ret) {
+ /*
+ * SDMA return an interrupt, need to clear
+ * the interrupt after read, wrtting 1 to clear the bit.
+ */
+ setbits_le32(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG,
+ CDNS_XSPI_SDMA_TRIGGER);
+ }
+
+ /* Check if SDMA ERROR happened */
+ if (irq_status & CDNS_XSPI_SDMA_ERROR) {
+ /*
+ * Need to clear the SDMA_ERROR interrupt
+ * after read, wrtting 1 to clear the bit.
+ */
+ dev_err(cdns_xspi->dev,
+ "Slave DMA transaction error\n");
+
+ cdns_xspi->sdma_error = true;
+ setbits_le32(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG,
+ CDNS_XSPI_SDMA_ERROR);
+
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static int cdns_xspi_wait_for_cmd_complete(struct cdns_xspi_plat *cdns_xspi)
+{
+ u32 irq_status;
+ int ret = 0;
+
+ ret = readl_relaxed_poll_timeout(cdns_xspi->iobase +
+ CDNS_XSPI_INTR_STATUS_REG,
+ irq_status,
+ (irq_status &
+ CDNS_XSPI_STIG_DONE),
+ 100000);
+
+ irq_status = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
+
+ if (!ret) {
+ /*
+ * Need to clear the interrupt after read,
+ * wrtting 1 to the clear the bit.
+ */
+ writel(irq_status & CDNS_XSPI_STIG_DONE,
+ cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
+ }
+
+ return ret;
+}
+
+static void cdns_xspi_trigger_command(struct cdns_xspi_plat *cdns_xspi,
+ u32 cmd_regs[6])
+{
+ writel(cmd_regs[5], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_5);
+ writel(cmd_regs[4], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_4);
+ writel(cmd_regs[3], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_3);
+ writel(cmd_regs[2], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_2);
+ writel(cmd_regs[1], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_1);
+ writel(cmd_regs[0], cdns_xspi->iobase + CDNS_XSPI_CMD_REG_0);
+}
+
+static int cdns_xspi_check_command_status(struct cdns_xspi_plat *cdns_xspi)
+{
+ int ret = 0;
+ u32 cmd_status = readl(cdns_xspi->iobase + CDNS_XSPI_CMD_STATUS_REG);
+
+ /* Check if the command has completed */
+ if (cmd_status & CDNS_XSPI_CMD_STATUS_COMPLETED) {
+ /*Check for failure status and report each type of error */
+ if ((cmd_status & CDNS_XSPI_CMD_STATUS_FAILED) != 0) {
+ if (cmd_status & CDNS_XSPI_CMD_STATUS_DQS_ERROR)
+ dev_err(cdns_xspi->dev,
+ "Incorrect DQS pulses detected\n");
+
+ if (cmd_status & CDNS_XSPI_CMD_STATUS_CRC_ERROR)
+ dev_err(cdns_xspi->dev,
+ "CRC error received\n");
+
+ if (cmd_status & CDNS_XSPI_CMD_STATUS_BUS_ERROR)
+ dev_err(cdns_xspi->dev,
+ "Error resp on system DMA interface\n");
+
+ if (cmd_status & CDNS_XSPI_CMD_STATUS_INV_SEQ_ERROR)
+ dev_err(cdns_xspi->dev,
+ "Invalid command sequence detected\n");
+
+ ret = -EPROTO;
+ }
+ } else {
+ /* Command did not complete at all -- fatal error */
+ dev_err(cdns_xspi->dev, "Fatal err - command not completed\n");
+ ret = -EPROTO;
+ }
+
+ return ret;
+}
+
+static void cdns_xspi_set_interrupts(struct cdns_xspi_plat *cdns_xspi,
+ bool enabled)
+{
+ u32 intr_enable;
+
+ intr_enable = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
+ if (enabled)
+ intr_enable |= CDNS_XSPI_INTR_MASK;
+ else
+ intr_enable &= ~CDNS_XSPI_INTR_MASK;
+ writel(intr_enable, cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
+}
+
+static int cdns_xspi_controller_init(struct cdns_xspi_plat *cdns_xspi)
+{
+ u32 ctrl_ver;
+ u32 ctrl_features;
+ u16 hw_magic_num;
+
+ ctrl_ver = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_VERSION_REG);
+ hw_magic_num = FIELD_GET(CDNS_XSPI_MAGIC_NUM, ctrl_ver);
+ if (hw_magic_num != CDNS_XSPI_MAGIC_NUM_VALUE) {
+ dev_err(cdns_xspi->dev,
+ "Incorrect XSPI magic number: %x, expected: %x\n",
+ hw_magic_num, CDNS_XSPI_MAGIC_NUM_VALUE);
+ return -ENXIO;
+ }
+
+ ctrl_features = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_FEATURES_REG);
+ cdns_xspi->hw_num_banks = FIELD_GET(CDNS_XSPI_NUM_BANKS, ctrl_features);
+ cdns_xspi->set_interrupts_handler(cdns_xspi, false);
+
+ return 0;
+}
+
+static void cdns_xspi_sdma_handle(struct cdns_xspi_plat *cdns_xspi)
+{
+ u32 sdma_size, sdma_trd_info;
+ u8 sdma_dir;
+ u8 *in_buf;
+ u8 *out_buf;
+
+ sdma_size = readl(cdns_xspi->iobase + CDNS_XSPI_SDMA_SIZE_REG);
+ sdma_trd_info = readl(cdns_xspi->iobase + CDNS_XSPI_SDMA_TRD_INFO_REG);
+ sdma_dir = FIELD_GET(CDNS_XSPI_SDMA_DIR, sdma_trd_info);
+
+ in_buf = (u8 *)cdns_xspi->in_buffer;
+ out_buf = (u8 *)cdns_xspi->out_buffer;
+
+ switch (sdma_dir) {
+ case CDNS_XSPI_SDMA_DIR_READ:
+ if (in_buf)
+ memcpy_fromio(in_buf, cdns_xspi->sdmabase, sdma_size);
+ break;
+
+ case CDNS_XSPI_SDMA_DIR_WRITE:
+ if (in_buf)
+ memcpy_toio(cdns_xspi->sdmabase, out_buf, sdma_size);
+ break;
+
+ default:
+ /* Handle unexpected direction */
+ dev_warn(cdns_xspi->dev,
+ "Unknown SDMA direction: %u\n", sdma_dir);
+ break;
+ }
+}
+
+static int cdns_xspi_send_stig_command(struct cdns_xspi_plat *cdns_xspi,
+ const struct spi_mem_op *op,
+ bool data_phase)
+{
+ u32 cmd_regs[6] = {0};
+ int ret = 0;
+ int dummybytes = op->dummy.nbytes;
+
+ ret = cdns_xspi_wait_for_controller_idle(cdns_xspi);
+ if (ret < 0)
+ return ret;
+
+ writel(FIELD_PREP(CDNS_XSPI_CTRL_WORK_MODE, CDNS_XSPI_WORK_MODE_STIG),
+ cdns_xspi->iobase + CDNS_XSPI_CTRL_CONFIG_REG);
+
+ cdns_xspi->set_interrupts_handler(cdns_xspi, true);
+ cdns_xspi->sdma_error = false;
+
+ cmd_regs[1] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_1(op, data_phase);
+ cmd_regs[2] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_2(op);
+ if (dummybytes != 0) {
+ cmd_regs[3] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, 1);
+ dummybytes--;
+ } else {
+ cmd_regs[3] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, 0);
+ }
+ cmd_regs[4] = CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_4(op,
+ cdns_xspi->cur_cs);
+
+ cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
+
+ if (data_phase) {
+ cmd_regs[0] = CDNS_XSPI_STIG_DONE_FLAG;
+ cmd_regs[1] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_1;
+ cmd_regs[2] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_2(op);
+ cmd_regs[3] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op, dummybytes);
+ cmd_regs[4] = CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op,
+ cdns_xspi->cur_cs);
+
+ cdns_xspi->in_buffer = op->data.buf.in;
+ cdns_xspi->out_buffer = op->data.buf.out;
+
+ cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
+
+ cdns_xspi_wait_for_sdma_complete(cdns_xspi);
+
+ if (cdns_xspi->sdma_error) {
+ cdns_xspi->set_interrupts_handler(cdns_xspi, false);
+ return -EIO;
+ }
+ cdns_xspi_sdma_handle(cdns_xspi);
+ }
+
+ cdns_xspi_wait_for_cmd_complete(cdns_xspi);
+ ret = cdns_xspi_check_command_status(cdns_xspi);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int cdns_xspi_mem_op(struct udevice *bus,
+ const struct spi_mem_op *op,
+ unsigned int cs)
+{
+ struct cdns_xspi_plat *plat = dev_get_plat(bus);
+ enum spi_mem_data_dir dir = op->data.dir;
+
+ if (plat->cur_cs != cs)
+ plat->cur_cs = cs;
+
+ return cdns_xspi_send_stig_command(plat, op,
+ (dir != SPI_MEM_NO_DATA));
+}
+
+static int cdns_xspi_mem_op_execute(struct spi_slave *spi,
+ const struct spi_mem_op *op)
+{
+ struct udevice *bus = spi->dev->parent;
+ unsigned int cs = 0;
+ int ret = 0;
+
+ cs = spi_chip_select(spi->dev);
+
+ if (cs < 0) {
+ /*
+ * spi_chip_select will return error number when not
+ * able to get chip select.
+ */
+ pr_err("%s: Unable to get chip select, ret=%d",
+ spi->dev->name, cs);
+ return cs;
+ }
+
+ ret = cdns_xspi_mem_op(bus, op, cs);
+
+ return ret;
+}
+
+static int cdns_xspi_adjust_mem_op_size(struct spi_slave *spi,
+ struct spi_mem_op *op)
+{
+ struct udevice *bus = spi->dev->parent;
+ struct cdns_xspi_plat *plat = dev_get_plat(bus);
+
+ op->data.nbytes = clamp_val(op->data.nbytes, 0, plat->sdmasize);
+
+ return 0;
+}
+
+static const struct spi_controller_mem_ops cadence_xspi_mem_ops = {
+ .exec_op = cdns_xspi_mem_op_execute,
+ .adjust_op_size = cdns_xspi_adjust_mem_op_size,
+};
+
+static void cdns_xspi_print_phy_config(struct cdns_xspi_plat *cdns_xspi)
+{
+ struct device *dev = cdns_xspi->dev;
+
+ dev_info(dev, "PHY configuration\n");
+ dev_info(dev, " * xspi_dll_phy_ctrl: %08x\n",
+ readl(cdns_xspi->iobase + CDNS_XSPI_DLL_PHY_CTRL));
+ dev_info(dev, " * phy_dq_timing: %08x\n",
+ readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DQ_TIMING));
+ dev_info(dev, " * phy_dqs_timing: %08x\n",
+ readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DQS_TIMING));
+ dev_info(dev, " * phy_gate_loopback_ctrl: %08x\n",
+ readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_GATE_LPBCK_CTRL));
+ dev_info(dev, " * phy_dll_slave_ctrl: %08x\n",
+ readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DLL_SLAVE_CTRL));
+}
+
+static int cdns_xspi_probe(struct udevice *bus)
+{
+ struct cdns_xspi_plat *cdns_xspi = dev_get_plat(bus);
+ struct resource res;
+ int ret = 0;
+
+ cdns_xspi->sdma_handler = &cdns_xspi_sdma_handle;
+ cdns_xspi->set_interrupts_handler = &cdns_xspi_set_interrupts;
+ cdns_xspi->cur_cs = 0;
+
+ ret = dev_read_resource_byname(bus, "io", &res);
+ if (ret)
+ return ret;
+
+ cdns_xspi->iobase = devm_ioremap(bus, res.start, resource_size(&res));
+
+ if (IS_ERR(cdns_xspi->iobase)) {
+ dev_err(bus, "Failed to remap controller base address\n");
+ return PTR_ERR(cdns_xspi->iobase);
+ }
+
+ ret = dev_read_resource_byname(bus, "sdma", &res);
+ if (ret)
+ return ret;
+
+ cdns_xspi->sdmabase = devm_ioremap(bus, res.start, resource_size(&res));
+
+ if (IS_ERR(cdns_xspi->sdmabase)) {
+ dev_err(bus, "Failed to remap SDMA address\n");
+ return PTR_ERR(cdns_xspi->sdmabase);
+ }
+ cdns_xspi->sdmasize = resource_size(&res);
+
+ ret = dev_read_resource_byname(bus, "aux", &res);
+ if (ret)
+ return ret;
+
+ cdns_xspi->auxbase = devm_ioremap(bus, res.start, resource_size(&res));
+
+ if (IS_ERR(cdns_xspi->auxbase)) {
+ dev_err(bus, "Failed to remap AUX address\n");
+ return PTR_ERR(cdns_xspi->auxbase);
+ }
+
+ cdns_xspi_print_phy_config(cdns_xspi);
+
+ ret = cdns_xspi_controller_init(cdns_xspi);
+
+ if (ret) {
+ dev_err(bus, "Failed to initialize controller\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cdns_xspi_remove(struct udevice *dev)
+{
+ struct cdns_xspi_plat *plat = dev_get_plat(dev);
+ int ret = 0;
+
+ if (plat->resets)
+ ret = reset_release_bulk(plat->resets);
+
+ return ret;
+}
+
+static int cadence_spi_set_speed(struct udevice *bus, uint hz)
+{
+ return 0;
+}
+
+static int cadence_spi_set_mode(struct udevice *bus, uint mode)
+{
+ return 0;
+}
+
+static const struct dm_spi_ops cdns_xspi_ops = {
+ .set_speed = cadence_spi_set_speed,
+ .set_mode = cadence_spi_set_mode,
+ .mem_ops = &cadence_xspi_mem_ops,
+};
+
+static const struct udevice_id cdns_xspi_of_match[] = {
+ {
+ .compatible = "cdns,xspi-nor",
+ },
+ {/* end of table */}
+};
+
+U_BOOT_DRIVER(cadence_xspi) = {
+ .name = CDNS_XSPI_NAME,
+ .id = UCLASS_SPI,
+ .of_match = cdns_xspi_of_match,
+ .ops = &cdns_xspi_ops,
+ .probe = cdns_xspi_probe,
+ .remove = cdns_xspi_remove,
+ .flags = DM_FLAG_OS_PREPARE,
+};
diff --git a/drivers/spi/cadence_xspi.h b/drivers/spi/cadence_xspi.h
new file mode 100644
index 00000000000..e408d27303f
--- /dev/null
+++ b/drivers/spi/cadence_xspi.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2025
+ * Altera Corporation <www.altera.com>
+ */
+
+#ifndef __CADENCE_XSPI_H__
+#define __CADENCE_XSPI_H__
+
+#include <spi-mem.h>
+#include <reset.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/bitfield.h>
+#include <linux/log2.h>
+
+#define CDNS_XSPI_MAGIC_NUM_VALUE 0x6522
+#define CDNS_XSPI_MAX_BANKS 8
+#define CDNS_XSPI_NAME "cadence_xspi"
+
+/*
+ * Note: below are additional auxiliary registers to
+ * configure XSPI controller pin-strap settings
+ */
+
+/* PHY DQ timing register */
+#define CDNS_XSPI_CCP_PHY_DQ_TIMING 0x0000
+
+/* PHY DQS timing register */
+#define CDNS_XSPI_CCP_PHY_DQS_TIMING 0x0004
+
+/* PHY gate loopback control register */
+#define CDNS_XSPI_CCP_PHY_GATE_LPBCK_CTRL 0x0008
+
+/* PHY DLL slave control register */
+#define CDNS_XSPI_CCP_PHY_DLL_SLAVE_CTRL 0x0010
+
+/* DLL PHY control register */
+#define CDNS_XSPI_DLL_PHY_CTRL 0x1034
+
+/* Command registers */
+#define CDNS_XSPI_CMD_REG_0 0x0000
+#define CDNS_XSPI_CMD_REG_1 0x0004
+#define CDNS_XSPI_CMD_REG_2 0x0008
+#define CDNS_XSPI_CMD_REG_3 0x000C
+#define CDNS_XSPI_CMD_REG_4 0x0010
+#define CDNS_XSPI_CMD_REG_5 0x0014
+
+/* Command status registers */
+#define CDNS_XSPI_CMD_STATUS_REG 0x0044
+
+/* Controller status register */
+#define CDNS_XSPI_CTRL_STATUS_REG 0x0100
+#define CDNS_XSPI_INIT_COMPLETED BIT(16)
+#define CDNS_XSPI_INIT_LEGACY BIT(9)
+#define CDNS_XSPI_INIT_FAIL BIT(8)
+#define CDNS_XSPI_CTRL_BUSY BIT(7)
+
+/* Controller interrupt status register */
+#define CDNS_XSPI_INTR_STATUS_REG 0x0110
+#define CDNS_XSPI_STIG_DONE BIT(23)
+#define CDNS_XSPI_SDMA_ERROR BIT(22)
+#define CDNS_XSPI_SDMA_TRIGGER BIT(21)
+#define CDNS_XSPI_CMD_IGNRD_EN BIT(20)
+#define CDNS_XSPI_DDMA_TERR_EN BIT(18)
+#define CDNS_XSPI_CDMA_TREE_EN BIT(17)
+#define CDNS_XSPI_CTRL_IDLE_EN BIT(16)
+
+#define CDNS_XSPI_TRD_COMP_INTR_STATUS 0x0120
+#define CDNS_XSPI_TRD_ERR_INTR_STATUS 0x0130
+#define CDNS_XSPI_TRD_ERR_INTR_EN 0x0134
+
+/* Controller interrupt enable register */
+#define CDNS_XSPI_INTR_ENABLE_REG 0x0114
+#define CDNS_XSPI_INTR_EN BIT(31)
+#define CDNS_XSPI_STIG_DONE_EN BIT(23)
+#define CDNS_XSPI_SDMA_ERROR_EN BIT(22)
+#define CDNS_XSPI_SDMA_TRIGGER_EN BIT(21)
+
+#define CDNS_XSPI_INTR_MASK (CDNS_XSPI_INTR_EN | \
+ CDNS_XSPI_STIG_DONE_EN | \
+ CDNS_XSPI_SDMA_ERROR_EN | \
+ CDNS_XSPI_SDMA_TRIGGER_EN)
+
+/* Controller config register */
+#define CDNS_XSPI_CTRL_CONFIG_REG 0x0230
+#define CDNS_XSPI_CTRL_WORK_MODE GENMASK(6, 5)
+
+#define CDNS_XSPI_WORK_MODE_DIRECT 0
+#define CDNS_XSPI_WORK_MODE_STIG 1
+#define CDNS_XSPI_WORK_MODE_ACMD 3
+
+/* SDMA trigger transaction registers */
+#define CDNS_XSPI_SDMA_SIZE_REG 0x0240
+#define CDNS_XSPI_SDMA_TRD_INFO_REG 0x0244
+#define CDNS_XSPI_SDMA_DIR BIT(8)
+
+/* Controller features register */
+#define CDNS_XSPI_CTRL_FEATURES_REG 0x0F04
+#define CDNS_XSPI_NUM_BANKS GENMASK(25, 24)
+#define CDNS_XSPI_DMA_DATA_WIDTH BIT(21)
+#define CDNS_XSPI_NUM_THREADS GENMASK(3, 0)
+
+/* Controller version register */
+#define CDNS_XSPI_CTRL_VERSION_REG 0x0F00
+#define CDNS_XSPI_MAGIC_NUM GENMASK(31, 16)
+#define CDNS_XSPI_CTRL_REV GENMASK(7, 0)
+
+/* STIG Profile 1.0 instruction fields (split into registers) */
+#define CDNS_XSPI_CMD_INSTR_TYPE GENMASK(6, 0)
+#define CDNS_XSPI_CMD_P1_R1_ADDR0 GENMASK(31, 24)
+#define CDNS_XSPI_CMD_P1_R2_ADDR1 GENMASK(7, 0)
+#define CDNS_XSPI_CMD_P1_R2_ADDR2 GENMASK(15, 8)
+#define CDNS_XSPI_CMD_P1_R2_ADDR3 GENMASK(23, 16)
+#define CDNS_XSPI_CMD_P1_R2_ADDR4 GENMASK(31, 24)
+#define CDNS_XSPI_CMD_P1_R3_ADDR5 GENMASK(7, 0)
+#define CDNS_XSPI_CMD_P1_R3_CMD GENMASK(23, 16)
+#define CDNS_XSPI_CMD_P1_R3_NUM_ADDR_BYTES GENMASK(30, 28)
+#define CDNS_XSPI_CMD_P1_R4_ADDR_IOS GENMASK(1, 0)
+#define CDNS_XSPI_CMD_P1_R4_CMD_IOS GENMASK(9, 8)
+#define CDNS_XSPI_CMD_P1_R4_BANK GENMASK(14, 12)
+
+/* STIG data sequence instruction fields (split into registers) */
+#define CDNS_XSPI_CMD_DSEQ_R2_DCNT_L GENMASK(31, 16)
+#define CDNS_XSPI_CMD_DSEQ_R3_DCNT_H GENMASK(15, 0)
+#define CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY GENMASK(25, 20)
+#define CDNS_XSPI_CMD_DSEQ_R4_BANK GENMASK(14, 12)
+#define CDNS_XSPI_CMD_DSEQ_R4_DATA_IOS GENMASK(9, 8)
+#define CDNS_XSPI_CMD_DSEQ_R4_DIR BIT(4)
+
+/* STIG command status fields */
+#define CDNS_XSPI_CMD_STATUS_COMPLETED BIT(15)
+#define CDNS_XSPI_CMD_STATUS_FAILED BIT(14)
+#define CDNS_XSPI_CMD_STATUS_DQS_ERROR BIT(3)
+#define CDNS_XSPI_CMD_STATUS_CRC_ERROR BIT(2)
+#define CDNS_XSPI_CMD_STATUS_BUS_ERROR BIT(1)
+#define CDNS_XSPI_CMD_STATUS_INV_SEQ_ERROR BIT(0)
+
+#define CDNS_XSPI_STIG_DONE_FLAG BIT(0)
+#define CDNS_XSPI_TRD_STATUS 0x0104
+
+#define MODE_NO_OF_BYTES GENMASK(25, 24)
+#define MODEBYTES_COUNT 1
+
+/* Helper macros for filling command registers */
+#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_1(op, data_phase) ( \
+ FIELD_PREP(CDNS_XSPI_CMD_INSTR_TYPE, (data_phase) ? \
+ CDNS_XSPI_STIG_INSTR_TYPE_1 : CDNS_XSPI_STIG_INSTR_TYPE_0) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R1_ADDR0, (op)->addr.val & 0xff))
+
+#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_2(op) ( \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR1, ((op)->addr.val >> 8) & 0xFF) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR2, ((op)->addr.val >> 16) & 0xFF) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR3, ((op)->addr.val >> 24) & 0xFF) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R2_ADDR4, ((op)->addr.val >> 32) & 0xFF))
+
+#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, modebytes) ( \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R3_ADDR5, ((op)->addr.val >> 40) & 0xFF) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R3_CMD, (op)->cmd.opcode) | \
+ FIELD_PREP(MODE_NO_OF_BYTES, modebytes) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R3_NUM_ADDR_BYTES, (op)->addr.nbytes))
+
+#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_4(op, chipsel) ( \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R4_ADDR_IOS, ilog2((op)->addr.buswidth)) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R4_CMD_IOS, ilog2((op)->cmd.buswidth)) | \
+ FIELD_PREP(CDNS_XSPI_CMD_P1_R4_BANK, chipsel))
+
+#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_1 \
+ FIELD_PREP(CDNS_XSPI_CMD_INSTR_TYPE, CDNS_XSPI_STIG_INSTR_TYPE_DATA_SEQ)
+
+#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_2(op) \
+ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R2_DCNT_L, (op)->data.nbytes & 0xFFFF)
+
+#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op, dummybytes) ( \
+ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_DCNT_H, \
+ ((op)->data.nbytes >> 16) & 0xffff) | \
+ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, \
+ (op)->dummy.buswidth != 0 ? \
+ (((dummybytes) * 8) / (op)->dummy.buswidth) : \
+ 0))
+
+#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel) ( \
+ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_BANK, chipsel) | \
+ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_DATA_IOS, \
+ ilog2((op)->data.buswidth)) | \
+ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_DIR, \
+ ((op)->data.dir == SPI_MEM_DATA_IN) ? \
+ CDNS_XSPI_STIG_CMD_DIR_READ : CDNS_XSPI_STIG_CMD_DIR_WRITE))
+
+enum cdns_xspi_stig_instr_type {
+ CDNS_XSPI_STIG_INSTR_TYPE_0,
+ CDNS_XSPI_STIG_INSTR_TYPE_1,
+ CDNS_XSPI_STIG_INSTR_TYPE_DATA_SEQ = 127,
+};
+
+enum cdns_xspi_sdma_dir {
+ CDNS_XSPI_SDMA_DIR_READ,
+ CDNS_XSPI_SDMA_DIR_WRITE,
+};
+
+enum cdns_xspi_stig_cmd_dir {
+ CDNS_XSPI_STIG_CMD_DIR_READ,
+ CDNS_XSPI_STIG_CMD_DIR_WRITE,
+};
+
+struct cdns_xspi_plat {
+ struct device *dev;
+ struct reset_ctl_bulk *resets;
+
+ void __iomem *iobase;
+ void __iomem *auxbase;
+ void __iomem *sdmabase;
+
+ int cur_cs;
+ unsigned int sdmasize;
+ bool sdma_error;
+
+ void *in_buffer;
+ const void *out_buffer;
+
+ u8 hw_num_banks;
+
+ void (*sdma_handler)(struct cdns_xspi_plat *cdns_xspi);
+ void (*set_interrupts_handler)(struct cdns_xspi_plat *cdns_xspi, bool enabled);
+};
+
+#endif /* __CADENCE_XSPI_H__ */
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 427b62e934b..99f381db9f9 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -271,6 +271,7 @@ config USB_EHCI_MSM
config USB_EHCI_PCI
bool "Support for PCI-based EHCI USB controller"
+ depends on PCI
default y if X86
help
Enables support for the PCI-based EHCI controller.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 3ee1f67190f..d59804580f1 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1249,7 +1249,7 @@ static int xhci_lowlevel_init(struct xhci_ctrl *ctrl)
reg = xhci_readl(&hccr->cr_hcsparams1);
ctrl->hub_desc.bNbrPorts = HCS_MAX_PORTS(reg);
- printf("Register %x NbrPorts %d\n", reg, ctrl->hub_desc.bNbrPorts);
+ debug("Register %x NbrPorts %d\n", reg, ctrl->hub_desc.bNbrPorts);
/* Port Indicators */
reg = xhci_readl(&hccr->cr_hccparams);