From 7f2c2f38c1c0dbfc5b1e13aa57678daa753e1c96 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 22 Sep 2020 14:00:36 +0200 Subject: clk: renesas: rcar-gen3: Remove stp_ck handling for SDHI There is no case (and none foreseen) where we would need to disable the SDn clock. So, for simplicity, remove its handling. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200922120036.10298-1-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-gen3-cpg.c | 51 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 488f8b3980c5..a7debddf7d09 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -224,10 +224,9 @@ static struct clk * __init cpg_z_clk_register(const char *name, #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) -#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ +#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \ { \ .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ - ((stp_ck) ? CPG_SD_STP_CK : 0) | \ ((sd_srcfc) << 2) | \ ((sd_fc) << 0), \ .div = (sd_div), \ @@ -247,36 +246,36 @@ struct sd_clock { }; /* SDn divider - * sd_srcfc sd_fc div - * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc - *------------------------------------------------------------------- - * 0 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) - * 0 0 1 (2) 1 (4) 8 : SDR50 - * 1 0 2 (4) 1 (4) 16 : HS / SDR25 - * 1 0 3 (8) 1 (4) 32 : NS / SDR12 - * 1 0 4 (16) 1 (4) 64 - * 0 0 0 (1) 0 (2) 2 - * 0 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) - * 1 0 2 (4) 0 (2) 8 - * 1 0 3 (8) 0 (2) 16 - * 1 0 4 (16) 0 (2) 32 + * sd_srcfc sd_fc div + * stp_hck (div) (div) = sd_srcfc x sd_fc + *--------------------------------------------------------- + * 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) + * 0 1 (2) 1 (4) 8 : SDR50 + * 1 2 (4) 1 (4) 16 : HS / SDR25 + * 1 3 (8) 1 (4) 32 : NS / SDR12 + * 1 4 (16) 1 (4) 64 + * 0 0 (1) 0 (2) 2 + * 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) + * 1 2 (4) 0 (2) 8 + * 1 3 (8) 0 (2) 16 + * 1 4 (16) 0 (2) 32 * * NOTE: There is a quirk option to ignore the first row of the dividers * table when searching for suitable settings. This is because HS400 on * early ES versions of H3 and M3-W requires a specific setting to work. */ static const struct sd_div_table cpg_sd_div_table[] = { -/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), +/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */ + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4), + CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8), + CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16), + CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32), + CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64), + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2), + CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4), + CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8), + CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16), + CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32), }; #define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) -- cgit v1.2.3-59-g8ed1b From 61a31292002b85529021a46e6288b29caf674fbe Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sat, 17 Oct 2020 00:13:32 +0530 Subject: clk: qcom: clk-alpha-pll: Add support for helper functions Introduce clk_alpha_pll_write_config and alpha_pll_check_rate_margin helper functions to be across PLL configure functions and PLL set rate functions. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1602873815-1677-2-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 155 +++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 89 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 564431130a76..f3b8b54fefd5 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -207,6 +207,13 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, #define wait_for_pll_update_ack_clear(pll) \ wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 1, "update_ack_clear") +static void clk_alpha_pll_write_config(struct regmap *regmap, unsigned int reg, + unsigned int val) +{ + if (val) + regmap_write(regmap, reg, val); +} + void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { @@ -1004,33 +1011,19 @@ void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, { u32 val, mask; - if (config->l) - regmap_write(regmap, PLL_L_VAL(pll), config->l); - - if (config->alpha) - regmap_write(regmap, PLL_FRAC(pll), config->alpha); - - if (config->config_ctl_val) - regmap_write(regmap, PLL_CONFIG_CTL(pll), + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); + clk_alpha_pll_write_config(regmap, PLL_FRAC(pll), config->alpha); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); - - if (config->config_ctl_hi_val) - regmap_write(regmap, PLL_CONFIG_CTL_U(pll), + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); - - if (config->user_ctl_val) - regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val); - - if (config->user_ctl_hi_val) - regmap_write(regmap, PLL_USER_CTL_U(pll), + clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), + config->user_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); - - if (config->test_ctl_val) - regmap_write(regmap, PLL_TEST_CTL(pll), + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); - - if (config->test_ctl_hi_val) - regmap_write(regmap, PLL_TEST_CTL_U(pll), + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); if (config->post_div_mask) { @@ -1145,25 +1138,38 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); } +/* + * Due to limited number of bits for fractional rate programming, the + * rounded up rate could be marginally higher than the requested rate. + */ +static int alpha_pll_check_rate_margin(struct clk_hw *hw, + unsigned long rrate, unsigned long rate) +{ + unsigned long rate_margin = rate + PLL_RATE_MARGIN; + + if (rrate > rate_margin || rrate < rate) { + pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n", + clk_hw_get_name(hw), rrate, rate, rate_margin); + return -EINVAL; + } + + return 0; +} + static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, alpha_width = pll_alpha_width(pll); + unsigned long rrate; + int ret; u64 a; - unsigned long rrate, max = rate + PLL_RATE_MARGIN; rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); - /* - * Due to limited number of bits for fractional rate programming, the - * rounded up rate could be marginally higher than the requested rate. - */ - if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) { - pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n", - clk_hw_get_name(hw), rrate, rate, max); - return -EINVAL; - } + ret = alpha_pll_check_rate_margin(hw, rrate, rate); + if (ret < 0) + return ret; regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); regmap_write(pll->clkr.regmap, PLL_FRAC(pll), a); @@ -1206,12 +1212,10 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw), &cal_l, &a, alpha_width); - /* - * Due to a limited number of bits for fractional rate programming, the - * rounded up rate could be marginally higher than the requested rate. - */ - if (rrate > (cal_freq + PLL_RATE_MARGIN) || rrate < cal_freq) - return -EINVAL; + + ret = alpha_pll_check_rate_margin(hw, rrate, cal_freq); + if (ret < 0) + return ret; /* Setup PLL for calibration frequency */ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l); @@ -1388,49 +1392,27 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { - if (config->l) - regmap_write(regmap, PLL_L_VAL(pll), config->l); - + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL); - - if (config->alpha) - regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); - - if (config->config_ctl_val) - regmap_write(regmap, PLL_CONFIG_CTL(pll), - config->config_ctl_val); - - if (config->config_ctl_hi_val) - regmap_write(regmap, PLL_CONFIG_CTL_U(pll), - config->config_ctl_hi_val); - - if (config->config_ctl_hi1_val) - regmap_write(regmap, PLL_CONFIG_CTL_U1(pll), - config->config_ctl_hi1_val); - - if (config->user_ctl_val) - regmap_write(regmap, PLL_USER_CTL(pll), - config->user_ctl_val); - - if (config->user_ctl_hi_val) - regmap_write(regmap, PLL_USER_CTL_U(pll), - config->user_ctl_hi_val); - - if (config->user_ctl_hi1_val) - regmap_write(regmap, PLL_USER_CTL_U1(pll), - config->user_ctl_hi1_val); - - if (config->test_ctl_val) - regmap_write(regmap, PLL_TEST_CTL(pll), - config->test_ctl_val); - - if (config->test_ctl_hi_val) - regmap_write(regmap, PLL_TEST_CTL_U(pll), - config->test_ctl_hi_val); - - if (config->test_ctl_hi1_val) - regmap_write(regmap, PLL_TEST_CTL_U1(pll), - config->test_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), + config->config_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), + config->config_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), + config->config_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), + config->user_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), + config->user_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), + config->user_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), + config->test_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), + config->test_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), + config->test_ctl_hi1_val); regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, PLL_UPDATE_BYPASS); @@ -1490,14 +1472,9 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate, rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); - /* - * Due to a limited number of bits for fractional rate programming, the - * rounded up rate could be marginally higher than the requested rate. - */ - if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) { - pr_err("Call set rate on the PLL with rounded rates!\n"); - return -EINVAL; - } + ret = alpha_pll_check_rate_margin(hw, rrate, rate); + if (ret < 0) + return ret; regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); -- cgit v1.2.3-59-g8ed1b From a2b57943a570a69679abf82e1de01c806db084d1 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sat, 17 Oct 2020 00:13:33 +0530 Subject: clk: qcom: clk-alpha-pll: Add support for controlling Agera PLLs Add programming sequence support for managing the Agera PLLs. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1602873815-1677-3-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 62 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 4 +++ 2 files changed, 66 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index f3b8b54fefd5..21c357c26ec4 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -116,6 +116,16 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_OPMODE] = 0x38, [PLL_OFF_ALPHA_VAL] = 0x40, }, + [CLK_ALPHA_PLL_TYPE_AGERA] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_ALPHA_VAL] = 0x08, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_CONFIG_CTL] = 0x10, + [PLL_OFF_CONFIG_CTL_U] = 0x14, + [PLL_OFF_TEST_CTL] = 0x18, + [PLL_OFF_TEST_CTL_U] = 0x1c, + [PLL_OFF_STATUS] = 0x2c, + }, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); @@ -1538,3 +1548,55 @@ const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = { .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops); + +void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); + clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), + config->user_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), + config->config_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), + config->config_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), + config->test_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), + config->test_ctl_hi_val); +} +EXPORT_SYMBOL_GPL(clk_agera_pll_configure); + +static int clk_alpha_pll_agera_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, alpha_width = pll_alpha_width(pll); + int ret; + unsigned long rrate; + u64 a; + + rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); + ret = alpha_pll_check_rate_margin(hw, rrate, rate); + if (ret < 0) + return ret; + + /* change L_VAL without having to go through the power on sequence */ + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + + if (clk_hw_is_enabled(hw)) + return wait_for_pll_enable_lock(pll); + + return 0; +} + +const struct clk_ops clk_alpha_pll_agera_ops = { + .enable = clk_alpha_pll_enable, + .disable = clk_alpha_pll_disable, + .is_enabled = clk_alpha_pll_is_enabled, + .recalc_rate = alpha_pll_fabia_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = clk_alpha_pll_agera_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index d3201b87c0cd..0ea30d2f3da1 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -15,6 +15,7 @@ enum { CLK_ALPHA_PLL_TYPE_FABIA, CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, + CLK_ALPHA_PLL_TYPE_AGERA, CLK_ALPHA_PLL_TYPE_MAX, }; @@ -141,6 +142,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops; extern const struct clk_ops clk_alpha_pll_lucid_ops; #define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops; +extern const struct clk_ops clk_alpha_pll_agera_ops; void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); @@ -148,6 +150,8 @@ void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); +void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); #define clk_lucid_pll_configure(pll, regmap, config) \ clk_trion_pll_configure(pll, regmap, config) -- cgit v1.2.3-59-g8ed1b From 57b971907eb07fbc8917f9f7a2df37da6304a296 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sat, 17 Oct 2020 00:13:34 +0530 Subject: dt-bindings: clock: Add YAML schemas for the QCOM Camera clock bindings. The Camera Subsystem clock provider have a bunch of generic properties that are needed in a device tree. Add a YAML schemas for those. Add clock ids for camera clocks which are required to bring the camera subsystem out of reset. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1602873815-1677-4-git-send-email-tdas@codeaurora.org Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,sc7180-camcc.yaml | 73 +++++++++++++ include/dt-bindings/clock/qcom,camcc-sc7180.h | 121 +++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml create mode 100644 include/dt-bindings/clock/qcom,camcc-sc7180.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml new file mode 100644 index 000000000000..f49027edfc44 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sc7180-camcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Camera Clock & Reset Controller Binding for SC7180 + +maintainers: + - Taniya Das + +description: | + Qualcomm camera clock control module which supports the clocks, resets and + power domains on SC7180. + + See also: + - dt-bindings/clock/qcom,camcc-sc7180.h + +properties: + compatible: + const: qcom,sc7180-camcc + + clocks: + items: + - description: Board XO source + - description: Camera_ahb clock from GCC + - description: Camera XO clock from GCC + + clock-names: + items: + - const: bi_tcxo + - const: iface + - const: xo + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + #include + clock-controller@ad00000 { + compatible = "qcom,sc7180-camcc"; + reg = <0x0ad00000 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_XO_CLK>; + clock-names = "bi_tcxo", "iface", "xo"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,camcc-sc7180.h b/include/dt-bindings/clock/qcom,camcc-sc7180.h new file mode 100644 index 000000000000..ef7d3a041b88 --- /dev/null +++ b/include/dt-bindings/clock/qcom,camcc-sc7180.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_SC7180_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_SC7180_H + +/* CAM_CC clocks */ +#define CAM_CC_PLL2_OUT_EARLY 0 +#define CAM_CC_PLL0 1 +#define CAM_CC_PLL1 2 +#define CAM_CC_PLL2 3 +#define CAM_CC_PLL2_OUT_AUX 4 +#define CAM_CC_PLL3 5 +#define CAM_CC_CAMNOC_AXI_CLK 6 +#define CAM_CC_CCI_0_CLK 7 +#define CAM_CC_CCI_0_CLK_SRC 8 +#define CAM_CC_CCI_1_CLK 9 +#define CAM_CC_CCI_1_CLK_SRC 10 +#define CAM_CC_CORE_AHB_CLK 11 +#define CAM_CC_CPAS_AHB_CLK 12 +#define CAM_CC_CPHY_RX_CLK_SRC 13 +#define CAM_CC_CSI0PHYTIMER_CLK 14 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 15 +#define CAM_CC_CSI1PHYTIMER_CLK 16 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 17 +#define CAM_CC_CSI2PHYTIMER_CLK 18 +#define CAM_CC_CSI2PHYTIMER_CLK_SRC 19 +#define CAM_CC_CSI3PHYTIMER_CLK 20 +#define CAM_CC_CSI3PHYTIMER_CLK_SRC 21 +#define CAM_CC_CSIPHY0_CLK 22 +#define CAM_CC_CSIPHY1_CLK 23 +#define CAM_CC_CSIPHY2_CLK 24 +#define CAM_CC_CSIPHY3_CLK 25 +#define CAM_CC_FAST_AHB_CLK_SRC 26 +#define CAM_CC_ICP_APB_CLK 27 +#define CAM_CC_ICP_ATB_CLK 28 +#define CAM_CC_ICP_CLK 29 +#define CAM_CC_ICP_CLK_SRC 30 +#define CAM_CC_ICP_CTI_CLK 31 +#define CAM_CC_ICP_TS_CLK 32 +#define CAM_CC_IFE_0_AXI_CLK 33 +#define CAM_CC_IFE_0_CLK 34 +#define CAM_CC_IFE_0_CLK_SRC 35 +#define CAM_CC_IFE_0_CPHY_RX_CLK 36 +#define CAM_CC_IFE_0_CSID_CLK 37 +#define CAM_CC_IFE_0_CSID_CLK_SRC 38 +#define CAM_CC_IFE_0_DSP_CLK 39 +#define CAM_CC_IFE_1_AXI_CLK 40 +#define CAM_CC_IFE_1_CLK 41 +#define CAM_CC_IFE_1_CLK_SRC 42 +#define CAM_CC_IFE_1_CPHY_RX_CLK 43 +#define CAM_CC_IFE_1_CSID_CLK 44 +#define CAM_CC_IFE_1_CSID_CLK_SRC 45 +#define CAM_CC_IFE_1_DSP_CLK 46 +#define CAM_CC_IFE_LITE_CLK 47 +#define CAM_CC_IFE_LITE_CLK_SRC 48 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 49 +#define CAM_CC_IFE_LITE_CSID_CLK 50 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 51 +#define CAM_CC_IPE_0_AHB_CLK 52 +#define CAM_CC_IPE_0_AREG_CLK 53 +#define CAM_CC_IPE_0_AXI_CLK 54 +#define CAM_CC_IPE_0_CLK 55 +#define CAM_CC_IPE_0_CLK_SRC 56 +#define CAM_CC_JPEG_CLK 57 +#define CAM_CC_JPEG_CLK_SRC 58 +#define CAM_CC_LRME_CLK 59 +#define CAM_CC_LRME_CLK_SRC 60 +#define CAM_CC_MCLK0_CLK 61 +#define CAM_CC_MCLK0_CLK_SRC 62 +#define CAM_CC_MCLK1_CLK 63 +#define CAM_CC_MCLK1_CLK_SRC 64 +#define CAM_CC_MCLK2_CLK 65 +#define CAM_CC_MCLK2_CLK_SRC 66 +#define CAM_CC_MCLK3_CLK 67 +#define CAM_CC_MCLK3_CLK_SRC 68 +#define CAM_CC_MCLK4_CLK 69 +#define CAM_CC_MCLK4_CLK_SRC 70 +#define CAM_CC_BPS_AHB_CLK 71 +#define CAM_CC_BPS_AREG_CLK 72 +#define CAM_CC_BPS_AXI_CLK 73 +#define CAM_CC_BPS_CLK 74 +#define CAM_CC_BPS_CLK_SRC 75 +#define CAM_CC_SLOW_AHB_CLK_SRC 76 +#define CAM_CC_SOC_AHB_CLK 77 +#define CAM_CC_SYS_TMR_CLK 78 + +/* CAM_CC power domains */ +#define BPS_GDSC 0 +#define IFE_0_GDSC 1 +#define IFE_1_GDSC 2 +#define IPE_0_GDSC 3 +#define TITAN_TOP_GDSC 4 + +/* CAM_CC resets */ +#define CAM_CC_BPS_BCR 0 +#define CAM_CC_CAMNOC_BCR 1 +#define CAM_CC_CCI_0_BCR 2 +#define CAM_CC_CCI_1_BCR 3 +#define CAM_CC_CPAS_BCR 4 +#define CAM_CC_CSI0PHY_BCR 5 +#define CAM_CC_CSI1PHY_BCR 6 +#define CAM_CC_CSI2PHY_BCR 7 +#define CAM_CC_CSI3PHY_BCR 8 +#define CAM_CC_ICP_BCR 9 +#define CAM_CC_IFE_0_BCR 10 +#define CAM_CC_IFE_1_BCR 11 +#define CAM_CC_IFE_LITE_BCR 12 +#define CAM_CC_IPE_0_BCR 13 +#define CAM_CC_JPEG_BCR 14 +#define CAM_CC_LRME_BCR 15 +#define CAM_CC_MCLK0_BCR 16 +#define CAM_CC_MCLK1_BCR 17 +#define CAM_CC_MCLK2_BCR 18 +#define CAM_CC_MCLK3_BCR 19 +#define CAM_CC_MCLK4_BCR 20 +#define CAM_CC_TITAN_TOP_BCR 21 + +#endif -- cgit v1.2.3-59-g8ed1b From 15d09e830bbc16880840ac8b01941465602807f4 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sat, 17 Oct 2020 00:13:35 +0530 Subject: clk: qcom: camcc: Add camera clock controller driver for SC7180 Add support for the camera clock controller found on SC7180 based devices. This would allow camera drivers to probe and control their clocks. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1602873815-1677-5-git-send-email-tdas@codeaurora.org [sboyd@kernel.org: Mark hw array static, add UL to big vco numbers] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/camcc-sc7180.c | 1736 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1746 insertions(+) create mode 100644 drivers/clk/qcom/camcc-sc7180.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 3a965bd326d5..886e8610b321 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -290,6 +290,15 @@ config QCS_GCC_404 Say Y if you want to use multimedia devices or peripheral devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc. +config SC_CAMCC_7180 + tristate "SC7180 Camera Clock Controller" + select SC_GCC_7180 + help + Support for the camera clock controller on Qualcomm Technologies, Inc + SC7180 devices. + Say Y if you want to support camera devices and functionality such as + capturing pictures. + config SC_DISPCC_7180 tristate "SC7180 Display Clock Controller" select SC_GCC_7180 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 11ae86febe87..ee02fafbae27 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o +obj-$(CONFIG_SC_CAMCC_7180) += camcc-sc7180.o obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c new file mode 100644 index 000000000000..f51bf5b6decc --- /dev/null +++ b/drivers/clk/qcom/camcc-sc7180.c @@ -0,0 +1,1736 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_AUX, + P_CAM_CC_PLL2_OUT_EARLY, + P_CAM_CC_PLL3_OUT_MAIN, + P_CORE_BI_PLL_TEST_SE, +}; + +static const struct pll_vco agera_vco[] = { + { 600000000, 3300000000UL, 0 }, +}; + +static const struct pll_vco fabia_vco[] = { + { 249600000, 2000000000UL, 0 }, +}; + +/* 600MHz configuration */ +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x1f, + .alpha = 0x4000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002067, + .test_ctl_val = 0x40000000, + .user_ctl_hi_val = 0x00004805, + .user_ctl_val = 0x00000001, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .vco_table = fabia_vco, + .num_vco = ARRAY_SIZE(fabia_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fabia_ops, + }, + }, +}; + +/* 860MHz configuration */ +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x2a, + .alpha = 0x1555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002067, + .test_ctl_val = 0x40000000, + .user_ctl_hi_val = 0x00004805, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .vco_table = fabia_vco, + .num_vco = ARRAY_SIZE(fabia_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fabia_ops, + }, + }, +}; + +/* 1920MHz configuration */ +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x64, + .config_ctl_val = 0x20000800, + .config_ctl_hi_val = 0x400003D2, + .test_ctl_val = 0x04000400, + .test_ctl_hi_val = 0x00004000, + .user_ctl_val = 0x0000030F, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .vco_table = agera_vco, + .num_vco = ARRAY_SIZE(agera_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_AGERA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_agera_ops, + }, + }, +}; + +static struct clk_fixed_factor cam_cc_pll2_out_early = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2_out_early", + .parent_names = (const char *[]){ "cam_cc_pll2" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll2_out_aux[] = { + { 0x3, 4 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll2_out_aux = { + .offset = 0x2000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll2_out_aux, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_aux), + .width = 2, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_AGERA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2_out_aux", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_pll2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +/* 1080MHz configuration */ +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x38, + .alpha = 0x4000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002067, + .test_ctl_val = 0x40000000, + .user_ctl_hi_val = 0x00004805, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .vco_table = fabia_vco, + .num_vco = ARRAY_SIZE(fabia_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fabia_ops, + }, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll1.clkr.hw }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_AUX, 1 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll2_out_aux.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EARLY, 4 }, + { P_CAM_CC_PLL3_OUT_MAIN, 5 }, + { P_CAM_CC_PLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll2_out_early.hw }, + { .hw = &cam_cc_pll3.clkr.hw }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 2 }, + { P_CAM_CC_PLL2_OUT_EARLY, 4 }, + { P_CAM_CC_PLL3_OUT_MAIN, 5 }, + { P_CAM_CC_PLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll1.clkr.hw }, + { .hw = &cam_cc_pll2_out_early.hw }, + { .hw = &cam_cc_pll3.clkr.hw }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_MAIN, 5 }, + { P_CAM_CC_PLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll3.clkr.hw }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map cam_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 2 }, + { P_CAM_CC_PLL3_OUT_MAIN, 5 }, + { P_CAM_CC_PLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll1.clkr.hw }, + { .hw = &cam_cc_pll3.clkr.hw }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0), + F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_bps_clk_src = { + .cmd_rcgr = 0x6010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + F(50000000, P_CAM_CC_PLL0_OUT_EVEN, 12, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0xb0d8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0xb14c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0), + F(270000000, P_CAM_CC_PLL3_OUT_MAIN, 4, 0, 0), + F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0x9064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x5004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x5028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { + .cmd_rcgr = 0x504c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi2phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .cmd_rcgr = 0x5070, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi3phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(404000000, P_CAM_CC_PLL1_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x603c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = { + F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0), + F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0), + F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_icp_clk_src = { + .cmd_rcgr = 0xb088, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_icp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = { + F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0), + F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0), + F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .cmd_rcgr = 0x9010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_csid_clk_src[] = { + F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0), + F(270000000, P_CAM_CC_PLL3_OUT_MAIN, 4, 0, 0), + F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = { + .cmd_rcgr = 0x903c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_csid_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .cmd_rcgr = 0xa010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = { + .cmd_rcgr = 0xa034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_csid_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0xb004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0xb024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_0_clk_src[] = { + F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0), + F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0), + F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0), + F(540000000, P_CAM_CC_PLL3_OUT_MAIN, 2, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_0_clk_src = { + .cmd_rcgr = 0x7010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ipe_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = { + F(66666667, P_CAM_CC_PLL0_OUT_EVEN, 9, 0, 0), + F(133333333, P_CAM_CC_PLL0_OUT_EVEN, 4.5, 0, 0), + F(216000000, P_CAM_CC_PLL3_OUT_MAIN, 5, 0, 0), + F(320000000, P_CAM_CC_PLL2_OUT_EARLY, 3, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0xb04c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_jpeg_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_lrme_clk_src[] = { + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(216000000, P_CAM_CC_PLL3_OUT_MAIN, 5, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(404000000, P_CAM_CC_PLL1_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_lrme_clk_src = { + .cmd_rcgr = 0xb0f8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6, + .freq_tbl = ftbl_cam_cc_lrme_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_lrme_clk_src", + .parent_data = cam_cc_parent_data_6, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_CC_PLL2_OUT_AUX, 10, 1, 2), + F(64000000, P_CAM_CC_PLL2_OUT_AUX, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .cmd_rcgr = 0x4004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk0_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .cmd_rcgr = 0x4024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk1_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .cmd_rcgr = 0x4044, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk2_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .cmd_rcgr = 0x4064, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk3_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .cmd_rcgr = 0x4084, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk4_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x6058, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch cam_cc_bps_ahb_clk = { + .halt_reg = 0x6070, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6070, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_areg_clk = { + .halt_reg = 0x6054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_areg_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_axi_clk = { + .halt_reg = 0x6038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_clk = { + .halt_reg = 0x6028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_bps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_clk = { + .halt_reg = 0xb124, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb124, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0xb0f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb0f0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cci_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0xb164, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb164, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cci_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0xb144, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xb144, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_core_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ahb_clk = { + .halt_reg = 0xb11c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb11c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cpas_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x501c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi0phytimer_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x5040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi1phytimer_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi2phytimer_clk = { + .halt_reg = 0x5064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi2phytimer_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_csi2phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi3phytimer_clk = { + .halt_reg = 0x5088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi3phytimer_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_csi3phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x5020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x5044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy2_clk = { + .halt_reg = 0x5068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy3_clk = { + .halt_reg = 0x508c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x508c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_clk = { + .halt_reg = 0xb0a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb0a0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_icp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_axi_clk = { + .halt_reg = 0x9080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_clk = { + .halt_reg = 0x9028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_cphy_rx_clk = { + .halt_reg = 0x907c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x907c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_cphy_rx_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_csid_clk = { + .halt_reg = 0x9054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_csid_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_0_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_dsp_clk = { + .halt_reg = 0x9038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_dsp_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_axi_clk = { + .halt_reg = 0xa058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_clk = { + .halt_reg = 0xa028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_cphy_rx_clk = { + .halt_reg = 0xa054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_cphy_rx_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_csid_clk = { + .halt_reg = 0xa04c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa04c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_csid_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_1_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_dsp_clk = { + .halt_reg = 0xa030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_dsp_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0xb01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb01c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0xb044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0xb03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_csid_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ife_lite_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_ahb_clk = { + .halt_reg = 0x7040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_areg_clk = { + .halt_reg = 0x703c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x703c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_areg_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_axi_clk = { + .halt_reg = 0x7038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_clk = { + .halt_reg = 0x7028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_ipe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_clk = { + .halt_reg = 0xb064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_jpeg_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_lrme_clk = { + .halt_reg = 0xb110, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb110, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_lrme_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_lrme_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk0_clk = { + .halt_reg = 0x401c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x401c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk1_clk = { + .halt_reg = 0x403c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x403c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk2_clk = { + .halt_reg = 0x405c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x405c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk3_clk = { + .halt_reg = 0x407c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x407c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk4_clk = { + .halt_reg = 0x409c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x409c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk4_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &cam_cc_mclk4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_soc_ahb_clk = { + .halt_reg = 0xb140, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb140, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_soc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sys_tmr_clk = { + .halt_reg = 0xb0a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb0a8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sys_tmr_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc bps_gdsc = { + .gdscr = 0x6004, + .pd = { + .name = "bps_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL, +}; + +static struct gdsc ife_0_gdsc = { + .gdscr = 0x9004, + .pd = { + .name = "ife_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ife_1_gdsc = { + .gdscr = 0xa004, + .pd = { + .name = "ife_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ipe_0_gdsc = { + .gdscr = 0x7004, + .pd = { + .name = "ipe_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL, +}; + +static struct gdsc titan_top_gdsc = { + .gdscr = 0xb134, + .pd = { + .name = "titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_hw *cam_cc_sc7180_hws[] = { + [CAM_CC_PLL2_OUT_EARLY] = &cam_cc_pll2_out_early.hw, +}; + +static struct clk_regmap *cam_cc_sc7180_clocks[] = { + [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr, + [CAM_CC_BPS_AREG_CLK] = &cam_cc_bps_areg_clk.clkr, + [CAM_CC_BPS_AXI_CLK] = &cam_cc_bps_axi_clk.clkr, + [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr, + [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr, + [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr, + [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr, + [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr, + [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr, + [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, + [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr, + [CAM_CC_IFE_0_AXI_CLK] = &cam_cc_ife_0_axi_clk.clkr, + [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr, + [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr, + [CAM_CC_IFE_0_CPHY_RX_CLK] = &cam_cc_ife_0_cphy_rx_clk.clkr, + [CAM_CC_IFE_0_CSID_CLK] = &cam_cc_ife_0_csid_clk.clkr, + [CAM_CC_IFE_0_CSID_CLK_SRC] = &cam_cc_ife_0_csid_clk_src.clkr, + [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr, + [CAM_CC_IFE_1_AXI_CLK] = &cam_cc_ife_1_axi_clk.clkr, + [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr, + [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr, + [CAM_CC_IFE_1_CPHY_RX_CLK] = &cam_cc_ife_1_cphy_rx_clk.clkr, + [CAM_CC_IFE_1_CSID_CLK] = &cam_cc_ife_1_csid_clk.clkr, + [CAM_CC_IFE_1_CSID_CLK_SRC] = &cam_cc_ife_1_csid_clk_src.clkr, + [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_0_AHB_CLK] = &cam_cc_ipe_0_ahb_clk.clkr, + [CAM_CC_IPE_0_AREG_CLK] = &cam_cc_ipe_0_areg_clk.clkr, + [CAM_CC_IPE_0_AXI_CLK] = &cam_cc_ipe_0_axi_clk.clkr, + [CAM_CC_IPE_0_CLK] = &cam_cc_ipe_0_clk.clkr, + [CAM_CC_IPE_0_CLK_SRC] = &cam_cc_ipe_0_clk_src.clkr, + [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_LRME_CLK] = &cam_cc_lrme_clk.clkr, + [CAM_CC_LRME_CLK_SRC] = &cam_cc_lrme_clk_src.clkr, + [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr, + [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr, + [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr, + [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr, + [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr, + [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr, + [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr, + [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr, + [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr, + [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL2_OUT_AUX] = &cam_cc_pll2_out_aux.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_SOC_AHB_CLK] = &cam_cc_soc_ahb_clk.clkr, + [CAM_CC_SYS_TMR_CLK] = &cam_cc_sys_tmr_clk.clkr, +}; +static struct gdsc *cam_cc_sc7180_gdscs[] = { + [BPS_GDSC] = &bps_gdsc, + [IFE_0_GDSC] = &ife_0_gdsc, + [IFE_1_GDSC] = &ife_1_gdsc, + [IPE_0_GDSC] = &ipe_0_gdsc, + [TITAN_TOP_GDSC] = &titan_top_gdsc, +}; + +static const struct regmap_config cam_cc_sc7180_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xd028, + .fast_io = true, +}; + +static const struct qcom_cc_desc cam_cc_sc7180_desc = { + .config = &cam_cc_sc7180_regmap_config, + .clk_hws = cam_cc_sc7180_hws, + .num_clk_hws = ARRAY_SIZE(cam_cc_sc7180_hws), + .clks = cam_cc_sc7180_clocks, + .num_clks = ARRAY_SIZE(cam_cc_sc7180_clocks), + .gdscs = cam_cc_sc7180_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_sc7180_gdscs), +}; + +static const struct of_device_id cam_cc_sc7180_match_table[] = { + { .compatible = "qcom,sc7180-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_sc7180_match_table); + +static int cam_cc_sc7180_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + pm_runtime_enable(&pdev->dev); + ret = pm_clk_create(&pdev->dev); + if (ret < 0) + return ret; + + ret = pm_clk_add(&pdev->dev, "xo"); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to acquire XO clock\n"); + goto disable_pm_runtime; + } + + ret = pm_clk_add(&pdev->dev, "iface"); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to acquire iface clock\n"); + goto disable_pm_runtime; + } + + ret = pm_clk_runtime_resume(&pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "pm runtime resume failed\n"); + goto destroy_pm_clk; + } + + regmap = qcom_cc_map(pdev, &cam_cc_sc7180_desc); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + pm_clk_runtime_suspend(&pdev->dev); + goto destroy_pm_clk; + } + + clk_fabia_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config); + clk_fabia_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config); + clk_agera_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config); + clk_fabia_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config); + + ret = qcom_cc_really_probe(pdev, &cam_cc_sc7180_desc, regmap); + + pm_clk_runtime_suspend(&pdev->dev); + + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register CAM CC clocks\n"); + goto destroy_pm_clk; + } + + return 0; + +destroy_pm_clk: + pm_clk_destroy(&pdev->dev); + +disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static const struct dev_pm_ops cam_cc_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver cam_cc_sc7180_driver = { + .probe = cam_cc_sc7180_probe, + .driver = { + .name = "cam_cc-sc7180", + .of_match_table = cam_cc_sc7180_match_table, + .pm = &cam_cc_pm_ops, + }, +}; + +static int __init cam_cc_sc7180_init(void) +{ + return platform_driver_register(&cam_cc_sc7180_driver); +} +subsys_initcall(cam_cc_sc7180_init); + +static void __exit cam_cc_sc7180_exit(void) +{ + platform_driver_unregister(&cam_cc_sc7180_driver); +} +module_exit(cam_cc_sc7180_exit); + +MODULE_DESCRIPTION("QTI CAM_CC SC7180 Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 7635622b77b53985d816b7f7c1a04e718c9db814 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 19 Oct 2020 15:49:34 -0700 Subject: clk: qcom: lpasscc-sc7810: Use devm in probe Let's convert the lpass clock control driver to use devm. This is a few more lines of code, but it will be useful in a later patch which disentangles the two devices handled by this driver. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20201019154857.v5.1.I4567b5e7e17bbb15ef063d447cb83fd43746cb18@changeid Signed-off-by: Stephen Boyd --- drivers/clk/qcom/lpasscorecc-sc7180.c | 38 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c index 228d08f5d26f..2d15e33ec837 100644 --- a/drivers/clk/qcom/lpasscorecc-sc7180.c +++ b/drivers/clk/qcom/lpasscorecc-sc7180.c @@ -356,6 +356,16 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = { .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs), }; +static void lpass_pm_runtime_disable(void *data) +{ + pm_runtime_disable(data); +} + +static void lpass_pm_clk_destroy(void *data) +{ + pm_clk_destroy(data); +} + static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) { const struct qcom_cc_desc *desc; @@ -418,34 +428,28 @@ static int lpass_core_sc7180_probe(struct platform_device *pdev) int ret; pm_runtime_enable(&pdev->dev); + ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev); + if (ret) + return ret; + ret = pm_clk_create(&pdev->dev); if (ret) - goto disable_pm_runtime; + return ret; + ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_clk_destroy, &pdev->dev); + if (ret) + return ret; ret = pm_clk_add(&pdev->dev, "iface"); if (ret < 0) { dev_err(&pdev->dev, "failed to acquire iface clock\n"); - goto destroy_pm_clk; + return ret; } - ret = -EINVAL; clk_probe = of_device_get_match_data(&pdev->dev); if (!clk_probe) - goto destroy_pm_clk; - - ret = clk_probe(pdev); - if (ret) - goto destroy_pm_clk; - - return 0; - -destroy_pm_clk: - pm_clk_destroy(&pdev->dev); - -disable_pm_runtime: - pm_runtime_disable(&pdev->dev); + return -EINVAL; - return ret; + return clk_probe(pdev); } static const struct dev_pm_ops lpass_core_cc_pm_ops = { -- cgit v1.2.3-59-g8ed1b From 4ee9fe3e292bafc915872fce5eacd2c185d7711f Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 19 Oct 2020 15:49:35 -0700 Subject: clk: qcom: lpass-sc7180: Disentangle the two clock devices The sc7180 lpass clock driver manages two different devices. These two devices were tangled together, using one probe and a lookup to figure out the real probe. I think it's cleaner to really separate the probe for these two devices since they're really different things, just both managed by the same driver. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20201019154857.v5.2.I75c409497d4dea9daefa53ec5f93824081c4ecbe@changeid Reviewed-by: Taniya Das Signed-off-by: Stephen Boyd --- drivers/clk/qcom/lpasscorecc-sc7180.c | 103 +++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c index 2d15e33ec837..1a3925badd7c 100644 --- a/drivers/clk/qcom/lpasscorecc-sc7180.c +++ b/drivers/clk/qcom/lpasscorecc-sc7180.c @@ -366,12 +366,39 @@ static void lpass_pm_clk_destroy(void *data) pm_clk_destroy(data); } +static int lpass_create_pm_clks(struct platform_device *pdev) +{ + int ret; + + pm_runtime_enable(&pdev->dev); + ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev); + if (ret) + return ret; + + ret = pm_clk_create(&pdev->dev); + if (ret) + return ret; + ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_clk_destroy, &pdev->dev); + if (ret) + return ret; + + ret = pm_clk_add(&pdev->dev, "iface"); + if (ret < 0) + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + + return ret; +} + static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) { const struct qcom_cc_desc *desc; struct regmap *regmap; int ret; + ret = lpass_create_pm_clks(pdev); + if (ret) + return ret; + lpass_core_cc_sc7180_regmap_config.name = "lpass_audio_cc"; desc = &lpass_audio_hm_sc7180_desc; ret = qcom_cc_probe_by_index(pdev, 1, desc); @@ -402,6 +429,11 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) static int lpass_hm_core_probe(struct platform_device *pdev) { const struct qcom_cc_desc *desc; + int ret; + + ret = lpass_create_pm_clks(pdev); + if (ret) + return ret; lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core"; desc = &lpass_core_hm_sc7180_desc; @@ -409,55 +441,28 @@ static int lpass_hm_core_probe(struct platform_device *pdev) return qcom_cc_probe_by_index(pdev, 0, desc); } -static const struct of_device_id lpass_core_cc_sc7180_match_table[] = { +static const struct of_device_id lpass_hm_sc7180_match_table[] = { { .compatible = "qcom,sc7180-lpasshm", - .data = lpass_hm_core_probe, }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_hm_sc7180_match_table); + +static const struct of_device_id lpass_core_cc_sc7180_match_table[] = { { .compatible = "qcom,sc7180-lpasscorecc", - .data = lpass_core_cc_sc7180_probe, }, { } }; MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table); -static int lpass_core_sc7180_probe(struct platform_device *pdev) -{ - int (*clk_probe)(struct platform_device *p); - int ret; - - pm_runtime_enable(&pdev->dev); - ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev); - if (ret) - return ret; - - ret = pm_clk_create(&pdev->dev); - if (ret) - return ret; - ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_clk_destroy, &pdev->dev); - if (ret) - return ret; - - ret = pm_clk_add(&pdev->dev, "iface"); - if (ret < 0) { - dev_err(&pdev->dev, "failed to acquire iface clock\n"); - return ret; - } - - clk_probe = of_device_get_match_data(&pdev->dev); - if (!clk_probe) - return -EINVAL; - - return clk_probe(pdev); -} - static const struct dev_pm_ops lpass_core_cc_pm_ops = { SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) }; static struct platform_driver lpass_core_cc_sc7180_driver = { - .probe = lpass_core_sc7180_probe, + .probe = lpass_core_cc_sc7180_probe, .driver = { .name = "lpass_core_cc-sc7180", .of_match_table = lpass_core_cc_sc7180_match_table, @@ -465,17 +470,37 @@ static struct platform_driver lpass_core_cc_sc7180_driver = { }, }; -static int __init lpass_core_cc_sc7180_init(void) +static const struct dev_pm_ops lpass_hm_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpass_hm_sc7180_driver = { + .probe = lpass_hm_core_probe, + .driver = { + .name = "lpass_hm-sc7180", + .of_match_table = lpass_hm_sc7180_match_table, + .pm = &lpass_hm_pm_ops, + }, +}; + +static int __init lpass_sc7180_init(void) { - return platform_driver_register(&lpass_core_cc_sc7180_driver); + int ret; + + ret = platform_driver_register(&lpass_core_cc_sc7180_driver); + if (ret) + return ret; + + return platform_driver_register(&lpass_hm_sc7180_driver); } -subsys_initcall(lpass_core_cc_sc7180_init); +subsys_initcall(lpass_sc7180_init); -static void __exit lpass_core_cc_sc7180_exit(void) +static void __exit lpass_sc7180_exit(void) { + platform_driver_unregister(&lpass_hm_sc7180_driver); platform_driver_unregister(&lpass_core_cc_sc7180_driver); } -module_exit(lpass_core_cc_sc7180_exit); +module_exit(lpass_sc7180_exit); MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7180 Driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From a6dee2fe778b9f79f75bfc203945ace79172623e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 26 Oct 2020 12:02:18 +0000 Subject: dt-bindings: clock: Add support for LPASS Audio Clock Controller Audio Clock controller is a block inside LPASS which controls 2 Glitch free muxes to LPASS codec Macros. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20201026120221.18984-2-srinivas.kandagatla@linaro.org Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,audiocc-sm8250.yaml | 58 ++++++++++++++++++++++ .../dt-bindings/clock/qcom,sm8250-lpass-audiocc.h | 13 +++++ 2 files changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml create mode 100644 include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml new file mode 100644 index 000000000000..915d76206ad0 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,audiocc-sm8250.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Clock bindings for LPASS Audio Clock Controller on SM8250 SoCs + +maintainers: + - Srinivas Kandagatla + +description: | + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. + See include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h for the full list + of Audio Clock controller clock IDs. + +properties: + compatible: + const: qcom,sm8250-lpass-audiocc + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + items: + - description: LPASS Core voting clock + - description: Glitch Free Mux register clock + + clock-names: + items: + - const: core + - const: bus + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + clock-controller@3300000 { + #clock-cells = <1>; + compatible = "qcom,sm8250-lpass-audiocc"; + reg = <0x03300000 0x30000>; + clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "core", "bus"; + }; diff --git a/include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h b/include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h new file mode 100644 index 000000000000..a1aa6cb5d840 --- /dev/null +++ b/include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _DT_BINDINGS_CLK_LPASS_AUDIOCC_SM8250_H +#define _DT_BINDINGS_CLK_LPASS_AUDIOCC_SM8250_H + +/* From AudioCC */ +#define LPASS_CDC_WSA_NPL 0 +#define LPASS_CDC_WSA_MCLK 1 +#define LPASS_CDC_RX_MCLK 2 +#define LPASS_CDC_RX_NPL 3 +#define LPASS_CDC_RX_MCLK_MCLK2 4 + +#endif /* _DT_BINDINGS_CLK_LPASS_AUDIOCC_SM8250_H */ -- cgit v1.2.3-59-g8ed1b From 7dbe5a7a3f990d642a3166b5d161db429d9f7271 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 26 Oct 2020 12:02:19 +0000 Subject: dt-bindings: clock: Add support for LPASS Always ON Controller Always ON Clock controller is a block inside LPASS which controls 1 Glitch free muxes to LPASS codec Macros. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20201026120221.18984-3-srinivas.kandagatla@linaro.org Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,aoncc-sm8250.yaml | 58 ++++++++++++++++++++++ .../dt-bindings/clock/qcom,sm8250-lpass-aoncc.h | 11 ++++ 2 files changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml create mode 100644 include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml new file mode 100644 index 000000000000..c40a74b5d672 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,aoncc-sm8250.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Clock bindings for LPASS Always ON Clock Controller on SM8250 SoCs + +maintainers: + - Srinivas Kandagatla + +description: | + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. + See include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h for the full list + of Audio Clock controller clock IDs. + +properties: + compatible: + const: qcom,sm8250-lpass-aon + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + items: + - description: LPASS Core voting clock + - description: Glitch Free Mux register clock + + clock-names: + items: + - const: core + - const: bus + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + clock-controller@3800000 { + #clock-cells = <1>; + compatible = "qcom,sm8250-lpass-aon"; + reg = <0x03380000 0x40000>; + clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "core", "bus"; + }; diff --git a/include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h b/include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h new file mode 100644 index 000000000000..f5a1cfac8612 --- /dev/null +++ b/include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _DT_BINDINGS_CLK_LPASS_AONCC_SM8250_H +#define _DT_BINDINGS_CLK_LPASS_AONCC_SM8250_H + +/* from AOCC */ +#define LPASS_CDC_VA_MCLK 0 +#define LPASS_CDC_TX_NPL 1 +#define LPASS_CDC_TX_MCLK 2 + +#endif /* _DT_BINDINGS_CLK_LPASS_AONCC_SM8250_H */ -- cgit v1.2.3-59-g8ed1b From a2d8f507803ee858c718b2a8d54c00ac9c5c5f09 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 26 Oct 2020 12:02:20 +0000 Subject: clk: qcom: Add support to LPASS AUDIO_CC Glitch Free Mux clocks GFM Muxes in AUDIO_CC control clocks to LPASS WSA and RX Codec Macros. This patch adds support to these muxes. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20201026120221.18984-4-srinivas.kandagatla@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 6 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/lpass-gfm-sm8250.c | 257 ++++++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100644 drivers/clk/qcom/lpass-gfm-sm8250.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 886e8610b321..48c624a1eff1 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -511,4 +511,10 @@ config KRAITCC Support for the Krait CPU clocks on Qualcomm devices. Say Y if you want to support CPU frequency scaling. +config CLK_GFM_LPASS_SM8250 + tristate "SM8250 GFM LPASS Clocks" + help + Support for the Glitch Free Mux (GFM) Low power audio + subsystem (LPASS) clocks found on SM8250 SoCs. + endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index ee02fafbae27..57b6349a3ee8 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -19,6 +19,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o # Keep alphabetically sorted by config obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o +obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o diff --git a/drivers/clk/qcom/lpass-gfm-sm8250.c b/drivers/clk/qcom/lpass-gfm-sm8250.c new file mode 100644 index 000000000000..48a73dd97d0d --- /dev/null +++ b/drivers/clk/qcom/lpass-gfm-sm8250.c @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * LPASS Audio CC and Always ON CC Glitch Free Mux clock driver + * + * Copyright (c) 2020 Linaro Ltd. + * Author: Srinivas Kandagatla + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct lpass_gfm { + struct device *dev; + void __iomem *base; +}; + +struct clk_gfm { + unsigned int mux_reg; + unsigned int mux_mask; + struct clk_hw hw; + struct lpass_gfm *priv; + void __iomem *gfm_mux; +}; + +#define GFM_MASK BIT(1) +#define to_clk_gfm(_hw) container_of(_hw, struct clk_gfm, hw) + +static u8 clk_gfm_get_parent(struct clk_hw *hw) +{ + struct clk_gfm *clk = to_clk_gfm(hw); + + return readl(clk->gfm_mux) & GFM_MASK; +} + +static int clk_gfm_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_gfm *clk = to_clk_gfm(hw); + unsigned int val; + + val = readl(clk->gfm_mux); + + if (index) + val |= GFM_MASK; + else + val &= ~GFM_MASK; + + writel(val, clk->gfm_mux); + + return 0; +} + +static const struct clk_ops clk_gfm_ops = { + .get_parent = clk_gfm_get_parent, + .set_parent = clk_gfm_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; + +static struct clk_gfm lpass_gfm_wsa_mclk = { + .mux_reg = 0x220d8, + .mux_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "WSA_MCLK", + .ops = &clk_gfm_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .parent_data = (const struct clk_parent_data[]){ + { + .index = 0, + .fw_name = "LPASS_CLK_ID_TX_CORE_MCLK", + }, { + .index = 1, + .fw_name = "LPASS_CLK_ID_WSA_CORE_MCLK", + }, + }, + .num_parents = 2, + }, +}; + +static struct clk_gfm lpass_gfm_wsa_npl = { + .mux_reg = 0x220d8, + .mux_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "WSA_NPL", + .ops = &clk_gfm_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .parent_data = (const struct clk_parent_data[]){ + { + .index = 0, + .fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK", + }, { + .index = 1, + .fw_name = "LPASS_CLK_ID_WSA_CORE_NPL_MCLK", + }, + }, + .num_parents = 2, + }, +}; + +static struct clk_gfm lpass_gfm_rx_mclk_mclk2 = { + .mux_reg = 0x240d8, + .mux_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "RX_MCLK_MCLK2", + .ops = &clk_gfm_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .parent_data = (const struct clk_parent_data[]){ + { + .index = 0, + .fw_name = "LPASS_CLK_ID_TX_CORE_MCLK", + }, { + .index = 1, + .fw_name = "LPASS_CLK_ID_RX_CORE_MCLK", + }, + }, + .num_parents = 2, + }, +}; + +static struct clk_gfm lpass_gfm_rx_npl = { + .mux_reg = 0x240d8, + .mux_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "RX_NPL", + .ops = &clk_gfm_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .parent_data = (const struct clk_parent_data[]){ + { + .index = 0, + .fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK", + }, { + .index = 1, + .fw_name = "LPASS_CLK_ID_RX_CORE_NPL_MCLK", + }, + }, + .num_parents = 2, + }, +}; + +static struct clk_gfm *audiocc_gfm_clks[] = { + [LPASS_CDC_WSA_NPL] = &lpass_gfm_wsa_npl, + [LPASS_CDC_WSA_MCLK] = &lpass_gfm_wsa_mclk, + [LPASS_CDC_RX_NPL] = &lpass_gfm_rx_npl, + [LPASS_CDC_RX_MCLK_MCLK2] = &lpass_gfm_rx_mclk_mclk2, +}; + +static struct clk_hw_onecell_data audiocc_hw_onecell_data = { + .hws = { + [LPASS_CDC_WSA_NPL] = &lpass_gfm_wsa_npl.hw, + [LPASS_CDC_WSA_MCLK] = &lpass_gfm_wsa_mclk.hw, + [LPASS_CDC_RX_NPL] = &lpass_gfm_rx_npl.hw, + [LPASS_CDC_RX_MCLK_MCLK2] = &lpass_gfm_rx_mclk_mclk2.hw, + }, + .num = ARRAY_SIZE(audiocc_gfm_clks), +}; + +struct lpass_gfm_data { + struct clk_hw_onecell_data *onecell_data; + struct clk_gfm **gfm_clks; +}; + +static struct lpass_gfm_data audiocc_data = { + .onecell_data = &audiocc_hw_onecell_data, + .gfm_clks = audiocc_gfm_clks, +}; + +static int lpass_gfm_clk_driver_probe(struct platform_device *pdev) +{ + const struct lpass_gfm_data *data; + struct device *dev = &pdev->dev; + struct clk_gfm *gfm; + struct lpass_gfm *cc; + int err, i; + + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + + cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); + if (!cc) + return -ENOMEM; + + cc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(cc->base)) + return PTR_ERR(cc->base); + + pm_runtime_enable(dev); + err = pm_clk_create(dev); + if (err) + goto pm_clk_err; + + err = of_pm_clk_add_clks(dev); + if (err < 0) { + dev_dbg(dev, "Failed to get lpass core voting clocks\n"); + goto clk_reg_err; + } + + for (i = 0; i < data->onecell_data->num; i++) { + if (!data->gfm_clks[i]) + continue; + + gfm = data->gfm_clks[i]; + gfm->priv = cc; + gfm->gfm_mux = cc->base; + gfm->gfm_mux = gfm->gfm_mux + data->gfm_clks[i]->mux_reg; + + err = devm_clk_hw_register(dev, &data->gfm_clks[i]->hw); + if (err) + goto clk_reg_err; + + } + + err = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + data->onecell_data); + if (err) + goto clk_reg_err; + + return 0; + +clk_reg_err: + pm_clk_destroy(dev); +pm_clk_err: + pm_runtime_disable(dev); + return err; +} + +static const struct of_device_id lpass_gfm_clk_match_table[] = { + { + .compatible = "qcom,sm8250-lpass-audiocc", + .data = &audiocc_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_gfm_clk_match_table); + +static const struct dev_pm_ops lpass_gfm_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpass_gfm_clk_driver = { + .probe = lpass_gfm_clk_driver_probe, + .driver = { + .name = "lpass-gfm-clk", + .of_match_table = lpass_gfm_clk_match_table, + .pm = &lpass_gfm_pm_ops, + }, +}; +module_platform_driver(lpass_gfm_clk_driver); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 794aa56a78052d195641b1ce43e5538574bedf41 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 26 Oct 2020 12:02:21 +0000 Subject: clk: qcom: Add support to LPASS AON_CC Glitch Free Mux clocks LPASS Always ON Clock controller has one GFM mux to control VA and TX clocks to codec macro on LPASS. This patch adds support to this mux. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20201026120221.18984-5-srinivas.kandagatla@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/lpass-gfm-sm8250.c | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/clk/qcom/lpass-gfm-sm8250.c b/drivers/clk/qcom/lpass-gfm-sm8250.c index 48a73dd97d0d..d366c7c2abc7 100644 --- a/drivers/clk/qcom/lpass-gfm-sm8250.c +++ b/drivers/clk/qcom/lpass-gfm-sm8250.c @@ -18,6 +18,7 @@ #include #include #include +#include struct lpass_gfm { struct device *dev; @@ -65,6 +66,46 @@ static const struct clk_ops clk_gfm_ops = { .determine_rate = __clk_mux_determine_rate, }; +static struct clk_gfm lpass_gfm_va_mclk = { + .mux_reg = 0x20000, + .mux_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "VA_MCLK", + .ops = &clk_gfm_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .num_parents = 2, + .parent_data = (const struct clk_parent_data[]){ + { + .index = 0, + .fw_name = "LPASS_CLK_ID_TX_CORE_MCLK", + }, { + .index = 1, + .fw_name = "LPASS_CLK_ID_VA_CORE_MCLK", + }, + }, + }, +}; + +static struct clk_gfm lpass_gfm_tx_npl = { + .mux_reg = 0x20000, + .mux_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "TX_NPL", + .ops = &clk_gfm_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + .parent_data = (const struct clk_parent_data[]){ + { + .index = 0, + .fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK", + }, { + .index = 1, + .fw_name = "LPASS_CLK_ID_VA_CORE_2X_MCLK", + }, + }, + .num_parents = 2, + }, +}; + static struct clk_gfm lpass_gfm_wsa_mclk = { .mux_reg = 0x220d8, .mux_mask = BIT(0), @@ -145,6 +186,19 @@ static struct clk_gfm lpass_gfm_rx_npl = { }, }; +static struct clk_gfm *aoncc_gfm_clks[] = { + [LPASS_CDC_VA_MCLK] = &lpass_gfm_va_mclk, + [LPASS_CDC_TX_NPL] = &lpass_gfm_tx_npl, +}; + +static struct clk_hw_onecell_data aoncc_hw_onecell_data = { + .hws = { + [LPASS_CDC_VA_MCLK] = &lpass_gfm_va_mclk.hw, + [LPASS_CDC_TX_NPL] = &lpass_gfm_tx_npl.hw, + }, + .num = ARRAY_SIZE(aoncc_gfm_clks), +}; + static struct clk_gfm *audiocc_gfm_clks[] = { [LPASS_CDC_WSA_NPL] = &lpass_gfm_wsa_npl, [LPASS_CDC_WSA_MCLK] = &lpass_gfm_wsa_mclk, @@ -172,6 +226,11 @@ static struct lpass_gfm_data audiocc_data = { .gfm_clks = audiocc_gfm_clks, }; +static struct lpass_gfm_data aoncc_data = { + .onecell_data = &aoncc_hw_onecell_data, + .gfm_clks = aoncc_gfm_clks, +}; + static int lpass_gfm_clk_driver_probe(struct platform_device *pdev) { const struct lpass_gfm_data *data; @@ -233,6 +292,10 @@ pm_clk_err: } static const struct of_device_id lpass_gfm_clk_match_table[] = { + { + .compatible = "qcom,sm8250-lpass-aoncc", + .data = &aoncc_data, + }, { .compatible = "qcom,sm8250-lpass-audiocc", .data = &audiocc_data, -- cgit v1.2.3-59-g8ed1b From e4accab4e0b069bd4ddc1ac769a77b989bb9ed1c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 13 Nov 2020 13:14:19 +0300 Subject: clk: qcom: lpass-sc7180: Clean up on error in lpass_sc7180_init() Clean up the first driver if the second driver can't be registered. Fixes: 4ee9fe3e292b ("clk: qcom: lpass-sc7180: Disentangle the two clock devices") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20201113101419.GC168908@mwanda Reviewed-by: Douglas Anderson Signed-off-by: Stephen Boyd --- drivers/clk/qcom/lpasscorecc-sc7180.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c index 1a3925badd7c..9081649f476f 100644 --- a/drivers/clk/qcom/lpasscorecc-sc7180.c +++ b/drivers/clk/qcom/lpasscorecc-sc7180.c @@ -491,7 +491,13 @@ static int __init lpass_sc7180_init(void) if (ret) return ret; - return platform_driver_register(&lpass_hm_sc7180_driver); + ret = platform_driver_register(&lpass_hm_sc7180_driver); + if (ret) { + platform_driver_unregister(&lpass_core_cc_sc7180_driver); + return ret; + } + + return 0; } subsys_initcall(lpass_sc7180_init); -- cgit v1.2.3-59-g8ed1b From 8d4025943e13010d753935e37ad085fca4906e6c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 14 Nov 2020 09:44:08 -0800 Subject: clk: qcom: camcc-sc7180: Use runtime PM ops instead of clk ones Let's call pm_runtime_get() here instead of calling the PM clk APIs directly. This avoids a compilation problem on CONFIG_PM=n where the pm_clk_runtime_{resume,suspend}() functions don't exist and covers the intent, i.e. enable the clks for this device so we can program PLL settings. Reported-by: Randy Dunlap Reported-by: Geert Uytterhoeven Cc: Nathan Chancellor Cc: Stephen Rothwell Cc: Taniya Das Cc: "Rafael J. Wysocki" Acked-by: Randy Dunlap # build-tested Fixes: 15d09e830bbc ("clk: qcom: camcc: Add camera clock controller driver for SC7180") Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20201114174408.579047-1-sboyd@kernel.org --- drivers/clk/qcom/camcc-sc7180.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c index f51bf5b6decc..dbac5651ab85 100644 --- a/drivers/clk/qcom/camcc-sc7180.c +++ b/drivers/clk/qcom/camcc-sc7180.c @@ -1669,16 +1669,14 @@ static int cam_cc_sc7180_probe(struct platform_device *pdev) goto disable_pm_runtime; } - ret = pm_clk_runtime_resume(&pdev->dev); - if (ret < 0) { - dev_err(&pdev->dev, "pm runtime resume failed\n"); + ret = pm_runtime_get(&pdev->dev); + if (ret) goto destroy_pm_clk; - } regmap = qcom_cc_map(pdev, &cam_cc_sc7180_desc); if (IS_ERR(regmap)) { ret = PTR_ERR(regmap); - pm_clk_runtime_suspend(&pdev->dev); + pm_runtime_put(&pdev->dev); goto destroy_pm_clk; } @@ -1688,9 +1686,7 @@ static int cam_cc_sc7180_probe(struct platform_device *pdev) clk_fabia_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config); ret = qcom_cc_really_probe(pdev, &cam_cc_sc7180_desc, regmap); - - pm_clk_runtime_suspend(&pdev->dev); - + pm_runtime_put(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "Failed to register CAM CC clocks\n"); goto destroy_pm_clk; -- cgit v1.2.3-59-g8ed1b From 6a17849703581f11b499da8e1d6a2941b9e738dd Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Fri, 6 Nov 2020 10:48:20 +0100 Subject: clk: remove unneeded dead-store initialization make clang-analyzer on x86_64 defconfig caught my attention with: drivers/clk/clk.c:423:19: warning: Value stored to 'parent' during its initialization is never read [clang-analyzer-deadcode.DeadStores] struct clk_core *parent = ERR_PTR(-ENOENT); ^ Commit fc0c209c147f ("clk: Allow parents to be specified without string names") introduced clk_core_fill_parent_index() with this unneeded dead-store initialization. So, simply remove this unneeded dead-store initialization to make clang-analyzer happy. As compilers will detect this unneeded assignment and optimize this anyway, the resulting object code is identical before and after this change. No functional change. No change to object code. Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20201106094820.30167-1-lukas.bulwahn@gmail.com Reviewed-by: Nathan Chancellor Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f83dac54ed85..ba35bf35bcd3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -420,7 +420,7 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index) static void clk_core_fill_parent_index(struct clk_core *core, u8 index) { struct clk_parent_map *entry = &core->parents[index]; - struct clk_core *parent = ERR_PTR(-ENOENT); + struct clk_core *parent; if (entry->hw) { parent = entry->hw->core; -- cgit v1.2.3-59-g8ed1b From e5a4b9b99e5b70a41578e78d30349315772add1b Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Oct 2020 18:21:45 +0200 Subject: clk: avoid devm_clk_release name clash In clk-devres.c, devm_clk_release() is used to call clk_put() memory managed clock. In clk.c the same name, in a different scope is used to call clk_unregister(). As it stands, it is not really a problem but it does not readability, especially if we need to call clk_put() on managed clock in clk.c Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20201021162147.563655-2-jbrunet@baylibre.com Tested-by: Kevin Hilman Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f83dac54ed85..f70dc0ef1cdd 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4068,12 +4068,12 @@ void clk_hw_unregister(struct clk_hw *hw) } EXPORT_SYMBOL_GPL(clk_hw_unregister); -static void devm_clk_release(struct device *dev, void *res) +static void devm_clk_unregister_cb(struct device *dev, void *res) { clk_unregister(*(struct clk **)res); } -static void devm_clk_hw_release(struct device *dev, void *res) +static void devm_clk_hw_unregister_cb(struct device *dev, void *res) { clk_hw_unregister(*(struct clk_hw **)res); } @@ -4093,7 +4093,7 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) struct clk *clk; struct clk **clkp; - clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL); + clkp = devres_alloc(devm_clk_unregister_cb, sizeof(*clkp), GFP_KERNEL); if (!clkp) return ERR_PTR(-ENOMEM); @@ -4123,7 +4123,7 @@ int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) struct clk_hw **hwp; int ret; - hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); + hwp = devres_alloc(devm_clk_hw_unregister_cb, sizeof(*hwp), GFP_KERNEL); if (!hwp) return -ENOMEM; @@ -4167,7 +4167,7 @@ static int devm_clk_hw_match(struct device *dev, void *res, void *data) */ void devm_clk_unregister(struct device *dev, struct clk *clk) { - WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk)); + WARN_ON(devres_release(dev, devm_clk_unregister_cb, devm_clk_match, clk)); } EXPORT_SYMBOL_GPL(devm_clk_unregister); @@ -4182,7 +4182,7 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister); */ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) { - WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, + WARN_ON(devres_release(dev, devm_clk_hw_unregister_cb, devm_clk_hw_match, hw)); } EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); -- cgit v1.2.3-59-g8ed1b From 30d6f8c15d2cd877c1f3d47d8a1064649ebe58e2 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Oct 2020 18:21:46 +0200 Subject: clk: add api to get clk consumer from clk_hw clk_register() is deprecated. Using 'clk' member of struct clk_hw is discouraged. With this constraint, it is difficult for driver to register clocks using the clk_hw API and then use the clock with the consumer API This adds a simple helper, clk_hw_get_clk(), to get a struct clk from a struct clk_hw. Like other clk_get() variant, each call to this helper must be balanced with a call to clk_put(). To make life easier on the consumers, a memory managed version is provided as well. Cc: Martin Blumenstingl Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20201021162147.563655-3-jbrunet@baylibre.com Tested-by: Kevin Hilman [sboyd@kernel.org: Fix kernel-doc] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 5 ++++ 2 files changed, 66 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f70dc0ef1cdd..48931f442de8 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3667,6 +3667,24 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, return clk; } +/** + * clk_hw_get_clk - get clk consumer given an clk_hw + * @hw: clk_hw associated with the clk being consumed + * @con_id: connection ID string on device + * + * Returns: new clk consumer + * This is the function to be used by providers which need + * to get a consumer clk and act on the clock element + * Calls to this function must be balanced with calls clk_put() + */ +struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id) +{ + struct device *dev = hw->core->dev; + + return clk_hw_create_clk(dev, hw, dev_name(dev), con_id); +} +EXPORT_SYMBOL(clk_hw_get_clk); + static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist) { const char *dst; @@ -4187,6 +4205,49 @@ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); +static void devm_clk_release(struct device *dev, void *res) +{ + clk_put(*(struct clk **)res); +} + +/** + * devm_clk_hw_get_clk - resource managed clk_hw_get_clk() + * @dev: device that is registering this clock + * @hw: clk_hw associated with the clk being consumed + * @con_id: connection ID string on device + * + * Managed clk_hw_get_clk(). Clocks got with this function are + * automatically clk_put() on driver detach. See clk_put() + * for more information. + */ +struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw, + const char *con_id) +{ + struct clk *clk; + struct clk **clkp; + + /* This should not happen because it would mean we have drivers + * passing around clk_hw pointers instead of having the caller use + * proper clk_get() style APIs + */ + WARN_ON_ONCE(dev != hw->core->dev); + + clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL); + if (!clkp) + return ERR_PTR(-ENOMEM); + + clk = clk_hw_get_clk(hw, con_id); + if (!IS_ERR(clk)) { + *clkp = clk; + devres_add(dev, clkp); + } else { + devres_free(clkp); + } + + return clk; +} +EXPORT_SYMBOL_GPL(devm_clk_hw_get_clk); + /* * clkdev helpers */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 03a5de5f99f4..86b707520ec0 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1088,6 +1088,11 @@ static inline struct clk_hw *__clk_get_hw(struct clk *clk) return (struct clk_hw *)clk; } #endif + +struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id); +struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw, + const char *con_id); + unsigned int clk_hw_get_num_parents(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, -- cgit v1.2.3-59-g8ed1b From 8e677e7f0aa3b01c501a9a48a04a34173380ccfd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Oct 2020 18:21:47 +0200 Subject: clk: meson: g12: drop use of __clk_lookup() g12 clock controller used __clk_lookup() to get struct clk from a struct clk_hw. This type of hack is no longer required as CCF now provides the necessary functions to get this. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20201021162147.563655-4-jbrunet@baylibre.com Tested-by: Kevin Hilman Signed-off-by: Stephen Boyd --- drivers/clk/meson/g12a.c | 68 +++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index b814d44917a5..235dcf72e34a 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -5156,10 +5156,11 @@ static const struct reg_sequence g12a_init_regs[] = { { .reg = HHI_MPLL_CNTL0, .def = 0x00000543 }, }; -static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, +#define DVFS_CON_ID "dvfs" + +static int meson_g12a_dvfs_setup_common(struct device *dev, struct clk_hw **hws) { - const char *notifier_clk_name; struct clk *notifier_clk; struct clk_hw *xtal; int ret; @@ -5168,21 +5169,21 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, /* Setup clock notifier for cpu_clk_postmux0 */ g12a_cpu_clk_postmux0_nb_data.xtal = xtal; - notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_postmux0.hw, + DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_postmux0_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk_postmux0 notifier\n"); + dev_err(dev, "failed to register the cpu_clk_postmux0 notifier\n"); return ret; } /* Setup clock notifier for cpu_clk_dyn mux */ - notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_dyn.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_dyn.hw, + DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk_dyn notifier\n"); + dev_err(dev, "failed to register the cpu_clk_dyn notifier\n"); return ret; } @@ -5192,33 +5193,33 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, static int meson_g12b_dvfs_setup(struct platform_device *pdev) { struct clk_hw **hws = g12b_hw_onecell_data.hws; - const char *notifier_clk_name; + struct device *dev = &pdev->dev; struct clk *notifier_clk; struct clk_hw *xtal; int ret; - ret = meson_g12a_dvfs_setup_common(pdev, hws); + ret = meson_g12a_dvfs_setup_common(dev, hws); if (ret) return ret; xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0); /* Setup clock notifier for cpu_clk mux */ - notifier_clk_name = clk_hw_get_name(&g12b_cpu_clk.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpu_clk.hw, + DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n"); + dev_err(dev, "failed to register the cpu_clk notifier\n"); return ret; } /* Setup clock notifier for sys1_pll */ - notifier_clk_name = clk_hw_get_name(&g12b_sys1_pll.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_sys1_pll.hw, + DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12b_cpu_clk_sys1_pll_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the sys1_pll notifier\n"); + dev_err(dev, "failed to register the sys1_pll notifier\n"); return ret; } @@ -5226,40 +5227,37 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for cpub_clk_postmux0 */ g12b_cpub_clk_postmux0_nb_data.xtal = xtal; - notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_postmux0.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_postmux0.hw, + DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12b_cpub_clk_postmux0_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpub_clk_postmux0 notifier\n"); + dev_err(dev, "failed to register the cpub_clk_postmux0 notifier\n"); return ret; } /* Setup clock notifier for cpub_clk_dyn mux */ - notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_dyn.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_dyn.hw, "dvfs"); ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpub_clk_dyn notifier\n"); + dev_err(dev, "failed to register the cpub_clk_dyn notifier\n"); return ret; } /* Setup clock notifier for cpub_clk mux */ - notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk.hw, DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpub_clk notifier\n"); + dev_err(dev, "failed to register the cpub_clk notifier\n"); return ret; } /* Setup clock notifier for sys_pll */ - notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12b_cpub_clk_sys_pll_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the sys_pll notifier\n"); + dev_err(dev, "failed to register the sys_pll notifier\n"); return ret; } @@ -5269,29 +5267,27 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) static int meson_g12a_dvfs_setup(struct platform_device *pdev) { struct clk_hw **hws = g12a_hw_onecell_data.hws; - const char *notifier_clk_name; + struct device *dev = &pdev->dev; struct clk *notifier_clk; int ret; - ret = meson_g12a_dvfs_setup_common(pdev, hws); + ret = meson_g12a_dvfs_setup_common(dev, hws); if (ret) return ret; /* Setup clock notifier for cpu_clk mux */ - notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk.hw, DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n"); + dev_err(dev, "failed to register the cpu_clk notifier\n"); return ret; } /* Setup clock notifier for sys_pll */ - notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw); - notifier_clk = __clk_lookup(notifier_clk_name); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID); ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the sys_pll notifier\n"); + dev_err(dev, "failed to register the sys_pll notifier\n"); return ret; } -- cgit v1.2.3-59-g8ed1b From 6d30d50d037dfa092f9d5d1fffa348ab4abb7163 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Oct 2020 18:38:46 +0200 Subject: clk: add devm variant of clk_notifier_register Add a memory managed variant of clk_notifier_register() to make life easier on clock consumers using notifiers Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20201021163847.595189-2-jbrunet@baylibre.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/clk.h | 10 ++++++++++ 2 files changed, 46 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 48931f442de8..6cf59e3c31b4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4395,6 +4395,42 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(clk_notifier_unregister); +struct clk_notifier_devres { + struct clk *clk; + struct notifier_block *nb; +}; + +static void devm_clk_notifier_release(struct device *dev, void *res) +{ + struct clk_notifier_devres *devres = res; + + clk_notifier_unregister(devres->clk, devres->nb); +} + +int devm_clk_notifier_register(struct device *dev, struct clk *clk, + struct notifier_block *nb) +{ + struct clk_notifier_devres *devres; + int ret; + + devres = devres_alloc(devm_clk_notifier_release, + sizeof(*devres), GFP_KERNEL); + + if (!devres) + return -ENOMEM; + + ret = clk_notifier_register(clk, nb); + if (!ret) { + devres->clk = clk; + devres->nb = nb; + } else { + devres_free(devres); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_clk_notifier_register); + #ifdef CONFIG_OF static void clk_core_reparent_orphans(void) { diff --git a/include/linux/clk.h b/include/linux/clk.h index 7fd6a1febcf4..f53afdf8198b 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -109,6 +109,16 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb); */ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb); +/** + * devm_clk_notifier_register - register a managed rate-change notifier callback + * @dev: device for clock "consumer" + * @clk: clock whose rate we are interested in + * @nb: notifier block with callback function pointer + * + * Returns 0 on success, -EERROR otherwise + */ +int devm_clk_notifier_register(struct device *dev, struct clk *clk, struct notifier_block *nb); + /** * clk_get_accuracy - obtain the clock accuracy in ppb (parts per billion) * for a clock source. -- cgit v1.2.3-59-g8ed1b From e6fb7aee486c7fbd4d94f4894feaa6f0424c1740 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Oct 2020 18:38:47 +0200 Subject: clk: meson: g12: use devm variant to register notifiers Until now, nothing was done to unregister the dvfs clock notifiers of the Amlogic g12 SoC family. This is not great but this driver was not really expected to be unloaded. With the ongoing effort to build everything as module for this platform, this needs to be cleanly handled. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20201021163847.595189-3-jbrunet@baylibre.com Signed-off-by: Stephen Boyd --- drivers/clk/meson/g12a.c | 34 ++++++++++++++++++++-------------- include/linux/clk.h | 10 +++++++++- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 235dcf72e34a..108e4491b1e2 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -5171,8 +5171,8 @@ static int meson_g12a_dvfs_setup_common(struct device *dev, g12a_cpu_clk_postmux0_nb_data.xtal = xtal; notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_postmux0.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, - &g12a_cpu_clk_postmux0_nb_data.nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_postmux0_nb_data.nb); if (ret) { dev_err(dev, "failed to register the cpu_clk_postmux0 notifier\n"); return ret; @@ -5181,7 +5181,8 @@ static int meson_g12a_dvfs_setup_common(struct device *dev, /* Setup clock notifier for cpu_clk_dyn mux */ notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_dyn.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { dev_err(dev, "failed to register the cpu_clk_dyn notifier\n"); return ret; @@ -5207,7 +5208,8 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for cpu_clk mux */ notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpu_clk.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { dev_err(dev, "failed to register the cpu_clk notifier\n"); return ret; @@ -5216,8 +5218,8 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for sys1_pll */ notifier_clk = devm_clk_hw_get_clk(dev, &g12b_sys1_pll.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, - &g12b_cpu_clk_sys1_pll_nb_data.nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12b_cpu_clk_sys1_pll_nb_data.nb); if (ret) { dev_err(dev, "failed to register the sys1_pll notifier\n"); return ret; @@ -5229,8 +5231,8 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) g12b_cpub_clk_postmux0_nb_data.xtal = xtal; notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_postmux0.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, - &g12b_cpub_clk_postmux0_nb_data.nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12b_cpub_clk_postmux0_nb_data.nb); if (ret) { dev_err(dev, "failed to register the cpub_clk_postmux0 notifier\n"); return ret; @@ -5238,7 +5240,8 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for cpub_clk_dyn mux */ notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_dyn.hw, "dvfs"); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { dev_err(dev, "failed to register the cpub_clk_dyn notifier\n"); return ret; @@ -5246,7 +5249,8 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for cpub_clk mux */ notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { dev_err(dev, "failed to register the cpub_clk notifier\n"); return ret; @@ -5254,8 +5258,8 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for sys_pll */ notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, - &g12b_cpub_clk_sys_pll_nb_data.nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12b_cpub_clk_sys_pll_nb_data.nb); if (ret) { dev_err(dev, "failed to register the sys_pll notifier\n"); return ret; @@ -5277,7 +5281,8 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for cpu_clk mux */ notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { dev_err(dev, "failed to register the cpu_clk notifier\n"); return ret; @@ -5285,7 +5290,8 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for sys_pll */ notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID); - ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_sys_pll_nb_data.nb); if (ret) { dev_err(dev, "failed to register the sys_pll notifier\n"); return ret; diff --git a/include/linux/clk.h b/include/linux/clk.h index f53afdf8198b..4ac766dc3daf 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -117,7 +117,8 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb); * * Returns 0 on success, -EERROR otherwise */ -int devm_clk_notifier_register(struct device *dev, struct clk *clk, struct notifier_block *nb); +int devm_clk_notifier_register(struct device *dev, struct clk *clk, + struct notifier_block *nb); /** * clk_get_accuracy - obtain the clock accuracy in ppb (parts per billion) @@ -196,6 +197,13 @@ static inline int clk_notifier_unregister(struct clk *clk, return -ENOTSUPP; } +static inline int devm_clk_notifier_register(struct device *dev, + struct clk *clk, + struct notifier_block *nb) +{ + return -ENOTSUPP; +} + static inline long clk_get_accuracy(struct clk *clk) { return -ENOTSUPP; -- cgit v1.2.3-59-g8ed1b From 3105c7c91feb176f8b918ebe13abd520f7651834 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 23 Oct 2020 16:19:25 +0300 Subject: clk: qcom: dispcc-sm8250: handle MMCX power domain On SM8250 MMCX power domain is required to access MMDS_GDSC registers. This power domain is expressed as mmcx-supply regulator property. Use this regulator as MDSS_GDSC supply. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201023131925.334864-6-dmitry.baryshkov@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/dispcc-sm8250.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c index 07a98d3f882d..588575e1169d 100644 --- a/drivers/clk/qcom/dispcc-sm8250.c +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -963,6 +963,7 @@ static struct gdsc mdss_gdsc = { }, .pwrsts = PWRSTS_OFF_ON, .flags = HW_CTRL, + .supply = "mmcx", }; static struct clk_regmap *disp_cc_sm8250_clocks[] = { -- cgit v1.2.3-59-g8ed1b From e44cdff05145b84293e3f424daa17e4f3ce0109c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 19 Nov 2020 17:45:09 +0100 Subject: clk: samsung: Allow compile testing of Exynos, S3C64xx and S5Pv210 So far all Exynos, S3C64xx and S5Pv210 clock units were selected by respective SOC/ARCH Kconfig option. On a kernel built for selected SoCs, this allowed to build only limited set of matching clock drivers. However compile testing was not possible in such case as Makefile object depends on SOC/ARCH option. Add separate Kconfig options for each of them to be able to compile test. Link: https://lore.kernel.org/r/20201119164509.754851-1-krzk@kernel.org Signed-off-by: Krzysztof Kozlowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/Kconfig | 67 ++++++++++++++++++++++++++++++++++++++++++-- drivers/clk/samsung/Makefile | 22 +++++++-------- include/linux/clk/samsung.h | 4 +-- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index 57d4b3f20417..9323fcfac6cc 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -2,10 +2,73 @@ # Recent Exynos platforms should just select COMMON_CLK_SAMSUNG: config COMMON_CLK_SAMSUNG bool "Samsung Exynos clock controller support" if COMPILE_TEST - # Clocks on ARM64 SoCs (e.g. Exynos5433, Exynos7) are chosen by - # EXYNOS_ARM64_COMMON_CLK to avoid building them on ARMv7: + select S3C64XX_COMMON_CLK if ARM && ARCH_S3C64XX + select S5PV210_COMMON_CLK if ARM && ARCH_S5PV210 + select EXYNOS_3250_COMMON_CLK if ARM && SOC_EXYNOS3250 + select EXYNOS_4_COMMON_CLK if ARM && ARCH_EXYNOS4 + select EXYNOS_5250_COMMON_CLK if ARM && SOC_EXYNOS5250 + select EXYNOS_5260_COMMON_CLK if ARM && SOC_EXYNOS5260 + select EXYNOS_5410_COMMON_CLK if ARM && SOC_EXYNOS5410 + select EXYNOS_5420_COMMON_CLK if ARM && SOC_EXYNOS5420 select EXYNOS_ARM64_COMMON_CLK if ARM64 && ARCH_EXYNOS +config S3C64XX_COMMON_CLK + bool "Samsung S3C64xx clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung S3C64xx SoCs. + Choose Y here only if you build for this SoC. + +config S5PV210_COMMON_CLK + bool "Samsung S5Pv210 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung S5Pv210 SoCs. + Choose Y here only if you build for this SoC. + +config EXYNOS_3250_COMMON_CLK + bool "Samsung Exynos3250 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos3250 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_4_COMMON_CLK + bool "Samsung Exynos4 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos4212 and Exynos4412 SoCs. Choose Y here only if you build for + this SoC. + +config EXYNOS_5250_COMMON_CLK + bool "Samsung Exynos5250 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5250 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_5260_COMMON_CLK + bool "Samsung Exynos5260 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5260 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_5410_COMMON_CLK + bool "Samsung Exynos5410 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5410 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_5420_COMMON_CLK + bool "Samsung Exynos5420 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5420 SoCs. Choose Y here only if you build for this SoC. + config EXYNOS_ARM64_COMMON_CLK bool "Samsung Exynos ARMv8-family clock controller support" if COMPILE_TEST depends on COMMON_CLK_SAMSUNG diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 1a4e6b787978..bb1433f11c88 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -4,15 +4,15 @@ # obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o -obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o -obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o -obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o -obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o -obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5-subcmu.o -obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o -obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o -obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o -obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o +obj-$(CONFIG_EXYNOS_3250_COMMON_CLK) += clk-exynos3250.o +obj-$(CONFIG_EXYNOS_4_COMMON_CLK) += clk-exynos4.o +obj-$(CONFIG_EXYNOS_4_COMMON_CLK) += clk-exynos4412-isp.o +obj-$(CONFIG_EXYNOS_5250_COMMON_CLK) += clk-exynos5250.o +obj-$(CONFIG_EXYNOS_5250_COMMON_CLK) += clk-exynos5-subcmu.o +obj-$(CONFIG_EXYNOS_5260_COMMON_CLK) += clk-exynos5260.o +obj-$(CONFIG_EXYNOS_5410_COMMON_CLK) += clk-exynos5410.o +obj-$(CONFIG_EXYNOS_5420_COMMON_CLK) += clk-exynos5420.o +obj-$(CONFIG_EXYNOS_5420_COMMON_CLK) += clk-exynos5-subcmu.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o @@ -21,5 +21,5 @@ obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o -obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o -obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o +obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o +obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o diff --git a/include/linux/clk/samsung.h b/include/linux/clk/samsung.h index 79097e365f7f..38b774001712 100644 --- a/include/linux/clk/samsung.h +++ b/include/linux/clk/samsung.h @@ -10,7 +10,7 @@ struct device_node; -#ifdef CONFIG_ARCH_S3C64XX +#ifdef CONFIG_S3C64XX_COMMON_CLK void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, unsigned long xusbxti_f, bool s3c6400, void __iomem *base); @@ -19,7 +19,7 @@ static inline void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, unsigned long xusbxti_f, bool s3c6400, void __iomem *base) { } -#endif /* CONFIG_ARCH_S3C64XX */ +#endif /* CONFIG_S3C64XX_COMMON_CLK */ #ifdef CONFIG_S3C2410_COMMON_CLK void s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, -- cgit v1.2.3-59-g8ed1b From 44a9e78f9242872c889f176782777fa2ed535650 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 20 Nov 2020 16:57:31 +0100 Subject: clk: samsung: Prevent potential endless loop in the PLL ops The PLL status polling loops in the set_rate callbacks of some PLLs have no timeout detection and may become endless loops when something goes wrong with the PLL. For some PLLs there is already the ktime API based timeout detection, but it will not work in all conditions when .set_rate gets called. In particular, before the clocksource is initialized or when the timekeeping is suspended. This patch adds a common helper with the PLL status bit polling and timeout detection. For conditions where the timekeeping API should not be used a simple readl_relaxed/cpu_relax() busy loop is added with the iterations limit derived from measurements of readl_relaxed() execution time for various PLL types and Exynos SoCs variants. Actual PLL lock time depends on the P divider value, the VCO frequency and a constant PLL type specific LOCK_FACTOR and can be calculated as lock_time = Pdiv * LOCK_FACTOR / VCO_freq For the ktime API use cases a common timeout value of 20 ms is applied for all the PLLs with an assumption that maximum possible value of Pdiv is 64, maximum possible LOCK_FACTOR value is 3000 and minimum VCO frequency is 24 MHz. Link: https://lore.kernel.org/r/20201120155731.26898-1-s.nawrocki@samsung.com Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-pll.c | 147 ++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 76 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index ac70ad785d8e..5873a9354b50 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -8,14 +8,17 @@ #include #include +#include #include #include +#include #include #include #include "clk.h" #include "clk-pll.h" -#define PLL_TIMEOUT_MS 10 +#define PLL_TIMEOUT_US 20000U +#define PLL_TIMEOUT_LOOPS 1000000U struct samsung_clk_pll { struct clk_hw hw; @@ -63,6 +66,53 @@ static long samsung_pll_round_rate(struct clk_hw *hw, return rate_table[i - 1].rate; } +static bool pll_early_timeout = true; + +static int __init samsung_pll_disable_early_timeout(void) +{ + pll_early_timeout = false; + return 0; +} +arch_initcall(samsung_pll_disable_early_timeout); + +/* Wait until the PLL is locked */ +static int samsung_pll_lock_wait(struct samsung_clk_pll *pll, + unsigned int reg_mask) +{ + int i, ret; + u32 val; + + /* + * This function might be called when the timekeeping API can't be used + * to detect timeouts. One situation is when the clocksource is not yet + * initialized, another when the timekeeping is suspended. udelay() also + * cannot be used when the clocksource is not running on arm64, since + * the current timer is used as cycle counter. So a simple busy loop + * is used here in that special cases. The limit of iterations has been + * derived from experimental measurements of various PLLs on multiple + * Exynos SoC variants. Single register read time was usually in range + * 0.4...1.5 us, never less than 0.4 us. + */ + if (pll_early_timeout || timekeeping_suspended) { + i = PLL_TIMEOUT_LOOPS; + while (i-- > 0) { + if (readl_relaxed(pll->con_reg) & reg_mask) + return 0; + + cpu_relax(); + } + ret = -ETIMEDOUT; + } else { + ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val, + val & reg_mask, 0, PLL_TIMEOUT_US); + } + + if (ret < 0) + pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw)); + + return ret; +} + static int samsung_pll3xxx_enable(struct clk_hw *hw) { struct samsung_clk_pll *pll = to_clk_pll(hw); @@ -72,13 +122,7 @@ static int samsung_pll3xxx_enable(struct clk_hw *hw) tmp |= BIT(pll->enable_offs); writel_relaxed(tmp, pll->con_reg); - /* wait lock time */ - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & BIT(pll->lock_offs))); - - return 0; + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); } static void samsung_pll3xxx_disable(struct clk_hw *hw) @@ -240,13 +284,10 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->sdiv << PLL35XX_SDIV_SHIFT); writel_relaxed(tmp, pll->con_reg); - /* Wait until the PLL is locked if it is enabled. */ - if (tmp & BIT(pll->enable_offs)) { - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & BIT(pll->lock_offs))); - } + /* Wait for PLL lock if the PLL is enabled */ + if (tmp & BIT(pll->enable_offs)) + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); + return 0; } @@ -318,7 +359,7 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long parent_rate) { struct samsung_clk_pll *pll = to_clk_pll(hw); - u32 tmp, pll_con0, pll_con1; + u32 pll_con0, pll_con1; const struct samsung_pll_rate_table *rate; rate = samsung_get_pll_settings(pll, drate); @@ -356,13 +397,8 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT; writel_relaxed(pll_con1, pll->con_reg + 4); - /* wait_lock_time */ - if (pll_con0 & BIT(pll->enable_offs)) { - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & BIT(pll->lock_offs))); - } + if (pll_con0 & BIT(pll->enable_offs)) + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); return 0; } @@ -437,7 +473,6 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, struct samsung_clk_pll *pll = to_clk_pll(hw); const struct samsung_pll_rate_table *rate; u32 con0, con1; - ktime_t start; /* Get required rate settings from table */ rate = samsung_get_pll_settings(pll, drate); @@ -488,21 +523,8 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(con1, pll->con_reg + 0x4); writel_relaxed(con0, pll->con_reg); - /* Wait for locking. */ - start = ktime_get(); - while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) { - ktime_t delta = ktime_sub(ktime_get(), start); - - if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { - pr_err("%s: could not lock PLL %s\n", - __func__, clk_hw_get_name(hw)); - return -EFAULT; - } - - cpu_relax(); - } - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, PLL45XX_LOCKED); } static const struct clk_ops samsung_pll45xx_clk_ops = { @@ -588,7 +610,6 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, struct samsung_clk_pll *pll = to_clk_pll(hw); const struct samsung_pll_rate_table *rate; u32 con0, con1, lock; - ktime_t start; /* Get required rate settings from table */ rate = samsung_get_pll_settings(pll, drate); @@ -647,21 +668,8 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(con0, pll->con_reg); writel_relaxed(con1, pll->con_reg + 0x4); - /* Wait for locking. */ - start = ktime_get(); - while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) { - ktime_t delta = ktime_sub(ktime_get(), start); - - if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { - pr_err("%s: could not lock PLL %s\n", - __func__, clk_hw_get_name(hw)); - return -EFAULT; - } - - cpu_relax(); - } - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, PLL46XX_LOCKED); } static const struct clk_ops samsung_pll46xx_clk_ops = { @@ -1035,14 +1043,9 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->sdiv << PLL2550XX_S_SHIFT); writel_relaxed(tmp, pll->con_reg); - /* wait_lock_time */ - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK - << PLL2550XX_LOCK_STAT_SHIFT))); - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, + PLL2550XX_LOCK_STAT_MASK << PLL2550XX_LOCK_STAT_SHIFT); } static const struct clk_ops samsung_pll2550xx_clk_ops = { @@ -1132,13 +1135,9 @@ static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate, con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT); writel_relaxed(con1, pll->con_reg + 4); - do { - cpu_relax(); - con0 = readl_relaxed(pll->con_reg); - } while (!(con0 & (PLL2650X_LOCK_STAT_MASK - << PLL2650X_LOCK_STAT_SHIFT))); - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, + PLL2650X_LOCK_STAT_MASK << PLL2650X_LOCK_STAT_SHIFT); } static const struct clk_ops samsung_pll2650x_clk_ops = { @@ -1196,7 +1195,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long parent_rate) { struct samsung_clk_pll *pll = to_clk_pll(hw); - u32 tmp, pll_con0, pll_con2; + u32 pll_con0, pll_con2; const struct samsung_pll_rate_table *rate; rate = samsung_get_pll_settings(pll, drate); @@ -1229,11 +1228,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(pll_con0, pll->con_reg); writel_relaxed(pll_con2, pll->con_reg + 8); - do { - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT))); - - return 0; + return samsung_pll_lock_wait(pll, 0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT); } static const struct clk_ops samsung_pll2650xx_clk_ops = { -- cgit v1.2.3-59-g8ed1b From 8d5d3c7a5bdd32044f595575f1aa16cd3bdd93a8 Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Thu, 19 Nov 2020 10:52:28 -0500 Subject: dt-bindings: clock: Add entry for crypto engine RPMH clock resource Add clock id forc CE clock resource which is required to bring up the crypto engine on sdm845. Reviewed-by: Bjorn Andersson Signed-off-by: Thara Gopinath Link: https://lore.kernel.org/r/20201119155233.3974286-2-thara.gopinath@linaro.org Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/qcom,rpmh.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/qcom,rpmh.h b/include/dt-bindings/clock/qcom,rpmh.h index 2e6c54e65455..30111c8f7fe9 100644 --- a/include/dt-bindings/clock/qcom,rpmh.h +++ b/include/dt-bindings/clock/qcom,rpmh.h @@ -21,5 +21,6 @@ #define RPMH_IPA_CLK 12 #define RPMH_LN_BB_CLK1 13 #define RPMH_LN_BB_CLK1_A 14 +#define RPMH_CE_CLK 15 #endif -- cgit v1.2.3-59-g8ed1b From dba6bc51975b54b0778678d581df5b423a5a0d81 Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Thu, 19 Nov 2020 10:52:29 -0500 Subject: clk: qcom: rpmh: Add CE clock on sdm845. Qualcomm CE clock resource that is managed by BCM is required by crypto driver to access the core clock. Reviewed-by: Bjorn Andersson Signed-off-by: Thara Gopinath Link: https://lore.kernel.org/r/20201119155233.3974286-3-thara.gopinath@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpmh.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index e2c669b08aff..7e2a4a9b9bf6 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -349,6 +349,7 @@ DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1); DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1); DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1); DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0"); +DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0"); static struct clk_hw *sdm845_rpmh_clocks[] = { [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, @@ -364,6 +365,7 @@ static struct clk_hw *sdm845_rpmh_clocks[] = { [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw, [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw, [RPMH_IPA_CLK] = &sdm845_ipa.hw, + [RPMH_CE_CLK] = &sdm845_ce.hw, }; static const struct clk_rpmh_desc clk_rpmh_sdm845 = { -- cgit v1.2.3-59-g8ed1b From 02d8e879e4101c2baa1f7a99c1a266742872a049 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 26 Nov 2020 23:24:00 +0000 Subject: clk: qcom: Kconfig: Fix spelling mistake "dyanmic" -> "dynamic" There is a spelling mistake in the Kconfig help text. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20201126232400.15011-1-colin.king@canonical.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 48c624a1eff1..8c8b568609d4 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -44,7 +44,7 @@ config QCOM_CLK_APCC_MSM8996 help Support for the CPU clock controller on msm8996 devices. Say Y if you want to support CPU clock scaling using CPUfreq - drivers for dyanmic power management. + drivers for dynamic power management. config QCOM_CLK_RPM tristate "RPM based Clock Controller" -- cgit v1.2.3-59-g8ed1b From a13ae5a3797aa86623c906604fb5a884b832a685 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 26 Nov 2020 12:58:39 +0530 Subject: dt-bindings: clock: Add SDX55 GCC clock bindings Add device tree bindings for global clock controller on SDX55 SoCs. Signed-off-by: Vinod Koul Signed-off-by: Manivannan Sadhasivam Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20201126072844.35370-2-manivannan.sadhasivam@linaro.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gcc-sdx55.yaml | 77 ++++++++++++++ include/dt-bindings/clock/qcom,gcc-sdx55.h | 112 +++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml create mode 100644 include/dt-bindings/clock/qcom,gcc-sdx55.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml new file mode 100644 index 000000000000..1121b3934cb9 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,gcc-sdx55.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller Binding for SDX55 + +maintainers: + - Vinod Koul + - Manivannan Sadhasivam + +description: | + Qualcomm global clock control module which supports the clocks, resets and + power domains on SDX55 + + See also: + - dt-bindings/clock/qcom,gcc-sdx55.h + +properties: + compatible: + const: qcom,gcc-sdx55 + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + - description: PLL test clock source (Optional clock) + minItems: 2 + maxItems: 3 + + clock-names: + items: + - const: bi_tcxo + - const: sleep_clk + - const: core_bi_pll_test_se # Optional clock + minItems: 2 + maxItems: 3 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - clocks + - clock-names + - reg + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + clock-controller@100000 { + compatible = "qcom,gcc-sdx55"; + reg = <0x00100000 0x1f0000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>, <&pll_test_clk>; + clock-names = "bi_tcxo", "sleep_clk", "core_bi_pll_test_se"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + +... diff --git a/include/dt-bindings/clock/qcom,gcc-sdx55.h b/include/dt-bindings/clock/qcom,gcc-sdx55.h new file mode 100644 index 000000000000..c372451b3461 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gcc-sdx55.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2020, Linaro Ltd. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SDX55_H +#define _DT_BINDINGS_CLK_QCOM_GCC_SDX55_H + +#define GPLL0 3 +#define GPLL0_OUT_EVEN 4 +#define GPLL4 5 +#define GPLL4_OUT_EVEN 6 +#define GPLL5 7 +#define GCC_AHB_PCIE_LINK_CLK 8 +#define GCC_BLSP1_AHB_CLK 9 +#define GCC_BLSP1_QUP1_I2C_APPS_CLK 10 +#define GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC 11 +#define GCC_BLSP1_QUP1_SPI_APPS_CLK 12 +#define GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC 13 +#define GCC_BLSP1_QUP2_I2C_APPS_CLK 14 +#define GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC 15 +#define GCC_BLSP1_QUP2_SPI_APPS_CLK 16 +#define GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC 17 +#define GCC_BLSP1_QUP3_I2C_APPS_CLK 18 +#define GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC 19 +#define GCC_BLSP1_QUP3_SPI_APPS_CLK 20 +#define GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC 21 +#define GCC_BLSP1_QUP4_I2C_APPS_CLK 22 +#define GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC 23 +#define GCC_BLSP1_QUP4_SPI_APPS_CLK 24 +#define GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC 25 +#define GCC_BLSP1_UART1_APPS_CLK 26 +#define GCC_BLSP1_UART1_APPS_CLK_SRC 27 +#define GCC_BLSP1_UART2_APPS_CLK 28 +#define GCC_BLSP1_UART2_APPS_CLK_SRC 29 +#define GCC_BLSP1_UART3_APPS_CLK 30 +#define GCC_BLSP1_UART3_APPS_CLK_SRC 31 +#define GCC_BLSP1_UART4_APPS_CLK 32 +#define GCC_BLSP1_UART4_APPS_CLK_SRC 33 +#define GCC_BOOT_ROM_AHB_CLK 34 +#define GCC_CE1_AHB_CLK 35 +#define GCC_CE1_AXI_CLK 36 +#define GCC_CE1_CLK 37 +#define GCC_CPUSS_AHB_CLK 38 +#define GCC_CPUSS_AHB_CLK_SRC 39 +#define GCC_CPUSS_GNOC_CLK 40 +#define GCC_CPUSS_RBCPR_CLK 41 +#define GCC_CPUSS_RBCPR_CLK_SRC 42 +#define GCC_EMAC_CLK_SRC 43 +#define GCC_EMAC_PTP_CLK_SRC 44 +#define GCC_ETH_AXI_CLK 45 +#define GCC_ETH_PTP_CLK 46 +#define GCC_ETH_RGMII_CLK 47 +#define GCC_ETH_SLAVE_AHB_CLK 48 +#define GCC_GP1_CLK 49 +#define GCC_GP1_CLK_SRC 50 +#define GCC_GP2_CLK 51 +#define GCC_GP2_CLK_SRC 52 +#define GCC_GP3_CLK 53 +#define GCC_GP3_CLK_SRC 54 +#define GCC_PCIE_0_CLKREF_CLK 55 +#define GCC_PCIE_AUX_CLK 56 +#define GCC_PCIE_AUX_PHY_CLK_SRC 57 +#define GCC_PCIE_CFG_AHB_CLK 58 +#define GCC_PCIE_MSTR_AXI_CLK 59 +#define GCC_PCIE_PIPE_CLK 60 +#define GCC_PCIE_RCHNG_PHY_CLK 61 +#define GCC_PCIE_RCHNG_PHY_CLK_SRC 62 +#define GCC_PCIE_SLEEP_CLK 63 +#define GCC_PCIE_SLV_AXI_CLK 64 +#define GCC_PCIE_SLV_Q2A_AXI_CLK 65 +#define GCC_PDM2_CLK 66 +#define GCC_PDM2_CLK_SRC 67 +#define GCC_PDM_AHB_CLK 68 +#define GCC_PDM_XO4_CLK 69 +#define GCC_SDCC1_AHB_CLK 70 +#define GCC_SDCC1_APPS_CLK 71 +#define GCC_SDCC1_APPS_CLK_SRC 72 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 73 +#define GCC_USB30_MASTER_CLK 74 +#define GCC_USB30_MASTER_CLK_SRC 75 +#define GCC_USB30_MOCK_UTMI_CLK 76 +#define GCC_USB30_MOCK_UTMI_CLK_SRC 77 +#define GCC_USB30_MSTR_AXI_CLK 78 +#define GCC_USB30_SLEEP_CLK 79 +#define GCC_USB30_SLV_AHB_CLK 80 +#define GCC_USB3_PHY_AUX_CLK 81 +#define GCC_USB3_PHY_AUX_CLK_SRC 82 +#define GCC_USB3_PHY_PIPE_CLK 83 +#define GCC_USB3_PRIM_CLKREF_CLK 84 +#define GCC_USB_PHY_CFG_AHB2PHY_CLK 85 +#define GCC_XO_DIV4_CLK 86 +#define GCC_XO_PCIE_LINK_CLK 87 + +#define GCC_EMAC_BCR 0 +#define GCC_PCIE_BCR 1 +#define GCC_PCIE_LINK_DOWN_BCR 2 +#define GCC_PCIE_NOCSR_COM_PHY_BCR 3 +#define GCC_PCIE_PHY_BCR 4 +#define GCC_PCIE_PHY_CFG_AHB_BCR 5 +#define GCC_PCIE_PHY_COM_BCR 6 +#define GCC_PCIE_PHY_NOCSR_COM_PHY_BCR 7 +#define GCC_PDM_BCR 8 +#define GCC_QUSB2PHY_BCR 9 +#define GCC_TCSR_PCIE_BCR 10 +#define GCC_USB30_BCR 11 +#define GCC_USB3_PHY_BCR 12 +#define GCC_USB3PHY_PHY_BCR 13 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 14 + +#endif -- cgit v1.2.3-59-g8ed1b From 3fade566c07abd54ad8324326a4a14f2b6c13e3d Mon Sep 17 00:00:00 2001 From: Naveen Yadav Date: Thu, 26 Nov 2020 12:58:40 +0530 Subject: clk: qcom: Add SDX55 GCC support Add Global Clock Controller (GCC) support for SDX55 SoCs from Qualcomm. Signed-off-by: Naveen Yadav [mani: converted to parent_data, commented critical clocks, cleanups] Signed-off-by: Manivannan Sadhasivam Reviewed-by: Vinod Koul Link: https://lore.kernel.org/r/20201126072844.35370-3-manivannan.sadhasivam@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-sdx55.c | 1626 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1634 insertions(+) create mode 100644 drivers/clk/qcom/gcc-sdx55.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 8c8b568609d4..3555eac37495 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -422,6 +422,13 @@ config SDM_LPASSCC_845 Say Y if you want to use the LPASS branch clocks of the LPASS clock controller to reset the LPASS subsystem. +config SDX_GCC_55 + tristate "SDX55 Global Clock Controller" + help + Support for the global clock controller on SDX55 devices. + Say Y if you want to use peripheral devices such as UART, + SPI, I2C, USB, SD/UFS, PCIe etc. + config SM_DISPCC_8250 tristate "SM8150 and SM8250 Display Clock Controller" depends on SM_GCC_8150 || SM_GCC_8250 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 57b6349a3ee8..9e5e0e3cb7b4 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o +obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o diff --git a/drivers/clk/qcom/gcc-sdx55.c b/drivers/clk/qcom/gcc-sdx55.c new file mode 100644 index 000000000000..bf114165e24b --- /dev/null +++ b/drivers/clk/qcom/gcc-sdx55.c @@ -0,0 +1,1626 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2020, Linaro Ltd. + */ + +#include +#include +#include +#include + +#include + +#include "common.h" +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_EVEN, + P_GPLL0_OUT_MAIN, + P_GPLL4_OUT_EVEN, + P_GPLL5_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .clkr = { + .enable_reg = 0x6d000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_lucid_even[] = { + { 0x0, 1 }, + { 0x1, 2 }, + { 0x3, 4 }, + { 0x7, 8 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_even = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .post_div_shift = 8, + .post_div_table = post_div_table_lucid_even, + .num_post_div = ARRAY_SIZE(post_div_table_lucid_even), + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_even", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .clkr = { + .enable_reg = 0x6d000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv gpll4_out_even = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .post_div_shift = 8, + .post_div_table = post_div_table_lucid_even, + .num_post_div = ARRAY_SIZE(post_div_table_lucid_even), + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll4_out_even", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll4.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static struct clk_alpha_pll gpll5 = { + .offset = 0x74000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .clkr = { + .enable_reg = 0x6d000, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gpll5", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parents_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se" }, +}; + +static const struct clk_parent_data gcc_parents_0_ao[] = { + { .fw_name = "bi_tcxo_ao" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL4_OUT_EVEN, 2 }, + { P_GPLL5_OUT_MAIN, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parents_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll4_out_even.clkr.hw }, + { .hw = &gpll5.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parents_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .fw_name = "sleep_clk", .name = "sleep_clk" }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parents_4[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "sleep_clk", .name = "sleep_clk" }, + { .fw_name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL4_OUT_EVEN, 2 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parents_5[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll4_out_even.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se" }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_qup1_i2c_apps_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_blsp1_qup1_i2c_apps_clk_src = { + .cmd_rcgr = 0x11024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_i2c_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_qup1_spi_apps_clk_src[] = { + F(960000, P_BI_TCXO, 10, 1, 2), + F(4800000, P_BI_TCXO, 4, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(15000000, P_GPLL0_OUT_EVEN, 5, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_GPLL0_OUT_MAIN, 12.5, 1, 2), + F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2), + F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_blsp1_qup1_spi_apps_clk_src = { + .cmd_rcgr = 0x1100c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_spi_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_qup2_i2c_apps_clk_src = { + .cmd_rcgr = 0x13024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_i2c_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_qup2_spi_apps_clk_src = { + .cmd_rcgr = 0x1300c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_spi_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_qup3_i2c_apps_clk_src = { + .cmd_rcgr = 0x15024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_i2c_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_qup3_spi_apps_clk_src = { + .cmd_rcgr = 0x1500c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_spi_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_qup4_i2c_apps_clk_src = { + .cmd_rcgr = 0x17024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_i2c_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_qup4_spi_apps_clk_src = { + .cmd_rcgr = 0x1700c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_spi_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_uart1_apps_clk_src[] = { + F(3686400, P_GPLL0_OUT_EVEN, 1, 192, 15625), + F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625), + F(16000000, P_GPLL0_OUT_EVEN, 1, 4, 75), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(19354839, P_GPLL0_OUT_MAIN, 15.5, 1, 2), + F(20000000, P_GPLL0_OUT_MAIN, 15, 1, 2), + F(20689655, P_GPLL0_OUT_MAIN, 14.5, 1, 2), + F(21428571, P_GPLL0_OUT_MAIN, 14, 1, 2), + F(22222222, P_GPLL0_OUT_MAIN, 13.5, 1, 2), + F(23076923, P_GPLL0_OUT_MAIN, 13, 1, 2), + F(24000000, P_GPLL0_OUT_MAIN, 5, 1, 5), + F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2), + F(26086957, P_GPLL0_OUT_MAIN, 11.5, 1, 2), + F(27272727, P_GPLL0_OUT_MAIN, 11, 1, 2), + F(28571429, P_GPLL0_OUT_MAIN, 10.5, 1, 2), + F(32000000, P_GPLL0_OUT_MAIN, 1, 4, 75), + F(40000000, P_GPLL0_OUT_MAIN, 15, 0, 0), + F(46400000, P_GPLL0_OUT_MAIN, 1, 29, 375), + F(48000000, P_GPLL0_OUT_MAIN, 12.5, 0, 0), + F(51200000, P_GPLL0_OUT_MAIN, 1, 32, 375), + F(56000000, P_GPLL0_OUT_MAIN, 1, 7, 75), + F(58982400, P_GPLL0_OUT_MAIN, 1, 1536, 15625), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + F(63157895, P_GPLL0_OUT_MAIN, 9.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_blsp1_uart1_apps_clk_src = { + .cmd_rcgr = 0x1200c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart1_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_uart2_apps_clk_src = { + .cmd_rcgr = 0x1400c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart2_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_uart3_apps_clk_src = { + .cmd_rcgr = 0x1600c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart3_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_blsp1_uart4_apps_clk_src = { + .cmd_rcgr = 0x1800c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart4_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_cpuss_ahb_clk_src = { + .cmd_rcgr = 0x24010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk_src", + .parent_data = gcc_parents_0_ao, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_cpuss_rbcpr_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = { + .cmd_rcgr = 0x2402c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_rbcpr_clk_src", + .parent_data = gcc_parents_0_ao, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac_clk_src[] = { + F(2500000, P_BI_TCXO, 1, 25, 192), + F(5000000, P_BI_TCXO, 1, 25, 96), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(250000000, P_GPLL4_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac_clk_src = { + .cmd_rcgr = 0x47020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_emac_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_emac_clk_src", + .parent_data = gcc_parents_5, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac_ptp_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(230400000, P_GPLL5_OUT_MAIN, 3.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac_ptp_clk_src = { + .cmd_rcgr = 0x47038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_emac_ptp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_emac_ptp_clk_src", + .parent_data = gcc_parents_2, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x2b004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parents_3, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x2c004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parents_3, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x2d004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parents_3, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = { + .cmd_rcgr = 0x37034, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_aux_phy_clk_src", + .parent_data = gcc_parents_4, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_rchng_phy_clk_src[] = { + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = { + .cmd_rcgr = 0x37050, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_rchng_phy_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_rchng_phy_clk_src", + .parent_data = gcc_parents_3, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x19010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0xf00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_master_clk_src[] = { + F(200000000, P_GPLL0_OUT_EVEN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_master_clk_src = { + .cmd_rcgr = 0xb024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_master_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_mock_utmi_clk_src = { + .cmd_rcgr = 0xb03c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_mock_utmi_clk_src", + .parent_data = gcc_parents_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb3_phy_aux_clk_src[] = { + F(1000000, P_BI_TCXO, 1, 5, 96), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb3_phy_aux_clk_src = { + .cmd_rcgr = 0xb064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_usb3_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_phy_aux_clk_src", + .parent_data = gcc_parents_4, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ahb_pcie_link_clk = { + .halt_reg = 0x22004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x22004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb_pcie_link_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_ahb_clk = { + .halt_reg = 0x10004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d008, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = { + .halt_reg = 0x11008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup1_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = { + .halt_reg = 0x11004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup1_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = { + .halt_reg = 0x13008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup2_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { + .halt_reg = 0x13004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup2_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = { + .halt_reg = 0x15008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup3_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = { + .halt_reg = 0x15004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup3_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup4_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_qup4_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart1_apps_clk = { + .halt_reg = 0x12004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart1_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_uart1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart2_apps_clk = { + .halt_reg = 0x14004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart2_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_uart2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart3_apps_clk = { + .halt_reg = 0x16004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x16004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart3_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_uart3_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart4_apps_clk = { + .halt_reg = 0x18004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x18004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart4_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_blsp1_uart4_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x1c004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1c004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6d008, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_ahb_clk = { + .halt_reg = 0x2100c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2100c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6d008, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_axi_clk = { + .halt_reg = 0x21008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d008, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_clk = { + .halt_reg = 0x21004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d008, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_rbcpr_clk = { + .halt_reg = 0x24008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x24008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_rbcpr_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_cpuss_rbcpr_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eth_axi_clk = { + .halt_reg = 0x4701c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_eth_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eth_ptp_clk = { + .halt_reg = 0x47018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x47018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_eth_ptp_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_emac_ptp_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eth_rgmii_clk = { + .halt_reg = 0x47010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x47010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_eth_rgmii_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_emac_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eth_slave_ahb_clk = { + .halt_reg = 0x47014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x47014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_eth_slave_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x2b000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2b000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_gp1_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x2c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_gp2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x2d000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2d000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_gp3_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_clkref_clk = { + .halt_reg = 0x88004, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x88004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_aux_clk = { + .halt_reg = 0x37024, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_aux_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_cfg_ahb_clk = { + .halt_reg = 0x3701c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_mstr_axi_clk = { + .halt_reg = 0x37018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_pipe_clk = { + .halt_reg = 0x3702c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_rchng_phy_clk = { + .halt_reg = 0x37020, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_rchng_phy_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_pcie_rchng_phy_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_sleep_clk = { + .halt_reg = 0x37028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_sleep_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_pcie_aux_phy_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_axi_clk = { + .halt_reg = 0x37014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x37014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_q2a_axi_clk = { + .halt_reg = 0x37010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x1900c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1900c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_pdm2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x19004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x19004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x19004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x19008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x19008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0xf008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0xf004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_sdcc1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_master_clk = { + .halt_reg = 0xb010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_master_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_usb30_master_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mock_utmi_clk = { + .halt_reg = 0xb020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_mock_utmi_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_usb30_mock_utmi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mstr_axi_clk = { + .halt_reg = 0xb014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sleep_clk = { + .halt_reg = 0xb01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb01c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_slv_ahb_clk = { + .halt_reg = 0xb018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_phy_aux_clk = { + .halt_reg = 0xb058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_phy_aux_clk", + .parent_hws = (const struct clk_hw *[]){ + &gcc_usb3_phy_aux_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_phy_pipe_clk = { + .halt_reg = 0xb05c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xb05c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_clk = { + .halt_reg = 0x88000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x88000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { + .halt_reg = 0xe004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xe004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xe004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_phy_cfg_ahb2phy_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_xo_pcie_link_clk = { + .halt_reg = 0x22008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x22008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_xo_pcie_link_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *gcc_sdx55_clocks[] = { + [GCC_AHB_PCIE_LINK_CLK] = &gcc_ahb_pcie_link_clk.clkr, + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC] = + &gcc_blsp1_qup1_i2c_apps_clk_src.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC] = + &gcc_blsp1_qup1_spi_apps_clk_src.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC] = + &gcc_blsp1_qup2_i2c_apps_clk_src.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC] = + &gcc_blsp1_qup2_spi_apps_clk_src.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC] = + &gcc_blsp1_qup3_i2c_apps_clk_src.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC] = + &gcc_blsp1_qup3_spi_apps_clk_src.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC] = + &gcc_blsp1_qup4_i2c_apps_clk_src.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC] = + &gcc_blsp1_qup4_spi_apps_clk_src.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK_SRC] = &gcc_blsp1_uart1_apps_clk_src.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK_SRC] = &gcc_blsp1_uart2_apps_clk_src.clkr, + [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr, + [GCC_BLSP1_UART3_APPS_CLK_SRC] = &gcc_blsp1_uart3_apps_clk_src.clkr, + [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, + [GCC_BLSP1_UART4_APPS_CLK_SRC] = &gcc_blsp1_uart4_apps_clk_src.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr, + [GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr, + [GCC_CPUSS_RBCPR_CLK_SRC] = &gcc_cpuss_rbcpr_clk_src.clkr, + [GCC_EMAC_CLK_SRC] = &gcc_emac_clk_src.clkr, + [GCC_EMAC_PTP_CLK_SRC] = &gcc_emac_ptp_clk_src.clkr, + [GCC_ETH_AXI_CLK] = &gcc_eth_axi_clk.clkr, + [GCC_ETH_PTP_CLK] = &gcc_eth_ptp_clk.clkr, + [GCC_ETH_RGMII_CLK] = &gcc_eth_rgmii_clk.clkr, + [GCC_ETH_SLAVE_AHB_CLK] = &gcc_eth_slave_ahb_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_PCIE_0_CLKREF_CLK] = &gcc_pcie_0_clkref_clk.clkr, + [GCC_PCIE_AUX_CLK] = &gcc_pcie_aux_clk.clkr, + [GCC_PCIE_AUX_PHY_CLK_SRC] = &gcc_pcie_aux_phy_clk_src.clkr, + [GCC_PCIE_CFG_AHB_CLK] = &gcc_pcie_cfg_ahb_clk.clkr, + [GCC_PCIE_MSTR_AXI_CLK] = &gcc_pcie_mstr_axi_clk.clkr, + [GCC_PCIE_PIPE_CLK] = &gcc_pcie_pipe_clk.clkr, + [GCC_PCIE_RCHNG_PHY_CLK] = &gcc_pcie_rchng_phy_clk.clkr, + [GCC_PCIE_RCHNG_PHY_CLK_SRC] = &gcc_pcie_rchng_phy_clk_src.clkr, + [GCC_PCIE_SLEEP_CLK] = &gcc_pcie_sleep_clk.clkr, + [GCC_PCIE_SLV_AXI_CLK] = &gcc_pcie_slv_axi_clk.clkr, + [GCC_PCIE_SLV_Q2A_AXI_CLK] = &gcc_pcie_slv_q2a_axi_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr, + [GCC_USB30_MASTER_CLK_SRC] = &gcc_usb30_master_clk_src.clkr, + [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr, + [GCC_USB30_MOCK_UTMI_CLK_SRC] = &gcc_usb30_mock_utmi_clk_src.clkr, + [GCC_USB30_MSTR_AXI_CLK] = &gcc_usb30_mstr_axi_clk.clkr, + [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr, + [GCC_USB30_SLV_AHB_CLK] = &gcc_usb30_slv_ahb_clk.clkr, + [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr, + [GCC_USB3_PHY_AUX_CLK_SRC] = &gcc_usb3_phy_aux_clk_src.clkr, + [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr, + [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr, + [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr, + [GCC_XO_PCIE_LINK_CLK] = &gcc_xo_pcie_link_clk.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr, + [GPLL4] = &gpll4.clkr, + [GPLL4_OUT_EVEN] = &gpll4_out_even.clkr, + [GPLL5] = &gpll5.clkr, +}; + +static const struct qcom_reset_map gcc_sdx55_resets[] = { + [GCC_EMAC_BCR] = { 0x47000 }, + [GCC_PCIE_BCR] = { 0x37000 }, + [GCC_PCIE_LINK_DOWN_BCR] = { 0x77000 }, + [GCC_PCIE_PHY_BCR] = { 0x39000 }, + [GCC_PCIE_PHY_COM_BCR] = { 0x78004 }, + [GCC_QUSB2PHY_BCR] = { 0xd000 }, + [GCC_USB30_BCR] = { 0xb000 }, + [GCC_USB3_PHY_BCR] = { 0xc000 }, + [GCC_USB3PHY_PHY_BCR] = { 0xc004 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0xe000 }, +}; + +static const struct regmap_config gcc_sdx55_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9b040, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sdx55_desc = { + .config = &gcc_sdx55_regmap_config, + .clks = gcc_sdx55_clocks, + .num_clks = ARRAY_SIZE(gcc_sdx55_clocks), + .resets = gcc_sdx55_resets, + .num_resets = ARRAY_SIZE(gcc_sdx55_resets), +}; + +static const struct of_device_id gcc_sdx55_match_table[] = { + { .compatible = "qcom,gcc-sdx55" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sdx55_match_table); + +static int gcc_sdx55_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gcc_sdx55_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Keep the clocks always-ON as they are critical to the functioning + * of the system: + * GCC_SYS_NOC_CPUSS_AHB_CLK, GCC_CPUSS_AHB_CLK, GCC_CPUSS_GNOC_CLK + */ + regmap_update_bits(regmap, 0x6d008, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x6d008, BIT(21), BIT(21)); + regmap_update_bits(regmap, 0x6d008, BIT(22), BIT(22)); + + return qcom_cc_really_probe(pdev, &gcc_sdx55_desc, regmap); +} + +static struct platform_driver gcc_sdx55_driver = { + .probe = gcc_sdx55_probe, + .driver = { + .name = "gcc-sdx55", + .of_match_table = gcc_sdx55_match_table, + }, +}; + +static int __init gcc_sdx55_init(void) +{ + return platform_driver_register(&gcc_sdx55_driver); +} +subsys_initcall(gcc_sdx55_init); + +static void __exit gcc_sdx55_exit(void) +{ + platform_driver_unregister(&gcc_sdx55_driver); +} +module_exit(gcc_sdx55_exit); + +MODULE_DESCRIPTION("QTI GCC SDX55 Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 2e2639b7ef1641252e838b5181c0b8fec8b6c067 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 26 Nov 2020 12:58:41 +0530 Subject: dt-bindings: clock: Introduce RPMHCC bindings for SDX55 Add compatible for SDX55 RPMHCC and DT include. Signed-off-by: Vinod Koul Signed-off-by: Manivannan Sadhasivam Reviewed-by: Bjorn Andersson Acked-by: Rob Herring Link: https://lore.kernel.org/r/20201126072844.35370-4-manivannan.sadhasivam@linaro.org Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml | 1 + include/dt-bindings/clock/qcom,rpmh.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml index a46a3a799a70..a54930f111ba 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml @@ -19,6 +19,7 @@ properties: enum: - qcom,sc7180-rpmh-clk - qcom,sdm845-rpmh-clk + - qcom,sdx55-rpmh-clk - qcom,sm8150-rpmh-clk - qcom,sm8250-rpmh-clk diff --git a/include/dt-bindings/clock/qcom,rpmh.h b/include/dt-bindings/clock/qcom,rpmh.h index 30111c8f7fe9..0662a583e93b 100644 --- a/include/dt-bindings/clock/qcom,rpmh.h +++ b/include/dt-bindings/clock/qcom,rpmh.h @@ -22,5 +22,6 @@ #define RPMH_LN_BB_CLK1 13 #define RPMH_LN_BB_CLK1_A 14 #define RPMH_CE_CLK 15 +#define RPMH_QPIC_CLK 16 #endif -- cgit v1.2.3-59-g8ed1b From afacfbbe1016a692b1fea4ed4c3f1d6f6a4ef4e5 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 26 Nov 2020 12:58:42 +0530 Subject: clk: qcom: Add support for SDX55 RPMh clocks Add support for following clocks maintained by RPMh in SDX55 SoCs. * BI TCXO * RF_CLK1 * RF_CLK1_AO * RF_CLK2 * RF_CLK2_AO * QPIC (Qualcomm Technologies, Inc. Parallel Interface Controller) Signed-off-by: Manivannan Sadhasivam Reviewed-by: Vinod Koul Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20201126072844.35370-5-manivannan.sadhasivam@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpmh.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 7e2a4a9b9bf6..f47595a04885 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -434,6 +434,25 @@ static const struct clk_rpmh_desc clk_rpmh_sm8250 = { .num_clks = ARRAY_SIZE(sm8250_rpmh_clocks), }; +DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1); +DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1); +DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0"); + +static struct clk_hw *sdx55_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, + [RPMH_RF_CLK1] = &sdx55_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdx55_rf_clk1_ao.hw, + [RPMH_RF_CLK2] = &sdx55_rf_clk2.hw, + [RPMH_RF_CLK2_A] = &sdx55_rf_clk2_ao.hw, + [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sdx55 = { + .clks = sdx55_rpmh_clocks, + .num_clks = ARRAY_SIZE(sdx55_rpmh_clocks), +}; + static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, void *data) { @@ -519,6 +538,7 @@ static int clk_rpmh_probe(struct platform_device *pdev) static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180}, { .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845}, + { .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55}, { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150}, { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250}, { } -- cgit v1.2.3-59-g8ed1b From bdf7805b8c0e45ade8d26e5bd4616ddcbb3fcc36 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 26 Nov 2020 12:58:43 +0530 Subject: dt-bindings: clock: Add GDSC in SDX55 GCC Add GDSC instances in SDX55 GCC block. Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20201126072844.35370-6-manivannan.sadhasivam@linaro.org Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/qcom,gcc-sdx55.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/dt-bindings/clock/qcom,gcc-sdx55.h b/include/dt-bindings/clock/qcom,gcc-sdx55.h index c372451b3461..fb9a5942f793 100644 --- a/include/dt-bindings/clock/qcom,gcc-sdx55.h +++ b/include/dt-bindings/clock/qcom,gcc-sdx55.h @@ -109,4 +109,9 @@ #define GCC_USB3PHY_PHY_BCR 13 #define GCC_USB_PHY_CFG_AHB2PHY_BCR 14 +/* GCC power domains */ +#define USB30_GDSC 0 +#define PCIE_GDSC 1 +#define EMAC_GDSC 2 + #endif -- cgit v1.2.3-59-g8ed1b From 063930ed2df5dbe07e994009a7e05e773f10b23a Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 26 Nov 2020 12:58:44 +0530 Subject: clk: qcom: Add GDSC support for SDX55 GCC Add GDSC support to control the power supply of power domains in SDX55 GCC. Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20201126072844.35370-7-manivannan.sadhasivam@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + drivers/clk/qcom/gcc-sdx55.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 3555eac37495..d32bb12cd8d0 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -424,6 +424,7 @@ config SDM_LPASSCC_845 config SDX_GCC_55 tristate "SDX55 Global Clock Controller" + select QCOM_GDSC help Support for the global clock controller on SDX55 devices. Say Y if you want to use peripheral devices such as UART, diff --git a/drivers/clk/qcom/gcc-sdx55.c b/drivers/clk/qcom/gcc-sdx55.c index bf114165e24b..e3b9030b2bae 100644 --- a/drivers/clk/qcom/gcc-sdx55.c +++ b/drivers/clk/qcom/gcc-sdx55.c @@ -17,6 +17,7 @@ #include "clk-pll.h" #include "clk-rcg.h" #include "clk-regmap.h" +#include "gdsc.h" #include "reset.h" enum { @@ -1455,6 +1456,30 @@ static struct clk_branch gcc_xo_pcie_link_clk = { }, }; +static struct gdsc usb30_gdsc = { + .gdscr = 0x0b004, + .pd = { + .name = "usb30_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_gdsc = { + .gdscr = 0x37004, + .pd = { + .name = "pcie_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc emac_gdsc = { + .gdscr = 0x47004, + .pd = { + .name = "emac_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *gcc_sdx55_clocks[] = { [GCC_AHB_PCIE_LINK_CLK] = &gcc_ahb_pcie_link_clk.clkr, [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, @@ -1560,6 +1585,12 @@ static const struct qcom_reset_map gcc_sdx55_resets[] = { [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0xe000 }, }; +static struct gdsc *gcc_sdx55_gdscs[] = { + [USB30_GDSC] = &usb30_gdsc, + [PCIE_GDSC] = &pcie_gdsc, + [EMAC_GDSC] = &emac_gdsc, +}; + static const struct regmap_config gcc_sdx55_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -1574,6 +1605,8 @@ static const struct qcom_cc_desc gcc_sdx55_desc = { .num_clks = ARRAY_SIZE(gcc_sdx55_clocks), .resets = gcc_sdx55_resets, .num_resets = ARRAY_SIZE(gcc_sdx55_resets), + .gdscs = gcc_sdx55_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sdx55_gdscs), }; static const struct of_device_id gcc_sdx55_match_table[] = { -- cgit v1.2.3-59-g8ed1b From 0ca995f5c7110c13795cf82c18639175e2ee20f2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 24 Sep 2020 13:18:08 +0200 Subject: clk: renesas: r8a779a0: Make rcar_r8a779a0_cpg_clk_register() static When compiling with clang: drivers/clk/renesas/r8a779a0-cpg-mssr.c:156:21: warning: no previous prototype for function 'rcar_r8a779a0_cpg_clk_register' [-Wmissing-prototypes] struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, ^ drivers/clk/renesas/r8a779a0-cpg-mssr.c:156:1: note: declare 'static' if the function is not intended to be used outside of this translation unit struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, ^ static Similarly, with sparse: drivers/clk/renesas/r8a779a0-cpg-mssr.c:156:12: warning: symbol 'rcar_r8a779a0_cpg_clk_register' was not declared. Should it be static? There are no users of rcar_r8a779a0_cpg_clk_register() outside this file, so it should be static. Fixes: 17bcc8035d2d19fc ("clk: renesas: cpg-mssr: Add support for R-Car V3U") Reported-by: kernel test robot Signed-off-by: Geert Uytterhoeven Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200924111808.15358-1-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 17ebbac7ddfb..7e25b3b8945b 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -153,7 +153,7 @@ static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; -struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, +static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, struct clk **clks, void __iomem *base, struct raw_notifier_head *notifiers) -- cgit v1.2.3-59-g8ed1b From 043585760f5191926467862c01a0893c2fefb359 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 25 Sep 2020 13:07:13 +0200 Subject: MAINTAINERS: Update git repo for Renesas clock drivers Align the clock branch name with other renesas-* branches pulled by subsystem maintainers. Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/20200925110713.2652-1-geert+renesas@glider.be --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index e73636b75f29..595e1023b398 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14888,7 +14888,7 @@ RENESAS CLOCK DRIVERS M: Geert Uytterhoeven L: linux-renesas-soc@vger.kernel.org S: Supported -T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git clk-renesas +T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git renesas-clk F: Documentation/devicetree/bindings/clock/renesas,* F: drivers/clk/renesas/ -- cgit v1.2.3-59-g8ed1b From 23378e70ca286de32cedcf6505af734b034148dc Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 16 Oct 2020 13:11:53 +0200 Subject: clk: renesas: r8a779a0: Add CSI4[0-3] clocks Add definitions of the CSI-2 receiver clocks for R-Car V3U. Signed-off-by: Jacopo Mondi Link: https://lore.kernel.org/r/20201016111158.17521-2-jacopo+renesas@jmondi.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 7e25b3b8945b..bd54a28c50ee 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -141,6 +141,10 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), + DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), + DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), + DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), -- cgit v1.2.3-59-g8ed1b From 874d4eee5421d08fd220adffc32da307f8b7c964 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 16 Oct 2020 13:11:56 +0200 Subject: clk: renesas: r8a779a0: Add VIN clocks Add definitions of the VIN instance clocks for R-Car V3U. Signed-off-by: Jacopo Mondi Link: https://lore.kernel.org/r/20201016111158.17521-5-jacopo+renesas@jmondi.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index bd54a28c50ee..2a00eb82013f 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -149,6 +149,38 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), + DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1), + DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1), + DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1), + DEF_MOD("vin03", 801, R8A779A0_CLK_S1D1), + DEF_MOD("vin04", 802, R8A779A0_CLK_S1D1), + DEF_MOD("vin05", 803, R8A779A0_CLK_S1D1), + DEF_MOD("vin06", 804, R8A779A0_CLK_S1D1), + DEF_MOD("vin07", 805, R8A779A0_CLK_S1D1), + DEF_MOD("vin10", 806, R8A779A0_CLK_S1D1), + DEF_MOD("vin11", 807, R8A779A0_CLK_S1D1), + DEF_MOD("vin12", 808, R8A779A0_CLK_S1D1), + DEF_MOD("vin13", 809, R8A779A0_CLK_S1D1), + DEF_MOD("vin14", 810, R8A779A0_CLK_S1D1), + DEF_MOD("vin15", 811, R8A779A0_CLK_S1D1), + DEF_MOD("vin16", 812, R8A779A0_CLK_S1D1), + DEF_MOD("vin17", 813, R8A779A0_CLK_S1D1), + DEF_MOD("vin20", 814, R8A779A0_CLK_S1D1), + DEF_MOD("vin21", 815, R8A779A0_CLK_S1D1), + DEF_MOD("vin22", 816, R8A779A0_CLK_S1D1), + DEF_MOD("vin23", 817, R8A779A0_CLK_S1D1), + DEF_MOD("vin24", 818, R8A779A0_CLK_S1D1), + DEF_MOD("vin25", 819, R8A779A0_CLK_S1D1), + DEF_MOD("vin26", 820, R8A779A0_CLK_S1D1), + DEF_MOD("vin27", 821, R8A779A0_CLK_S1D1), + DEF_MOD("vin30", 822, R8A779A0_CLK_S1D1), + DEF_MOD("vin31", 823, R8A779A0_CLK_S1D1), + DEF_MOD("vin32", 824, R8A779A0_CLK_S1D1), + DEF_MOD("vin33", 825, R8A779A0_CLK_S1D1), + DEF_MOD("vin34", 826, R8A779A0_CLK_S1D1), + DEF_MOD("vin35", 827, R8A779A0_CLK_S1D1), + DEF_MOD("vin36", 828, R8A779A0_CLK_S1D1), + DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1), }; static spinlock_t cpg_lock; -- cgit v1.2.3-59-g8ed1b From 13d2617bf224351e78141183ca51971df83a9dd5 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 16 Oct 2020 13:17:07 +0100 Subject: clk: renesas: r8a774a1: Add RPC clocks Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, as well as the RPC-IF module clock, in the RZ/G2M (R8A774A1) CPG/MSSR driver. Inspired by commit 94e3935b5756 ("clk: renesas: r8a77980: Add RPC clocks"). Signed-off-by: Biju Das Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20201016121709.8447-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a774a1-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c index fd54b9f625da..4a43ebec7d5e 100644 --- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c @@ -41,6 +41,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -67,6 +68,12 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774A1_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -200,6 +207,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774A1_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774A1_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774A1_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774A1_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774A1_CLK_S0D6), DEF_MOD("i2c5", 919, R8A774A1_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A774A1_CLK_CP), -- cgit v1.2.3-59-g8ed1b From fb9805c51793339e0affbc8e3ce2b3210b41c9fa Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 16 Oct 2020 13:17:08 +0100 Subject: clk: renesas: r8a774b1: Add RPC clocks Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, as well as the RPC-IF module clock, in the RZ/G2N (R8A774B1) CPG/MSSR driver. Inspired by commit 94e3935b5756 ("clk: renesas: r8a77980: Add RPC clocks"). Signed-off-by: Biju Das Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20201016121709.8447-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a774b1-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c index f436691271ec..6f04c40fe237 100644 --- a/drivers/clk/renesas/r8a774b1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c @@ -40,6 +40,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -65,6 +66,12 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774B1_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -196,6 +203,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774B1_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774B1_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774B1_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774B1_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774B1_CLK_S0D6), DEF_MOD("i2c5", 919, R8A774B1_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A774B1_CLK_CP), -- cgit v1.2.3-59-g8ed1b From 4ef39a80da8b15ed933d387bc02ec14df4f4f1a7 Mon Sep 17 00:00:00 2001 From: Yejune Deng Date: Tue, 3 Nov 2020 11:44:53 +0800 Subject: clk: renesas: rcar-usb2-clock-sel: Replace devm_reset_control_array_get() devm_reset_control_array_get_shared() looks more readable Signed-off-by: Yejune Deng Link: https://lore.kernel.org/r/1604375093-6451-1-git-send-email-yejune.deng@gmail.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-usb2-clock-sel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index d4c02986c34e..3abafd78f7c8 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -160,7 +160,7 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (ret < 0) return ret; - priv->rsts = devm_reset_control_array_get(dev, true, false); + priv->rsts = devm_reset_control_array_get_shared(dev); if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts); -- cgit v1.2.3-59-g8ed1b From b5fb3b8859a491ff31e933927809f17a4e39459f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 3 Nov 2020 17:24:34 +0100 Subject: clk: renesas: cpg-mssr: fix kerneldoc of cpg_mssr_priv The struct cpg_mssr_priv missed proper formatting: drivers/clk/renesas/renesas-cpg-mssr.c:142: warning: cannot understand function prototype: 'struct cpg_mssr_priv ' Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20201103162435.13689-7-krzk@kernel.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 94db88370337..1c3215dc4877 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -119,7 +119,8 @@ static const u16 srstclr_for_v3u[] = { }; /** - * Clock Pulse Generator / Module Standby and Software Reset Private Data + * struct cpg_mssr_priv - Clock Pulse Generator / Module Standby + * and Software Reset Private Data * * @rcdev: Optional reset controller entity * @dev: CPG/MSSR device -- cgit v1.2.3-59-g8ed1b From 14653942de7f63e21ece32e3901f09a248598a43 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 9 Nov 2020 16:26:14 +0100 Subject: clk: renesas: r8a779a0: Fix R and OSC clocks The R-Car V3U clock driver defines the R and OSC clocks using R-Car Gen3 clock types. However, The R-Car V3U clock driver does not use the R-Car Gen3 clock driver core, hence registering the R and OSC clocks fails: renesas-cpg-mssr e6150000.clock-controller: Failed to register core clock osc: -22 renesas-cpg-mssr e6150000.clock-controller: Failed to register core clock r: -22 Fix this by introducing clock definition macros specific to R-Car V3U. Note that rcar_r8a779a0_cpg_clk_register() already handled the related clock types. Drop the now unneeded include of rcar-gen3-cpg.h. Fixes: 17bcc8035d2d19fc ("clk: renesas: cpg-mssr: Add support for R-Car V3U") Signed-off-by: Geert Uytterhoeven Tested-by: Yoshihiro Shimoda Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201109152614.2465483-1-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 2a00eb82013f..aa5389b04d74 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -26,7 +26,6 @@ #include #include "renesas-cpg-mssr.h" -#include "rcar-gen3-cpg.h" enum rcar_r8a779a0_clk_types { CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM, @@ -84,6 +83,14 @@ enum clk_ids { DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \ .offset = _offset) +#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL, \ + (_parent0) << 16 | (_parent1), \ + .div = (_div0) << 16 | (_div1), .offset = _md) + +#define DEF_OSC(_name, _id, _parent, _div) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div) + static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -136,8 +143,8 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880), - DEF_GEN3_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8), - DEF_GEN3_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), + DEF_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8), + DEF_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), }; static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { -- cgit v1.2.3-59-g8ed1b From 40745482eec81bea686cd1b38693191dc7e9ac66 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 16 Nov 2020 10:10:02 +0000 Subject: clk: renesas: r8a774c0: Add RPC clocks Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, as well as the RPC-IF module clock, in the RZ/G2E (R8A774C0) CPG/MSSR driver. Add new clk type CLK_TYPE_GEN3_E3_RPCSRC to register rpcsrc as a fixed clock on R-Car Gen3 E3 (and also RZ/G2E which is identical to E3 SoC), parent and the divider is set based on the register value CPG_RPCCKCR[4:3] which has been set prior to booting the kernel. Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20201116101002.5986-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a774c0-cpg-mssr.c | 9 +++++++++ drivers/clk/renesas/rcar-gen3-cpg.c | 28 ++++++++++++++++++++++++++++ drivers/clk/renesas/rcar-gen3-cpg.h | 5 +++++ 3 files changed, 42 insertions(+) diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c index 9fc9fa9e531a..ed3a2cf0e0bb 100644 --- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c @@ -44,6 +44,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, CLK_OCO, @@ -74,6 +75,13 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = { DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), + DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1), + + DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774C0_CLK_RPC), + DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), @@ -199,6 +207,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774C0_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774C0_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774C0_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774C0_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774C0_CLK_S3D2), DEF_MOD("i2c5", 919, R8A774C0_CLK_S3D2), DEF_MOD("i2c-dvfs", 926, R8A774C0_CLK_CP), diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index a7debddf7d09..063b61151488 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -695,6 +695,34 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, cpg_rpcsrc_div_table, &cpg_lock); + case CLK_TYPE_GEN3_E3_RPCSRC: + /* + * Register RPCSRC as fixed factor clock based on the + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for + * which has been set prior to booting the kernel. + */ + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3; + + switch (value) { + case 0: + div = 5; + break; + case 1: + div = 3; + break; + case 2: + parent = clks[core->parent >> 16]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + div = core->div; + break; + case 3: + default: + div = 2; + break; + } + break; + case CLK_TYPE_GEN3_RPC: return cpg_rpc_clk_register(core->name, base, __clk_get_name(parent), notifiers); diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index c4ac80cac6a0..3d949c4a3244 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -24,6 +24,7 @@ enum rcar_gen3_clk_types { CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ CLK_TYPE_GEN3_RPCSRC, + CLK_TYPE_GEN3_E3_RPCSRC, CLK_TYPE_GEN3_RPC, CLK_TYPE_GEN3_RPCD2, @@ -54,6 +55,10 @@ enum rcar_gen3_clk_types { #define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset) \ DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset) +#define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC, \ + (_parent0) << 16 | (_parent1), .div = 8) + struct rcar_gen3_cpg_pll_config { u8 extal_div; u8 pll1_mult; -- cgit v1.2.3-59-g8ed1b From fd0d8ed7c1b430f7e4a0a823a924ae3c849d74a3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 19 Nov 2020 13:50:53 +0100 Subject: clk: renesas: sh73a0: Stop using __raw_*() I/O accessors There is no reason to keep on using the __raw_{read,write}l() I/O accessors in Renesas ARM driver code. Switch to using the plain {read,write}l() I/O accessors, to have a chance that this works on big-endian. Suggested-by: Arnd Bergmann Signed-off-by: Geert Uytterhoeven Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20201119125053.4065746-1-geert+renesas@glider.be --- drivers/clk/renesas/clk-sh73a0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/clk-sh73a0.c b/drivers/clk/renesas/clk-sh73a0.c index 5f25a70bc61c..4146c1d717b9 100644 --- a/drivers/clk/renesas/clk-sh73a0.c +++ b/drivers/clk/renesas/clk-sh73a0.c @@ -121,7 +121,7 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg, (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR); parent_name = phy_no ? "dsi1pck" : "dsi0pck"; - mult = __raw_readl(dsi_reg); + mult = readl(dsi_reg); if (!(mult & 0x8000)) mult = 1; else -- cgit v1.2.3-59-g8ed1b From f5c50b1fed55332beb88e81e9e17c49673b77344 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 5 Nov 2020 11:32:04 +0900 Subject: dt-bindings: clock: renesas: rcar-usb2-clock-sel: Convert bindings to json-schema Convert Renesas R-Car USB 2.0 clock selector bindings documentation to json-schema. Signed-off-by: Yoshihiro Shimoda Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1604543524-31482-1-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,rcar-usb2-clock-sel.txt | 68 -------------- .../clock/renesas,rcar-usb2-clock-sel.yaml | 100 +++++++++++++++++++++ 2 files changed, 100 insertions(+), 68 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt create mode 100644 Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt deleted file mode 100644 index da92f5748dee..000000000000 --- a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt +++ /dev/null @@ -1,68 +0,0 @@ -* Renesas R-Car USB 2.0 clock selector - -This file provides information on what the device node for the R-Car USB 2.0 -clock selector. - -If you connect an external clock to the USB_EXTAL pin only, you should set -the clock rate to "usb_extal" node only. -If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module -is not needed because this is default setting. (Of course, you can set the -clock rates to both "usb_extal" and "usb_xtal" nodes. - -Case 1: An external clock connects to R-Car SoC - +----------+ +--- R-Car ---------------------+ - |External |---|USB_EXTAL ---> all usb channels| - |clock | |USB_XTAL | - +----------+ +-------------------------------+ -In this case, we need this driver with "usb_extal" clock. - -Case 2: An oscillator connects to R-Car SoC - +----------+ +--- R-Car ---------------------+ - |Oscillator|---|USB_EXTAL -+-> all usb channels| - | |---|USB_XTAL --+ | - +----------+ +-------------------------------+ -In this case, we don't need this selector. - -Required properties: -- compatible: "renesas,r8a7795-rcar-usb2-clock-sel" if the device is a part of - an R8A7795 SoC. - "renesas,r8a7796-rcar-usb2-clock-sel" if the device if a part of - an R8A77960 SoC. - "renesas,r8a77961-rcar-usb2-clock-sel" if the device if a part of - an R8A77961 SoC. - "renesas,rcar-gen3-usb2-clock-sel" for a generic R-Car Gen3 - compatible device. - - When compatible with the generic version, nodes must list the - SoC-specific version corresponding to the platform first - followed by the generic version. - -- reg: offset and length of the USB 2.0 clock selector register block. -- clocks: A list of phandles and specifier pairs. -- clock-names: Name of the clocks. - - The functional clock of USB 2.0 host side must be "ehci_ohci" - - The functional clock of HS-USB side must be "hs-usb-if" - - The USB_EXTAL clock pin must be "usb_extal" - - The USB_XTAL clock pin must be "usb_xtal" -- #clock-cells: Must be 0 -- power-domains: A phandle and symbolic PM domain specifier. - See power/renesas,rcar-sysc.yaml. -- resets: A list of phandles and specifier pairs. -- reset-names: Name of the resets. - - The reset of USB 2.0 host side must be "ehci_ohci" - - The reset of HS-USB side must be "hs-usb-if" - -Example (R-Car H3): - - usb2_clksel: clock-controller@e6590630 { - compatible = "renesas,r8a7795-rcar-usb2-clock-sel", - "renesas,rcar-gen3-usb2-clock-sel"; - reg = <0 0xe6590630 0 0x02>; - clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, - <&usb_extal>, <&usb_xtal>; - clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal"; - #clock-cells = <0>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 703>, <&cpg 704>; - reset-names = "ehci_ohci", "hs-usb-if"; - }; diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml new file mode 100644 index 000000000000..5be1229b3d6e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml @@ -0,0 +1,100 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/clock/renesas,rcar-usb2-clock-sel.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas R-Car USB 2.0 clock selector + +maintainers: + - Yoshihiro Shimoda + +description: | + If you connect an external clock to the USB_EXTAL pin only, you should set + the clock rate to "usb_extal" node only. + If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module + is not needed because this is default setting. (Of course, you can set the + clock rates to both "usb_extal" and "usb_xtal" nodes. + + Case 1: An external clock connects to R-Car SoC + +----------+ +--- R-Car ---------------------+ + |External |---|USB_EXTAL ---> all usb channels| + |clock | |USB_XTAL | + +----------+ +-------------------------------+ + + In this case, we need this driver with "usb_extal" clock. + + Case 2: An oscillator connects to R-Car SoC + +----------+ +--- R-Car ---------------------+ + |Oscillator|---|USB_EXTAL -+-> all usb channels| + | |---|USB_XTAL --+ | + +----------+ +-------------------------------+ + In this case, we don't need this selector. + +properties: + compatible: + items: + - enum: + - renesas,r8a7795-rcar-usb2-clock-sel # R-Car H3 + - renesas,r8a7796-rcar-usb2-clock-sel # R-Car M3-W + - renesas,r8a77961-rcar-usb2-clock-sel # R-Car M3-W+ + - const: renesas,rcar-gen3-usb2-clock-sel + + reg: + maxItems: 1 + + clocks: + minItems: 4 + maxItems: 4 + + clock-names: + items: + - const: ehci_ohci + - const: hs-usb-if + - const: usb_extal + - const: usb_xtal + + '#clock-cells': + const: 0 + + power-domains: + maxItems: 1 + + resets: + minItems: 2 + maxItems: 2 + + reset-names: + items: + - const: ehci_ohci + - const: hs-usb-if + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - power-domains + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + + usb2_clksel: clock-controller@e6590630 { + compatible = "renesas,r8a7795-rcar-usb2-clock-sel", + "renesas,rcar-gen3-usb2-clock-sel"; + reg = <0xe6590630 0x02>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, + <&usb_extal>, <&usb_xtal>; + clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal"; + #clock-cells = <0>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 703>, <&cpg 704>; + reset-names = "ehci_ohci", "hs-usb-if"; + }; -- cgit v1.2.3-59-g8ed1b From 6d37a8d192830267e6b10a6d57ae28d2e89097e7 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 10 Dec 2020 10:22:38 -0800 Subject: clk: qcom: gcc-sc7180: Use floor ops for sdcc clks I would repeat the same commit message that was in commit 5e4b7e82d497 ("clk: qcom: gcc-sdm845: Use floor ops for sdcc clks") but it seems silly to do so when you could just go read that commit. NOTE: this is actually extra terrible because we're missing the 50 MHz rate in the table (see the next patch AKA ("clk: qcom: gcc-sc7180: Add 50 MHz clock rate for SDC2")). That means then when you run an older SD card it'll try to clock it at 100 MHz when it's only specced to run at 50 MHz max. As you can probably guess that doesn't work super well. Signed-off-by: Douglas Anderson Fixes: 17269568f726 ("clk: qcom: Add Global Clock controller (GCC) driver for SC7180") Link: https://lore.kernel.org/r/20201210102234.1.I096779f219625148900fc984dd0084ed1ba87c7f@changeid Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sc7180.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/gcc-sc7180.c b/drivers/clk/qcom/gcc-sc7180.c index 68d8f7aaf64e..b080739ab0c3 100644 --- a/drivers/clk/qcom/gcc-sc7180.c +++ b/drivers/clk/qcom/gcc-sc7180.c @@ -642,7 +642,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { .name = "gcc_sdcc1_ice_core_clk_src", .parent_data = gcc_parent_data_0, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; @@ -666,7 +666,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { .name = "gcc_sdcc2_apps_clk_src", .parent_data = gcc_parent_data_5, .num_parents = 5, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; -- cgit v1.2.3-59-g8ed1b From 043577518f027544e8f9e9568140a1fe87ee01a0 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 10 Dec 2020 10:22:39 -0800 Subject: clk: qcom: gcc-sc7180: Add 50 MHz clock rate for SDC2 50 MHz is an incredibly common clock rate for SD cards to run at. It's "high speed" mode in SD (not very fast these days, but it used to be) or: #define HIGH_SPEED_MAX_DTR 50000000 If we don't support this then older "high speed" cards can only run at 25 MHz or at half their normal speed. There doesn't seem to be any reason to skip this clock rate, so add it. Fixes: 17269568f726 ("clk: qcom: Add Global Clock controller (GCC) driver for SC7180") Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20201210102234.2.I26dcc0cee374f5571d9929c9985f463773167e68@changeid Reviewed-by: Bjorn Andersson Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sc7180.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gcc-sc7180.c b/drivers/clk/qcom/gcc-sc7180.c index b080739ab0c3..d82d725ac231 100644 --- a/drivers/clk/qcom/gcc-sc7180.c +++ b/drivers/clk/qcom/gcc-sc7180.c @@ -651,6 +651,7 @@ static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { F(9600000, P_BI_TCXO, 2, 0, 0), F(19200000, P_BI_TCXO, 1, 0, 0), F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0), { } -- cgit v1.2.3-59-g8ed1b From ce8c195e652fa69f669789de37712a519b09155f Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 20 Nov 2020 22:10:17 +0530 Subject: clk: qcom: lpasscc: Introduce pm autosuspend for SC7180 The LPASSCC driver's suspend/resume is invoked multiple number of times and thus allow the device to autosuspend for 500ms. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1605890417-721-1-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/lpasscorecc-sc7180.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c index 9081649f476f..2e0ecc38efdd 100644 --- a/drivers/clk/qcom/lpasscorecc-sc7180.c +++ b/drivers/clk/qcom/lpasscorecc-sc7180.c @@ -370,7 +370,10 @@ static int lpass_create_pm_clks(struct platform_device *pdev) { int ret; + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 500); pm_runtime_enable(&pdev->dev); + ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev); if (ret) return ret; @@ -423,7 +426,12 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) clk_fabia_pll_configure(&lpass_lpaaudio_dig_pll, regmap, &lpass_lpaaudio_dig_pll_config); - return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap); + ret = qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap); + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + + return ret; } static int lpass_hm_core_probe(struct platform_device *pdev) -- cgit v1.2.3-59-g8ed1b From eb50f3f42cb6de3820736206ac5019583f6856b1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 8 Dec 2020 12:16:58 +0530 Subject: dt-bindings: clock: Add RPMHCC bindings for SM8350 Add bindings and update documentation for clock rpmh driver on SM8350. Reviewed-by: Bjorn Andersson Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20201208064702.3654324-2-vkoul@kernel.org Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml index a54930f111ba..12c9cbc0ebf9 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml @@ -22,6 +22,7 @@ properties: - qcom,sdx55-rpmh-clk - qcom,sm8150-rpmh-clk - qcom,sm8250-rpmh-clk + - qcom,sm8350-rpmh-clk clocks: maxItems: 1 -- cgit v1.2.3-59-g8ed1b From f7b36cc19efb4765467af7cce3a91269fbb529b1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 8 Dec 2020 12:16:59 +0530 Subject: clk: qcom: rpmh: add support for SM8350 rpmh clocks This adds the RPMH clocks present in SM8350 SoC Reviewed-by: Bjorn Andersson Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20201208064702.3654324-3-vkoul@kernel.org [sboyd@kernel.org: Move sdx55 to the right place] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpmh.c | 58 +++++++++++++++++++++++++++-------- include/dt-bindings/clock/qcom,rpmh.h | 8 +++++ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index f47595a04885..6a2a13c5058e 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -373,6 +373,25 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = { .num_clks = ARRAY_SIZE(sdm845_rpmh_clocks), }; +DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1); +DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1); +DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0"); + +static struct clk_hw *sdx55_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, + [RPMH_RF_CLK1] = &sdx55_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdx55_rf_clk1_ao.hw, + [RPMH_RF_CLK2] = &sdx55_rf_clk2.hw, + [RPMH_RF_CLK2_A] = &sdx55_rf_clk2_ao.hw, + [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sdx55 = { + .clks = sdx55_rpmh_clocks, + .num_clks = ARRAY_SIZE(sdx55_rpmh_clocks), +}; + static struct clk_hw *sm8150_rpmh_clocks[] = { [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, @@ -434,23 +453,37 @@ static const struct clk_rpmh_desc clk_rpmh_sm8250 = { .num_clks = ARRAY_SIZE(sm8250_rpmh_clocks), }; -DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1); -DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1); -DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0"); +DEFINE_CLK_RPMH_VRM(sm8350, div_clk1, div_clk1_ao, "divclka1", 2); +DEFINE_CLK_RPMH_VRM(sm8350, rf_clk4, rf_clk4_ao, "rfclka4", 1); +DEFINE_CLK_RPMH_VRM(sm8350, rf_clk5, rf_clk5_ao, "rfclka5", 1); +DEFINE_CLK_RPMH_BCM(sm8350, pka, "PKA0"); +DEFINE_CLK_RPMH_BCM(sm8350, hwkm, "HK0"); -static struct clk_hw *sdx55_rpmh_clocks[] = { +static struct clk_hw *sm8350_rpmh_clocks[] = { [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, - [RPMH_RF_CLK1] = &sdx55_rf_clk1.hw, - [RPMH_RF_CLK1_A] = &sdx55_rf_clk1_ao.hw, - [RPMH_RF_CLK2] = &sdx55_rf_clk2.hw, - [RPMH_RF_CLK2_A] = &sdx55_rf_clk2_ao.hw, - [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw, + [RPMH_DIV_CLK1] = &sm8350_div_clk1.hw, + [RPMH_DIV_CLK1_A] = &sm8350_div_clk1_ao.hw, + [RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw, + [RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_ao.hw, + [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw, + [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw, + [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw, + [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw, + [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw, + [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw, + [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw, + [RPMH_RF_CLK5] = &sm8350_rf_clk5.hw, + [RPMH_RF_CLK5_A] = &sm8350_rf_clk5_ao.hw, + [RPMH_IPA_CLK] = &sdm845_ipa.hw, + [RPMH_PKA_CLK] = &sm8350_pka.hw, + [RPMH_HWKM_CLK] = &sm8350_hwkm.hw, }; -static const struct clk_rpmh_desc clk_rpmh_sdx55 = { - .clks = sdx55_rpmh_clocks, - .num_clks = ARRAY_SIZE(sdx55_rpmh_clocks), +static const struct clk_rpmh_desc clk_rpmh_sm8350 = { + .clks = sm8350_rpmh_clocks, + .num_clks = ARRAY_SIZE(sm8350_rpmh_clocks), }; static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, @@ -541,6 +574,7 @@ static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55}, { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150}, { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250}, + { .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350}, { } }; MODULE_DEVICE_TABLE(of, clk_rpmh_match_table); diff --git a/include/dt-bindings/clock/qcom,rpmh.h b/include/dt-bindings/clock/qcom,rpmh.h index 0662a583e93b..583a99161aaa 100644 --- a/include/dt-bindings/clock/qcom,rpmh.h +++ b/include/dt-bindings/clock/qcom,rpmh.h @@ -23,5 +23,13 @@ #define RPMH_LN_BB_CLK1_A 14 #define RPMH_CE_CLK 15 #define RPMH_QPIC_CLK 16 +#define RPMH_DIV_CLK1 17 +#define RPMH_DIV_CLK1_A 18 +#define RPMH_RF_CLK4 19 +#define RPMH_RF_CLK4_A 20 +#define RPMH_RF_CLK5 21 +#define RPMH_RF_CLK5_A 22 +#define RPMH_PKA_CLK 23 +#define RPMH_HWKM_CLK 24 #endif -- cgit v1.2.3-59-g8ed1b