diff options
| author | Tom Rini <[email protected]> | 2025-12-08 13:17:27 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-12-08 13:17:27 -0600 |
| commit | 59202e5ae76ef3acb34c4236e43248f1cd3fc642 (patch) | |
| tree | 30004ced6a059b2c25afb0aca8b049908c2212c3 /drivers | |
| parent | 8e12d6ccb3cfa84dd275a1b852b2a235de0162b0 (diff) | |
| parent | 0e0a198a68be71148f5ec27ef86796174f91436f (diff) | |
Merge tag 'v2026.01-rc4' into next
Prepare v2026.01-rc4
Diffstat (limited to 'drivers')
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); |
