2021-10-08 15:45:21

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH v3 0/5] clk: samsung: Introduce Exynos850 SoC clock driver

This patch series provides the implementation for Exynos850 clock
driver, its documentation and corresponding changes for Samsung clock
infrastructure (adds new PLL types used in Exynos850 SoC, following
TRM).

I tried to follow already established design for Samsung clock drivers
(getting most insights from Exynos5433 clock driver), and integrate the
driver into existing infrastructure. The whole driver was implemented
from scratch, using mostly TRM and downstream kernel for clock
dependencies/hierarchy info.

For now only basic clocks are implemented, including next blocks:
- CMU_TOP
- CMU_PERI
- CMU_CORE
- CMU_HSI
- CMU_DPU

Some CMUs are still not implemented, but that can be added in future,
when the need arises. The driver also lacks CLKOUT support, PM ops and
automatic clocks control (using Q-Channel protocol). All that can be
added independently later.

Implemented clock tree was tested via UART and MMC drivers, and using
DebugFS clk support (e.g. using 'clk_summary' file). In order to keep
all clocks running I added 'clk_ignore_unused' kernel param in my local
tree, and defined CLOCK_ALLOW_WRITE_DEBUGFS in clk.c for actually
testing the clocks via DebugFS.

Changes in v3:
- Changed the licence for bindings header to GPL+BSD
- Added R-b tag by Krzysztof Kozlowski to patches 4/5 and 5/5

Changes in v2:
- Added CMU_DPU implementation
- Moved bus clock enablement to clk-exynos850.c
- See also "v2 changes" list in each particular patch

Sam Protsenko (5):
clk: samsung: clk-pll: Implement pll0822x PLL type
clk: samsung: clk-pll: Implement pll0831x PLL type
dt-bindings: clock: Add bindings definitions for Exynos850 CMU
dt-bindings: clock: Document Exynos850 CMU bindings
clk: samsung: Introduce Exynos850 clock driver

.../clock/samsung,exynos850-clock.yaml | 185 ++++
drivers/clk/samsung/Makefile | 1 +
drivers/clk/samsung/clk-exynos850.c | 835 ++++++++++++++++++
drivers/clk/samsung/clk-pll.c | 196 ++++
drivers/clk/samsung/clk-pll.h | 2 +
include/dt-bindings/clock/exynos850.h | 141 +++
6 files changed, 1360 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
create mode 100644 drivers/clk/samsung/clk-exynos850.c
create mode 100644 include/dt-bindings/clock/exynos850.h

--
2.30.2


2021-10-08 15:45:26

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH v3 5/5] clk: samsung: Introduce Exynos850 clock driver

This is the initial implementation adding only basic clocks like UART,
MMC, I2C and corresponding parent clocks. Design is influenced by
Exynos5433 clock driver.

Bus clock is enabled by default (in probe function) for all CMUs except
CMU_TOP, the reasoning is as follows. By default if bus clock has no
users its "enable count" value is 0. It might be actually running if
it's already enabled in bootloader, but then in some cases it can be
disabled by mistake. For example, such case was observed when
dw_mci_probe() enabled the bus clock, then failed to do something and
disabled that bus clock on error path. After that, even the attempt to
read the 'clk_summary' file in DebugFS freezed forever, as CMU bus clock
ended up being disabled and it wasn't possible to access CMU registers
anymore.

