brintos

brintos / linux-shallow public Read only

0
0
Text · 15.6 KiB · a0d3414 Raw
599 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// Regulator driver for DA9055 PMIC4//5// Copyright(c) 2012 Dialog Semiconductor Ltd.6//7// Author: David Dajun Chen <dchen@diasemi.com>8 9#include <linux/module.h>10#include <linux/init.h>11#include <linux/err.h>12#include <linux/gpio/consumer.h>13#include <linux/platform_device.h>14#include <linux/regulator/driver.h>15#include <linux/regulator/machine.h>16#include <linux/of.h>17#include <linux/regulator/of_regulator.h>18 19#include <linux/mfd/da9055/core.h>20#include <linux/mfd/da9055/reg.h>21#include <linux/mfd/da9055/pdata.h>22 23#define DA9055_MIN_UA		024#define DA9055_MAX_UA		325 26#define DA9055_LDO_MODE_SYNC	027#define DA9055_LDO_MODE_SLEEP	128 29#define DA9055_BUCK_MODE_SLEEP	130#define DA9055_BUCK_MODE_SYNC	231#define DA9055_BUCK_MODE_AUTO	332 33/* DA9055 REGULATOR IDs */34#define DA9055_ID_BUCK1	035#define DA9055_ID_BUCK2	136#define DA9055_ID_LDO1		237#define DA9055_ID_LDO2		338#define DA9055_ID_LDO3		439#define DA9055_ID_LDO4		540#define DA9055_ID_LDO5		641#define DA9055_ID_LDO6		742 43/* DA9055 BUCK current limit */44static const unsigned int da9055_current_limits[] = {45	500000, 600000, 700000, 80000046};47 48struct da9055_conf_reg {49	int reg;50	int sel_mask;51	int en_mask;52};53 54struct da9055_volt_reg {55	int reg_a;56	int reg_b;57	int sl_shift;58	int v_mask;59};60 61struct da9055_mode_reg {62	int reg;63	int mask;64	int shift;65};66 67struct da9055_regulator_info {68	struct regulator_desc reg_desc;69	struct da9055_conf_reg conf;70	struct da9055_volt_reg volt;71	struct da9055_mode_reg mode;72};73 74struct da9055_regulator {75	struct da9055 *da9055;76	const struct da9055_regulator_info *info;77	struct regulator_dev *rdev;78	enum gpio_select reg_rselect;79};80 81static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)82{83	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);84	const struct da9055_regulator_info *info = regulator->info;85	int ret, mode = 0;86 87	ret = da9055_reg_read(regulator->da9055, info->mode.reg);88	if (ret < 0)89		return ret;90 91	switch ((ret & info->mode.mask) >> info->mode.shift) {92	case DA9055_BUCK_MODE_SYNC:93		mode = REGULATOR_MODE_FAST;94		break;95	case DA9055_BUCK_MODE_AUTO:96		mode = REGULATOR_MODE_NORMAL;97		break;98	case DA9055_BUCK_MODE_SLEEP:99		mode = REGULATOR_MODE_STANDBY;100		break;101	}102 103	return mode;104}105 106static int da9055_buck_set_mode(struct regulator_dev *rdev,107					unsigned int mode)108{109	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);110	const struct da9055_regulator_info *info = regulator->info;111	int val = 0;112 113	switch (mode) {114	case REGULATOR_MODE_FAST:115		val = DA9055_BUCK_MODE_SYNC << info->mode.shift;116		break;117	case REGULATOR_MODE_NORMAL:118		val = DA9055_BUCK_MODE_AUTO << info->mode.shift;119		break;120	case REGULATOR_MODE_STANDBY:121		val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;122		break;123	}124 125	return da9055_reg_update(regulator->da9055, info->mode.reg,126				 info->mode.mask, val);127}128 129static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)130{131	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);132	const struct da9055_regulator_info *info = regulator->info;133	int ret;134 135	ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);136	if (ret < 0)137		return ret;138 139	if (ret >> info->volt.sl_shift)140		return REGULATOR_MODE_STANDBY;141	else142		return REGULATOR_MODE_NORMAL;143}144 145static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)146{147	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);148	const struct da9055_regulator_info *info = regulator->info;149	struct da9055_volt_reg volt = info->volt;150	int val = 0;151 152	switch (mode) {153	case REGULATOR_MODE_NORMAL:154	case REGULATOR_MODE_FAST:155		val = DA9055_LDO_MODE_SYNC;156		break;157	case REGULATOR_MODE_STANDBY:158		val = DA9055_LDO_MODE_SLEEP;159		break;160	}161 162	return da9055_reg_update(regulator->da9055, volt.reg_b,163				 1 << volt.sl_shift,164				 val << volt.sl_shift);165}166 167static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)168{169	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);170	const struct da9055_regulator_info *info = regulator->info;171	struct da9055_volt_reg volt = info->volt;172	int ret, sel;173 174	/*175	 * There are two voltage register set A & B for voltage ramping but176	 * either one of then can be active therefore we first determine177	 * the active register set.178	 */179	ret = da9055_reg_read(regulator->da9055, info->conf.reg);180	if (ret < 0)181		return ret;182 183	ret &= info->conf.sel_mask;184 185	/* Get the voltage for the active register set A/B */186	if (ret == DA9055_REGUALTOR_SET_A)187		ret = da9055_reg_read(regulator->da9055, volt.reg_a);188	else189		ret = da9055_reg_read(regulator->da9055, volt.reg_b);190 191	if (ret < 0)192		return ret;193 194	sel = (ret & volt.v_mask);195	return sel;196}197 198static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,199					    unsigned int selector)200{201	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);202	const struct da9055_regulator_info *info = regulator->info;203	int ret;204 205	/*206	 * Regulator register set A/B is not selected through GPIO therefore207	 * we use default register set A for voltage ramping.208	 */209	if (regulator->reg_rselect == NO_GPIO) {210		/* Select register set A */211		ret = da9055_reg_update(regulator->da9055, info->conf.reg,212					info->conf.sel_mask, DA9055_SEL_REG_A);213		if (ret < 0)214			return ret;215 216		/* Set the voltage */217		return da9055_reg_update(regulator->da9055, info->volt.reg_a,218					 info->volt.v_mask, selector);219	}220 221	/*222	 * Here regulator register set A/B is selected through GPIO.223	 * Therefore we first determine the selected register set A/B and224	 * then set the desired voltage for that register set A/B.225	 */226	ret = da9055_reg_read(regulator->da9055, info->conf.reg);227	if (ret < 0)228		return ret;229 230	ret &= info->conf.sel_mask;231 232	/* Set the voltage */233	if (ret == DA9055_REGUALTOR_SET_A)234		return da9055_reg_update(regulator->da9055, info->volt.reg_a,235					 info->volt.v_mask, selector);236	else237		return da9055_reg_update(regulator->da9055, info->volt.reg_b,238					 info->volt.v_mask, selector);239}240 241static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,242						int uV)243{244	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);245	const struct da9055_regulator_info *info = regulator->info;246	int ret;247 248	/* Select register set B for suspend voltage ramping. */249	if (regulator->reg_rselect == NO_GPIO) {250		ret = da9055_reg_update(regulator->da9055, info->conf.reg,251					info->conf.sel_mask, DA9055_SEL_REG_B);252		if (ret < 0)253			return ret;254	}255 256	ret = regulator_map_voltage_linear(rdev, uV, uV);257	if (ret < 0)258		return ret;259 260	return da9055_reg_update(regulator->da9055, info->volt.reg_b,261				 info->volt.v_mask, ret);262}263 264static int da9055_suspend_enable(struct regulator_dev *rdev)265{266	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);267	const struct da9055_regulator_info *info = regulator->info;268 269	/* Select register set B for voltage ramping. */270	if (regulator->reg_rselect == NO_GPIO)271		return da9055_reg_update(regulator->da9055, info->conf.reg,272					info->conf.sel_mask, DA9055_SEL_REG_B);273	else274		return 0;275}276 277static int da9055_suspend_disable(struct regulator_dev *rdev)278{279	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);280	const struct da9055_regulator_info *info = regulator->info;281 282	/* Diselect register set B. */283	if (regulator->reg_rselect == NO_GPIO)284		return da9055_reg_update(regulator->da9055, info->conf.reg,285					info->conf.sel_mask, DA9055_SEL_REG_A);286	else287		return 0;288}289 290static const struct regulator_ops da9055_buck_ops = {291	.get_mode = da9055_buck_get_mode,292	.set_mode = da9055_buck_set_mode,293 294	.get_current_limit = regulator_get_current_limit_regmap,295	.set_current_limit = regulator_set_current_limit_regmap,296 297	.get_voltage_sel = da9055_regulator_get_voltage_sel,298	.set_voltage_sel = da9055_regulator_set_voltage_sel,299	.list_voltage = regulator_list_voltage_linear,300	.map_voltage = regulator_map_voltage_linear,301	.is_enabled = regulator_is_enabled_regmap,302	.enable = regulator_enable_regmap,303	.disable = regulator_disable_regmap,304 305	.set_suspend_voltage = da9055_regulator_set_suspend_voltage,306	.set_suspend_enable = da9055_suspend_enable,307	.set_suspend_disable = da9055_suspend_disable,308	.set_suspend_mode = da9055_buck_set_mode,309};310 311static const struct regulator_ops da9055_ldo_ops = {312	.get_mode = da9055_ldo_get_mode,313	.set_mode = da9055_ldo_set_mode,314 315	.get_voltage_sel = da9055_regulator_get_voltage_sel,316	.set_voltage_sel = da9055_regulator_set_voltage_sel,317	.list_voltage = regulator_list_voltage_linear,318	.map_voltage = regulator_map_voltage_linear,319	.is_enabled = regulator_is_enabled_regmap,320	.enable = regulator_enable_regmap,321	.disable = regulator_disable_regmap,322 323	.set_suspend_voltage = da9055_regulator_set_suspend_voltage,324	.set_suspend_enable = da9055_suspend_enable,325	.set_suspend_disable = da9055_suspend_disable,326	.set_suspend_mode = da9055_ldo_set_mode,327 328};329 330#define DA9055_LDO(_id, step, min, max, vbits, voffset) \331{\332	.reg_desc = {\333		.name = #_id,\334		.of_match = of_match_ptr(#_id),\335		.regulators_node = of_match_ptr("regulators"),\336		.ops = &da9055_ldo_ops,\337		.type = REGULATOR_VOLTAGE,\338		.id = DA9055_ID_##_id,\339		.n_voltages = (max - min) / step + 1 + (voffset), \340		.enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \341		.enable_mask = 1, \342		.min_uV = (min) * 1000,\343		.uV_step = (step) * 1000,\344		.linear_min_sel = (voffset),\345		.owner = THIS_MODULE,\346	},\347	.conf = {\348		.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \349		.sel_mask = (1 << 4),\350		.en_mask = 1,\351	},\352	.volt = {\353		.reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \354		.reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \355		.sl_shift = 7,\356		.v_mask = (1 << (vbits)) - 1,\357	},\358}359 360#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \361{\362	.reg_desc = {\363		.name = #_id,\364		.of_match = of_match_ptr(#_id),\365		.regulators_node = of_match_ptr("regulators"),\366		.ops = &da9055_buck_ops,\367		.type = REGULATOR_VOLTAGE,\368		.id = DA9055_ID_##_id,\369		.n_voltages = (max - min) / step + 1 + (voffset), \370		.enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \371		.enable_mask = 1,\372		.min_uV = (min) * 1000,\373		.uV_step = (step) * 1000,\374		.linear_min_sel = (voffset),\375		.owner = THIS_MODULE,\376		.curr_table = da9055_current_limits,\377		.n_current_limits = ARRAY_SIZE(da9055_current_limits),\378		.csel_reg = DA9055_REG_BUCK_LIM,\379		.csel_mask = (mbits),\380	},\381	.conf = {\382		.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \383		.sel_mask = (1 << 4),\384		.en_mask = 1,\385	},\386	.volt = {\387		.reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \388		.reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \389		.sl_shift = 7,\390		.v_mask = (1 << (vbits)) - 1,\391	},\392	.mode = {\393		.reg = DA9055_REG_BCORE_MODE,\394		.mask = (mbits),\395		.shift = (sbits),\396	},\397}398 399static const struct da9055_regulator_info da9055_regulator_info[] = {400	DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),401	DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),402	DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),403	DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),404	DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),405	DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),406	DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),407	DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),408};409 410/*411 * Configures regulator to be controlled either through GPIO 1 or 2.412 * GPIO can control regulator state and/or select the regulator register413 * set A/B for voltage ramping.414 */415static int da9055_gpio_init(struct device *dev,416			    struct da9055_regulator *regulator,417			    struct regulator_config *config,418			    struct da9055_pdata *pdata, int id)419{420	const struct da9055_regulator_info *info = regulator->info;421	struct gpio_desc *ren;422	struct gpio_desc *ena;423	struct gpio_desc *rsel;424	int ret = 0;425 426	/* Look for "regulator-enable-gpios" GPIOs in the regulator node */427	ren = devm_gpiod_get_optional(dev, "regulator-enable", GPIOD_IN);428	if (IS_ERR(ren))429		return PTR_ERR(ren);430 431	if (ren) {432		/* This GPIO is not optional at this point */433		ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);434		if (IS_ERR(ena))435			return PTR_ERR(ena);436 437		config->ena_gpiod = ena;438 439		/*440		 * GPI pin is muxed with regulator to control the441		 * regulator state.442		 */443		gpiod_set_consumer_name(ren, "DA9055 ren GPI");444 445		/*446		 * Let the regulator know that its state is controlled447		 * through GPI.448		 */449		ret = da9055_reg_update(regulator->da9055, info->conf.reg,450					DA9055_E_GPI_MASK,451					pdata->reg_ren[id]452					<< DA9055_E_GPI_SHIFT);453		if (ret < 0)454			return ret;455	}456 457	/* Look for "regulator-select-gpios" GPIOs in the regulator node */458	rsel = devm_gpiod_get_optional(dev, "regulator-select", GPIOD_IN);459	if (IS_ERR(rsel))460		return PTR_ERR(rsel);461 462	if (rsel) {463		regulator->reg_rselect = pdata->reg_rsel[id];464 465		/*466		 * GPI pin is muxed with regulator to select the467		 * regulator register set A/B for voltage ramping.468		 */469		gpiod_set_consumer_name(rsel, "DA9055 rsel GPI");470 471		/*472		 * Let the regulator know that its register set A/B473		 * will be selected through GPI for voltage ramping.474		 */475		ret = da9055_reg_update(regulator->da9055, info->conf.reg,476					DA9055_V_GPI_MASK,477					pdata->reg_rsel[id]478					<< DA9055_V_GPI_SHIFT);479	}480 481	return ret;482}483 484static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)485{486	struct da9055_regulator *regulator = data;487 488	regulator_notifier_call_chain(regulator->rdev,489				      REGULATOR_EVENT_OVER_CURRENT, NULL);490 491	return IRQ_HANDLED;492}493 494static inline const struct da9055_regulator_info *find_regulator_info(int id)495{496	const struct da9055_regulator_info *info;497	int i;498 499	for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {500		info = &da9055_regulator_info[i];501		if (info->reg_desc.id == id)502			return info;503	}504 505	return NULL;506}507 508static int da9055_regulator_probe(struct platform_device *pdev)509{510	struct regulator_config config = { };511	struct da9055_regulator *regulator;512	struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);513	struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);514	int ret, irq;515 516	regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),517				 GFP_KERNEL);518	if (!regulator)519		return -ENOMEM;520 521	regulator->info = find_regulator_info(pdev->id);522	if (regulator->info == NULL) {523		dev_err(&pdev->dev, "invalid regulator ID specified\n");524		return -EINVAL;525	}526 527	regulator->da9055 = da9055;528	config.dev = da9055->dev;529	config.driver_data = regulator;530	config.regmap = da9055->regmap;531 532	if (pdata)533		config.init_data = pdata->regulators[pdev->id];534 535	ret = da9055_gpio_init(&pdev->dev, regulator, &config, pdata, pdev->id);536	if (ret < 0)537		return ret;538 539	regulator->rdev = devm_regulator_register(&pdev->dev,540						  &regulator->info->reg_desc,541						  &config);542	if (IS_ERR(regulator->rdev)) {543		dev_err(&pdev->dev, "Failed to register regulator %s\n",544			regulator->info->reg_desc.name);545		return PTR_ERR(regulator->rdev);546	}547 548	/* Only LDO 5 and 6 has got the over current interrupt */549	if (pdev->id == DA9055_ID_LDO5 || pdev->id ==  DA9055_ID_LDO6) {550		irq = platform_get_irq_byname(pdev, "REGULATOR");551		if (irq < 0)552			return irq;553 554		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,555						da9055_ldo5_6_oc_irq,556						IRQF_TRIGGER_HIGH |557						IRQF_ONESHOT |558						IRQF_PROBE_SHARED,559						pdev->name, regulator);560		if (ret != 0) {561			if (ret != -EBUSY) {562				dev_err(&pdev->dev,563				"Failed to request Regulator IRQ %d: %d\n",564				irq, ret);565				return ret;566			}567		}568	}569 570	platform_set_drvdata(pdev, regulator);571 572	return 0;573}574 575static struct platform_driver da9055_regulator_driver = {576	.probe = da9055_regulator_probe,577	.driver = {578		.name = "da9055-regulator",579		.probe_type = PROBE_PREFER_ASYNCHRONOUS,580	},581};582 583static int __init da9055_regulator_init(void)584{585	return platform_driver_register(&da9055_regulator_driver);586}587subsys_initcall(da9055_regulator_init);588 589static void __exit da9055_regulator_exit(void)590{591	platform_driver_unregister(&da9055_regulator_driver);592}593module_exit(da9055_regulator_exit);594 595MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");596MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");597MODULE_LICENSE("GPL");598MODULE_ALIAS("platform:da9055-regulator");599