cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-rpmh.c (22434B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/clk-provider.h>
      7#include <linux/err.h>
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/of.h>
     11#include <linux/of_device.h>
     12#include <linux/platform_device.h>
     13#include <soc/qcom/cmd-db.h>
     14#include <soc/qcom/rpmh.h>
     15#include <soc/qcom/tcs.h>
     16
     17#include <dt-bindings/clock/qcom,rpmh.h>
     18
     19#define CLK_RPMH_ARC_EN_OFFSET		0
     20#define CLK_RPMH_VRM_EN_OFFSET		4
     21
     22/**
     23 * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager(BCM)
     24 * @unit: divisor used to convert Hz value to an RPMh msg
     25 * @width: multiplier used to convert Hz value to an RPMh msg
     26 * @vcd: virtual clock domain that this bcm belongs to
     27 * @reserved: reserved to pad the struct
     28 */
     29struct bcm_db {
     30	__le32 unit;
     31	__le16 width;
     32	u8 vcd;
     33	u8 reserved;
     34};
     35
     36/**
     37 * struct clk_rpmh - individual rpmh clock data structure
     38 * @hw:			handle between common and hardware-specific interfaces
     39 * @res_name:		resource name for the rpmh clock
     40 * @div:		clock divider to compute the clock rate
     41 * @res_addr:		base address of the rpmh resource within the RPMh
     42 * @res_on_val:		rpmh clock enable value
     43 * @state:		rpmh clock requested state
     44 * @aggr_state:		rpmh clock aggregated state
     45 * @last_sent_aggr_state: rpmh clock last aggr state sent to RPMh
     46 * @valid_state_mask:	mask to determine the state of the rpmh clock
     47 * @unit:		divisor to convert rate to rpmh msg in magnitudes of Khz
     48 * @dev:		device to which it is attached
     49 * @peer:		pointer to the clock rpmh sibling
     50 */
     51struct clk_rpmh {
     52	struct clk_hw hw;
     53	const char *res_name;
     54	u8 div;
     55	u32 res_addr;
     56	u32 res_on_val;
     57	u32 state;
     58	u32 aggr_state;
     59	u32 last_sent_aggr_state;
     60	u32 valid_state_mask;
     61	u32 unit;
     62	struct device *dev;
     63	struct clk_rpmh *peer;
     64};
     65
     66struct clk_rpmh_desc {
     67	struct clk_hw **clks;
     68	size_t num_clks;
     69};
     70
     71static DEFINE_MUTEX(rpmh_clk_lock);
     72
     73#define __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name,	\
     74			  _res_en_offset, _res_on, _div)		\
     75	static struct clk_rpmh _platform##_##_name_active;		\
     76	static struct clk_rpmh _platform##_##_name = {			\
     77		.res_name = _res_name,					\
     78		.res_addr = _res_en_offset,				\
     79		.res_on_val = _res_on,					\
     80		.div = _div,						\
     81		.peer = &_platform##_##_name_active,			\
     82		.valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) |	\
     83				      BIT(RPMH_ACTIVE_ONLY_STATE) |	\
     84				      BIT(RPMH_SLEEP_STATE)),		\
     85		.hw.init = &(struct clk_init_data){			\
     86			.ops = &clk_rpmh_ops,				\
     87			.name = #_name,					\
     88			.parent_data =  &(const struct clk_parent_data){ \
     89					.fw_name = "xo",		\
     90					.name = "xo_board",		\
     91			},						\
     92			.num_parents = 1,				\
     93		},							\
     94	};								\
     95	static struct clk_rpmh _platform##_##_name_active = {		\
     96		.res_name = _res_name,					\
     97		.res_addr = _res_en_offset,				\
     98		.res_on_val = _res_on,					\
     99		.div = _div,						\
    100		.peer = &_platform##_##_name,				\
    101		.valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) |	\
    102					BIT(RPMH_ACTIVE_ONLY_STATE)),	\
    103		.hw.init = &(struct clk_init_data){			\
    104			.ops = &clk_rpmh_ops,				\
    105			.name = #_name_active,				\
    106			.parent_data =  &(const struct clk_parent_data){ \
    107					.fw_name = "xo",		\
    108					.name = "xo_board",		\
    109			},						\
    110			.num_parents = 1,				\
    111		},							\
    112	}
    113
    114#define DEFINE_CLK_RPMH_ARC(_platform, _name, _name_active, _res_name,	\
    115			    _res_on, _div)				\
    116	__DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name,	\
    117			  CLK_RPMH_ARC_EN_OFFSET, _res_on, _div)
    118
    119#define DEFINE_CLK_RPMH_VRM(_platform, _name, _name_active, _res_name,	\
    120				_div)					\
    121	__DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name,	\
    122			  CLK_RPMH_VRM_EN_OFFSET, 1, _div)
    123
    124#define DEFINE_CLK_RPMH_BCM(_platform, _name, _res_name)		\
    125	static struct clk_rpmh _platform##_##_name = {			\
    126		.res_name = _res_name,					\
    127		.valid_state_mask = BIT(RPMH_ACTIVE_ONLY_STATE),	\
    128		.div = 1,						\
    129		.hw.init = &(struct clk_init_data){			\
    130			.ops = &clk_rpmh_bcm_ops,			\
    131			.name = #_name,					\
    132		},							\
    133	}
    134
    135static inline struct clk_rpmh *to_clk_rpmh(struct clk_hw *_hw)
    136{
    137	return container_of(_hw, struct clk_rpmh, hw);
    138}
    139
    140static inline bool has_state_changed(struct clk_rpmh *c, u32 state)
    141{
    142	return (c->last_sent_aggr_state & BIT(state))
    143		!= (c->aggr_state & BIT(state));
    144}
    145
    146static int clk_rpmh_send(struct clk_rpmh *c, enum rpmh_state state,
    147			 struct tcs_cmd *cmd, bool wait)
    148{
    149	if (wait)
    150		return rpmh_write(c->dev, state, cmd, 1);
    151
    152	return rpmh_write_async(c->dev, state, cmd, 1);
    153}
    154
    155static int clk_rpmh_send_aggregate_command(struct clk_rpmh *c)
    156{
    157	struct tcs_cmd cmd = { 0 };
    158	u32 cmd_state, on_val;
    159	enum rpmh_state state = RPMH_SLEEP_STATE;
    160	int ret;
    161	bool wait;
    162
    163	cmd.addr = c->res_addr;
    164	cmd_state = c->aggr_state;
    165	on_val = c->res_on_val;
    166
    167	for (; state <= RPMH_ACTIVE_ONLY_STATE; state++) {
    168		if (has_state_changed(c, state)) {
    169			if (cmd_state & BIT(state))
    170				cmd.data = on_val;
    171
    172			wait = cmd_state && state == RPMH_ACTIVE_ONLY_STATE;
    173			ret = clk_rpmh_send(c, state, &cmd, wait);
    174			if (ret) {
    175				dev_err(c->dev, "set %s state of %s failed: (%d)\n",
    176					!state ? "sleep" :
    177					state == RPMH_WAKE_ONLY_STATE	?
    178					"wake" : "active", c->res_name, ret);
    179				return ret;
    180			}
    181		}
    182	}
    183
    184	c->last_sent_aggr_state = c->aggr_state;
    185	c->peer->last_sent_aggr_state =  c->last_sent_aggr_state;
    186
    187	return 0;
    188}
    189
    190/*
    191 * Update state and aggregate state values based on enable value.
    192 */
    193static int clk_rpmh_aggregate_state_send_command(struct clk_rpmh *c,
    194						bool enable)
    195{
    196	int ret;
    197
    198	/* Nothing required to be done if already off or on */
    199	if (enable == c->state)
    200		return 0;
    201
    202	c->state = enable ? c->valid_state_mask : 0;
    203	c->aggr_state = c->state | c->peer->state;
    204	c->peer->aggr_state = c->aggr_state;
    205
    206	ret = clk_rpmh_send_aggregate_command(c);
    207	if (!ret)
    208		return 0;
    209
    210	if (ret && enable)
    211		c->state = 0;
    212	else if (ret)
    213		c->state = c->valid_state_mask;
    214
    215	WARN(1, "clk: %s failed to %s\n", c->res_name,
    216	     enable ? "enable" : "disable");
    217	return ret;
    218}
    219
    220static int clk_rpmh_prepare(struct clk_hw *hw)
    221{
    222	struct clk_rpmh *c = to_clk_rpmh(hw);
    223	int ret = 0;
    224
    225	mutex_lock(&rpmh_clk_lock);
    226	ret = clk_rpmh_aggregate_state_send_command(c, true);
    227	mutex_unlock(&rpmh_clk_lock);
    228
    229	return ret;
    230}
    231
    232static void clk_rpmh_unprepare(struct clk_hw *hw)
    233{
    234	struct clk_rpmh *c = to_clk_rpmh(hw);
    235
    236	mutex_lock(&rpmh_clk_lock);
    237	clk_rpmh_aggregate_state_send_command(c, false);
    238	mutex_unlock(&rpmh_clk_lock);
    239};
    240
    241static unsigned long clk_rpmh_recalc_rate(struct clk_hw *hw,
    242					unsigned long prate)
    243{
    244	struct clk_rpmh *r = to_clk_rpmh(hw);
    245
    246	/*
    247	 * RPMh clocks have a fixed rate. Return static rate.
    248	 */
    249	return prate / r->div;
    250}
    251
    252static const struct clk_ops clk_rpmh_ops = {
    253	.prepare	= clk_rpmh_prepare,
    254	.unprepare	= clk_rpmh_unprepare,
    255	.recalc_rate	= clk_rpmh_recalc_rate,
    256};
    257
    258static int clk_rpmh_bcm_send_cmd(struct clk_rpmh *c, bool enable)
    259{
    260	struct tcs_cmd cmd = { 0 };
    261	u32 cmd_state;
    262	int ret = 0;
    263
    264	mutex_lock(&rpmh_clk_lock);
    265	if (enable) {
    266		cmd_state = 1;
    267		if (c->aggr_state)
    268			cmd_state = c->aggr_state;
    269	} else {
    270		cmd_state = 0;
    271	}
    272
    273	if (c->last_sent_aggr_state != cmd_state) {
    274		cmd.addr = c->res_addr;
    275		cmd.data = BCM_TCS_CMD(1, enable, 0, cmd_state);
    276
    277		ret = clk_rpmh_send(c, RPMH_ACTIVE_ONLY_STATE, &cmd, enable);
    278		if (ret) {
    279			dev_err(c->dev, "set active state of %s failed: (%d)\n",
    280				c->res_name, ret);
    281		} else {
    282			c->last_sent_aggr_state = cmd_state;
    283		}
    284	}
    285
    286	mutex_unlock(&rpmh_clk_lock);
    287
    288	return ret;
    289}
    290
    291static int clk_rpmh_bcm_prepare(struct clk_hw *hw)
    292{
    293	struct clk_rpmh *c = to_clk_rpmh(hw);
    294
    295	return clk_rpmh_bcm_send_cmd(c, true);
    296}
    297
    298static void clk_rpmh_bcm_unprepare(struct clk_hw *hw)
    299{
    300	struct clk_rpmh *c = to_clk_rpmh(hw);
    301
    302	clk_rpmh_bcm_send_cmd(c, false);
    303}
    304
    305static int clk_rpmh_bcm_set_rate(struct clk_hw *hw, unsigned long rate,
    306				 unsigned long parent_rate)
    307{
    308	struct clk_rpmh *c = to_clk_rpmh(hw);
    309
    310	c->aggr_state = rate / c->unit;
    311	/*
    312	 * Since any non-zero value sent to hw would result in enabling the
    313	 * clock, only send the value if the clock has already been prepared.
    314	 */
    315	if (clk_hw_is_prepared(hw))
    316		clk_rpmh_bcm_send_cmd(c, true);
    317
    318	return 0;
    319}
    320
    321static long clk_rpmh_round_rate(struct clk_hw *hw, unsigned long rate,
    322				unsigned long *parent_rate)
    323{
    324	return rate;
    325}
    326
    327static unsigned long clk_rpmh_bcm_recalc_rate(struct clk_hw *hw,
    328					unsigned long prate)
    329{
    330	struct clk_rpmh *c = to_clk_rpmh(hw);
    331
    332	return c->aggr_state * c->unit;
    333}
    334
    335static const struct clk_ops clk_rpmh_bcm_ops = {
    336	.prepare	= clk_rpmh_bcm_prepare,
    337	.unprepare	= clk_rpmh_bcm_unprepare,
    338	.set_rate	= clk_rpmh_bcm_set_rate,
    339	.round_rate	= clk_rpmh_round_rate,
    340	.recalc_rate	= clk_rpmh_bcm_recalc_rate,
    341};
    342
    343/* Resource name must match resource id present in cmd-db */
    344DEFINE_CLK_RPMH_ARC(sdm845, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2);
    345DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2);
    346DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
    347DEFINE_CLK_RPMH_VRM(sdm845, rf_clk1, rf_clk1_ao, "rfclka1", 1);
    348DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1);
    349DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1);
    350DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
    351DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
    352DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
    353DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk3, rf_clk3_ao, "rfclkd3", 1);
    354DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk4, rf_clk4_ao, "rfclkd4", 1);
    355DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0");
    356DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0");
    357
    358static struct clk_hw *sdm845_rpmh_clocks[] = {
    359	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    360	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    361	[RPMH_LN_BB_CLK2]	= &sdm845_ln_bb_clk2.hw,
    362	[RPMH_LN_BB_CLK2_A]	= &sdm845_ln_bb_clk2_ao.hw,
    363	[RPMH_LN_BB_CLK3]	= &sdm845_ln_bb_clk3.hw,
    364	[RPMH_LN_BB_CLK3_A]	= &sdm845_ln_bb_clk3_ao.hw,
    365	[RPMH_RF_CLK1]		= &sdm845_rf_clk1.hw,
    366	[RPMH_RF_CLK1_A]	= &sdm845_rf_clk1_ao.hw,
    367	[RPMH_RF_CLK2]		= &sdm845_rf_clk2.hw,
    368	[RPMH_RF_CLK2_A]	= &sdm845_rf_clk2_ao.hw,
    369	[RPMH_RF_CLK3]		= &sdm845_rf_clk3.hw,
    370	[RPMH_RF_CLK3_A]	= &sdm845_rf_clk3_ao.hw,
    371	[RPMH_IPA_CLK]		= &sdm845_ipa.hw,
    372	[RPMH_CE_CLK]		= &sdm845_ce.hw,
    373};
    374
    375static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
    376	.clks = sdm845_rpmh_clocks,
    377	.num_clks = ARRAY_SIZE(sdm845_rpmh_clocks),
    378};
    379
    380DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
    381DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
    382DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0");
    383DEFINE_CLK_RPMH_BCM(sdx55, ipa, "IP0");
    384
    385static struct clk_hw *sdx55_rpmh_clocks[] = {
    386	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    387	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    388	[RPMH_RF_CLK1]		= &sdx55_rf_clk1.hw,
    389	[RPMH_RF_CLK1_A]	= &sdx55_rf_clk1_ao.hw,
    390	[RPMH_RF_CLK2]		= &sdx55_rf_clk2.hw,
    391	[RPMH_RF_CLK2_A]	= &sdx55_rf_clk2_ao.hw,
    392	[RPMH_QPIC_CLK]		= &sdx55_qpic_clk.hw,
    393	[RPMH_IPA_CLK]		= &sdx55_ipa.hw,
    394};
    395
    396static const struct clk_rpmh_desc clk_rpmh_sdx55 = {
    397	.clks = sdx55_rpmh_clocks,
    398	.num_clks = ARRAY_SIZE(sdx55_rpmh_clocks),
    399};
    400
    401static struct clk_hw *sm8150_rpmh_clocks[] = {
    402	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    403	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    404	[RPMH_LN_BB_CLK2]	= &sdm845_ln_bb_clk2.hw,
    405	[RPMH_LN_BB_CLK2_A]	= &sdm845_ln_bb_clk2_ao.hw,
    406	[RPMH_LN_BB_CLK3]	= &sdm845_ln_bb_clk3.hw,
    407	[RPMH_LN_BB_CLK3_A]	= &sdm845_ln_bb_clk3_ao.hw,
    408	[RPMH_RF_CLK1]		= &sdm845_rf_clk1.hw,
    409	[RPMH_RF_CLK1_A]	= &sdm845_rf_clk1_ao.hw,
    410	[RPMH_RF_CLK2]		= &sdm845_rf_clk2.hw,
    411	[RPMH_RF_CLK2_A]	= &sdm845_rf_clk2_ao.hw,
    412	[RPMH_RF_CLK3]		= &sdm845_rf_clk3.hw,
    413	[RPMH_RF_CLK3_A]	= &sdm845_rf_clk3_ao.hw,
    414};
    415
    416static const struct clk_rpmh_desc clk_rpmh_sm8150 = {
    417	.clks = sm8150_rpmh_clocks,
    418	.num_clks = ARRAY_SIZE(sm8150_rpmh_clocks),
    419};
    420
    421static struct clk_hw *sc7180_rpmh_clocks[] = {
    422	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    423	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    424	[RPMH_LN_BB_CLK2]	= &sdm845_ln_bb_clk2.hw,
    425	[RPMH_LN_BB_CLK2_A]	= &sdm845_ln_bb_clk2_ao.hw,
    426	[RPMH_LN_BB_CLK3]	= &sdm845_ln_bb_clk3.hw,
    427	[RPMH_LN_BB_CLK3_A]	= &sdm845_ln_bb_clk3_ao.hw,
    428	[RPMH_RF_CLK1]		= &sdm845_rf_clk1.hw,
    429	[RPMH_RF_CLK1_A]	= &sdm845_rf_clk1_ao.hw,
    430	[RPMH_RF_CLK2]		= &sdm845_rf_clk2.hw,
    431	[RPMH_RF_CLK2_A]	= &sdm845_rf_clk2_ao.hw,
    432	[RPMH_IPA_CLK]		= &sdm845_ipa.hw,
    433};
    434
    435static const struct clk_rpmh_desc clk_rpmh_sc7180 = {
    436	.clks = sc7180_rpmh_clocks,
    437	.num_clks = ARRAY_SIZE(sc7180_rpmh_clocks),
    438};
    439
    440static struct clk_hw *sc8180x_rpmh_clocks[] = {
    441	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    442	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    443	[RPMH_LN_BB_CLK2]	= &sdm845_ln_bb_clk2.hw,
    444	[RPMH_LN_BB_CLK2_A]	= &sdm845_ln_bb_clk2_ao.hw,
    445	[RPMH_LN_BB_CLK3]	= &sdm845_ln_bb_clk3.hw,
    446	[RPMH_LN_BB_CLK3_A]	= &sdm845_ln_bb_clk3_ao.hw,
    447	[RPMH_RF_CLK1]		= &sc8180x_rf_clk1.hw,
    448	[RPMH_RF_CLK1_A]	= &sc8180x_rf_clk1_ao.hw,
    449	[RPMH_RF_CLK2]		= &sc8180x_rf_clk2.hw,
    450	[RPMH_RF_CLK2_A]	= &sc8180x_rf_clk2_ao.hw,
    451	[RPMH_RF_CLK3]		= &sc8180x_rf_clk3.hw,
    452	[RPMH_RF_CLK3_A]	= &sc8180x_rf_clk3_ao.hw,
    453};
    454
    455static const struct clk_rpmh_desc clk_rpmh_sc8180x = {
    456	.clks = sc8180x_rpmh_clocks,
    457	.num_clks = ARRAY_SIZE(sc8180x_rpmh_clocks),
    458};
    459
    460DEFINE_CLK_RPMH_VRM(sm8250, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 2);
    461
    462static struct clk_hw *sm8250_rpmh_clocks[] = {
    463	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    464	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    465	[RPMH_LN_BB_CLK1]	= &sm8250_ln_bb_clk1.hw,
    466	[RPMH_LN_BB_CLK1_A]	= &sm8250_ln_bb_clk1_ao.hw,
    467	[RPMH_LN_BB_CLK2]	= &sdm845_ln_bb_clk2.hw,
    468	[RPMH_LN_BB_CLK2_A]	= &sdm845_ln_bb_clk2_ao.hw,
    469	[RPMH_LN_BB_CLK3]	= &sdm845_ln_bb_clk3.hw,
    470	[RPMH_LN_BB_CLK3_A]	= &sdm845_ln_bb_clk3_ao.hw,
    471	[RPMH_RF_CLK1]		= &sdm845_rf_clk1.hw,
    472	[RPMH_RF_CLK1_A]	= &sdm845_rf_clk1_ao.hw,
    473	[RPMH_RF_CLK3]		= &sdm845_rf_clk3.hw,
    474	[RPMH_RF_CLK3_A]	= &sdm845_rf_clk3_ao.hw,
    475};
    476
    477static const struct clk_rpmh_desc clk_rpmh_sm8250 = {
    478	.clks = sm8250_rpmh_clocks,
    479	.num_clks = ARRAY_SIZE(sm8250_rpmh_clocks),
    480};
    481
    482DEFINE_CLK_RPMH_VRM(sm8350, div_clk1, div_clk1_ao, "divclka1", 2);
    483DEFINE_CLK_RPMH_VRM(sm8350, rf_clk4, rf_clk4_ao, "rfclka4", 1);
    484DEFINE_CLK_RPMH_VRM(sm8350, rf_clk5, rf_clk5_ao, "rfclka5", 1);
    485DEFINE_CLK_RPMH_BCM(sm8350, pka, "PKA0");
    486DEFINE_CLK_RPMH_BCM(sm8350, hwkm, "HK0");
    487
    488static struct clk_hw *sm8350_rpmh_clocks[] = {
    489	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    490	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    491	[RPMH_DIV_CLK1]		= &sm8350_div_clk1.hw,
    492	[RPMH_DIV_CLK1_A]	= &sm8350_div_clk1_ao.hw,
    493	[RPMH_LN_BB_CLK1]	= &sm8250_ln_bb_clk1.hw,
    494	[RPMH_LN_BB_CLK1_A]	= &sm8250_ln_bb_clk1_ao.hw,
    495	[RPMH_LN_BB_CLK2]	= &sdm845_ln_bb_clk2.hw,
    496	[RPMH_LN_BB_CLK2_A]	= &sdm845_ln_bb_clk2_ao.hw,
    497	[RPMH_RF_CLK1]		= &sdm845_rf_clk1.hw,
    498	[RPMH_RF_CLK1_A]	= &sdm845_rf_clk1_ao.hw,
    499	[RPMH_RF_CLK3]		= &sdm845_rf_clk3.hw,
    500	[RPMH_RF_CLK3_A]	= &sdm845_rf_clk3_ao.hw,
    501	[RPMH_RF_CLK4]		= &sm8350_rf_clk4.hw,
    502	[RPMH_RF_CLK4_A]	= &sm8350_rf_clk4_ao.hw,
    503	[RPMH_RF_CLK5]		= &sm8350_rf_clk5.hw,
    504	[RPMH_RF_CLK5_A]	= &sm8350_rf_clk5_ao.hw,
    505	[RPMH_IPA_CLK]		= &sdm845_ipa.hw,
    506	[RPMH_PKA_CLK]		= &sm8350_pka.hw,
    507	[RPMH_HWKM_CLK]		= &sm8350_hwkm.hw,
    508};
    509
    510static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
    511	.clks = sm8350_rpmh_clocks,
    512	.num_clks = ARRAY_SIZE(sm8350_rpmh_clocks),
    513};
    514
    515DEFINE_CLK_RPMH_VRM(sc8280xp, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
    516
    517static struct clk_hw *sc8280xp_rpmh_clocks[] = {
    518	[RPMH_CXO_CLK]		= &sdm845_bi_tcxo.hw,
    519	[RPMH_CXO_CLK_A]	= &sdm845_bi_tcxo_ao.hw,
    520	[RPMH_LN_BB_CLK3]       = &sc8280xp_ln_bb_clk3.hw,
    521	[RPMH_LN_BB_CLK3_A]     = &sc8280xp_ln_bb_clk3_ao.hw,
    522	[RPMH_IPA_CLK]          = &sdm845_ipa.hw,
    523	[RPMH_PKA_CLK]          = &sm8350_pka.hw,
    524	[RPMH_HWKM_CLK]         = &sm8350_hwkm.hw,
    525};
    526
    527static const struct clk_rpmh_desc clk_rpmh_sc8280xp = {
    528	.clks = sc8280xp_rpmh_clocks,
    529	.num_clks = ARRAY_SIZE(sc8280xp_rpmh_clocks),
    530};
    531
    532/* Resource name must match resource id present in cmd-db */
    533DEFINE_CLK_RPMH_ARC(sc7280, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 4);
    534
    535DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
    536DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 4);
    537
    538static struct clk_hw *sm8450_rpmh_clocks[] = {
    539	[RPMH_CXO_CLK]		= &sc7280_bi_tcxo.hw,
    540	[RPMH_CXO_CLK_A]	= &sc7280_bi_tcxo_ao.hw,
    541	[RPMH_LN_BB_CLK1]	= &sm8450_ln_bb_clk1.hw,
    542	[RPMH_LN_BB_CLK1_A]	= &sm8450_ln_bb_clk1_ao.hw,
    543	[RPMH_LN_BB_CLK2]	= &sm8450_ln_bb_clk2.hw,
    544	[RPMH_LN_BB_CLK2_A]	= &sm8450_ln_bb_clk2_ao.hw,
    545	[RPMH_RF_CLK1]		= &sdm845_rf_clk1.hw,
    546	[RPMH_RF_CLK1_A]	= &sdm845_rf_clk1_ao.hw,
    547	[RPMH_RF_CLK2]		= &sdm845_rf_clk2.hw,
    548	[RPMH_RF_CLK2_A]	= &sdm845_rf_clk2_ao.hw,
    549	[RPMH_RF_CLK3]		= &sdm845_rf_clk3.hw,
    550	[RPMH_RF_CLK3_A]	= &sdm845_rf_clk3_ao.hw,
    551	[RPMH_RF_CLK4]		= &sm8350_rf_clk4.hw,
    552	[RPMH_RF_CLK4_A]	= &sm8350_rf_clk4_ao.hw,
    553	[RPMH_IPA_CLK]		= &sdm845_ipa.hw,
    554};
    555
    556static const struct clk_rpmh_desc clk_rpmh_sm8450 = {
    557	.clks = sm8450_rpmh_clocks,
    558	.num_clks = ARRAY_SIZE(sm8450_rpmh_clocks),
    559};
    560
    561static struct clk_hw *sc7280_rpmh_clocks[] = {
    562	[RPMH_CXO_CLK]      = &sc7280_bi_tcxo.hw,
    563	[RPMH_CXO_CLK_A]    = &sc7280_bi_tcxo_ao.hw,
    564	[RPMH_LN_BB_CLK2]   = &sdm845_ln_bb_clk2.hw,
    565	[RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
    566	[RPMH_RF_CLK1]      = &sdm845_rf_clk1.hw,
    567	[RPMH_RF_CLK1_A]    = &sdm845_rf_clk1_ao.hw,
    568	[RPMH_RF_CLK3]      = &sdm845_rf_clk3.hw,
    569	[RPMH_RF_CLK3_A]    = &sdm845_rf_clk3_ao.hw,
    570	[RPMH_RF_CLK4]      = &sm8350_rf_clk4.hw,
    571	[RPMH_RF_CLK4_A]    = &sm8350_rf_clk4_ao.hw,
    572	[RPMH_IPA_CLK]      = &sdm845_ipa.hw,
    573	[RPMH_PKA_CLK]      = &sm8350_pka.hw,
    574	[RPMH_HWKM_CLK]     = &sm8350_hwkm.hw,
    575};
    576
    577static const struct clk_rpmh_desc clk_rpmh_sc7280 = {
    578	.clks = sc7280_rpmh_clocks,
    579	.num_clks = ARRAY_SIZE(sc7280_rpmh_clocks),
    580};
    581
    582DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk2, ln_bb_clk2_ao, "lnbclkg2", 4);
    583DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk3, ln_bb_clk3_ao, "lnbclkg3", 4);
    584DEFINE_CLK_RPMH_ARC(sm6350, qlink, qlink_ao, "qphy.lvl", 0x1, 4);
    585
    586static struct clk_hw *sm6350_rpmh_clocks[] = {
    587	[RPMH_CXO_CLK]		= &sc7280_bi_tcxo.hw,
    588	[RPMH_CXO_CLK_A]	= &sc7280_bi_tcxo_ao.hw,
    589	[RPMH_LN_BB_CLK2]	= &sm6350_ln_bb_clk2.hw,
    590	[RPMH_LN_BB_CLK2_A]	= &sm6350_ln_bb_clk2_ao.hw,
    591	[RPMH_LN_BB_CLK3]	= &sm6350_ln_bb_clk3.hw,
    592	[RPMH_LN_BB_CLK3_A]	= &sm6350_ln_bb_clk3_ao.hw,
    593	[RPMH_QLINK_CLK]	= &sm6350_qlink.hw,
    594	[RPMH_QLINK_CLK_A]	= &sm6350_qlink_ao.hw,
    595};
    596
    597static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
    598	.clks = sm6350_rpmh_clocks,
    599	.num_clks = ARRAY_SIZE(sm6350_rpmh_clocks),
    600};
    601
    602DEFINE_CLK_RPMH_VRM(sdx65, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
    603
    604static struct clk_hw *sdx65_rpmh_clocks[] = {
    605	[RPMH_CXO_CLK]          = &sc7280_bi_tcxo.hw,
    606	[RPMH_CXO_CLK_A]        = &sc7280_bi_tcxo_ao.hw,
    607	[RPMH_LN_BB_CLK1]       = &sdx65_ln_bb_clk1.hw,
    608	[RPMH_LN_BB_CLK1_A]     = &sdx65_ln_bb_clk1_ao.hw,
    609	[RPMH_RF_CLK1]          = &sdm845_rf_clk1.hw,
    610	[RPMH_RF_CLK1_A]        = &sdm845_rf_clk1_ao.hw,
    611	[RPMH_RF_CLK2]          = &sdm845_rf_clk2.hw,
    612	[RPMH_RF_CLK2_A]        = &sdm845_rf_clk2_ao.hw,
    613	[RPMH_RF_CLK3]          = &sdm845_rf_clk3.hw,
    614	[RPMH_RF_CLK3_A]        = &sdm845_rf_clk3_ao.hw,
    615	[RPMH_RF_CLK4]          = &sm8350_rf_clk4.hw,
    616	[RPMH_RF_CLK4_A]        = &sm8350_rf_clk4_ao.hw,
    617	[RPMH_IPA_CLK]          = &sdm845_ipa.hw,
    618	[RPMH_QPIC_CLK]         = &sdx55_qpic_clk.hw,
    619};
    620
    621static const struct clk_rpmh_desc clk_rpmh_sdx65 = {
    622	.clks = sdx65_rpmh_clocks,
    623	.num_clks = ARRAY_SIZE(sdx65_rpmh_clocks),
    624};
    625
    626static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
    627					 void *data)
    628{
    629	struct clk_rpmh_desc *rpmh = data;
    630	unsigned int idx = clkspec->args[0];
    631
    632	if (idx >= rpmh->num_clks) {
    633		pr_err("%s: invalid index %u\n", __func__, idx);
    634		return ERR_PTR(-EINVAL);
    635	}
    636
    637	return rpmh->clks[idx];
    638}
    639
    640static int clk_rpmh_probe(struct platform_device *pdev)
    641{
    642	struct clk_hw **hw_clks;
    643	struct clk_rpmh *rpmh_clk;
    644	const struct clk_rpmh_desc *desc;
    645	int ret, i;
    646
    647	desc = of_device_get_match_data(&pdev->dev);
    648	if (!desc)
    649		return -ENODEV;
    650
    651	hw_clks = desc->clks;
    652
    653	for (i = 0; i < desc->num_clks; i++) {
    654		const char *name;
    655		u32 res_addr;
    656		size_t aux_data_len;
    657		const struct bcm_db *data;
    658
    659		if (!hw_clks[i])
    660			continue;
    661
    662		name = hw_clks[i]->init->name;
    663
    664		rpmh_clk = to_clk_rpmh(hw_clks[i]);
    665		res_addr = cmd_db_read_addr(rpmh_clk->res_name);
    666		if (!res_addr) {
    667			dev_err(&pdev->dev, "missing RPMh resource address for %s\n",
    668				rpmh_clk->res_name);
    669			return -ENODEV;
    670		}
    671
    672		data = cmd_db_read_aux_data(rpmh_clk->res_name, &aux_data_len);
    673		if (IS_ERR(data)) {
    674			ret = PTR_ERR(data);
    675			dev_err(&pdev->dev,
    676				"error reading RPMh aux data for %s (%d)\n",
    677				rpmh_clk->res_name, ret);
    678			return ret;
    679		}
    680
    681		/* Convert unit from Khz to Hz */
    682		if (aux_data_len == sizeof(*data))
    683			rpmh_clk->unit = le32_to_cpu(data->unit) * 1000ULL;
    684
    685		rpmh_clk->res_addr += res_addr;
    686		rpmh_clk->dev = &pdev->dev;
    687
    688		ret = devm_clk_hw_register(&pdev->dev, hw_clks[i]);
    689		if (ret) {
    690			dev_err(&pdev->dev, "failed to register %s\n", name);
    691			return ret;
    692		}
    693	}
    694
    695	/* typecast to silence compiler warning */
    696	ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_rpmh_hw_get,
    697					  (void *)desc);
    698	if (ret) {
    699		dev_err(&pdev->dev, "Failed to add clock provider\n");
    700		return ret;
    701	}
    702
    703	dev_dbg(&pdev->dev, "Registered RPMh clocks\n");
    704
    705	return 0;
    706}
    707
    708static const struct of_device_id clk_rpmh_match_table[] = {
    709	{ .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180},
    710	{ .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
    711	{ .compatible = "qcom,sc8280xp-rpmh-clk", .data = &clk_rpmh_sc8280xp},
    712	{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
    713	{ .compatible = "qcom,sdx55-rpmh-clk",  .data = &clk_rpmh_sdx55},
    714	{ .compatible = "qcom,sdx65-rpmh-clk",  .data = &clk_rpmh_sdx65},
    715	{ .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350},
    716	{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
    717	{ .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
    718	{ .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
    719	{ .compatible = "qcom,sm8450-rpmh-clk", .data = &clk_rpmh_sm8450},
    720	{ .compatible = "qcom,sc7280-rpmh-clk", .data = &clk_rpmh_sc7280},
    721	{ }
    722};
    723MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);
    724
    725static struct platform_driver clk_rpmh_driver = {
    726	.probe		= clk_rpmh_probe,
    727	.driver		= {
    728		.name	= "clk-rpmh",
    729		.of_match_table = clk_rpmh_match_table,
    730	},
    731};
    732
    733static int __init clk_rpmh_init(void)
    734{
    735	return platform_driver_register(&clk_rpmh_driver);
    736}
    737core_initcall(clk_rpmh_init);
    738
    739static void __exit clk_rpmh_exit(void)
    740{
    741	platform_driver_unregister(&clk_rpmh_driver);
    742}
    743module_exit(clk_rpmh_exit);
    744
    745MODULE_DESCRIPTION("QCOM RPMh Clock Driver");
    746MODULE_LICENSE("GPL v2");