To avoid such cases, CMU driver must increment the ref count for that
bus clock by running clk_prepare_enable(). There is already existing
'.clk_name' field in struct samsung_cmu_info, exactly for that reason.
It was added in commit 523d3de41f02 ("clk: samsung: exynos5433: Add
support for runtime PM"), with next mentioning in commit message:

> Also for each CMU there is one special parent clock, which has to be
> enabled all the time when any access to CMU registers is being done.

But that clock is actually only enabled in Exynos5433 clock driver right
now. So the same code is added to exynos850_cmu_probe() function,
As was described above, it might be helpful not only for PM reasons, but
also to prevent possible erroneous clock gating on error paths.

Another way to workaround that issue would be to use CLOCK_IS_CRITICAL
flag for corresponding gate clocks. But that might be not very good
design decision, as we might still want to disable that bus clock, e.g.
on PM suspend.

Signed-off-by: Sam Protsenko <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
---
Changes in v3:
- Added R-b tag by Krzysztof Kozlowski

Changes in v2:
- Used of_iomap() for the whole CMU range instead of ioremap() in
exynos850_init_clocks()
- Used readl/writel functions in exynos850_init_clocks() for consistency
with other drivers
- Added all clock ids
- Added CMU_DPU
- Implemented platform_driver for all Power Domain capable CMUs
- Moved bus clock enablement code here to probe function
- Used clk_get() instead of __clk_lookup()

drivers/clk/samsung/Makefile | 1 +
drivers/clk/samsung/clk-exynos850.c | 835 ++++++++++++++++++++++++++++
2 files changed, 836 insertions(+)
create mode 100644 drivers/clk/samsung/clk-exynos850.c

diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 028b2e27a37e..c46cf11e4d0b 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
+obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
new file mode 100644
index 000000000000..2294989e244c
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -0,0 +1,835 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Linaro Ltd.
+ * Author: Sam Protsenko <[email protected]>
+ *
+ * Common Clock Framework support for Exynos850 SoC.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/exynos850.h>
+
+#include "clk.h"
+
+/* Gate register bits */
+#define GATE_MANUAL BIT(20)
+#define GATE_ENABLE_HWACG BIT(28)
+
+/* Gate register offsets range */
+#define GATE_OFF_START 0x2000
+#define GATE_OFF_END 0x2fff
+
+/**
+ * exynos850_init_clocks - Set clocks initial configuration
+ * @np: CMU device tree node with "reg" property (CMU addr)
+ * @reg_offs: Register offsets array for clocks to init
+ * @reg_offs_len: Number of register offsets in reg_offs array
+ *
+ * Set manual control mode for all gate clocks.
+ */
+static void __init exynos850_init_clocks(struct device_node *np,
+ const unsigned long *reg_offs, size_t reg_offs_len)
+{
+ void __iomem *reg_base;
+ size_t i;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ for (i = 0; i < reg_offs_len; ++i) {
+ void __iomem *reg = reg_base + reg_offs[i];
+ u32 val;
+
+ /* Modify only gate clock registers */
+ if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END)
+ continue;
+
+ val = readl(reg);
+ val |= GATE_MANUAL;
+ val &= ~GATE_ENABLE_HWACG;
+ writel(val, reg);
+ }
+
+ iounmap(reg_base);
+}
+
+/* ---- CMU_TOP ------------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_TOP (0x120e0000) */
+#define PLL_LOCKTIME_PLL_MMC 0x0000
+#define PLL_LOCKTIME_PLL_SHARED0 0x0004
+#define PLL_LOCKTIME_PLL_SHARED1 0x0008
+#define PLL_CON0_PLL_MMC 0x0100
+#define PLL_CON3_PLL_MMC 0x010c
+#define PLL_CON0_PLL_SHARED0 0x0140
+#define PLL_CON3_PLL_SHARED0 0x014c
+#define PLL_CON0_PLL_SHARED1 0x0180
+#define PLL_CON3_PLL_SHARED1 0x018c
+#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1014
+#define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018
+#define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c
+#define CLK_CON_MUX_MUX_CLKCMU_CORE_SSS 0x1020
+#define CLK_CON_MUX_MUX_CLKCMU_DPU 0x1034
+#define CLK_CON_MUX_MUX_CLKCMU_HSI_BUS 0x103c
+#define CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD 0x1040
+#define CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD 0x1044
+#define CLK_CON_MUX_MUX_CLKCMU_PERI_BUS 0x1070
+#define CLK_CON_MUX_MUX_CLKCMU_PERI_IP 0x1074
+#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART 0x1078
+#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x1820
+#define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1824
+#define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828
+#define CLK_CON_DIV_CLKCMU_CORE_SSS 0x182c
+#define CLK_CON_DIV_CLKCMU_DPU 0x1840
+#define CLK_CON_DIV_CLKCMU_HSI_BUS 0x1848
+#define CLK_CON_DIV_CLKCMU_HSI_MMC_CARD 0x184c
+#define CLK_CON_DIV_CLKCMU_HSI_USB20DRD 0x1850
+#define CLK_CON_DIV_CLKCMU_PERI_BUS 0x187c
+#define CLK_CON_DIV_CLKCMU_PERI_IP 0x1880
+#define CLK_CON_DIV_CLKCMU_PERI_UART 0x1884
+#define CLK_CON_DIV_PLL_SHARED0_DIV2 0x188c
+#define CLK_CON_DIV_PLL_SHARED0_DIV3 0x1890
+#define CLK_CON_DIV_PLL_SHARED0_DIV4 0x1894
+#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x1898
+#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x189c
+#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18a0
+#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x201c
+#define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020
+#define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024
+#define CLK_CON_GAT_GATE_CLKCMU_CORE_SSS 0x2028
+#define CLK_CON_GAT_GATE_CLKCMU_DPU 0x203c
+#define CLK_CON_GAT_GATE_CLKCMU_HSI_BUS 0x2044
+#define CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD 0x2048
+#define CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD 0x204c
+#define CLK_CON_GAT_GATE_CLKCMU_PERI_BUS 0x2080
+#define CLK_CON_GAT_GATE_CLKCMU_PERI_IP 0x2084
+#define CLK_CON_GAT_GATE_CLKCMU_PERI_UART 0x2088
+
+static const unsigned long top_clk_regs[] __initconst = {
+ PLL_LOCKTIME_PLL_MMC,
+ PLL_LOCKTIME_PLL_SHARED0,
+ PLL_LOCKTIME_PLL_SHARED1,
+ PLL_CON0_PLL_MMC,
+ PLL_CON3_PLL_MMC,
+ PLL_CON0_PLL_SHARED0,
+ PLL_CON3_PLL_SHARED0,
+ PLL_CON0_PLL_SHARED1,
+ PLL_CON3_PLL_SHARED1,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_CCI,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_SSS,
+ CLK_CON_MUX_MUX_CLKCMU_DPU,
+ CLK_CON_MUX_MUX_CLKCMU_HSI_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD,
+ CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD,
+ CLK_CON_MUX_MUX_CLKCMU_PERI_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_PERI_IP,
+ CLK_CON_MUX_MUX_CLKCMU_PERI_UART,
+ CLK_CON_DIV_CLKCMU_CORE_BUS,
+ CLK_CON_DIV_CLKCMU_CORE_CCI,
+ CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD,
+ CLK_CON_DIV_CLKCMU_CORE_SSS,
+ CLK_CON_DIV_CLKCMU_DPU,
+ CLK_CON_DIV_CLKCMU_HSI_BUS,
+ CLK_CON_DIV_CLKCMU_HSI_MMC_CARD,
+ CLK_CON_DIV_CLKCMU_HSI_USB20DRD,
+ CLK_CON_DIV_CLKCMU_PERI_BUS,
+ CLK_CON_DIV_CLKCMU_PERI_IP,
+ CLK_CON_DIV_CLKCMU_PERI_UART,
+ CLK_CON_DIV_PLL_SHARED0_DIV2,
+ CLK_CON_DIV_PLL_SHARED0_DIV3,
+ CLK_CON_DIV_PLL_SHARED0_DIV4,
+ CLK_CON_DIV_PLL_SHARED1_DIV2,
+ CLK_CON_DIV_PLL_SHARED1_DIV3,
+ CLK_CON_DIV_PLL_SHARED1_DIV4,
+ CLK_CON_GAT_GATE_CLKCMU_CORE_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_CORE_CCI,
+ CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD,
+ CLK_CON_GAT_GATE_CLKCMU_CORE_SSS,
+ CLK_CON_GAT_GATE_CLKCMU_DPU,
+ CLK_CON_GAT_GATE_CLKCMU_HSI_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD,
+ CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD,
+ CLK_CON_GAT_GATE_CLKCMU_PERI_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_PERI_IP,
+ CLK_CON_GAT_GATE_CLKCMU_PERI_UART,
+};
+
+/*
+ * Do not provide PLL tables to core PLLs, as MANUAL_PLL_CTRL bit is not set
+ * for those PLLs by default, so set_rate operation would fail.
+ */
+static const struct samsung_pll_clock top_pll_clks[] __initconst = {
+ /* CMU_TOP_PURECLKCOMP */
+ PLL(pll_0822x, CLK_FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0,
+ NULL),
+ PLL(pll_0822x, CLK_FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1,
+ NULL),
+ PLL(pll_0831x, CLK_FOUT_MMC_PLL, "fout_mmc_pll", "oscclk",
+ PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, NULL),
+};
+
+/* List of parent clocks for Muxes in CMU_TOP */
+PNAME(mout_shared0_pll_p) = { "oscclk", "fout_shared0_pll" };
+PNAME(mout_shared1_pll_p) = { "oscclk", "fout_shared1_pll" };
+PNAME(mout_mmc_pll_p) = { "oscclk", "fout_mmc_pll" };
+/* List of parent clocks for Muxes in CMU_TOP: for CMU_CORE */
+PNAME(mout_core_bus_p) = { "dout_shared1_div2", "dout_shared0_div3",
+ "dout_shared1_div3", "dout_shared0_div4" };
+PNAME(mout_core_cci_p) = { "dout_shared0_div2", "dout_shared1_div2",
+ "dout_shared0_div3", "dout_shared1_div3" };
+PNAME(mout_core_mmc_embd_p) = { "oscclk", "dout_shared0_div2",
+ "dout_shared1_div2", "dout_shared0_div3",
+ "dout_shared1_div3", "mout_mmc_pll",
+ "oscclk", "oscclk" };
+PNAME(mout_core_sss_p) = { "dout_shared0_div3", "dout_shared1_div3",
+ "dout_shared0_div4", "dout_shared1_div4" };
+/* List of parent clocks for Muxes in CMU_TOP: for CMU_HSI */
+PNAME(mout_hsi_bus_p) = { "dout_shared0_div2", "dout_shared1_div2" };
+PNAME(mout_hsi_mmc_card_p) = { "oscclk", "dout_shared0_div2",
+ "dout_shared1_div2", "dout_shared0_div3",
+ "dout_shared1_div3", "mout_mmc_pll",
+ "oscclk", "oscclk" };
+PNAME(mout_hsi_usb20drd_p) = { "oscclk", "dout_shared0_div4",
+ "dout_shared1_div4", "oscclk" };
+/* List of parent clocks for Muxes in CMU_TOP: for CMU_PERI */
+PNAME(mout_peri_bus_p) = { "dout_shared0_div4", "dout_shared1_div4" };
+PNAME(mout_peri_uart_p) = { "oscclk", "dout_shared0_div4",
+ "dout_shared1_div4", "oscclk" };
+PNAME(mout_peri_ip_p) = { "oscclk", "dout_shared0_div4",
+ "dout_shared1_div4", "oscclk" };
+
+/* List of parent clocks for Muxes in CMU_TOP: for CMU_DPU */
+PNAME(mout_dpu_p) = { "dout_shared0_div3", "dout_shared1_div3",
+ "dout_shared0_div4", "dout_shared1_div4" };
+
+static const struct samsung_mux_clock top_mux_clks[] __initconst = {
+ /* CMU_TOP_PURECLKCOMP */
+ MUX(CLK_MOUT_SHARED0_PLL, "mout_shared0_pll", mout_shared0_pll_p,
+ PLL_CON0_PLL_SHARED0, 4, 1),
+ MUX(CLK_MOUT_SHARED1_PLL, "mout_shared1_pll", mout_shared1_pll_p,
+ PLL_CON0_PLL_SHARED1, 4, 1),
+ MUX(CLK_MOUT_MMC_PLL, "mout_mmc_pll", mout_mmc_pll_p,
+ PLL_CON0_PLL_MMC, 4, 1),
+
+ /* CORE */
+ MUX(CLK_MOUT_CORE_BUS, "mout_core_bus", mout_core_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 2),
+ MUX(CLK_MOUT_CORE_CCI, "mout_core_cci", mout_core_cci_p,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, 0, 2),
+ MUX(CLK_MOUT_CORE_MMC_EMBD, "mout_core_mmc_embd", mout_core_mmc_embd_p,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD, 0, 3),
+ MUX(CLK_MOUT_CORE_SSS, "mout_core_sss", mout_core_sss_p,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, 0, 2),
+
+ /* DPU */
+ MUX(CLK_MOUT_DPU, "mout_dpu", mout_dpu_p,
+ CLK_CON_MUX_MUX_CLKCMU_DPU, 0, 2),
+
+ /* HSI */
+ MUX(CLK_MOUT_HSI_BUS, "mout_hsi_bus", mout_hsi_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, 0, 1),
+ MUX(CLK_MOUT_HSI_MMC_CARD, "mout_hsi_mmc_card", mout_hsi_mmc_card_p,
+ CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD, 0, 3),
+ MUX(CLK_MOUT_HSI_USB20DRD, "mout_hsi_usb20drd", mout_hsi_usb20drd_p,
+ CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD, 0, 2),
+
+ /* PERI */
+ MUX(CLK_MOUT_PERI_BUS, "mout_peri_bus", mout_peri_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_PERI_BUS, 0, 1),
+ MUX(CLK_MOUT_PERI_UART, "mout_peri_uart", mout_peri_uart_p,
+ CLK_CON_MUX_MUX_CLKCMU_PERI_UART, 0, 2),
+ MUX(CLK_MOUT_PERI_IP, "mout_peri_ip", mout_peri_ip_p,
+ CLK_CON_MUX_MUX_CLKCMU_PERI_IP, 0, 2),
+};
+
+static const struct samsung_div_clock top_div_clks[] __initconst = {
+ /* CMU_TOP_PURECLKCOMP */
+ DIV(CLK_DOUT_SHARED0_DIV3, "dout_shared0_div3", "mout_shared0_pll",
+ CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2),
+ DIV(CLK_DOUT_SHARED0_DIV2, "dout_shared0_div2", "mout_shared0_pll",
+ CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1),
+ DIV(CLK_DOUT_SHARED1_DIV3, "dout_shared1_div3", "mout_shared1_pll",
+ CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2),
+ DIV(CLK_DOUT_SHARED1_DIV2, "dout_shared1_div2", "mout_shared1_pll",
+ CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1),
+ DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "dout_shared0_div2",
+ CLK_CON_DIV_PLL_SHARED0_DIV4, 0, 1),
+ DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2",
+ CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1),
+
+ /* CORE */
+ DIV(CLK_DOUT_CORE_BUS, "dout_core_bus", "gout_core_bus",
+ CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4),
+ DIV(CLK_DOUT_CORE_CCI, "dout_core_cci", "gout_core_cci",
+ CLK_CON_DIV_CLKCMU_CORE_CCI, 0, 4),
+ DIV(CLK_DOUT_CORE_MMC_EMBD, "dout_core_mmc_embd", "gout_core_mmc_embd",
+ CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD, 0, 9),
+ DIV(CLK_DOUT_CORE_SSS, "dout_core_sss", "gout_core_sss",
+ CLK_CON_DIV_CLKCMU_CORE_SSS, 0, 4),
+
+ /* DPU */
+ DIV(CLK_DOUT_DPU, "dout_dpu", "gout_dpu",
+ CLK_CON_DIV_CLKCMU_DPU, 0, 4),
+
+ /* HSI */
+ DIV(CLK_DOUT_HSI_BUS, "dout_hsi_bus", "gout_hsi_bus",
+ CLK_CON_DIV_CLKCMU_HSI_BUS, 0, 4),
+ DIV(CLK_DOUT_HSI_MMC_CARD, "dout_hsi_mmc_card", "gout_hsi_mmc_card",
+ CLK_CON_DIV_CLKCMU_HSI_MMC_CARD, 0, 9),
+ DIV(CLK_DOUT_HSI_USB20DRD, "dout_hsi_usb20drd", "gout_hsi_usb20drd",
+ CLK_CON_DIV_CLKCMU_HSI_USB20DRD, 0, 4),
+
+ /* PERI */
+ DIV(CLK_DOUT_PERI_BUS, "dout_peri_bus", "gout_peri_bus",
+ CLK_CON_DIV_CLKCMU_PERI_BUS, 0, 4),
+ DIV(CLK_DOUT_PERI_UART, "dout_peri_uart", "gout_peri_uart",
+ CLK_CON_DIV_CLKCMU_PERI_UART, 0, 4),
+ DIV(CLK_DOUT_PERI_IP, "dout_peri_ip", "gout_peri_ip",
+ CLK_CON_DIV_CLKCMU_PERI_IP, 0, 4),
+};
+
+static const struct samsung_gate_clock top_gate_clks[] __initconst = {
+ /* CORE */
+ GATE(CLK_GOUT_CORE_BUS, "gout_core_bus", "mout_core_bus",
+ CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CORE_CCI, "gout_core_cci", "mout_core_cci",
+ CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, 21, 0, 0),
+ GATE(CLK_GOUT_CORE_MMC_EMBD, "gout_core_mmc_embd", "mout_core_mmc_embd",
+ CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD, 21, 0, 0),
+ GATE(CLK_GOUT_CORE_SSS, "gout_core_sss", "mout_core_sss",
+ CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, 21, 0, 0),
+
+ /* DPU */
+ GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu",
+ CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0),
+
+ /* HSI */
+ GATE(CLK_GOUT_HSI_BUS, "gout_hsi_bus", "mout_hsi_bus",
+ CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_HSI_MMC_CARD, "gout_hsi_mmc_card", "mout_hsi_mmc_card",
+ CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD, 21, 0, 0),
+ GATE(CLK_GOUT_HSI_USB20DRD, "gout_hsi_usb20drd", "mout_hsi_usb20drd",
+ CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD, 21, 0, 0),
+
+ /* PERI */
+ GATE(CLK_GOUT_PERI_BUS, "gout_peri_bus", "mout_peri_bus",
+ CLK_CON_GAT_GATE_CLKCMU_PERI_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_PERI_UART, "gout_peri_uart", "mout_peri_uart",
+ CLK_CON_GAT_GATE_CLKCMU_PERI_UART, 21, 0, 0),
+ GATE(CLK_GOUT_PERI_IP, "gout_peri_ip", "mout_peri_ip",
+ CLK_CON_GAT_GATE_CLKCMU_PERI_IP, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info top_cmu_info __initconst = {
+ .pll_clks = top_pll_clks,
+ .nr_pll_clks = ARRAY_SIZE(top_pll_clks),
+ .mux_clks = top_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(top_mux_clks),
+ .div_clks = top_div_clks,
+ .nr_div_clks = ARRAY_SIZE(top_div_clks),
+ .gate_clks = top_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(top_gate_clks),
+ .nr_clk_ids = TOP_NR_CLK,
+ .clk_regs = top_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(top_clk_regs),
+};
+
+static void __init exynos850_cmu_top_init(struct device_node *np)
+{
+ exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs));
+ samsung_cmu_register_one(np, &top_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top",
+ exynos850_cmu_top_init);
+
+/* ---- CMU_HSI ------------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_HSI (0x13400000) */
+#define PLL_CON0_MUX_CLKCMU_HSI_BUS_USER 0x0600
+#define PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER 0x0610
+#define PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER 0x0620
+#define CLK_CON_MUX_MUX_CLK_HSI_RTC 0x1000
+#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV 0x2008
+#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50 0x200c
+#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26 0x2010
+#define CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK 0x2018
+#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK 0x2024
+#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN 0x2028
+#define CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK 0x2038
+#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20 0x203c
+#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY 0x2040
+
+static const unsigned long hsi_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_HSI_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
+ PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
+ CLK_CON_MUX_MUX_CLK_HSI_RTC,
+ CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV,
+ CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50,
+ CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26,
+ CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK,
+ CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK,
+ CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN,
+ CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK,
+ CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20,
+ CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY,
+};
+
+/* List of parent clocks for Muxes in CMU_PERI */
+PNAME(mout_hsi_bus_user_p) = { "oscclk", "dout_hsi_bus" };
+PNAME(mout_hsi_mmc_card_user_p) = { "oscclk", "dout_hsi_mmc_card" };
+PNAME(mout_hsi_usb20drd_user_p) = { "oscclk", "dout_hsi_usb20drd" };
+PNAME(mout_hsi_rtc_p) = { "rtcclk", "oscclk" };
+
+static const struct samsung_mux_clock hsi_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_HSI_BUS_USER, "mout_hsi_bus_user", mout_hsi_bus_user_p,
+ PLL_CON0_MUX_CLKCMU_HSI_BUS_USER, 4, 1),
+ MUX_F(CLK_MOUT_HSI_MMC_CARD_USER, "mout_hsi_mmc_card_user",
+ mout_hsi_mmc_card_user_p, PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
+ 4, 1, CLK_SET_RATE_PARENT, 0),
+ MUX(CLK_MOUT_HSI_USB20DRD_USER, "mout_hsi_usb20drd_user",
+ mout_hsi_usb20drd_user_p, PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
+ 4, 1),
+ MUX(CLK_MOUT_HSI_RTC, "mout_hsi_rtc", mout_hsi_rtc_p,
+ CLK_CON_MUX_MUX_CLK_HSI_RTC, 0, 1),
+};
+
+static const struct samsung_gate_clock hsi_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_USB_RTC_CLK, "gout_usb_rtc", "mout_hsi_rtc",
+ CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV, 21, 0, 0),
+ GATE(CLK_GOUT_USB_REF_CLK, "gout_usb_ref", "mout_hsi_usb20drd_user",
+ CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50, 21, 0, 0),
+ GATE(CLK_GOUT_USB_PHY_REF_CLK, "gout_usb_phy_ref", "oscclk",
+ CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26, 21, 0, 0),
+ GATE(CLK_GOUT_GPIO_HSI_PCLK, "gout_gpio_hsi_pclk", "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_MMC_CARD_ACLK, "gout_mmc_card_aclk", "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_MMC_CARD_SDCLKIN, "gout_mmc_card_sdclkin",
+ "mout_hsi_mmc_card_user",
+ CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN, 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_SYSREG_HSI_PCLK, "gout_sysreg_hsi_pclk",
+ "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_USB_PHY_ACLK, "gout_usb_phy_aclk", "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20, 21, 0, 0),
+ GATE(CLK_GOUT_USB_BUS_EARLY_CLK, "gout_usb_bus_early",
+ "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info hsi_cmu_info __initconst = {
+ .mux_clks = hsi_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(hsi_mux_clks),
+ .gate_clks = hsi_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(hsi_gate_clks),
+ .nr_clk_ids = HSI_NR_CLK,
+ .clk_regs = hsi_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(hsi_clk_regs),
+ .clk_name = "dout_hsi_bus",
+};
+
+/* ---- CMU_PERI ------------------------------------------------------------ */
+
+/* Register Offset definitions for CMU_PERI (0x10030000) */
+#define PLL_CON0_MUX_CLKCMU_PERI_BUS_USER 0x0600
+#define PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER 0x0610
+#define PLL_CON0_MUX_CLKCMU_PERI_SPI_USER 0x0620
+#define PLL_CON0_MUX_CLKCMU_PERI_UART_USER 0x0630
+#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0 0x1800
+#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1 0x1804
+#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2 0x1808
+#define CLK_CON_DIV_DIV_CLK_PERI_SPI_0 0x180c
+#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0 0x200c
+#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1 0x2010
+#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2 0x2014
+#define CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK 0x2020
+#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK 0x2024
+#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK 0x2028
+#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK 0x202c
+#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK 0x2030
+#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK 0x2034
+#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK 0x2038
+#define CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK 0x203c
+#define CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK 0x2040
+#define CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK 0x2044
+#define CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK 0x2048
+#define CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK 0x204c
+#define CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK 0x2050
+#define CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK 0x2054
+#define CLK_CON_GAT_GOUT_PERI_MCT_PCLK 0x205c
+#define CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK 0x2064
+#define CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK 0x209c
+#define CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK 0x20a0
+#define CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK 0x20a4
+#define CLK_CON_GAT_GOUT_PERI_UART_IPCLK 0x20a8
+#define CLK_CON_GAT_GOUT_PERI_UART_PCLK 0x20ac
+#define CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK 0x20b0
+#define CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK 0x20b4
+
+static const unsigned long peri_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_PERI_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER,
+ PLL_CON0_MUX_CLKCMU_PERI_SPI_USER,
+ PLL_CON0_MUX_CLKCMU_PERI_UART_USER,
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0,
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1,
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2,
+ CLK_CON_DIV_DIV_CLK_PERI_SPI_0,
+ CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0,
+ CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1,
+ CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2,
+ CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK,
+ CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK,
+ CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK,
+ CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK,
+ CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK,
+ CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK,
+ CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK,
+ CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK,
+ CLK_CON_GAT_GOUT_PERI_MCT_PCLK,
+ CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK,
+ CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK,
+ CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK,
+ CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK,
+ CLK_CON_GAT_GOUT_PERI_UART_IPCLK,
+ CLK_CON_GAT_GOUT_PERI_UART_PCLK,
+ CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK,
+ CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK,
+};
+
+/* List of parent clocks for Muxes in CMU_PERI */
+PNAME(mout_peri_bus_user_p) = { "oscclk", "dout_peri_bus" };
+PNAME(mout_peri_uart_user_p) = { "oscclk", "dout_peri_uart" };
+PNAME(mout_peri_hsi2c_user_p) = { "oscclk", "dout_peri_ip" };
+PNAME(mout_peri_spi_user_p) = { "oscclk", "dout_peri_ip" };
+
+static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_PERI_BUS_USER, "mout_peri_bus_user", mout_peri_bus_user_p,
+ PLL_CON0_MUX_CLKCMU_PERI_BUS_USER, 4, 1),
+ MUX(CLK_MOUT_PERI_UART_USER, "mout_peri_uart_user",
+ mout_peri_uart_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART_USER, 4, 1),
+ MUX(CLK_MOUT_PERI_HSI2C_USER, "mout_peri_hsi2c_user",
+ mout_peri_hsi2c_user_p, PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, 4, 1),
+ MUX(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user", mout_peri_spi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1),
+};
+
+static const struct samsung_div_clock peri_div_clks[] __initconst = {
+ DIV(CLK_DOUT_PERI_HSI2C0, "dout_peri_hsi2c0", "gout_peri_hsi2c0",
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0, 0, 5),
+ DIV(CLK_DOUT_PERI_HSI2C1, "dout_peri_hsi2c1", "gout_peri_hsi2c1",
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, 0, 5),
+ DIV(CLK_DOUT_PERI_HSI2C2, "dout_peri_hsi2c2", "gout_peri_hsi2c2",
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, 0, 5),
+ DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
+ CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5),
+};
+
+static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_PERI_HSI2C0, "gout_peri_hsi2c0", "mout_peri_hsi2c_user",
+ CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0, 21, 0, 0),
+ GATE(CLK_GOUT_PERI_HSI2C1, "gout_peri_hsi2c1", "mout_peri_hsi2c_user",
+ CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1, 21, 0, 0),
+ GATE(CLK_GOUT_PERI_HSI2C2, "gout_peri_hsi2c2", "mout_peri_hsi2c_user",
+ CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2, 21, 0, 0),
+ GATE(CLK_GOUT_HSI2C0_IPCLK, "gout_hsi2c0_ipclk", "dout_peri_hsi2c0",
+ CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK, 21, 0, 0),
+ GATE(CLK_GOUT_HSI2C0_PCLK, "gout_hsi2c0_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_HSI2C1_IPCLK, "gout_hsi2c1_ipclk", "dout_peri_hsi2c1",
+ CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK, 21, 0, 0),
+ GATE(CLK_GOUT_HSI2C1_PCLK, "gout_hsi2c1_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_HSI2C2_IPCLK, "gout_hsi2c2_ipclk", "dout_peri_hsi2c2",
+ CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK, 21, 0, 0),
+ GATE(CLK_GOUT_HSI2C2_PCLK, "gout_hsi2c2_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C0_PCLK, "gout_i2c0_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C1_PCLK, "gout_i2c1_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C2_PCLK, "gout_i2c2_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C3_PCLK, "gout_i2c3_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C4_PCLK, "gout_i2c4_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C5_PCLK, "gout_i2c5_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_I2C6_PCLK, "gout_i2c6_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_MCT_PCLK, "gout_mct_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_MCT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PWM_MOTOR_PCLK, "gout_pwm_motor_pclk",
+ "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_SPI0_IPCLK, "gout_spi0_ipclk", "dout_peri_spi0",
+ CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, 0, 0),
+ GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk",
+ "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_UART_IPCLK, "gout_uart_ipclk", "mout_peri_uart_user",
+ CLK_CON_GAT_GOUT_PERI_UART_IPCLK, 21, 0, 0),
+ GATE(CLK_GOUT_UART_PCLK, "gout_uart_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_UART_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_WDT0_PCLK, "gout_wdt0_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_WDT1_PCLK, "gout_wdt1_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_GPIO_PERI_PCLK, "gout_gpio_peri_pclk",
+ "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info peri_cmu_info __initconst = {
+ .mux_clks = peri_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(peri_mux_clks),
+ .div_clks = peri_div_clks,
+ .nr_div_clks = ARRAY_SIZE(peri_div_clks),
+ .gate_clks = peri_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(peri_gate_clks),
+ .nr_clk_ids = PERI_NR_CLK,
+ .clk_regs = peri_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(peri_clk_regs),
+ .clk_name = "dout_peri_bus",
+};
+
+/* ---- CMU_CORE ------------------------------------------------------------ */
+
+/* Register Offset definitions for CMU_CORE (0x12000000) */
+#define PLL_CON0_MUX_CLKCMU_CORE_BUS_USER 0x0600
+#define PLL_CON0_MUX_CLKCMU_CORE_CCI_USER 0x0610
+#define PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER 0x0620
+#define PLL_CON0_MUX_CLKCMU_CORE_SSS_USER 0x0630
+#define CLK_CON_MUX_MUX_CLK_CORE_GIC 0x1000
+#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800
+#define CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK 0x2038
+#define CLK_CON_GAT_GOUT_CORE_GIC_CLK 0x2040
+#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK 0x20e8
+#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN 0x20ec
+#define CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK 0x2128
+#define CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK 0x212c
+
+static const unsigned long core_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_CORE_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_CORE_CCI_USER,
+ PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER,
+ PLL_CON0_MUX_CLKCMU_CORE_SSS_USER,
+ CLK_CON_MUX_MUX_CLK_CORE_GIC,
+ CLK_CON_DIV_DIV_CLK_CORE_BUSP,
+ CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK,
+ CLK_CON_GAT_GOUT_CORE_GIC_CLK,
+ CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK,
+ CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
+ CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK,
+ CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK,
+};
+
+/* List of parent clocks for Muxes in CMU_CORE */
+PNAME(mout_core_bus_user_p) = { "oscclk", "dout_core_bus" };
+PNAME(mout_core_cci_user_p) = { "oscclk", "dout_core_cci" };
+PNAME(mout_core_mmc_embd_user_p) = { "oscclk", "dout_core_mmc_embd" };
+PNAME(mout_core_sss_user_p) = { "oscclk", "dout_core_sss" };
+PNAME(mout_core_gic_p) = { "dout_core_busp", "oscclk" };
+
+static const struct samsung_mux_clock core_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_CORE_BUS_USER, "mout_core_bus_user", mout_core_bus_user_p,
+ PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, 4, 1),
+ MUX(CLK_MOUT_CORE_CCI_USER, "mout_core_cci_user", mout_core_cci_user_p,
+ PLL_CON0_MUX_CLKCMU_CORE_CCI_USER, 4, 1),
+ MUX_F(CLK_MOUT_CORE_MMC_EMBD_USER, "mout_core_mmc_embd_user",
+ mout_core_mmc_embd_user_p, PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER,
+ 4, 1, CLK_SET_RATE_PARENT, 0),
+ MUX(CLK_MOUT_CORE_SSS_USER, "mout_core_sss_user", mout_core_sss_user_p,
+ PLL_CON0_MUX_CLKCMU_CORE_SSS_USER, 4, 1),
+ MUX(CLK_MOUT_CORE_GIC, "mout_core_gic", mout_core_gic_p,
+ CLK_CON_MUX_MUX_CLK_CORE_GIC, 0, 1),
+};
+
+static const struct samsung_div_clock core_div_clks[] __initconst = {
+ DIV(CLK_DOUT_CORE_BUSP, "dout_core_busp", "mout_core_bus_user",
+ CLK_CON_DIV_DIV_CLK_CORE_BUSP, 0, 2),
+};
+
+static const struct samsung_gate_clock core_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_CCI_ACLK, "gout_cci_aclk", "mout_core_cci_user",
+ CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_GIC_CLK, "gout_gic_clk", "mout_core_gic",
+ CLK_CON_GAT_GOUT_CORE_GIC_CLK, 21, 0, 0),
+ GATE(CLK_GOUT_MMC_EMBD_ACLK, "gout_mmc_embd_aclk", "dout_core_busp",
+ CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_MMC_EMBD_SDCLKIN, "gout_mmc_embd_sdclkin",
+ "mout_core_mmc_embd_user", CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
+ 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_SSS_ACLK, "gout_sss_aclk", "mout_core_sss_user",
+ CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_SSS_PCLK, "gout_sss_pclk", "dout_core_busp",
+ CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info core_cmu_info __initconst = {
+ .mux_clks = core_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(core_mux_clks),
+ .div_clks = core_div_clks,
+ .nr_div_clks = ARRAY_SIZE(core_div_clks),
+ .gate_clks = core_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(core_gate_clks),
+ .nr_clk_ids = CORE_NR_CLK,
+ .clk_regs = core_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(core_clk_regs),
+ .clk_name = "dout_core_bus",
+};
+
+/* ---- CMU_DPU ------------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_DPU (0x13000000) */
+#define PLL_CON0_MUX_CLKCMU_DPU_USER 0x0600
+#define CLK_CON_DIV_DIV_CLK_DPU_BUSP 0x1800
+#define CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK 0x2004
+#define CLK_CON_GAT_GOUT_DPU_ACLK_DECON0 0x2010
+#define CLK_CON_GAT_GOUT_DPU_ACLK_DMA 0x2014
+#define CLK_CON_GAT_GOUT_DPU_ACLK_DPP 0x2018
+#define CLK_CON_GAT_GOUT_DPU_PPMU_ACLK 0x2028
+#define CLK_CON_GAT_GOUT_DPU_PPMU_PCLK 0x202c
+#define CLK_CON_GAT_GOUT_DPU_SMMU_CLK 0x2038
+#define CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK 0x203c
+
+static const unsigned long dpu_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_DPU_USER,
+ CLK_CON_DIV_DIV_CLK_DPU_BUSP,
+ CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK,
+ CLK_CON_GAT_GOUT_DPU_ACLK_DECON0,
+ CLK_CON_GAT_GOUT_DPU_ACLK_DMA,
+ CLK_CON_GAT_GOUT_DPU_ACLK_DPP,
+ CLK_CON_GAT_GOUT_DPU_PPMU_ACLK,
+ CLK_CON_GAT_GOUT_DPU_PPMU_PCLK,
+ CLK_CON_GAT_GOUT_DPU_SMMU_CLK,
+ CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK,
+};
+
+/* List of parent clocks for Muxes in CMU_CORE */
+PNAME(mout_dpu_user_p) = { "oscclk", "dout_dpu" };
+
+static const struct samsung_mux_clock dpu_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_DPU_USER, "mout_dpu_user", mout_dpu_user_p,
+ PLL_CON0_MUX_CLKCMU_DPU_USER, 4, 1),
+};
+
+static const struct samsung_div_clock dpu_div_clks[] __initconst = {
+ DIV(CLK_DOUT_DPU_BUSP, "dout_dpu_busp", "mout_dpu_user",
+ CLK_CON_DIV_DIV_CLK_DPU_BUSP, 0, 3),
+};
+
+static const struct samsung_gate_clock dpu_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_DPU_CMU_DPU_PCLK, "gout_dpu_cmu_dpu_pclk",
+ "dout_dpu_busp", CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_DECON0_ACLK, "gout_dpu_decon0_aclk", "mout_dpu_user",
+ CLK_CON_GAT_GOUT_DPU_ACLK_DECON0, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_DMA_ACLK, "gout_dpu_dma_aclk", "mout_dpu_user",
+ CLK_CON_GAT_GOUT_DPU_ACLK_DMA, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_DPP_ACLK, "gout_dpu_dpp_aclk", "mout_dpu_user",
+ CLK_CON_GAT_GOUT_DPU_ACLK_DPP, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_PPMU_ACLK, "gout_dpu_ppmu_aclk", "mout_dpu_user",
+ CLK_CON_GAT_GOUT_DPU_PPMU_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_PPMU_PCLK, "gout_dpu_ppmu_pclk", "dout_dpu_busp",
+ CLK_CON_GAT_GOUT_DPU_PPMU_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_SMMU_CLK, "gout_dpu_smmu_clk", "mout_dpu_user",
+ CLK_CON_GAT_GOUT_DPU_SMMU_CLK, 21, 0, 0),
+ GATE(CLK_GOUT_DPU_SYSREG_PCLK, "gout_dpu_sysreg_pclk", "dout_dpu_busp",
+ CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info dpu_cmu_info __initconst = {
+ .mux_clks = dpu_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(dpu_mux_clks),
+ .div_clks = dpu_div_clks,
+ .nr_div_clks = ARRAY_SIZE(dpu_div_clks),
+ .gate_clks = dpu_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(dpu_gate_clks),
+ .nr_clk_ids = DPU_NR_CLK,
+ .clk_regs = dpu_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(dpu_clk_regs),
+ .clk_name = "dout_dpu",
+};
+
+/* ---- platform_driver ----------------------------------------------------- */
+
+static int __init exynos850_cmu_probe(struct platform_device *pdev)
+{
+ const struct samsung_cmu_info *info;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+
+ info = of_device_get_match_data(dev);
+ exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs);
+ samsung_cmu_register_one(np, info);
+
+ /* Keep bus clock running, so it's possible to access CMU registers */
+ if (info->clk_name) {
+ struct clk *bus_clk;
+
+ bus_clk = clk_get(dev, info->clk_name);
+ if (IS_ERR(bus_clk)) {
+ pr_err("%s: could not find bus clock %s; err = %ld\n",
+ __func__, info->clk_name, PTR_ERR(bus_clk));
+ } else {
+ clk_prepare_enable(bus_clk);
+ }
+ }
+
+ return 0;
+}
+
+/* CMUs which belong to Power Domains and need runtime PM to be implemented */
+static const struct of_device_id exynos850_cmu_of_match[] = {
+ {
+ .compatible = "samsung,exynos850-cmu-hsi",
+ .data = &hsi_cmu_info,
+ }, {
+ .compatible = "samsung,exynos850-cmu-peri",
+ .data = &peri_cmu_info,
+ }, {
+ .compatible = "samsung,exynos850-cmu-core",
+ .data = &core_cmu_info,
+ }, {
+ .compatible = "samsung,exynos850-cmu-dpu",
+ .data = &dpu_cmu_info,
+ }, {
+ },
+};
+
+static struct platform_driver exynos850_cmu_driver __refdata = {
+ .driver = {
+ .name = "exynos850-cmu",
+ .of_match_table = exynos850_cmu_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = exynos850_cmu_probe,
+};
+
+static int __init exynos850_cmu_init(void)
+{
+ return platform_driver_register(&exynos850_cmu_driver);
+}
+core_initcall(exynos850_cmu_init);
--
2.30.2

2021-10-08 15:46:00

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH v3 2/5] clk: samsung: clk-pll: Implement pll0831x PLL type

