brintos

brintos / linux-shallow public Read only

0
0
Text · 16.0 KiB · c7b270f Raw
539 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// max77686.c - Regulator driver for the Maxim 776864//5// Copyright (C) 2012 Samsung Electronics6// Chiwoong Byun <woong.byun@samsung.com>7// Jonghwa Lee <jonghwa3.lee@samsung.com>8//9// This driver is based on max8997.c10 11#include <linux/kernel.h>12#include <linux/bug.h>13#include <linux/err.h>14#include <linux/gpio/consumer.h>15#include <linux/slab.h>16#include <linux/platform_device.h>17#include <linux/regulator/driver.h>18#include <linux/regulator/machine.h>19#include <linux/regulator/of_regulator.h>20#include <linux/mfd/max77686.h>21#include <linux/mfd/max77686-private.h>22 23#define MAX77686_LDO_MINUV	80000024#define MAX77686_LDO_UVSTEP	5000025#define MAX77686_LDO_LOW_MINUV	80000026#define MAX77686_LDO_LOW_UVSTEP	2500027#define MAX77686_BUCK_MINUV	75000028#define MAX77686_BUCK_UVSTEP	5000029#define MAX77686_BUCK_ENABLE_TIME	40		/* us */30#define MAX77686_DVS_ENABLE_TIME	22		/* us */31#define MAX77686_RAMP_DELAY	100000			/* uV/us */32#define MAX77686_DVS_RAMP_DELAY	27500			/* uV/us */33#define MAX77686_DVS_MINUV	60000034#define MAX77686_DVS_UVSTEP	1250035 36/*37 * Value for configuring buck[89] and LDO{20,21,22} as GPIO control.38 * It is the same as 'off' for other regulators.39 */40#define MAX77686_GPIO_CONTROL		0x041/*42 * Values used for configuring LDOs and bucks.43 * Forcing low power mode: LDO1, 3-5, 9, 13, 17-2644 */45#define MAX77686_LDO_LOWPOWER		0x146/*47 * On/off controlled by PWRREQ:48 *  - LDO2, 6-8, 10-12, 14-1649 *  - buck[1234]50 */51#define MAX77686_OFF_PWRREQ		0x152/* Low power mode controlled by PWRREQ: All LDOs */53#define MAX77686_LDO_LOWPOWER_PWRREQ	0x254/* Forcing low power mode: buck[234] */55#define MAX77686_BUCK_LOWPOWER		0x256#define MAX77686_NORMAL			0x357 58#define MAX77686_OPMODE_SHIFT	659#define MAX77686_OPMODE_BUCK234_SHIFT	460#define MAX77686_OPMODE_MASK	0x361 62#define MAX77686_VSEL_MASK	0x3F63#define MAX77686_DVS_VSEL_MASK	0xFF64 65#define MAX77686_RAMP_RATE_MASK	0xC066 67#define MAX77686_REGULATORS	MAX77686_REG_MAX68#define MAX77686_LDOS		2669 70struct max77686_data {71	struct device *dev;72	DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);73 74	/* Array indexed by regulator id */75	unsigned int opmode[MAX77686_REGULATORS];76};77 78static unsigned int max77686_get_opmode_shift(int id)79{80	switch (id) {81	case MAX77686_BUCK1:82	case MAX77686_BUCK5 ... MAX77686_BUCK9:83		return 0;84	case MAX77686_BUCK2 ... MAX77686_BUCK4:85		return MAX77686_OPMODE_BUCK234_SHIFT;86	default:87		/* all LDOs */88		return MAX77686_OPMODE_SHIFT;89	}90}91 92/*93 * When regulator is configured for GPIO control then it94 * replaces "normal" mode. Any change from low power mode to normal95 * should actually change to GPIO control.96 * Map normal mode to proper value for such regulators.97 */98static unsigned int max77686_map_normal_mode(struct max77686_data *max77686,99					     int id)100{101	switch (id) {102	case MAX77686_BUCK8:103	case MAX77686_BUCK9:104	case MAX77686_LDO20 ... MAX77686_LDO22:105		if (test_bit(id, max77686->gpio_enabled))106			return MAX77686_GPIO_CONTROL;107	}108 109	return MAX77686_NORMAL;110}111 112/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */113static int max77686_set_suspend_disable(struct regulator_dev *rdev)114{115	unsigned int val, shift;116	struct max77686_data *max77686 = rdev_get_drvdata(rdev);117	int ret, id = rdev_get_id(rdev);118 119	shift = max77686_get_opmode_shift(id);120	val = MAX77686_OFF_PWRREQ;121 122	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,123				 rdev->desc->enable_mask, val << shift);124	if (ret)125		return ret;126 127	max77686->opmode[id] = val;128	return 0;129}130 131/* Some LDOs supports [LPM/Normal]ON mode during suspend state */132static int max77686_set_suspend_mode(struct regulator_dev *rdev,133				     unsigned int mode)134{135	struct max77686_data *max77686 = rdev_get_drvdata(rdev);136	unsigned int val;137	int ret, id = rdev_get_id(rdev);138 139	/* BUCK[5-9] doesn't support this feature */140	if (id >= MAX77686_BUCK5)141		return 0;142 143	switch (mode) {144	case REGULATOR_MODE_IDLE:			/* ON in LP Mode */145		val = MAX77686_LDO_LOWPOWER_PWRREQ;146		break;147	case REGULATOR_MODE_NORMAL:			/* ON in Normal Mode */148		val = max77686_map_normal_mode(max77686, id);149		break;150	default:151		pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",152			rdev->desc->name, mode);153		return -EINVAL;154	}155 156	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,157				  rdev->desc->enable_mask,158				  val << MAX77686_OPMODE_SHIFT);159	if (ret)160		return ret;161 162	max77686->opmode[id] = val;163	return 0;164}165 166/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */167static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,168				     unsigned int mode)169{170	unsigned int val;171	struct max77686_data *max77686 = rdev_get_drvdata(rdev);172	int ret, id = rdev_get_id(rdev);173 174	switch (mode) {175	case REGULATOR_MODE_STANDBY:			/* switch off */176		val = MAX77686_OFF_PWRREQ;177		break;178	case REGULATOR_MODE_IDLE:			/* ON in LP Mode */179		val = MAX77686_LDO_LOWPOWER_PWRREQ;180		break;181	case REGULATOR_MODE_NORMAL:			/* ON in Normal Mode */182		val = max77686_map_normal_mode(max77686, id);183		break;184	default:185		pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",186			rdev->desc->name, mode);187		return -EINVAL;188	}189 190	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,191				 rdev->desc->enable_mask,192				 val << MAX77686_OPMODE_SHIFT);193	if (ret)194		return ret;195 196	max77686->opmode[id] = val;197	return 0;198}199 200static int max77686_enable(struct regulator_dev *rdev)201{202	struct max77686_data *max77686 = rdev_get_drvdata(rdev);203	unsigned int shift;204	int id = rdev_get_id(rdev);205 206	shift = max77686_get_opmode_shift(id);207 208	if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)209		max77686->opmode[id] = max77686_map_normal_mode(max77686, id);210 211	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,212				  rdev->desc->enable_mask,213				  max77686->opmode[id] << shift);214}215 216static int max77686_of_parse_cb(struct device_node *np,217		const struct regulator_desc *desc,218		struct regulator_config *config)219{220	struct max77686_data *max77686 = config->driver_data;221	int ret;222 223	switch (desc->id) {224	case MAX77686_BUCK8:225	case MAX77686_BUCK9:226	case MAX77686_LDO20 ... MAX77686_LDO22:227		config->ena_gpiod = fwnode_gpiod_get_index(228				of_fwnode_handle(np),229				"maxim,ena",230				0,231				GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,232				"max77686-regulator");233		if (IS_ERR(config->ena_gpiod))234			config->ena_gpiod = NULL;235		break;236	default:237		return 0;238	}239 240	if (config->ena_gpiod) {241		set_bit(desc->id, max77686->gpio_enabled);242 243		ret = regmap_update_bits(config->regmap, desc->enable_reg,244					 desc->enable_mask,245					 MAX77686_GPIO_CONTROL);246		if (ret) {247			gpiod_put(config->ena_gpiod);248			config->ena_gpiod = NULL;249		}250	}251 252	return 0;253}254 255static const unsigned int max77686_buck_dvs_ramp_table[] = {256	13750, 27500, 55000, 100000257};258 259static const struct regulator_ops max77686_ops = {260	.list_voltage		= regulator_list_voltage_linear,261	.map_voltage		= regulator_map_voltage_linear,262	.is_enabled		= regulator_is_enabled_regmap,263	.enable			= max77686_enable,264	.disable		= regulator_disable_regmap,265	.get_voltage_sel	= regulator_get_voltage_sel_regmap,266	.set_voltage_sel	= regulator_set_voltage_sel_regmap,267	.set_voltage_time_sel	= regulator_set_voltage_time_sel,268	.set_suspend_mode	= max77686_set_suspend_mode,269};270 271static const struct regulator_ops max77686_ldo_ops = {272	.list_voltage		= regulator_list_voltage_linear,273	.map_voltage		= regulator_map_voltage_linear,274	.is_enabled		= regulator_is_enabled_regmap,275	.enable			= max77686_enable,276	.disable		= regulator_disable_regmap,277	.get_voltage_sel	= regulator_get_voltage_sel_regmap,278	.set_voltage_sel	= regulator_set_voltage_sel_regmap,279	.set_voltage_time_sel	= regulator_set_voltage_time_sel,280	.set_suspend_mode	= max77686_ldo_set_suspend_mode,281	.set_suspend_disable	= max77686_set_suspend_disable,282};283 284static const struct regulator_ops max77686_buck1_ops = {285	.list_voltage		= regulator_list_voltage_linear,286	.map_voltage		= regulator_map_voltage_linear,287	.is_enabled		= regulator_is_enabled_regmap,288	.enable			= max77686_enable,289	.disable		= regulator_disable_regmap,290	.get_voltage_sel	= regulator_get_voltage_sel_regmap,291	.set_voltage_sel	= regulator_set_voltage_sel_regmap,292	.set_voltage_time_sel	= regulator_set_voltage_time_sel,293	.set_suspend_disable	= max77686_set_suspend_disable,294};295 296static const struct regulator_ops max77686_buck_dvs_ops = {297	.list_voltage		= regulator_list_voltage_linear,298	.map_voltage		= regulator_map_voltage_linear,299	.is_enabled		= regulator_is_enabled_regmap,300	.enable			= max77686_enable,301	.disable		= regulator_disable_regmap,302	.get_voltage_sel	= regulator_get_voltage_sel_regmap,303	.set_voltage_sel	= regulator_set_voltage_sel_regmap,304	.set_voltage_time_sel	= regulator_set_voltage_time_sel,305	.set_ramp_delay		= regulator_set_ramp_delay_regmap,306	.set_suspend_disable	= max77686_set_suspend_disable,307};308 309#define regulator_desc_ldo(num)		{				\310	.name		= "LDO"#num,					\311	.of_match	= of_match_ptr("LDO"#num),			\312	.regulators_node	= of_match_ptr("voltage-regulators"),	\313	.of_parse_cb	= max77686_of_parse_cb,				\314	.id		= MAX77686_LDO##num,				\315	.ops		= &max77686_ops,				\316	.type		= REGULATOR_VOLTAGE,				\317	.owner		= THIS_MODULE,					\318	.min_uV		= MAX77686_LDO_MINUV,				\319	.uV_step	= MAX77686_LDO_UVSTEP,				\320	.ramp_delay	= MAX77686_RAMP_DELAY,				\321	.n_voltages	= MAX77686_VSEL_MASK + 1,			\322	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\323	.vsel_mask	= MAX77686_VSEL_MASK,				\324	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\325	.enable_mask	= MAX77686_OPMODE_MASK				\326			<< MAX77686_OPMODE_SHIFT,			\327}328#define regulator_desc_lpm_ldo(num)	{				\329	.name		= "LDO"#num,					\330	.of_match	= of_match_ptr("LDO"#num),			\331	.regulators_node	= of_match_ptr("voltage-regulators"),	\332	.id		= MAX77686_LDO##num,				\333	.ops		= &max77686_ldo_ops,				\334	.type		= REGULATOR_VOLTAGE,				\335	.owner		= THIS_MODULE,					\336	.min_uV		= MAX77686_LDO_MINUV,				\337	.uV_step	= MAX77686_LDO_UVSTEP,				\338	.ramp_delay	= MAX77686_RAMP_DELAY,				\339	.n_voltages	= MAX77686_VSEL_MASK + 1,			\340	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\341	.vsel_mask	= MAX77686_VSEL_MASK,				\342	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\343	.enable_mask	= MAX77686_OPMODE_MASK				\344			<< MAX77686_OPMODE_SHIFT,			\345}346#define regulator_desc_ldo_low(num)		{			\347	.name		= "LDO"#num,					\348	.of_match	= of_match_ptr("LDO"#num),			\349	.regulators_node	= of_match_ptr("voltage-regulators"),	\350	.id		= MAX77686_LDO##num,				\351	.ops		= &max77686_ldo_ops,				\352	.type		= REGULATOR_VOLTAGE,				\353	.owner		= THIS_MODULE,					\354	.min_uV		= MAX77686_LDO_LOW_MINUV,			\355	.uV_step	= MAX77686_LDO_LOW_UVSTEP,			\356	.ramp_delay	= MAX77686_RAMP_DELAY,				\357	.n_voltages	= MAX77686_VSEL_MASK + 1,			\358	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\359	.vsel_mask	= MAX77686_VSEL_MASK,				\360	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\361	.enable_mask	= MAX77686_OPMODE_MASK				\362			<< MAX77686_OPMODE_SHIFT,			\363}364#define regulator_desc_ldo1_low(num)		{			\365	.name		= "LDO"#num,					\366	.of_match	= of_match_ptr("LDO"#num),			\367	.regulators_node	= of_match_ptr("voltage-regulators"),	\368	.id		= MAX77686_LDO##num,				\369	.ops		= &max77686_ops,				\370	.type		= REGULATOR_VOLTAGE,				\371	.owner		= THIS_MODULE,					\372	.min_uV		= MAX77686_LDO_LOW_MINUV,			\373	.uV_step	= MAX77686_LDO_LOW_UVSTEP,			\374	.ramp_delay	= MAX77686_RAMP_DELAY,				\375	.n_voltages	= MAX77686_VSEL_MASK + 1,			\376	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\377	.vsel_mask	= MAX77686_VSEL_MASK,				\378	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\379	.enable_mask	= MAX77686_OPMODE_MASK				\380			<< MAX77686_OPMODE_SHIFT,			\381}382#define regulator_desc_buck(num)		{			\383	.name		= "BUCK"#num,					\384	.of_match	= of_match_ptr("BUCK"#num),			\385	.regulators_node	= of_match_ptr("voltage-regulators"),	\386	.of_parse_cb	= max77686_of_parse_cb,				\387	.id		= MAX77686_BUCK##num,				\388	.ops		= &max77686_ops,				\389	.type		= REGULATOR_VOLTAGE,				\390	.owner		= THIS_MODULE,					\391	.min_uV		= MAX77686_BUCK_MINUV,				\392	.uV_step	= MAX77686_BUCK_UVSTEP,				\393	.ramp_delay	= MAX77686_RAMP_DELAY,				\394	.enable_time	= MAX77686_BUCK_ENABLE_TIME,			\395	.n_voltages	= MAX77686_VSEL_MASK + 1,			\396	.vsel_reg	= MAX77686_REG_BUCK5OUT + (num - 5) * 2,	\397	.vsel_mask	= MAX77686_VSEL_MASK,				\398	.enable_reg	= MAX77686_REG_BUCK5CTRL + (num - 5) * 2,	\399	.enable_mask	= MAX77686_OPMODE_MASK,				\400}401#define regulator_desc_buck1(num)		{			\402	.name		= "BUCK"#num,					\403	.of_match	= of_match_ptr("BUCK"#num),			\404	.regulators_node	= of_match_ptr("voltage-regulators"),	\405	.id		= MAX77686_BUCK##num,				\406	.ops		= &max77686_buck1_ops,				\407	.type		= REGULATOR_VOLTAGE,				\408	.owner		= THIS_MODULE,					\409	.min_uV		= MAX77686_BUCK_MINUV,				\410	.uV_step	= MAX77686_BUCK_UVSTEP,				\411	.ramp_delay	= MAX77686_RAMP_DELAY,				\412	.enable_time	= MAX77686_BUCK_ENABLE_TIME,			\413	.n_voltages	= MAX77686_VSEL_MASK + 1,			\414	.vsel_reg	= MAX77686_REG_BUCK1OUT,			\415	.vsel_mask	= MAX77686_VSEL_MASK,				\416	.enable_reg	= MAX77686_REG_BUCK1CTRL,			\417	.enable_mask	= MAX77686_OPMODE_MASK,				\418}419#define regulator_desc_buck_dvs(num)		{			\420	.name		= "BUCK"#num,					\421	.of_match	= of_match_ptr("BUCK"#num),			\422	.regulators_node	= of_match_ptr("voltage-regulators"),	\423	.id		= MAX77686_BUCK##num,				\424	.ops		= &max77686_buck_dvs_ops,			\425	.type		= REGULATOR_VOLTAGE,				\426	.owner		= THIS_MODULE,					\427	.min_uV		= MAX77686_DVS_MINUV,				\428	.uV_step	= MAX77686_DVS_UVSTEP,				\429	.ramp_delay	= MAX77686_DVS_RAMP_DELAY,			\430	.enable_time	= MAX77686_DVS_ENABLE_TIME,			\431	.n_voltages	= MAX77686_DVS_VSEL_MASK + 1,			\432	.vsel_reg	= MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,	\433	.vsel_mask	= MAX77686_DVS_VSEL_MASK,			\434	.enable_reg	= MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,	\435	.enable_mask	= MAX77686_OPMODE_MASK				\436			<< MAX77686_OPMODE_BUCK234_SHIFT,		\437	.ramp_reg	= MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,	\438	.ramp_mask	= MAX77686_RAMP_RATE_MASK,			\439	.ramp_delay_table = max77686_buck_dvs_ramp_table,		\440	.n_ramp_values	= ARRAY_SIZE(max77686_buck_dvs_ramp_table),	\441}442 443static const struct regulator_desc regulators[] = {444	regulator_desc_ldo1_low(1),445	regulator_desc_ldo_low(2),446	regulator_desc_ldo(3),447	regulator_desc_ldo(4),448	regulator_desc_ldo(5),449	regulator_desc_ldo_low(6),450	regulator_desc_ldo_low(7),451	regulator_desc_ldo_low(8),452	regulator_desc_ldo(9),453	regulator_desc_lpm_ldo(10),454	regulator_desc_lpm_ldo(11),455	regulator_desc_lpm_ldo(12),456	regulator_desc_ldo(13),457	regulator_desc_lpm_ldo(14),458	regulator_desc_ldo_low(15),459	regulator_desc_lpm_ldo(16),460	regulator_desc_ldo(17),461	regulator_desc_ldo(18),462	regulator_desc_ldo(19),463	regulator_desc_ldo(20),464	regulator_desc_ldo(21),465	regulator_desc_ldo(22),466	regulator_desc_ldo(23),467	regulator_desc_ldo(24),468	regulator_desc_ldo(25),469	regulator_desc_ldo(26),470	regulator_desc_buck1(1),471	regulator_desc_buck_dvs(2),472	regulator_desc_buck_dvs(3),473	regulator_desc_buck_dvs(4),474	regulator_desc_buck(5),475	regulator_desc_buck(6),476	regulator_desc_buck(7),477	regulator_desc_buck(8),478	regulator_desc_buck(9),479};480 481static int max77686_pmic_probe(struct platform_device *pdev)482{483	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);484	struct max77686_data *max77686;485	int i;486	struct regulator_config config = { };487 488	dev_dbg(&pdev->dev, "%s\n", __func__);489 490	max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),491				GFP_KERNEL);492	if (!max77686)493		return -ENOMEM;494 495	max77686->dev = &pdev->dev;496	config.dev = iodev->dev;497	config.regmap = iodev->regmap;498	config.driver_data = max77686;499	platform_set_drvdata(pdev, max77686);500 501	for (i = 0; i < MAX77686_REGULATORS; i++) {502		struct regulator_dev *rdev;503		int id = regulators[i].id;504 505		max77686->opmode[id] = MAX77686_NORMAL;506		rdev = devm_regulator_register(&pdev->dev,507						&regulators[i], &config);508		if (IS_ERR(rdev)) {509			int ret = PTR_ERR(rdev);510			dev_err(&pdev->dev,511				"regulator init failed for %d: %d\n", i, ret);512			return ret;513		}514	}515 516	return 0;517}518 519static const struct platform_device_id max77686_pmic_id[] = {520	{"max77686-pmic", 0},521	{ },522};523MODULE_DEVICE_TABLE(platform, max77686_pmic_id);524 525static struct platform_driver max77686_pmic_driver = {526	.driver = {527		.name = "max77686-pmic",528		.probe_type = PROBE_PREFER_ASYNCHRONOUS,529	},530	.probe = max77686_pmic_probe,531	.id_table = max77686_pmic_id,532};533 534module_platform_driver(max77686_pmic_driver);535 536MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");537MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");538MODULE_LICENSE("GPL");539