brintos

brintos / linux-shallow public Read only

0
0
Text · 12.1 KiB · b9955aa Raw
475 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) ST-Ericsson SA 20104 *5 * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com>6 *7 * This file is based on drivers/regulator/ab8500.c8 *9 * AB8500 external regulators10 *11 * ab8500-ext supports the following regulators:12 * - VextSupply313 */14#include <linux/init.h>15#include <linux/kernel.h>16#include <linux/err.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/platform_device.h>20#include <linux/regulator/driver.h>21#include <linux/regulator/machine.h>22#include <linux/regulator/of_regulator.h>23#include <linux/mfd/abx500.h>24#include <linux/mfd/abx500/ab8500.h>25 26/* AB8500 external regulators */27enum ab8500_ext_regulator_id {28	AB8500_EXT_SUPPLY1,29	AB8500_EXT_SUPPLY2,30	AB8500_EXT_SUPPLY3,31	AB8500_NUM_EXT_REGULATORS,32};33 34struct ab8500_ext_regulator_cfg {35	bool hwreq; /* requires hw mode or high power mode */36};37 38/* supply for VextSupply3 */39static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {40	/* SIM supply for 3 V SIM cards */41	REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),42};43 44/*45 * AB8500 external regulators46 */47static struct regulator_init_data ab8500_ext_regulators[] = {48	/* fixed Vbat supplies VSMPS1_EXT_1V8 */49	[AB8500_EXT_SUPPLY1] = {50		.constraints = {51			.name = "ab8500-ext-supply1",52			.min_uV = 1800000,53			.max_uV = 1800000,54			.initial_mode = REGULATOR_MODE_IDLE,55			.boot_on = 1,56			.always_on = 1,57		},58	},59	/* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */60	[AB8500_EXT_SUPPLY2] = {61		.constraints = {62			.name = "ab8500-ext-supply2",63			.min_uV = 1360000,64			.max_uV = 1360000,65		},66	},67	/* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */68	[AB8500_EXT_SUPPLY3] = {69		.constraints = {70			.name = "ab8500-ext-supply3",71			.min_uV = 3400000,72			.max_uV = 3400000,73			.valid_ops_mask = REGULATOR_CHANGE_STATUS,74			.boot_on = 1,75		},76		.num_consumer_supplies =77			ARRAY_SIZE(ab8500_ext_supply3_consumers),78		.consumer_supplies = ab8500_ext_supply3_consumers,79	},80};81 82/**83 * struct ab8500_ext_regulator_info - ab8500 regulator information84 * @dev: device pointer85 * @desc: regulator description86 * @cfg: regulator configuration (extension of regulator FW configuration)87 * @update_bank: bank to control on/off88 * @update_reg: register to control on/off89 * @update_mask: mask to enable/disable and set mode of regulator90 * @update_val: bits holding the regulator current mode91 * @update_val_hp: bits to set EN pin active (LPn pin deactive)92 *                 normally this means high power mode93 * @update_val_lp: bits to set EN pin active and LPn pin active94 *                 normally this means low power mode95 * @update_val_hw: bits to set regulator pins in HW control96 *                 SysClkReq pins and logic will choose mode97 */98struct ab8500_ext_regulator_info {99	struct device *dev;100	struct regulator_desc desc;101	struct ab8500_ext_regulator_cfg *cfg;102	u8 update_bank;103	u8 update_reg;104	u8 update_mask;105	u8 update_val;106	u8 update_val_hp;107	u8 update_val_lp;108	u8 update_val_hw;109};110 111static int ab8500_ext_regulator_enable(struct regulator_dev *rdev)112{113	int ret;114	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);115	u8 regval;116 117	if (info == NULL) {118		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");119		return -EINVAL;120	}121 122	/*123	 * To satisfy both HW high power request and SW request, the regulator124	 * must be on in high power.125	 */126	if (info->cfg && info->cfg->hwreq)127		regval = info->update_val_hp;128	else129		regval = info->update_val;130 131	ret = abx500_mask_and_set_register_interruptible(info->dev,132		info->update_bank, info->update_reg,133		info->update_mask, regval);134	if (ret < 0) {135		dev_err(rdev_get_dev(rdev),136			"couldn't set enable bits for regulator\n");137		return ret;138	}139 140	dev_dbg(rdev_get_dev(rdev),141		"%s-enable (bank, reg, mask, value): 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",142		info->desc.name, info->update_bank, info->update_reg,143		info->update_mask, regval);144 145	return 0;146}147 148static int ab8500_ext_regulator_disable(struct regulator_dev *rdev)149{150	int ret;151	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);152	u8 regval;153 154	if (info == NULL) {155		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");156		return -EINVAL;157	}158 159	/*160	 * Set the regulator in HW request mode if configured161	 */162	if (info->cfg && info->cfg->hwreq)163		regval = info->update_val_hw;164	else165		regval = 0;166 167	ret = abx500_mask_and_set_register_interruptible(info->dev,168		info->update_bank, info->update_reg,169		info->update_mask, regval);170	if (ret < 0) {171		dev_err(rdev_get_dev(rdev),172			"couldn't set disable bits for regulator\n");173		return ret;174	}175 176	dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):"177		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",178		info->desc.name, info->update_bank, info->update_reg,179		info->update_mask, regval);180 181	return 0;182}183 184static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev)185{186	int ret;187	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);188	u8 regval;189 190	if (info == NULL) {191		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");192		return -EINVAL;193	}194 195	ret = abx500_get_register_interruptible(info->dev,196		info->update_bank, info->update_reg, &regval);197	if (ret < 0) {198		dev_err(rdev_get_dev(rdev),199			"couldn't read 0x%x register\n", info->update_reg);200		return ret;201	}202 203	dev_dbg(rdev_get_dev(rdev), "%s-is_enabled (bank, reg, mask, value):"204		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",205		info->desc.name, info->update_bank, info->update_reg,206		info->update_mask, regval);207 208	if (((regval & info->update_mask) == info->update_val_lp) ||209	    ((regval & info->update_mask) == info->update_val_hp))210		return 1;211	else212		return 0;213}214 215static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev,216					 unsigned int mode)217{218	int ret = 0;219	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);220	u8 regval;221 222	if (info == NULL) {223		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");224		return -EINVAL;225	}226 227	switch (mode) {228	case REGULATOR_MODE_NORMAL:229		regval = info->update_val_hp;230		break;231	case REGULATOR_MODE_IDLE:232		regval = info->update_val_lp;233		break;234 235	default:236		return -EINVAL;237	}238 239	/* If regulator is enabled and info->cfg->hwreq is set, the regulator240	   must be on in high power, so we don't need to write the register with241	   the same value.242	 */243	if (ab8500_ext_regulator_is_enabled(rdev) &&244	    !(info->cfg && info->cfg->hwreq)) {245		ret = abx500_mask_and_set_register_interruptible(info->dev,246					info->update_bank, info->update_reg,247					info->update_mask, regval);248		if (ret < 0) {249			dev_err(rdev_get_dev(rdev),250				"Could not set regulator mode.\n");251			return ret;252		}253 254		dev_dbg(rdev_get_dev(rdev),255			"%s-set_mode (bank, reg, mask, value): "256			"0x%x, 0x%x, 0x%x, 0x%x\n",257			info->desc.name, info->update_bank, info->update_reg,258			info->update_mask, regval);259	}260 261	info->update_val = regval;262 263	return 0;264}265 266static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev)267{268	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);269	int ret;270 271	if (info == NULL) {272		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");273		return -EINVAL;274	}275 276	if (info->update_val == info->update_val_hp)277		ret = REGULATOR_MODE_NORMAL;278	else if (info->update_val == info->update_val_lp)279		ret = REGULATOR_MODE_IDLE;280	else281		ret = -EINVAL;282 283	return ret;284}285 286static int ab8500_ext_set_voltage(struct regulator_dev *rdev, int min_uV,287				  int max_uV, unsigned *selector)288{289	struct regulation_constraints *regu_constraints = rdev->constraints;290 291	if (!regu_constraints) {292		dev_err(rdev_get_dev(rdev), "No regulator constraints\n");293		return -EINVAL;294	}295 296	if (regu_constraints->min_uV == min_uV &&297	    regu_constraints->max_uV == max_uV)298		return 0;299 300	dev_err(rdev_get_dev(rdev),301		"Requested min %duV max %duV != constrained min %duV max %duV\n",302		min_uV, max_uV,303		regu_constraints->min_uV, regu_constraints->max_uV);304 305	return -EINVAL;306}307 308static int ab8500_ext_list_voltage(struct regulator_dev *rdev,309				   unsigned selector)310{311	struct regulation_constraints *regu_constraints = rdev->constraints;312 313	if (regu_constraints == NULL) {314		dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n");315		return -EINVAL;316	}317	/* return the uV for the fixed regulators */318	if (regu_constraints->min_uV && regu_constraints->max_uV) {319		if (regu_constraints->min_uV == regu_constraints->max_uV)320			return regu_constraints->min_uV;321	}322	return -EINVAL;323}324 325static const struct regulator_ops ab8500_ext_regulator_ops = {326	.enable			= ab8500_ext_regulator_enable,327	.disable		= ab8500_ext_regulator_disable,328	.is_enabled		= ab8500_ext_regulator_is_enabled,329	.set_mode		= ab8500_ext_regulator_set_mode,330	.get_mode		= ab8500_ext_regulator_get_mode,331	.set_voltage		= ab8500_ext_set_voltage,332	.list_voltage		= ab8500_ext_list_voltage,333};334 335static struct ab8500_ext_regulator_info336		ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = {337	[AB8500_EXT_SUPPLY1] = {338		.desc = {339			.name		= "VEXTSUPPLY1",340			.of_match	= of_match_ptr("ab8500_ext1"),341			.ops		= &ab8500_ext_regulator_ops,342			.type		= REGULATOR_VOLTAGE,343			.id		= AB8500_EXT_SUPPLY1,344			.owner		= THIS_MODULE,345			.n_voltages	= 1,346		},347		.update_bank		= 0x04,348		.update_reg		= 0x08,349		.update_mask		= 0x03,350		.update_val		= 0x01,351		.update_val_hp		= 0x01,352		.update_val_lp		= 0x03,353		.update_val_hw		= 0x02,354	},355	[AB8500_EXT_SUPPLY2] = {356		.desc = {357			.name		= "VEXTSUPPLY2",358			.of_match	= of_match_ptr("ab8500_ext2"),359			.ops		= &ab8500_ext_regulator_ops,360			.type		= REGULATOR_VOLTAGE,361			.id		= AB8500_EXT_SUPPLY2,362			.owner		= THIS_MODULE,363			.n_voltages	= 1,364		},365		.update_bank		= 0x04,366		.update_reg		= 0x08,367		.update_mask		= 0x0c,368		.update_val		= 0x04,369		.update_val_hp		= 0x04,370		.update_val_lp		= 0x0c,371		.update_val_hw		= 0x08,372	},373	[AB8500_EXT_SUPPLY3] = {374		.desc = {375			.name		= "VEXTSUPPLY3",376			.of_match	= of_match_ptr("ab8500_ext3"),377			.ops		= &ab8500_ext_regulator_ops,378			.type		= REGULATOR_VOLTAGE,379			.id		= AB8500_EXT_SUPPLY3,380			.owner		= THIS_MODULE,381			.n_voltages	= 1,382		},383		.update_bank		= 0x04,384		.update_reg		= 0x08,385		.update_mask		= 0x30,386		.update_val		= 0x10,387		.update_val_hp		= 0x10,388		.update_val_lp		= 0x30,389		.update_val_hw		= 0x20,390	},391};392 393static int ab8500_ext_regulator_probe(struct platform_device *pdev)394{395	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);396	struct regulator_config config = { };397	struct regulator_dev *rdev;398	int i;399 400	if (!ab8500) {401		dev_err(&pdev->dev, "null mfd parent\n");402		return -EINVAL;403	}404 405	/* check for AB8500 2.x */406	if (is_ab8500_2p0_or_earlier(ab8500)) {407		struct ab8500_ext_regulator_info *info;408 409		/* VextSupply3LPn is inverted on AB8500 2.x */410		info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3];411		info->update_val = 0x30;412		info->update_val_hp = 0x30;413		info->update_val_lp = 0x10;414	}415 416	/* register all regulators */417	for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {418		struct ab8500_ext_regulator_info *info = NULL;419 420		/* assign per-regulator data */421		info = &ab8500_ext_regulator_info[i];422		info->dev = &pdev->dev;423		info->cfg = (struct ab8500_ext_regulator_cfg *)424			ab8500_ext_regulators[i].driver_data;425 426		config.dev = &pdev->dev;427		config.driver_data = info;428		config.init_data = &ab8500_ext_regulators[i];429 430		/* register regulator with framework */431		rdev = devm_regulator_register(&pdev->dev, &info->desc,432					       &config);433		if (IS_ERR(rdev)) {434			dev_err(&pdev->dev, "failed to register regulator %s\n",435					info->desc.name);436			return PTR_ERR(rdev);437		}438 439		dev_dbg(&pdev->dev, "%s-probed\n", info->desc.name);440	}441 442	return 0;443}444 445static struct platform_driver ab8500_ext_regulator_driver = {446	.probe = ab8500_ext_regulator_probe,447	.driver         = {448		.name   = "ab8500-ext-regulator",449		.probe_type = PROBE_PREFER_ASYNCHRONOUS,450	},451};452 453static int __init ab8500_ext_regulator_init(void)454{455	int ret;456 457	ret = platform_driver_register(&ab8500_ext_regulator_driver);458	if (ret)459		pr_err("Failed to register ab8500 ext regulator: %d\n", ret);460 461	return ret;462}463subsys_initcall(ab8500_ext_regulator_init);464 465static void __exit ab8500_ext_regulator_exit(void)466{467	platform_driver_unregister(&ab8500_ext_regulator_driver);468}469module_exit(ab8500_ext_regulator_exit);470 471MODULE_LICENSE("GPL v2");472MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");473MODULE_DESCRIPTION("AB8500 external regulator driver");474MODULE_ALIAS("platform:ab8500-ext-regulator");475