pll0831x PLL is used in Exynos850 SoC for top-level fractional PLLs. The
code was derived from very similar pll36xx type, with next differences:

1. Lock time for pll0831x is 500*P_DIV, when for pll36xx it's 3000*P_DIV
2. It's not suggested in Exynos850 TRM that S_DIV change doesn't require
performing PLL lock procedure (which is done in pll36xx
implementation)
3. The offset from PMS-values register to K-value register is 0x8 for
pll0831x, when for pll36xx it's 0x4

When defining pll0831x type, CON3 register offset should be provided as
a "con" parameter of PLL() macro, like this:

PLL(pll_0831x, 0, "fout_mmc_pll", "oscclk",
PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, pll0831x_26mhz_tbl),

To define PLL rates table, one can use PLL_36XX_RATE() macro, e.g.:

PLL_36XX_RATE(26 * MHZ, 799999877, 31, 1, 0, -15124)

as it's completely appropriate for pl0831x type and there is no sense in
duplicating that.

If bit #1 (MANUAL_PLL_CTRL) is not set in CON1 register, it won't be
possible to set new rate, with next error showing in kernel log:

Could not lock PLL fout_mmc_pll

That can happen for example if bootloader clears that bit beforehand.
PLL driver doesn't account for that, so if MANUAL_PLL_CTRL bit was
cleared, it's assumed it was done for a reason and it shouldn't be
possible to change that PLL's rate at all.

Signed-off-by: Sam Protsenko <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Acked-by: Chanwoo Choi <[email protected]>
---
Changes in v3:
- (none)

Changes in v2:
- Added R-b tag by Krzysztof Kozlowski
- Added Ack tag by Chanwoo Choi

drivers/clk/samsung/clk-pll.c | 105 ++++++++++++++++++++++++++++++++++
drivers/clk/samsung/clk-pll.h | 1 +
2 files changed, 106 insertions(+)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 03131b149c0b..83d1b03647db 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -498,6 +498,103 @@ static const struct clk_ops samsung_pll0822x_clk_min_ops = {
.recalc_rate = samsung_pll0822x_recalc_rate,
};

+/*
+ * PLL0831x Clock Type
+ */
+/* Maximum lock time can be 500 * PDIV cycles */
+#define PLL0831X_LOCK_FACTOR (500)
+
+#define PLL0831X_KDIV_MASK (0xFFFF)
+#define PLL0831X_MDIV_MASK (0x1FF)
+#define PLL0831X_PDIV_MASK (0x3F)
+#define PLL0831X_SDIV_MASK (0x7)
+#define PLL0831X_MDIV_SHIFT (16)
+#define PLL0831X_PDIV_SHIFT (8)
+#define PLL0831X_SDIV_SHIFT (0)
+#define PLL0831X_KDIV_SHIFT (0)
+#define PLL0831X_LOCK_STAT_SHIFT (29)
+#define PLL0831X_ENABLE_SHIFT (31)
+
+static unsigned long samsung_pll0831x_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ u32 mdiv, pdiv, sdiv, pll_con3, pll_con5;
+ s16 kdiv;
+ u64 fvco = parent_rate;
+
+ pll_con3 = readl_relaxed(pll->con_reg);
+ pll_con5 = readl_relaxed(pll->con_reg + 8);
+ mdiv = (pll_con3 >> PLL0831X_MDIV_SHIFT) & PLL0831X_MDIV_MASK;
+ pdiv = (pll_con3 >> PLL0831X_PDIV_SHIFT) & PLL0831X_PDIV_MASK;
+ sdiv = (pll_con3 >> PLL0831X_SDIV_SHIFT) & PLL0831X_SDIV_MASK;
+ kdiv = (s16)((pll_con5 >> PLL0831X_KDIV_SHIFT) & PLL0831X_KDIV_MASK);
+
+ fvco *= (mdiv << 16) + kdiv;
+ do_div(fvco, (pdiv << sdiv));
+ fvco >>= 16;
+
+ return (unsigned long)fvco;
+}
+
+static int samsung_pll0831x_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long parent_rate)
+{
+ const struct samsung_pll_rate_table *rate;
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ u32 pll_con3, pll_con5;
+
+ /* Get required rate settings from table */
+ rate = samsung_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ pll_con3 = readl_relaxed(pll->con_reg);
+ pll_con5 = readl_relaxed(pll->con_reg + 8);
+
+ /* Change PLL PMSK values */
+ pll_con3 &= ~((PLL0831X_MDIV_MASK << PLL0831X_MDIV_SHIFT) |
+ (PLL0831X_PDIV_MASK << PLL0831X_PDIV_SHIFT) |
+ (PLL0831X_SDIV_MASK << PLL0831X_SDIV_SHIFT));
+ pll_con3 |= (rate->mdiv << PLL0831X_MDIV_SHIFT) |
+ (rate->pdiv << PLL0831X_PDIV_SHIFT) |
+ (rate->sdiv << PLL0831X_SDIV_SHIFT);
+ pll_con5 &= ~(PLL0831X_KDIV_MASK << PLL0831X_KDIV_SHIFT);
+ /*
+ * kdiv is 16-bit 2's complement (s16), but stored as unsigned int.
+ * Cast it to u16 to avoid leading 0xffff's in case of negative value.
+ */
+ pll_con5 |= ((u16)rate->kdiv << PLL0831X_KDIV_SHIFT);
+
+ /* Set PLL lock time */
+ writel_relaxed(rate->pdiv * PLL0831X_LOCK_FACTOR, pll->lock_reg);
+
+ /* Write PMSK values */
+ writel_relaxed(pll_con3, pll->con_reg);
+ writel_relaxed(pll_con5, pll->con_reg + 8);
+
+ /* Wait for PLL lock if the PLL is enabled */
+ if (pll_con3 & BIT(pll->enable_offs))
+ return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
+
+ return 0;
+}
+
+static const struct clk_ops samsung_pll0831x_clk_ops = {
+ .recalc_rate = samsung_pll0831x_recalc_rate,
+ .set_rate = samsung_pll0831x_set_rate,
+ .round_rate = samsung_pll_round_rate,
+ .enable = samsung_pll3xxx_enable,
+ .disable = samsung_pll3xxx_disable,
+};
+
+static const struct clk_ops samsung_pll0831x_clk_min_ops = {
+ .recalc_rate = samsung_pll0831x_recalc_rate,
+};
+
/*
* PLL45xx Clock Type
*/
@@ -1407,6 +1504,14 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
else
init.ops = &samsung_pll36xx_clk_ops;
break;
+ case pll_0831x:
+ pll->enable_offs = PLL0831X_ENABLE_SHIFT;
+ pll->lock_offs = PLL0831X_LOCK_STAT_SHIFT;
+ if (!pll->rate_table)
+ init.ops = &samsung_pll0831x_clk_min_ops;
+ else
+ init.ops = &samsung_pll0831x_clk_ops;
+ break;
case pll_6552:
case pll_6552_s3c2416:
init.ops = &samsung_pll6552_clk_ops;
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 213e94a97f23..a739f2b7ae80 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -37,6 +37,7 @@ enum samsung_pll_type {
pll_1452x,
pll_1460x,
pll_0822x,
+ pll_0831x,
};

#define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \
--
2.30.2

2021-10-08 15:47:41

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH v3 3/5] dt-bindings: clock: Add bindings definitions for Exynos850 CMU

Clock controller driver is designed to have separate instances for each
particular CMU. So clock IDs in this bindings header also start from 1
for each CMU.

Signed-off-by: Sam Protsenko <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Changes in v3:
- Changed the license to GPL-2.0-only + BSD-2-Clause

Changes in v2:
- Added all clock ids
- Added CLK_ prefix for all clock constants
- Added R-b tag by Krzysztof Kozlowski
- Added Ack tag by Rob Herring

include/dt-bindings/clock/exynos850.h | 141 ++++++++++++++++++++++++++
1 file changed, 141 insertions(+)
create mode 100644 include/dt-bindings/clock/exynos850.h

diff --git a/include/dt-bindings/clock/exynos850.h b/include/dt-bindings/clock/exynos850.h
new file mode 100644
index 000000000000..8999184f94a2
--- /dev/null
+++ b/include/dt-bindings/clock/exynos850.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2021 Linaro Ltd.
+ * Author: Sam Protsenko <[email protected]>
+ *
+ * Device Tree binding constants for Exynos850 clock controller.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_EXYNOS_850_H
+#define _DT_BINDINGS_CLOCK_EXYNOS_850_H
+
+/* CMU_TOP */
+#define CLK_FOUT_SHARED0_PLL 1
+#define CLK_FOUT_SHARED1_PLL 2
+#define CLK_FOUT_MMC_PLL 3
+#define CLK_MOUT_SHARED0_PLL 4
+#define CLK_MOUT_SHARED1_PLL 5
+#define CLK_MOUT_MMC_PLL 6
+#define CLK_MOUT_CORE_BUS 7
+#define CLK_MOUT_CORE_CCI 8
+#define CLK_MOUT_CORE_MMC_EMBD 9
+#define CLK_MOUT_CORE_SSS 10
+#define CLK_MOUT_DPU 11
+#define CLK_MOUT_HSI_BUS 12
+#define CLK_MOUT_HSI_MMC_CARD 13
+#define CLK_MOUT_HSI_USB20DRD 14
+#define CLK_MOUT_PERI_BUS 15
+#define CLK_MOUT_PERI_UART 16
+#define CLK_MOUT_PERI_IP 17
+#define CLK_DOUT_SHARED0_DIV3 18
+#define CLK_DOUT_SHARED0_DIV2 19
+#define CLK_DOUT_SHARED1_DIV3 20
+#define CLK_DOUT_SHARED1_DIV2 21
+#define CLK_DOUT_SHARED0_DIV4 22
+#define CLK_DOUT_SHARED1_DIV4 23
+#define CLK_DOUT_CORE_BUS 24
+#define CLK_DOUT_CORE_CCI 25
+#define CLK_DOUT_CORE_MMC_EMBD 26
+#define CLK_DOUT_CORE_SSS 27
+#define CLK_DOUT_DPU 28
+#define CLK_DOUT_HSI_BUS 29
+#define CLK_DOUT_HSI_MMC_CARD 30
+#define CLK_DOUT_HSI_USB20DRD 31
+#define CLK_DOUT_PERI_BUS 32
+#define CLK_DOUT_PERI_UART 33
+#define CLK_DOUT_PERI_IP 34
+#define CLK_GOUT_CORE_BUS 35
+#define CLK_GOUT_CORE_CCI 36
+#define CLK_GOUT_CORE_MMC_EMBD 37
+#define CLK_GOUT_CORE_SSS 38
+#define CLK_GOUT_DPU 39
+#define CLK_GOUT_HSI_BUS 40
+#define CLK_GOUT_HSI_MMC_CARD 41
+#define CLK_GOUT_HSI_USB20DRD 42
+#define CLK_GOUT_PERI_BUS 43
+#define CLK_GOUT_PERI_UART 44
+#define CLK_GOUT_PERI_IP 45
+#define TOP_NR_CLK 46
+
+/* CMU_HSI */
+#define CLK_MOUT_HSI_BUS_USER 1
+#define CLK_MOUT_HSI_MMC_CARD_USER 2
+#define CLK_MOUT_HSI_USB20DRD_USER 3
+#define CLK_MOUT_HSI_RTC 4
+#define CLK_GOUT_USB_RTC_CLK 5
+#define CLK_GOUT_USB_REF_CLK 6
+#define CLK_GOUT_USB_PHY_REF_CLK 7
+#define CLK_GOUT_USB_PHY_ACLK 8
+#define CLK_GOUT_USB_BUS_EARLY_CLK 9
+#define CLK_GOUT_GPIO_HSI_PCLK 10
+#define CLK_GOUT_MMC_CARD_ACLK 11
+#define CLK_GOUT_MMC_CARD_SDCLKIN 12
+#define CLK_GOUT_SYSREG_HSI_PCLK 13
+#define HSI_NR_CLK 14
+
+/* CMU_PERI */
+#define CLK_MOUT_PERI_BUS_USER 1
+#define CLK_MOUT_PERI_UART_USER 2
+#define CLK_MOUT_PERI_HSI2C_USER 3
+#define CLK_MOUT_PERI_SPI_USER 4
+#define CLK_DOUT_PERI_HSI2C0 5
+#define CLK_DOUT_PERI_HSI2C1 6
+#define CLK_DOUT_PERI_HSI2C2 7
+#define CLK_DOUT_PERI_SPI0 8
+#define CLK_GOUT_PERI_HSI2C0 9
+#define CLK_GOUT_PERI_HSI2C1 10
+#define CLK_GOUT_PERI_HSI2C2 11
+#define CLK_GOUT_GPIO_PERI_PCLK 12
+#define CLK_GOUT_HSI2C0_IPCLK 13
+#define CLK_GOUT_HSI2C0_PCLK 14
+#define CLK_GOUT_HSI2C1_IPCLK 15
+#define CLK_GOUT_HSI2C1_PCLK 16
+#define CLK_GOUT_HSI2C2_IPCLK 17
+#define CLK_GOUT_HSI2C2_PCLK 18
+#define CLK_GOUT_I2C0_PCLK 19
+#define CLK_GOUT_I2C1_PCLK 20
+#define CLK_GOUT_I2C2_PCLK 21
+#define CLK_GOUT_I2C3_PCLK 22
+#define CLK_GOUT_I2C4_PCLK 23
+#define CLK_GOUT_I2C5_PCLK 24
+#define CLK_GOUT_I2C6_PCLK 25
+#define CLK_GOUT_MCT_PCLK 26
+#define CLK_GOUT_PWM_MOTOR_PCLK 27
+#define CLK_GOUT_SPI0_IPCLK 28
+#define CLK_GOUT_SPI0_PCLK 29
+#define CLK_GOUT_SYSREG_PERI_PCLK 30
+#define CLK_GOUT_UART_IPCLK 31
+#define CLK_GOUT_UART_PCLK 32
+#define CLK_GOUT_WDT0_PCLK 33
+#define CLK_GOUT_WDT1_PCLK 34
+#define PERI_NR_CLK 35
+
+/* CMU_CORE */
+#define CLK_MOUT_CORE_BUS_USER 1
+#define CLK_MOUT_CORE_CCI_USER 2
+#define CLK_MOUT_CORE_MMC_EMBD_USER 3
+#define CLK_MOUT_CORE_SSS_USER 4
+#define CLK_MOUT_CORE_GIC 5
+#define CLK_DOUT_CORE_BUSP 6
+#define CLK_GOUT_CCI_ACLK 7
+#define CLK_GOUT_GIC_CLK 8
+#define CLK_GOUT_MMC_EMBD_ACLK 9
+#define CLK_GOUT_MMC_EMBD_SDCLKIN 10
+#define CLK_GOUT_SSS_ACLK 11
+#define CLK_GOUT_SSS_PCLK 12
+#define CORE_NR_CLK 13
+
+/* CMU_DPU */
+#define CLK_MOUT_DPU_USER 1
+#define CLK_DOUT_DPU_BUSP 2
+#define CLK_GOUT_DPU_CMU_DPU_PCLK 3
+#define CLK_GOUT_DPU_DECON0_ACLK 4
+#define CLK_GOUT_DPU_DMA_ACLK 5
+#define CLK_GOUT_DPU_DPP_ACLK 6
+#define CLK_GOUT_DPU_PPMU_ACLK 7
+#define CLK_GOUT_DPU_PPMU_PCLK 8
+#define CLK_GOUT_DPU_SMMU_CLK 9
+#define CLK_GOUT_DPU_SYSREG_PCLK 10
+#define DPU_NR_CLK 11
+
+#endif /* _DT_BINDINGS_CLOCK_EXYNOS_850_H */
--
2.30.2

2021-10-08 15:48:16

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH v3 4/5] dt-bindings: clock: Document Exynos850 CMU bindings

Provide dt-schema documentation for Exynos850 SoC clock controller.

Signed-off-by: Sam Protsenko <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Acked-by: Chanwoo Choi <[email protected]>
---
Changes in v3:
- Added R-b tag by Krzysztof Kozlowski

Changes in v2:
- Dropped OSCCLK node declaration example
- Dropped UART node declaration example
- Added Ack tag by Chanwoo Choi

.../clock/samsung,exynos850-clock.yaml | 185 ++++++++++++++++++
1 file changed, 185 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml

diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
new file mode 100644
index 000000000000..79202e6e6402
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
@@ -0,0 +1,185 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,exynos850-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos850 SoC clock controller
+
+maintainers:
+ - Sam Protsenko <[email protected]>
+ - Chanwoo Choi <[email protected]>
+ - Krzysztof Kozlowski <[email protected]>
+ - Sylwester Nawrocki <[email protected]>
+ - Tomasz Figa <[email protected]>
+
+description: |
+ Exynos850 clock controller is comprised of several CMU units, generating
+ clocks for different domains. Those CMU units are modeled as separate device
+ tree nodes, and might depend on each other. Root clocks in that clock tree are
+ two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
+ clocks must be defined as fixed-rate clocks in dts.
+
+ CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
+ dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
+
+ Each clock is assigned an identifier and client nodes can use this identifier
+ to specify the clock which they consume. All clocks that available for usage
+ in clock consumer nodes are defined as preprocessor macros in
+ 'dt-bindings/clock/exynos850.h' header.
+
+properties:
+ compatible:
+ enum:
+ - samsung,exynos850-cmu-top
+ - samsung,exynos850-cmu-core
+ - samsung,exynos850-cmu-dpu
+ - samsung,exynos850-cmu-hsi
+ - samsung,exynos850-cmu-peri
+
+ clocks:
+ minItems: 1
+ maxItems: 5
+
+ clock-names:
+ minItems: 1
+ maxItems: 5
+
+ "#clock-cells":
+ const: 1
+
+ reg:
+ maxItems: 1
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos850-cmu-top
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+
+ clock-names:
+ items:
+ - const: oscclk
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos850-cmu-core
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_CORE bus clock (from CMU_TOP)
+ - description: CCI clock (from CMU_TOP)
+ - description: eMMC clock (from CMU_TOP)
+ - description: SSS clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: dout_core_bus
+ - const: dout_core_cci
+ - const: dout_core_mmc_embd
+ - const: dout_core_sss
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos850-cmu-dpu
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: DPU clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: dout_dpu
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos850-cmu-hsi
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: External RTC clock (32768 Hz)
+ - description: CMU_HSI bus clock (from CMU_TOP)
+ - description: SD card clock (from CMU_TOP)
+ - description: "USB 2.0 DRD clock (from CMU_TOP)"
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: rtcclk
+ - const: dout_hsi_bus
+ - const: dout_hsi_mmc_card
+ - const: dout_hsi_usb20drd
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos850-cmu-peri
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_PERI bus clock (from CMU_TOP)
+ - description: UART clock (from CMU_TOP)
+ - description: Parent clock for HSI2C and SPI (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: dout_peri_bus
+ - const: dout_peri_uart
+ - const: dout_peri_ip
+
+required:
+ - compatible
+ - "#clock-cells"
+ - clocks
+ - clock-names
+ - reg
+
+additionalProperties: false
+
+examples:
+ # Clock controller node for CMU_PERI
+ - |
+ #include <dt-bindings/clock/exynos850.h>
+
+ cmu_peri: clock-controller@10030000 {
+ compatible = "samsung,exynos850-cmu-peri";
+ reg = <0x10030000 0x8000>;
+ #clock-cells = <1>;
+
+ clocks = <&oscclk>, <&cmu_top CLK_DOUT_PERI_BUS>,
+ <&cmu_top CLK_DOUT_PERI_UART>,
+ <&cmu_top CLK_DOUT_PERI_IP>;
+ clock-names = "oscclk", "dout_peri_bus",
+ "dout_peri_uart", "dout_peri_ip";
+ };
+
+...
--
2.30.2

2021-10-09 20:27:21

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH v3 2/5] clk: samsung: clk-pll: Implement pll0831x PLL type

On 08.10.2021 17:43, Sam Protsenko wrote:
> pll0831x PLL is used in Exynos850 SoC for top-level fractional PLLs. The
> code was derived from very similar pll36xx type, with next differences:
>
> 1. Lock time for pll0831x is 500*P_DIV, when for pll36xx it's 3000*P_DIV
> 2. It's not suggested in Exynos850 TRM that S_DIV change doesn't require
> performing PLL lock procedure (which is done in pll36xx
> implementation)
> 3. The offset from PMS-values register to K-value register is 0x8 for
> pll0831x, when for pll36xx it's 0x4
>
> When defining pll0831x type, CON3 register offset should be provided as
> a "con" parameter of PLL() macro, like this:
>
> PLL(pll_0831x, 0, "fout_mmc_pll", "oscclk",
> PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, pll0831x_26mhz_tbl),
>
> To define PLL rates table, one can use PLL_36XX_RATE() macro, e.g.:
>
> PLL_36XX_RATE(26 * MHZ, 799999877, 31, 1, 0, -15124)
>
> as it's completely appropriate for pl0831x type and there is no sense in
> duplicating that.
>
> If bit #1 (MANUAL_PLL_CTRL) is not set in CON1 register, it won't be
> possible to set new rate, with next error showing in kernel log:
>
> Could not lock PLL fout_mmc_pll
>
> That can happen for example if bootloader clears that bit beforehand.
> PLL driver doesn't account for that, so if MANUAL_PLL_CTRL bit was
> cleared, it's assumed it was done for a reason and it shouldn't be
> possible to change that PLL's rate at all.
>
> Signed-off-by: Sam Protsenko<[email protected]>
> Reviewed-by: Krzysztof Kozlowski<[email protected]>
> Acked-by: Chanwoo Choi<[email protected]>

Applied, thanks.

2021-10-09 20:30:01

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH v3 3/5] dt-bindings: clock: Add bindings definitions for Exynos850 CMU

On 08.10.2021 17:43, Sam Protsenko wrote:
> Clock controller driver is designed to have separate instances for each
> particular CMU. So clock IDs in this bindings header also start from 1
> for each CMU.
>
> Signed-off-by: Sam Protsenko<[email protected]>
> Reviewed-by: Krzysztof Kozlowski<[email protected]>
> Acked-by: Rob Herring<[email protected]>

Applied, thanks.

2021-10-09 20:42:13

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] dt-bindings: clock: Document Exynos850 CMU bindings

On 08.10.2021 17:43, Sam Protsenko wrote:
> Provide dt-schema documentation for Exynos850 SoC clock controller.
>
> Signed-off-by: Sam Protsenko <[email protected]>
> Reviewed-by: Krzysztof Kozlowski <[email protected]>
> Acked-by: Chanwoo Choi <[email protected]>

> diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
> new file mode 100644
> index 000000000000..79202e6e6402
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
> @@ -0,0 +1,185 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/samsung,exynos850-clock.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Samsung Exynos850 SoC clock controller
> +
> +maintainers:
> + - Sam Protsenko <[email protected]>
> + - Chanwoo Choi <[email protected]>
> + - Krzysztof Kozlowski <[email protected]>
> + - Sylwester Nawrocki <[email protected]>
> + - Tomasz Figa <[email protected]>
> +
> +description: |
> + Exynos850 clock controller is comprised of several CMU units, generating
> + clocks for different domains. Those CMU units are modeled as separate device
> + tree nodes, and might depend on each other. Root clocks in that clock tree are
> + two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
> + clocks must be defined as fixed-rate clocks in dts.
> +
> + CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
> + dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
> +
> + Each clock is assigned an identifier and client nodes can use this identifier
> + to specify the clock which they consume. All clocks that available for usage

s/All clocks that available/All clocks available ?
No need to resend, I can amend it when applying.

2021-10-11 13:33:31

by Sam Protsenko

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] dt-bindings: clock: Document Exynos850 CMU bindings

On Sat, 9 Oct 2021 at 23:41, Sylwester Nawrocki <[email protected]> wrote:
>
> On 08.10.2021 17:43, Sam Protsenko wrote:
> > Provide dt-schema documentation for Exynos850 SoC clock controller.
> >
> > Signed-off-by: Sam Protsenko <[email protected]>
> > Reviewed-by: Krzysztof Kozlowski <[email protected]>
> > Acked-by: Chanwoo Choi <[email protected]>
>
> > diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
> > new file mode 100644
> > index 000000000000..79202e6e6402
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
> > @@ -0,0 +1,185 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/clock/samsung,exynos850-clock.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Samsung Exynos850 SoC clock controller
> > +
> > +maintainers:
> > + - Sam Protsenko <[email protected]>
> > + - Chanwoo Choi <[email protected]>
> > + - Krzysztof Kozlowski <[email protected]>
> > + - Sylwester Nawrocki <[email protected]>
> > + - Tomasz Figa <[email protected]>
> > +
> > +description: |
> > + Exynos850 clock controller is comprised of several CMU units, generating
> > + clocks for different domains. Those CMU units are modeled as separate device
> > + tree nodes, and might depend on each other. Root clocks in that clock tree are
> > + two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
> > + clocks must be defined as fixed-rate clocks in dts.
> > +
> > + CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
> > + dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
> > +
> > + Each clock is assigned an identifier and client nodes can use this identifier
> > + to specify the clock which they consume. All clocks that available for usage
>
> s/All clocks that available/All clocks available ?
> No need to resend, I can amend it when applying.
>

Yeah, not a native speaker, I tend to do such mistakes sometimes :)
Please fix when applying.

Btw, I can see that you already applied 3 out of 5 patches from this
patch series here: [1]. Can you please also apply the rest, or is
there any outstanding comments that I missed?

[1] https://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git/log/?h=for-v5.16/next

2021-10-11 13:35:54

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] dt-bindings: clock: Document Exynos850 CMU bindings

On 11.10.2021 12:13, Sam Protsenko wrote:
> On Sat, 9 Oct 2021 at 23:41, Sylwester Nawrocki <[email protected]> wrote:
>>
>> On 08.10.2021 17:43, Sam Protsenko wrote:
>>> Provide dt-schema documentation for Exynos850 SoC clock controller.
>>>
>>> Signed-off-by: Sam Protsenko <[email protected]>
>>> Reviewed-by: Krzysztof Kozlowski <[email protected]>
>>> Acked-by: Chanwoo Choi <[email protected]>
[...]
>>> +++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
>>> @@ -0,0 +1,185 @@
[...]
>>> +
>>> +title: Samsung Exynos850 SoC clock controller
>>> +
>>> +maintainers:
>>> + - Sam Protsenko <[email protected]>
>>> + - Chanwoo Choi <[email protected]>
>>> + - Krzysztof Kozlowski <[email protected]>
>>> + - Sylwester Nawrocki <[email protected]>
>>> + - Tomasz Figa <[email protected]>
>>> +
>>> +description: |
>>> + Exynos850 clock controller is comprised of several CMU units, generating
>>> + clocks for different domains. Those CMU units are modeled as separate device
>>> + tree nodes, and might depend on each other. Root clocks in that clock tree are
>>> + two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
>>> + clocks must be defined as fixed-rate clocks in dts.
>>> +
>>> + CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
>>> + dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
>>> +
>>> + Each clock is assigned an identifier and client nodes can use this identifier
>>> + to specify the clock which they consume. All clocks that available for usage
>>
>> s/All clocks that available/All clocks available ?
>> No need to resend, I can amend it when applying.
>>
>
> Yeah, not a native speaker, I tend to do such mistakes sometimes :)
> Please fix when applying.
>
> Btw, I can see that you already applied 3 out of 5 patches from this
> patch series here: [1]. Can you please also apply the rest, or is
> there any outstanding comments that I missed?

The patches look good to me, I just wanted to allow some for Rob to have
a look and provide an Ack.

Regards,
--
Sylwester Nawrocki
Samsung R&D Institute Poland

2021-10-12 08:17:51

by Sam Protsenko

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] clk: samsung: Introduce Exynos850 clock driver

Hi Sylwester,

