0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/err.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/platform_device.h>
0013 #include <soc/qcom/cmd-db.h>
0014 #include <soc/qcom/rpmh.h>
0015 #include <soc/qcom/tcs.h>
0016
0017 #include <dt-bindings/clock/qcom,rpmh.h>
0018
0019 #define CLK_RPMH_ARC_EN_OFFSET 0
0020 #define CLK_RPMH_VRM_EN_OFFSET 4
0021
0022
0023
0024
0025
0026
0027
0028
0029 struct bcm_db {
0030 __le32 unit;
0031 __le16 width;
0032 u8 vcd;
0033 u8 reserved;
0034 };
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 struct clk_rpmh {
0052 struct clk_hw hw;
0053 const char *res_name;
0054 u8 div;
0055 u32 res_addr;
0056 u32 res_on_val;
0057 u32 state;
0058 u32 aggr_state;
0059 u32 last_sent_aggr_state;
0060 u32 valid_state_mask;
0061 u32 unit;
0062 struct device *dev;
0063 struct clk_rpmh *peer;
0064 };
0065
0066 struct clk_rpmh_desc {
0067 struct clk_hw **clks;
0068 size_t num_clks;
0069 };
0070
0071 static DEFINE_MUTEX(rpmh_clk_lock);
0072
0073 #define __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
0074 _res_en_offset, _res_on, _div) \
0075 static struct clk_rpmh _platform##_##_name_active; \
0076 static struct clk_rpmh _platform##_##_name = { \
0077 .res_name = _res_name, \
0078 .res_addr = _res_en_offset, \
0079 .res_on_val = _res_on, \
0080 .div = _div, \
0081 .peer = &_platform##_##_name_active, \
0082 .valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) | \
0083 BIT(RPMH_ACTIVE_ONLY_STATE) | \
0084 BIT(RPMH_SLEEP_STATE)), \
0085 .hw.init = &(struct clk_init_data){ \
0086 .ops = &clk_rpmh_ops, \
0087 .name = #_name, \
0088 .parent_data = &(const struct clk_parent_data){ \
0089 .fw_name = "xo", \
0090 .name = "xo_board", \
0091 }, \
0092 .num_parents = 1, \
0093 }, \
0094 }; \
0095 static struct clk_rpmh _platform##_##_name_active = { \
0096 .res_name = _res_name, \
0097 .res_addr = _res_en_offset, \
0098 .res_on_val = _res_on, \
0099 .div = _div, \
0100 .peer = &_platform##_##_name, \
0101 .valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) | \
0102 BIT(RPMH_ACTIVE_ONLY_STATE)), \
0103 .hw.init = &(struct clk_init_data){ \
0104 .ops = &clk_rpmh_ops, \
0105 .name = #_name_active, \
0106 .parent_data = &(const struct clk_parent_data){ \
0107 .fw_name = "xo", \
0108 .name = "xo_board", \
0109 }, \
0110 .num_parents = 1, \
0111 }, \
0112 }
0113
0114 #define DEFINE_CLK_RPMH_ARC(_platform, _name, _name_active, _res_name, \
0115 _res_on, _div) \
0116 __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
0117 CLK_RPMH_ARC_EN_OFFSET, _res_on, _div)
0118
0119 #define DEFINE_CLK_RPMH_VRM(_platform, _name, _name_active, _res_name, \
0120 _div) \
0121 __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
0122 CLK_RPMH_VRM_EN_OFFSET, 1, _div)
0123
0124 #define DEFINE_CLK_RPMH_BCM(_platform, _name, _res_name) \
0125 static struct clk_rpmh _platform##_##_name = { \
0126 .res_name = _res_name, \
0127 .valid_state_mask = BIT(RPMH_ACTIVE_ONLY_STATE), \
0128 .div = 1, \
0129 .hw.init = &(struct clk_init_data){ \
0130 .ops = &clk_rpmh_bcm_ops, \
0131 .name = #_name, \
0132 }, \
0133 }
0134
0135 static inline struct clk_rpmh *to_clk_rpmh(struct clk_hw *_hw)
0136 {
0137 return container_of(_hw, struct clk_rpmh, hw);
0138 }
0139
0140 static inline bool has_state_changed(struct clk_rpmh *c, u32 state)
0141 {
0142 return (c->last_sent_aggr_state & BIT(state))
0143 != (c->aggr_state & BIT(state));
0144 }
0145
0146 static int clk_rpmh_send(struct clk_rpmh *c, enum rpmh_state state,
0147 struct tcs_cmd *cmd, bool wait)
0148 {
0149 if (wait)
0150 return rpmh_write(c->dev, state, cmd, 1);
0151
0152 return rpmh_write_async(c->dev, state, cmd, 1);
0153 }
0154
0155 static int clk_rpmh_send_aggregate_command(struct clk_rpmh *c)
0156 {
0157 struct tcs_cmd cmd = { 0 };
0158 u32 cmd_state, on_val;
0159 enum rpmh_state state = RPMH_SLEEP_STATE;
0160 int ret;
0161 bool wait;
0162
0163 cmd.addr = c->res_addr;
0164 cmd_state = c->aggr_state;
0165 on_val = c->res_on_val;
0166
0167 for (; state <= RPMH_ACTIVE_ONLY_STATE; state++) {
0168 if (has_state_changed(c, state)) {
0169 if (cmd_state & BIT(state))
0170 cmd.data = on_val;
0171
0172 wait = cmd_state && state == RPMH_ACTIVE_ONLY_STATE;
0173 ret = clk_rpmh_send(c, state, &cmd, wait);
0174 if (ret) {
0175 dev_err(c->dev, "set %s state of %s failed: (%d)\n",
0176 !state ? "sleep" :
0177 state == RPMH_WAKE_ONLY_STATE ?
0178 "wake" : "active", c->res_name, ret);
0179 return ret;
0180 }
0181 }
0182 }
0183
0184 c->last_sent_aggr_state = c->aggr_state;
0185 c->peer->last_sent_aggr_state = c->last_sent_aggr_state;
0186
0187 return 0;
0188 }
0189
0190
0191
0192
0193 static int clk_rpmh_aggregate_state_send_command(struct clk_rpmh *c,
0194 bool enable)
0195 {
0196 int ret;
0197
0198
0199 if (enable == c->state)
0200 return 0;
0201
0202 c->state = enable ? c->valid_state_mask : 0;
0203 c->aggr_state = c->state | c->peer->state;
0204 c->peer->aggr_state = c->aggr_state;
0205
0206 ret = clk_rpmh_send_aggregate_command(c);
0207 if (!ret)
0208 return 0;
0209
0210 if (ret && enable)
0211 c->state = 0;
0212 else if (ret)
0213 c->state = c->valid_state_mask;
0214
0215 WARN(1, "clk: %s failed to %s\n", c->res_name,
0216 enable ? "enable" : "disable");
0217 return ret;
0218 }
0219
0220 static int clk_rpmh_prepare(struct clk_hw *hw)
0221 {
0222 struct clk_rpmh *c = to_clk_rpmh(hw);
0223 int ret = 0;
0224
0225 mutex_lock(&rpmh_clk_lock);
0226 ret = clk_rpmh_aggregate_state_send_command(c, true);
0227 mutex_unlock(&rpmh_clk_lock);
0228
0229 return ret;
0230 }
0231
0232 static void clk_rpmh_unprepare(struct clk_hw *hw)
0233 {
0234 struct clk_rpmh *c = to_clk_rpmh(hw);
0235
0236 mutex_lock(&rpmh_clk_lock);
0237 clk_rpmh_aggregate_state_send_command(c, false);
0238 mutex_unlock(&rpmh_clk_lock);
0239 };
0240
0241 static unsigned long clk_rpmh_recalc_rate(struct clk_hw *hw,
0242 unsigned long prate)
0243 {
0244 struct clk_rpmh *r = to_clk_rpmh(hw);
0245
0246
0247
0248
0249 return prate / r->div;
0250 }
0251
0252 static const struct clk_ops clk_rpmh_ops = {
0253 .prepare = clk_rpmh_prepare,
0254 .unprepare = clk_rpmh_unprepare,
0255 .recalc_rate = clk_rpmh_recalc_rate,
0256 };
0257
0258 static int clk_rpmh_bcm_send_cmd(struct clk_rpmh *c, bool enable)
0259 {
0260 struct tcs_cmd cmd = { 0 };
0261 u32 cmd_state;
0262 int ret = 0;
0263
0264 mutex_lock(&rpmh_clk_lock);
0265 if (enable) {
0266 cmd_state = 1;
0267 if (c->aggr_state)
0268 cmd_state = c->aggr_state;
0269 } else {
0270 cmd_state = 0;
0271 }
0272
0273 if (c->last_sent_aggr_state != cmd_state) {
0274 cmd.addr = c->res_addr;
0275 cmd.data = BCM_TCS_CMD(1, enable, 0, cmd_state);
0276
0277
0278
0279
0280
0281
0282 ret = clk_rpmh_send(c, RPMH_ACTIVE_ONLY_STATE, &cmd, enable);
0283 if (ret) {
0284 dev_err(c->dev, "set active state of %s failed: (%d)\n",
0285 c->res_name, ret);
0286 } else {
0287 c->last_sent_aggr_state = cmd_state;
0288 }
0289 }
0290
0291 mutex_unlock(&rpmh_clk_lock);
0292
0293 return ret;
0294 }
0295
0296 static int clk_rpmh_bcm_prepare(struct clk_hw *hw)
0297 {
0298 struct clk_rpmh *c = to_clk_rpmh(hw);
0299
0300 return clk_rpmh_bcm_send_cmd(c, true);
0301 }
0302
0303 static void clk_rpmh_bcm_unprepare(struct clk_hw *hw)
0304 {
0305 struct clk_rpmh *c = to_clk_rpmh(hw);
0306
0307 clk_rpmh_bcm_send_cmd(c, false);
0308 }
0309
0310 static int clk_rpmh_bcm_set_rate(struct clk_hw *hw, unsigned long rate,
0311 unsigned long parent_rate)
0312 {
0313 struct clk_rpmh *c = to_clk_rpmh(hw);
0314
0315 c->aggr_state = rate / c->unit;
0316
0317
0318
0319
0320 if (clk_hw_is_prepared(hw))
0321 clk_rpmh_bcm_send_cmd(c, true);
0322
0323 return 0;
0324 }
0325
0326 static long clk_rpmh_round_rate(struct clk_hw *hw, unsigned long rate,
0327 unsigned long *parent_rate)
0328 {
0329 return rate;
0330 }
0331
0332 static unsigned long clk_rpmh_bcm_recalc_rate(struct clk_hw *hw,
0333 unsigned long prate)
0334 {
0335 struct clk_rpmh *c = to_clk_rpmh(hw);
0336
0337 return c->aggr_state * c->unit;
0338 }
0339
0340 static const struct clk_ops clk_rpmh_bcm_ops = {
0341 .prepare = clk_rpmh_bcm_prepare,
0342 .unprepare = clk_rpmh_bcm_unprepare,
0343 .set_rate = clk_rpmh_bcm_set_rate,
0344 .round_rate = clk_rpmh_round_rate,
0345 .recalc_rate = clk_rpmh_bcm_recalc_rate,
0346 };
0347
0348
0349 DEFINE_CLK_RPMH_ARC(sdm845, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2);
0350 DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2);
0351 DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
0352 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk1, rf_clk1_ao, "rfclka1", 1);
0353 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1);
0354 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1);
0355 DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
0356 DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
0357 DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
0358 DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk3, rf_clk3_ao, "rfclkd3", 1);
0359 DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk4, rf_clk4_ao, "rfclkd4", 1);
0360 DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0");
0361 DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0");
0362
0363 static struct clk_hw *sdm845_rpmh_clocks[] = {
0364 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0365 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0366 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0367 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0368 [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
0369 [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
0370 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0371 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0372 [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
0373 [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
0374 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0375 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0376 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0377 [RPMH_CE_CLK] = &sdm845_ce.hw,
0378 };
0379
0380 static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
0381 .clks = sdm845_rpmh_clocks,
0382 .num_clks = ARRAY_SIZE(sdm845_rpmh_clocks),
0383 };
0384
0385 DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
0386 DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
0387 DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0");
0388 DEFINE_CLK_RPMH_BCM(sdx55, ipa, "IP0");
0389
0390 static struct clk_hw *sdx55_rpmh_clocks[] = {
0391 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0392 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0393 [RPMH_RF_CLK1] = &sdx55_rf_clk1.hw,
0394 [RPMH_RF_CLK1_A] = &sdx55_rf_clk1_ao.hw,
0395 [RPMH_RF_CLK2] = &sdx55_rf_clk2.hw,
0396 [RPMH_RF_CLK2_A] = &sdx55_rf_clk2_ao.hw,
0397 [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
0398 [RPMH_IPA_CLK] = &sdx55_ipa.hw,
0399 };
0400
0401 static const struct clk_rpmh_desc clk_rpmh_sdx55 = {
0402 .clks = sdx55_rpmh_clocks,
0403 .num_clks = ARRAY_SIZE(sdx55_rpmh_clocks),
0404 };
0405
0406 static struct clk_hw *sm8150_rpmh_clocks[] = {
0407 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0408 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0409 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0410 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0411 [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
0412 [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
0413 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0414 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0415 [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
0416 [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
0417 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0418 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0419 };
0420
0421 static const struct clk_rpmh_desc clk_rpmh_sm8150 = {
0422 .clks = sm8150_rpmh_clocks,
0423 .num_clks = ARRAY_SIZE(sm8150_rpmh_clocks),
0424 };
0425
0426 static struct clk_hw *sc7180_rpmh_clocks[] = {
0427 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0428 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0429 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0430 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0431 [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
0432 [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
0433 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0434 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0435 [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
0436 [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
0437 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0438 };
0439
0440 static const struct clk_rpmh_desc clk_rpmh_sc7180 = {
0441 .clks = sc7180_rpmh_clocks,
0442 .num_clks = ARRAY_SIZE(sc7180_rpmh_clocks),
0443 };
0444
0445 static struct clk_hw *sc8180x_rpmh_clocks[] = {
0446 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0447 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0448 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0449 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0450 [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
0451 [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
0452 [RPMH_RF_CLK1] = &sc8180x_rf_clk1.hw,
0453 [RPMH_RF_CLK1_A] = &sc8180x_rf_clk1_ao.hw,
0454 [RPMH_RF_CLK2] = &sc8180x_rf_clk2.hw,
0455 [RPMH_RF_CLK2_A] = &sc8180x_rf_clk2_ao.hw,
0456 [RPMH_RF_CLK3] = &sc8180x_rf_clk3.hw,
0457 [RPMH_RF_CLK3_A] = &sc8180x_rf_clk3_ao.hw,
0458 };
0459
0460 static const struct clk_rpmh_desc clk_rpmh_sc8180x = {
0461 .clks = sc8180x_rpmh_clocks,
0462 .num_clks = ARRAY_SIZE(sc8180x_rpmh_clocks),
0463 };
0464
0465 DEFINE_CLK_RPMH_VRM(sm8250, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 2);
0466
0467 static struct clk_hw *sm8250_rpmh_clocks[] = {
0468 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0469 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0470 [RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw,
0471 [RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_ao.hw,
0472 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0473 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0474 [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
0475 [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
0476 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0477 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0478 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0479 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0480 };
0481
0482 static const struct clk_rpmh_desc clk_rpmh_sm8250 = {
0483 .clks = sm8250_rpmh_clocks,
0484 .num_clks = ARRAY_SIZE(sm8250_rpmh_clocks),
0485 };
0486
0487 DEFINE_CLK_RPMH_VRM(sm8350, div_clk1, div_clk1_ao, "divclka1", 2);
0488 DEFINE_CLK_RPMH_VRM(sm8350, rf_clk4, rf_clk4_ao, "rfclka4", 1);
0489 DEFINE_CLK_RPMH_VRM(sm8350, rf_clk5, rf_clk5_ao, "rfclka5", 1);
0490 DEFINE_CLK_RPMH_BCM(sm8350, pka, "PKA0");
0491 DEFINE_CLK_RPMH_BCM(sm8350, hwkm, "HK0");
0492
0493 static struct clk_hw *sm8350_rpmh_clocks[] = {
0494 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0495 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0496 [RPMH_DIV_CLK1] = &sm8350_div_clk1.hw,
0497 [RPMH_DIV_CLK1_A] = &sm8350_div_clk1_ao.hw,
0498 [RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw,
0499 [RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_ao.hw,
0500 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0501 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0502 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0503 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0504 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0505 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0506 [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
0507 [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
0508 [RPMH_RF_CLK5] = &sm8350_rf_clk5.hw,
0509 [RPMH_RF_CLK5_A] = &sm8350_rf_clk5_ao.hw,
0510 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0511 [RPMH_PKA_CLK] = &sm8350_pka.hw,
0512 [RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
0513 };
0514
0515 static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
0516 .clks = sm8350_rpmh_clocks,
0517 .num_clks = ARRAY_SIZE(sm8350_rpmh_clocks),
0518 };
0519
0520 DEFINE_CLK_RPMH_VRM(sc8280xp, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
0521
0522 static struct clk_hw *sc8280xp_rpmh_clocks[] = {
0523 [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
0524 [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
0525 [RPMH_LN_BB_CLK3] = &sc8280xp_ln_bb_clk3.hw,
0526 [RPMH_LN_BB_CLK3_A] = &sc8280xp_ln_bb_clk3_ao.hw,
0527 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0528 [RPMH_PKA_CLK] = &sm8350_pka.hw,
0529 [RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
0530 };
0531
0532 static const struct clk_rpmh_desc clk_rpmh_sc8280xp = {
0533 .clks = sc8280xp_rpmh_clocks,
0534 .num_clks = ARRAY_SIZE(sc8280xp_rpmh_clocks),
0535 };
0536
0537
0538 DEFINE_CLK_RPMH_ARC(sc7280, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 4);
0539
0540 DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
0541 DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 4);
0542
0543 static struct clk_hw *sm8450_rpmh_clocks[] = {
0544 [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
0545 [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
0546 [RPMH_LN_BB_CLK1] = &sm8450_ln_bb_clk1.hw,
0547 [RPMH_LN_BB_CLK1_A] = &sm8450_ln_bb_clk1_ao.hw,
0548 [RPMH_LN_BB_CLK2] = &sm8450_ln_bb_clk2.hw,
0549 [RPMH_LN_BB_CLK2_A] = &sm8450_ln_bb_clk2_ao.hw,
0550 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0551 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0552 [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
0553 [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
0554 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0555 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0556 [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
0557 [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
0558 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0559 };
0560
0561 static const struct clk_rpmh_desc clk_rpmh_sm8450 = {
0562 .clks = sm8450_rpmh_clocks,
0563 .num_clks = ARRAY_SIZE(sm8450_rpmh_clocks),
0564 };
0565
0566 static struct clk_hw *sc7280_rpmh_clocks[] = {
0567 [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
0568 [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
0569 [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
0570 [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
0571 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0572 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0573 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0574 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0575 [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
0576 [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
0577 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0578 [RPMH_PKA_CLK] = &sm8350_pka.hw,
0579 [RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
0580 };
0581
0582 static const struct clk_rpmh_desc clk_rpmh_sc7280 = {
0583 .clks = sc7280_rpmh_clocks,
0584 .num_clks = ARRAY_SIZE(sc7280_rpmh_clocks),
0585 };
0586
0587 DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk2, ln_bb_clk2_ao, "lnbclkg2", 4);
0588 DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk3, ln_bb_clk3_ao, "lnbclkg3", 4);
0589 DEFINE_CLK_RPMH_ARC(sm6350, qlink, qlink_ao, "qphy.lvl", 0x1, 4);
0590
0591 static struct clk_hw *sm6350_rpmh_clocks[] = {
0592 [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
0593 [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
0594 [RPMH_LN_BB_CLK2] = &sm6350_ln_bb_clk2.hw,
0595 [RPMH_LN_BB_CLK2_A] = &sm6350_ln_bb_clk2_ao.hw,
0596 [RPMH_LN_BB_CLK3] = &sm6350_ln_bb_clk3.hw,
0597 [RPMH_LN_BB_CLK3_A] = &sm6350_ln_bb_clk3_ao.hw,
0598 [RPMH_QLINK_CLK] = &sm6350_qlink.hw,
0599 [RPMH_QLINK_CLK_A] = &sm6350_qlink_ao.hw,
0600 };
0601
0602 static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
0603 .clks = sm6350_rpmh_clocks,
0604 .num_clks = ARRAY_SIZE(sm6350_rpmh_clocks),
0605 };
0606
0607 DEFINE_CLK_RPMH_VRM(sdx65, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
0608
0609 static struct clk_hw *sdx65_rpmh_clocks[] = {
0610 [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
0611 [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
0612 [RPMH_LN_BB_CLK1] = &sdx65_ln_bb_clk1.hw,
0613 [RPMH_LN_BB_CLK1_A] = &sdx65_ln_bb_clk1_ao.hw,
0614 [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
0615 [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
0616 [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
0617 [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
0618 [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
0619 [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
0620 [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
0621 [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
0622 [RPMH_IPA_CLK] = &sdm845_ipa.hw,
0623 [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
0624 };
0625
0626 static const struct clk_rpmh_desc clk_rpmh_sdx65 = {
0627 .clks = sdx65_rpmh_clocks,
0628 .num_clks = ARRAY_SIZE(sdx65_rpmh_clocks),
0629 };
0630
0631 static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
0632 void *data)
0633 {
0634 struct clk_rpmh_desc *rpmh = data;
0635 unsigned int idx = clkspec->args[0];
0636
0637 if (idx >= rpmh->num_clks) {
0638 pr_err("%s: invalid index %u\n", __func__, idx);
0639 return ERR_PTR(-EINVAL);
0640 }
0641
0642 return rpmh->clks[idx];
0643 }
0644
0645 static int clk_rpmh_probe(struct platform_device *pdev)
0646 {
0647 struct clk_hw **hw_clks;
0648 struct clk_rpmh *rpmh_clk;
0649 const struct clk_rpmh_desc *desc;
0650 int ret, i;
0651
0652 desc = of_device_get_match_data(&pdev->dev);
0653 if (!desc)
0654 return -ENODEV;
0655
0656 hw_clks = desc->clks;
0657
0658 for (i = 0; i < desc->num_clks; i++) {
0659 const char *name;
0660 u32 res_addr;
0661 size_t aux_data_len;
0662 const struct bcm_db *data;
0663
0664 if (!hw_clks[i])
0665 continue;
0666
0667 name = hw_clks[i]->init->name;
0668
0669 rpmh_clk = to_clk_rpmh(hw_clks[i]);
0670 res_addr = cmd_db_read_addr(rpmh_clk->res_name);
0671 if (!res_addr) {
0672 dev_err(&pdev->dev, "missing RPMh resource address for %s\n",
0673 rpmh_clk->res_name);
0674 return -ENODEV;
0675 }
0676
0677 data = cmd_db_read_aux_data(rpmh_clk->res_name, &aux_data_len);
0678 if (IS_ERR(data)) {
0679 ret = PTR_ERR(data);
0680 dev_err(&pdev->dev,
0681 "error reading RPMh aux data for %s (%d)\n",
0682 rpmh_clk->res_name, ret);
0683 return ret;
0684 }
0685
0686
0687 if (aux_data_len == sizeof(*data))
0688 rpmh_clk->unit = le32_to_cpu(data->unit) * 1000ULL;
0689
0690 rpmh_clk->res_addr += res_addr;
0691 rpmh_clk->dev = &pdev->dev;
0692
0693 ret = devm_clk_hw_register(&pdev->dev, hw_clks[i]);
0694 if (ret) {
0695 dev_err(&pdev->dev, "failed to register %s\n", name);
0696 return ret;
0697 }
0698 }
0699
0700
0701 ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_rpmh_hw_get,
0702 (void *)desc);
0703 if (ret) {
0704 dev_err(&pdev->dev, "Failed to add clock provider\n");
0705 return ret;
0706 }
0707
0708 dev_dbg(&pdev->dev, "Registered RPMh clocks\n");
0709
0710 return 0;
0711 }
0712
0713 static const struct of_device_id clk_rpmh_match_table[] = {
0714 { .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180},
0715 { .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
0716 { .compatible = "qcom,sc8280xp-rpmh-clk", .data = &clk_rpmh_sc8280xp},
0717 { .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
0718 { .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55},
0719 { .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65},
0720 { .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
0721 { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
0722 { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
0723 { .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
0724 { .compatible = "qcom,sm8450-rpmh-clk", .data = &clk_rpmh_sm8450},
0725 { .compatible = "qcom,sc7280-rpmh-clk", .data = &clk_rpmh_sc7280},
0726 { }
0727 };
0728 MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);
0729
0730 static struct platform_driver clk_rpmh_driver = {
0731 .probe = clk_rpmh_probe,
0732 .driver = {
0733 .name = "clk-rpmh",
0734 .of_match_table = clk_rpmh_match_table,
0735 },
0736 };
0737
0738 static int __init clk_rpmh_init(void)
0739 {
0740 return platform_driver_register(&clk_rpmh_driver);
0741 }
0742 core_initcall(clk_rpmh_init);
0743
0744 static void __exit clk_rpmh_exit(void)
0745 {
0746 platform_driver_unregister(&clk_rpmh_driver);
0747 }
0748 module_exit(clk_rpmh_exit);
0749
0750 MODULE_DESCRIPTION("QCOM RPMh Clock Driver");
0751 MODULE_LICENSE("GPL v2");