brintos

brintos / linux-shallow public Read only

0
0
Text · 29.0 KiB · 2d5fec1 Raw
1011 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 219 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 ranges150 */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 regulators444 */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 regulators482 */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 regulators528 */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 regulators566 */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 the728		 * possible register values are:729		 * NONE, LPM, HPM730		 * otherwise:731		 * NONE, LPM, AUTO, HPM, BYPASS732		 */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			else744				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	{ "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },806	{ "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },807	{ "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },808	{ "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },809	{ "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },810 811	{ "l0",   QCOM_RPM_PM8058_LDO0,   &pm8058_nldo, "vdd_l0_l1_lvs"	},812	{ "l1",   QCOM_RPM_PM8058_LDO1,   &pm8058_nldo, "vdd_l0_l1_lvs" },813	{ "l2",   QCOM_RPM_PM8058_LDO2,   &pm8058_pldo, "vdd_l2_l11_l12" },814	{ "l3",   QCOM_RPM_PM8058_LDO3,   &pm8058_pldo, "vdd_l3_l4_l5" },815	{ "l4",   QCOM_RPM_PM8058_LDO4,   &pm8058_pldo, "vdd_l3_l4_l5" },816	{ "l5",   QCOM_RPM_PM8058_LDO5,   &pm8058_pldo, "vdd_l3_l4_l5" },817	{ "l6",   QCOM_RPM_PM8058_LDO6,   &pm8058_pldo, "vdd_l6_l7" },818	{ "l7",   QCOM_RPM_PM8058_LDO7,   &pm8058_pldo, "vdd_l6_l7" },819	{ "l8",   QCOM_RPM_PM8058_LDO8,   &pm8058_pldo, "vdd_l8" },820	{ "l9",   QCOM_RPM_PM8058_LDO9,   &pm8058_pldo, "vdd_l9" },821	{ "l10",  QCOM_RPM_PM8058_LDO10,  &pm8058_pldo, "vdd_l10" },822	{ "l11",  QCOM_RPM_PM8058_LDO11,  &pm8058_pldo, "vdd_l2_l11_l12" },823	{ "l12",  QCOM_RPM_PM8058_LDO12,  &pm8058_pldo, "vdd_l2_l11_l12" },824	{ "l13",  QCOM_RPM_PM8058_LDO13,  &pm8058_pldo, "vdd_l13_l16" },825	{ "l14",  QCOM_RPM_PM8058_LDO14,  &pm8058_pldo, "vdd_l14_l15" },826	{ "l15",  QCOM_RPM_PM8058_LDO15,  &pm8058_pldo, "vdd_l14_l15" },827	{ "l16",  QCOM_RPM_PM8058_LDO16,  &pm8058_pldo, "vdd_l13_l16" },828	{ "l17",  QCOM_RPM_PM8058_LDO17,  &pm8058_pldo, "vdd_l17_l18" },829	{ "l18",  QCOM_RPM_PM8058_LDO18,  &pm8058_pldo, "vdd_l17_l18" },830	{ "l19",  QCOM_RPM_PM8058_LDO19,  &pm8058_pldo, "vdd_l19_l20" },831	{ "l20",  QCOM_RPM_PM8058_LDO20,  &pm8058_pldo, "vdd_l19_l20" },832	{ "l21",  QCOM_RPM_PM8058_LDO21,  &pm8058_nldo, "vdd_l21" },833	{ "l22",  QCOM_RPM_PM8058_LDO22,  &pm8058_nldo, "vdd_l22" },834	{ "l23",  QCOM_RPM_PM8058_LDO23,  &pm8058_nldo, "vdd_l23_l24_l25" },835	{ "l24",  QCOM_RPM_PM8058_LDO24,  &pm8058_nldo, "vdd_l23_l24_l25" },836	{ "l25",  QCOM_RPM_PM8058_LDO25,  &pm8058_nldo, "vdd_l23_l24_l25" },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	{ "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },847	{ "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },848	{ "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },849	{ "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },850	{ "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },851 852	{ "l0",   QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" },853	{ "l1",   QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" },854	{ "l2",   QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" },855	{ "l3",   QCOM_RPM_PM8901_LDO3, &pm8901_pldo, "vdd_l3" },856	{ "l4",   QCOM_RPM_PM8901_LDO4, &pm8901_pldo, "vdd_l4" },857	{ "l5",   QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" },858	{ "l6",   QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" },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	struct regulator_config config = { };941	struct regulator_dev *rdev;942	struct qcom_rpm_reg *vreg;943	struct qcom_rpm *rpm;944 945	rpm = dev_get_drvdata(pdev->dev.parent);946	if (!rpm) {947		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");948		return -ENODEV;949	}950 951	reg = device_get_match_data(&pdev->dev);952	if (!reg) {953		dev_err(&pdev->dev, "failed to match device\n");954		return -ENODEV;955	}956 957	for (; reg->name; reg++) {958		vreg = devm_kmemdup(&pdev->dev, reg->template, sizeof(*vreg), GFP_KERNEL);959		if (!vreg)960			return -ENOMEM;961 962		mutex_init(&vreg->lock);963 964		vreg->dev = &pdev->dev;965		vreg->resource = reg->resource;966		vreg->rpm = rpm;967 968		vreg->desc.id = -1;969		vreg->desc.owner = THIS_MODULE;970		vreg->desc.type = REGULATOR_VOLTAGE;971		vreg->desc.name = reg->name;972		vreg->desc.supply_name = reg->supply;973		vreg->desc.of_match = reg->name;974		vreg->desc.of_parse_cb = rpm_reg_of_parse;975 976		config.dev = &pdev->dev;977		config.driver_data = vreg;978		rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);979		if (IS_ERR(rdev)) {980			dev_err(&pdev->dev, "failed to register %s\n", reg->name);981			return PTR_ERR(rdev);982		}983	}984 985	return 0;986}987 988static struct platform_driver rpm_reg_driver = {989	.probe          = rpm_reg_probe,990	.driver  = {991		.name  = "qcom_rpm_reg",992		.probe_type = PROBE_PREFER_ASYNCHRONOUS,993		.of_match_table = of_match_ptr(rpm_of_match),994	},995};996 997static int __init rpm_reg_init(void)998{999	return platform_driver_register(&rpm_reg_driver);1000}1001subsys_initcall(rpm_reg_init);1002 1003static void __exit rpm_reg_exit(void)1004{1005	platform_driver_unregister(&rpm_reg_driver);1006}1007module_exit(rpm_reg_exit)1008 1009MODULE_DESCRIPTION("Qualcomm RPM regulator driver");1010MODULE_LICENSE("GPL v2");1011