On Fri, 8 Oct 2021 at 18:44, Sam Protsenko <[email protected]> wrote:
>
> This is the initial implementation adding only basic clocks like UART,
> MMC, I2C and corresponding parent clocks. Design is influenced by
> Exynos5433 clock driver.
>
> Bus clock is enabled by default (in probe function) for all CMUs except
> CMU_TOP, the reasoning is as follows. By default if bus clock has no
> users its "enable count" value is 0. It might be actually running if
> it's already enabled in bootloader, but then in some cases it can be
> disabled by mistake. For example, such case was observed when
> dw_mci_probe() enabled the bus clock, then failed to do something and
> disabled that bus clock on error path. After that, even the attempt to
> read the 'clk_summary' file in DebugFS freezed forever, as CMU bus clock
> ended up being disabled and it wasn't possible to access CMU registers
> anymore.
>
> To avoid such cases, CMU driver must increment the ref count for that
> bus clock by running clk_prepare_enable(). There is already existing
> '.clk_name' field in struct samsung_cmu_info, exactly for that reason.
> It was added in commit 523d3de41f02 ("clk: samsung: exynos5433: Add
> support for runtime PM"), with next mentioning in commit message:
>
> > Also for each CMU there is one special parent clock, which has to be
> > enabled all the time when any access to CMU registers is being done.
>
> But that clock is actually only enabled in Exynos5433 clock driver right
> now. So the same code is added to exynos850_cmu_probe() function,
> As was described above, it might be helpful not only for PM reasons, but
> also to prevent possible erroneous clock gating on error paths.
>
> Another way to workaround that issue would be to use CLOCK_IS_CRITICAL
> flag for corresponding gate clocks. But that might be not very good
> design decision, as we might still want to disable that bus clock, e.g.
> on PM suspend.
>
> Signed-off-by: Sam Protsenko <[email protected]>
> Reviewed-by: Krzysztof Kozlowski <[email protected]>
> ---

Can we also apply this one?

> Changes in v3:
> - Added R-b tag by Krzysztof Kozlowski
>
> Changes in v2:
> - Used of_iomap() for the whole CMU range instead of ioremap() in
> exynos850_init_clocks()
> - Used readl/writel functions in exynos850_init_clocks() for consistency
> with other drivers
> - Added all clock ids
> - Added CMU_DPU
> - Implemented platform_driver for all Power Domain capable CMUs
> - Moved bus clock enablement code here to probe function
> - Used clk_get() instead of __clk_lookup()
>
> drivers/clk/samsung/Makefile | 1 +
> drivers/clk/samsung/clk-exynos850.c | 835 ++++++++++++++++++++++++++++
> 2 files changed, 836 insertions(+)
> create mode 100644 drivers/clk/samsung/clk-exynos850.c
>
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> index 028b2e27a37e..c46cf11e4d0b 100644
> --- a/drivers/clk/samsung/Makefile
> +++ b/drivers/clk/samsung/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
> obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
> obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o
> obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
> +obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o
> obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
> obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
> obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
> diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
> new file mode 100644
> index 000000000000..2294989e244c
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos850.c
> @@ -0,0 +1,835 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2021 Linaro Ltd.
> + * Author: Sam Protsenko <[email protected]>
> + *
> + * Common Clock Framework support for Exynos850 SoC.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +
> +#include <dt-bindings/clock/exynos850.h>
> +
> +#include "clk.h"
> +
> +/* Gate register bits */
> +#define GATE_MANUAL BIT(20)
> +#define GATE_ENABLE_HWACG BIT(28)
> +
> +/* Gate register offsets range */
> +#define GATE_OFF_START 0x2000
> +#define GATE_OFF_END 0x2fff
> +
> +/**
> + * exynos850_init_clocks - Set clocks initial configuration
> + * @np: CMU device tree node with "reg" property (CMU addr)
> + * @reg_offs: Register offsets array for clocks to init
> + * @reg_offs_len: Number of register offsets in reg_offs array
> + *
> + * Set manual control mode for all gate clocks.
> + */
> +static void __init exynos850_init_clocks(struct device_node *np,
> + const unsigned long *reg_offs, size_t reg_offs_len)
> +{
> + void __iomem *reg_base;
> + size_t i;
> +
> + reg_base = of_iomap(np, 0);
> + if (!reg_base)
> + panic("%s: failed to map registers\n", __func__);
> +
> + for (i = 0; i < reg_offs_len; ++i) {
> + void __iomem *reg = reg_base + reg_offs[i];
> + u32 val;
> +
> + /* Modify only gate clock registers */
> + if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END)
> + continue;
> +
> + val = readl(reg);
> + val |= GATE_MANUAL;
> + val &= ~GATE_ENABLE_HWACG;
> + writel(val, reg);
> + }
> +
> + iounmap(reg_base);
> +}
> +
> +/* ---- CMU_TOP ------------------------------------------------------------- */
> +
> +/* Register Offset definitions for CMU_TOP (0x120e0000) */
> +#define PLL_LOCKTIME_PLL_MMC 0x0000
> +#define PLL_LOCKTIME_PLL_SHARED0 0x0004
> +#define PLL_LOCKTIME_PLL_SHARED1 0x0008
> +#define PLL_CON0_PLL_MMC 0x0100
> +#define PLL_CON3_PLL_MMC 0x010c
> +#define PLL_CON0_PLL_SHARED0 0x0140
> +#define PLL_CON3_PLL_SHARED0 0x014c
> +#define PLL_CON0_PLL_SHARED1 0x0180
> +#define PLL_CON3_PLL_SHARED1 0x018c
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1014
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_SSS 0x1020
> +#define CLK_CON_MUX_MUX_CLKCMU_DPU 0x1034
> +#define CLK_CON_MUX_MUX_CLKCMU_HSI_BUS 0x103c
> +#define CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD 0x1040
> +#define CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD 0x1044
> +#define CLK_CON_MUX_MUX_CLKCMU_PERI_BUS 0x1070
> +#define CLK_CON_MUX_MUX_CLKCMU_PERI_IP 0x1074
> +#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART 0x1078
> +#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x1820
> +#define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1824
> +#define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828
> +#define CLK_CON_DIV_CLKCMU_CORE_SSS 0x182c
> +#define CLK_CON_DIV_CLKCMU_DPU 0x1840
> +#define CLK_CON_DIV_CLKCMU_HSI_BUS 0x1848
> +#define CLK_CON_DIV_CLKCMU_HSI_MMC_CARD 0x184c
> +#define CLK_CON_DIV_CLKCMU_HSI_USB20DRD 0x1850
> +#define CLK_CON_DIV_CLKCMU_PERI_BUS 0x187c
> +#define CLK_CON_DIV_CLKCMU_PERI_IP 0x1880
> +#define CLK_CON_DIV_CLKCMU_PERI_UART 0x1884
> +#define CLK_CON_DIV_PLL_SHARED0_DIV2 0x188c
> +#define CLK_CON_DIV_PLL_SHARED0_DIV3 0x1890
> +#define CLK_CON_DIV_PLL_SHARED0_DIV4 0x1894
> +#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x1898
> +#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x189c
> +#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18a0
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x201c
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_SSS 0x2028
> +#define CLK_CON_GAT_GATE_CLKCMU_DPU 0x203c
> +#define CLK_CON_GAT_GATE_CLKCMU_HSI_BUS 0x2044
> +#define CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD 0x2048
> +#define CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD 0x204c
> +#define CLK_CON_GAT_GATE_CLKCMU_PERI_BUS 0x2080
> +#define CLK_CON_GAT_GATE_CLKCMU_PERI_IP 0x2084
> +#define CLK_CON_GAT_GATE_CLKCMU_PERI_UART 0x2088
> +
> +static const unsigned long top_clk_regs[] __initconst = {
> + PLL_LOCKTIME_PLL_MMC,
> + PLL_LOCKTIME_PLL_SHARED0,
> + PLL_LOCKTIME_PLL_SHARED1,
> + PLL_CON0_PLL_MMC,
> + PLL_CON3_PLL_MMC,
> + PLL_CON0_PLL_SHARED0,
> + PLL_CON3_PLL_SHARED0,
> + PLL_CON0_PLL_SHARED1,
> + PLL_CON3_PLL_SHARED1,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_CCI,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_SSS,
> + CLK_CON_MUX_MUX_CLKCMU_DPU,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_BUS,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_BUS,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_IP,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_UART,
> + CLK_CON_DIV_CLKCMU_CORE_BUS,
> + CLK_CON_DIV_CLKCMU_CORE_CCI,
> + CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD,
> + CLK_CON_DIV_CLKCMU_CORE_SSS,
> + CLK_CON_DIV_CLKCMU_DPU,
> + CLK_CON_DIV_CLKCMU_HSI_BUS,
> + CLK_CON_DIV_CLKCMU_HSI_MMC_CARD,
> + CLK_CON_DIV_CLKCMU_HSI_USB20DRD,
> + CLK_CON_DIV_CLKCMU_PERI_BUS,
> + CLK_CON_DIV_CLKCMU_PERI_IP,
> + CLK_CON_DIV_CLKCMU_PERI_UART,
> + CLK_CON_DIV_PLL_SHARED0_DIV2,
> + CLK_CON_DIV_PLL_SHARED0_DIV3,
> + CLK_CON_DIV_PLL_SHARED0_DIV4,
> + CLK_CON_DIV_PLL_SHARED1_DIV2,
> + CLK_CON_DIV_PLL_SHARED1_DIV3,
> + CLK_CON_DIV_PLL_SHARED1_DIV4,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_CCI,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_SSS,
> + CLK_CON_GAT_GATE_CLKCMU_DPU,
> + CLK_CON_GAT_GATE_CLKCMU_HSI_BUS,
> + CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD,
> + CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD,
> + CLK_CON_GAT_GATE_CLKCMU_PERI_BUS,
> + CLK_CON_GAT_GATE_CLKCMU_PERI_IP,
> + CLK_CON_GAT_GATE_CLKCMU_PERI_UART,
> +};
> +
> +/*
> + * Do not provide PLL tables to core PLLs, as MANUAL_PLL_CTRL bit is not set
> + * for those PLLs by default, so set_rate operation would fail.
> + */
> +static const struct samsung_pll_clock top_pll_clks[] __initconst = {
> + /* CMU_TOP_PURECLKCOMP */
> + PLL(pll_0822x, CLK_FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk",
> + PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0,
> + NULL),
> + PLL(pll_0822x, CLK_FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk",
> + PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1,
> + NULL),
> + PLL(pll_0831x, CLK_FOUT_MMC_PLL, "fout_mmc_pll", "oscclk",
> + PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, NULL),
> +};
> +
> +/* List of parent clocks for Muxes in CMU_TOP */
> +PNAME(mout_shared0_pll_p) = { "oscclk", "fout_shared0_pll" };
> +PNAME(mout_shared1_pll_p) = { "oscclk", "fout_shared1_pll" };
> +PNAME(mout_mmc_pll_p) = { "oscclk", "fout_mmc_pll" };
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_CORE */
> +PNAME(mout_core_bus_p) = { "dout_shared1_div2", "dout_shared0_div3",
> + "dout_shared1_div3", "dout_shared0_div4" };
> +PNAME(mout_core_cci_p) = { "dout_shared0_div2", "dout_shared1_div2",
> + "dout_shared0_div3", "dout_shared1_div3" };
> +PNAME(mout_core_mmc_embd_p) = { "oscclk", "dout_shared0_div2",
> + "dout_shared1_div2", "dout_shared0_div3",
> + "dout_shared1_div3", "mout_mmc_pll",
> + "oscclk", "oscclk" };
> +PNAME(mout_core_sss_p) = { "dout_shared0_div3", "dout_shared1_div3",
> + "dout_shared0_div4", "dout_shared1_div4" };
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_HSI */
> +PNAME(mout_hsi_bus_p) = { "dout_shared0_div2", "dout_shared1_div2" };
> +PNAME(mout_hsi_mmc_card_p) = { "oscclk", "dout_shared0_div2",
> + "dout_shared1_div2", "dout_shared0_div3",
> + "dout_shared1_div3", "mout_mmc_pll",
> + "oscclk", "oscclk" };
> +PNAME(mout_hsi_usb20drd_p) = { "oscclk", "dout_shared0_div4",
> + "dout_shared1_div4", "oscclk" };
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_PERI */
> +PNAME(mout_peri_bus_p) = { "dout_shared0_div4", "dout_shared1_div4" };
> +PNAME(mout_peri_uart_p) = { "oscclk", "dout_shared0_div4",
> + "dout_shared1_div4", "oscclk" };
> +PNAME(mout_peri_ip_p) = { "oscclk", "dout_shared0_div4",
> + "dout_shared1_div4", "oscclk" };
> +
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_DPU */
> +PNAME(mout_dpu_p) = { "dout_shared0_div3", "dout_shared1_div3",
> + "dout_shared0_div4", "dout_shared1_div4" };
> +
> +static const struct samsung_mux_clock top_mux_clks[] __initconst = {
> + /* CMU_TOP_PURECLKCOMP */
> + MUX(CLK_MOUT_SHARED0_PLL, "mout_shared0_pll", mout_shared0_pll_p,
> + PLL_CON0_PLL_SHARED0, 4, 1),
> + MUX(CLK_MOUT_SHARED1_PLL, "mout_shared1_pll", mout_shared1_pll_p,
> + PLL_CON0_PLL_SHARED1, 4, 1),
> + MUX(CLK_MOUT_MMC_PLL, "mout_mmc_pll", mout_mmc_pll_p,
> + PLL_CON0_PLL_MMC, 4, 1),
> +
> + /* CORE */
> + MUX(CLK_MOUT_CORE_BUS, "mout_core_bus", mout_core_bus_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 2),
> + MUX(CLK_MOUT_CORE_CCI, "mout_core_cci", mout_core_cci_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, 0, 2),
> + MUX(CLK_MOUT_CORE_MMC_EMBD, "mout_core_mmc_embd", mout_core_mmc_embd_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD, 0, 3),
> + MUX(CLK_MOUT_CORE_SSS, "mout_core_sss", mout_core_sss_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, 0, 2),
> +
> + /* DPU */
> + MUX(CLK_MOUT_DPU, "mout_dpu", mout_dpu_p,
> + CLK_CON_MUX_MUX_CLKCMU_DPU, 0, 2),
> +
> + /* HSI */
> + MUX(CLK_MOUT_HSI_BUS, "mout_hsi_bus", mout_hsi_bus_p,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, 0, 1),
> + MUX(CLK_MOUT_HSI_MMC_CARD, "mout_hsi_mmc_card", mout_hsi_mmc_card_p,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD, 0, 3),
> + MUX(CLK_MOUT_HSI_USB20DRD, "mout_hsi_usb20drd", mout_hsi_usb20drd_p,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD, 0, 2),
> +
> + /* PERI */
> + MUX(CLK_MOUT_PERI_BUS, "mout_peri_bus", mout_peri_bus_p,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_BUS, 0, 1),
> + MUX(CLK_MOUT_PERI_UART, "mout_peri_uart", mout_peri_uart_p,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_UART, 0, 2),
> + MUX(CLK_MOUT_PERI_IP, "mout_peri_ip", mout_peri_ip_p,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_IP, 0, 2),
> +};
> +
> +static const struct samsung_div_clock top_div_clks[] __initconst = {
> + /* CMU_TOP_PURECLKCOMP */
> + DIV(CLK_DOUT_SHARED0_DIV3, "dout_shared0_div3", "mout_shared0_pll",
> + CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2),
> + DIV(CLK_DOUT_SHARED0_DIV2, "dout_shared0_div2", "mout_shared0_pll",
> + CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1),
> + DIV(CLK_DOUT_SHARED1_DIV3, "dout_shared1_div3", "mout_shared1_pll",
> + CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2),
> + DIV(CLK_DOUT_SHARED1_DIV2, "dout_shared1_div2", "mout_shared1_pll",
> + CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1),
> + DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "dout_shared0_div2",
> + CLK_CON_DIV_PLL_SHARED0_DIV4, 0, 1),
> + DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2",
> + CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1),
> +
> + /* CORE */
> + DIV(CLK_DOUT_CORE_BUS, "dout_core_bus", "gout_core_bus",
> + CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4),
> + DIV(CLK_DOUT_CORE_CCI, "dout_core_cci", "gout_core_cci",
> + CLK_CON_DIV_CLKCMU_CORE_CCI, 0, 4),
> + DIV(CLK_DOUT_CORE_MMC_EMBD, "dout_core_mmc_embd", "gout_core_mmc_embd",
> + CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD, 0, 9),
> + DIV(CLK_DOUT_CORE_SSS, "dout_core_sss", "gout_core_sss",
> + CLK_CON_DIV_CLKCMU_CORE_SSS, 0, 4),
> +
> + /* DPU */
> + DIV(CLK_DOUT_DPU, "dout_dpu", "gout_dpu",
> + CLK_CON_DIV_CLKCMU_DPU, 0, 4),
> +
> + /* HSI */
> + DIV(CLK_DOUT_HSI_BUS, "dout_hsi_bus", "gout_hsi_bus",
> + CLK_CON_DIV_CLKCMU_HSI_BUS, 0, 4),
> + DIV(CLK_DOUT_HSI_MMC_CARD, "dout_hsi_mmc_card", "gout_hsi_mmc_card",
> + CLK_CON_DIV_CLKCMU_HSI_MMC_CARD, 0, 9),
> + DIV(CLK_DOUT_HSI_USB20DRD, "dout_hsi_usb20drd", "gout_hsi_usb20drd",
> + CLK_CON_DIV_CLKCMU_HSI_USB20DRD, 0, 4),
> +
> + /* PERI */
> + DIV(CLK_DOUT_PERI_BUS, "dout_peri_bus", "gout_peri_bus",
> + CLK_CON_DIV_CLKCMU_PERI_BUS, 0, 4),
> + DIV(CLK_DOUT_PERI_UART, "dout_peri_uart", "gout_peri_uart",
> + CLK_CON_DIV_CLKCMU_PERI_UART, 0, 4),
> + DIV(CLK_DOUT_PERI_IP, "dout_peri_ip", "gout_peri_ip",
> + CLK_CON_DIV_CLKCMU_PERI_IP, 0, 4),
> +};
> +
> +static const struct samsung_gate_clock top_gate_clks[] __initconst = {
> + /* CORE */
> + GATE(CLK_GOUT_CORE_BUS, "gout_core_bus", "mout_core_bus",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, 21, 0, 0),
> + GATE(CLK_GOUT_CORE_CCI, "gout_core_cci", "mout_core_cci",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, 21, 0, 0),
> + GATE(CLK_GOUT_CORE_MMC_EMBD, "gout_core_mmc_embd", "mout_core_mmc_embd",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD, 21, 0, 0),
> + GATE(CLK_GOUT_CORE_SSS, "gout_core_sss", "mout_core_sss",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, 21, 0, 0),
> +
> + /* DPU */
> + GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu",
> + CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0),
> +
> + /* HSI */
> + GATE(CLK_GOUT_HSI_BUS, "gout_hsi_bus", "mout_hsi_bus",
> + CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, 21, 0, 0),
> + GATE(CLK_GOUT_HSI_MMC_CARD, "gout_hsi_mmc_card", "mout_hsi_mmc_card",
> + CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD, 21, 0, 0),
> + GATE(CLK_GOUT_HSI_USB20DRD, "gout_hsi_usb20drd", "mout_hsi_usb20drd",
> + CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD, 21, 0, 0),
> +
> + /* PERI */
> + GATE(CLK_GOUT_PERI_BUS, "gout_peri_bus", "mout_peri_bus",
> + CLK_CON_GAT_GATE_CLKCMU_PERI_BUS, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_UART, "gout_peri_uart", "mout_peri_uart",
> + CLK_CON_GAT_GATE_CLKCMU_PERI_UART, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_IP, "gout_peri_ip", "mout_peri_ip",
> + CLK_CON_GAT_GATE_CLKCMU_PERI_IP, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info top_cmu_info __initconst = {
> + .pll_clks = top_pll_clks,
> + .nr_pll_clks = ARRAY_SIZE(top_pll_clks),
> + .mux_clks = top_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(top_mux_clks),
> + .div_clks = top_div_clks,
> + .nr_div_clks = ARRAY_SIZE(top_div_clks),
> + .gate_clks = top_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(top_gate_clks),
> + .nr_clk_ids = TOP_NR_CLK,
> + .clk_regs = top_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(top_clk_regs),
> +};
> +
> +static void __init exynos850_cmu_top_init(struct device_node *np)
> +{
> + exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs));
> + samsung_cmu_register_one(np, &top_cmu_info);
> +}
> +
> +CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top",
> + exynos850_cmu_top_init);
> +
> +/* ---- CMU_HSI ------------------------------------------------------------- */
> +
> +/* Register Offset definitions for CMU_HSI (0x13400000) */
> +#define PLL_CON0_MUX_CLKCMU_HSI_BUS_USER 0x0600
> +#define PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER 0x0610
> +#define PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER 0x0620
> +#define CLK_CON_MUX_MUX_CLK_HSI_RTC 0x1000
> +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV 0x2008
> +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50 0x200c
> +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26 0x2010
> +#define CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK 0x2018
> +#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK 0x2024
> +#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN 0x2028
> +#define CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK 0x2038
> +#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20 0x203c
> +#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY 0x2040
> +
> +static const unsigned long hsi_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_HSI_BUS_USER,
> + PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
> + PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
> + CLK_CON_MUX_MUX_CLK_HSI_RTC,
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV,
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50,
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26,
> + CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK,
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK,
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN,
> + CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK,
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20,
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_PERI */
> +PNAME(mout_hsi_bus_user_p) = { "oscclk", "dout_hsi_bus" };
> +PNAME(mout_hsi_mmc_card_user_p) = { "oscclk", "dout_hsi_mmc_card" };
> +PNAME(mout_hsi_usb20drd_user_p) = { "oscclk", "dout_hsi_usb20drd" };
> +PNAME(mout_hsi_rtc_p) = { "rtcclk", "oscclk" };
> +
> +static const struct samsung_mux_clock hsi_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_HSI_BUS_USER, "mout_hsi_bus_user", mout_hsi_bus_user_p,
> + PLL_CON0_MUX_CLKCMU_HSI_BUS_USER, 4, 1),
> + MUX_F(CLK_MOUT_HSI_MMC_CARD_USER, "mout_hsi_mmc_card_user",
> + mout_hsi_mmc_card_user_p, PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
> + 4, 1, CLK_SET_RATE_PARENT, 0),
> + MUX(CLK_MOUT_HSI_USB20DRD_USER, "mout_hsi_usb20drd_user",
> + mout_hsi_usb20drd_user_p, PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
> + 4, 1),
> + MUX(CLK_MOUT_HSI_RTC, "mout_hsi_rtc", mout_hsi_rtc_p,
> + CLK_CON_MUX_MUX_CLK_HSI_RTC, 0, 1),
> +};
> +
> +static const struct samsung_gate_clock hsi_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_USB_RTC_CLK, "gout_usb_rtc", "mout_hsi_rtc",
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV, 21, 0, 0),
> + GATE(CLK_GOUT_USB_REF_CLK, "gout_usb_ref", "mout_hsi_usb20drd_user",
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50, 21, 0, 0),
> + GATE(CLK_GOUT_USB_PHY_REF_CLK, "gout_usb_phy_ref", "oscclk",
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26, 21, 0, 0),
> + GATE(CLK_GOUT_GPIO_HSI_PCLK, "gout_gpio_hsi_pclk", "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_CARD_ACLK, "gout_mmc_card_aclk", "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_CARD_SDCLKIN, "gout_mmc_card_sdclkin",
> + "mout_hsi_mmc_card_user",
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN, 21, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_GOUT_SYSREG_HSI_PCLK, "gout_sysreg_hsi_pclk",
> + "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_USB_PHY_ACLK, "gout_usb_phy_aclk", "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20, 21, 0, 0),
> + GATE(CLK_GOUT_USB_BUS_EARLY_CLK, "gout_usb_bus_early",
> + "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info hsi_cmu_info __initconst = {
> + .mux_clks = hsi_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(hsi_mux_clks),
> + .gate_clks = hsi_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(hsi_gate_clks),
> + .nr_clk_ids = HSI_NR_CLK,
> + .clk_regs = hsi_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(hsi_clk_regs),
> + .clk_name = "dout_hsi_bus",
> +};
> +
> +/* ---- CMU_PERI ------------------------------------------------------------ */
> +
> +/* Register Offset definitions for CMU_PERI (0x10030000) */
> +#define PLL_CON0_MUX_CLKCMU_PERI_BUS_USER 0x0600
> +#define PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER 0x0610
> +#define PLL_CON0_MUX_CLKCMU_PERI_SPI_USER 0x0620
> +#define PLL_CON0_MUX_CLKCMU_PERI_UART_USER 0x0630
> +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0 0x1800
> +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1 0x1804
> +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2 0x1808
> +#define CLK_CON_DIV_DIV_CLK_PERI_SPI_0 0x180c
> +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0 0x200c
> +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1 0x2010
> +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2 0x2014
> +#define CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK 0x2020
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK 0x2024
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK 0x2028
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK 0x202c
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK 0x2030
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK 0x2034
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK 0x2038
> +#define CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK 0x203c
> +#define CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK 0x2040
> +#define CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK 0x2044
> +#define CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK 0x2048
> +#define CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK 0x204c
> +#define CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK 0x2050
> +#define CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK 0x2054
> +#define CLK_CON_GAT_GOUT_PERI_MCT_PCLK 0x205c
> +#define CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK 0x2064
> +#define CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK 0x209c
> +#define CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK 0x20a0
> +#define CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK 0x20a4
> +#define CLK_CON_GAT_GOUT_PERI_UART_IPCLK 0x20a8
> +#define CLK_CON_GAT_GOUT_PERI_UART_PCLK 0x20ac
> +#define CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK 0x20b0
> +#define CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK 0x20b4
> +
> +static const unsigned long peri_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_PERI_BUS_USER,
> + PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER,
> + PLL_CON0_MUX_CLKCMU_PERI_SPI_USER,
> + PLL_CON0_MUX_CLKCMU_PERI_UART_USER,
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0,
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1,
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2,
> + CLK_CON_DIV_DIV_CLK_PERI_SPI_0,
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0,
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1,
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2,
> + CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK,
> + CLK_CON_GAT_GOUT_PERI_MCT_PCLK,
> + CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK,
> + CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK,
> + CLK_CON_GAT_GOUT_PERI_UART_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_UART_PCLK,
> + CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_PERI */
> +PNAME(mout_peri_bus_user_p) = { "oscclk", "dout_peri_bus" };
> +PNAME(mout_peri_uart_user_p) = { "oscclk", "dout_peri_uart" };
> +PNAME(mout_peri_hsi2c_user_p) = { "oscclk", "dout_peri_ip" };
> +PNAME(mout_peri_spi_user_p) = { "oscclk", "dout_peri_ip" };
> +
> +static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_PERI_BUS_USER, "mout_peri_bus_user", mout_peri_bus_user_p,
> + PLL_CON0_MUX_CLKCMU_PERI_BUS_USER, 4, 1),
> + MUX(CLK_MOUT_PERI_UART_USER, "mout_peri_uart_user",
> + mout_peri_uart_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART_USER, 4, 1),
> + MUX(CLK_MOUT_PERI_HSI2C_USER, "mout_peri_hsi2c_user",
> + mout_peri_hsi2c_user_p, PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, 4, 1),
> + MUX(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user", mout_peri_spi_user_p,
> + PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1),
> +};
> +
> +static const struct samsung_div_clock peri_div_clks[] __initconst = {
> + DIV(CLK_DOUT_PERI_HSI2C0, "dout_peri_hsi2c0", "gout_peri_hsi2c0",
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0, 0, 5),
> + DIV(CLK_DOUT_PERI_HSI2C1, "dout_peri_hsi2c1", "gout_peri_hsi2c1",
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, 0, 5),
> + DIV(CLK_DOUT_PERI_HSI2C2, "dout_peri_hsi2c2", "gout_peri_hsi2c2",
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, 0, 5),
> + DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
> + CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5),
> +};
> +
> +static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_PERI_HSI2C0, "gout_peri_hsi2c0", "mout_peri_hsi2c_user",
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_HSI2C1, "gout_peri_hsi2c1", "mout_peri_hsi2c_user",
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_HSI2C2, "gout_peri_hsi2c2", "mout_peri_hsi2c_user",
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C0_IPCLK, "gout_hsi2c0_ipclk", "dout_peri_hsi2c0",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C0_PCLK, "gout_hsi2c0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C1_IPCLK, "gout_hsi2c1_ipclk", "dout_peri_hsi2c1",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C1_PCLK, "gout_hsi2c1_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C2_IPCLK, "gout_hsi2c2_ipclk", "dout_peri_hsi2c2",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C2_PCLK, "gout_hsi2c2_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C0_PCLK, "gout_i2c0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C1_PCLK, "gout_i2c1_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C2_PCLK, "gout_i2c2_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C3_PCLK, "gout_i2c3_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C4_PCLK, "gout_i2c4_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C5_PCLK, "gout_i2c5_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C6_PCLK, "gout_i2c6_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_MCT_PCLK, "gout_mct_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_MCT_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_PWM_MOTOR_PCLK, "gout_pwm_motor_pclk",
> + "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_SPI0_IPCLK, "gout_spi0_ipclk", "dout_peri_spi0",
> + CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk",
> + "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_UART_IPCLK, "gout_uart_ipclk", "mout_peri_uart_user",
> + CLK_CON_GAT_GOUT_PERI_UART_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_UART_PCLK, "gout_uart_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_UART_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_WDT0_PCLK, "gout_wdt0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_WDT1_PCLK, "gout_wdt1_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_GPIO_PERI_PCLK, "gout_gpio_peri_pclk",
> + "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info peri_cmu_info __initconst = {
> + .mux_clks = peri_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(peri_mux_clks),
> + .div_clks = peri_div_clks,
> + .nr_div_clks = ARRAY_SIZE(peri_div_clks),
> + .gate_clks = peri_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(peri_gate_clks),
> + .nr_clk_ids = PERI_NR_CLK,
> + .clk_regs = peri_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(peri_clk_regs),
> + .clk_name = "dout_peri_bus",
> +};
> +
> +/* ---- CMU_CORE ------------------------------------------------------------ */
> +
> +/* Register Offset definitions for CMU_CORE (0x12000000) */
> +#define PLL_CON0_MUX_CLKCMU_CORE_BUS_USER 0x0600
> +#define PLL_CON0_MUX_CLKCMU_CORE_CCI_USER 0x0610
> +#define PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER 0x0620
> +#define PLL_CON0_MUX_CLKCMU_CORE_SSS_USER 0x0630
> +#define CLK_CON_MUX_MUX_CLK_CORE_GIC 0x1000
> +#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800
> +#define CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK 0x2038
> +#define CLK_CON_GAT_GOUT_CORE_GIC_CLK 0x2040
> +#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK 0x20e8
> +#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN 0x20ec
> +#define CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK 0x2128
> +#define CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK 0x212c
> +
> +static const unsigned long core_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER,
> + PLL_CON0_MUX_CLKCMU_CORE_CCI_USER,
> + PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER,
> + PLL_CON0_MUX_CLKCMU_CORE_SSS_USER,
> + CLK_CON_MUX_MUX_CLK_CORE_GIC,
> + CLK_CON_DIV_DIV_CLK_CORE_BUSP,
> + CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK,
> + CLK_CON_GAT_GOUT_CORE_GIC_CLK,
> + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK,
> + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
> + CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK,
> + CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_CORE */
> +PNAME(mout_core_bus_user_p) = { "oscclk", "dout_core_bus" };
> +PNAME(mout_core_cci_user_p) = { "oscclk", "dout_core_cci" };
> +PNAME(mout_core_mmc_embd_user_p) = { "oscclk", "dout_core_mmc_embd" };
> +PNAME(mout_core_sss_user_p) = { "oscclk", "dout_core_sss" };
> +PNAME(mout_core_gic_p) = { "dout_core_busp", "oscclk" };
> +
> +static const struct samsung_mux_clock core_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_CORE_BUS_USER, "mout_core_bus_user", mout_core_bus_user_p,
> + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, 4, 1),
> + MUX(CLK_MOUT_CORE_CCI_USER, "mout_core_cci_user", mout_core_cci_user_p,
> + PLL_CON0_MUX_CLKCMU_CORE_CCI_USER, 4, 1),
> + MUX_F(CLK_MOUT_CORE_MMC_EMBD_USER, "mout_core_mmc_embd_user",
> + mout_core_mmc_embd_user_p, PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER,
> + 4, 1, CLK_SET_RATE_PARENT, 0),
> + MUX(CLK_MOUT_CORE_SSS_USER, "mout_core_sss_user", mout_core_sss_user_p,
> + PLL_CON0_MUX_CLKCMU_CORE_SSS_USER, 4, 1),
> + MUX(CLK_MOUT_CORE_GIC, "mout_core_gic", mout_core_gic_p,
> + CLK_CON_MUX_MUX_CLK_CORE_GIC, 0, 1),
> +};
> +
> +static const struct samsung_div_clock core_div_clks[] __initconst = {
> + DIV(CLK_DOUT_CORE_BUSP, "dout_core_busp", "mout_core_bus_user",
> + CLK_CON_DIV_DIV_CLK_CORE_BUSP, 0, 2),
> +};
> +
> +static const struct samsung_gate_clock core_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_CCI_ACLK, "gout_cci_aclk", "mout_core_cci_user",
> + CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_GIC_CLK, "gout_gic_clk", "mout_core_gic",
> + CLK_CON_GAT_GOUT_CORE_GIC_CLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_EMBD_ACLK, "gout_mmc_embd_aclk", "dout_core_busp",
> + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_EMBD_SDCLKIN, "gout_mmc_embd_sdclkin",
> + "mout_core_mmc_embd_user", CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
> + 21, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_GOUT_SSS_ACLK, "gout_sss_aclk", "mout_core_sss_user",
> + CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_SSS_PCLK, "gout_sss_pclk", "dout_core_busp",
> + CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info core_cmu_info __initconst = {
> + .mux_clks = core_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(core_mux_clks),
> + .div_clks = core_div_clks,
> + .nr_div_clks = ARRAY_SIZE(core_div_clks),
> + .gate_clks = core_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(core_gate_clks),
> + .nr_clk_ids = CORE_NR_CLK,
> + .clk_regs = core_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(core_clk_regs),
> + .clk_name = "dout_core_bus",
> +};
> +
> +/* ---- CMU_DPU ------------------------------------------------------------- */
> +
> +/* Register Offset definitions for CMU_DPU (0x13000000) */
> +#define PLL_CON0_MUX_CLKCMU_DPU_USER 0x0600
> +#define CLK_CON_DIV_DIV_CLK_DPU_BUSP 0x1800
> +#define CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK 0x2004
> +#define CLK_CON_GAT_GOUT_DPU_ACLK_DECON0 0x2010
> +#define CLK_CON_GAT_GOUT_DPU_ACLK_DMA 0x2014
> +#define CLK_CON_GAT_GOUT_DPU_ACLK_DPP 0x2018
> +#define CLK_CON_GAT_GOUT_DPU_PPMU_ACLK 0x2028
> +#define CLK_CON_GAT_GOUT_DPU_PPMU_PCLK 0x202c
> +#define CLK_CON_GAT_GOUT_DPU_SMMU_CLK 0x2038
> +#define CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK 0x203c
> +
> +static const unsigned long dpu_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_DPU_USER,
> + CLK_CON_DIV_DIV_CLK_DPU_BUSP,
> + CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK,
> + CLK_CON_GAT_GOUT_DPU_ACLK_DECON0,
> + CLK_CON_GAT_GOUT_DPU_ACLK_DMA,
> + CLK_CON_GAT_GOUT_DPU_ACLK_DPP,
> + CLK_CON_GAT_GOUT_DPU_PPMU_ACLK,
> + CLK_CON_GAT_GOUT_DPU_PPMU_PCLK,
> + CLK_CON_GAT_GOUT_DPU_SMMU_CLK,
> + CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_CORE */
> +PNAME(mout_dpu_user_p) = { "oscclk", "dout_dpu" };
> +
> +static const struct samsung_mux_clock dpu_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_DPU_USER, "mout_dpu_user", mout_dpu_user_p,
> + PLL_CON0_MUX_CLKCMU_DPU_USER, 4, 1),
> +};
> +
> +static const struct samsung_div_clock dpu_div_clks[] __initconst = {
> + DIV(CLK_DOUT_DPU_BUSP, "dout_dpu_busp", "mout_dpu_user",
> + CLK_CON_DIV_DIV_CLK_DPU_BUSP, 0, 3),
> +};
> +
> +static const struct samsung_gate_clock dpu_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_DPU_CMU_DPU_PCLK, "gout_dpu_cmu_dpu_pclk",
> + "dout_dpu_busp", CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_DECON0_ACLK, "gout_dpu_decon0_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_ACLK_DECON0, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_DMA_ACLK, "gout_dpu_dma_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_ACLK_DMA, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_DPP_ACLK, "gout_dpu_dpp_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_ACLK_DPP, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_PPMU_ACLK, "gout_dpu_ppmu_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_PPMU_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_PPMU_PCLK, "gout_dpu_ppmu_pclk", "dout_dpu_busp",
> + CLK_CON_GAT_GOUT_DPU_PPMU_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_SMMU_CLK, "gout_dpu_smmu_clk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_SMMU_CLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_SYSREG_PCLK, "gout_dpu_sysreg_pclk", "dout_dpu_busp",
> + CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info dpu_cmu_info __initconst = {
> + .mux_clks = dpu_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(dpu_mux_clks),
> + .div_clks = dpu_div_clks,
> + .nr_div_clks = ARRAY_SIZE(dpu_div_clks),
> + .gate_clks = dpu_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(dpu_gate_clks),
> + .nr_clk_ids = DPU_NR_CLK,
> + .clk_regs = dpu_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(dpu_clk_regs),
> + .clk_name = "dout_dpu",
> +};
> +
> +/* ---- platform_driver ----------------------------------------------------- */
> +
> +static int __init exynos850_cmu_probe(struct platform_device *pdev)
> +{
> + const struct samsung_cmu_info *info;
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> +
> + info = of_device_get_match_data(dev);
> + exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs);
> + samsung_cmu_register_one(np, info);
> +
> + /* Keep bus clock running, so it's possible to access CMU registers */
> + if (info->clk_name) {
> + struct clk *bus_clk;
> +
> + bus_clk = clk_get(dev, info->clk_name);
> + if (IS_ERR(bus_clk)) {
> + pr_err("%s: could not find bus clock %s; err = %ld\n",
> + __func__, info->clk_name, PTR_ERR(bus_clk));
> + } else {
> + clk_prepare_enable(bus_clk);
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* CMUs which belong to Power Domains and need runtime PM to be implemented */
> +static const struct of_device_id exynos850_cmu_of_match[] = {
> + {
> + .compatible = "samsung,exynos850-cmu-hsi",
> + .data = &hsi_cmu_info,
> + }, {
> + .compatible = "samsung,exynos850-cmu-peri",
> + .data = &peri_cmu_info,
> + }, {
> + .compatible = "samsung,exynos850-cmu-core",
> + .data = &core_cmu_info,
> + }, {
> + .compatible = "samsung,exynos850-cmu-dpu",
> + .data = &dpu_cmu_info,
> + }, {
> + },
> +};
> +
> +static struct platform_driver exynos850_cmu_driver __refdata = {
> + .driver = {
> + .name = "exynos850-cmu",
> + .of_match_table = exynos850_cmu_of_match,
> + .suppress_bind_attrs = true,
> + },
> + .probe = exynos850_cmu_probe,
> +};
> +
> +static int __init exynos850_cmu_init(void)
> +{
> + return platform_driver_register(&exynos850_cmu_driver);
> +}
> +core_initcall(exynos850_cmu_init);
> --
> 2.30.2
>

2021-10-12 08:18:10

by Sam Protsenko

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] dt-bindings: clock: Document Exynos850 CMU bindings

Hi Rob,

On Mon, 11 Oct 2021 at 13:42, Sylwester Nawrocki <[email protected]> wrote:
>
> On 11.10.2021 12:13, Sam Protsenko wrote:
> > On Sat, 9 Oct 2021 at 23:41, Sylwester Nawrocki <[email protected]> wrote:
> >>
> >> On 08.10.2021 17:43, Sam Protsenko wrote:
> >>> Provide dt-schema documentation for Exynos850 SoC clock controller.
> >>>
> >>> Signed-off-by: Sam Protsenko <[email protected]>
> >>> Reviewed-by: Krzysztof Kozlowski <[email protected]>
> >>> Acked-by: Chanwoo Choi <[email protected]>
> [...]
> >>> +++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
> >>> @@ -0,0 +1,185 @@
> [...]
> >>> +
> >>> +title: Samsung Exynos850 SoC clock controller
> >>> +
> >>> +maintainers:
> >>> + - Sam Protsenko <[email protected]>
> >>> + - Chanwoo Choi <[email protected]>
> >>> + - Krzysztof Kozlowski <[email protected]>
> >>> + - Sylwester Nawrocki <[email protected]>
> >>> + - Tomasz Figa <[email protected]>
> >>> +
> >>> +description: |
> >>> + Exynos850 clock controller is comprised of several CMU units, generating
> >>> + clocks for different domains. Those CMU units are modeled as separate device
> >>> + tree nodes, and might depend on each other. Root clocks in that clock tree are
> >>> + two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
> >>> + clocks must be defined as fixed-rate clocks in dts.
> >>> +
> >>> + CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
> >>> + dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
> >>> +
> >>> + Each clock is assigned an identifier and client nodes can use this identifier
> >>> + to specify the clock which they consume. All clocks that available for usage
> >>
> >> s/All clocks that available/All clocks available ?
> >> No need to resend, I can amend it when applying.
> >>
> >
> > Yeah, not a native speaker, I tend to do such mistakes sometimes :)
> > Please fix when applying.
> >
> > Btw, I can see that you already applied 3 out of 5 patches from this
> > patch series here: [1]. Can you please also apply the rest, or is
> > there any outstanding comments that I missed?
>
> The patches look good to me, I just wanted to allow some for Rob to have
> a look and provide an Ack.
>

