summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2021-06-01 16:57:52 +0300
committerEmil Renner Berthing <kernel@esmil.dk>2021-06-07 01:55:57 +0300
commit09a73a6fbb30a868682b2d6178743d0da3e5e8ae (patch)
tree7732adf282ae16b06c8a751ea24b72f28a3290a9
parente0369eaac760ae5cdc07e434143bcf7239fc9a0e (diff)
downloadlinux-09a73a6fbb30a868682b2d6178743d0da3e5e8ae.tar.xz
[WIP] clk: starfive: Add preliminary JH7100 Clock Generator Driver
Add a preliminary driver for the StarFive JH7100 Clock Generator. For now, all clocks are implemented as fixed-factor clocks relative to osc0, based on the list of fixed-frequency clocks defined in jh7100.dtsi. To be updated when the documentation becomes available. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/starfive/Kconfig9
-rw-r--r--drivers/clk/starfive/Makefile3
-rw-r--r--drivers/clk/starfive/clk-starfive-jh7100.c124
5 files changed, 138 insertions, 0 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e80918be8e9c..61b243a14f42 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -397,6 +397,7 @@ source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sifive/Kconfig"
source "drivers/clk/socfpga/Kconfig"
source "drivers/clk/sprd/Kconfig"
+source "drivers/clk/starfive/Kconfig"
source "drivers/clk/sunxi/Kconfig"
source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5f06879d7fe9..c154596d1ab5 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -109,6 +109,7 @@ obj-y += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-y += sprd/
obj-$(CONFIG_ARCH_STI) += st/
+obj-$(CONFIG_SOC_STARFIVE_VIC7100) += starfive/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
diff --git a/drivers/clk/starfive/Kconfig b/drivers/clk/starfive/Kconfig
new file mode 100644
index 000000000000..0e23c9a8a663
--- /dev/null
+++ b/drivers/clk/starfive/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_STARFIVE_JH7100
+ bool "StarFive JH7100 clock support"
+ depends on SOC_STARFIVE_VIC7100 || COMPILE_TEST
+ default y if SOC_STARFIVE_VIC7100
+ help
+ Say yes here to support the clock controller on the StarFive JH7100
+ SoC.
diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
new file mode 100644
index 000000000000..09759cc73530
--- /dev/null
+++ b/drivers/clk/starfive/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+# StarFive Clock
+obj-$(CONFIG_CLK_STARFIVE_JH7100) += clk-starfive-jh7100.o
diff --git a/drivers/clk/starfive/clk-starfive-jh7100.c b/drivers/clk/starfive/clk-starfive-jh7100.c
new file mode 100644
index 000000000000..a768394c28f0
--- /dev/null
+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * StarFive JH7100 Clock Generator Driver
+ * This is part of the PCR (Power/Clock/Reset) Management Unit Driver
+ *
+ * FIXME PRELIMINARY
+ * For now, all clocks are implemented as fixed-factor clocks relative to osc0
+ *
+ * TODO Real clock topology, clock register programming
+ * PLL0 used for system main logic, including CPU, bus
+ * PLL1 output to support DDR, DLA and DSP
+ * PLL2 output to support slow speed peripherals, video input and video output
+ *
+ * Copyright (C) 2021 Glider bv
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/starfive-jh7100-clkgen.h>
+
+static const struct jh7100_clk {
+ const char *name;
+ unsigned int mult;
+ unsigned int div;
+} jh7100_clks[] = {
+ [JH7100_CLK_AXI] = { "axi", .mult = 20, .div = 1 },
+ [JH7100_CLK_AHB0] = { "ahb0", .mult = 10, .div = 1 },
+ [JH7100_CLK_AHB2] = { "ahb2", .mult = 5, .div = 1 },
+ [JH7100_CLK_APB1] = { "apb1", .mult = 5, .div = 1 },
+ [JH7100_CLK_APB2] = { "apb2", .mult = 5, .div = 1 },
+ [JH7100_CLK_VPU] = { "vpu", .mult = 16, .div = 1 },
+ [JH7100_CLK_JPU] = { "jpu", .mult = 40, .div = 3 },
+ [JH7100_CLK_PWM] = { "pwm", .mult = 5, .div = 1 },
+ [JH7100_CLK_DWMMC_BIU] = { "dwmmc-biu", .mult = 4, .div = 1 },
+ [JH7100_CLK_DWMMC_CIU] = { "dwmmc-ciu", .mult = 4, .div = 1 },
+ [JH7100_CLK_UART] = { "uart", .mult = 4, .div = 1 },
+ [JH7100_CLK_HS_UART] = { "hs_uart", .mult = 297, .div = 100 },
+ [JH7100_CLK_I2C0] = { "i2c0", .mult = 99, .div = 50 },
+ [JH7100_CLK_I2C2] = { "i2c2", .mult = 2, .div = 1 },
+ [JH7100_CLK_QSPI] = { "qspi", .mult = 2, .div = 1 },
+ [JH7100_CLK_SPI] = { "spi", .mult = 2, .div = 1 },
+ [JH7100_CLK_GMAC] = { "gmac", .mult = 1, .div = 1 },
+ [JH7100_CLK_HF] = { "hf", .mult = 1, .div = 1 },
+ [JH7100_CLK_RTC] = { "rtc", .mult = 1, .div = 4 }
+};
+
+struct clk_starfive_jh7100_priv {
+ struct clk_onecell_data data;
+ void __iomem *base;
+ struct clk *clks[];
+};
+
+static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ unsigned int nclks = ARRAY_SIZE(jh7100_clks);
+ struct clk_starfive_jh7100_priv *priv;
+ const char *osc0_name;
+ struct clk_hw *hw;
+ struct clk *osc0;
+ unsigned int i;
+
+ priv = devm_kzalloc(dev, struct_size(priv, clks, nclks), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ osc0 = devm_clk_get(dev, "osc0");
+ if (IS_ERR(osc0))
+ return PTR_ERR(osc0);
+
+ osc0_name = __clk_get_name(osc0);
+
+ for (i = 0; i < nclks; i++) {
+ hw = devm_clk_hw_register_fixed_factor(dev,
+ jh7100_clks[i].name, osc0_name, 0, jh7100_clks[i].mult,
+ jh7100_clks[i].div);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ priv->clks[i] = hw->clk;
+ }
+
+ priv->data.clks = priv->clks;
+ priv->data.clk_num = nclks;
+
+ return of_clk_add_provider(np, of_clk_src_onecell_get, &priv->data);
+}
+
+static const struct of_device_id clk_starfive_jh7100_match[] = {
+ {
+ .compatible = "starfive,jh7100-clkgen",
+ },
+ { /* sentinel */ }
+};
+static struct platform_driver clk_starfive_jh7100_driver = {
+ .driver = {
+ .name = "clk-starfive-jh7100",
+ .of_match_table = clk_starfive_jh7100_match,
+ },
+};
+
+static int __init clk_starfive_jh7100_init(void)
+{
+ return platform_driver_probe(&clk_starfive_jh7100_driver,
+ clk_starfive_jh7100_probe);
+}
+
+subsys_initcall(clk_starfive_jh7100_init);
+
+MODULE_DESCRIPTION("StarFive JH7100 Clock Generator Driver");
+MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
+MODULE_LICENSE("GPL v2");