diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt index 7b7104e8cb1e..9cfcb4f2bc97 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt @@ -8,6 +8,8 @@ Required properties : "qcom,gcc-msm8660" "qcom,gcc-msm8960" "qcom,gcc-msm8974" + "qcom,gcc-msm8974pro" + "qcom,gcc-msm8974pro-ac" - reg : shall contain base register location and length - #clock-cells : shall contain 1 diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 7a420fcdb89e..7af7c18d2144 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -35,6 +35,7 @@ #define P_XO 0 #define P_GPLL0 1 #define P_GPLL1 1 +#define P_GPLL4 2 static const u8 gcc_xo_gpll0_map[] = { [P_XO] = 0, @@ -46,6 +47,18 @@ static const char *gcc_xo_gpll0[] = { "gpll0_vote", }; +static const u8 gcc_xo_gpll0_gpll4_map[] = { + [P_XO] = 0, + [P_GPLL0] = 1, + [P_GPLL4] = 5, +}; + +static const char *gcc_xo_gpll0_gpll4[] = { + "xo", + "gpll0_vote", + "gpll4_vote", +}; + #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } static struct clk_pll gpll0 = { @@ -138,6 +151,33 @@ static struct clk_regmap gpll1_vote = { }, }; +static struct clk_pll gpll4 = { + .l_reg = 0x1dc4, + .m_reg = 0x1dc8, + .n_reg = 0x1dcc, + .config_reg = 0x1dd4, + .mode_reg = 0x1dc0, + .status_reg = 0x1ddc, + .status_bit = 17, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap gpll4_vote = { + .enable_reg = 0x1480, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4_vote", + .parent_names = (const char *[]){ "gpll4" }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { F(125000000, P_GPLL0, 1, 5, 24), { } @@ -812,18 +852,33 @@ static const struct freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = { { } }; +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_pro[] = { + F(144000, P_XO, 16, 3, 25), + F(400000, P_XO, 12, 1, 4), + F(20000000, P_GPLL0, 15, 1, 2), + F(25000000, P_GPLL0, 12, 1, 2), + F(50000000, P_GPLL0, 12, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + F(192000000, P_GPLL4, 4, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(384000000, P_GPLL4, 2, 0, 0), + { } +}; + +static struct clk_init_data sdcc1_apps_clk_src_init = { + .name = "sdcc1_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, +}; + static struct clk_rcg2 sdcc1_apps_clk_src = { .cmd_rcgr = 0x04d0, .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk, - .clkr.hw.init = &(struct clk_init_data){ - .name = "sdcc1_apps_clk_src", - .parent_names = gcc_xo_gpll0, - .num_parents = 2, - .ops = &clk_rcg2_ops, - }, + .clkr.hw.init = &sdcc1_apps_clk_src_init, }; static struct clk_rcg2 sdcc2_apps_clk_src = { @@ -1995,6 +2050,38 @@ static struct clk_branch gcc_sdcc1_apps_clk = { }, }; +static struct clk_branch gcc_sdcc1_cdccal_ff_clk = { + .halt_reg = 0x04e8, + .clkr = { + .enable_reg = 0x04e8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_cdccal_ff_clk", + .parent_names = (const char *[]){ + "xo" + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = { + .halt_reg = 0x04e4, + .clkr = { + .enable_reg = 0x04e4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_cdccal_sleep_clk", + .parent_names = (const char *[]){ + "sleep_clk_src" + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc2_ahb_clk = { .halt_reg = 0x0508, .clkr = { @@ -2484,6 +2571,10 @@ static struct clk_regmap *gcc_msm8974_clocks[] = { [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr, [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, [GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src, + [GPLL4] = NULL, + [GPLL4_VOTE] = NULL, + [GCC_SDCC1_CDCCAL_SLEEP_CLK] = NULL, + [GCC_SDCC1_CDCCAL_FF_CLK] = NULL, }; static const struct qcom_reset_map gcc_msm8974_resets[] = { @@ -2585,14 +2676,41 @@ static const struct qcom_cc_desc gcc_msm8974_desc = { static const struct of_device_id gcc_msm8974_match_table[] = { { .compatible = "qcom,gcc-msm8974" }, + { .compatible = "qcom,gcc-msm8974pro" , .data = (void *)1UL }, + { .compatible = "qcom,gcc-msm8974pro-ac", .data = (void *)1UL }, { } }; MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); +static void msm8974_pro_clock_override(void) +{ + sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4; + sdcc1_apps_clk_src_init.num_parents = 3; + sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_pro; + sdcc1_apps_clk_src.parent_map = gcc_xo_gpll0_gpll4_map; + + gcc_msm8974_clocks[GPLL4] = &gpll4.clkr; + gcc_msm8974_clocks[GPLL4_VOTE] = &gpll4_vote; + gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_SLEEP_CLK] = + &gcc_sdcc1_cdccal_sleep_clk.clkr; + gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_FF_CLK] = + &gcc_sdcc1_cdccal_ff_clk.clkr; +} + static int gcc_msm8974_probe(struct platform_device *pdev) { struct clk *clk; struct device *dev = &pdev->dev; + bool pro; + const struct of_device_id *id; + + id = of_match_device(gcc_msm8974_match_table, dev); + if (!id) + return -ENODEV; + pro = !!(id->data); + + if (pro) + msm8974_pro_clock_override(); /* Temporary until RPM clocks supported */ clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); diff --git a/include/dt-bindings/clock/qcom,gcc-msm8974.h b/include/dt-bindings/clock/qcom,gcc-msm8974.h index 223ca174d9d3..51e51c860fe6 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8974.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8974.h @@ -316,5 +316,9 @@ #define GCC_CE2_CLK_SLEEP_ENA 299 #define GCC_CE2_AXI_CLK_SLEEP_ENA 300 #define GCC_CE2_AHB_CLK_SLEEP_ENA 301 +#define GPLL4 302 +#define GPLL4_VOTE 303 +#define GCC_SDCC1_CDCCAL_SLEEP_CLK 304 +#define GCC_SDCC1_CDCCAL_FF_CLK 305 #endif