aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2019-05-11 00:27:44 +0530
committerManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>2019-05-14 22:47:48 +0530
commit73ece2e0f7c7f2ab1373e652ea5d34b9f607fe73 (patch)
tree4aca56d3f1dd576d7656d82665ca3e8ce0aafcb6
parent141a4cf701d71b743e3ddc074a09b30e5cde871f (diff)
download96b-common-73ece2e0f7c7f2ab1373e652ea5d34b9f607fe73.tar.gz
clk: Add BM1880 common clk driver
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-rw-r--r--arch/arm64/boot/dts/bitmain/bm1880-sophon-edge.dts12
-rw-r--r--arch/arm64/boot/dts/bitmain/bm1880.dtsi23
-rw-r--r--drivers/clk/Kconfig6
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-bm1880.c237
-rw-r--r--include/dt-bindings/clock/bm1880-clock.h66
6 files changed, 331 insertions, 14 deletions
diff --git a/arch/arm64/boot/dts/bitmain/bm1880-sophon-edge.dts b/arch/arm64/boot/dts/bitmain/bm1880-sophon-edge.dts
index 41da899963b2..22baf7a7a216 100644
--- a/arch/arm64/boot/dts/bitmain/bm1880-sophon-edge.dts
+++ b/arch/arm64/boot/dts/bitmain/bm1880-sophon-edge.dts
@@ -26,12 +26,6 @@
device_type = "memory";
reg = <0x1 0x00000000 0x0 0x40000000>; // 1GB
};
-
- uart_clk: uart-clk {
- compatible = "fixed-clock";
- clock-frequency = <500000000>;
- #clock-cells = <0>;
- };
};
&pinctrl {
@@ -59,21 +53,21 @@
&uart0 {
status = "okay";
- clocks = <&uart_clk>;
+// clocks = <&uart_clk>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0_default>;
};
&uart1 {
status = "okay";
- clocks = <&uart_clk>;
+// clocks = <&uart_clk>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1_default>;
};
&uart2 {
status = "okay";
- clocks = <&uart_clk>;
+// clocks = <&uart_clk>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2_default>;
};
diff --git a/arch/arm64/boot/dts/bitmain/bm1880.dtsi b/arch/arm64/boot/dts/bitmain/bm1880.dtsi
index 37ecb760a2d2..dc574bced19f 100644
--- a/arch/arm64/boot/dts/bitmain/bm1880.dtsi
+++ b/arch/arm64/boot/dts/bitmain/bm1880.dtsi
@@ -4,6 +4,7 @@
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
*/
+#include <dt-bindings/clock/bm1880-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/bitmain,bm1880-reset.h>
@@ -94,15 +95,15 @@
reg = <0x50 0x4B0>;
};
- clk_rst: reset-controller@800 {
- compatible = "bitmain,bm1880-reset";
+ clk: clock-controller@800 {
+ compatible = "bitmain,bm1880-clk";
reg = <0x800 0x8>;
- #reset-cells = <1>;
+ #clock-cells = <1>;
};
- rst: reset-controller@C00 {
+ rst: reset-controller@c00 {
compatible = "bitmain,bm1880-reset";
- reg = <0xC00 0x8>;
+ reg = <0xc00 0x8>;
#reset-cells = <1>;
};
};
@@ -110,6 +111,9 @@
uart0: serial@58018000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x58018000 0x0 0x2000>;
+ clocks = <&clk BM1880_CLK_UART_500M>,
+ <&clk BM1880_CLK_APB_UART>;
+ clock-names = "baudclk", "apb_pclk";
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -120,6 +124,9 @@
uart1: serial@5801A000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x5801a000 0x0 0x2000>;
+ clocks = <&clk BM1880_CLK_UART_500M>,
+ <&clk BM1880_CLK_APB_UART>;
+ clock-names = "baudclk", "apb_pclk";
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -130,6 +137,9 @@
uart2: serial@5801C000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x5801c000 0x0 0x2000>;
+ clocks = <&clk BM1880_CLK_UART_500M>,
+ <&clk BM1880_CLK_APB_UART>;
+ clock-names = "baudclk", "apb_pclk";
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
@@ -140,6 +150,9 @@
uart3: serial@5801E000 {
compatible = "snps,dw-apb-uart";
reg = <0x0 0x5801e000 0x0 0x2000>;
+ clocks = <&clk BM1880_CLK_UART_500M>,
+ <&clk BM1880_CLK_APB_UART>;
+ clock-names = "baudclk", "apb_pclk";
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index e705aab9e38b..dd7f84e276f5 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -296,6 +296,12 @@ config COMMON_CLK_FIXED_MMIO
help
Support for Memory Mapped IO Fixed clocks
+config COMMON_CLK_BM1880
+ bool "Clock driver for Bitmain BM1880 SoC"
+ depends on ARCH_BITMAIN || COMPILE_TEST
+ ---help---
+ This driver supports the clocks on Bitmain BM1880 SoC.
+
source "drivers/clk/actions/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 1db133652f0c..6e6d9e44aca6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
obj-$(CONFIG_COMMON_CLK_BD718XX) += clk-bd718x7.o
+obj-$(CONFIG_COMMON_CLK_BM1880) += clk-bm1880.o
obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
diff --git a/drivers/clk/clk-bm1880.c b/drivers/clk/clk-bm1880.c
new file mode 100644
index 000000000000..77211e0dfcfb
--- /dev/null
+++ b/drivers/clk/clk-bm1880.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bitmain BM1880 SoC clock driver
+ *
+ * Copyright (c) 2019 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/bm1880-clock.h>
+
+#define BM1880_REG_WIDTH 32
+
+static DEFINE_SPINLOCK(bm1880_clk_lock);
+
+struct bm1880_clock_data {
+ void __iomem *base;
+ struct clk_onecell_data clk_data;
+};
+
+struct bm1880_gate_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent;
+ unsigned long flags;
+ unsigned long gate_flags;
+};
+
+struct bm1880_composite_clock {
+ unsigned int id;
+ const char *name;
+ const char **parents;
+ unsigned int num_parents;
+ unsigned long rate;
+ unsigned long flags;
+ unsigned long gate_flags;
+ unsigned long rate_flags;
+};
+
+static const struct bm1880_gate_clock bm1880_gate_clks[] = {
+ { BM1880_CLK_A53, "clk_a53", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AHB_ROM, "clk_ahb_rom", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI_SRAM, "clk_axi_sram", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_DDR_AXI, "clk_ddr_axi", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_EFUSE, "clk_efuse", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_APB_EFUSE, "clk_apb_efuse", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI_EMMC, "clk_axi_emmc", NULL, 0, 0 },
+ { BM1880_CLK_EMMC, "clk_emmc", NULL, 0, 0 },
+ { BM1880_CLK_AXI_SD, "clk_axi_sd", NULL, 0, 0 },
+ { BM1880_CLK_SD, "clk_sd", NULL, 0, 0 },
+ { BM1880_CLK_AXI_ETH0, "clk_axi_eth0", NULL, 0, 0 },
+ { BM1880_CLK_AXI_ETH1, "clk_axi_eth1", NULL, 0, 0 },
+ { BM1880_CLK_AXI_GDMA, "clk_axi_gdma", NULL, 0, 0 },
+ { BM1880_CLK_APB_GPIO, "clk_apb_gpio", NULL, 0, 0 },
+ { BM1880_CLK_APB_GPIO_INTR, "clk_apb_gpio_intr", NULL, 0, 0 },
+ { BM1880_CLK_GPIO_DB, "clk_gpio_db", NULL, 0, 0 },
+ { BM1880_CLK_AXI_MINER, "clk_axi_miner", NULL, 0, 0 },
+ { BM1880_CLK_AHB_SF, "clk_ahb_sf", NULL, 0, 0 },
+ { BM1880_CLK_SDMA_AXI, "clk_sdma_axi", NULL, 0, 0 },
+ { BM1880_CLK_SDMA_AUD, "clk_sdma_aud", NULL, 0, 0 },
+ { BM1880_CLK_APB_I2C, "clk_apb_i2c", NULL, 0, 0 },
+ { BM1880_CLK_APB_WDT, "clk_apb_wdt", NULL, 0, 0 },
+ { BM1880_CLK_APB_JPEG, "clk_apb_jpeg", NULL, 0, 0 },
+ { BM1880_CLK_JPEG_AXI, "clk_jpeg_axi", NULL, 0, 0 },
+ { BM1880_CLK_AXI_NF, "clk_axi_nf", NULL, 0, 0 },
+ { BM1880_CLK_APB_NF, "clk_apb_nf", NULL, 0, 0 },
+ { BM1880_CLK_NF, "clk_nf", NULL, 0, 0 },
+ { BM1880_CLK_APB_PWM, "clk_apb_pwm", NULL, 0, 0 },
+ { BM1880_CLK_RV, "clk_rv", NULL, 0, 0 },
+ { BM1880_CLK_APB_SPI, "clk_apb_spi", NULL, 0, 0 },
+ { BM1880_CLK_TPU_AXI, "clk_tpu_axi", NULL, 0, 0 },
+ { BM1880_CLK_APB_UART, "clk_apb_uart", NULL, 0, 0 },
+ { BM1880_CLK_APB_I2S, "clk_apb_i2s", NULL, 0, 0 },
+ { BM1880_CLK_AXI_USB, "clk_axi_usb", NULL, 0, 0 },
+ { BM1880_CLK_APB_USB, "clk_apb_usb", NULL, 0, 0 },
+ { BM1880_CLK_APB_VIDEO, "clk_apb_video", NULL, 0, 0 },
+ { BM1880_CLK_VIDEO_AXI, "clk_video_axi", NULL, 0, 0 },
+ { BM1880_CLK_VPP_AXI, "clk_vpp_axi", NULL, 0, 0 },
+ { BM1880_CLK_APB_VPP, "clk_apb_vpp", NULL, 0, 0 },
+ { BM1880_CLK_AXI1, "clk_axi1", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI2, "clk_axi2", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI3, "clk_axi3", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI4, "clk_axi4", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI5, "clk_axi5", NULL, CLK_IGNORE_UNUSED, 0 },
+ { BM1880_CLK_AXI6, "clk_axi6", NULL, CLK_IGNORE_UNUSED, 0 },
+};
+
+static const struct bm1880_composite_clock bm1880_composite_clks[] = {
+ { BM1880_CLK_50M_A53, "clk_50m_a53", NULL, 0, 50000000, CLK_IGNORE_UNUSED, 0, 0 },
+ { BM1880_CLK_100K_EMMC, "clk_100k_emmc", NULL, 0, 100000, 0, 0, 0 },
+ { BM1880_CLK_100K_SD, "clk_100k_sd", NULL, 0, 100000, 0, 0, 0 },
+ { BM1880_CLK_500M_ETH0, "clk_500m_eth0", NULL, 0, 500000000, 0, 0, 0 },
+ { BM1880_CLK_500M_ETH1, "clk_500m_eth1", NULL, 0, 500000000, 0, 0, 0 },
+ { BM1880_CLK_UART_500M, "clk_uart_500m", NULL, 0, 500000000, 0, 0, 0 },
+ { BM1880_CLK_125M_USB, "clk_125m_usb", NULL, 0, 125000000, 0, 0, 0 },
+ { BM1880_CLK_33K_USB, "clk_33k_usb", NULL, 0, 33000, 0, 0, 0 },
+ { BM1880_CLK_12M_USB, "clk_12m_usb", NULL, 0, 12000000, 0, 0, 0 },
+};
+
+int bm1880_clk_register_gate(const struct bm1880_gate_clock *clks,
+ int num_clks, struct bm1880_clock_data *data)
+{
+ struct clk *clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < num_clks; i++) {
+ clk = clk_register_gate(NULL, clks[i].name,
+ clks[i].parent,
+ clks[i].flags,
+ (base + ((clks[i].id / BM1880_REG_WIDTH) * 4)),
+ clks[i].id % BM1880_REG_WIDTH,
+ clks[i].gate_flags,
+ &bm1880_clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err_clk;
+ }
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err_clk:
+ while (i--)
+ clk_unregister_gate(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+
+int bm1880_clk_register_composite(const struct bm1880_composite_clock *clks,
+ int num_clks, struct bm1880_clock_data *data)
+{
+ struct clk *clk;
+ struct clk_gate *gate = NULL;
+ struct clk_fixed_rate *rate = NULL;
+ void __iomem *base = data->base;
+ int i;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return -ENOMEM;
+
+ rate = kzalloc(sizeof(*rate), GFP_KERNEL);
+ if (!rate)
+ return -ENOMEM;
+
+ for (i = 0; i < num_clks; i++) {
+ gate->flags = clks[i].gate_flags;
+ gate->reg = (base + ((clks[i].id / BM1880_REG_WIDTH) * 4));
+ gate->bit_idx = clks[i].id % BM1880_REG_WIDTH;
+ gate->lock = &bm1880_clk_lock;
+
+ rate->fixed_rate = clks[i].rate;
+ rate->flags = clks[i].rate_flags;
+
+ clk = clk_register_composite(NULL, clks[i].name,
+ clks[i].parents,
+ clks[i].num_parents,
+ NULL, NULL,
+ &rate->hw, &clk_fixed_rate_ops,
+ &gate->hw, &clk_gate_ops,
+ clks[i].flags);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err_clk;
+ }
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err_clk:
+ while (i--)
+ clk_unregister_composite(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+
+static void bm1880_clk_init(struct device_node *np)
+{
+ struct bm1880_clock_data *clk_data;
+ struct clk **clk_table;
+ void __iomem *base;
+ int num_clks;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%pOFn: unable to map resource", np);
+ of_node_put(np);
+ return;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ return;
+
+ clk_data->base = base;
+ num_clks = ARRAY_SIZE(bm1880_gate_clks) +
+ ARRAY_SIZE(bm1880_composite_clks);
+
+ clk_table = kcalloc(num_clks, sizeof(*clk_table), GFP_KERNEL);
+ if (!clk_table)
+ goto err_out;
+
+ clk_data->clk_data.clks = clk_table;
+ clk_data->clk_data.clk_num = num_clks;
+
+ /* Register Gate clocks */
+ bm1880_clk_register_gate(bm1880_gate_clks,
+ ARRAY_SIZE(bm1880_gate_clks),
+ clk_data);
+
+ /* Register Composite clocks */
+ bm1880_clk_register_composite(bm1880_composite_clks,
+ ARRAY_SIZE(bm1880_composite_clks),
+ clk_data);
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+
+ return;
+err_out:
+ kfree(clk_data);
+
+ return;
+}
+
+CLK_OF_DECLARE_DRIVER(bm1880_clk, "bitmain,bm1880-clk", bm1880_clk_init);
diff --git a/include/dt-bindings/clock/bm1880-clock.h b/include/dt-bindings/clock/bm1880-clock.h
new file mode 100644
index 000000000000..de19d7b167f8
--- /dev/null
+++ b/include/dt-bindings/clock/bm1880-clock.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device Tree binding constants for Bitmain BM1880 SoC
+ *
+ * Copyright (c) 2019 Linaro Ltd.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BM1880_H
+#define __DT_BINDINGS_CLOCK_BM1880_H
+
+#define BM1880_CLK_A53 0
+#define BM1880_CLK_50M_A53 1
+#define BM1880_CLK_AHB_ROM 2
+#define BM1880_CLK_AXI_SRAM 3
+#define BM1880_CLK_DDR_AXI 4
+#define BM1880_CLK_EFUSE 5
+#define BM1880_CLK_APB_EFUSE 6
+#define BM1880_CLK_AXI_EMMC 7
+#define BM1880_CLK_EMMC 8
+#define BM1880_CLK_100K_EMMC 9
+#define BM1880_CLK_AXI_SD 10
+#define BM1880_CLK_SD 11
+#define BM1880_CLK_100K_SD 12
+#define BM1880_CLK_500M_ETH0 13
+#define BM1880_CLK_AXI_ETH0 14
+#define BM1880_CLK_500M_ETH1 15
+#define BM1880_CLK_AXI_ETH1 16
+#define BM1880_CLK_AXI_GDMA 17
+#define BM1880_CLK_APB_GPIO 18
+#define BM1880_CLK_APB_GPIO_INTR 19
+#define BM1880_CLK_GPIO_DB 20
+#define BM1880_CLK_AXI_MINER 21
+#define BM1880_CLK_AHB_SF 22
+#define BM1880_CLK_SDMA_AXI 23
+#define BM1880_CLK_SDMA_AUD 24
+#define BM1880_CLK_APB_I2C 25
+#define BM1880_CLK_APB_WDT 26
+#define BM1880_CLK_APB_JPEG 27
+#define BM1880_CLK_JPEG_AXI 28
+#define BM1880_CLK_AXI_NF 29
+#define BM1880_CLK_APB_NF 30
+#define BM1880_CLK_NF 31
+#define BM1880_CLK_APB_PWM 32
+#define BM1880_CLK_RV 33
+#define BM1880_CLK_APB_SPI 34
+#define BM1880_CLK_TPU_AXI 35
+#define BM1880_CLK_UART_500M 36
+#define BM1880_CLK_APB_UART 37
+#define BM1880_CLK_APB_I2S 38
+#define BM1880_CLK_AXI_USB 39
+#define BM1880_CLK_APB_USB 40
+#define BM1880_CLK_125M_USB 41
+#define BM1880_CLK_33K_USB 42
+#define BM1880_CLK_12M_USB 43
+#define BM1880_CLK_APB_VIDEO 44
+#define BM1880_CLK_VIDEO_AXI 45
+#define BM1880_CLK_VPP_AXI 46
+#define BM1880_CLK_APB_VPP 47
+#define BM1880_CLK_AXI1 48
+#define BM1880_CLK_AXI2 49
+#define BM1880_CLK_AXI3 50
+#define BM1880_CLK_AXI4 51
+#define BM1880_CLK_AXI5 52
+#define BM1880_CLK_AXI6 53
+
+#endif /* __DT_BINDINGS_CLOCK_BM1880_H */