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

rpmpd.c (19291B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
      3
      4#include <linux/err.h>
      5#include <linux/init.h>
      6#include <linux/kernel.h>
      7#include <linux/module.h>
      8#include <linux/mutex.h>
      9#include <linux/pm_domain.h>
     10#include <linux/of.h>
     11#include <linux/of_device.h>
     12#include <linux/platform_device.h>
     13#include <linux/pm_opp.h>
     14#include <linux/soc/qcom/smd-rpm.h>
     15
     16#include <dt-bindings/power/qcom-rpmpd.h>
     17
     18#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
     19
     20/* Resource types:
     21 * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
     22#define RPMPD_SMPA 0x61706d73
     23#define RPMPD_LDOA 0x616f646c
     24#define RPMPD_SMPB 0x62706d73
     25#define RPMPD_LDOB 0x626f646c
     26#define RPMPD_RWCX 0x78637772
     27#define RPMPD_RWMX 0x786d7772
     28#define RPMPD_RWLC 0x636c7772
     29#define RPMPD_RWLM 0x6d6c7772
     30#define RPMPD_RWSC 0x63737772
     31#define RPMPD_RWSM 0x6d737772
     32
     33/* Operation Keys */
     34#define KEY_CORNER		0x6e726f63 /* corn */
     35#define KEY_ENABLE		0x6e657773 /* swen */
     36#define KEY_FLOOR_CORNER	0x636676   /* vfc */
     37#define KEY_FLOOR_LEVEL		0x6c6676   /* vfl */
     38#define KEY_LEVEL		0x6c766c76 /* vlvl */
     39
     40#define MAX_CORNER_RPMPD_STATE	6
     41
     42#define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key,	\
     43			  r_id)						\
     44	static struct rpmpd _platform##_##_active;			\
     45	static struct rpmpd _platform##_##_name = {			\
     46		.pd = {	.name = #_name,	},				\
     47		.peer = &_platform##_##_active,				\
     48		.res_type = RPMPD_##r_type,				\
     49		.res_id = r_id,						\
     50		.key = KEY_##r_key,					\
     51	};								\
     52	static struct rpmpd _platform##_##_active = {			\
     53		.pd = { .name = #_active, },				\
     54		.peer = &_platform##_##_name,				\
     55		.active_only = true,					\
     56		.res_type = RPMPD_##r_type,				\
     57		.res_id = r_id,						\
     58		.key = KEY_##r_key,					\
     59	}
     60
     61#define DEFINE_RPMPD_CORNER(_platform, _name, r_type, r_id)		\
     62	static struct rpmpd _platform##_##_name = {			\
     63		.pd = { .name = #_name, },				\
     64		.res_type = RPMPD_##r_type,				\
     65		.res_id = r_id,						\
     66		.key = KEY_CORNER,					\
     67	}
     68
     69#define DEFINE_RPMPD_LEVEL(_platform, _name, r_type, r_id)		\
     70	static struct rpmpd _platform##_##_name = {			\
     71		.pd = { .name = #_name, },				\
     72		.res_type = RPMPD_##r_type,				\
     73		.res_id = r_id,						\
     74		.key = KEY_LEVEL,					\
     75	}
     76
     77#define DEFINE_RPMPD_VFC(_platform, _name, r_type, r_id)		\
     78	static struct rpmpd _platform##_##_name = {			\
     79		.pd = { .name = #_name, },				\
     80		.res_type = RPMPD_##r_type,				\
     81		.res_id = r_id,						\
     82		.key = KEY_FLOOR_CORNER,				\
     83	}
     84
     85#define DEFINE_RPMPD_VFL(_platform, _name, r_type, r_id)		\
     86	static struct rpmpd _platform##_##_name = {			\
     87		.pd = { .name = #_name, },				\
     88		.res_type = RPMPD_##r_type,				\
     89		.res_id = r_id,						\
     90		.key = KEY_FLOOR_LEVEL,					\
     91	}
     92
     93struct rpmpd_req {
     94	__le32 key;
     95	__le32 nbytes;
     96	__le32 value;
     97};
     98
     99struct rpmpd {
    100	struct generic_pm_domain pd;
    101	struct rpmpd *peer;
    102	const bool active_only;
    103	unsigned int corner;
    104	bool enabled;
    105	const int res_type;
    106	const int res_id;
    107	struct qcom_smd_rpm *rpm;
    108	unsigned int max_state;
    109	__le32 key;
    110};
    111
    112struct rpmpd_desc {
    113	struct rpmpd **rpmpds;
    114	size_t num_pds;
    115	unsigned int max_state;
    116};
    117
    118static DEFINE_MUTEX(rpmpd_lock);
    119
    120/* mdm9607 RPM Power Domains */
    121DEFINE_RPMPD_PAIR(mdm9607, vddcx, vddcx_ao, SMPA, LEVEL, 3);
    122DEFINE_RPMPD_VFL(mdm9607, vddcx_vfl, SMPA, 3);
    123
    124DEFINE_RPMPD_PAIR(mdm9607, vddmx, vddmx_ao, LDOA, LEVEL, 12);
    125DEFINE_RPMPD_VFL(mdm9607, vddmx_vfl, LDOA, 12);
    126static struct rpmpd *mdm9607_rpmpds[] = {
    127	[MDM9607_VDDCX] =	&mdm9607_vddcx,
    128	[MDM9607_VDDCX_AO] =	&mdm9607_vddcx_ao,
    129	[MDM9607_VDDCX_VFL] =	&mdm9607_vddcx_vfl,
    130	[MDM9607_VDDMX] =	&mdm9607_vddmx,
    131	[MDM9607_VDDMX_AO] =	&mdm9607_vddmx_ao,
    132	[MDM9607_VDDMX_VFL] =	&mdm9607_vddmx_vfl,
    133};
    134
    135static const struct rpmpd_desc mdm9607_desc = {
    136	.rpmpds = mdm9607_rpmpds,
    137	.num_pds = ARRAY_SIZE(mdm9607_rpmpds),
    138	.max_state = RPM_SMD_LEVEL_TURBO,
    139};
    140
    141/* msm8226 RPM Power Domains */
    142DEFINE_RPMPD_PAIR(msm8226, vddcx, vddcx_ao, SMPA, CORNER, 1);
    143DEFINE_RPMPD_VFC(msm8226, vddcx_vfc, SMPA, 1);
    144
    145static struct rpmpd *msm8226_rpmpds[] = {
    146	[MSM8226_VDDCX] =	&msm8226_vddcx,
    147	[MSM8226_VDDCX_AO] =	&msm8226_vddcx_ao,
    148	[MSM8226_VDDCX_VFC] =	&msm8226_vddcx_vfc,
    149};
    150
    151static const struct rpmpd_desc msm8226_desc = {
    152	.rpmpds = msm8226_rpmpds,
    153	.num_pds = ARRAY_SIZE(msm8226_rpmpds),
    154	.max_state = MAX_CORNER_RPMPD_STATE,
    155};
    156
    157/* msm8939 RPM Power Domains */
    158DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1);
    159DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1);
    160
    161DEFINE_RPMPD_PAIR(msm8939, vddcx, vddcx_ao, SMPA, CORNER, 2);
    162DEFINE_RPMPD_VFC(msm8939, vddcx_vfc, SMPA, 2);
    163
    164DEFINE_RPMPD_PAIR(msm8939, vddmx, vddmx_ao, LDOA, CORNER, 3);
    165
    166static struct rpmpd *msm8939_rpmpds[] = {
    167	[MSM8939_VDDMDCX] =	&msm8939_vddmd,
    168	[MSM8939_VDDMDCX_AO] =	&msm8939_vddmd_ao,
    169	[MSM8939_VDDMDCX_VFC] =	&msm8939_vddmd_vfc,
    170	[MSM8939_VDDCX] =	&msm8939_vddcx,
    171	[MSM8939_VDDCX_AO] =	&msm8939_vddcx_ao,
    172	[MSM8939_VDDCX_VFC] =	&msm8939_vddcx_vfc,
    173	[MSM8939_VDDMX] =	&msm8939_vddmx,
    174	[MSM8939_VDDMX_AO] =	&msm8939_vddmx_ao,
    175};
    176
    177static const struct rpmpd_desc msm8939_desc = {
    178	.rpmpds = msm8939_rpmpds,
    179	.num_pds = ARRAY_SIZE(msm8939_rpmpds),
    180	.max_state = MAX_CORNER_RPMPD_STATE,
    181};
    182
    183/* msm8916 RPM Power Domains */
    184DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
    185DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
    186
    187DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
    188
    189static struct rpmpd *msm8916_rpmpds[] = {
    190	[MSM8916_VDDCX] =	&msm8916_vddcx,
    191	[MSM8916_VDDCX_AO] =	&msm8916_vddcx_ao,
    192	[MSM8916_VDDCX_VFC] =	&msm8916_vddcx_vfc,
    193	[MSM8916_VDDMX] =	&msm8916_vddmx,
    194	[MSM8916_VDDMX_AO] =	&msm8916_vddmx_ao,
    195};
    196
    197static const struct rpmpd_desc msm8916_desc = {
    198	.rpmpds = msm8916_rpmpds,
    199	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
    200	.max_state = MAX_CORNER_RPMPD_STATE,
    201};
    202
    203/* msm8953 RPM Power Domains */
    204DEFINE_RPMPD_PAIR(msm8953, vddmd, vddmd_ao, SMPA, LEVEL, 1);
    205DEFINE_RPMPD_PAIR(msm8953, vddcx, vddcx_ao, SMPA, LEVEL, 2);
    206DEFINE_RPMPD_PAIR(msm8953, vddmx, vddmx_ao, SMPA, LEVEL, 7);
    207
    208DEFINE_RPMPD_VFL(msm8953, vddcx_vfl, SMPA, 2);
    209
    210static struct rpmpd *msm8953_rpmpds[] = {
    211	[MSM8953_VDDMD] =	&msm8953_vddmd,
    212	[MSM8953_VDDMD_AO] =	&msm8953_vddmd_ao,
    213	[MSM8953_VDDCX] =	&msm8953_vddcx,
    214	[MSM8953_VDDCX_AO] =	&msm8953_vddcx_ao,
    215	[MSM8953_VDDCX_VFL] =	&msm8953_vddcx_vfl,
    216	[MSM8953_VDDMX] =	&msm8953_vddmx,
    217	[MSM8953_VDDMX_AO] =	&msm8953_vddmx_ao,
    218};
    219
    220static const struct rpmpd_desc msm8953_desc = {
    221	.rpmpds = msm8953_rpmpds,
    222	.num_pds = ARRAY_SIZE(msm8953_rpmpds),
    223	.max_state = RPM_SMD_LEVEL_TURBO,
    224};
    225
    226/* msm8976 RPM Power Domains */
    227DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
    228DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
    229
    230DEFINE_RPMPD_VFL(msm8976, vddcx_vfl, RWSC, 2);
    231DEFINE_RPMPD_VFL(msm8976, vddmx_vfl, RWSM, 6);
    232
    233static struct rpmpd *msm8976_rpmpds[] = {
    234	[MSM8976_VDDCX] =	&msm8976_vddcx,
    235	[MSM8976_VDDCX_AO] =	&msm8976_vddcx_ao,
    236	[MSM8976_VDDCX_VFL] =	&msm8976_vddcx_vfl,
    237	[MSM8976_VDDMX] =	&msm8976_vddmx,
    238	[MSM8976_VDDMX_AO] =	&msm8976_vddmx_ao,
    239	[MSM8976_VDDMX_VFL] =	&msm8976_vddmx_vfl,
    240};
    241
    242static const struct rpmpd_desc msm8976_desc = {
    243	.rpmpds = msm8976_rpmpds,
    244	.num_pds = ARRAY_SIZE(msm8976_rpmpds),
    245	.max_state = RPM_SMD_LEVEL_TURBO_HIGH,
    246};
    247
    248/* msm8994 RPM Power domains */
    249DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1);
    250DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2);
    251/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
    252DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2);
    253
    254DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1);
    255DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2);
    256
    257static struct rpmpd *msm8994_rpmpds[] = {
    258	[MSM8994_VDDCX] =	&msm8994_vddcx,
    259	[MSM8994_VDDCX_AO] =	&msm8994_vddcx_ao,
    260	[MSM8994_VDDCX_VFC] =	&msm8994_vddcx_vfc,
    261	[MSM8994_VDDMX] =	&msm8994_vddmx,
    262	[MSM8994_VDDMX_AO] =	&msm8994_vddmx_ao,
    263	[MSM8994_VDDGFX] =	&msm8994_vddgfx,
    264	[MSM8994_VDDGFX_VFC] =	&msm8994_vddgfx_vfc,
    265};
    266
    267static const struct rpmpd_desc msm8994_desc = {
    268	.rpmpds = msm8994_rpmpds,
    269	.num_pds = ARRAY_SIZE(msm8994_rpmpds),
    270	.max_state = MAX_CORNER_RPMPD_STATE,
    271};
    272
    273/* msm8996 RPM Power domains */
    274DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1);
    275DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2);
    276DEFINE_RPMPD_CORNER(msm8996, vddsscx, LDOA, 26);
    277
    278DEFINE_RPMPD_VFC(msm8996, vddcx_vfc, SMPA, 1);
    279DEFINE_RPMPD_VFC(msm8996, vddsscx_vfc, LDOA, 26);
    280
    281static struct rpmpd *msm8996_rpmpds[] = {
    282	[MSM8996_VDDCX] =	&msm8996_vddcx,
    283	[MSM8996_VDDCX_AO] =	&msm8996_vddcx_ao,
    284	[MSM8996_VDDCX_VFC] =	&msm8996_vddcx_vfc,
    285	[MSM8996_VDDMX] =	&msm8996_vddmx,
    286	[MSM8996_VDDMX_AO] =	&msm8996_vddmx_ao,
    287	[MSM8996_VDDSSCX] =	&msm8996_vddsscx,
    288	[MSM8996_VDDSSCX_VFC] =	&msm8996_vddsscx_vfc,
    289};
    290
    291static const struct rpmpd_desc msm8996_desc = {
    292	.rpmpds = msm8996_rpmpds,
    293	.num_pds = ARRAY_SIZE(msm8996_rpmpds),
    294	.max_state = MAX_CORNER_RPMPD_STATE,
    295};
    296
    297/* msm8998 RPM Power domains */
    298DEFINE_RPMPD_PAIR(msm8998, vddcx, vddcx_ao, RWCX, LEVEL, 0);
    299DEFINE_RPMPD_VFL(msm8998, vddcx_vfl, RWCX, 0);
    300
    301DEFINE_RPMPD_PAIR(msm8998, vddmx, vddmx_ao, RWMX, LEVEL, 0);
    302DEFINE_RPMPD_VFL(msm8998, vddmx_vfl, RWMX, 0);
    303
    304DEFINE_RPMPD_LEVEL(msm8998, vdd_ssccx, RWSC, 0);
    305DEFINE_RPMPD_VFL(msm8998, vdd_ssccx_vfl, RWSC, 0);
    306
    307DEFINE_RPMPD_LEVEL(msm8998, vdd_sscmx, RWSM, 0);
    308DEFINE_RPMPD_VFL(msm8998, vdd_sscmx_vfl, RWSM, 0);
    309
    310static struct rpmpd *msm8998_rpmpds[] = {
    311	[MSM8998_VDDCX] =		&msm8998_vddcx,
    312	[MSM8998_VDDCX_AO] =		&msm8998_vddcx_ao,
    313	[MSM8998_VDDCX_VFL] =		&msm8998_vddcx_vfl,
    314	[MSM8998_VDDMX] =		&msm8998_vddmx,
    315	[MSM8998_VDDMX_AO] =		&msm8998_vddmx_ao,
    316	[MSM8998_VDDMX_VFL] =		&msm8998_vddmx_vfl,
    317	[MSM8998_SSCCX] =		&msm8998_vdd_ssccx,
    318	[MSM8998_SSCCX_VFL] =		&msm8998_vdd_ssccx_vfl,
    319	[MSM8998_SSCMX] =		&msm8998_vdd_sscmx,
    320	[MSM8998_SSCMX_VFL] =		&msm8998_vdd_sscmx_vfl,
    321};
    322
    323static const struct rpmpd_desc msm8998_desc = {
    324	.rpmpds = msm8998_rpmpds,
    325	.num_pds = ARRAY_SIZE(msm8998_rpmpds),
    326	.max_state = RPM_SMD_LEVEL_BINNING,
    327};
    328
    329/* qcs404 RPM Power domains */
    330DEFINE_RPMPD_PAIR(qcs404, vddmx, vddmx_ao, RWMX, LEVEL, 0);
    331DEFINE_RPMPD_VFL(qcs404, vddmx_vfl, RWMX, 0);
    332
    333DEFINE_RPMPD_LEVEL(qcs404, vdd_lpicx, RWLC, 0);
    334DEFINE_RPMPD_VFL(qcs404, vdd_lpicx_vfl, RWLC, 0);
    335
    336DEFINE_RPMPD_LEVEL(qcs404, vdd_lpimx, RWLM, 0);
    337DEFINE_RPMPD_VFL(qcs404, vdd_lpimx_vfl, RWLM, 0);
    338
    339static struct rpmpd *qcs404_rpmpds[] = {
    340	[QCS404_VDDMX] = &qcs404_vddmx,
    341	[QCS404_VDDMX_AO] = &qcs404_vddmx_ao,
    342	[QCS404_VDDMX_VFL] = &qcs404_vddmx_vfl,
    343	[QCS404_LPICX] = &qcs404_vdd_lpicx,
    344	[QCS404_LPICX_VFL] = &qcs404_vdd_lpicx_vfl,
    345	[QCS404_LPIMX] = &qcs404_vdd_lpimx,
    346	[QCS404_LPIMX_VFL] = &qcs404_vdd_lpimx_vfl,
    347};
    348
    349static const struct rpmpd_desc qcs404_desc = {
    350	.rpmpds = qcs404_rpmpds,
    351	.num_pds = ARRAY_SIZE(qcs404_rpmpds),
    352	.max_state = RPM_SMD_LEVEL_BINNING,
    353};
    354
    355/* sdm660 RPM Power domains */
    356DEFINE_RPMPD_PAIR(sdm660, vddcx, vddcx_ao, RWCX, LEVEL, 0);
    357DEFINE_RPMPD_VFL(sdm660, vddcx_vfl, RWCX, 0);
    358
    359DEFINE_RPMPD_PAIR(sdm660, vddmx, vddmx_ao, RWMX, LEVEL, 0);
    360DEFINE_RPMPD_VFL(sdm660, vddmx_vfl, RWMX, 0);
    361
    362DEFINE_RPMPD_LEVEL(sdm660, vdd_ssccx, RWLC, 0);
    363DEFINE_RPMPD_VFL(sdm660, vdd_ssccx_vfl, RWLC, 0);
    364
    365DEFINE_RPMPD_LEVEL(sdm660, vdd_sscmx, RWLM, 0);
    366DEFINE_RPMPD_VFL(sdm660, vdd_sscmx_vfl, RWLM, 0);
    367
    368static struct rpmpd *sdm660_rpmpds[] = {
    369	[SDM660_VDDCX] =		&sdm660_vddcx,
    370	[SDM660_VDDCX_AO] =		&sdm660_vddcx_ao,
    371	[SDM660_VDDCX_VFL] =		&sdm660_vddcx_vfl,
    372	[SDM660_VDDMX] =		&sdm660_vddmx,
    373	[SDM660_VDDMX_AO] =		&sdm660_vddmx_ao,
    374	[SDM660_VDDMX_VFL] =		&sdm660_vddmx_vfl,
    375	[SDM660_SSCCX] =		&sdm660_vdd_ssccx,
    376	[SDM660_SSCCX_VFL] =		&sdm660_vdd_ssccx_vfl,
    377	[SDM660_SSCMX] =		&sdm660_vdd_sscmx,
    378	[SDM660_SSCMX_VFL] =		&sdm660_vdd_sscmx_vfl,
    379};
    380
    381static const struct rpmpd_desc sdm660_desc = {
    382	.rpmpds = sdm660_rpmpds,
    383	.num_pds = ARRAY_SIZE(sdm660_rpmpds),
    384	.max_state = RPM_SMD_LEVEL_TURBO,
    385};
    386
    387/* sm4250/6115 RPM Power domains */
    388DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
    389DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
    390
    391DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
    392DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
    393
    394DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
    395DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
    396
    397static struct rpmpd *sm6115_rpmpds[] = {
    398	[SM6115_VDDCX] =		&sm6115_vddcx,
    399	[SM6115_VDDCX_AO] =		&sm6115_vddcx_ao,
    400	[SM6115_VDDCX_VFL] =		&sm6115_vddcx_vfl,
    401	[SM6115_VDDMX] =		&sm6115_vddmx,
    402	[SM6115_VDDMX_AO] =		&sm6115_vddmx_ao,
    403	[SM6115_VDDMX_VFL] =		&sm6115_vddmx_vfl,
    404	[SM6115_VDD_LPI_CX] =		&sm6115_vdd_lpi_cx,
    405	[SM6115_VDD_LPI_MX] =		&sm6115_vdd_lpi_mx,
    406};
    407
    408static const struct rpmpd_desc sm6115_desc = {
    409	.rpmpds = sm6115_rpmpds,
    410	.num_pds = ARRAY_SIZE(sm6115_rpmpds),
    411	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
    412};
    413
    414/* sm6125 RPM Power domains */
    415DEFINE_RPMPD_PAIR(sm6125, vddcx, vddcx_ao, RWCX, LEVEL, 0);
    416DEFINE_RPMPD_VFL(sm6125, vddcx_vfl, RWCX, 0);
    417
    418DEFINE_RPMPD_PAIR(sm6125, vddmx, vddmx_ao, RWMX, LEVEL, 0);
    419DEFINE_RPMPD_VFL(sm6125, vddmx_vfl, RWMX, 0);
    420
    421static struct rpmpd *sm6125_rpmpds[] = {
    422	[SM6125_VDDCX] =		&sm6125_vddcx,
    423	[SM6125_VDDCX_AO] =		&sm6125_vddcx_ao,
    424	[SM6125_VDDCX_VFL] =		&sm6125_vddcx_vfl,
    425	[SM6125_VDDMX] =		&sm6125_vddmx,
    426	[SM6125_VDDMX_AO] =		&sm6125_vddmx_ao,
    427	[SM6125_VDDMX_VFL] =		&sm6125_vddmx_vfl,
    428};
    429
    430static const struct rpmpd_desc sm6125_desc = {
    431	.rpmpds = sm6125_rpmpds,
    432	.num_pds = ARRAY_SIZE(sm6125_rpmpds),
    433	.max_state = RPM_SMD_LEVEL_BINNING,
    434};
    435
    436static struct rpmpd *qcm2290_rpmpds[] = {
    437	[QCM2290_VDDCX] = &sm6115_vddcx,
    438	[QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
    439	[QCM2290_VDDCX_VFL] = &sm6115_vddcx_vfl,
    440	[QCM2290_VDDMX] = &sm6115_vddmx,
    441	[QCM2290_VDDMX_AO] = &sm6115_vddmx_ao,
    442	[QCM2290_VDDMX_VFL] = &sm6115_vddmx_vfl,
    443	[QCM2290_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
    444	[QCM2290_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
    445};
    446
    447static const struct rpmpd_desc qcm2290_desc = {
    448	.rpmpds = qcm2290_rpmpds,
    449	.num_pds = ARRAY_SIZE(qcm2290_rpmpds),
    450	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
    451};
    452
    453static const struct of_device_id rpmpd_match_table[] = {
    454	{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
    455	{ .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
    456	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
    457	{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
    458	{ .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
    459	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
    460	{ .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
    461	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
    462	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
    463	{ .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
    464	{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
    465	{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
    466	{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
    467	{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
    468	{ }
    469};
    470MODULE_DEVICE_TABLE(of, rpmpd_match_table);
    471
    472static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
    473{
    474	struct rpmpd_req req = {
    475		.key = KEY_ENABLE,
    476		.nbytes = cpu_to_le32(sizeof(u32)),
    477		.value = cpu_to_le32(enable),
    478	};
    479
    480	return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
    481				  pd->res_type, pd->res_id, &req, sizeof(req));
    482}
    483
    484static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
    485{
    486	struct rpmpd_req req = {
    487		.key = pd->key,
    488		.nbytes = cpu_to_le32(sizeof(u32)),
    489		.value = cpu_to_le32(corner),
    490	};
    491
    492	return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
    493				  &req, sizeof(req));
    494};
    495
    496static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
    497			    unsigned int *active, unsigned int *sleep)
    498{
    499	*active = corner;
    500
    501	if (pd->active_only)
    502		*sleep = 0;
    503	else
    504		*sleep = *active;
    505}
    506
    507static int rpmpd_aggregate_corner(struct rpmpd *pd)
    508{
    509	int ret;
    510	struct rpmpd *peer = pd->peer;
    511	unsigned int active_corner, sleep_corner;
    512	unsigned int this_active_corner = 0, this_sleep_corner = 0;
    513	unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
    514
    515	to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
    516
    517	if (peer && peer->enabled)
    518		to_active_sleep(peer, peer->corner, &peer_active_corner,
    519				&peer_sleep_corner);
    520
    521	active_corner = max(this_active_corner, peer_active_corner);
    522
    523	ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
    524	if (ret)
    525		return ret;
    526
    527	sleep_corner = max(this_sleep_corner, peer_sleep_corner);
    528
    529	return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
    530}
    531
    532static int rpmpd_power_on(struct generic_pm_domain *domain)
    533{
    534	int ret;
    535	struct rpmpd *pd = domain_to_rpmpd(domain);
    536
    537	mutex_lock(&rpmpd_lock);
    538
    539	ret = rpmpd_send_enable(pd, true);
    540	if (ret)
    541		goto out;
    542
    543	pd->enabled = true;
    544
    545	if (pd->corner)
    546		ret = rpmpd_aggregate_corner(pd);
    547
    548out:
    549	mutex_unlock(&rpmpd_lock);
    550
    551	return ret;
    552}
    553
    554static int rpmpd_power_off(struct generic_pm_domain *domain)
    555{
    556	int ret;
    557	struct rpmpd *pd = domain_to_rpmpd(domain);
    558
    559	mutex_lock(&rpmpd_lock);
    560
    561	ret = rpmpd_send_enable(pd, false);
    562	if (!ret)
    563		pd->enabled = false;
    564
    565	mutex_unlock(&rpmpd_lock);
    566
    567	return ret;
    568}
    569
    570static int rpmpd_set_performance(struct generic_pm_domain *domain,
    571				 unsigned int state)
    572{
    573	int ret = 0;
    574	struct rpmpd *pd = domain_to_rpmpd(domain);
    575
    576	if (state > pd->max_state)
    577		state = pd->max_state;
    578
    579	mutex_lock(&rpmpd_lock);
    580
    581	pd->corner = state;
    582
    583	/* Always send updates for vfc and vfl */
    584	if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
    585	    pd->key != KEY_FLOOR_LEVEL)
    586		goto out;
    587
    588	ret = rpmpd_aggregate_corner(pd);
    589
    590out:
    591	mutex_unlock(&rpmpd_lock);
    592
    593	return ret;
    594}
    595
    596static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
    597					  struct dev_pm_opp *opp)
    598{
    599	return dev_pm_opp_get_level(opp);
    600}
    601
    602static int rpmpd_probe(struct platform_device *pdev)
    603{
    604	int i;
    605	size_t num;
    606	struct genpd_onecell_data *data;
    607	struct qcom_smd_rpm *rpm;
    608	struct rpmpd **rpmpds;
    609	const struct rpmpd_desc *desc;
    610
    611	rpm = dev_get_drvdata(pdev->dev.parent);
    612	if (!rpm) {
    613		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
    614		return -ENODEV;
    615	}
    616
    617	desc = of_device_get_match_data(&pdev->dev);
    618	if (!desc)
    619		return -EINVAL;
    620
    621	rpmpds = desc->rpmpds;
    622	num = desc->num_pds;
    623
    624	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
    625	if (!data)
    626		return -ENOMEM;
    627
    628	data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
    629				     GFP_KERNEL);
    630	if (!data->domains)
    631		return -ENOMEM;
    632
    633	data->num_domains = num;
    634
    635	for (i = 0; i < num; i++) {
    636		if (!rpmpds[i]) {
    637			dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
    638				 i);
    639			continue;
    640		}
    641
    642		rpmpds[i]->rpm = rpm;
    643		rpmpds[i]->max_state = desc->max_state;
    644		rpmpds[i]->pd.power_off = rpmpd_power_off;
    645		rpmpds[i]->pd.power_on = rpmpd_power_on;
    646		rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
    647		rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
    648		pm_genpd_init(&rpmpds[i]->pd, NULL, true);
    649
    650		data->domains[i] = &rpmpds[i]->pd;
    651	}
    652
    653	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
    654}
    655
    656static struct platform_driver rpmpd_driver = {
    657	.driver = {
    658		.name = "qcom-rpmpd",
    659		.of_match_table = rpmpd_match_table,
    660		.suppress_bind_attrs = true,
    661	},
    662	.probe = rpmpd_probe,
    663};
    664
    665static int __init rpmpd_init(void)
    666{
    667	return platform_driver_register(&rpmpd_driver);
    668}
    669core_initcall(rpmpd_init);
    670
    671MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
    672MODULE_LICENSE("GPL v2");