Can you please review this one?

Thanks!

> Regards,
> --
> Sylwester Nawrocki
> Samsung R&D Institute Poland

2021-10-15 09:44:53

by Chanwoo Choi

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] clk: samsung: Introduce Exynos850 clock driver

On 10/9/21 12:43 AM, Sam Protsenko wrote:
> This is the initial implementation adding only basic clocks like UART,
> MMC, I2C and corresponding parent clocks. Design is influenced by
> Exynos5433 clock driver.
>
> Bus clock is enabled by default (in probe function) for all CMUs except
> CMU_TOP, the reasoning is as follows. By default if bus clock has no
> users its "enable count" value is 0. It might be actually running if
> it's already enabled in bootloader, but then in some cases it can be
> disabled by mistake. For example, such case was observed when
> dw_mci_probe() enabled the bus clock, then failed to do something and
> disabled that bus clock on error path. After that, even the attempt to
> read the 'clk_summary' file in DebugFS freezed forever, as CMU bus clock
> ended up being disabled and it wasn't possible to access CMU registers
> anymore.
>
> To avoid such cases, CMU driver must increment the ref count for that
> bus clock by running clk_prepare_enable(). There is already existing
> '.clk_name' field in struct samsung_cmu_info, exactly for that reason.
> It was added in commit 523d3de41f02 ("clk: samsung: exynos5433: Add
> support for runtime PM"), with next mentioning in commit message:
>
> > Also for each CMU there is one special parent clock, which has to be
> > enabled all the time when any access to CMU registers is being done.
>
> But that clock is actually only enabled in Exynos5433 clock driver right
> now. So the same code is added to exynos850_cmu_probe() function,
> As was described above, it might be helpful not only for PM reasons, but
> also to prevent possible erroneous clock gating on error paths.
>
> Another way to workaround that issue would be to use CLOCK_IS_CRITICAL
> flag for corresponding gate clocks. But that might be not very good
> design decision, as we might still want to disable that bus clock, e.g.
> on PM suspend.
>
> Signed-off-by: Sam Protsenko <[email protected]>
> Reviewed-by: Krzysztof Kozlowski <[email protected]>
> ---
> Changes in v3:
> - Added R-b tag by Krzysztof Kozlowski
>
> Changes in v2:
> - Used of_iomap() for the whole CMU range instead of ioremap() in
> exynos850_init_clocks()
> - Used readl/writel functions in exynos850_init_clocks() for consistency
> with other drivers
> - Added all clock ids
> - Added CMU_DPU
> - Implemented platform_driver for all Power Domain capable CMUs
> - Moved bus clock enablement code here to probe function
> - Used clk_get() instead of __clk_lookup()
>
> drivers/clk/samsung/Makefile | 1 +
> drivers/clk/samsung/clk-exynos850.c | 835 ++++++++++++++++++++++++++++
> 2 files changed, 836 insertions(+)
> create mode 100644 drivers/clk/samsung/clk-exynos850.c
>
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> index 028b2e27a37e..c46cf11e4d0b 100644
> --- a/drivers/clk/samsung/Makefile
> +++ b/drivers/clk/samsung/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
> obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
> obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o
> obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
> +obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o
> obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
> obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
> obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
> diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
> new file mode 100644
> index 000000000000..2294989e244c
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos850.c
> @@ -0,0 +1,835 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2021 Linaro Ltd.
> + * Author: Sam Protsenko <[email protected]>
> + *
> + * Common Clock Framework support for Exynos850 SoC.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +
> +#include <dt-bindings/clock/exynos850.h>
> +
> +#include "clk.h"
> +
> +/* Gate register bits */
> +#define GATE_MANUAL BIT(20)
> +#define GATE_ENABLE_HWACG BIT(28)
> +
> +/* Gate register offsets range */
> +#define GATE_OFF_START 0x2000
> +#define GATE_OFF_END 0x2fff
> +
> +/**
> + * exynos850_init_clocks - Set clocks initial configuration
> + * @np: CMU device tree node with "reg" property (CMU addr)
> + * @reg_offs: Register offsets array for clocks to init
> + * @reg_offs_len: Number of register offsets in reg_offs array
> + *
> + * Set manual control mode for all gate clocks.
> + */
> +static void __init exynos850_init_clocks(struct device_node *np,
> + const unsigned long *reg_offs, size_t reg_offs_len)
> +{
> + void __iomem *reg_base;
> + size_t i;
> +
> + reg_base = of_iomap(np, 0);
> + if (!reg_base)
> + panic("%s: failed to map registers\n", __func__);
> +
> + for (i = 0; i < reg_offs_len; ++i) {
> + void __iomem *reg = reg_base + reg_offs[i];
> + u32 val;
> +
> + /* Modify only gate clock registers */
> + if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END)
> + continue;
> +
> + val = readl(reg);
> + val |= GATE_MANUAL;
> + val &= ~GATE_ENABLE_HWACG;
> + writel(val, reg);
> + }
> +
> + iounmap(reg_base);
> +}
> +
> +/* ---- CMU_TOP ------------------------------------------------------------- */
> +
> +/* Register Offset definitions for CMU_TOP (0x120e0000) */
> +#define PLL_LOCKTIME_PLL_MMC 0x0000
> +#define PLL_LOCKTIME_PLL_SHARED0 0x0004
> +#define PLL_LOCKTIME_PLL_SHARED1 0x0008
> +#define PLL_CON0_PLL_MMC 0x0100
> +#define PLL_CON3_PLL_MMC 0x010c
> +#define PLL_CON0_PLL_SHARED0 0x0140
> +#define PLL_CON3_PLL_SHARED0 0x014c
> +#define PLL_CON0_PLL_SHARED1 0x0180
> +#define PLL_CON3_PLL_SHARED1 0x018c
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1014
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c
> +#define CLK_CON_MUX_MUX_CLKCMU_CORE_SSS 0x1020
> +#define CLK_CON_MUX_MUX_CLKCMU_DPU 0x1034
> +#define CLK_CON_MUX_MUX_CLKCMU_HSI_BUS 0x103c
> +#define CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD 0x1040
> +#define CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD 0x1044
> +#define CLK_CON_MUX_MUX_CLKCMU_PERI_BUS 0x1070
> +#define CLK_CON_MUX_MUX_CLKCMU_PERI_IP 0x1074
> +#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART 0x1078
> +#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x1820
> +#define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1824
> +#define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828
> +#define CLK_CON_DIV_CLKCMU_CORE_SSS 0x182c
> +#define CLK_CON_DIV_CLKCMU_DPU 0x1840
> +#define CLK_CON_DIV_CLKCMU_HSI_BUS 0x1848
> +#define CLK_CON_DIV_CLKCMU_HSI_MMC_CARD 0x184c
> +#define CLK_CON_DIV_CLKCMU_HSI_USB20DRD 0x1850
> +#define CLK_CON_DIV_CLKCMU_PERI_BUS 0x187c
> +#define CLK_CON_DIV_CLKCMU_PERI_IP 0x1880
> +#define CLK_CON_DIV_CLKCMU_PERI_UART 0x1884
> +#define CLK_CON_DIV_PLL_SHARED0_DIV2 0x188c
> +#define CLK_CON_DIV_PLL_SHARED0_DIV3 0x1890
> +#define CLK_CON_DIV_PLL_SHARED0_DIV4 0x1894
> +#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x1898
> +#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x189c
> +#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18a0
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x201c
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024
> +#define CLK_CON_GAT_GATE_CLKCMU_CORE_SSS 0x2028
> +#define CLK_CON_GAT_GATE_CLKCMU_DPU 0x203c
> +#define CLK_CON_GAT_GATE_CLKCMU_HSI_BUS 0x2044
> +#define CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD 0x2048
> +#define CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD 0x204c
> +#define CLK_CON_GAT_GATE_CLKCMU_PERI_BUS 0x2080
> +#define CLK_CON_GAT_GATE_CLKCMU_PERI_IP 0x2084
> +#define CLK_CON_GAT_GATE_CLKCMU_PERI_UART 0x2088
> +
> +static const unsigned long top_clk_regs[] __initconst = {
> + PLL_LOCKTIME_PLL_MMC,
> + PLL_LOCKTIME_PLL_SHARED0,
> + PLL_LOCKTIME_PLL_SHARED1,
> + PLL_CON0_PLL_MMC,
> + PLL_CON3_PLL_MMC,
> + PLL_CON0_PLL_SHARED0,
> + PLL_CON3_PLL_SHARED0,
> + PLL_CON0_PLL_SHARED1,
> + PLL_CON3_PLL_SHARED1,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_CCI,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_SSS,
> + CLK_CON_MUX_MUX_CLKCMU_DPU,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_BUS,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_BUS,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_IP,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_UART,
> + CLK_CON_DIV_CLKCMU_CORE_BUS,
> + CLK_CON_DIV_CLKCMU_CORE_CCI,
> + CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD,
> + CLK_CON_DIV_CLKCMU_CORE_SSS,
> + CLK_CON_DIV_CLKCMU_DPU,
> + CLK_CON_DIV_CLKCMU_HSI_BUS,
> + CLK_CON_DIV_CLKCMU_HSI_MMC_CARD,
> + CLK_CON_DIV_CLKCMU_HSI_USB20DRD,
> + CLK_CON_DIV_CLKCMU_PERI_BUS,
> + CLK_CON_DIV_CLKCMU_PERI_IP,
> + CLK_CON_DIV_CLKCMU_PERI_UART,
> + CLK_CON_DIV_PLL_SHARED0_DIV2,
> + CLK_CON_DIV_PLL_SHARED0_DIV3,
> + CLK_CON_DIV_PLL_SHARED0_DIV4,
> + CLK_CON_DIV_PLL_SHARED1_DIV2,
> + CLK_CON_DIV_PLL_SHARED1_DIV3,
> + CLK_CON_DIV_PLL_SHARED1_DIV4,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_CCI,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD,
> + CLK_CON_GAT_GATE_CLKCMU_CORE_SSS,
> + CLK_CON_GAT_GATE_CLKCMU_DPU,
> + CLK_CON_GAT_GATE_CLKCMU_HSI_BUS,
> + CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD,
> + CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD,
> + CLK_CON_GAT_GATE_CLKCMU_PERI_BUS,
> + CLK_CON_GAT_GATE_CLKCMU_PERI_IP,
> + CLK_CON_GAT_GATE_CLKCMU_PERI_UART,
> +};
> +
> +/*
> + * Do not provide PLL tables to core PLLs, as MANUAL_PLL_CTRL bit is not set
> + * for those PLLs by default, so set_rate operation would fail.
> + */
> +static const struct samsung_pll_clock top_pll_clks[] __initconst = {
> + /* CMU_TOP_PURECLKCOMP */
> + PLL(pll_0822x, CLK_FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk",
> + PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0,
> + NULL),
> + PLL(pll_0822x, CLK_FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk",
> + PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1,
> + NULL),
> + PLL(pll_0831x, CLK_FOUT_MMC_PLL, "fout_mmc_pll", "oscclk",
> + PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, NULL),
> +};
> +
> +/* List of parent clocks for Muxes in CMU_TOP */
> +PNAME(mout_shared0_pll_p) = { "oscclk", "fout_shared0_pll" };
> +PNAME(mout_shared1_pll_p) = { "oscclk", "fout_shared1_pll" };
> +PNAME(mout_mmc_pll_p) = { "oscclk", "fout_mmc_pll" };
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_CORE */
> +PNAME(mout_core_bus_p) = { "dout_shared1_div2", "dout_shared0_div3",
> + "dout_shared1_div3", "dout_shared0_div4" };
> +PNAME(mout_core_cci_p) = { "dout_shared0_div2", "dout_shared1_div2",
> + "dout_shared0_div3", "dout_shared1_div3" };
> +PNAME(mout_core_mmc_embd_p) = { "oscclk", "dout_shared0_div2",
> + "dout_shared1_div2", "dout_shared0_div3",
> + "dout_shared1_div3", "mout_mmc_pll",
> + "oscclk", "oscclk" };
> +PNAME(mout_core_sss_p) = { "dout_shared0_div3", "dout_shared1_div3",
> + "dout_shared0_div4", "dout_shared1_div4" };
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_HSI */
> +PNAME(mout_hsi_bus_p) = { "dout_shared0_div2", "dout_shared1_div2" };
> +PNAME(mout_hsi_mmc_card_p) = { "oscclk", "dout_shared0_div2",
> + "dout_shared1_div2", "dout_shared0_div3",
> + "dout_shared1_div3", "mout_mmc_pll",
> + "oscclk", "oscclk" };
> +PNAME(mout_hsi_usb20drd_p) = { "oscclk", "dout_shared0_div4",
> + "dout_shared1_div4", "oscclk" };
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_PERI */
> +PNAME(mout_peri_bus_p) = { "dout_shared0_div4", "dout_shared1_div4" };
> +PNAME(mout_peri_uart_p) = { "oscclk", "dout_shared0_div4",
> + "dout_shared1_div4", "oscclk" };
> +PNAME(mout_peri_ip_p) = { "oscclk", "dout_shared0_div4",
> + "dout_shared1_div4", "oscclk" };
> +
> +/* List of parent clocks for Muxes in CMU_TOP: for CMU_DPU */
> +PNAME(mout_dpu_p) = { "dout_shared0_div3", "dout_shared1_div3",
> + "dout_shared0_div4", "dout_shared1_div4" };
> +
> +static const struct samsung_mux_clock top_mux_clks[] __initconst = {
> + /* CMU_TOP_PURECLKCOMP */
> + MUX(CLK_MOUT_SHARED0_PLL, "mout_shared0_pll", mout_shared0_pll_p,
> + PLL_CON0_PLL_SHARED0, 4, 1),
> + MUX(CLK_MOUT_SHARED1_PLL, "mout_shared1_pll", mout_shared1_pll_p,
> + PLL_CON0_PLL_SHARED1, 4, 1),
> + MUX(CLK_MOUT_MMC_PLL, "mout_mmc_pll", mout_mmc_pll_p,
> + PLL_CON0_PLL_MMC, 4, 1),
> +
> + /* CORE */
> + MUX(CLK_MOUT_CORE_BUS, "mout_core_bus", mout_core_bus_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 2),
> + MUX(CLK_MOUT_CORE_CCI, "mout_core_cci", mout_core_cci_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, 0, 2),
> + MUX(CLK_MOUT_CORE_MMC_EMBD, "mout_core_mmc_embd", mout_core_mmc_embd_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD, 0, 3),
> + MUX(CLK_MOUT_CORE_SSS, "mout_core_sss", mout_core_sss_p,
> + CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, 0, 2),
> +
> + /* DPU */
> + MUX(CLK_MOUT_DPU, "mout_dpu", mout_dpu_p,
> + CLK_CON_MUX_MUX_CLKCMU_DPU, 0, 2),
> +
> + /* HSI */
> + MUX(CLK_MOUT_HSI_BUS, "mout_hsi_bus", mout_hsi_bus_p,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, 0, 1),
> + MUX(CLK_MOUT_HSI_MMC_CARD, "mout_hsi_mmc_card", mout_hsi_mmc_card_p,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD, 0, 3),
> + MUX(CLK_MOUT_HSI_USB20DRD, "mout_hsi_usb20drd", mout_hsi_usb20drd_p,
> + CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD, 0, 2),
> +
> + /* PERI */
> + MUX(CLK_MOUT_PERI_BUS, "mout_peri_bus", mout_peri_bus_p,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_BUS, 0, 1),
> + MUX(CLK_MOUT_PERI_UART, "mout_peri_uart", mout_peri_uart_p,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_UART, 0, 2),
> + MUX(CLK_MOUT_PERI_IP, "mout_peri_ip", mout_peri_ip_p,
> + CLK_CON_MUX_MUX_CLKCMU_PERI_IP, 0, 2),
> +};
> +
> +static const struct samsung_div_clock top_div_clks[] __initconst = {
> + /* CMU_TOP_PURECLKCOMP */
> + DIV(CLK_DOUT_SHARED0_DIV3, "dout_shared0_div3", "mout_shared0_pll",
> + CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2),
> + DIV(CLK_DOUT_SHARED0_DIV2, "dout_shared0_div2", "mout_shared0_pll",
> + CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1),
> + DIV(CLK_DOUT_SHARED1_DIV3, "dout_shared1_div3", "mout_shared1_pll",
> + CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2),
> + DIV(CLK_DOUT_SHARED1_DIV2, "dout_shared1_div2", "mout_shared1_pll",
> + CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1),
> + DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "dout_shared0_div2",
> + CLK_CON_DIV_PLL_SHARED0_DIV4, 0, 1),
> + DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2",
> + CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1),
> +
> + /* CORE */
> + DIV(CLK_DOUT_CORE_BUS, "dout_core_bus", "gout_core_bus",
> + CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4),
> + DIV(CLK_DOUT_CORE_CCI, "dout_core_cci", "gout_core_cci",
> + CLK_CON_DIV_CLKCMU_CORE_CCI, 0, 4),
> + DIV(CLK_DOUT_CORE_MMC_EMBD, "dout_core_mmc_embd", "gout_core_mmc_embd",
> + CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD, 0, 9),
> + DIV(CLK_DOUT_CORE_SSS, "dout_core_sss", "gout_core_sss",
> + CLK_CON_DIV_CLKCMU_CORE_SSS, 0, 4),
> +
> + /* DPU */
> + DIV(CLK_DOUT_DPU, "dout_dpu", "gout_dpu",
> + CLK_CON_DIV_CLKCMU_DPU, 0, 4),
> +
> + /* HSI */
> + DIV(CLK_DOUT_HSI_BUS, "dout_hsi_bus", "gout_hsi_bus",
> + CLK_CON_DIV_CLKCMU_HSI_BUS, 0, 4),
> + DIV(CLK_DOUT_HSI_MMC_CARD, "dout_hsi_mmc_card", "gout_hsi_mmc_card",
> + CLK_CON_DIV_CLKCMU_HSI_MMC_CARD, 0, 9),
> + DIV(CLK_DOUT_HSI_USB20DRD, "dout_hsi_usb20drd", "gout_hsi_usb20drd",
> + CLK_CON_DIV_CLKCMU_HSI_USB20DRD, 0, 4),
> +
> + /* PERI */
> + DIV(CLK_DOUT_PERI_BUS, "dout_peri_bus", "gout_peri_bus",
> + CLK_CON_DIV_CLKCMU_PERI_BUS, 0, 4),
> + DIV(CLK_DOUT_PERI_UART, "dout_peri_uart", "gout_peri_uart",
> + CLK_CON_DIV_CLKCMU_PERI_UART, 0, 4),
> + DIV(CLK_DOUT_PERI_IP, "dout_peri_ip", "gout_peri_ip",
> + CLK_CON_DIV_CLKCMU_PERI_IP, 0, 4),
> +};
> +
> +static const struct samsung_gate_clock top_gate_clks[] __initconst = {
> + /* CORE */
> + GATE(CLK_GOUT_CORE_BUS, "gout_core_bus", "mout_core_bus",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, 21, 0, 0),
> + GATE(CLK_GOUT_CORE_CCI, "gout_core_cci", "mout_core_cci",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, 21, 0, 0),
> + GATE(CLK_GOUT_CORE_MMC_EMBD, "gout_core_mmc_embd", "mout_core_mmc_embd",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD, 21, 0, 0),
> + GATE(CLK_GOUT_CORE_SSS, "gout_core_sss", "mout_core_sss",
> + CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, 21, 0, 0),
> +
> + /* DPU */
> + GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu",
> + CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0),
> +
> + /* HSI */
> + GATE(CLK_GOUT_HSI_BUS, "gout_hsi_bus", "mout_hsi_bus",
> + CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, 21, 0, 0),
> + GATE(CLK_GOUT_HSI_MMC_CARD, "gout_hsi_mmc_card", "mout_hsi_mmc_card",
> + CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD, 21, 0, 0),
> + GATE(CLK_GOUT_HSI_USB20DRD, "gout_hsi_usb20drd", "mout_hsi_usb20drd",
> + CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD, 21, 0, 0),
> +
> + /* PERI */
> + GATE(CLK_GOUT_PERI_BUS, "gout_peri_bus", "mout_peri_bus",
> + CLK_CON_GAT_GATE_CLKCMU_PERI_BUS, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_UART, "gout_peri_uart", "mout_peri_uart",
> + CLK_CON_GAT_GATE_CLKCMU_PERI_UART, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_IP, "gout_peri_ip", "mout_peri_ip",
> + CLK_CON_GAT_GATE_CLKCMU_PERI_IP, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info top_cmu_info __initconst = {
> + .pll_clks = top_pll_clks,
> + .nr_pll_clks = ARRAY_SIZE(top_pll_clks),
> + .mux_clks = top_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(top_mux_clks),
> + .div_clks = top_div_clks,
> + .nr_div_clks = ARRAY_SIZE(top_div_clks),
> + .gate_clks = top_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(top_gate_clks),
> + .nr_clk_ids = TOP_NR_CLK,
> + .clk_regs = top_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(top_clk_regs),
> +};
> +
> +static void __init exynos850_cmu_top_init(struct device_node *np)
> +{
> + exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs));
> + samsung_cmu_register_one(np, &top_cmu_info);
> +}
> +
> +CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top",
> + exynos850_cmu_top_init);
> +
> +/* ---- CMU_HSI ------------------------------------------------------------- */
> +
> +/* Register Offset definitions for CMU_HSI (0x13400000) */
> +#define PLL_CON0_MUX_CLKCMU_HSI_BUS_USER 0x0600
> +#define PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER 0x0610
> +#define PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER 0x0620
> +#define CLK_CON_MUX_MUX_CLK_HSI_RTC 0x1000
> +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV 0x2008
> +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50 0x200c
> +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26 0x2010
> +#define CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK 0x2018
> +#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK 0x2024
> +#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN 0x2028
> +#define CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK 0x2038
> +#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20 0x203c
> +#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY 0x2040
> +
> +static const unsigned long hsi_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_HSI_BUS_USER,
> + PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
> + PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
> + CLK_CON_MUX_MUX_CLK_HSI_RTC,
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV,
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50,
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26,
> + CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK,
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK,
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN,
> + CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK,
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20,
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_PERI */
> +PNAME(mout_hsi_bus_user_p) = { "oscclk", "dout_hsi_bus" };
> +PNAME(mout_hsi_mmc_card_user_p) = { "oscclk", "dout_hsi_mmc_card" };
> +PNAME(mout_hsi_usb20drd_user_p) = { "oscclk", "dout_hsi_usb20drd" };
> +PNAME(mout_hsi_rtc_p) = { "rtcclk", "oscclk" };
> +
> +static const struct samsung_mux_clock hsi_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_HSI_BUS_USER, "mout_hsi_bus_user", mout_hsi_bus_user_p,
> + PLL_CON0_MUX_CLKCMU_HSI_BUS_USER, 4, 1),
> + MUX_F(CLK_MOUT_HSI_MMC_CARD_USER, "mout_hsi_mmc_card_user",
> + mout_hsi_mmc_card_user_p, PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
> + 4, 1, CLK_SET_RATE_PARENT, 0),
> + MUX(CLK_MOUT_HSI_USB20DRD_USER, "mout_hsi_usb20drd_user",
> + mout_hsi_usb20drd_user_p, PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
> + 4, 1),
> + MUX(CLK_MOUT_HSI_RTC, "mout_hsi_rtc", mout_hsi_rtc_p,
> + CLK_CON_MUX_MUX_CLK_HSI_RTC, 0, 1),
> +};
> +
> +static const struct samsung_gate_clock hsi_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_USB_RTC_CLK, "gout_usb_rtc", "mout_hsi_rtc",
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV, 21, 0, 0),
> + GATE(CLK_GOUT_USB_REF_CLK, "gout_usb_ref", "mout_hsi_usb20drd_user",
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50, 21, 0, 0),
> + GATE(CLK_GOUT_USB_PHY_REF_CLK, "gout_usb_phy_ref", "oscclk",
> + CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26, 21, 0, 0),
> + GATE(CLK_GOUT_GPIO_HSI_PCLK, "gout_gpio_hsi_pclk", "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_CARD_ACLK, "gout_mmc_card_aclk", "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_CARD_SDCLKIN, "gout_mmc_card_sdclkin",
> + "mout_hsi_mmc_card_user",
> + CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN, 21, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_GOUT_SYSREG_HSI_PCLK, "gout_sysreg_hsi_pclk",
> + "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_USB_PHY_ACLK, "gout_usb_phy_aclk", "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20, 21, 0, 0),
> + GATE(CLK_GOUT_USB_BUS_EARLY_CLK, "gout_usb_bus_early",
> + "mout_hsi_bus_user",
> + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info hsi_cmu_info __initconst = {
> + .mux_clks = hsi_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(hsi_mux_clks),
> + .gate_clks = hsi_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(hsi_gate_clks),
> + .nr_clk_ids = HSI_NR_CLK,
> + .clk_regs = hsi_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(hsi_clk_regs),
> + .clk_name = "dout_hsi_bus",
> +};
> +
> +/* ---- CMU_PERI ------------------------------------------------------------ */
> +
> +/* Register Offset definitions for CMU_PERI (0x10030000) */
> +#define PLL_CON0_MUX_CLKCMU_PERI_BUS_USER 0x0600
> +#define PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER 0x0610
> +#define PLL_CON0_MUX_CLKCMU_PERI_SPI_USER 0x0620
> +#define PLL_CON0_MUX_CLKCMU_PERI_UART_USER 0x0630
> +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0 0x1800
> +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1 0x1804
> +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2 0x1808
> +#define CLK_CON_DIV_DIV_CLK_PERI_SPI_0 0x180c
> +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0 0x200c
> +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1 0x2010
> +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2 0x2014
> +#define CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK 0x2020
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK 0x2024
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK 0x2028
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK 0x202c
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK 0x2030
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK 0x2034
> +#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK 0x2038
> +#define CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK 0x203c
> +#define CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK 0x2040
> +#define CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK 0x2044
> +#define CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK 0x2048
> +#define CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK 0x204c
> +#define CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK 0x2050
> +#define CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK 0x2054
> +#define CLK_CON_GAT_GOUT_PERI_MCT_PCLK 0x205c
> +#define CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK 0x2064
> +#define CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK 0x209c
> +#define CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK 0x20a0
> +#define CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK 0x20a4
> +#define CLK_CON_GAT_GOUT_PERI_UART_IPCLK 0x20a8
> +#define CLK_CON_GAT_GOUT_PERI_UART_PCLK 0x20ac
> +#define CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK 0x20b0
> +#define CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK 0x20b4
> +
> +static const unsigned long peri_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_PERI_BUS_USER,
> + PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER,
> + PLL_CON0_MUX_CLKCMU_PERI_SPI_USER,
> + PLL_CON0_MUX_CLKCMU_PERI_UART_USER,
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0,
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1,
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2,
> + CLK_CON_DIV_DIV_CLK_PERI_SPI_0,
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0,
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1,
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2,
> + CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK,
> + CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK,
> + CLK_CON_GAT_GOUT_PERI_MCT_PCLK,
> + CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK,
> + CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK,
> + CLK_CON_GAT_GOUT_PERI_UART_IPCLK,
> + CLK_CON_GAT_GOUT_PERI_UART_PCLK,
> + CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK,
> + CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_PERI */
> +PNAME(mout_peri_bus_user_p) = { "oscclk", "dout_peri_bus" };
> +PNAME(mout_peri_uart_user_p) = { "oscclk", "dout_peri_uart" };
> +PNAME(mout_peri_hsi2c_user_p) = { "oscclk", "dout_peri_ip" };
> +PNAME(mout_peri_spi_user_p) = { "oscclk", "dout_peri_ip" };
> +
> +static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_PERI_BUS_USER, "mout_peri_bus_user", mout_peri_bus_user_p,
> + PLL_CON0_MUX_CLKCMU_PERI_BUS_USER, 4, 1),
> + MUX(CLK_MOUT_PERI_UART_USER, "mout_peri_uart_user",
> + mout_peri_uart_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART_USER, 4, 1),
> + MUX(CLK_MOUT_PERI_HSI2C_USER, "mout_peri_hsi2c_user",
> + mout_peri_hsi2c_user_p, PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, 4, 1),
> + MUX(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user", mout_peri_spi_user_p,
> + PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1),
> +};
> +
> +static const struct samsung_div_clock peri_div_clks[] __initconst = {
> + DIV(CLK_DOUT_PERI_HSI2C0, "dout_peri_hsi2c0", "gout_peri_hsi2c0",
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0, 0, 5),
> + DIV(CLK_DOUT_PERI_HSI2C1, "dout_peri_hsi2c1", "gout_peri_hsi2c1",
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, 0, 5),
> + DIV(CLK_DOUT_PERI_HSI2C2, "dout_peri_hsi2c2", "gout_peri_hsi2c2",
> + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, 0, 5),
> + DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
> + CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5),
> +};
> +
> +static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_PERI_HSI2C0, "gout_peri_hsi2c0", "mout_peri_hsi2c_user",
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_HSI2C1, "gout_peri_hsi2c1", "mout_peri_hsi2c_user",
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1, 21, 0, 0),
> + GATE(CLK_GOUT_PERI_HSI2C2, "gout_peri_hsi2c2", "mout_peri_hsi2c_user",
> + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C0_IPCLK, "gout_hsi2c0_ipclk", "dout_peri_hsi2c0",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C0_PCLK, "gout_hsi2c0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C1_IPCLK, "gout_hsi2c1_ipclk", "dout_peri_hsi2c1",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C1_PCLK, "gout_hsi2c1_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C2_IPCLK, "gout_hsi2c2_ipclk", "dout_peri_hsi2c2",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_HSI2C2_PCLK, "gout_hsi2c2_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C0_PCLK, "gout_i2c0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C1_PCLK, "gout_i2c1_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C2_PCLK, "gout_i2c2_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C3_PCLK, "gout_i2c3_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C4_PCLK, "gout_i2c4_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C5_PCLK, "gout_i2c5_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_I2C6_PCLK, "gout_i2c6_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_MCT_PCLK, "gout_mct_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_MCT_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_PWM_MOTOR_PCLK, "gout_pwm_motor_pclk",
> + "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_SPI0_IPCLK, "gout_spi0_ipclk", "dout_peri_spi0",
> + CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk",
> + "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_UART_IPCLK, "gout_uart_ipclk", "mout_peri_uart_user",
> + CLK_CON_GAT_GOUT_PERI_UART_IPCLK, 21, 0, 0),
> + GATE(CLK_GOUT_UART_PCLK, "gout_uart_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_UART_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_WDT0_PCLK, "gout_wdt0_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_WDT1_PCLK, "gout_wdt1_pclk", "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_GPIO_PERI_PCLK, "gout_gpio_peri_pclk",
> + "mout_peri_bus_user",
> + CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info peri_cmu_info __initconst = {
> + .mux_clks = peri_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(peri_mux_clks),
> + .div_clks = peri_div_clks,
> + .nr_div_clks = ARRAY_SIZE(peri_div_clks),
> + .gate_clks = peri_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(peri_gate_clks),
> + .nr_clk_ids = PERI_NR_CLK,
> + .clk_regs = peri_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(peri_clk_regs),
> + .clk_name = "dout_peri_bus",
> +};
> +
> +/* ---- CMU_CORE ------------------------------------------------------------ */
> +
> +/* Register Offset definitions for CMU_CORE (0x12000000) */
> +#define PLL_CON0_MUX_CLKCMU_CORE_BUS_USER 0x0600
> +#define PLL_CON0_MUX_CLKCMU_CORE_CCI_USER 0x0610
> +#define PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER 0x0620
> +#define PLL_CON0_MUX_CLKCMU_CORE_SSS_USER 0x0630
> +#define CLK_CON_MUX_MUX_CLK_CORE_GIC 0x1000
> +#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800
> +#define CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK 0x2038
> +#define CLK_CON_GAT_GOUT_CORE_GIC_CLK 0x2040
> +#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK 0x20e8
> +#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN 0x20ec
> +#define CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK 0x2128
> +#define CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK 0x212c
> +
> +static const unsigned long core_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER,
> + PLL_CON0_MUX_CLKCMU_CORE_CCI_USER,
> + PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER,
> + PLL_CON0_MUX_CLKCMU_CORE_SSS_USER,
> + CLK_CON_MUX_MUX_CLK_CORE_GIC,
> + CLK_CON_DIV_DIV_CLK_CORE_BUSP,
> + CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK,
> + CLK_CON_GAT_GOUT_CORE_GIC_CLK,
> + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK,
> + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
> + CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK,
> + CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_CORE */
> +PNAME(mout_core_bus_user_p) = { "oscclk", "dout_core_bus" };
> +PNAME(mout_core_cci_user_p) = { "oscclk", "dout_core_cci" };
> +PNAME(mout_core_mmc_embd_user_p) = { "oscclk", "dout_core_mmc_embd" };
> +PNAME(mout_core_sss_user_p) = { "oscclk", "dout_core_sss" };
> +PNAME(mout_core_gic_p) = { "dout_core_busp", "oscclk" };
> +
> +static const struct samsung_mux_clock core_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_CORE_BUS_USER, "mout_core_bus_user", mout_core_bus_user_p,
> + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, 4, 1),
> + MUX(CLK_MOUT_CORE_CCI_USER, "mout_core_cci_user", mout_core_cci_user_p,
> + PLL_CON0_MUX_CLKCMU_CORE_CCI_USER, 4, 1),
> + MUX_F(CLK_MOUT_CORE_MMC_EMBD_USER, "mout_core_mmc_embd_user",
> + mout_core_mmc_embd_user_p, PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER,
> + 4, 1, CLK_SET_RATE_PARENT, 0),
> + MUX(CLK_MOUT_CORE_SSS_USER, "mout_core_sss_user", mout_core_sss_user_p,
> + PLL_CON0_MUX_CLKCMU_CORE_SSS_USER, 4, 1),
> + MUX(CLK_MOUT_CORE_GIC, "mout_core_gic", mout_core_gic_p,
> + CLK_CON_MUX_MUX_CLK_CORE_GIC, 0, 1),
> +};
> +
> +static const struct samsung_div_clock core_div_clks[] __initconst = {
> + DIV(CLK_DOUT_CORE_BUSP, "dout_core_busp", "mout_core_bus_user",
> + CLK_CON_DIV_DIV_CLK_CORE_BUSP, 0, 2),
> +};
> +
> +static const struct samsung_gate_clock core_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_CCI_ACLK, "gout_cci_aclk", "mout_core_cci_user",
> + CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_GIC_CLK, "gout_gic_clk", "mout_core_gic",
> + CLK_CON_GAT_GOUT_CORE_GIC_CLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_EMBD_ACLK, "gout_mmc_embd_aclk", "dout_core_busp",
> + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_MMC_EMBD_SDCLKIN, "gout_mmc_embd_sdclkin",
> + "mout_core_mmc_embd_user", CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN,
> + 21, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_GOUT_SSS_ACLK, "gout_sss_aclk", "mout_core_sss_user",
> + CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_SSS_PCLK, "gout_sss_pclk", "dout_core_busp",
> + CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info core_cmu_info __initconst = {
> + .mux_clks = core_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(core_mux_clks),
> + .div_clks = core_div_clks,
> + .nr_div_clks = ARRAY_SIZE(core_div_clks),
> + .gate_clks = core_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(core_gate_clks),
> + .nr_clk_ids = CORE_NR_CLK,
> + .clk_regs = core_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(core_clk_regs),
> + .clk_name = "dout_core_bus",
> +};
> +
> +/* ---- CMU_DPU ------------------------------------------------------------- */
> +
> +/* Register Offset definitions for CMU_DPU (0x13000000) */
> +#define PLL_CON0_MUX_CLKCMU_DPU_USER 0x0600
> +#define CLK_CON_DIV_DIV_CLK_DPU_BUSP 0x1800
> +#define CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK 0x2004
> +#define CLK_CON_GAT_GOUT_DPU_ACLK_DECON0 0x2010
> +#define CLK_CON_GAT_GOUT_DPU_ACLK_DMA 0x2014
> +#define CLK_CON_GAT_GOUT_DPU_ACLK_DPP 0x2018
> +#define CLK_CON_GAT_GOUT_DPU_PPMU_ACLK 0x2028
> +#define CLK_CON_GAT_GOUT_DPU_PPMU_PCLK 0x202c
> +#define CLK_CON_GAT_GOUT_DPU_SMMU_CLK 0x2038
> +#define CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK 0x203c
> +
> +static const unsigned long dpu_clk_regs[] __initconst = {
> + PLL_CON0_MUX_CLKCMU_DPU_USER,
> + CLK_CON_DIV_DIV_CLK_DPU_BUSP,
> + CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK,
> + CLK_CON_GAT_GOUT_DPU_ACLK_DECON0,
> + CLK_CON_GAT_GOUT_DPU_ACLK_DMA,
> + CLK_CON_GAT_GOUT_DPU_ACLK_DPP,
> + CLK_CON_GAT_GOUT_DPU_PPMU_ACLK,
> + CLK_CON_GAT_GOUT_DPU_PPMU_PCLK,
> + CLK_CON_GAT_GOUT_DPU_SMMU_CLK,
> + CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK,
> +};
> +
> +/* List of parent clocks for Muxes in CMU_CORE */
> +PNAME(mout_dpu_user_p) = { "oscclk", "dout_dpu" };
> +
> +static const struct samsung_mux_clock dpu_mux_clks[] __initconst = {
> + MUX(CLK_MOUT_DPU_USER, "mout_dpu_user", mout_dpu_user_p,
> + PLL_CON0_MUX_CLKCMU_DPU_USER, 4, 1),
> +};
> +
> +static const struct samsung_div_clock dpu_div_clks[] __initconst = {
> + DIV(CLK_DOUT_DPU_BUSP, "dout_dpu_busp", "mout_dpu_user",
> + CLK_CON_DIV_DIV_CLK_DPU_BUSP, 0, 3),
> +};
> +
> +static const struct samsung_gate_clock dpu_gate_clks[] __initconst = {
> + GATE(CLK_GOUT_DPU_CMU_DPU_PCLK, "gout_dpu_cmu_dpu_pclk",
> + "dout_dpu_busp", CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_DECON0_ACLK, "gout_dpu_decon0_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_ACLK_DECON0, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_DMA_ACLK, "gout_dpu_dma_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_ACLK_DMA, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_DPP_ACLK, "gout_dpu_dpp_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_ACLK_DPP, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_PPMU_ACLK, "gout_dpu_ppmu_aclk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_PPMU_ACLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_PPMU_PCLK, "gout_dpu_ppmu_pclk", "dout_dpu_busp",
> + CLK_CON_GAT_GOUT_DPU_PPMU_PCLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_SMMU_CLK, "gout_dpu_smmu_clk", "mout_dpu_user",
> + CLK_CON_GAT_GOUT_DPU_SMMU_CLK, 21, 0, 0),
> + GATE(CLK_GOUT_DPU_SYSREG_PCLK, "gout_dpu_sysreg_pclk", "dout_dpu_busp",
> + CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK, 21, 0, 0),
> +};
> +
> +static const struct samsung_cmu_info dpu_cmu_info __initconst = {
> + .mux_clks = dpu_mux_clks,
> + .nr_mux_clks = ARRAY_SIZE(dpu_mux_clks),
> + .div_clks = dpu_div_clks,
> + .nr_div_clks = ARRAY_SIZE(dpu_div_clks),
> + .gate_clks = dpu_gate_clks,
> + .nr_gate_clks = ARRAY_SIZE(dpu_gate_clks),
> + .nr_clk_ids = DPU_NR_CLK,
> + .clk_regs = dpu_clk_regs,
> + .nr_clk_regs = ARRAY_SIZE(dpu_clk_regs),
> + .clk_name = "dout_dpu",
> +};
> +
> +/* ---- platform_driver ----------------------------------------------------- */
> +
> +static int __init exynos850_cmu_probe(struct platform_device *pdev)
> +{
> + const struct samsung_cmu_info *info;
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> +
> + info = of_device_get_match_data(dev);
> + exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs);
> + samsung_cmu_register_one(np, info);
> +
> + /* Keep bus clock running, so it's possible to access CMU registers */
> + if (info->clk_name) {
> + struct clk *bus_clk;
> +
> + bus_clk = clk_get(dev, info->clk_name);
> + if (IS_ERR(bus_clk)) {
> + pr_err("%s: could not find bus clock %s; err = %ld\n",
> + __func__, info->clk_name, PTR_ERR(bus_clk));
> + } else {
> + clk_prepare_enable(bus_clk);
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* CMUs which belong to Power Domains and need runtime PM to be implemented */
> +static const struct of_device_id exynos850_cmu_of_match[] = {
> + {
> + .compatible = "samsung,exynos850-cmu-hsi",
> + .data = &hsi_cmu_info,
> + }, {
> + .compatible = "samsung,exynos850-cmu-peri",
> + .data = &peri_cmu_info,
> + }, {
> + .compatible = "samsung,exynos850-cmu-core",
> + .data = &core_cmu_info,
> + }, {
> + .compatible = "samsung,exynos850-cmu-dpu",
> + .data = &dpu_cmu_info,
> + }, {
> + },
> +};
> +
> +static struct platform_driver exynos850_cmu_driver __refdata = {
> + .driver = {
> + .name = "exynos850-cmu",
> + .of_match_table = exynos850_cmu_of_match,
> + .suppress_bind_attrs = true,
> + },
> + .probe = exynos850_cmu_probe,
> +};
> +
> +static int __init exynos850_cmu_init(void)
> +{
> + return platform_driver_register(&exynos850_cmu_driver);
> +}
> +core_initcall(exynos850_cmu_init);
>

Looks good to me.
Acked-by: Chanwoo Choi <[email protected]>

--
Best Regards,
Chanwoo Choi
Samsung Electronics

2021-10-16 06:56:49

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] clk: samsung: Introduce Exynos850 clock driver

Hi Sam,

On 12.10.2021 10:14, Sam Protsenko wrote:
> Hi Sylwester,
>
> On Fri, 8 Oct 2021 at 18:44, Sam Protsenko<[email protected]> wrote:
>> This is the initial implementation adding only basic clocks like UART,
>> MMC, I2C and corresponding parent clocks. Design is influenced by
>> Exynos5433 clock driver.
[...]
>> Signed-off-by: Sam Protsenko<[email protected]>
>> Reviewed-by: Krzysztof Kozlowski<[email protected]>
>> ---
> Can we also apply this one?

I think so, apologies for a bit excessive latency on my side. The patch looks
good to me, I have just applied it to clk-samsung tree. Thank you for your work
and good luck in upstreaming remaining parts of the exynos850 platform.


2021-10-16 09:33:33

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] dt-bindings: clock: Document Exynos850 CMU bindings

