From 466a5e647c47df998c4ec9354c6b8e07dab942e6 Mon Sep 17 00:00:00 2001 From: Bintian Wang Date: Tue, 6 Jan 2015 09:30:36 +0800 Subject: arm64: Enable Hisilicon ARMv8 SoC family in Kconfig and defconfig This patch introduces ARCH_HISI to enable Hisilicon SoC family in Kconfig and defconfig. Signed-off-by: Bintian Wang Reviewed-by: Haojian Zhuang Reviewed-by: Wei Xu Signed-off-by: Xinwei Kong --- arch/arm64/Kconfig | 5 +++++ arch/arm64/configs/defconfig | 1 + 2 files changed, 6 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 533d69d62692..69975d6df4b9 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -286,6 +286,11 @@ config ARCH_ZYNQMP help This enables support for Xilinx ZynqMP Family +config ARCH_HISI + bool "Hisilicon SoC Family" + help + This enables support for Hisilicon ARMv8 Family of SoCs. + endmenu menu "Bus support" diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 2247d8fb49ed..025e20b4ac16 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -356,6 +356,7 @@ CONFIG_ARCH_THUNDER=y CONFIG_ARCH_VEXPRESS=y CONFIG_ARCH_XGENE=y CONFIG_ARCH_ZYNQMP=y +CONFIG_ARCH_HISI=y # # Bus support -- cgit v1.2.3 From cf9077fd2ea62e3ba6bb1f339d3acdefc50d24bb Mon Sep 17 00:00:00 2001 From: Bintian Wang Date: Tue, 6 Jan 2015 09:30:37 +0800 Subject: clk: hi6220: Clock driver support for Hisilicon hi6220 SoC Add clock drivers for hi6220 SoC, this driver controls the SoC registers to supply different clocks to different IPs in the SoC. We add one divider clock for hi6220 because the divider in hi6220 also has a mask bit but it doesnot obey the rule defined by flag "CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by left shift fixed bits (e.g. 16 bits), so we add this divider clock to handle it. This patch also enables this clock driver for ARCH_HISI. Signed-off-by: Bintian Wang Reviewed-by: Haojian Zhuang Reviewed-by: Zhangfei Zhao Signed-off-by: Xinwei Kong --- arch/arm64/Kconfig | 1 + drivers/clk/Kconfig | 2 + drivers/clk/Makefile | 4 +- drivers/clk/hisilicon/Kconfig | 5 + drivers/clk/hisilicon/Makefile | 1 + drivers/clk/hisilicon/clk-hi6220.c | 284 ++++++++++++++++++++++++++++++ drivers/clk/hisilicon/clk.c | 29 +++ drivers/clk/hisilicon/clk.h | 17 ++ drivers/clk/hisilicon/clkdivider-hi6220.c | 272 ++++++++++++++++++++++++++++ include/dt-bindings/clock/hi6220-clock.h | 172 ++++++++++++++++++ 10 files changed, 784 insertions(+), 3 deletions(-) create mode 100644 drivers/clk/hisilicon/Kconfig create mode 100644 drivers/clk/hisilicon/clk-hi6220.c create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c create mode 100644 include/dt-bindings/clock/hi6220-clock.h diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 69975d6df4b9..f7c536e58a17 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -288,6 +288,7 @@ config ARCH_ZYNQMP config ARCH_HISI bool "Hisilicon SoC Family" + select COMMON_CLK_HI6220 help This enables support for Hisilicon ARMv8 Family of SoCs. diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9897f353bf1a..935c44b6c2d2 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -152,6 +152,8 @@ config COMMON_CLK_CDCE706 source "drivers/clk/qcom/Kconfig" +source "drivers/clk/hisilicon/Kconfig" + endmenu source "drivers/clk/bcm/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3d00c25382c5..971995428861 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -47,9 +47,7 @@ obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ -obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ -obj-$(CONFIG_ARCH_HIP04) += hisilicon/ -obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ +obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig new file mode 100644 index 000000000000..e3ead46ae2a4 --- /dev/null +++ b/drivers/clk/hisilicon/Kconfig @@ -0,0 +1,5 @@ +config COMMON_CLK_HI6220 + tristate "Hi6220 Clock Driver" + depends on OF && ARCH_HISI + help + Build the Hisilicon Hi6220 clock driver based on the common clock framework. diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile index 038c02f4d0e7..bbf0539a5d34 100644 --- a/drivers/clk/hisilicon/Makefile +++ b/drivers/clk/hisilicon/Makefile @@ -7,3 +7,4 @@ obj-y += clk.o clkgate-separated.o obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o +obj-$(CONFIG_COMMON_CLK_HI6220) += clkdivider-hi6220.o clk-hi6220.o diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c new file mode 100644 index 000000000000..29c71655817f --- /dev/null +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -0,0 +1,284 @@ +/* + * Hisilicon Hi6220 clock driver + * + * Copyright (c) 2014 Hisilicon Limited. + * + * Author: Bintian Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" + + +/* clocks in AO (always on) controller */ +static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = { + { HI6220_REF32K, "ref32k", NULL, CLK_IS_ROOT, 32764, }, + { HI6220_CLK_TCXO, "clk_tcxo", NULL, CLK_IS_ROOT, 19200000, }, + { HI6220_MMC1_PAD, "mmc1_pad", NULL, CLK_IS_ROOT, 100000000, }, + { HI6220_MMC2_PAD, "mmc2_pad", NULL, CLK_IS_ROOT, 100000000, }, + { HI6220_MMC0_PAD, "mmc0_pad", NULL, CLK_IS_ROOT, 200000000, }, + { HI6220_PLL_BBP, "bbppll0", NULL, CLK_IS_ROOT, 245760000, }, + { HI6220_PLL_GPU, "gpupll", NULL, CLK_IS_ROOT, 1000000000,}, + { HI6220_PLL1_DDR, "ddrpll1", NULL, CLK_IS_ROOT, 1066000000,}, + { HI6220_PLL_SYS, "syspll", NULL, CLK_IS_ROOT, 1200000000,}, + { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,}, + { HI6220_DDR_SRC, "ddr_sel_src", NULL, CLK_IS_ROOT, 1200000000,}, + { HI6220_PLL_MEDIA, "media_pll", NULL, CLK_IS_ROOT, 1440000000,}, + { HI6220_PLL_DDR, "ddrpll0", NULL, CLK_IS_ROOT, 1600000000,}, +}; + +static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = { + { HI6220_300M, "clk_300m", "syspll", 1, 4, 0, }, + { HI6220_150M, "clk_150m", "clk_300m", 1, 2, 0, }, + { HI6220_PICOPHY_SRC, "picophy_src", "clk_150m", 1, 4, 0, }, + { HI6220_MMC0_SRC_SEL, "mmc0srcsel", "mmc0_sel", 1, 8, 0, }, + { HI6220_MMC1_SRC_SEL, "mmc1srcsel", "mmc1_sel", 1, 8, 0, }, + { HI6220_MMC2_SRC_SEL, "mmc2srcsel", "mmc2_sel", 1, 8, 0, }, + { HI6220_VPU_CODEC, "vpucodec", "codec_jpeg_aclk", 1, 2, 0, }, + { HI6220_MMC0_SMP, "mmc0_sample", "mmc0_sel", 1, 8, 0, }, + { HI6220_MMC1_SMP, "mmc1_sample", "mmc1_sel", 1, 8, 0, }, + { HI6220_MMC2_SMP, "mmc2_sample", "mmc2_sel", 1, 8, 0, }, +}; + +static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = { + { HI6220_WDT0_PCLK, "wdt0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, }, + { HI6220_WDT1_PCLK, "wdt1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, }, + { HI6220_WDT2_PCLK, "wdt2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, }, + { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, }, + { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, }, + { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, }, + { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, }, + { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, }, + { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, }, + { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, }, + { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, }, + { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, }, + { HI6220_UART0_PCLK, "uart0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, }, +}; + +static void __init hi6220_clk_ao_init(struct device_node *np) +{ + struct hisi_clock_data *clk_data; + + clk_data = hisi_clk_init(np, HI6220_AO_NR_CLKS); + if (!clk_data) + return; + + hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks, + ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data); + + hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks, + ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data); + + hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao, + ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data); +} +CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-clock-ao", hi6220_clk_ao_init); + + +/* clocks in sysctrl */ +static const char *mmc0_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", }; +static const char *mmc0_mux1_p[] __initconst = { "mmc0_mux0", "pll_media_gate", }; +static const char *mmc0_src_p[] __initconst = { "mmc0srcsel", "mmc0_div", }; +static const char *mmc1_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", }; +static const char *mmc1_mux1_p[] __initconst = { "mmc1_mux0", "pll_media_gate", }; +static const char *mmc1_src_p[] __initconst = { "mmc1srcsel", "mmc1_div", }; +static const char *mmc2_mux0_p[] __initconst = { "pll_ddr_gate", "syspll", }; +static const char *mmc2_mux1_p[] __initconst = { "mmc2_mux0", "pll_media_gate", }; +static const char *mmc2_src_p[] __initconst = { "mmc2srcsel", "mmc2_div", }; +static const char *mmc0_sample_in[] __initconst = { "mmc0_sample", "mmc0_pad", }; +static const char *mmc1_sample_in[] __initconst = { "mmc1_sample", "mmc1_pad", }; +static const char *mmc2_sample_in[] __initconst = { "mmc2_sample", "mmc2_pad", }; +static const char *uart1_src[] __initconst = { "clk_tcxo", "clk_150m", }; +static const char *uart2_src[] __initconst = { "clk_tcxo", "clk_150m", }; +static const char *uart3_src[] __initconst = { "clk_tcxo", "clk_150m", }; +static const char *uart4_src[] __initconst = { "clk_tcxo", "clk_150m", }; +static const char *hifi_src[] __initconst = { "syspll", "pll_media_gate", }; + +static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = { + { HI6220_MMC0_CLK, "mmc0_clk", "mmc0_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, }, + { HI6220_MMC0_CIUCLK, "mmc0_ciuclk", "mmc0_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, }, + { HI6220_MMC1_CLK, "mmc1_clk", "mmc1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, }, + { HI6220_MMC1_CIUCLK, "mmc1_ciuclk", "mmc1_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, }, + { HI6220_MMC2_CLK, "mmc2_clk", "mmc2_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2, 0, }, + { HI6220_MMC2_CIUCLK, "mmc2_ciuclk", "mmc2_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2, 0, }, + { HI6220_USBOTG_HCLK, "usbotg_hclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4, 0, }, + { HI6220_CLK_PICOPHY, "clk_picophy", "cs_dapb", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5, 0, }, + { HI6220_HIFI, "hifi_clk", "hifi_div", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0, 0, }, + { HI6220_DACODEC_PCLK, "dacodec_pclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5, 0, }, + { HI6220_EDMAC_ACLK, "edmac_aclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2, 0, }, + { HI6220_CS_ATB, "cs_atb", "cs_atb_div", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0, 0, }, + { HI6220_I2C0_CLK, "i2c0_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1, 0, }, + { HI6220_I2C1_CLK, "i2c1_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2, 0, }, + { HI6220_I2C2_CLK, "i2c2_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3, 0, }, + { HI6220_I2C3_CLK, "i2c3_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4, 0, }, + { HI6220_UART1_PCLK, "uart1_pclk", "uart1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5, 0, }, + { HI6220_UART2_PCLK, "uart2_pclk", "uart2_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6, 0, }, + { HI6220_UART3_PCLK, "uart3_pclk", "uart3_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7, 0, }, + { HI6220_UART4_PCLK, "uart4_pclk", "uart4_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8, 0, }, + { HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9, 0, }, + { HI6220_MMU_CLK, "mmu_clk", "ddrc_axi1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, }, + { HI6220_HIFI_SEL, "hifi_sel", "hifi_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0, 0, }, + { HI6220_MMC0_SYSPLL, "mmc0_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1, 0, }, + { HI6220_MMC1_SYSPLL, "mmc1_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2, 0, }, + { HI6220_MMC2_SYSPLL, "mmc2_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3, 0, }, + { HI6220_MMC0_SEL, "mmc0_sel", "mmc0_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6, 0, }, + { HI6220_MMC1_SEL, "mmc1_sel", "mmc1_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7, 0, }, + { HI6220_BBPPLL_SEL, "bbppll_sel", "pll0_bbp_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9, 0, }, + { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, }, + { HI6220_MMC2_SEL, "mmc2_sel", "mmc2_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, }, + { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, }, +}; + +static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = { + { HI6220_MMC0_SRC, "mmc0_src", mmc0_src_p, ARRAY_SIZE(mmc0_src_p), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, }, + { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, }, + { HI6220_MMC1_SRC, "mmc1_src", mmc1_src_p, ARRAY_SIZE(mmc1_src_p), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, }, + { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, }, + { HI6220_MMC2_SRC, "mmc2_src", mmc2_src_p, ARRAY_SIZE(mmc2_src_p), CLK_SET_RATE_PARENT, 0x4, 4, 1, 0, }, + { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4, 4, 1, 0, }, + { HI6220_HIFI_SRC, "hifi_src", hifi_src, ARRAY_SIZE(hifi_src), CLK_SET_RATE_PARENT, 0x400, 0, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_UART1_SRC, "uart1_src", uart1_src, ARRAY_SIZE(uart1_src), CLK_SET_RATE_PARENT, 0x400, 1, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_UART2_SRC, "uart2_src", uart2_src, ARRAY_SIZE(uart2_src), CLK_SET_RATE_PARENT, 0x400, 2, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_UART3_SRC, "uart3_src", uart3_src, ARRAY_SIZE(uart3_src), CLK_SET_RATE_PARENT, 0x400, 3, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_UART4_SRC, "uart4_src", uart4_src, ARRAY_SIZE(uart4_src), CLK_SET_RATE_PARENT, 0x400, 4, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_MMC0_MUX0, "mmc0_mux0", mmc0_mux0_p, ARRAY_SIZE(mmc0_mux0_p), CLK_SET_RATE_PARENT, 0x400, 5, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_MMC1_MUX0, "mmc1_mux0", mmc1_mux0_p, ARRAY_SIZE(mmc1_mux0_p), CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_MMC2_MUX0, "mmc2_mux0", mmc2_mux0_p, ARRAY_SIZE(mmc2_mux0_p), CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_MMC0_MUX1, "mmc0_mux1", mmc0_mux1_p, ARRAY_SIZE(mmc0_mux1_p), CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_MMC1_MUX1, "mmc1_mux1", mmc1_mux1_p, ARRAY_SIZE(mmc1_mux1_p), CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,}, + { HI6220_MMC2_MUX1, "mmc2_mux1", mmc2_mux1_p, ARRAY_SIZE(mmc2_mux1_p), CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,}, +}; + +static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = { + { HI6220_CLK_BUS, "clk_bus", "clk_300m", CLK_SET_RATE_PARENT, 0x490, 0, 4, 7, }, + { HI6220_MMC0_DIV, "mmc0_div", "mmc0_syspll", CLK_SET_RATE_PARENT, 0x494, 0, 6, 7, }, + { HI6220_MMC1_DIV, "mmc1_div", "mmc1_syspll", CLK_SET_RATE_PARENT, 0x498, 0, 6, 7, }, + { HI6220_MMC2_DIV, "mmc2_div", "mmc2_syspll", CLK_SET_RATE_PARENT, 0x49c, 0, 6, 7, }, + { HI6220_HIFI_DIV, "hifi_div", "hifi_sel", CLK_SET_RATE_PARENT, 0x4a0, 0, 4, 7, }, + { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel", CLK_SET_RATE_PARENT, 0x4a0, 8, 6, 15,}, + { HI6220_CS_DAPB, "cs_dapb", "picophy_src", CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,}, + { HI6220_CS_ATB_DIV, "cs_atb_div", "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0, 4, 7, }, +}; + +static void __init hi6220_clk_sys_init(struct device_node *np) +{ + struct hisi_clock_data *clk_data; + + clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS); + if (!clk_data) + return; + + hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys, + ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data); + + hisi_clk_register_mux(hi6220_mux_clks_sys, + ARRAY_SIZE(hi6220_mux_clks_sys), clk_data); + + hi6220_clk_register_divider(hi6220_div_clks_sys, + ARRAY_SIZE(hi6220_div_clks_sys), clk_data); +} +CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-clock-sys", hi6220_clk_sys_init); + + +/* clocks in media controller */ +static const char *clk_1000_1200_src[] __initconst = { "pll_gpu_gate", "media_syspll_src", }; +static const char *clk_1440_1200_src[] __initconst = { "media_syspll_src", "media_pll_src", }; +static const char *clk_1000_1440_src[] __initconst = { "pll_gpu_gate", "media_pll_src", }; + +static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = { + { HI6220_DSI_PCLK, "dsi_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0, 0, }, + { HI6220_G3D_PCLK, "g3d_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1, 0, }, + { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3, 0, }, + { HI6220_ISP_SCLK, "isp_sclk", "isp_sclk_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5, 0, }, + { HI6220_ADE_CORE, "ade_core", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6, 0, }, + { HI6220_MED_MMU, "media_mmu", "mmu_clk", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8, 0, }, + { HI6220_CFG_CSI4PHY, "cfg_csi4phy", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9, 0, }, + { HI6220_CFG_CSI2PHY, "cfg_csi2phy", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, }, + { HI6220_ISP_SCLK_GATE, "isp_sclk_gate", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, }, + { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, }, + { HI6220_ADE_CORE_GATE, "ade_core_gate", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, }, + { HI6220_CODEC_VPU_GATE, "codec_vpu_gate", "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, }, + { HI6220_MED_SYSPLL, "media_syspll_src", "media_syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, }, +}; + +static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = { + { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, }, + { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, }, + { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, }, +}; + +static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = { + { HI6220_CODEC_JPEG, "codec_jpeg_aclk", "media_pll_src", CLK_SET_RATE_PARENT, 0xcbc, 0, 4, 23, }, + { HI6220_ISP_SCLK_SRC, "isp_sclk_src", "isp_sclk_gate", CLK_SET_RATE_PARENT, 0xcbc, 8, 4, 15, }, + { HI6220_ISP_SCLK1, "isp_sclk1", "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, }, + { HI6220_ADE_CORE_SRC, "ade_core_src", "ade_core_gate", CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, }, + { HI6220_ADE_PIX_SRC, "ade_pix_src", "clk_1440_1200", CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, }, + { HI6220_G3D_CLK, "g3d_clk", "clk_1000_1200", CLK_SET_RATE_PARENT, 0xcc4, 8, 4, 15, }, + { HI6220_CODEC_VPU_SRC,"codec_vpu_src", "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, }, +}; + +static void __init hi6220_clk_media_init(struct device_node *np) +{ + struct hisi_clock_data *clk_data; + + clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS); + if (!clk_data) + return; + + hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media, + ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data); + + hisi_clk_register_mux(hi6220_mux_clks_media, + ARRAY_SIZE(hi6220_mux_clks_media), clk_data); + + hi6220_clk_register_divider(hi6220_div_clks_media, + ARRAY_SIZE(hi6220_div_clks_media), clk_data); +} +CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-clock-media", hi6220_clk_media_init); + + +/* clocks in pmctrl */ +static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = { + { HI6220_PLL_GPU_GATE, "pll_gpu_gate", "gpupll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8, 0, 0, }, + { HI6220_PLL1_DDR_GATE, "pll1_ddr_gate", "ddrpll1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0, 0, }, + { HI6220_PLL_DDR_GATE, "pll_ddr_gate", "ddrpll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0, 0, }, + { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0, 0, }, + { HI6220_PLL0_BBP_GATE, "pll0_bbp_gate", "bbppll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0, 0, }, +}; + +static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = { + { HI6220_DDRC_SRC, "ddrc_src", "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, }, + { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src", CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, }, +}; + +static void __init hi6220_clk_power_init(struct device_node *np) +{ + struct hisi_clock_data *clk_data; + + clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS); + if (!clk_data) + return; + + hisi_clk_register_gate(hi6220_gate_clks_power, + ARRAY_SIZE(hi6220_gate_clks_power), clk_data); + + hi6220_clk_register_divider(hi6220_div_clks_power, + ARRAY_SIZE(hi6220_div_clks_power), clk_data); +} +CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-clock-power", hi6220_clk_power_init); diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index a078e84f7b05..5d2305c0b881 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, data->clk_data.clks[clks[i].id] = clk; } } + +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks, + int nums, struct hisi_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + clk = hi6220_register_clkdiv(NULL, clks[i].name, + clks[i].parent_name, + clks[i].flags, + base + clks[i].offset, + clks[i].shift, + clks[i].width, + clks[i].mask_bit, + &hisi_clk_lock); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + data->clk_data.clks[clks[i].id] = clk; + } +} diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 31083ffc0650..462a5704c734 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -79,6 +79,18 @@ struct hisi_divider_clock { const char *alias; }; +struct hi6220_divider_clock { + unsigned int id; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long offset; + u8 shift; + u8 width; + u32 mask_bit; + const char *alias; +}; + struct hisi_gate_clock { unsigned int id; const char *name; @@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *, const char *, unsigned long, void __iomem *, u8, u8, spinlock_t *); +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, void __iomem *reg, + u8 shift, u8 width, u32 mask_bit, spinlock_t *lock); struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int); void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *, @@ -108,4 +123,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *, int, struct hisi_clock_data *); void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, int, struct hisi_clock_data *); +void __init hi6220_clk_register_divider(struct hi6220_divider_clock *, + int, struct hisi_clock_data *); #endif /* __HISI_CLK_H */ diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c new file mode 100644 index 000000000000..af8fa62b4cc6 --- /dev/null +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c @@ -0,0 +1,272 @@ +/* + * Hisilicon hi6220 SoC divider clock driver + * + * Copyright (c) 2013-2014 Hisilicon Limited. + * Author: Bintian Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#define div_mask(width) ((1 << (width)) - 1) + +/* + * The reverse of DIV_ROUND_UP: The maximum number which + * divided by m is r + */ +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) + +/** + * struct hi6220_clk_divider - divider clock for hi6220 + * + * @hw: handle between common and hardware-specific interfaces + * @reg: register containing divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @mask: mask for setting divider rate + * @table: the div table that the divider supports + * @lock: register lock + */ +struct hi6220_clk_divider { + struct clk_hw hw; + void __iomem *reg; + u8 shift; + u8 width; + u32 mask; + const struct clk_div_table *table; + spinlock_t *lock; +}; + +#define to_hi6220_clk_divider(_hw) \ + container_of(_hw, struct hi6220_clk_divider, hw) + +static unsigned int hi6220_get_table_maxdiv(const struct clk_div_table *table) +{ + unsigned int maxdiv = 0; + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div > maxdiv) + maxdiv = clkt->div; + return maxdiv; +} + +static unsigned int hi6220_get_table_div(const struct clk_div_table *table, + unsigned int val) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->val == val) + return clkt->div; + + return 0; +} + +static unsigned int hi6220_get_table_val(const struct clk_div_table *table, + unsigned int div) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return clkt->val; + return 0; +} + +static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + unsigned int div, val; + struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw); + + val = readl_relaxed(dclk->reg) >> dclk->shift; + val &= div_mask(dclk->width); + + div = hi6220_get_table_div(dclk->table, val); + if (!div) { + pr_warn("%s: Invalid divisor for clock %s\n", __func__, + __clk_get_name(hw->clk)); + return parent_rate; + } + + return parent_rate / div; +} + +static bool hi6220_is_valid_div(const struct clk_div_table *table, + unsigned int div) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return true; + return false; +} + +static int hi6220_clkdiv_bestdiv(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate) +{ + unsigned int i, bestdiv = 0; + unsigned long parent_rate, best = 0, now, maxdiv; + + struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw); + struct clk *clk_parent = __clk_get_parent(hw->clk); + + maxdiv = hi6220_get_table_maxdiv(dclk->table); + + if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { + parent_rate = *best_parent_rate; + bestdiv = DIV_ROUND_UP(parent_rate, rate); + bestdiv = (bestdiv == 0) ? 1 : bestdiv; + bestdiv = (bestdiv > maxdiv) ? maxdiv : bestdiv; + return bestdiv; + } + + /* + * The maximum divider we can use without overflowing + * unsigned long in rate * i below + */ + maxdiv = min(ULONG_MAX / rate, maxdiv); + + for (i = 1; i <= maxdiv; i++) { + if (!hi6220_is_valid_div(dclk->table, i)) + continue; + parent_rate = __clk_round_rate(clk_parent, + MULT_ROUND_UP(rate, i)); + now = parent_rate / i; + if (now <= rate && now > best) { + bestdiv = i; + best = now; + *best_parent_rate = parent_rate; + } + } + + if (!bestdiv) { + bestdiv = hi6220_get_table_maxdiv(dclk->table); + *best_parent_rate = __clk_round_rate(clk_parent, 1); + } + + return bestdiv; +} + +static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + int div; + + if (!rate) + rate = 1; + + div = hi6220_clkdiv_bestdiv(hw, rate, prate); + + return *prate / div; +} + +static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + unsigned int div, value; + unsigned long flags = 0; + u32 data; + struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw); + + div = parent_rate / rate; + + if (!hi6220_is_valid_div(dclk->table, div)) + return -EINVAL; + + value = hi6220_get_table_val(dclk->table, div); + + if (value > div_mask(dclk->width)) + value = div_mask(dclk->width); + + if (dclk->lock) + spin_lock_irqsave(dclk->lock, flags); + + data = readl_relaxed(dclk->reg); + data &= ~(div_mask(dclk->width) << dclk->shift); + data |= value << dclk->shift; + data |= dclk->mask; + + writel_relaxed(data, dclk->reg); + + if (dclk->lock) + spin_unlock_irqrestore(dclk->lock, flags); + + return 0; +} + +static struct clk_ops hi6220_clkdiv_ops = { + .recalc_rate = hi6220_clkdiv_recalc_rate, + .round_rate = hi6220_clkdiv_round_rate, + .set_rate = hi6220_clkdiv_set_rate, +}; + +struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, void __iomem *reg, + u8 shift, u8 width, u32 mask_bit, spinlock_t *lock) +{ + struct hi6220_clk_divider *div; + struct clk *clk; + struct clk_init_data init; + struct clk_div_table *table; + u32 max_div, min_div; + int i; + + /* allocate the divider */ + div = kzalloc(sizeof(struct hi6220_clk_divider), GFP_KERNEL); + if (!div) { + pr_err("%s: could not allocate divider clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + /* Init the divider table */ + max_div = div_mask(width) + 1; + min_div = 1; + + table = kzalloc(sizeof(struct clk_div_table) * (max_div + 1), GFP_KERNEL); + if (!table) { + kfree(div); + pr_err("%s: failed to alloc divider table!\n", __func__); + return ERR_PTR(-ENOMEM); + } + + for (i = 0; i < max_div; i++) { + table[i].div = min_div + i; + table[i].val = table[i].div - 1; + } + + init.name = name; + init.ops = &hi6220_clkdiv_ops; + init.flags = flags | CLK_IS_BASIC; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + + /* struct hi6220_clk_divider assignments */ + div->reg = reg; + div->shift = shift; + div->width = width; + div->mask = mask_bit ? BIT(mask_bit) : 0; + div->lock = lock; + div->hw.init = &init; + div->table = table; + + /* register the clock */ + clk = clk_register(dev, &div->hw); + + if (IS_ERR(clk)) { + kfree(table); + kfree(div); + } + + return clk; +} diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h new file mode 100644 index 000000000000..d03d828f46c9 --- /dev/null +++ b/include/dt-bindings/clock/hi6220-clock.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014 Hisilicon Limited. + * + * Author: Bintian Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __DT_BINDINGS_CLOCK_HI6220_H +#define __DT_BINDINGS_CLOCK_HI6220_H + +/* clk in AO (always on) controller */ +#define HI6220_NONE_CLOCK 0 + +/* fixed rate clocks */ +#define HI6220_REF32K 1 +#define HI6220_CLK_TCXO 2 +#define HI6220_MMC1_PAD 3 +#define HI6220_MMC2_PAD 4 +#define HI6220_MMC0_PAD 5 +#define HI6220_PLL_BBP 6 +#define HI6220_PLL_GPU 7 +#define HI6220_PLL1_DDR 8 +#define HI6220_PLL_SYS 9 +#define HI6220_PLL_SYS_MEDIA 10 +#define HI6220_DDR_SRC 11 +#define HI6220_PLL_MEDIA 12 +#define HI6220_PLL_DDR 13 + +/* fixed factor clocks */ +#define HI6220_300M 16 +#define HI6220_150M 17 +#define HI6220_PICOPHY_SRC 18 +#define HI6220_MMC0_SRC_SEL 19 +#define HI6220_MMC1_SRC_SEL 20 +#define HI6220_MMC2_SRC_SEL 21 +#define HI6220_VPU_CODEC 22 +#define HI6220_MMC0_SMP 23 +#define HI6220_MMC1_SMP 24 +#define HI6220_MMC2_SMP 25 + +/* gate clocks */ +#define HI6220_WDT0_PCLK 28 +#define HI6220_WDT1_PCLK 29 +#define HI6220_WDT2_PCLK 30 +#define HI6220_TIMER0_PCLK 31 +#define HI6220_TIMER1_PCLK 32 +#define HI6220_TIMER2_PCLK 33 +#define HI6220_TIMER3_PCLK 34 +#define HI6220_TIMER4_PCLK 35 +#define HI6220_TIMER5_PCLK 36 +#define HI6220_TIMER6_PCLK 37 +#define HI6220_TIMER7_PCLK 38 +#define HI6220_TIMER8_PCLK 39 +#define HI6220_UART0_PCLK 40 + +#define HI6220_AO_NR_CLKS 48 + +/* clk in systrl */ +/* gate clock */ +#define HI6220_MMC0_CLK 1 +#define HI6220_MMC0_CIUCLK 2 +#define HI6220_MMC1_CLK 3 +#define HI6220_MMC1_CIUCLK 4 +#define HI6220_MMC2_CLK 5 +#define HI6220_MMC2_CIUCLK 6 +#define HI6220_USBOTG_HCLK 7 +#define HI6220_CLK_PICOPHY 8 +#define HI6220_HIFI 9 +#define HI6220_DACODEC_PCLK 10 +#define HI6220_EDMAC_ACLK 11 +#define HI6220_CS_ATB 12 +#define HI6220_I2C0_CLK 13 +#define HI6220_I2C1_CLK 14 +#define HI6220_I2C2_CLK 15 +#define HI6220_I2C3_CLK 16 +#define HI6220_UART1_PCLK 17 +#define HI6220_UART2_PCLK 18 +#define HI6220_UART3_PCLK 19 +#define HI6220_UART4_PCLK 20 +#define HI6220_SPI_CLK 21 +#define HI6220_MMU_CLK 22 +#define HI6220_HIFI_SEL 23 +#define HI6220_MMC0_SYSPLL 24 +#define HI6220_MMC1_SYSPLL 25 +#define HI6220_MMC2_SYSPLL 26 +#define HI6220_MMC0_SEL 27 +#define HI6220_MMC1_SEL 28 +#define HI6220_BBPPLL_SEL 29 +#define HI6220_MEDIA_PLL_SRC 30 +#define HI6220_MMC2_SEL 31 +#define HI6220_CS_ATB_SYSPLL 32 + +/* mux clocks */ +#define HI6220_MMC0_SRC 35 +#define HI6220_MMC0_SMP_IN 36 +#define HI6220_MMC1_SRC 37 +#define HI6220_MMC1_SMP_IN 38 +#define HI6220_MMC2_SRC 39 +#define HI6220_MMC2_SMP_IN 40 +#define HI6220_HIFI_SRC 41 +#define HI6220_UART1_SRC 42 +#define HI6220_UART2_SRC 43 +#define HI6220_UART3_SRC 44 +#define HI6220_UART4_SRC 45 +#define HI6220_MMC0_MUX0 46 +#define HI6220_MMC1_MUX0 47 +#define HI6220_MMC2_MUX0 48 +#define HI6220_MMC0_MUX1 49 +#define HI6220_MMC1_MUX1 50 +#define HI6220_MMC2_MUX1 51 + +/* divider clocks */ +#define HI6220_CLK_BUS 54 +#define HI6220_MMC0_DIV 55 +#define HI6220_MMC1_DIV 56 +#define HI6220_MMC2_DIV 57 +#define HI6220_HIFI_DIV 58 +#define HI6220_BBPPLL0_DIV 59 +#define HI6220_CS_DAPB 60 +#define HI6220_CS_ATB_DIV 61 + +#define HI6220_SYS_NR_CLKS 64 + +/* clk in media controller */ +/* gate clocks */ +#define HI6220_DSI_PCLK 1 +#define HI6220_G3D_PCLK 2 +#define HI6220_ACLK_CODEC_VPU 3 +#define HI6220_ISP_SCLK 4 +#define HI6220_ADE_CORE 5 +#define HI6220_MED_MMU 6 +#define HI6220_CFG_CSI4PHY 7 +#define HI6220_CFG_CSI2PHY 8 +#define HI6220_ISP_SCLK_GATE 9 +#define HI6220_ISP_SCLK_GATE1 10 +#define HI6220_ADE_CORE_GATE 11 +#define HI6220_CODEC_VPU_GATE 12 +#define HI6220_MED_SYSPLL 13 + +/* mux clocks */ +#define HI6220_1440_1200 20 +#define HI6220_1000_1200 21 +#define HI6220_1000_1440 22 + +/* divider clocks */ +#define HI6220_CODEC_JPEG 30 +#define HI6220_ISP_SCLK_SRC 31 +#define HI6220_ISP_SCLK1 32 +#define HI6220_ADE_CORE_SRC 33 +#define HI6220_ADE_PIX_SRC 34 +#define HI6220_G3D_CLK 35 +#define HI6220_CODEC_VPU_SRC 36 + +#define HI6220_MEDIA_NR_CLKS 40 + +/* clk in power controller */ +/* gate clocks */ +#define HI6220_PLL_GPU_GATE 1 +#define HI6220_PLL1_DDR_GATE 2 +#define HI6220_PLL_DDR_GATE 3 +#define HI6220_PLL_MEDIA_GATE 4 +#define HI6220_PLL0_BBP_GATE 5 + +/* divider clocks */ +#define HI6220_DDRC_SRC 10 +#define HI6220_DDRC_AXI1 11 + +#define HI6220_POWER_NR_CLKS 16 +#endif -- cgit v1.2.3 From b9349112eccaab3e3210c27828fd56d1121dc479 Mon Sep 17 00:00:00 2001 From: Bintian Wang Date: Tue, 6 Jan 2015 09:30:38 +0800 Subject: clk: hi6220: Document devicetree bindings for hi6220 clock Document DT files bindings for Hisilicon hi6220 clock. Signed-off-by: Bintian Wang Reviewed-by: Haojian Zhuang Signed-off-by: Xinwei Kong --- .../devicetree/bindings/clock/hi6220-clock.txt | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/hi6220-clock.txt diff --git a/Documentation/devicetree/bindings/clock/hi6220-clock.txt b/Documentation/devicetree/bindings/clock/hi6220-clock.txt new file mode 100644 index 000000000000..5c3a50a3f724 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/hi6220-clock.txt @@ -0,0 +1,26 @@ +* Hisilicon Hi6220 Clock Controller + +The hi6220 clock controller generates and supplies clock to various +controllers within the hi6220 SoC. + +Required Properties: + +- compatible: should be one of the following. + - "hisilicon,hi6220-clock-ao" - controller for those clocks under + SoC power always on domain. + - "hisilicon,hi6220-clock-sys" - controller for those clocks under + SoC system control domain. + - "hisilicon,hi6220-clock-media" - controller for those clocks under + SoC media control domain. + - "hisilicon,hi6220-clock-power" - controller for those clocks under + SoC power control domain. + +- reg: physical base address of the controller and length of memory mapped + region. + +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes use this identifier +to specify the clock which they consume. + +All these identifier could be found in . -- cgit v1.2.3 From 418f870f18afd695c7446d187ccf526af4321edb Mon Sep 17 00:00:00 2001 From: Bintian Wang Date: Tue, 6 Jan 2015 09:30:39 +0800 Subject: arm64: dts: Add dts files for Hisilicon Hi6220 SoC and HiKey board Add initial dtsi file to support Hisilicon Hi6220 SoC with support of Octal core CPUs in two clusters and each cluster has quard Cortex-A53. Also add dts file to support HiKey development board which is based on Hi6220 SoC. These dts files will be changed later and more nodes will be added to describe other devices. Signed-off-by: Bintian Wang Reviewed-by: Haojian Zhuang Reviewed-by: Yiping Xu Signed-off-by: John Stultz --- arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/hisilicon/Makefile | 1 + arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 36 ++++ arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 220 +++++++++++++++++++++++++ arch/arm64/configs/defconfig | 1 - 5 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts create mode 100644 arch/arm64/boot/dts/hisilicon/hi6220.dtsi diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 8275d2b8f1f4..3fa4955c0841 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -7,6 +7,7 @@ dts-dirs += freescale dts-dirs += mediatek dts-dirs += qcom dts-dirs += sprd +dts-dirs += hisilicon dts-dirs += xilinx dts-dirs += hisilicon diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile index 2ef991fd29d2..fd4ea729b9ef 100644 --- a/arch/arm64/boot/dts/hisilicon/Makefile +++ b/arch/arm64/boot/dts/hisilicon/Makefile @@ -1,5 +1,6 @@ dtb-$(CONFIG_ARCH_P660) += hisi_p660_evb.dtb hip05-d02.dtb dtb-$(CONFIG_ARCH_Hi1610) += hi1610_32c-evb.dtb +dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts new file mode 100644 index 000000000000..8876bb6bd541 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -0,0 +1,36 @@ +/* + * dts file for Hisilicon HiKey Development Board + * + * Copyright (C) 2014, Hisilicon Ltd. + * + */ + +/dts-v1/; + +/memreserve/ 0x00000000 0x07400000; +/memreserve/ 0x0740f000 0x1000; + +#include "hi6220.dtsi" + +/ { + model = "HiKey Development Board"; + compatible = "hisilicon,hikey"; + hisi,boardid = <0 0 4 3>; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + + aliases { + serial0 = &uart0; + }; + + chosen { + linux,initrd-start = <0x0 0x0ae00000>; + linux,initrd-end = <0x0 0x0b600000>; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x00000000 0x0 0x40000000>; + }; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi new file mode 100644 index 000000000000..e70f35313f07 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -0,0 +1,220 @@ +/* + * dts file for Hisilicon Hi6220 SoC + * + * Copyright (C) 2014, Hisilicon Ltd. + */ + +#include + +/ { + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + operating-points = < + /* kHz */ + 208000 0 + 432000 0 + 729000 0 + 960000 0 + 1200000 0 + >; + }; + cpu1: cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x1>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + }; + cpu2: cpu@2 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x2>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + }; + cpu3: cpu@3 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x3>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + }; + cpu4: cpu@4 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x100>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + operating-points = < + /* kHz */ + 208000 0 + 432000 0 + 729000 0 + 960000 0 + 1200000 0 + >; + }; + cpu5: cpu@5 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x101>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + }; + cpu6: cpu@6 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x102>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + }; + cpu7: cpu@7 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x103>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x740fff8>; + clock-latency = <0>; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + }; + }; + + gic: interrupt-controller@f6800000 { + compatible = "arm,gic-400", "arm,cortex-a15-gic"; + reg = <0x0 0xf6801000 0x0 0x1000>, /* GICD */ + <0x0 0xf6802000 0x0 0x2000>, /* GICC */ + <0x0 0xf6804000 0x0 0x2000>, /* GICH */ + <0x0 0xf6806000 0x0 0x2000>; /* GICV */ + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + }; + + ao_ctrl: ao_ctrl { + compatible = "hisilicon,aoctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0xf7800000 0x0 0x2000>; + ranges = <0 0x0 0xf7800000 0x2000>; + + clock_ao: clock0@0 { + compatible = "hisilicon,hi6220-clock-ao"; + reg = <0 0x1000>; + #clock-cells = <1>; + }; + }; + + sys_ctrl: sys_ctrl { + compatible = "hisilicon,sysctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0xf7030000 0x0 0x2000>; + ranges = <0 0x0 0xf7030000 0x2000>; + + clock_sys: clock1@0 { + compatible = "hisilicon,hi6220-clock-sys"; + reg = <0 0x1000>; + #clock-cells = <1>; + }; + }; + + media_ctrl: media_ctrl { + compatible = "hisilicon,mediactrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0xf4410000 0x0 0x1000>; + ranges = <0 0x0 0xf4410000 0x1000>; + + clock_media: clock2@0 { + compatible = "hisilicon,hi6220-clock-media"; + reg = <0 0x1000>; + #clock-cells = <1>; + }; + }; + + pm_ctrl: pm_ctrl { + compatible = "hisilicon,pmctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0xf7032000 0x0 0x1000>; + ranges = <0 0x0 0xf7032000 0x1000>; + + clock_power: clock3@0 { + compatible = "hisilicon,hi6220-clock-power"; + reg = <0 0x1000>; + #clock-cells = <1>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = <1 13 0xff08>, + <1 14 0xff08>, + <1 11 0xff08>, + <1 10 0xff08>; + clock-frequency = <1200000>; + }; + + smb { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + ranges; + + uart0: uart@f8015000 { /* console */ + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0xf8015000 0x0 0x1000>; + interrupts = <0 36 4>; + clocks = <&clock_ao HI6220_UART0_PCLK>; + clock-names = "apb_pclk"; + status = "ok"; + }; + }; +}; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 025e20b4ac16..2247d8fb49ed 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -356,7 +356,6 @@ CONFIG_ARCH_THUNDER=y CONFIG_ARCH_VEXPRESS=y CONFIG_ARCH_XGENE=y CONFIG_ARCH_ZYNQMP=y -CONFIG_ARCH_HISI=y # # Bus support -- cgit v1.2.3