|
9 | 9 | #include <linux/clk-provider.h>
|
10 | 10 | #include <linux/regmap.h>
|
11 | 11 | #include <linux/module.h>
|
| 12 | +#include <linux/clk.h> |
| 13 | +#include <linux/soc/qcom/smem.h> |
12 | 14 |
|
13 | 15 | #include <dt-bindings/clock/qcom,apss-ipq.h>
|
| 16 | +#include <dt-bindings/arm/qcom,ids.h> |
14 | 17 |
|
15 | 18 | #include "common.h"
|
16 | 19 | #include "clk-regmap.h"
|
@@ -81,15 +84,68 @@ static const struct qcom_cc_desc apss_ipq6018_desc = {
|
81 | 84 | .num_clks = ARRAY_SIZE(apss_ipq6018_clks),
|
82 | 85 | };
|
83 | 86 |
|
| 87 | +static int cpu_clk_notifier_fn(struct notifier_block *nb, unsigned long action, |
| 88 | + void *data) |
| 89 | +{ |
| 90 | + struct clk_hw *hw; |
| 91 | + u8 index; |
| 92 | + int err; |
| 93 | + |
| 94 | + if (action == PRE_RATE_CHANGE) |
| 95 | + index = P_GPLL0; |
| 96 | + else if (action == POST_RATE_CHANGE || action == ABORT_RATE_CHANGE) |
| 97 | + index = P_APSS_PLL_EARLY; |
| 98 | + else |
| 99 | + return NOTIFY_OK; |
| 100 | + |
| 101 | + hw = &apcs_alias0_clk_src.clkr.hw; |
| 102 | + err = clk_rcg2_mux_closest_ops.set_parent(hw, index); |
| 103 | + |
| 104 | + return notifier_from_errno(err); |
| 105 | +} |
| 106 | + |
84 | 107 | static int apss_ipq6018_probe(struct platform_device *pdev)
|
85 | 108 | {
|
| 109 | + struct clk_hw *hw = &apcs_alias0_clk_src.clkr.hw; |
| 110 | + struct notifier_block *cpu_clk_notifier; |
86 | 111 | struct regmap *regmap;
|
| 112 | + u32 soc_id; |
| 113 | + int ret; |
| 114 | + |
| 115 | + ret = qcom_smem_get_soc_id(&soc_id); |
| 116 | + if (ret) |
| 117 | + return ret; |
87 | 118 |
|
88 | 119 | regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
89 | 120 | if (!regmap)
|
90 | 121 | return -ENODEV;
|
91 | 122 |
|
92 |
| - return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); |
| 123 | + ret = qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); |
| 124 | + if (ret) |
| 125 | + return ret; |
| 126 | + |
| 127 | + switch (soc_id) { |
| 128 | + /* Only below variants of IPQ53xx support scaling */ |
| 129 | + case QCOM_ID_IPQ5332: |
| 130 | + case QCOM_ID_IPQ5322: |
| 131 | + case QCOM_ID_IPQ5300: |
| 132 | + cpu_clk_notifier = devm_kzalloc(&pdev->dev, |
| 133 | + sizeof(*cpu_clk_notifier), |
| 134 | + GFP_KERNEL); |
| 135 | + if (!cpu_clk_notifier) |
| 136 | + return -ENOMEM; |
| 137 | + |
| 138 | + cpu_clk_notifier->notifier_call = cpu_clk_notifier_fn; |
| 139 | + |
| 140 | + ret = devm_clk_notifier_register(&pdev->dev, hw->clk, cpu_clk_notifier); |
| 141 | + if (ret) |
| 142 | + return ret; |
| 143 | + break; |
| 144 | + default: |
| 145 | + break; |
| 146 | + } |
| 147 | + |
| 148 | + return 0; |
93 | 149 | }
|
94 | 150 |
|
95 | 151 | static struct platform_driver apss_ipq6018_driver = {
|
|
0 commit comments