On 12.10.2021 10:13, Sam Protsenko wrote:
> On Mon, 11 Oct 2021 at 13:42, Sylwester Nawrocki<[email protected]> wrote:
>> On 11.10.2021 12:13, Sam Protsenko wrote:
>>> On Sat, 9 Oct 2021 at 23:41, Sylwester Nawrocki<[email protected]> wrote:
>>>> On 08.10.2021 17:43, Sam Protsenko wrote:
>>>>> Provide dt-schema documentation for Exynos850 SoC clock controller.
>>>>>
>>>>> Signed-off-by: Sam Protsenko<[email protected]>
>>>>> Reviewed-by: Krzysztof Kozlowski<[email protected]>
>>>>> Acked-by: Chanwoo Choi<[email protected]>
>> [...]
>>>>> +++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml
>>>>> @@ -0,0 +1,185 @@
>> [...]
>>>>> +
>>>>> +title: Samsung Exynos850 SoC clock controller
>>>>> +
>>>>> +maintainers:
>>>>> + - Sam Protsenko<[email protected]>
>>>>> + - Chanwoo Choi<[email protected]>
>>>>> + - Krzysztof Kozlowski<[email protected]>
>>>>> + - Sylwester Nawrocki<[email protected]>
>>>>> + - Tomasz Figa<[email protected]>
>>>>> +
>>>>> +description: |
>>>>> + Exynos850 clock controller is comprised of several CMU units, generating
>>>>> + clocks for different domains. Those CMU units are modeled as separate device
>>>>> + tree nodes, and might depend on each other. Root clocks in that clock tree are
>>>>> + two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external
>>>>> + clocks must be defined as fixed-rate clocks in dts.
>>>>> +
>>>>> + CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
>>>>> + dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP.
>>>>> +
>>>>> + Each clock is assigned an identifier and client nodes can use this identifier
>>>>> + to specify the clock which they consume. All clocks that available for usage

