From f5edaefee2d621f4e7628f1421c58a2361572d3a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 14 Feb 2018 14:43:40 +0100 Subject: clk: qcom: use divider_ro_round_rate helper There is now an helper function to round the rate when the divider is read-only. Let's use it Signed-off-by: Jerome Brunet Signed-off-by: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-regmap-divider.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers/clk/qcom') diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c index 4e9b8c2c8980..1ee75a5e93f4 100644 --- a/drivers/clk/qcom/clk-regmap-divider.c +++ b/drivers/clk/qcom/clk-regmap-divider.c @@ -28,22 +28,14 @@ static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate, { struct clk_regmap_div *divider = to_clk_regmap_div(hw); struct clk_regmap *clkr = ÷r->clkr; - u32 div; - struct clk_hw *hw_parent = clk_hw_get_parent(hw); - - regmap_read(clkr->regmap, divider->reg, &div); - div >>= divider->shift; - div &= BIT(divider->width) - 1; - div += 1; - - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { - if (!hw_parent) - return -EINVAL; + u32 val; - *prate = clk_hw_round_rate(hw_parent, rate * div); - } + regmap_read(clkr->regmap, divider->reg, &val); + val >>= divider->shift; + val &= BIT(divider->width) - 1; - return DIV_ROUND_UP_ULL((u64)*prate, div); + return divider_ro_round_rate(hw, rate, prate, NULL, divider->width, + CLK_DIVIDER_ROUND_CLOSEST, val); } static long div_round_rate(struct clk_hw *hw, unsigned long rate, -- cgit v1.2.3 From 496037c015079ece7ebc1344fcab80f0618eae5e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 7 Dec 2017 10:59:22 +0000 Subject: clk: qcom: gcc-msm8996: Mark aggre0 noc clks as critical aggre0 bus clks are not associated with any of the drivers, so its important that these clks are always on to get peripherals on this bus working. So mark them as critical. Eventually when we have a proper bus driver these clks can be marked appropriately. Without this patch pcie on db820c is not functional. Signed-off-by: Srinivas Kandagatla Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8996.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/clk/qcom') diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index 5d7451209206..3d6452932797 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -2895,7 +2895,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = { .name = "gcc_aggre0_snoc_axi_clk", .parent_names = (const char *[]){ "system_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -2910,7 +2910,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = { .name = "gcc_aggre0_cnoc_ahb_clk", .parent_names = (const char *[]){ "config_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -2925,7 +2925,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = { .name = "gcc_smmu_aggre0_axi_clk", .parent_names = (const char *[]){ "system_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -2940,7 +2940,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = { .name = "gcc_smmu_aggre0_ahb_clk", .parent_names = (const char *[]){ "config_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, -- cgit v1.2.3 From 91927ff6446c281a3aa5cf8875cf7f0853a2bb55 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 1 Feb 2018 16:33:26 -0800 Subject: clk: qcom: smd-rpm: Migrate to devm_of_clk_add_hw_provider() Signed-off-by: Stephen Boyd Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/clk/qcom') diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index c26d9007bfc4..850c02a52248 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -686,7 +686,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) goto err; } - ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get, + ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get, rcc); if (ret) goto err; @@ -697,19 +697,12 @@ err: return ret; } -static int rpm_smd_clk_remove(struct platform_device *pdev) -{ - of_clk_del_provider(pdev->dev.of_node); - return 0; -} - static struct platform_driver rpm_smd_clk_driver = { .driver = { .name = "qcom-clk-smd-rpm", .of_match_table = rpm_smd_clk_match_table, }, .probe = rpm_smd_clk_probe, - .remove = rpm_smd_clk_remove, }; static int __init rpm_smd_clk_init(void) -- cgit v1.2.3 From 8bcde6582c908bc6567c9d38f7b000d199f7f009 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Sun, 18 Mar 2018 14:44:01 +0000 Subject: clk: qcom: rpmcc: Add support to XO buffered clocks XO is onchip buffer clock to generate 19.2MHz. This patch adds support to 5 XO buffer clocks found on PMIC8921, these buffer clocks can be controlled from external pin or in manual mode. Signed-off-by: Srinivas Kandagatla Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpm.c | 79 +++++++++++++++++++++++++++++++++- include/dt-bindings/clock/qcom,rpmcc.h | 5 +++ 2 files changed, 83 insertions(+), 1 deletion(-) (limited to 'drivers/clk/qcom') diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c index c60f61b10c7f..b94981447664 100644 --- a/drivers/clk/qcom/clk-rpm.c +++ b/drivers/clk/qcom/clk-rpm.c @@ -29,6 +29,7 @@ #define QCOM_RPM_MISC_CLK_TYPE 0x306b6c63 #define QCOM_RPM_SCALING_ENABLE_ID 0x2 +#define QCOM_RPM_XO_MODE_ON 0x2 #define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \ static struct clk_rpm _platform##_##_active; \ @@ -56,6 +57,18 @@ }, \ } +#define DEFINE_CLK_RPM_XO_BUFFER(_platform, _name, _active, offset) \ + static struct clk_rpm _platform##_##_name = { \ + .rpm_clk_id = QCOM_RPM_CXO_BUFFERS, \ + .xo_offset = (offset), \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_rpm_xo_ops, \ + .name = #_name, \ + .parent_names = (const char *[]){ "cxo_board" }, \ + .num_parents = 1, \ + }, \ + } + #define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \ static struct clk_rpm _platform##_##_name = { \ .rpm_clk_id = (r_id), \ @@ -126,8 +139,11 @@ #define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw) +struct rpm_cc; + struct clk_rpm { const int rpm_clk_id; + const int xo_offset; const bool active_only; unsigned long rate; bool enabled; @@ -135,12 +151,15 @@ struct clk_rpm { struct clk_rpm *peer; struct clk_hw hw; struct qcom_rpm *rpm; + struct rpm_cc *rpm_cc; }; struct rpm_cc { struct qcom_rpm *rpm; struct clk_rpm **clks; size_t num_clks; + u32 xo_buffer_value; + struct mutex xo_lock; }; struct rpm_clk_desc { @@ -159,7 +178,8 @@ static int clk_rpm_handoff(struct clk_rpm *r) * The vendor tree simply reads the status for this * RPM clock. */ - if (r->rpm_clk_id == QCOM_RPM_PLL_4) + if (r->rpm_clk_id == QCOM_RPM_PLL_4 || + r->rpm_clk_id == QCOM_RPM_CXO_BUFFERS) return 0; ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, @@ -288,6 +308,46 @@ out: mutex_unlock(&rpm_clk_lock); } +static int clk_rpm_xo_prepare(struct clk_hw *hw) +{ + struct clk_rpm *r = to_clk_rpm(hw); + struct rpm_cc *rcc = r->rpm_cc; + int ret, clk_id = r->rpm_clk_id; + u32 value; + + mutex_lock(&rcc->xo_lock); + + value = rcc->xo_buffer_value | (QCOM_RPM_XO_MODE_ON << r->xo_offset); + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1); + if (!ret) { + r->enabled = true; + rcc->xo_buffer_value = value; + } + + mutex_unlock(&rcc->xo_lock); + + return ret; +} + +static void clk_rpm_xo_unprepare(struct clk_hw *hw) +{ + struct clk_rpm *r = to_clk_rpm(hw); + struct rpm_cc *rcc = r->rpm_cc; + int ret, clk_id = r->rpm_clk_id; + u32 value; + + mutex_lock(&rcc->xo_lock); + + value = rcc->xo_buffer_value & ~(QCOM_RPM_XO_MODE_ON << r->xo_offset); + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1); + if (!ret) { + r->enabled = false; + rcc->xo_buffer_value = value; + } + + mutex_unlock(&rcc->xo_lock); +} + static int clk_rpm_fixed_prepare(struct clk_hw *hw) { struct clk_rpm *r = to_clk_rpm(hw); @@ -378,6 +438,11 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw, return r->rate; } +static const struct clk_ops clk_rpm_xo_ops = { + .prepare = clk_rpm_xo_prepare, + .unprepare = clk_rpm_xo_unprepare, +}; + static const struct clk_ops clk_rpm_fixed_ops = { .prepare = clk_rpm_fixed_prepare, .unprepare = clk_rpm_fixed_unprepare, @@ -449,6 +514,11 @@ DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK); DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK); DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK); DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK); +DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d0_clk, xo_d0_a_clk, 0); +DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d1_clk, xo_d1_a_clk, 8); +DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a0_clk, xo_a0_a_clk, 16); +DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a1_clk, xo_a1_a_clk, 24); +DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a2_clk, xo_a2_a_clk, 28); static struct clk_rpm *apq8064_clks[] = { [RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk, @@ -469,6 +539,11 @@ static struct clk_rpm *apq8064_clks[] = { [RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk, [RPM_QDSS_CLK] = &apq8064_qdss_clk, [RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk, + [RPM_XO_D0] = &apq8064_xo_d0_clk, + [RPM_XO_D1] = &apq8064_xo_d1_clk, + [RPM_XO_A0] = &apq8064_xo_a0_clk, + [RPM_XO_A1] = &apq8064_xo_a1_clk, + [RPM_XO_A2] = &apq8064_xo_a2_clk, }; static const struct rpm_clk_desc rpm_clk_apq8064 = { @@ -526,12 +601,14 @@ static int rpm_clk_probe(struct platform_device *pdev) rcc->clks = rpm_clks; rcc->num_clks = num_clks; + mutex_init(&rcc->xo_lock); for (i = 0; i < num_clks; i++) { if (!rpm_clks[i]) continue; rpm_clks[i]->rpm = rpm; + rpm_clks[i]->rpm_cc = rcc; ret = clk_rpm_handoff(rpm_clks[i]); if (ret) diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index b8337a5fa347..c585b82b9c05 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -40,6 +40,11 @@ #define RPM_SMI_CLK 22 #define RPM_SMI_A_CLK 23 #define RPM_PLL4_CLK 24 +#define RPM_XO_D0 25 +#define RPM_XO_D1 26 +#define RPM_XO_A0 27 +#define RPM_XO_A1 28 +#define RPM_XO_A2 29 /* SMD RPM clocks */ #define RPM_SMD_XO_CLK_SRC 0 -- cgit v1.2.3