diff options
author | Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | 2019-05-11 00:27:44 +0530 |
---|---|---|
committer | Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | 2019-05-14 22:47:48 +0530 |
commit | 73ece2e0f7c7f2ab1373e652ea5d34b9f607fe73 (patch) | |
tree | 4aca56d3f1dd576d7656d82665ca3e8ce0aafcb6 | |
parent | 141a4cf701d71b743e3ddc074a09b30e5cde871f (diff) | |
download | 96b-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.dts | 12 | ||||
-rw-r--r-- | arch/arm64/boot/dts/bitmain/bm1880.dtsi | 23 | ||||
-rw-r--r-- | drivers/clk/Kconfig | 6 | ||||
-rw-r--r-- | drivers/clk/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/clk-bm1880.c | 237 | ||||
-rw-r--r-- | include/dt-bindings/clock/bm1880-clock.h | 66 |
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 */ |