>>>> s/All clocks that available/All clocks available ?
>>>> No need to resend, I can amend it when applying.
>>>>
>>> Yeah, not a native speaker, I tend to do such mistakes sometimes:)
>>> Please fix when applying.
>>>
>>> Btw, I can see that you already applied 3 out of 5 patches from this
>>> patch series here: [1]. Can you please also apply the rest, or is
>>> there any outstanding comments that I missed?
>> The patches look good to me, I just wanted to allow some for Rob to have
>> a look and provide an Ack.
>>
> Can you please review this one?

The binding is rather straightforward so I applied the patch now, thank you.



2021-10-16 14:33:38

by Sam Protsenko

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] clk: samsung: Introduce Exynos850 clock driver

On Fri, 15 Oct 2021 at 16:30, Sylwester Nawrocki <[email protected]> wrote:
>
> Hi Sam,
>
> On 12.10.2021 10:14, Sam Protsenko wrote:
> > Hi Sylwester,
> >
> > On Fri, 8 Oct 2021 at 18:44, Sam Protsenko<[email protected]> wrote:
> >> This is the initial implementation adding only basic clocks like UART,
> >> MMC, I2C and corresponding parent clocks. Design is influenced by
> >> Exynos5433 clock driver.
> [...]
> >> Signed-off-by: Sam Protsenko<[email protected]>
> >> Reviewed-by: Krzysztof Kozlowski<[email protected]>
> >> ---
> > Can we also apply this one?
>
> I think so, apologies for a bit excessive latency on my side. The patch looks
> good to me, I have just applied it to clk-samsung tree. Thank you for your work
> and good luck in upstreaming remaining parts of the exynos850 platform.
>
>

Thank you, Sylwester! A lot of work remains to be done on E850 clock
driver, so I guess I'll be bothering you soon enough :)