From 8b5ae71fdf9f257387effbbf80f3d571013f3d4f Mon Sep 17 00:00:00 2001 From: Qiufang Dai Date: Sat, 23 Dec 2017 17:32:27 +0800 Subject: [PATCH] clock: clock tree for G12A PD#156734: base clock tree for G12A, include clk81, ee gate, sdemmc clock, fix/hifi/syspll/pcie plls, mpll, clkmsr Change-Id: I9fe7c1d64d9db5d384070f5dcefdc69f5f60dbd2 Signed-off-by: Qiufang Dai --- .../bindings/clock/amlogic,meson-clkc.txt | 1 + MAINTAINERS | 3 + arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 2 +- drivers/amlogic/clk/Makefile | 1 + drivers/amlogic/clk/clk_measure.c | 147 +++ drivers/amlogic/clk/clkc.h | 7 + drivers/amlogic/clk/g12a/Makefile | 9 + drivers/amlogic/clk/g12a/g12a.c | 958 ++++++++++++++++++ drivers/amlogic/clk/g12a/g12a.h | 129 +++ drivers/amlogic/clk/g12a/g12a_clk-mpll.c | 170 ++++ drivers/amlogic/clk/g12a/g12a_clk-pll.c | 392 +++++++ drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c | 169 +++ include/dt-bindings/clock/amlogic,g12a-clkc.h | 276 ++--- 13 files changed, 2136 insertions(+), 128 deletions(-) create mode 100644 drivers/amlogic/clk/g12a/Makefile create mode 100644 drivers/amlogic/clk/g12a/g12a.c create mode 100644 drivers/amlogic/clk/g12a/g12a.h create mode 100644 drivers/amlogic/clk/g12a/g12a_clk-mpll.c create mode 100644 drivers/amlogic/clk/g12a/g12a_clk-pll.c create mode 100644 drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt index ae2fa0c1aeb1..6b91cc2b4f7c 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt @@ -12,6 +12,7 @@ Required Properties: "amlogic,axg-aoclkc" - for axg ao clock "amlogic,txlx-clkc" - for txlx ee clock "amlogic,txlx-aoclkc" - for txlx ao clock + "amlogic,g12a-clkc" - for g12a ee clock - reg: physical base address of the clock controller and length of memory mapped region. diff --git a/MAINTAINERS b/MAINTAINERS index 3273c09ed0cc..f148cc55de0e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14277,3 +14277,6 @@ F: arch/arm64/boot/dts/amlogic/mesong12a.dtsi F: arch/arm64/boot/dts/amlogic/g12a_pxp.dts F: include/dt-bindings/clock/amlogic,g12a-audio-clk.h F: include/dt-bindings/clock/amlogic,g12a-clkc.h +F: drivers/amlogic/clk/g12a/* +F: drivers/amlogic/clk/clkc.h + diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 3c1106ae3814..68e820f7d513 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -247,7 +247,7 @@ ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; clkc: clock-controller@0 { - compatible = "amlogic,axg-clkc"; + compatible = "amlogic,g12a-clkc"; #clock-cells = <1>; reg = <0x0 0x0 0x0 0x320>; }; diff --git a/drivers/amlogic/clk/Makefile b/drivers/amlogic/clk/Makefile index cc0e619dd657..66aad270c558 100644 --- a/drivers/amlogic/clk/Makefile +++ b/drivers/amlogic/clk/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_AMLOGIC_GX_CLK) += clk-cpu.o clk-mpll.o clk_test.o obj-$(CONFIG_AMLOGIC_GX_CLK) += gxl/ obj-$(CONFIG_AMLOGIC_GX_CLK) += axg/ obj-$(CONFIG_AMLOGIC_GX_CLK) += txlx/ +obj-$(CONFIG_AMLOGIC_GX_CLK) += g12a/ obj-$(CONFIG_AMLOGIC_M8B_CLK) += m8b/ diff --git a/drivers/amlogic/clk/clk_measure.c b/drivers/amlogic/clk/clk_measure.c index 1fe16b594bf1..3bfc764a7d7e 100644 --- a/drivers/amlogic/clk/clk_measure.c +++ b/drivers/amlogic/clk/clk_measure.c @@ -145,6 +145,7 @@ static unsigned int axg_clk_util_clk_msr(unsigned int clk_mux) } return 0; } + int m8b_clk_measure(struct seq_file *s, void *what, unsigned int index) { static const char * const clk_table[] = { @@ -694,6 +695,149 @@ int txlx_clk_measure(struct seq_file *s, void *what, unsigned int index) return 0; } +int g12a_clk_measure(struct seq_file *s, void *what, unsigned int index) +{ + static const char * const clk_table[] = { + [122] = "mod_audio_pdm_dclk_o ", + [121] = "audio_spdifin_mst_clk ", + [120] = "audio_spdifout_mst_clk ", + [119] = "audio_spdifout_b_mst_clk ", + [118] = "audio_pdm_sysclk ", + [117] = "audio_resample_clk ", + [116] = "audio_tdmin_a_sclk ", + [115] = "audio_tdmin_b_sclk ", + [114] = "audio_tdmin_c_sclk ", + [113] = "audio_tdmin_lb_sclk ", + [112] = "audio_tdmout_a_sclk ", + [111] = "audio_tdmout_b_sclk ", + [110] = "audio_tdmout_c_sclk ", + [109] = "c_alocker_out_clk ", + [108] = "c_alocker_in_clk ", + [107] = "au_dac_clk_g128x ", + [106] = "ephy_test_clk ", + [105] = "am_ring_osc_clk_out_ee[9] ", + [104] = "am_ring_osc_clk_out_ee[8] ", + [103] = "am_ring_osc_clk_out_ee[7] ", + [102] = "am_ring_osc_clk_out_ee[6] ", + [101] = "am_ring_osc_clk_out_ee[5] ", + [100] = "am_ring_osc_clk_out_ee[4] ", + [99] = "am_ring_osc_clk_out_ee[3] ", + [98] = "cts_ts_clk ", + [97] = "cts_vpu_clkb_tmp ", + [96] = "cts_vpu_clkb ", + [95] = "eth_phy_plltxclk ", + [94] = "eth_phy_rxclk ", + [93] = "1'b0 ", + [92] = "1'b0 ", + [91] = "1'b0 ", + [90] = "cts_hdmitx_sys_clk ", + [89] = "HDMI_CLK_TODIG ", + [88] = "1'b0 ", + [87] = "1'b0 ", + [86] = "1'b0 ", + [85] = "1'b0 ", + [84] = "co_tx_clk ", + [83] = "co_rx_clk ", + [82] = "cts_ge2d_clk ", + [81] = "cts_vapbclk ", + [80] = "rng_ring_osc_clk[3] ", + [79] = "rng_ring_osc_clk[2] ", + [78] = "rng_ring_osc_clk[1] ", + [77] = "rng_ring_osc_clk[0] ", + [76] = "1'b0 ", + [75] = "cts_hevcf_clk ", + [74] = "1'b0 ", + [73] = "cts_pwm_C_clk ", + [72] = "cts_pwm_D_clk ", + [71] = "cts_pwm_E_clk ", + [70] = "cts_pwm_F_clk ", + [69] = "cts_hdcp22_skpclk ", + [68] = "cts_hdcp22_esmclk ", + [67] = "cts_dsi_phy_clk ", + [66] = "cts_vid_lock_clk ", + [65] = "cts_spicc_0_clk ", + [64] = "cts_spicc_1_clk ", + [63] = "cts_dsi_meas_clk ", + [62] = "cts_hevcb_clk ", + [61] = "gpio_clk_msr ", + [60] = "1'b0 ", + [59] = "cts_hcodec_clk ", + [58] = "cts_wave420l_bclk ", + [57] = "cts_wave420l_cclk ", + [56] = "cts_wave420l_aclk ", + [55] = "vid_pll_div_clk_out ", + [54] = "cts_vpu_clkc ", + [53] = "cts_sd_emmc_clk_A ", + [52] = "cts_sd_emmc_clk_B ", + [51] = "cts_sd_emmc_clk_C ", + [50] = "mp3_clk_out ", + [49] = "mp2_clk_out ", + [48] = "mp1_clk_out ", + [47] = "ddr_dpll_pt_clk ", + [46] = "cts_vpu_clk ", + [45] = "cts_pwm_A_clk ", + [44] = "cts_pwm_B_clk ", + [43] = "fclk_div5 ", + [42] = "mp0_clk_out ", + [41] = "mac_eth_rx_clk_rmii ", + [40] = "1'b0 ", + [39] = "cts_bt656_clk0 ", + [38] = "cts_vdin_meas_clk ", + [37] = "cts_cdac_clk_c ", + [36] = "cts_hdmi_tx_pixel_clk ", + [35] = "cts_mali_clk ", + [34] = "eth_mppll_50m_ckout ", + [33] = "sys_cpu_ring_osc_clk[1] ", + [32] = "cts_vdec_clk ", + [31] = "mpll_clk_test_out ", + [30] = "pcie_clk_inn ", + [29] = "pcie_clk_inp ", + [28] = "cts_sar_adc_clk ", + [27] = "co_clkin_to_mac ", + [26] = "sc_clk_int ", + [25] = "cts_eth_clk_rmii ", + [24] = "cts_eth_clk125Mhz ", + [23] = "mpll_clk_50m ", + [22] = "mac_eth_phy_ref_clk ", + [21] = "lcd_an_clk_ph3 ", + [20] = "rtc_osc_clk_out ", + [19] = "lcd_an_clk_ph2 ", + [18] = "sys_cpu_clk_div16 ", + [17] = "sys_pll_div16 ", + [16] = "cts_FEC_CLK_2 ", + [15] = "cts_FEC_CLK_1 ", + [14] = "cts_FEC_CLK_0 ", + [13] = "mod_tcon_clko ", + [12] = "hifi_pll_clk ", + [11] = "mac_eth_tx_clk ", + [10] = "cts_vdac_clk ", + [9] = "cts_encl_clk ", + [8] = "cts_encp_clk ", + [7] = "clk81 ", + [6] = "cts_enci_clk ", + [5] = "1'b0 ", + [4] = "gp0_pll_clk ", + [3] = "sys_cpu_ring_osc_clk[0] ", + [2] = "am_ring_osc_clk_out_ee[2]", + [1] = "am_ring_osc_clk_out_ee[1]", + [0] = "am_ring_osc_clk_out_ee[0]", + }; + int i; + int len = sizeof(clk_table)/sizeof(char *); + + if (index == 0xff) { + for (i = 0; i < len; i++) + seq_printf(s, "[%2d][%10d]%s\n", + i, gxbb_clk_util_clk_msr(i), + clk_table[i]); + return 0; + } + seq_printf(s, "[%10d]%s\n", gxbb_clk_util_clk_msr(index), + clk_table[index]); + clk_msr_index = 0xff; + return 0; +} + int meson_clk_measure(unsigned int clk_mux) { int clk_val; @@ -705,6 +849,7 @@ int meson_clk_measure(unsigned int clk_mux) case MESON_CPU_MAJOR_ID_GXL: case MESON_CPU_MAJOR_ID_GXM: case MESON_CPU_MAJOR_ID_TXLX: + case MESON_CPU_MAJOR_ID_G12A: clk_val = gxbb_clk_util_clk_msr(clk_mux); break; case MESON_CPU_MAJOR_ID_AXG: @@ -732,6 +877,8 @@ static int dump_clk(struct seq_file *s, void *what) axg_clk_measure(s, what, clk_msr_index); else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX) txlx_clk_measure(s, what, clk_msr_index); + else if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) + g12a_clk_measure(s, what, clk_msr_index); return 0; } diff --git a/drivers/amlogic/clk/clkc.h b/drivers/amlogic/clk/clkc.h index 79e7a8a05dec..e28d9bf2ee30 100644 --- a/drivers/amlogic/clk/clkc.h +++ b/drivers/amlogic/clk/clkc.h @@ -107,6 +107,7 @@ struct meson_clk_mpll { u8 en_dds; u16 top_misc_reg; /*after txlx*/ u16 top_misc_bit; + u16 mpll_cntl0_reg; spinlock_t *lock; }; @@ -211,6 +212,10 @@ extern const struct clk_ops meson_clk_mpll_ops; extern const struct clk_ops meson_clk_mux_ops; extern const struct clk_ops meson_axg_pll_ro_ops; extern const struct clk_ops meson_axg_pll_ops; +extern const struct clk_ops meson_g12a_pll_ro_ops; +extern const struct clk_ops meson_g12a_pll_ops; +extern const struct clk_ops meson_g12a_mpll_ro_ops; +extern const struct clk_ops meson_g12a_mpll_ops; extern void meson_clk_register_composite(struct clk **soc_clks, struct meson_composite *composite, @@ -235,4 +240,6 @@ void meson_txlx_sdemmc_init(void); void meson_txlx_media_init(void); void meson_init_gpu(void); +void meson_g12a_sdemmc_init(void); + #endif /* __CLKC_H */ diff --git a/drivers/amlogic/clk/g12a/Makefile b/drivers/amlogic/clk/g12a/Makefile new file mode 100644 index 000000000000..f485a97a5a13 --- /dev/null +++ b/drivers/amlogic/clk/g12a/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for Meson G12A clk +# + +obj-$(CONFIG_AMLOGIC_GX_CLK) += g12a.o g12a_clk-pll.o g12a_clk_sdemmc.o g12a_clk-mpll.o + +# g12a_ao.o\ + g12a_clk-pll.o \ + g12a_clk_sdemmc.o g12a_clk_media.o g12a_clk_misc.o diff --git a/drivers/amlogic/clk/g12a/g12a.c b/drivers/amlogic/clk/g12a/g12a.c new file mode 100644 index 000000000000..a531da63fd30 --- /dev/null +++ b/drivers/amlogic/clk/g12a/g12a.c @@ -0,0 +1,958 @@ +/* + * drivers/amlogic/clk/g12a/g12a.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../clkc.h" +#include "g12a.h" + +static struct clk_onecell_data clk_data; +/* #undef pr_debug */ +/* #define pr_debug pr_info */ + +static const struct clk_div_table cpu_div_table[] = { + { .val = 1, .div = 1 }, + { .val = 2, .div = 2 }, + { .val = 3, .div = 3 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { .val = 8, .div = 16 }, + { /* sentinel */ }, +}; + +static struct meson_clk_pll g12a_fixed_pll = { + .m = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 16, + .width = 2, + }, + .frac = { + .reg_off = HHI_FIX_PLL_CNTL1, + .shift = 0, + .width = 19, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll", + .ops = &meson_g12a_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll g12a_sys_pll = { + .m = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 16, + .width = 3, + }, + .rate_table = g12a_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sys_pll", + .ops = &meson_g12a_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll g12a_gp0_pll = { + .m = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 16, + .width = 3, + }, + .rate_table = g12a_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "gp0_pll", + .ops = &meson_g12a_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll g12a_hifi_pll = { + .m = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 16, + .width = 2, + }, + .rate_table = g12a_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &meson_g12a_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll g12a_pcie_pll = { + .m = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 16, + .width = 5, + }, + + .frac = { + .reg_off = HHI_PCIE_PLL_CNTL1, + .shift = 0, + .width = 12, + }, + .rate_table = g12a_pcie_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_pcie_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "pcie_pll", + .ops = &meson_g12a_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div3 = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div5 = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div7 = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_fclk_div2p5 = { + .mult = 2, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2p5", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll g12a_mpll0 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL1, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL1, + .shift = 20, + .width = 9, + }, + .sdm_en = 30, + .en_dds = 31, + .mpll_cntl0_reg = HHI_MPLL_CNTL0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &meson_g12a_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll g12a_mpll1 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL3, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL3, + .shift = 20, + .width = 9, + }, + .sdm_en = 30, + .en_dds = 31, + .mpll_cntl0_reg = HHI_MPLL_CNTL0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &meson_g12a_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll g12a_mpll2 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL5, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL5, + .shift = 20, + .width = 9, + }, + .sdm_en = 30, + .en_dds = 31, + .mpll_cntl0_reg = HHI_MPLL_CNTL0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &meson_g12a_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll g12a_mpll3 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 20, + .width = 9, + }, + .sdm_en = 30, + .en_dds = 31, + .mpll_cntl0_reg = HHI_MPLL_CNTL0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll3", + .ops = &meson_g12a_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +#if 0 +static struct clk_mux g12a_pcie_mux = { + .reg = (void *)HHI_PCIE_PLL_CNTL6, + .mask = 0x1, + .shift = 2, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "g12a_pcie_mux", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "mpll3", "pcie_pll" }, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_mux g12a_pcie_ref = { + .reg = (void *)HHI_PCIE_PLL_CNTL6, + .mask = 0x1, + .shift = 1, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "g12a_pcie_ref", + .ops = &clk_mux_ops, + //.parent_names = (const char *[]){ "g12a_pcie_input_gate", + .parent_names = (const char *[]){ "NULL", + "g12a_pcie_mux" }, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate g12a_pcie_cml_en0 = { + .reg = (void *)HHI_PCIE_PLL_CNTL6, + .bit_idx = 4, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "g12a_pcie_cml_en0", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "g12a_pcie_ref" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate g12a_pcie_cml_en1 = { + .reg = (void *)HHI_PCIE_PLL_CNTL6, + .bit_idx = 3, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "g12a_pcie_cml_en1", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "g12a_pcie_ref" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate g12a_mipi_enable_gate = { + .reg = (void *)HHI_MIPI_CNTL0, + .bit_idx = 29, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "g12a_mipi_enable_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "NULL" }, + .num_parents = 0, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate g12a_mipi_bandgap_gate = { + .reg = (void *)HHI_MIPI_CNTL0, + .bit_idx = 26, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "g12a_mipi_bandgap_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "NULL" }, + .num_parents = 0, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; +#endif +/* + * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL + * post-dividers and should be modelled with their respective PLLs via the + * forthcoming coordinated clock rates feature + */ +static u32 mux_table_cpu_px0[] = { 0, 1, 2 }; +static u32 mux_table_cpu_px[] = { 0, 1 }; + +static struct clk_mux g12a_cpu_fixedpll_p00 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x3, + .shift = 0, + .table = mux_table_cpu_px0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p00", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "xtal", "fclk_div2", + "fclk_div3"}, + .num_parents = 3, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider g12a_cpu_fixedpll_p01 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .shift = 4, + .width = 6, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p01", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cpu_fixedpll_p00" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_mux g12a_cpu_fixedpll_p0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 2, + .table = mux_table_cpu_px, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p0", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "cpu_fixedpll_p00", + "cpu_fixedpll_p01"}, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + }, +}; + +static struct clk_mux g12a_cpu_fixedpll_p10 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x3, + .shift = 16, + .table = mux_table_cpu_px0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p10", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "xtal", "fclk_div2", + "fclk_div3"}, + .num_parents = 3, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider g12a_cpu_fixedpll_p11 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .shift = 20, + .width = 6, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p11", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cpu_fixedpll_p10" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_mux g12a_cpu_fixedpll_p1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 18, + .table = mux_table_cpu_px, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p1", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "cpu_fixedpll_p10", + "cpu_fixedpll_p11"}, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + }, +}; + +static struct clk_mux g12a_cpu_fixedpll_p = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 10, + .table = mux_table_cpu_px, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cpu_fixedpll_p", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "cpu_fixedpll_p0", + "cpu_fixedpll_p1"}, + .num_parents = 2, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_cpu g12a_cpu_clk = { + .reg_off = HHI_SYS_CPU_CLK_CNTL0, + .clk_nb.notifier_call = meson_clk_cpu_notifier_cb, + .mux.reg = (void *)HHI_SYS_CPU_CLK_CNTL0, + .mux.shift = 11, + .mux.mask = 0x1, + .mux.lock = &clk_lock, + .mux.table = mux_table_cpu_px, + .mux.hw.init = &(struct clk_init_data){ + .name = "cpu_clk", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "cpu_fixedpll_p", "sys_pll"}, + .num_parents = 2, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static u32 mux_table_clk81[] = { 6, 5, 7 }; + +static struct clk_mux g12a_mpeg_clk_sel = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .mask = 0x7, + .shift = 12, + .flags = CLK_MUX_READ_ONLY, + .table = mux_table_clk81, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpeg_clk_sel", + .ops = &clk_mux_ro_ops, + /* + * FIXME bits 14:12 selects from 8 possible parents: + * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, + * fclk_div4, fclk_div3, fclk_div5 + */ + .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", + "fclk_div5" }, + .num_parents = 3, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider g12a_mpeg_clk_div = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpeg_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* the mother of dragons^W gates */ +static struct clk_gate g12a_clk81 = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "clk81", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "mpeg_clk_div" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), + }, +}; + + +/* Everything Else (EE) domain gates */ +static MESON_GATE(g12a_ddr, HHI_GCLK_MPEG0, 0); +static MESON_GATE(g12a_dos, HHI_GCLK_MPEG0, 1); +static MESON_GATE(g12a_alocker, HHI_GCLK_MPEG0, 2); +static MESON_GATE(g12a_mipi_dsi_host, HHI_GCLK_MPEG0, 3); +static MESON_GATE(g12a_eth_phy, HHI_GCLK_MPEG0, 4); +static MESON_GATE(g12a_isa, HHI_GCLK_MPEG0, 5); +static MESON_GATE(g12a_pl301, HHI_GCLK_MPEG0, 6); +static MESON_GATE(g12a_periphs, HHI_GCLK_MPEG0, 7); +static MESON_GATE(g12a_spicc_0, HHI_GCLK_MPEG0, 8); +static MESON_GATE(g12a_i2c, HHI_GCLK_MPEG0, 9); +static MESON_GATE(g12a_sana, HHI_GCLK_MPEG0, 10); +static MESON_GATE(g12a_sd, HHI_GCLK_MPEG0, 11); +static MESON_GATE(g12a_rng0, HHI_GCLK_MPEG0, 12); +static MESON_GATE(g12a_uart0, HHI_GCLK_MPEG0, 13); +static MESON_GATE(g12a_spicc_1, HHI_GCLK_MPEG0, 14); +static MESON_GATE(g12a_hiu_reg, HHI_GCLK_MPEG0, 19); +static MESON_GATE(g12a_mipi_dsi_phy, HHI_GCLK_MPEG0, 20); +static MESON_GATE(g12a_assist_misc, HHI_GCLK_MPEG0, 23); +static MESON_GATE(g12a_emmc_a, HHI_GCLK_MPEG0, 24); +static MESON_GATE(g12a_emmc_b, HHI_GCLK_MPEG0, 25); +static MESON_GATE(g12a_emmc_c, HHI_GCLK_MPEG0, 26); +static MESON_GATE(g12a_acodec, HHI_GCLK_MPEG0, 28); + +static MESON_GATE(g12a_audio, HHI_GCLK_MPEG1, 0); +static MESON_GATE(g12a_eth_core, HHI_GCLK_MPEG1, 3); +static MESON_GATE(g12a_u_stp_top, HHI_GCLK_MPEG1, 4); +static MESON_GATE(g12a_aififo, HHI_GCLK_MPEG1, 11); +static MESON_GATE(g12a_adc, HHI_GCLK_MPEG1, 13); +static MESON_GATE(g12a_uart1, HHI_GCLK_MPEG1, 16); +static MESON_GATE(g12a_g2d, HHI_GCLK_MPEG1, 20); +static MESON_GATE(g12a_reset, HHI_GCLK_MPEG1, 23); +static MESON_GATE(g12a_pcie_comb, HHI_GCLK_MPEG1, 24); +static MESON_GATE(g12a_parser, HHI_GCLK_MPEG1, 25); +static MESON_GATE(g12a_usb_general, HHI_GCLK_MPEG1, 26); +static MESON_GATE(g12a_pcie_phy, HHI_GCLK_MPEG1, 27); +static MESON_GATE(g12a_ahb_arb0, HHI_GCLK_MPEG1, 29); + +static MESON_GATE(g12a_ahb_data_bus, HHI_GCLK_MPEG2, 1); +static MESON_GATE(g12a_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2); +static MESON_GATE(g12a_htx_hdcp22, HHI_GCLK_MPEG2, 3); +static MESON_GATE(g12a_htx_pclk, HHI_GCLK_MPEG2, 4); +static MESON_GATE(g12a_bt656, HHI_GCLK_MPEG2, 6); +static MESON_GATE(g12a_usb1_to_ddr, HHI_GCLK_MPEG2, 8); +static MESON_GATE(g12a_mmc_pclk, HHI_GCLK_MPEG2, 11); +static MESON_GATE(g12a_uart2, HHI_GCLK_MPEG2, 15); +static MESON_GATE(g12a_vpu_intr, HHI_GCLK_MPEG2, 25); +static MESON_GATE(g12a_gic, HHI_GCLK_MPEG2, 30); + +/* Always On (AO) domain gates */ +#if 0 +static MESON_GATE(g12a_ao_media_cpu, HHI_GCLK_AO, 0); +static MESON_GATE(g12a_ao_ahb_sram, HHI_GCLK_AO, 1); +static MESON_GATE(g12a_ao_ahb_bus, HHI_GCLK_AO, 2); +static MESON_GATE(g12a_ao_iface, HHI_GCLK_AO, 3); +static MESON_GATE(g12a_ao_i2c, HHI_GCLK_AO, 4); +#endif +/* Array of all clocks provided by this provider */ + +static struct clk_hw *g12a_clk_hws[] = { + [CLKID_SYS_PLL] = &g12a_sys_pll.hw, + [CLKID_FIXED_PLL] = &g12a_fixed_pll.hw, + [CLKID_GP0_PLL] = &g12a_gp0_pll.hw, + [CLKID_HIFI_PLL] = &g12a_hifi_pll.hw, + [CLKID_PCIE_PLL] = &g12a_pcie_pll.hw, + [CLKID_FCLK_DIV2] = &g12a_fclk_div2.hw, + [CLKID_FCLK_DIV3] = &g12a_fclk_div3.hw, + [CLKID_FCLK_DIV4] = &g12a_fclk_div4.hw, + [CLKID_FCLK_DIV5] = &g12a_fclk_div5.hw, + [CLKID_FCLK_DIV7] = &g12a_fclk_div7.hw, + [CLKID_FCLK_DIV2P5] = &g12a_fclk_div2p5.hw, + [CLKID_MPEG_SEL] = &g12a_mpeg_clk_sel.hw, + [CLKID_MPEG_DIV] = &g12a_mpeg_clk_div.hw, + [CLKID_CLK81] = &g12a_clk81.hw, + + [CLKID_MPLL0] = &g12a_mpll0.hw, + [CLKID_MPLL1] = &g12a_mpll1.hw, + [CLKID_MPLL2] = &g12a_mpll2.hw, + [CLKID_MPLL3] = &g12a_mpll3.hw, + + [CLKID_DDR] = &g12a_ddr.hw, + [CLKID_DOS] = &g12a_dos.hw, + [CLKID_AUDIO_LOCKER] = &g12a_alocker.hw, + [CLKID_MIPI_DSI_HOST] = &g12a_mipi_dsi_host.hw, + [CLKID_ETH_PHY] = &g12a_eth_phy.hw, + [CLKID_ISA] = &g12a_isa.hw, + [CLKID_PL301] = &g12a_pl301.hw, + [CLKID_PERIPHS] = &g12a_periphs.hw, + [CLKID_SPICC0] = &g12a_spicc_0.hw, + [CLKID_I2C] = &g12a_i2c.hw, + [CLKID_SANA] = &g12a_sana.hw, + [CLKID_SD] = &g12a_sd.hw, + [CLKID_RNG0] = &g12a_rng0.hw, + [CLKID_UART0] = &g12a_uart0.hw, + [CLKID_SPICC1] = &g12a_spicc_1.hw, + [CLKID_HIU_REG] = &g12a_hiu_reg.hw, + [CLKID_MIPI_DSI_PHY] = &g12a_mipi_dsi_phy.hw, + [CLKID_ASSIST_MISC] = &g12a_assist_misc.hw, + [CLKID_SD_EMMC_A] = &g12a_emmc_a.hw, + [CLKID_SD_EMMC_B] = &g12a_emmc_b.hw, + [CLKID_SD_EMMC_C] = &g12a_emmc_c.hw, + [CLKID_ACODEC] = &g12a_acodec.hw, + [CLKID_AUDIO] = &g12a_audio.hw, + [CLKID_ETH_CORE] = &g12a_eth_core.hw, + [CLKID_U_STP_TOP] = &g12a_u_stp_top.hw, + [CLKID_AIFIFO] = &g12a_aififo.hw, + [CLKID_ADC] = &g12a_adc.hw, + [CLKID_UART1] = &g12a_uart1.hw, + [CLKID_G2D] = &g12a_g2d.hw, + [CLKID_RESET] = &g12a_reset.hw, + [CLKID_PCIE_COMB] = &g12a_pcie_comb.hw, + [CLKID_PARSER] = &g12a_parser.hw, + [CLKID_USB_GENERAL] = &g12a_usb_general.hw, + [CLKID_PCIE_PHY] = &g12a_pcie_phy.hw, + [CLKID_AHB_ARB0] = &g12a_ahb_arb0.hw, + [CLKID_AHB_DATA_BUS] = &g12a_ahb_data_bus.hw, + [CLKID_AHB_CTRL_BUS] = &g12a_ahb_ctrl_bus.hw, + [CLKID_HTX_HDCP22] = &g12a_htx_hdcp22.hw, + [CLKID_HTX_PCLK] = &g12a_htx_pclk.hw, + [CLKID_BT656] = &g12a_bt656.hw, + [CLKID_USB1_TO_DDR] = &g12a_usb1_to_ddr.hw, + [CLKID_MMC_PCLK] = &g12a_mmc_pclk.hw, + [CLKID_UART2] = &g12a_uart2.hw, + [CLKID_VPU_INTR] = &g12a_vpu_intr.hw, + [CLKID_GIC] = &g12a_gic.hw, + +#if 0 + [CLKID_AO_MEDIA_CPU] = &g12a_ao_media_cpu.hw, + [CLKID_AO_AHB_SRAM] = &g12a_ao_ahb_sram.hw, + [CLKID_AO_AHB_BUS] = &g12a_ao_ahb_bus.hw, + [CLKID_AO_IFACE] = &g12a_ao_iface.hw, + [CLKID_AO_I2C] = &g12a_ao_i2c.hw, +#endif + [CLKID_CPU_FCLK_P00] = &g12a_cpu_fixedpll_p00.hw, + [CLKID_CPU_FCLK_P01] = &g12a_cpu_fixedpll_p01.hw, + [CLKID_CPU_FCLK_P0] = &g12a_cpu_fixedpll_p0.hw, + [CLKID_CPU_FCLK_P10] = &g12a_cpu_fixedpll_p10.hw, + [CLKID_CPU_FCLK_P11] = &g12a_cpu_fixedpll_p11.hw, + [CLKID_CPU_FCLK_P1] = &g12a_cpu_fixedpll_p1.hw, + [CLKID_CPU_FCLK_P] = &g12a_cpu_fixedpll_p.hw, + [CLKID_CPU_CLK] = &g12a_cpu_clk.mux.hw, + + [CLKID_PCIE_PLL] = &g12a_pcie_pll.hw, +}; +/* Convenience tables to populate base addresses in .probe */ + +static struct meson_clk_pll *const g12a_clk_plls[] = { + &g12a_fixed_pll, + &g12a_sys_pll, + &g12a_gp0_pll, + &g12a_hifi_pll, + &g12a_pcie_pll, +}; + +static struct meson_clk_mpll *const g12a_clk_mplls[] = { + &g12a_mpll0, + &g12a_mpll1, + &g12a_mpll2, + &g12a_mpll3, +}; + +static struct clk_gate *g12a_clk_gates[] = { + &g12a_clk81, + &g12a_ddr, + &g12a_dos, + &g12a_alocker, + &g12a_mipi_dsi_host, + &g12a_eth_phy, + &g12a_isa, + &g12a_pl301, + &g12a_periphs, + &g12a_spicc_0, + &g12a_i2c, + &g12a_sana, + &g12a_sd, + &g12a_rng0, + &g12a_uart0, + &g12a_spicc_1, + &g12a_hiu_reg, + &g12a_mipi_dsi_phy, + &g12a_assist_misc, + &g12a_emmc_a, + &g12a_emmc_b, + &g12a_emmc_c, + &g12a_acodec, + &g12a_audio, + &g12a_eth_core, + &g12a_u_stp_top, + &g12a_aififo, + &g12a_adc, + &g12a_uart1, + &g12a_g2d, + &g12a_reset, + &g12a_pcie_comb, + &g12a_parser, + &g12a_usb_general, + &g12a_pcie_phy, + &g12a_ahb_arb0, + &g12a_ahb_data_bus, + &g12a_ahb_ctrl_bus, + &g12a_htx_hdcp22, + &g12a_htx_pclk, + &g12a_bt656, + &g12a_usb1_to_ddr, + &g12a_mmc_pclk, + &g12a_uart2, + &g12a_vpu_intr, + &g12a_gic, +#if 0 + &g12a_ao_media_cpu, + &g12a_ao_ahb_sram, + &g12a_ao_ahb_bus, + &g12a_ao_iface, + &g12a_ao_i2c, + &g12a_mipi_enable_gate, + &g12a_mipi_bandgap_gate, +#endif +}; + +static void __init g12a_clkc_init(struct device_node *np) +{ + int ret = 0, clkid, i; + struct clk_hw *parent_hw; + struct clk *parent_clk; + + /* Generic clocks and PLLs */ + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("%s: Unable to map clk base\n", __func__); + /* return -ENXIO; */ + return; + } + /* pr_debug("%s: iomap clk_base ok!", __func__); */ + /* Populate base address for PLLs */ + for (i = 0; i < ARRAY_SIZE(g12a_clk_plls); i++) + g12a_clk_plls[i]->base = clk_base; + + /* Populate base address for MPLLs */ + for (i = 0; i < ARRAY_SIZE(g12a_clk_mplls); i++) + g12a_clk_mplls[i]->base = clk_base; + + /* Populate the base address for CPU clk */ + g12a_cpu_clk.mux.reg = clk_base + (u64)g12a_cpu_clk.mux.reg; + g12a_cpu_fixedpll_p00.reg = clk_base + (u64)g12a_cpu_fixedpll_p00.reg; + g12a_cpu_fixedpll_p01.reg = clk_base + (u64)g12a_cpu_fixedpll_p01.reg; + g12a_cpu_fixedpll_p10.reg = clk_base + (u64)g12a_cpu_fixedpll_p10.reg; + g12a_cpu_fixedpll_p11.reg = clk_base + (u64)g12a_cpu_fixedpll_p11.reg; + g12a_cpu_fixedpll_p0.reg = clk_base + (u64)g12a_cpu_fixedpll_p0.reg; + g12a_cpu_fixedpll_p1.reg = clk_base + (u64)g12a_cpu_fixedpll_p1.reg; + g12a_cpu_fixedpll_p.reg = clk_base + (u64)g12a_cpu_fixedpll_p.reg; + + /* Populate the base address for the MPEG clks */ + g12a_mpeg_clk_sel.reg = clk_base + (u64)g12a_mpeg_clk_sel.reg; + g12a_mpeg_clk_div.reg = clk_base + (u64)g12a_mpeg_clk_div.reg; + + /* Populate base address for gates */ + for (i = 0; i < ARRAY_SIZE(g12a_clk_gates); i++) + g12a_clk_gates[i]->reg = clk_base + + (u64)g12a_clk_gates[i]->reg; + + if (!clks) { + clks = kzalloc(NR_CLKS*sizeof(struct clk *), GFP_KERNEL); + if (!clks) { + /* pr_err("%s: alloc clks fail!", __func__); */ + /* return -ENOMEM; */ + return; + } + } + + if (clks == NULL) { + pr_err("%s: error: not kzalloc clks in aoclk!", __func__); + return; + } + + clk_data.clks = clks; + clk_data.clk_num = NR_CLKS; + /* + * register all clks + */ + + for (clkid = 0; clkid < ARRAY_SIZE(g12a_clk_hws); clkid++) { + if (g12a_clk_hws[clkid]) { + clks[clkid] = clk_register(NULL, g12a_clk_hws[clkid]); + if (IS_ERR(clks[clkid])) { + pr_err("%s: failed to register %s\n", __func__, + clk_hw_get_name(g12a_clk_hws[clkid])); + goto iounmap; + } + } + } + + meson_g12a_sdemmc_init(); + /*g12a_amlogic_init_misc();*/ + + pr_debug("%s: register all clk ok!", __func__); + /* + * Register CPU clk notifier + * + * FIXME this is wrong for a lot of reasons. First, the muxes should be + * struct clk_hw objects. Second, we shouldn't program the muxes in + * notifier handlers. The tricky programming sequence will be handled + * by the forthcoming coordinated clock rates mechanism once that + * feature is released. + * + * Furthermore, looking up the parent this way is terrible. At some + * point we will stop allocating a default struct clk when registering + * a new clk_hw, and this hack will no longer work. Releasing the ccr + * feature before that time solves the problem :-) + */ + parent_hw = clk_hw_get_parent(&g12a_cpu_clk.mux.hw); + parent_clk = parent_hw->clk; + ret = clk_notifier_register(parent_clk, &g12a_cpu_clk.clk_nb); + if (ret) { + pr_err("%s: failed to register clock notifier for cpu_clk\n", + __func__); + goto iounmap; + } + pr_debug("%s: cpu clk register notifier ok!", __func__); + + ret = of_clk_add_provider(np, of_clk_src_onecell_get, + &clk_data); + if (ret < 0) + pr_err("%s fail ret: %d\n", __func__, ret); + else + pr_info("%s initialization complete\n", __func__); + return; + +iounmap: + iounmap(clk_base); + pr_info("%s: %d: ret: %d\n", __func__, __LINE__, ret); + /* return; */ +} + +CLK_OF_DECLARE(g12a, "amlogic,g12a-clkc", g12a_clkc_init); + + diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h new file mode 100644 index 000000000000..2a0e36e0dbbb --- /dev/null +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -0,0 +1,129 @@ +/* + * drivers/amlogic/clk/g12a/g12a.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __G12A_H +#define __G12A_H + +/* + * Clock controller register offsets + * + * Register offsets from the data sheet are listed in comment blocks below. + * Those offsets must be multiplied by 4 before adding them to the base address + * to get the right value + */ + +#define HHI_MIPI_CNTL0 0x0 /* 0x0 offset in data sheet */ +#define HHI_MIPI_CNTL1 0x4 /* 0x1 offset in data sheet */ +#define HHI_MIPI_CNTL2 0x8 /* 0x2 offset in data sheet */ + +#define HHI_GP0_PLL_CNTL0 0x40 /* 0x10 offset in data sheet */ + + +#define HHI_PCIE_PLL_CNTL0 0x98 /* 0x26 offset in data sheet */ +#define HHI_PCIE_PLL_CNTL1 0x9c /* 0x27 offset in data sheet */ +//#define HHI_PCIE_PLL_CNTL6 0xf0 /* 0x3c offset in data sheet */ + +#define HHI_HIFI_PLL_CNTL0 0xD8 /* 0x36 offset in data sheet */ + +#define HHI_GCLK_MPEG0 0x140 /* 0x50 offset in data sheet */ +#define HHI_GCLK_MPEG1 0x144 /* 0x51 offset in data sheet */ +#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */ +#if 0 +#define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */ + +#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */ +#define HHI_SPICC_HCLK_CNTL 0x168 /* 0x5a offset in data sheet */ +#endif +#define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ +#define HHI_AUD_CLK_CNTL 0x178 /* 0x5e offset in data sheet */ +#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ +//#define HHI_AUD_CLK_CNTL2 0x190 /* 0x64 offset in data sheet */ +#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ + +#define HHI_MALI_CLK_CNTL 0x1b0 /* 0x6c offset in data sheet */ +#define HHI_VPU_CLK_CNTL 0x1bC /* 0x6f offset in data sheet */ + +#define HHI_HDMI_CLK_CNTL 0x1CC /* 0x73 offset in data sheet */ + +#define HHI_VDEC_CLK_CNTL 0x1E0 /* 0x78 offset in data sheet */ +#define HHI_VDEC2_CLK_CNTL 0x1E4 /* 0x79 offset in data sheet */ +#define HHI_VDEC3_CLK_CNTL 0x1E8 /* 0x7a offset in data sheet */ +#define HHI_VDEC4_CLK_CNTL 0x1EC /* 0x7b offset in data sheet */ +#define HHI_HDCP22_CLK_CNTL 0x1F0 /* 0x7c offset in data sheet */ +#define HHI_VAPBCLK_CNTL 0x1F4 /* 0x7d offset in data sheet */ + +#define HHI_VPU_CLKB_CNTL 0x20C /* 0x83 offset in data sheet */ +#define HHI_GEN_CLK_CNTL 0x228 /* 0x8a offset in data sheet */ + + +#define HHI_VDIN_MEAS_CLK_CNTL 0x250 /* 0x94 offset in data sheet */ +#define HHI_MIPIDSI_PHY_CLK_CNTL 0x254 /* 0x95 offset in data sheet */ +#define HHI_NAND_CLK_CNTL 0x25C /* 0x97 offset in data sheet */ +#define HHI_SD_EMMC_CLK_CNTL 0x264 /* 0x99 offset in data sheet */ + +#define HHI_MPLL_CNTL0 0x278 /* 0x9e offset in data sheet */ +#define HHI_MPLL_CNTL1 0x27C /* 0x9f offset in data sheet */ +#define HHI_MPLL_CNTL2 0x280 /* 0xa0 offset in data sheet */ +#define HHI_MPLL_CNTL3 0x284 /* 0xa1 offset in data sheet */ +#define HHI_MPLL_CNTL4 0x288 /* 0xa2 offset in data sheet */ +#define HHI_MPLL_CNTL5 0x28c /* 0xa3 offset in data sheet */ +#define HHI_MPLL_CNTL6 0x290 /* 0xa4 offset in data sheet */ +#define HHI_MPLL_CNTL7 0x294 /* 0xa5 offset in data sheet */ +#define HHI_MPLL_CNTL8 0x298 /* 0xa6 offset in data sheet */ + +#define HHI_FIX_PLL_CNTL0 0x2A0 /* 0xa8 offset in data sheet */ +#define HHI_FIX_PLL_CNTL1 0x2A4 /* 0xa9 offset in data sheet */ + +#if 0 +#define HHI_MPLL3_CNTL0 0x2E0 /* 0xb8 offset in data sheet */ +#define HHI_MPLL3_CNTL1 0x2E4 /* 0xb9 offset in data sheet */ +#define HHI_PLL_TOP_MISC 0x2E8 /* 0xba offset in data sheet */ +#endif +#define HHI_SYS_PLL_CNTL0 0x2f4 /* 0xbd offset in data sheet */ +#define HHI_SYS_PLL_CNTL1 0x2f8 /* 0xbe offset in data sheet */ +#define HHI_SYS_PLL_CNTL2 0x2fc /* 0xbf offset in data sheet */ +#define HHI_SYS_PLL_CNTL3 0x300 /* 0xc0 offset in data sheet */ +#define HHI_SYS_PLL_CNTL4 0x304 /* 0xc1 offset in data sheet */ +#define HHI_SYS_PLL_CNTL5 0x308 /* 0xc2 offset in data sheet */ +#define HHI_SYS_PLL_CNTL6 0x30c /* 0xc3 offset in data sheet */ + +/*G12A: pll: FDCO: 3G~6G FDCO = 24*(M+frac)/N + *N: recommend is 1 + *clk_out = FDCO >> OD + */ +static const struct pll_rate_table g12a_pll_rate_table[] = { + PLL_RATE(24000000, 128, 1, 7), /*DCO=3072M*/ + PLL_RATE(48000000, 128, 1, 6), /*DCO=3072M*/ + PLL_RATE(96000000, 128, 1, 5), /*DCO=3072M*/ + PLL_RATE(192000000, 128, 1, 4), /*DCO=3072M*/ + PLL_RATE(312000000, 208, 1, 4), /*DCO=4992M*/ + PLL_RATE(408000000, 136, 1, 3), /*DCO=3264M*/ + PLL_RATE(600000000, 200, 1, 3), /*DCO=4800M*/ + PLL_RATE(696000000, 232, 1, 3), /*DCO=5568M*/ + PLL_RATE(792000000, 132, 1, 2), /*DCO=3168M*/ + PLL_RATE(912000000, 152, 1, 2), /*DCO=3648M*/ + + { /* sentinel */ }, +}; + +/*PCIE clk_out = 24M*m/2/2/OD*/ +static const struct pll_rate_table g12a_pcie_pll_rate_table[] = { + PLL_RATE(100000000, 150, 0, 9), + { /* sentinel */ }, +}; +#endif /* __G12A_H */ diff --git a/drivers/amlogic/clk/g12a/g12a_clk-mpll.c b/drivers/amlogic/clk/g12a/g12a_clk-mpll.c new file mode 100644 index 000000000000..4ba61d72e5d2 --- /dev/null +++ b/drivers/amlogic/clk/g12a/g12a_clk-mpll.c @@ -0,0 +1,170 @@ +/* + * drivers/amlogic/clk/g12a/g12a_clk-mpll.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* + * MultiPhase Locked Loops are outputs from a PLL with additional frequency + * scaling capabilities. MPLL rates are calculated as: + * + * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) + */ + +#include +#include + +#include "../clkc.h" +/* #undef pr_debug */ +/* #define pr_debug pr_info */ +#define SDM_MAX 16384 +#define MAX_RATE 500000000 +#define MIN_RATE 7830000 + +#define G12A_MPLL_CNTL0 0x00000543 +#define G12A_MPLL_CNTL2 0x40000033 + + +#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) + +static unsigned long mpll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long rate = 0; + unsigned long reg, sdm, n2; + + p = &mpll->sdm; + reg = readl(mpll->base + p->reg_off); + sdm = PARM_GET(p->width, p->shift, reg); + + p = &mpll->n2; + reg = readl(mpll->base + p->reg_off); + n2 = PARM_GET(p->width, p->shift, reg); + + rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm); + + return rate; +} + +static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long rate_val = rate; + + if (rate_val < MIN_RATE) + rate = MIN_RATE; + if (rate_val > MAX_RATE) + rate = MAX_RATE; + + return rate_val; +} + + +static int mpll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg, sdm, n2; + unsigned long flags = 0; + + if ((rate > MAX_RATE) || (rate < MIN_RATE)) { + pr_err("Err: can not set rate to %lu!\n", rate); + pr_err("Range[5000000 - 500000000]\n"); + return -1; + } + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + + /* calculate new n2 and sdm */ + n2 = parent_rate / rate; + sdm = DIV_ROUND_UP((parent_rate - n2 * rate) * SDM_MAX, rate); + if (sdm >= SDM_MAX) + sdm = SDM_MAX - 1; + + pr_debug("%s: sdm: %lu n2: %lu rate: %lu parent_rate: %lu\n", + __func__, sdm, n2, rate, parent_rate); + + writel(G12A_MPLL_CNTL0, mpll->base + mpll->mpll_cntl0_reg); + + p = &mpll->sdm; + writel(G12A_MPLL_CNTL2, mpll->base + p->reg_off + (u64)(1*4)); + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, sdm); + p = &mpll->n2; + reg = PARM_SET(p->width, p->shift, reg, n2); + reg = PARM_SET(1, mpll->sdm_en, reg, 1); + reg = PARM_SET(1, mpll->en_dds, reg, 1); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); + + return 0; +} + +static int mpll_enable(struct clk_hw *hw) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p = &mpll->sdm; + unsigned long reg; + unsigned long flags = 0; + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(1, mpll->sdm_en, reg, 1); + reg = PARM_SET(1, mpll->en_dds, reg, 1); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); + + return 0; +} + +static void mpll_disable(struct clk_hw *hw) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p = &mpll->sdm; + unsigned long reg; + unsigned long flags = 0; + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(1, mpll->sdm_en, reg, 0); + reg = PARM_SET(1, mpll->en_dds, reg, 0); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); +} + +const struct clk_ops meson_g12a_mpll_ops = { + .recalc_rate = mpll_recalc_rate, + .round_rate = meson_clk_pll_round_rate, + .set_rate = mpll_set_rate, + .enable = mpll_enable, + .disable = mpll_disable, +}; + +const struct clk_ops meson_g12a_mpll_ro_ops = { + .recalc_rate = mpll_recalc_rate, +}; diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c new file mode 100644 index 000000000000..e0001157cdd4 --- /dev/null +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -0,0 +1,392 @@ +/* + * drivers/amlogic/clk/g12a/g12a_clk-pll.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* + * In the most basic form, a Meson PLL is composed as follows: + * + * PLL + * +------------------------------+ + * | | + * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out + * | ^ ^ | + * +------------------------------+ + * | | + * FREF VCO + * + * out = (in * M / N) >> OD + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../clkc.h" + +#define MESON_PLL_RESET BIT(29) +#define MESON_PLL_ENABLE BIT(28) +#define MESON_PLL_LOCK BIT(31) + +/* G12A */ + +//#define G12A_PCIE_PLL_CNTL 0x400106c8 +#define G12A_PCIE_PLL_CNTL1 0x00000000 +#define G12A_PCIE_PLL_CNTL2 0x00001000 +#define G12A_PCIE_PLL_CNTL3 0x10058e00 +#define G12A_PCIE_PLL_CNTL4 0x000100c0 +#define G12A_PCIE_PLL_CNTL4_ 0x008100c0 +#define G12A_PCIE_PLL_CNTL5 0x28000048 +#define G12A_PCIE_PLL_CNTL5_ 0x28000068 + +#define G12A_PLL_CNTL1 0x00000000 +#define G12A_PLL_CNTL2 0x00000000 +#define G12A_PLL_CNTL3 0x0a691c20 +#define G12A_PLL_CNTL4 0x33071290 +#define G12A_PLL_CNTL5 0x39270000 +#define G12A_PLL_CNTL6 0x50540000 + + +#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) + +static unsigned long meson_g12a_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct meson_clk_pll *pll = to_meson_clk_pll(hw); + struct parm *p; + unsigned long parent_rate_mhz = parent_rate; + unsigned long rate_mhz; + u16 n, m, od, od2 = 0; + u32 reg, frac = 0; + + p = &pll->n; + reg = readl(pll->base + p->reg_off); + n = PARM_GET(p->width, p->shift, reg); + + p = &pll->m; + reg = readl(pll->base + p->reg_off); + m = PARM_GET(p->width, p->shift, reg); + + p = &pll->od; + reg = readl(pll->base + p->reg_off); + od = PARM_GET(p->width, p->shift, reg); + + p = &pll->od2; + if (p->width) { + reg = readl(pll->base + p->reg_off); + od2 = PARM_GET(p->width, p->shift, reg); + } + + p = &pll->frac; + + if (p->width) { + reg = readl(pll->base + p->reg_off); + frac = PARM_GET(p->width - 1, p->shift, reg); + + if (reg & (1 << (p->width - 1))) + rate_mhz = (parent_rate_mhz * m - + ((parent_rate_mhz * frac) + >> (p->width - 2))) / n; + else + rate_mhz = (parent_rate_mhz * m + + ((parent_rate_mhz * frac) + >> (p->width - 2))) / n; + + if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) + rate_mhz = rate_mhz/4/od; + else + rate_mhz = rate_mhz >> od; + } else { + if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) + rate_mhz = (parent_rate_mhz * m / n) / 4 / od; + else + rate_mhz = (parent_rate_mhz * m / n) >> od >> od2; + } + + return rate_mhz; +} + +static long meson_g12a_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct meson_clk_pll *pll = to_meson_clk_pll(hw); + const struct pll_rate_table *rate_table = pll->rate_table; + int i; + + for (i = 0; i < pll->rate_count; i++) { + if (rate <= rate_table[i].rate) + return rate_table[i].rate; + } + + /* else return the smallest value */ + return rate_table[0].rate; +} + +static const struct pll_rate_table *meson_g12a_get_pll_settings + (struct meson_clk_pll *pll, unsigned long rate) +{ + const struct pll_rate_table *rate_table = pll->rate_table; + int i; + + for (i = 0; i < pll->rate_count; i++) { + if (rate == rate_table[i].rate) + return &rate_table[i]; + } + return NULL; +} + +static int meson_g12a_pll_wait_lock(struct meson_clk_pll *pll, + struct parm *p_n) +{ + int delay = 24000000; + u32 reg; + + while (delay > 0) { + reg = readl(pll->base + p_n->reg_off); + + if (reg & MESON_PLL_LOCK) + return 0; + delay--; + } + return -ETIMEDOUT; +} + +static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct meson_clk_pll *pll = to_meson_clk_pll(hw); + struct parm *p; + const struct pll_rate_table *rate_set; + unsigned long old_rate; + int ret = 0; + u32 reg; + unsigned long flags = 0; + + if (parent_rate == 0 || rate == 0) + return -EINVAL; + + old_rate = rate; + + rate_set = meson_g12a_get_pll_settings(pll, rate); + if (!rate_set) + return -EINVAL; + + p = &pll->n; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + if (readl(pll->base + p->reg_off) & MESON_PLL_ENABLE) { + old_rate = meson_g12a_pll_recalc_rate(hw, parent_rate); + old_rate = meson_g12a_pll_round_rate(hw, old_rate, NULL); + + if (old_rate == rate) { + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + return ret; + } + } + + if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "hifi_pll") + || !strcmp(clk_hw_get_name(hw), "pcie_pll") + || !strcmp(clk_hw_get_name(hw), "sys_pll")) { + void *cntlbase = pll->base + p->reg_off; + + writel((readl(cntlbase) | MESON_PLL_RESET) + & (~MESON_PLL_ENABLE), cntlbase); + + if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { + writel(G12A_PCIE_PLL_CNTL1, cntlbase + (u64)(1*4)); + writel(G12A_PCIE_PLL_CNTL2, cntlbase + (u64)(2*4)); + writel(G12A_PCIE_PLL_CNTL3, cntlbase + (u64)(3*4)); + writel(G12A_PCIE_PLL_CNTL4, cntlbase + (u64)(4*4)); + writel(G12A_PCIE_PLL_CNTL5, cntlbase + (u64)(5*4)); + writel(G12A_PCIE_PLL_CNTL5_, cntlbase + (u64)(5*4)); + udelay(20); + writel(G12A_PCIE_PLL_CNTL4_, cntlbase + (u64)(4*4)); + udelay(10); + /*set pcie_apll_afc_start bit*/ + writel(readl(cntlbase) | (1 << 26), cntlbase); + udelay(10); + } else { + writel(G12A_PLL_CNTL1, cntlbase + (u64)1*4); + writel(G12A_PLL_CNTL2, cntlbase + (u64)2*4); + writel(G12A_PLL_CNTL3, cntlbase + (u64)3*4); + writel(G12A_PLL_CNTL4, cntlbase + (u64)4*4); + writel(G12A_PLL_CNTL5, cntlbase + (u64)5*4); + writel(G12A_PLL_CNTL6, cntlbase + (u64)6*4); + udelay(10); + } + } else { + pr_err("%s: %s pll not found!!!\n", + __func__, clk_hw_get_name(hw)); + return -EINVAL; + } + + reg = readl(pll->base + p->reg_off); + + reg = PARM_SET(p->width, p->shift, reg, rate_set->n); + writel(reg, pll->base + p->reg_off); + + p = &pll->m; + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->m); + writel(reg, pll->base + p->reg_off); + + p = &pll->od; + /*check OD width*/ + if (rate_set->od >> p->width) { + ret = -EINVAL; + pr_warn("%s: OD width is wrong at rate %lu !!\n", + __func__, rate); + goto OUT; + } + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->od); + writel(reg, pll->base + p->reg_off); + + p = &pll->od2; + if (p->width) { + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->od2); + writel(reg, pll->base + p->reg_off); + } + + p = &pll->frac; + if (p->width) { + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->frac); + writel(reg, pll->base + p->reg_off); + } + + p = &pll->n; + + /* PLL reset */ + writel(readl(pll->base + p->reg_off) | MESON_PLL_ENABLE, + pll->base + p->reg_off); + udelay(10); + writel(readl(pll->base + p->reg_off) & (~MESON_PLL_RESET), + pll->base + p->reg_off); + ret = meson_g12a_pll_wait_lock(pll, p); + +OUT: + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + if (ret) { + pr_warn("%s: pll did not lock, trying to lock rate %lu again\n", + __func__, rate); + meson_g12a_pll_set_rate(hw, rate, parent_rate); + } + + return ret; +} + +static int meson_g12a_pll_enable(struct clk_hw *hw) +{ + struct meson_clk_pll *pll = to_meson_clk_pll(hw); + struct parm *p; + int ret = 0; + unsigned long flags = 0; + unsigned long first_set = 1; + struct clk *parent; + unsigned long rate; + + p = &pll->n; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + if (readl(pll->base + p->reg_off) & MESON_PLL_ENABLE) { + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + return ret; + } + + if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "hifi_pll") + || !strcmp(clk_hw_get_name(hw), "pcie_pll") + || !strcmp(clk_hw_get_name(hw), "sys_pll")) { + void *cntlbase = pll->base + p->reg_off; + + if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { + if (readl(cntlbase + (u64)(3*4)) == G12A_PCIE_PLL_CNTL3) + first_set = 0; + } else { + if (readl(cntlbase + (u64)(6*4)) == G12A_PLL_CNTL6) + first_set = 0; + } + } + + parent = clk_get_parent(hw->clk); + + /*First init, just set minimal rate.*/ + if (first_set) + rate = pll->rate_table[0].rate; + else { + rate = meson_g12a_pll_recalc_rate(hw, clk_get_rate(parent)); + rate = meson_g12a_pll_round_rate(hw, rate, NULL); + } + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + ret = meson_g12a_pll_set_rate(hw, rate, clk_get_rate(parent)); + + return ret; +} + +static void meson_g12a_pll_disable(struct clk_hw *hw) +{ + struct meson_clk_pll *pll = to_meson_clk_pll(hw); + struct parm *p = &pll->n; + unsigned long flags = 0; + + if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "hifi_pll") + || !strcmp(clk_hw_get_name(hw), "pcie_pll")) { + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + writel(readl(pll->base + p->reg_off) & (~MESON_PLL_ENABLE), + pll->base + p->reg_off); + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + } + +} + +const struct clk_ops meson_g12a_pll_ops = { + .recalc_rate = meson_g12a_pll_recalc_rate, + .round_rate = meson_g12a_pll_round_rate, + .set_rate = meson_g12a_pll_set_rate, + .enable = meson_g12a_pll_enable, + .disable = meson_g12a_pll_disable, +}; + +const struct clk_ops meson_g12a_pll_ro_ops = { + .recalc_rate = meson_g12a_pll_recalc_rate, +}; + diff --git a/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c b/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c new file mode 100644 index 000000000000..acd96e0ca1b0 --- /dev/null +++ b/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c @@ -0,0 +1,169 @@ +/* + * drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../clkc.h" +#include "g12a.h" + +static const char * const sd_emmc_parent_names[] = { "xtal", "fclk_div2", + "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0" }; + +static struct clk_mux sd_emmc_p0_mux_B = { + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, + .mask = 0x7, + .shift = 25, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_p0_mux_B", + .ops = &clk_mux_ops, + .parent_names = sd_emmc_parent_names, + .num_parents = 8, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_divider sd_emmc_p0_div_B = { + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_p0_div_B", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "sd_emmc_p0_mux_B" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate sd_emmc_p0_gate_B = { + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, + .bit_idx = 23, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_p0_gate_B", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "sd_emmc_p0_div_B" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_mux sd_emmc_p0_mux_C = { + .reg = (void *)HHI_NAND_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_p0_mux_C", + .ops = &clk_mux_ops, + .parent_names = sd_emmc_parent_names, + .num_parents = 8, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_divider sd_emmc_p0_div_C = { + .reg = (void *)HHI_NAND_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_p0_div_C", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "sd_emmc_p0_mux_C" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_gate sd_emmc_p0_gate_C = { + .reg = (void *)HHI_NAND_CLK_CNTL, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_p0_gate_C", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "sd_emmc_p0_div_C" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_hw *sd_emmc_clk_hws[] = { + [CLKID_SD_EMMC_B_P0_MUX - CLKID_SD_EMMC_B_P0_MUX] + = &sd_emmc_p0_mux_B.hw, + [CLKID_SD_EMMC_B_P0_DIV - CLKID_SD_EMMC_B_P0_MUX] + = &sd_emmc_p0_div_B.hw, + [CLKID_SD_EMMC_B_P0_GATE - CLKID_SD_EMMC_B_P0_MUX] + = &sd_emmc_p0_gate_B.hw, + [CLKID_SD_EMMC_C_P0_MUX - CLKID_SD_EMMC_B_P0_MUX] + = &sd_emmc_p0_mux_C.hw, + [CLKID_SD_EMMC_C_P0_DIV - CLKID_SD_EMMC_B_P0_MUX] + = &sd_emmc_p0_div_C.hw, + [CLKID_SD_EMMC_C_P0_GATE - CLKID_SD_EMMC_B_P0_MUX] + = &sd_emmc_p0_gate_C.hw, +}; + + +void meson_g12a_sdemmc_init(void) +{ + /* Populate base address for reg */ + pr_info("%s: register amlogic sdemmc clk\n", __func__); + + sd_emmc_p0_mux_B.reg = clk_base + (u64)(sd_emmc_p0_mux_B.reg); + sd_emmc_p0_div_B.reg = clk_base + (u64)(sd_emmc_p0_div_B.reg); + sd_emmc_p0_gate_B.reg = clk_base + (u64)(sd_emmc_p0_gate_B.reg); + sd_emmc_p0_mux_C.reg = clk_base + (u64)(sd_emmc_p0_mux_C.reg); + sd_emmc_p0_div_C.reg = clk_base + (u64)(sd_emmc_p0_div_C.reg); + sd_emmc_p0_gate_C.reg = clk_base + (u64)(sd_emmc_p0_gate_C.reg); + + clks[CLKID_SD_EMMC_B_P0_COMP] = clk_register_composite(NULL, + "sd_emmc_p0_B_comp", + sd_emmc_parent_names, 8, + sd_emmc_clk_hws[CLKID_SD_EMMC_B_P0_MUX - CLKID_SD_EMMC_B_P0_MUX], + &clk_mux_ops, + sd_emmc_clk_hws[CLKID_SD_EMMC_B_P0_DIV - CLKID_SD_EMMC_B_P0_MUX], + &clk_divider_ops, + sd_emmc_clk_hws[CLKID_SD_EMMC_B_P0_GATE - CLKID_SD_EMMC_B_P0_MUX], + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_SD_EMMC_B_P0_COMP])) + pr_err("%s: %d clk_register_composite sd_emmc_p0_B_comp error\n", + __func__, __LINE__); + + clks[CLKID_SD_EMMC_C_P0_COMP] = clk_register_composite(NULL, + "sd_emmc_p0_C_comp", + sd_emmc_parent_names, 8, + sd_emmc_clk_hws[CLKID_SD_EMMC_C_P0_MUX - CLKID_SD_EMMC_B_P0_MUX], + &clk_mux_ops, + sd_emmc_clk_hws[CLKID_SD_EMMC_C_P0_DIV - CLKID_SD_EMMC_B_P0_MUX], + &clk_divider_ops, + sd_emmc_clk_hws[CLKID_SD_EMMC_C_P0_GATE - CLKID_SD_EMMC_B_P0_MUX], + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_SD_EMMC_C_P0_COMP])) + pr_err("%s: %d clk_register_composite sd_emmc_p0_C_comp error\n", + __func__, __LINE__); + + pr_info("%s: register amlogic sdemmc clk\n", __func__); +} diff --git a/include/dt-bindings/clock/amlogic,g12a-clkc.h b/include/dt-bindings/clock/amlogic,g12a-clkc.h index 406a34bd9dae..4197d3671daf 100644 --- a/include/dt-bindings/clock/amlogic,g12a-clkc.h +++ b/include/dt-bindings/clock/amlogic,g12a-clkc.h @@ -22,147 +22,169 @@ * CLKID index values */ -#define CLKID_SYS_PLL 0 -#define CLKID_FIXED_PLL 1 -#define CLKID_FCLK_DIV2 2 -#define CLKID_FCLK_DIV3 3 -#define CLKID_FCLK_DIV4 4 -#define CLKID_FCLK_DIV5 5 -#define CLKID_FCLK_DIV7 6 -#define CLKID_GP0_PLL 7 -#define CLKID_HIFI_PLL 8 -#define CLKID_MPEG_SEL 9 -#define CLKID_MPEG_DIV 10 -#define CLKID_CLK81 11 -#define CLKID_MPLL0 12 -#define CLKID_MPLL1 13 -#define CLKID_MPLL2 14 -#define CLKID_MPLL3 15 -#define CLKID_CPU_FCLK_P00 16 -#define CLKID_CPU_FCLK_P01 17 -#define CLKID_CPU_FCLK_P0 18 -#define CLKID_CPU_FCLK_P10 19 -#define CLKID_CPU_FCLK_P11 20 -#define CLKID_CPU_FCLK_P1 21 -#define CLKID_CPU_FCLK_P 22 -#define CLKID_CPU_CLK 23 -#define CLKID_PCIE_PLL 24 -#define CLKID_PCIE_MUX 25 -#define CLKID_PCIE_REF 26 -#define CLKID_PCIE_INPUT_GATE 27 -#define CLKID_PCIE_CML_EN0 28 -#define CLKID_PCIE_CML_EN1 29 -#define CLKID_MIPI_ENABLE_GATE 30 +#define CLKID_SYS_PLL 0 +#define CLKID_FIXED_PLL 1 +#define CLKID_FCLK_DIV2 2 +#define CLKID_FCLK_DIV3 3 +#define CLKID_FCLK_DIV4 4 +#define CLKID_FCLK_DIV5 5 +#define CLKID_FCLK_DIV7 6 +#define CLKID_GP0_PLL 7 +#define CLKID_HIFI_PLL 8 +#define CLKID_MPEG_SEL 9 +#define CLKID_MPEG_DIV 10 +#define CLKID_CLK81 11 +#define CLKID_MPLL0 12 +#define CLKID_MPLL1 13 +#define CLKID_MPLL2 14 +#define CLKID_MPLL3 15 +#define CLKID_CPU_FCLK_P00 16 +#define CLKID_CPU_FCLK_P01 17 +#define CLKID_CPU_FCLK_P0 18 +#define CLKID_CPU_FCLK_P10 19 +#define CLKID_CPU_FCLK_P11 20 +#define CLKID_CPU_FCLK_P1 21 +#define CLKID_CPU_FCLK_P 22 +#define CLKID_CPU_CLK 23 +#define CLKID_PCIE_PLL 24 +#define CLKID_PCIE_MUX 25 +#define CLKID_PCIE_REF 26 +#define CLKID_PCIE_INPUT_GATE 27 +#define CLKID_PCIE_CML_EN0 28 +#define CLKID_PCIE_CML_EN1 29 +#define CLKID_MIPI_ENABLE_GATE 30 #define CLKID_MIPI_BANDGAP_GATE 31 +#define CLKID_FCLK_DIV2P5 32 /*HHI_GCLK_MPEG0: 0x50*/ -#define GATE_BASE0 32 -#define CLKID_DDR (GATE_BASE0 + 0) -#define CLKID_AUDIO_LOCKER (GATE_BASE0 + 1) -#define CLKID_MIPI_DSI_HOST (GATE_BASE0 + 2) -#define CLKID_ISA (GATE_BASE0 + 3) -#define CLKID_PL301 (GATE_BASE0 + 4) -#define CLKID_PERIPHS (GATE_BASE0 + 5) -#define CLKID_SPICC0 (GATE_BASE0 + 6) -#define CLKID_I2C (GATE_BASE0 + 7) -#define CLKID_RNG0 (GATE_BASE0 + 8) -#define CLKID_UART0 (GATE_BASE0 + 9) -#define CLKID_MIPI_DSI_PHY (GATE_BASE0 + 10) -#define CLKID_SPICC1 (GATE_BASE0 + 11) -#define CLKID_PCIE_A (GATE_BASE0 + 12) -#define CLKID_PCIE_B (GATE_BASE0 + 13) -#define CLKID_HIU_REG (GATE_BASE0 + 14) -#define CLKID_ASSIST_MISC (GATE_BASE0 + 15) -#define CLKID_SD_EMMC_B (GATE_BASE0 + 16) -#define CLKID_SD_EMMC_C (GATE_BASE0 + 17) -#define CLKID_DMA (GATE_BASE0 + 18) -#define CLKID_SPI (GATE_BASE0 + 19) +#define GATE_BASE0 33 +#define CLKID_DDR (GATE_BASE0 + 0) +#define CLKID_DOS (GATE_BASE0 + 1) +#define CLKID_AUDIO_LOCKER (GATE_BASE0 + 2) +#define CLKID_MIPI_DSI_HOST (GATE_BASE0 + 3) +#define CLKID_ETH_PHY (GATE_BASE0 + 4) +#define CLKID_ISA (GATE_BASE0 + 5) +#define CLKID_PL301 (GATE_BASE0 + 6) +#define CLKID_PERIPHS (GATE_BASE0 + 7) +#define CLKID_SPICC0 (GATE_BASE0 + 8) +#define CLKID_I2C (GATE_BASE0 + 9) +#define CLKID_SANA (GATE_BASE0 + 10) +#define CLKID_SD (GATE_BASE0 + 11) +#define CLKID_RNG0 (GATE_BASE0 + 12) +#define CLKID_UART0 (GATE_BASE0 + 13) +#define CLKID_SPICC1 (GATE_BASE0 + 14) +#define CLKID_HIU_REG (GATE_BASE0 + 15) +#define CLKID_MIPI_DSI_PHY (GATE_BASE0 + 16) +#define CLKID_ASSIST_MISC (GATE_BASE0 + 17) +#define CLKID_SD_EMMC_A (GATE_BASE0 + 18) +#define CLKID_SD_EMMC_B (GATE_BASE0 + 19) +#define CLKID_SD_EMMC_C (GATE_BASE0 + 20) +#define CLKID_ACODEC (GATE_BASE0 + 21) + /*HHI_GCLK_MPEG1: 0x51*/ -#define GATE_BASE1 (GATE_BASE0 + 20) /*28+20*/ -#define CLKID_AUDIO (GATE_BASE1 + 0) -#define CLKID_ETH_CORE (GATE_BASE1 + 1) -#define CLKID_UART1 (GATE_BASE1 + 2) -#define CLKID_G2D (GATE_BASE1 + 3) -#define CLKID_USB0 (GATE_BASE1 + 4) -#define CLKID_USB1 (GATE_BASE1 + 5) -#define CLKID_RESET (GATE_BASE1 + 6) -#define CLKID_USB_GENERAL (GATE_BASE1 + 7) -#define CLKID_AHB_ARB0 (GATE_BASE1 + 8) -#define CLKID_EFUSE (GATE_BASE1 + 9) -#define CLKID_BOOT_ROM (GATE_BASE1 + 10) +#define GATE_BASE1 (GATE_BASE0 + 22) +#define CLKID_AUDIO (GATE_BASE1 + 0) +#define CLKID_ETH_CORE (GATE_BASE1 + 1) +#define CLKID_U_STP_TOP (GATE_BASE1 + 2) +#define CLKID_AIFIFO (GATE_BASE1 + 3) +#define CLKID_ADC (GATE_BASE1 + 4) +#define CLKID_UART1 (GATE_BASE1 + 5) +#define CLKID_G2D (GATE_BASE1 + 6) +#define CLKID_RESET (GATE_BASE1 + 7) +#define CLKID_PCIE_COMB (GATE_BASE1 + 8) +#define CLKID_PARSER (GATE_BASE1 + 9) +#define CLKID_USB_GENERAL (GATE_BASE1 + 10) +#define CLKID_PCIE_PHY (GATE_BASE1 + 11) +#define CLKID_AHB_ARB0 (GATE_BASE1 + 12) + /*HHI_GCLK_MPEG2: 0x52*/ -#define GATE_BASE2 (GATE_BASE1 + 11) /*28+20+11*/ -#define CLKID_AHB_DATA_BUS (GATE_BASE2 + 0) -#define CLKID_AHB_CTRL_BUS (GATE_BASE2 + 1) -#define CLKID_USB1_TO_DDR (GATE_BASE2 + 2) -#define CLKID_USB0_TO_DDR (GATE_BASE2 + 3) -#define CLKID_MMC_PCLK (GATE_BASE2 + 4) -#define CLKID_VPU_INTR (GATE_BASE2 + 5) -#define CLKID_SEC_AHB_AHB3_BRIDGE (GATE_BASE2 + 6) -#define CLKID_GIC (GATE_BASE2 + 7) +#define GATE_BASE2 (GATE_BASE1 + 13) +#define CLKID_AHB_DATA_BUS (GATE_BASE2 + 0) +#define CLKID_AHB_CTRL_BUS (GATE_BASE2 + 1) +#define CLKID_HTX_HDCP22 (GATE_BASE2 + 2) +#define CLKID_HTX_PCLK (GATE_BASE2 + 3) +#define CLKID_BT656 (GATE_BASE2 + 4) +#define CLKID_USB1_TO_DDR (GATE_BASE2 + 5) +#define CLKID_MMC_PCLK (GATE_BASE2 + 6) +#define CLKID_UART2 (GATE_BASE2 + 7) +#define CLKID_VPU_INTR (GATE_BASE2 + 8) +#define CLKID_GIC (GATE_BASE2 + 9) -#define GATE_AO_BASE (GATE_BASE2 + 8) /*28+20+11+8*/ -#define CLKID_AO_MEDIA_CPU (GATE_AO_BASE + 0) -#define CLKID_AO_AHB_SRAM (GATE_AO_BASE + 1) -#define CLKID_AO_AHB_BUS (GATE_AO_BASE + 2) -#define CLKID_AO_IFACE (GATE_AO_BASE + 3) -#define CLKID_AO_I2C (GATE_AO_BASE + 4) +#define GATE_AO_BASE (GATE_BASE2 + 10) +#define CLKID_AO_MEDIA_CPU (GATE_AO_BASE + 0) +#define CLKID_AO_AHB_SRAM (GATE_AO_BASE + 1) +#define CLKID_AO_AHB_BUS (GATE_AO_BASE + 2) +#define CLKID_AO_IFACE (GATE_AO_BASE + 3) +#define CLKID_AO_I2C (GATE_AO_BASE + 4) -#define OTHER_BASE (GATE_AO_BASE + 5) /*28+20+11+8+5=72*/ -#define CLKID_SD_EMMC_B_P0_MUX (OTHER_BASE + 0) -#define CLKID_SD_EMMC_B_P0_DIV (OTHER_BASE + 1) +#define OTHER_BASE (GATE_AO_BASE + 5) +#define CLKID_SD_EMMC_B_P0_MUX (OTHER_BASE + 0) +#define CLKID_SD_EMMC_B_P0_DIV (OTHER_BASE + 1) #define CLKID_SD_EMMC_B_P0_GATE (OTHER_BASE + 2) #define CLKID_SD_EMMC_B_P0_COMP (OTHER_BASE + 3) -#define CLKID_SD_EMMC_C_P0_MUX (OTHER_BASE + 4) -#define CLKID_SD_EMMC_C_P0_DIV (OTHER_BASE + 5) +#define CLKID_SD_EMMC_C_P0_MUX (OTHER_BASE + 4) +#define CLKID_SD_EMMC_C_P0_DIV (OTHER_BASE + 5) #define CLKID_SD_EMMC_C_P0_GATE (OTHER_BASE + 6) #define CLKID_SD_EMMC_C_P0_COMP (OTHER_BASE + 7) -#define CLKID_SD_EMMC_B_MUX (OTHER_BASE + 8) -#define CLKID_SD_EMMC_B_DIV (OTHER_BASE + 9) -#define CLKID_SD_EMMC_B_GATE (OTHER_BASE + 10) -#define CLKID_SD_EMMC_B_COMP (OTHER_BASE + 11) -#define CLKID_SD_EMMC_C_MUX (OTHER_BASE + 12) -#define CLKID_SD_EMMC_C_DIV (OTHER_BASE + 13) -#define CLKID_SD_EMMC_C_GATE (OTHER_BASE + 14) -#define CLKID_SD_EMMC_C_COMP (OTHER_BASE + 15) +#define CLKID_SD_EMMC_B_MUX (OTHER_BASE + 8) +#define CLKID_SD_EMMC_B_DIV (OTHER_BASE + 9) +#define CLKID_SD_EMMC_B_GATE (OTHER_BASE + 10) +#define CLKID_SD_EMMC_B_COMP (OTHER_BASE + 11) +#define CLKID_SD_EMMC_C_MUX (OTHER_BASE + 12) +#define CLKID_SD_EMMC_C_DIV (OTHER_BASE + 13) +#define CLKID_SD_EMMC_C_GATE (OTHER_BASE + 14) +#define CLKID_SD_EMMC_C_COMP (OTHER_BASE + 15) -#define CLKID_MEDIA_BASE (OTHER_BASE + 16) /*28+20+11+8+5+16*/ -#define CLKID_VPU_P0_MUX (CLKID_MEDIA_BASE + 0) -#define CLKID_VPU_P0_DIV (CLKID_MEDIA_BASE + 1) -#define CLKID_VPU_P0_GATE (CLKID_MEDIA_BASE + 2) -#define CLKID_VPU_P0_COMP (CLKID_MEDIA_BASE + 3) -#define CLKID_VPU_P1_MUX (CLKID_MEDIA_BASE + 4) -#define CLKID_VPU_P1_DIV (CLKID_MEDIA_BASE + 5) -#define CLKID_VPU_P1_GATE (CLKID_MEDIA_BASE + 6) -#define CLKID_VPU_P1_COMP (CLKID_MEDIA_BASE + 7) -#define CLKID_VPU_MUX (CLKID_MEDIA_BASE + 8) -#define CLKID_VAPB_P0_MUX (CLKID_MEDIA_BASE + 9) -#define CLKID_VAPB_P0_DIV (CLKID_MEDIA_BASE + 10) -#define CLKID_VAPB_P0_GATE (CLKID_MEDIA_BASE + 11) -#define CLKID_VAPB_P0_COMP (CLKID_MEDIA_BASE + 12) -#define CLKID_VAPB_P1_MUX (CLKID_MEDIA_BASE + 13) -#define CLKID_VAPB_P1_DIV (CLKID_MEDIA_BASE + 14) -#define CLKID_VAPB_P1_GATE (CLKID_MEDIA_BASE + 15) -#define CLKID_VAPB_P1_COMP (CLKID_MEDIA_BASE + 16) -#define CLKID_VAPB_MUX (CLKID_MEDIA_BASE + 17) -#define CLKID_GE2D_GATE (CLKID_MEDIA_BASE + 18) -#define CLKID_DSI_MEAS_MUX (CLKID_MEDIA_BASE + 19) -#define CLKID_DSI_MEAS_DIV (CLKID_MEDIA_BASE + 20) -#define CLKID_DSI_MEAS_GATE (CLKID_MEDIA_BASE + 21) -#define CLKID_DSI_MEAS_COMP (CLKID_MEDIA_BASE + 22) +#define CLKID_GPU_BASE (OTHER_BASE + 16) +#define CLKID_GPU_P0_MUX (CLKID_GPU_BASE + 0) +#define CLKID_GPU_P0_DIV (CLKID_GPU_BASE + 1) +#define CLKID_GPU_P0_GATE (CLKID_GPU_BASE + 2) +#define CLKID_GPU_P0_COMP (CLKID_GPU_BASE + 3) +#define CLKID_GPU_P1_MUX (CLKID_GPU_BASE + 4) +#define CLKID_GPU_P1_DIV (CLKID_GPU_BASE + 5) +#define CLKID_GPU_P1_GATE (CLKID_GPU_BASE + 6) +#define CLKID_GPU_P1_COMP (CLKID_GPU_BASE + 7) +#define CLKID_GPU_MUX (CLKID_GPU_BASE + 8) -#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 23) /*28+20+11+8+5+16+23 = 111*/ -#define CLKID_SPICC_MUX (CLKID_MISC_BASE + 0) -#define CLKID_SPICC_DIV (CLKID_MISC_BASE + 1) -#define CLKID_SPICC_GATE (CLKID_MISC_BASE + 2) -#define CLKID_SPICC_COMP (CLKID_MISC_BASE + 3) +#define CLKID_MEDIA_BASE (CLKID_GPU_BASE + 9) +#define CLKID_VPU_P0_MUX (CLKID_MEDIA_BASE + 0) +#define CLKID_VPU_P0_DIV (CLKID_MEDIA_BASE + 1) +#define CLKID_VPU_P0_GATE (CLKID_MEDIA_BASE + 2) +#define CLKID_VPU_P0_COMP (CLKID_MEDIA_BASE + 3) +#define CLKID_VPU_P1_MUX (CLKID_MEDIA_BASE + 4) +#define CLKID_VPU_P1_DIV (CLKID_MEDIA_BASE + 5) +#define CLKID_VPU_P1_GATE (CLKID_MEDIA_BASE + 6) +#define CLKID_VPU_P1_COMP (CLKID_MEDIA_BASE + 7) +#define CLKID_VPU_MUX (CLKID_MEDIA_BASE + 8) +#define CLKID_VAPB_P0_MUX (CLKID_MEDIA_BASE + 9) +#define CLKID_VAPB_P0_DIV (CLKID_MEDIA_BASE + 10) +#define CLKID_VAPB_P0_GATE (CLKID_MEDIA_BASE + 11) +#define CLKID_VAPB_P0_COMP (CLKID_MEDIA_BASE + 12) +#define CLKID_VAPB_P1_MUX (CLKID_MEDIA_BASE + 13) +#define CLKID_VAPB_P1_DIV (CLKID_MEDIA_BASE + 14) +#define CLKID_VAPB_P1_GATE (CLKID_MEDIA_BASE + 15) +#define CLKID_VAPB_P1_COMP (CLKID_MEDIA_BASE + 16) +#define CLKID_VAPB_MUX (CLKID_MEDIA_BASE + 17) +#define CLKID_GE2D_GATE (CLKID_MEDIA_BASE + 18) +#define CLKID_DSI_MEAS_MUX (CLKID_MEDIA_BASE + 19) +#define CLKID_DSI_MEAS_DIV (CLKID_MEDIA_BASE + 20) +#define CLKID_DSI_MEAS_GATE (CLKID_MEDIA_BASE + 21) +#define CLKID_DSI_MEAS_COMP (CLKID_MEDIA_BASE + 22) +#define CLKID_VPU_CLKB_TMP_COMP (CLKID_MEDIA_BASE + 23) +#define CLKID_VPU_CLKB_COMP (CLKID_MEDIA_BASE + 24) -#define CLKID_AO_BASE (CLKID_MISC_BASE + 4) /*28+20+11+8+5+16+23+4 = 115*/ -#define CLKID_AO_CLK81 (CLKID_AO_BASE + 0) -#define CLKID_SARADC_MUX (CLKID_AO_BASE + 1) -#define CLKID_SARADC_DIV (CLKID_AO_BASE + 2) -#define CLKID_SARADC_GATE (CLKID_AO_BASE + 3) +#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 25) +#define CLKID_SPICC_MUX (CLKID_MISC_BASE + 0) +#define CLKID_SPICC_DIV (CLKID_MISC_BASE + 1) +#define CLKID_SPICC_GATE (CLKID_MISC_BASE + 2) +#define CLKID_SPICC_COMP (CLKID_MISC_BASE + 3) -#define NR_CLKS (OTHER_BASE + 47) +#define CLKID_AO_BASE (CLKID_MISC_BASE + 4) +#define CLKID_AO_CLK81 (CLKID_AO_BASE + 0) +#define CLKID_SARADC_MUX (CLKID_AO_BASE + 1) +#define CLKID_SARADC_DIV (CLKID_AO_BASE + 2) +#define CLKID_SARADC_GATE (CLKID_AO_BASE + 3) + +#define NR_CLKS (CLKID_MISC_BASE + 4) #endif /* __G12A_CLKC_H */