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

qcom_rpm-regulator.c (29704B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2014, Sony Mobile Communications AB.
      4 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
      5 */
      6
      7#include <linux/module.h>
      8#include <linux/platform_device.h>
      9#include <linux/of.h>
     10#include <linux/of_device.h>
     11#include <linux/regulator/driver.h>
     12#include <linux/regulator/machine.h>
     13#include <linux/regulator/of_regulator.h>
     14#include <linux/mfd/qcom_rpm.h>
     15
     16#include <dt-bindings/mfd/qcom-rpm.h>
     17
     18#define MAX_REQUEST_LEN 2
     19
     20struct request_member {
     21	int		word;
     22	unsigned int	mask;
     23	int		shift;
     24};
     25
     26struct rpm_reg_parts {
     27	struct request_member mV;		/* used if voltage is in mV */
     28	struct request_member uV;		/* used if voltage is in uV */
     29	struct request_member ip;		/* peak current in mA */
     30	struct request_member pd;		/* pull down enable */
     31	struct request_member ia;		/* average current in mA */
     32	struct request_member fm;		/* force mode */
     33	struct request_member pm;		/* power mode */
     34	struct request_member pc;		/* pin control */
     35	struct request_member pf;		/* pin function */
     36	struct request_member enable_state;	/* NCP and switch */
     37	struct request_member comp_mode;	/* NCP */
     38	struct request_member freq;		/* frequency: NCP and SMPS */
     39	struct request_member freq_clk_src;	/* clock source: SMPS */
     40	struct request_member hpm;		/* switch: control OCP and SS */
     41	int request_len;
     42};
     43
     44#define FORCE_MODE_IS_2_BITS(reg) \
     45	(((reg)->parts->fm.mask >> (reg)->parts->fm.shift) == 3)
     46
     47struct qcom_rpm_reg {
     48	struct qcom_rpm *rpm;
     49
     50	struct mutex lock;
     51	struct device *dev;
     52	struct regulator_desc desc;
     53	const struct rpm_reg_parts *parts;
     54
     55	int resource;
     56	u32 val[MAX_REQUEST_LEN];
     57
     58	int uV;
     59	int is_enabled;
     60
     61	bool supports_force_mode_auto;
     62	bool supports_force_mode_bypass;
     63};
     64
     65static const struct rpm_reg_parts rpm8660_ldo_parts = {
     66	.request_len    = 2,
     67	.mV             = { 0, 0x00000FFF,  0 },
     68	.ip             = { 0, 0x00FFF000, 12 },
     69	.fm             = { 0, 0x03000000, 24 },
     70	.pc             = { 0, 0x3C000000, 26 },
     71	.pf             = { 0, 0xC0000000, 30 },
     72	.pd             = { 1, 0x00000001,  0 },
     73	.ia             = { 1, 0x00001FFE,  1 },
     74};
     75
     76static const struct rpm_reg_parts rpm8660_smps_parts = {
     77	.request_len    = 2,
     78	.mV             = { 0, 0x00000FFF,  0 },
     79	.ip             = { 0, 0x00FFF000, 12 },
     80	.fm             = { 0, 0x03000000, 24 },
     81	.pc             = { 0, 0x3C000000, 26 },
     82	.pf             = { 0, 0xC0000000, 30 },
     83	.pd             = { 1, 0x00000001,  0 },
     84	.ia             = { 1, 0x00001FFE,  1 },
     85	.freq           = { 1, 0x001FE000, 13 },
     86	.freq_clk_src   = { 1, 0x00600000, 21 },
     87};
     88
     89static const struct rpm_reg_parts rpm8660_switch_parts = {
     90	.request_len    = 1,
     91	.enable_state   = { 0, 0x00000001,  0 },
     92	.pd             = { 0, 0x00000002,  1 },
     93	.pc             = { 0, 0x0000003C,  2 },
     94	.pf             = { 0, 0x000000C0,  6 },
     95	.hpm            = { 0, 0x00000300,  8 },
     96};
     97
     98static const struct rpm_reg_parts rpm8660_ncp_parts = {
     99	.request_len    = 1,
    100	.mV             = { 0, 0x00000FFF,  0 },
    101	.enable_state   = { 0, 0x00001000, 12 },
    102	.comp_mode      = { 0, 0x00002000, 13 },
    103	.freq           = { 0, 0x003FC000, 14 },
    104};
    105
    106static const struct rpm_reg_parts rpm8960_ldo_parts = {
    107	.request_len    = 2,
    108	.uV             = { 0, 0x007FFFFF,  0 },
    109	.pd             = { 0, 0x00800000, 23 },
    110	.pc             = { 0, 0x0F000000, 24 },
    111	.pf             = { 0, 0xF0000000, 28 },
    112	.ip             = { 1, 0x000003FF,  0 },
    113	.ia             = { 1, 0x000FFC00, 10 },
    114	.fm             = { 1, 0x00700000, 20 },
    115};
    116
    117static const struct rpm_reg_parts rpm8960_smps_parts = {
    118	.request_len    = 2,
    119	.uV             = { 0, 0x007FFFFF,  0 },
    120	.pd             = { 0, 0x00800000, 23 },
    121	.pc             = { 0, 0x0F000000, 24 },
    122	.pf             = { 0, 0xF0000000, 28 },
    123	.ip             = { 1, 0x000003FF,  0 },
    124	.ia             = { 1, 0x000FFC00, 10 },
    125	.fm             = { 1, 0x00700000, 20 },
    126	.pm             = { 1, 0x00800000, 23 },
    127	.freq           = { 1, 0x1F000000, 24 },
    128	.freq_clk_src   = { 1, 0x60000000, 29 },
    129};
    130
    131static const struct rpm_reg_parts rpm8960_switch_parts = {
    132	.request_len    = 1,
    133	.enable_state   = { 0, 0x00000001,  0 },
    134	.pd             = { 0, 0x00000002,  1 },
    135	.pc             = { 0, 0x0000003C,  2 },
    136	.pf             = { 0, 0x000003C0,  6 },
    137	.hpm            = { 0, 0x00000C00, 10 },
    138};
    139
    140static const struct rpm_reg_parts rpm8960_ncp_parts = {
    141	.request_len    = 1,
    142	.uV             = { 0, 0x007FFFFF,  0 },
    143	.enable_state   = { 0, 0x00800000, 23 },
    144	.comp_mode      = { 0, 0x01000000, 24 },
    145	.freq           = { 0, 0x3E000000, 25 },
    146};
    147
    148/*
    149 * Physically available PMIC regulator voltage ranges
    150 */
    151static const struct linear_range pldo_ranges[] = {
    152	REGULATOR_LINEAR_RANGE( 750000,   0,  59, 12500),
    153	REGULATOR_LINEAR_RANGE(1500000,  60, 123, 25000),
    154	REGULATOR_LINEAR_RANGE(3100000, 124, 160, 50000),
    155};
    156
    157static const struct linear_range nldo_ranges[] = {
    158	REGULATOR_LINEAR_RANGE( 750000,   0,  63, 12500),
    159};
    160
    161static const struct linear_range nldo1200_ranges[] = {
    162	REGULATOR_LINEAR_RANGE( 375000,   0,  59,  6250),
    163	REGULATOR_LINEAR_RANGE( 750000,  60, 123, 12500),
    164};
    165
    166static const struct linear_range smps_ranges[] = {
    167	REGULATOR_LINEAR_RANGE( 375000,   0,  29, 12500),
    168	REGULATOR_LINEAR_RANGE( 750000,  30,  89, 12500),
    169	REGULATOR_LINEAR_RANGE(1500000,  90, 153, 25000),
    170};
    171
    172static const struct linear_range ftsmps_ranges[] = {
    173	REGULATOR_LINEAR_RANGE( 350000,   0,   6, 50000),
    174	REGULATOR_LINEAR_RANGE( 700000,   7,  63, 12500),
    175	REGULATOR_LINEAR_RANGE(1500000,  64, 100, 50000),
    176};
    177
    178static const struct linear_range smb208_ranges[] = {
    179	REGULATOR_LINEAR_RANGE( 375000,   0,  29, 12500),
    180	REGULATOR_LINEAR_RANGE( 750000,  30,  89, 12500),
    181	REGULATOR_LINEAR_RANGE(1500000,  90, 153, 25000),
    182	REGULATOR_LINEAR_RANGE(3100000, 154, 234, 25000),
    183};
    184
    185static const struct linear_range ncp_ranges[] = {
    186	REGULATOR_LINEAR_RANGE(1500000,   0,  31, 50000),
    187};
    188
    189static int rpm_reg_write(struct qcom_rpm_reg *vreg,
    190			 const struct request_member *req,
    191			 const int value)
    192{
    193	if (WARN_ON((value << req->shift) & ~req->mask))
    194		return -EINVAL;
    195
    196	vreg->val[req->word] &= ~req->mask;
    197	vreg->val[req->word] |= value << req->shift;
    198
    199	return qcom_rpm_write(vreg->rpm,
    200			      QCOM_RPM_ACTIVE_STATE,
    201			      vreg->resource,
    202			      vreg->val,
    203			      vreg->parts->request_len);
    204}
    205
    206static int rpm_reg_set_mV_sel(struct regulator_dev *rdev,
    207			      unsigned selector)
    208{
    209	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    210	const struct rpm_reg_parts *parts = vreg->parts;
    211	const struct request_member *req = &parts->mV;
    212	int ret = 0;
    213	int uV;
    214
    215	if (req->mask == 0)
    216		return -EINVAL;
    217
    218	uV = regulator_list_voltage_linear_range(rdev, selector);
    219	if (uV < 0)
    220		return uV;
    221
    222	mutex_lock(&vreg->lock);
    223	if (vreg->is_enabled)
    224		ret = rpm_reg_write(vreg, req, uV / 1000);
    225
    226	if (!ret)
    227		vreg->uV = uV;
    228	mutex_unlock(&vreg->lock);
    229
    230	return ret;
    231}
    232
    233static int rpm_reg_set_uV_sel(struct regulator_dev *rdev,
    234			      unsigned selector)
    235{
    236	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    237	const struct rpm_reg_parts *parts = vreg->parts;
    238	const struct request_member *req = &parts->uV;
    239	int ret = 0;
    240	int uV;
    241
    242	if (req->mask == 0)
    243		return -EINVAL;
    244
    245	uV = regulator_list_voltage_linear_range(rdev, selector);
    246	if (uV < 0)
    247		return uV;
    248
    249	mutex_lock(&vreg->lock);
    250	if (vreg->is_enabled)
    251		ret = rpm_reg_write(vreg, req, uV);
    252
    253	if (!ret)
    254		vreg->uV = uV;
    255	mutex_unlock(&vreg->lock);
    256
    257	return ret;
    258}
    259
    260static int rpm_reg_get_voltage(struct regulator_dev *rdev)
    261{
    262	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    263
    264	return vreg->uV;
    265}
    266
    267static int rpm_reg_mV_enable(struct regulator_dev *rdev)
    268{
    269	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    270	const struct rpm_reg_parts *parts = vreg->parts;
    271	const struct request_member *req = &parts->mV;
    272	int ret;
    273
    274	if (req->mask == 0)
    275		return -EINVAL;
    276
    277	mutex_lock(&vreg->lock);
    278	ret = rpm_reg_write(vreg, req, vreg->uV / 1000);
    279	if (!ret)
    280		vreg->is_enabled = 1;
    281	mutex_unlock(&vreg->lock);
    282
    283	return ret;
    284}
    285
    286static int rpm_reg_uV_enable(struct regulator_dev *rdev)
    287{
    288	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    289	const struct rpm_reg_parts *parts = vreg->parts;
    290	const struct request_member *req = &parts->uV;
    291	int ret;
    292
    293	if (req->mask == 0)
    294		return -EINVAL;
    295
    296	mutex_lock(&vreg->lock);
    297	ret = rpm_reg_write(vreg, req, vreg->uV);
    298	if (!ret)
    299		vreg->is_enabled = 1;
    300	mutex_unlock(&vreg->lock);
    301
    302	return ret;
    303}
    304
    305static int rpm_reg_switch_enable(struct regulator_dev *rdev)
    306{
    307	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    308	const struct rpm_reg_parts *parts = vreg->parts;
    309	const struct request_member *req = &parts->enable_state;
    310	int ret;
    311
    312	if (req->mask == 0)
    313		return -EINVAL;
    314
    315	mutex_lock(&vreg->lock);
    316	ret = rpm_reg_write(vreg, req, 1);
    317	if (!ret)
    318		vreg->is_enabled = 1;
    319	mutex_unlock(&vreg->lock);
    320
    321	return ret;
    322}
    323
    324static int rpm_reg_mV_disable(struct regulator_dev *rdev)
    325{
    326	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    327	const struct rpm_reg_parts *parts = vreg->parts;
    328	const struct request_member *req = &parts->mV;
    329	int ret;
    330
    331	if (req->mask == 0)
    332		return -EINVAL;
    333
    334	mutex_lock(&vreg->lock);
    335	ret = rpm_reg_write(vreg, req, 0);
    336	if (!ret)
    337		vreg->is_enabled = 0;
    338	mutex_unlock(&vreg->lock);
    339
    340	return ret;
    341}
    342
    343static int rpm_reg_uV_disable(struct regulator_dev *rdev)
    344{
    345	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    346	const struct rpm_reg_parts *parts = vreg->parts;
    347	const struct request_member *req = &parts->uV;
    348	int ret;
    349
    350	if (req->mask == 0)
    351		return -EINVAL;
    352
    353	mutex_lock(&vreg->lock);
    354	ret = rpm_reg_write(vreg, req, 0);
    355	if (!ret)
    356		vreg->is_enabled = 0;
    357	mutex_unlock(&vreg->lock);
    358
    359	return ret;
    360}
    361
    362static int rpm_reg_switch_disable(struct regulator_dev *rdev)
    363{
    364	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    365	const struct rpm_reg_parts *parts = vreg->parts;
    366	const struct request_member *req = &parts->enable_state;
    367	int ret;
    368
    369	if (req->mask == 0)
    370		return -EINVAL;
    371
    372	mutex_lock(&vreg->lock);
    373	ret = rpm_reg_write(vreg, req, 0);
    374	if (!ret)
    375		vreg->is_enabled = 0;
    376	mutex_unlock(&vreg->lock);
    377
    378	return ret;
    379}
    380
    381static int rpm_reg_is_enabled(struct regulator_dev *rdev)
    382{
    383	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    384
    385	return vreg->is_enabled;
    386}
    387
    388static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
    389{
    390	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
    391	const struct rpm_reg_parts *parts = vreg->parts;
    392	const struct request_member *req = &parts->ia;
    393	int load_mA = load_uA / 1000;
    394	int max_mA = req->mask >> req->shift;
    395	int ret;
    396
    397	if (req->mask == 0)
    398		return -EINVAL;
    399
    400	if (load_mA > max_mA)
    401		load_mA = max_mA;
    402
    403	mutex_lock(&vreg->lock);
    404	ret = rpm_reg_write(vreg, req, load_mA);
    405	mutex_unlock(&vreg->lock);
    406
    407	return ret;
    408}
    409
    410static const struct regulator_ops uV_ops = {
    411	.list_voltage = regulator_list_voltage_linear_range,
    412
    413	.set_voltage_sel = rpm_reg_set_uV_sel,
    414	.get_voltage = rpm_reg_get_voltage,
    415
    416	.enable = rpm_reg_uV_enable,
    417	.disable = rpm_reg_uV_disable,
    418	.is_enabled = rpm_reg_is_enabled,
    419
    420	.set_load = rpm_reg_set_load,
    421};
    422
    423static const struct regulator_ops mV_ops = {
    424	.list_voltage = regulator_list_voltage_linear_range,
    425
    426	.set_voltage_sel = rpm_reg_set_mV_sel,
    427	.get_voltage = rpm_reg_get_voltage,
    428
    429	.enable = rpm_reg_mV_enable,
    430	.disable = rpm_reg_mV_disable,
    431	.is_enabled = rpm_reg_is_enabled,
    432
    433	.set_load = rpm_reg_set_load,
    434};
    435
    436static const struct regulator_ops switch_ops = {
    437	.enable = rpm_reg_switch_enable,
    438	.disable = rpm_reg_switch_disable,
    439	.is_enabled = rpm_reg_is_enabled,
    440};
    441
    442/*
    443 * PM8018 regulators
    444 */
    445static const struct qcom_rpm_reg pm8018_pldo = {
    446	.desc.linear_ranges = pldo_ranges,
    447	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
    448	.desc.n_voltages = 161,
    449	.desc.ops = &uV_ops,
    450	.parts = &rpm8960_ldo_parts,
    451	.supports_force_mode_auto = false,
    452	.supports_force_mode_bypass = false,
    453};
    454
    455static const struct qcom_rpm_reg pm8018_nldo = {
    456	.desc.linear_ranges = nldo_ranges,
    457	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
    458	.desc.n_voltages = 64,
    459	.desc.ops = &uV_ops,
    460	.parts = &rpm8960_ldo_parts,
    461	.supports_force_mode_auto = false,
    462	.supports_force_mode_bypass = false,
    463};
    464
    465static const struct qcom_rpm_reg pm8018_smps = {
    466	.desc.linear_ranges = smps_ranges,
    467	.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
    468	.desc.n_voltages = 154,
    469	.desc.ops = &uV_ops,
    470	.parts = &rpm8960_smps_parts,
    471	.supports_force_mode_auto = false,
    472	.supports_force_mode_bypass = false,
    473};
    474
    475static const struct qcom_rpm_reg pm8018_switch = {
    476	.desc.ops = &switch_ops,
    477	.parts = &rpm8960_switch_parts,
    478};
    479
    480/*
    481 * PM8058 regulators
    482 */
    483static const struct qcom_rpm_reg pm8058_pldo = {
    484	.desc.linear_ranges = pldo_ranges,
    485	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
    486	.desc.n_voltages = 161,
    487	.desc.ops = &mV_ops,
    488	.parts = &rpm8660_ldo_parts,
    489	.supports_force_mode_auto = false,
    490	.supports_force_mode_bypass = false,
    491};
    492
    493static const struct qcom_rpm_reg pm8058_nldo = {
    494	.desc.linear_ranges = nldo_ranges,
    495	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
    496	.desc.n_voltages = 64,
    497	.desc.ops = &mV_ops,
    498	.parts = &rpm8660_ldo_parts,
    499	.supports_force_mode_auto = false,
    500	.supports_force_mode_bypass = false,
    501};
    502
    503static const struct qcom_rpm_reg pm8058_smps = {
    504	.desc.linear_ranges = smps_ranges,
    505	.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
    506	.desc.n_voltages = 154,
    507	.desc.ops = &mV_ops,
    508	.parts = &rpm8660_smps_parts,
    509	.supports_force_mode_auto = false,
    510	.supports_force_mode_bypass = false,
    511};
    512
    513static const struct qcom_rpm_reg pm8058_ncp = {
    514	.desc.linear_ranges = ncp_ranges,
    515	.desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges),
    516	.desc.n_voltages = 32,
    517	.desc.ops = &mV_ops,
    518	.parts = &rpm8660_ncp_parts,
    519};
    520
    521static const struct qcom_rpm_reg pm8058_switch = {
    522	.desc.ops = &switch_ops,
    523	.parts = &rpm8660_switch_parts,
    524};
    525
    526/*
    527 * PM8901 regulators
    528 */
    529static const struct qcom_rpm_reg pm8901_pldo = {
    530	.desc.linear_ranges = pldo_ranges,
    531	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
    532	.desc.n_voltages = 161,
    533	.desc.ops = &mV_ops,
    534	.parts = &rpm8660_ldo_parts,
    535	.supports_force_mode_auto = false,
    536	.supports_force_mode_bypass = true,
    537};
    538
    539static const struct qcom_rpm_reg pm8901_nldo = {
    540	.desc.linear_ranges = nldo_ranges,
    541	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
    542	.desc.n_voltages = 64,
    543	.desc.ops = &mV_ops,
    544	.parts = &rpm8660_ldo_parts,
    545	.supports_force_mode_auto = false,
    546	.supports_force_mode_bypass = true,
    547};
    548
    549static const struct qcom_rpm_reg pm8901_ftsmps = {
    550	.desc.linear_ranges = ftsmps_ranges,
    551	.desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges),
    552	.desc.n_voltages = 101,
    553	.desc.ops = &mV_ops,
    554	.parts = &rpm8660_smps_parts,
    555	.supports_force_mode_auto = true,
    556	.supports_force_mode_bypass = false,
    557};
    558
    559static const struct qcom_rpm_reg pm8901_switch = {
    560	.desc.ops = &switch_ops,
    561	.parts = &rpm8660_switch_parts,
    562};
    563
    564/*
    565 * PM8921 regulators
    566 */
    567static const struct qcom_rpm_reg pm8921_pldo = {
    568	.desc.linear_ranges = pldo_ranges,
    569	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
    570	.desc.n_voltages = 161,
    571	.desc.ops = &uV_ops,
    572	.parts = &rpm8960_ldo_parts,
    573	.supports_force_mode_auto = false,
    574	.supports_force_mode_bypass = true,
    575};
    576
    577static const struct qcom_rpm_reg pm8921_nldo = {
    578	.desc.linear_ranges = nldo_ranges,
    579	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
    580	.desc.n_voltages = 64,
    581	.desc.ops = &uV_ops,
    582	.parts = &rpm8960_ldo_parts,
    583	.supports_force_mode_auto = false,
    584	.supports_force_mode_bypass = true,
    585};
    586
    587static const struct qcom_rpm_reg pm8921_nldo1200 = {
    588	.desc.linear_ranges = nldo1200_ranges,
    589	.desc.n_linear_ranges = ARRAY_SIZE(nldo1200_ranges),
    590	.desc.n_voltages = 124,
    591	.desc.ops = &uV_ops,
    592	.parts = &rpm8960_ldo_parts,
    593	.supports_force_mode_auto = false,
    594	.supports_force_mode_bypass = true,
    595};
    596
    597static const struct qcom_rpm_reg pm8921_smps = {
    598	.desc.linear_ranges = smps_ranges,
    599	.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
    600	.desc.n_voltages = 154,
    601	.desc.ops = &uV_ops,
    602	.parts = &rpm8960_smps_parts,
    603	.supports_force_mode_auto = true,
    604	.supports_force_mode_bypass = false,
    605};
    606
    607static const struct qcom_rpm_reg pm8921_ncp = {
    608	.desc.linear_ranges = ncp_ranges,
    609	.desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges),
    610	.desc.n_voltages = 32,
    611	.desc.ops = &uV_ops,
    612	.parts = &rpm8960_ncp_parts,
    613};
    614
    615static const struct qcom_rpm_reg pm8921_switch = {
    616	.desc.ops = &switch_ops,
    617	.parts = &rpm8960_switch_parts,
    618};
    619
    620static const struct qcom_rpm_reg smb208_smps = {
    621	.desc.linear_ranges = smb208_ranges,
    622	.desc.n_linear_ranges = ARRAY_SIZE(smb208_ranges),
    623	.desc.n_voltages = 235,
    624	.desc.ops = &uV_ops,
    625	.parts = &rpm8960_smps_parts,
    626	.supports_force_mode_auto = false,
    627	.supports_force_mode_bypass = false,
    628};
    629
    630static int rpm_reg_set(struct qcom_rpm_reg *vreg,
    631		       const struct request_member *req,
    632		       const int value)
    633{
    634	if (req->mask == 0 || (value << req->shift) & ~req->mask)
    635		return -EINVAL;
    636
    637	vreg->val[req->word] &= ~req->mask;
    638	vreg->val[req->word] |= value << req->shift;
    639
    640	return 0;
    641}
    642
    643static int rpm_reg_of_parse_freq(struct device *dev,
    644				 struct device_node *node,
    645				 struct qcom_rpm_reg *vreg)
    646{
    647	static const int freq_table[] = {
    648		19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
    649		2400000, 2130000, 1920000, 1750000, 1600000, 1480000, 1370000,
    650		1280000, 1200000,
    651
    652	};
    653	const char *key;
    654	u32 freq;
    655	int ret;
    656	int i;
    657
    658	key = "qcom,switch-mode-frequency";
    659	ret = of_property_read_u32(node, key, &freq);
    660	if (ret) {
    661		dev_err(dev, "regulator requires %s property\n", key);
    662		return -EINVAL;
    663	}
    664
    665	for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
    666		if (freq == freq_table[i]) {
    667			rpm_reg_set(vreg, &vreg->parts->freq, i + 1);
    668			return 0;
    669		}
    670	}
    671
    672	dev_err(dev, "invalid frequency %d\n", freq);
    673	return -EINVAL;
    674}
    675
    676static int rpm_reg_of_parse(struct device_node *node,
    677			    const struct regulator_desc *desc,
    678			    struct regulator_config *config)
    679{
    680	struct qcom_rpm_reg *vreg = config->driver_data;
    681	struct device *dev = config->dev;
    682	const char *key;
    683	u32 force_mode;
    684	bool pwm;
    685	u32 val;
    686	int ret;
    687
    688	key = "bias-pull-down";
    689	if (of_property_read_bool(node, key)) {
    690		ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
    691		if (ret) {
    692			dev_err(dev, "%s is invalid", key);
    693			return ret;
    694		}
    695	}
    696
    697	if (vreg->parts->freq.mask) {
    698		ret = rpm_reg_of_parse_freq(dev, node, vreg);
    699		if (ret < 0)
    700			return ret;
    701	}
    702
    703	if (vreg->parts->pm.mask) {
    704		key = "qcom,power-mode-hysteretic";
    705		pwm = !of_property_read_bool(node, key);
    706
    707		ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
    708		if (ret) {
    709			dev_err(dev, "failed to set power mode\n");
    710			return ret;
    711		}
    712	}
    713
    714	if (vreg->parts->fm.mask) {
    715		force_mode = -1;
    716
    717		key = "qcom,force-mode";
    718		ret = of_property_read_u32(node, key, &val);
    719		if (ret == -EINVAL) {
    720			val = QCOM_RPM_FORCE_MODE_NONE;
    721		} else if (ret < 0) {
    722			dev_err(dev, "failed to read %s\n", key);
    723			return ret;
    724		}
    725
    726		/*
    727		 * If force-mode is encoded as 2 bits then the
    728		 * possible register values are:
    729		 * NONE, LPM, HPM
    730		 * otherwise:
    731		 * NONE, LPM, AUTO, HPM, BYPASS
    732		 */
    733		switch (val) {
    734		case QCOM_RPM_FORCE_MODE_NONE:
    735			force_mode = 0;
    736			break;
    737		case QCOM_RPM_FORCE_MODE_LPM:
    738			force_mode = 1;
    739			break;
    740		case QCOM_RPM_FORCE_MODE_HPM:
    741			if (FORCE_MODE_IS_2_BITS(vreg))
    742				force_mode = 2;
    743			else
    744				force_mode = 3;
    745			break;
    746		case QCOM_RPM_FORCE_MODE_AUTO:
    747			if (vreg->supports_force_mode_auto)
    748				force_mode = 2;
    749			break;
    750		case QCOM_RPM_FORCE_MODE_BYPASS:
    751			if (vreg->supports_force_mode_bypass)
    752				force_mode = 4;
    753			break;
    754		}
    755
    756		if (force_mode == -1) {
    757			dev_err(dev, "invalid force mode\n");
    758			return -EINVAL;
    759		}
    760
    761		ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
    762		if (ret) {
    763			dev_err(dev, "failed to set force mode\n");
    764			return ret;
    765		}
    766	}
    767
    768	return 0;
    769}
    770
    771struct rpm_regulator_data {
    772	const char *name;
    773	int resource;
    774	const struct qcom_rpm_reg *template;
    775	const char *supply;
    776};
    777
    778static const struct rpm_regulator_data rpm_pm8018_regulators[] = {
    779	{ "s1",  QCOM_RPM_PM8018_SMPS1, &pm8018_smps, "vdd_s1" },
    780	{ "s2",  QCOM_RPM_PM8018_SMPS2, &pm8018_smps, "vdd_s2" },
    781	{ "s3",  QCOM_RPM_PM8018_SMPS3, &pm8018_smps, "vdd_s3" },
    782	{ "s4",  QCOM_RPM_PM8018_SMPS4, &pm8018_smps, "vdd_s4" },
    783	{ "s5",  QCOM_RPM_PM8018_SMPS5, &pm8018_smps, "vdd_s5" },
    784
    785	{ "l2",  QCOM_RPM_PM8018_LDO2,  &pm8018_pldo, "vdd_l2" },
    786	{ "l3",  QCOM_RPM_PM8018_LDO3,  &pm8018_pldo, "vdd_l3" },
    787	{ "l4",  QCOM_RPM_PM8018_LDO4,  &pm8018_pldo, "vdd_l4" },
    788	{ "l5",  QCOM_RPM_PM8018_LDO5,  &pm8018_pldo, "vdd_l5" },
    789	{ "l6",  QCOM_RPM_PM8018_LDO6,  &pm8018_pldo, "vdd_l7" },
    790	{ "l7",  QCOM_RPM_PM8018_LDO7,  &pm8018_pldo, "vdd_l7" },
    791	{ "l8",  QCOM_RPM_PM8018_LDO8,  &pm8018_nldo, "vdd_l8" },
    792	{ "l9",  QCOM_RPM_PM8018_LDO9,  &pm8921_nldo1200,
    793						      "vdd_l9_l10_l11_l12" },
    794	{ "l10", QCOM_RPM_PM8018_LDO10, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
    795	{ "l11", QCOM_RPM_PM8018_LDO11, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
    796	{ "l12", QCOM_RPM_PM8018_LDO12, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
    797	{ "l14", QCOM_RPM_PM8018_LDO14, &pm8018_pldo, "vdd_l14" },
    798
    799	{ "lvs1", QCOM_RPM_PM8018_LVS1, &pm8018_switch, "lvs1_in" },
    800
    801	{ }
    802};
    803
    804static const struct rpm_regulator_data rpm_pm8058_regulators[] = {
    805	{ "l0",   QCOM_RPM_PM8058_LDO0,   &pm8058_nldo, "vdd_l0_l1_lvs"	},
    806	{ "l1",   QCOM_RPM_PM8058_LDO1,   &pm8058_nldo, "vdd_l0_l1_lvs" },
    807	{ "l2",   QCOM_RPM_PM8058_LDO2,   &pm8058_pldo, "vdd_l2_l11_l12" },
    808	{ "l3",   QCOM_RPM_PM8058_LDO3,   &pm8058_pldo, "vdd_l3_l4_l5" },
    809	{ "l4",   QCOM_RPM_PM8058_LDO4,   &pm8058_pldo, "vdd_l3_l4_l5" },
    810	{ "l5",   QCOM_RPM_PM8058_LDO5,   &pm8058_pldo, "vdd_l3_l4_l5" },
    811	{ "l6",   QCOM_RPM_PM8058_LDO6,   &pm8058_pldo, "vdd_l6_l7" },
    812	{ "l7",   QCOM_RPM_PM8058_LDO7,   &pm8058_pldo, "vdd_l6_l7" },
    813	{ "l8",   QCOM_RPM_PM8058_LDO8,   &pm8058_pldo, "vdd_l8" },
    814	{ "l9",   QCOM_RPM_PM8058_LDO9,   &pm8058_pldo, "vdd_l9" },
    815	{ "l10",  QCOM_RPM_PM8058_LDO10,  &pm8058_pldo, "vdd_l10" },
    816	{ "l11",  QCOM_RPM_PM8058_LDO11,  &pm8058_pldo, "vdd_l2_l11_l12" },
    817	{ "l12",  QCOM_RPM_PM8058_LDO12,  &pm8058_pldo, "vdd_l2_l11_l12" },
    818	{ "l13",  QCOM_RPM_PM8058_LDO13,  &pm8058_pldo, "vdd_l13_l16" },
    819	{ "l14",  QCOM_RPM_PM8058_LDO14,  &pm8058_pldo, "vdd_l14_l15" },
    820	{ "l15",  QCOM_RPM_PM8058_LDO15,  &pm8058_pldo, "vdd_l14_l15" },
    821	{ "l16",  QCOM_RPM_PM8058_LDO16,  &pm8058_pldo, "vdd_l13_l16" },
    822	{ "l17",  QCOM_RPM_PM8058_LDO17,  &pm8058_pldo, "vdd_l17_l18" },
    823	{ "l18",  QCOM_RPM_PM8058_LDO18,  &pm8058_pldo, "vdd_l17_l18" },
    824	{ "l19",  QCOM_RPM_PM8058_LDO19,  &pm8058_pldo, "vdd_l19_l20" },
    825	{ "l20",  QCOM_RPM_PM8058_LDO20,  &pm8058_pldo, "vdd_l19_l20" },
    826	{ "l21",  QCOM_RPM_PM8058_LDO21,  &pm8058_nldo, "vdd_l21" },
    827	{ "l22",  QCOM_RPM_PM8058_LDO22,  &pm8058_nldo, "vdd_l22" },
    828	{ "l23",  QCOM_RPM_PM8058_LDO23,  &pm8058_nldo, "vdd_l23_l24_l25" },
    829	{ "l24",  QCOM_RPM_PM8058_LDO24,  &pm8058_nldo, "vdd_l23_l24_l25" },
    830	{ "l25",  QCOM_RPM_PM8058_LDO25,  &pm8058_nldo, "vdd_l23_l24_l25" },
    831
    832	{ "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },
    833	{ "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },
    834	{ "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },
    835	{ "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },
    836	{ "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },
    837
    838	{ "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" },
    839	{ "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" },
    840
    841	{ "ncp",  QCOM_RPM_PM8058_NCP, &pm8058_ncp, "vdd_ncp" },
    842	{ }
    843};
    844
    845static const struct rpm_regulator_data rpm_pm8901_regulators[] = {
    846	{ "l0",   QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" },
    847	{ "l1",   QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" },
    848	{ "l2",   QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" },
    849	{ "l3",   QCOM_RPM_PM8901_LDO3, &pm8901_pldo, "vdd_l3" },
    850	{ "l4",   QCOM_RPM_PM8901_LDO4, &pm8901_pldo, "vdd_l4" },
    851	{ "l5",   QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" },
    852	{ "l6",   QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" },
    853
    854	{ "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },
    855	{ "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },
    856	{ "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },
    857	{ "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },
    858	{ "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },
    859
    860	{ "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" },
    861	{ "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" },
    862	{ "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" },
    863	{ "lvs3", QCOM_RPM_PM8901_LVS3, &pm8901_switch, "lvs3_in" },
    864
    865	{ "mvs", QCOM_RPM_PM8901_MVS, &pm8901_switch, "mvs_in" },
    866	{ }
    867};
    868
    869static const struct rpm_regulator_data rpm_pm8921_regulators[] = {
    870	{ "s1",  QCOM_RPM_PM8921_SMPS1, &pm8921_smps, "vdd_s1" },
    871	{ "s2",  QCOM_RPM_PM8921_SMPS2, &pm8921_smps, "vdd_s2" },
    872	{ "s3",  QCOM_RPM_PM8921_SMPS3, &pm8921_smps },
    873	{ "s4",  QCOM_RPM_PM8921_SMPS4, &pm8921_smps, "vdd_s4" },
    874	{ "s7",  QCOM_RPM_PM8921_SMPS7, &pm8921_smps, "vdd_s7" },
    875	{ "s8",  QCOM_RPM_PM8921_SMPS8, &pm8921_smps, "vdd_s8"  },
    876
    877	{ "l1",  QCOM_RPM_PM8921_LDO1, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
    878	{ "l2",  QCOM_RPM_PM8921_LDO2, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
    879	{ "l3",  QCOM_RPM_PM8921_LDO3, &pm8921_pldo, "vdd_l3_l15_l17" },
    880	{ "l4",  QCOM_RPM_PM8921_LDO4, &pm8921_pldo, "vdd_l4_l14" },
    881	{ "l5",  QCOM_RPM_PM8921_LDO5, &pm8921_pldo, "vdd_l5_l8_l16" },
    882	{ "l6",  QCOM_RPM_PM8921_LDO6, &pm8921_pldo, "vdd_l6_l7" },
    883	{ "l7",  QCOM_RPM_PM8921_LDO7, &pm8921_pldo, "vdd_l6_l7" },
    884	{ "l8",  QCOM_RPM_PM8921_LDO8, &pm8921_pldo, "vdd_l5_l8_l16" },
    885	{ "l9",  QCOM_RPM_PM8921_LDO9, &pm8921_pldo, "vdd_l9_l11" },
    886	{ "l10", QCOM_RPM_PM8921_LDO10, &pm8921_pldo, "vdd_l10_l22" },
    887	{ "l11", QCOM_RPM_PM8921_LDO11, &pm8921_pldo, "vdd_l9_l11" },
    888	{ "l12", QCOM_RPM_PM8921_LDO12, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
    889	{ "l14", QCOM_RPM_PM8921_LDO14, &pm8921_pldo, "vdd_l4_l14" },
    890	{ "l15", QCOM_RPM_PM8921_LDO15, &pm8921_pldo, "vdd_l3_l15_l17" },
    891	{ "l16", QCOM_RPM_PM8921_LDO16, &pm8921_pldo, "vdd_l5_l8_l16" },
    892	{ "l17", QCOM_RPM_PM8921_LDO17, &pm8921_pldo, "vdd_l3_l15_l17" },
    893	{ "l18", QCOM_RPM_PM8921_LDO18, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
    894	{ "l21", QCOM_RPM_PM8921_LDO21, &pm8921_pldo, "vdd_l21_l23_l29" },
    895	{ "l22", QCOM_RPM_PM8921_LDO22, &pm8921_pldo, "vdd_l10_l22" },
    896	{ "l23", QCOM_RPM_PM8921_LDO23, &pm8921_pldo, "vdd_l21_l23_l29" },
    897	{ "l24", QCOM_RPM_PM8921_LDO24, &pm8921_nldo1200, "vdd_l24" },
    898	{ "l25", QCOM_RPM_PM8921_LDO25, &pm8921_nldo1200, "vdd_l25" },
    899	{ "l26", QCOM_RPM_PM8921_LDO26, &pm8921_nldo1200, "vdd_l26" },
    900	{ "l27", QCOM_RPM_PM8921_LDO27, &pm8921_nldo1200, "vdd_l27" },
    901	{ "l28", QCOM_RPM_PM8921_LDO28, &pm8921_nldo1200, "vdd_l28" },
    902	{ "l29", QCOM_RPM_PM8921_LDO29, &pm8921_pldo, "vdd_l21_l23_l29" },
    903
    904	{ "lvs1", QCOM_RPM_PM8921_LVS1, &pm8921_switch, "vin_lvs1_3_6" },
    905	{ "lvs2", QCOM_RPM_PM8921_LVS2, &pm8921_switch, "vin_lvs2" },
    906	{ "lvs3", QCOM_RPM_PM8921_LVS3, &pm8921_switch, "vin_lvs1_3_6" },
    907	{ "lvs4", QCOM_RPM_PM8921_LVS4, &pm8921_switch, "vin_lvs4_5_7" },
    908	{ "lvs5", QCOM_RPM_PM8921_LVS5, &pm8921_switch, "vin_lvs4_5_7" },
    909	{ "lvs6", QCOM_RPM_PM8921_LVS6, &pm8921_switch, "vin_lvs1_3_6" },
    910	{ "lvs7", QCOM_RPM_PM8921_LVS7, &pm8921_switch, "vin_lvs4_5_7" },
    911
    912	{ "usb-switch", QCOM_RPM_USB_OTG_SWITCH, &pm8921_switch, "vin_5vs" },
    913	{ "hdmi-switch", QCOM_RPM_HDMI_SWITCH, &pm8921_switch, "vin_5vs" },
    914	{ "ncp", QCOM_RPM_PM8921_NCP, &pm8921_ncp, "vdd_ncp" },
    915	{ }
    916};
    917
    918static const struct rpm_regulator_data rpm_smb208_regulators[] = {
    919	{ "s1a",  QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" },
    920	{ "s1b",  QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" },
    921	{ "s2a",  QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" },
    922	{ "s2b",  QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" },
    923	{ }
    924};
    925
    926static const struct of_device_id rpm_of_match[] = {
    927	{ .compatible = "qcom,rpm-pm8018-regulators",
    928		.data = &rpm_pm8018_regulators },
    929	{ .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
    930	{ .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
    931	{ .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },
    932	{ .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators },
    933	{ }
    934};
    935MODULE_DEVICE_TABLE(of, rpm_of_match);
    936
    937static int rpm_reg_probe(struct platform_device *pdev)
    938{
    939	const struct rpm_regulator_data *reg;
    940	const struct of_device_id *match;
    941	struct regulator_config config = { };
    942	struct regulator_dev *rdev;
    943	struct qcom_rpm_reg *vreg;
    944	struct qcom_rpm *rpm;
    945
    946	rpm = dev_get_drvdata(pdev->dev.parent);
    947	if (!rpm) {
    948		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
    949		return -ENODEV;
    950	}
    951
    952	match = of_match_device(rpm_of_match, &pdev->dev);
    953	if (!match) {
    954		dev_err(&pdev->dev, "failed to match device\n");
    955		return -ENODEV;
    956	}
    957
    958	for (reg = match->data; reg->name; reg++) {
    959		vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
    960		if (!vreg)
    961			return -ENOMEM;
    962
    963		memcpy(vreg, reg->template, sizeof(*vreg));
    964		mutex_init(&vreg->lock);
    965
    966		vreg->dev = &pdev->dev;
    967		vreg->resource = reg->resource;
    968		vreg->rpm = rpm;
    969
    970		vreg->desc.id = -1;
    971		vreg->desc.owner = THIS_MODULE;
    972		vreg->desc.type = REGULATOR_VOLTAGE;
    973		vreg->desc.name = reg->name;
    974		vreg->desc.supply_name = reg->supply;
    975		vreg->desc.of_match = reg->name;
    976		vreg->desc.of_parse_cb = rpm_reg_of_parse;
    977
    978		config.dev = &pdev->dev;
    979		config.driver_data = vreg;
    980		rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
    981		if (IS_ERR(rdev)) {
    982			dev_err(&pdev->dev, "failed to register %s\n", reg->name);
    983			return PTR_ERR(rdev);
    984		}
    985	}
    986
    987	return 0;
    988}
    989
    990static struct platform_driver rpm_reg_driver = {
    991	.probe          = rpm_reg_probe,
    992	.driver  = {
    993		.name  = "qcom_rpm_reg",
    994		.of_match_table = of_match_ptr(rpm_of_match),
    995	},
    996};
    997
    998static int __init rpm_reg_init(void)
    999{
   1000	return platform_driver_register(&rpm_reg_driver);
   1001}
   1002subsys_initcall(rpm_reg_init);
   1003
   1004static void __exit rpm_reg_exit(void)
   1005{
   1006	platform_driver_unregister(&rpm_reg_driver);
   1007}
   1008module_exit(rpm_reg_exit)
   1009
   1010MODULE_DESCRIPTION("Qualcomm RPM regulator driver");
   1011MODULE_LICENSE("GPL v2");