Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
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  * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager(BCM)
0024  * @unit: divisor used to convert Hz value to an RPMh msg
0025  * @width: multiplier used to convert Hz value to an RPMh msg
0026  * @vcd: virtual clock domain that this bcm belongs to
0027  * @reserved: reserved to pad the struct
0028  */
0029 struct bcm_db {
0030     __le32 unit;
0031     __le16 width;
0032     u8 vcd;
0033     u8 reserved;
0034 };
0035 
0036 /**
0037  * struct clk_rpmh - individual rpmh clock data structure
0038  * @hw:         handle between common and hardware-specific interfaces
0039  * @res_name:       resource name for the rpmh clock
0040  * @div:        clock divider to compute the clock rate
0041  * @res_addr:       base address of the rpmh resource within the RPMh
0042  * @res_on_val:     rpmh clock enable value
0043  * @state:      rpmh clock requested state
0044  * @aggr_state:     rpmh clock aggregated state
0045  * @last_sent_aggr_state: rpmh clock last aggr state sent to RPMh
0046  * @valid_state_mask:   mask to determine the state of the rpmh clock
0047  * @unit:       divisor to convert rate to rpmh msg in magnitudes of Khz
0048  * @dev:        device to which it is attached
0049  * @peer:       pointer to the clock rpmh sibling
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  * Update state and aggregate state values based on enable value.
0192  */
0193 static int clk_rpmh_aggregate_state_send_command(struct clk_rpmh *c,
0194                         bool enable)
0195 {
0196     int ret;
0197 
0198     /* Nothing required to be done if already off or on */
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      * RPMh clocks have a fixed rate. Return static rate.
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          * Send only an active only state request. RPMh continues to
0279          * use the active state when we're in sleep/wake state as long
0280          * as the sleep/wake state has never been set.
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      * Since any non-zero value sent to hw would result in enabling the
0318      * clock, only send the value if the clock has already been prepared.
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 /* Resource name must match resource id present in cmd-db */
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 /* Resource name must match resource id present in cmd-db */
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         /* Convert unit from Khz to Hz */
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     /* typecast to silence compiler warning */
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");