brintos

brintos / linux-shallow public Read only

0
0
Text · 14.7 KiB · 3fee7e3 Raw
641 lines · c
1/*2 * Regulator driver for TPS6524x PMIC3 *4 * Copyright (C) 2010 Texas Instruments5 *6 * This program is free software; you can redistribute it and/or7 * modify it under the terms of the GNU General Public License as8 * published by the Free Software Foundation version 2.9 *10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,11 * whether express or implied; without even the implied warranty of12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU13 * General Public License for more details.14 */15 16#include <linux/kernel.h>17#include <linux/module.h>18#include <linux/err.h>19#include <linux/errno.h>20#include <linux/slab.h>21#include <linux/spi/spi.h>22#include <linux/regulator/driver.h>23#include <linux/regulator/machine.h>24 25#define REG_LDO_SET		0x026#define LDO_ILIM_MASK		1	/* 0 = 400-800, 1 = 900-1500 */27#define LDO_VSEL_MASK		0x0f28#define LDO2_ILIM_SHIFT		1229#define LDO2_VSEL_SHIFT		430#define LDO1_ILIM_SHIFT		831#define LDO1_VSEL_SHIFT		032 33#define REG_BLOCK_EN		0x134#define BLOCK_MASK		135#define BLOCK_LDO1_SHIFT	036#define BLOCK_LDO2_SHIFT	137#define BLOCK_LCD_SHIFT		238#define BLOCK_USB_SHIFT		339 40#define REG_DCDC_SET		0x241#define DCDC_VDCDC_MASK		0x1f42#define DCDC_VDCDC1_SHIFT	043#define DCDC_VDCDC2_SHIFT	544#define DCDC_VDCDC3_SHIFT	1045 46#define REG_DCDC_EN		0x347#define DCDCDCDC_EN_MASK	0x148#define DCDCDCDC1_EN_SHIFT	049#define DCDCDCDC1_PG_MSK	BIT(1)50#define DCDCDCDC2_EN_SHIFT	251#define DCDCDCDC2_PG_MSK	BIT(3)52#define DCDCDCDC3_EN_SHIFT	453#define DCDCDCDC3_PG_MSK	BIT(5)54 55#define REG_USB			0x456#define USB_ILIM_SHIFT		057#define USB_ILIM_MASK		0x358#define USB_TSD_SHIFT		259#define USB_TSD_MASK		0x360#define USB_TWARN_SHIFT		461#define USB_TWARN_MASK		0x362#define USB_IWARN_SD		BIT(6)63#define USB_FAST_LOOP		BIT(7)64 65#define REG_ALARM		0x566#define ALARM_LDO1		BIT(0)67#define ALARM_DCDC1		BIT(1)68#define ALARM_DCDC2		BIT(2)69#define ALARM_DCDC3		BIT(3)70#define ALARM_LDO2		BIT(4)71#define ALARM_USB_WARN		BIT(5)72#define ALARM_USB_ALARM		BIT(6)73#define ALARM_LCD		BIT(9)74#define ALARM_TEMP_WARM		BIT(10)75#define ALARM_TEMP_HOT		BIT(11)76#define ALARM_NRST		BIT(14)77#define ALARM_POWERUP		BIT(15)78 79#define REG_INT_ENABLE		0x680#define INT_LDO1		BIT(0)81#define INT_DCDC1		BIT(1)82#define INT_DCDC2		BIT(2)83#define INT_DCDC3		BIT(3)84#define INT_LDO2		BIT(4)85#define INT_USB_WARN		BIT(5)86#define INT_USB_ALARM		BIT(6)87#define INT_LCD			BIT(9)88#define INT_TEMP_WARM		BIT(10)89#define INT_TEMP_HOT		BIT(11)90#define INT_GLOBAL_EN		BIT(15)91 92#define REG_INT_STATUS		0x793#define STATUS_LDO1		BIT(0)94#define STATUS_DCDC1		BIT(1)95#define STATUS_DCDC2		BIT(2)96#define STATUS_DCDC3		BIT(3)97#define STATUS_LDO2		BIT(4)98#define STATUS_USB_WARN		BIT(5)99#define STATUS_USB_ALARM	BIT(6)100#define STATUS_LCD		BIT(9)101#define STATUS_TEMP_WARM	BIT(10)102#define STATUS_TEMP_HOT		BIT(11)103 104#define REG_SOFTWARE_RESET	0xb105#define REG_WRITE_ENABLE	0xd106#define REG_REV_ID		0xf107 108#define N_DCDC			3109#define N_LDO			2110#define N_SWITCH		2111#define N_REGULATORS		(N_DCDC + N_LDO + N_SWITCH)112 113#define CMD_READ(reg)		((reg) << 6)114#define CMD_WRITE(reg)		(BIT(5) | (reg) << 6)115#define STAT_CLK		BIT(3)116#define STAT_WRITE		BIT(2)117#define STAT_INVALID		BIT(1)118#define STAT_WP			BIT(0)119 120struct field {121	int		reg;122	int		shift;123	int		mask;124};125 126struct supply_info {127	const char	*name;128	int		n_voltages;129	const unsigned int *voltages;130	int		n_ilimsels;131	const unsigned int *ilimsels;132	struct field	enable, voltage, ilimsel;133};134 135struct tps6524x {136	struct device		*dev;137	struct spi_device	*spi;138	struct mutex		lock;139	struct regulator_desc	desc[N_REGULATORS];140};141 142static int __read_reg(struct tps6524x *hw, int reg)143{144	int error = 0;145	u16 cmd = CMD_READ(reg), in;146	u8 status;147	struct spi_message m;148	struct spi_transfer t[3];149 150	spi_message_init(&m);151	memset(t, 0, sizeof(t));152 153	t[0].tx_buf = &cmd;154	t[0].len = 2;155	t[0].bits_per_word = 12;156	spi_message_add_tail(&t[0], &m);157 158	t[1].rx_buf = &in;159	t[1].len = 2;160	t[1].bits_per_word = 16;161	spi_message_add_tail(&t[1], &m);162 163	t[2].rx_buf = &status;164	t[2].len = 1;165	t[2].bits_per_word = 4;166	spi_message_add_tail(&t[2], &m);167 168	error = spi_sync(hw->spi, &m);169	if (error < 0)170		return error;171 172	dev_dbg(hw->dev, "read reg %d, data %x, status %x\n",173		reg, in, status);174 175	if (!(status & STAT_CLK) || (status & STAT_WRITE))176		return -EIO;177 178	if (status & STAT_INVALID)179		return -EINVAL;180 181	return in;182}183 184static int read_reg(struct tps6524x *hw, int reg)185{186	int ret;187 188	mutex_lock(&hw->lock);189	ret = __read_reg(hw, reg);190	mutex_unlock(&hw->lock);191 192	return ret;193}194 195static int __write_reg(struct tps6524x *hw, int reg, int val)196{197	int error = 0;198	u16 cmd = CMD_WRITE(reg), out = val;199	u8 status;200	struct spi_message m;201	struct spi_transfer t[3];202 203	spi_message_init(&m);204	memset(t, 0, sizeof(t));205 206	t[0].tx_buf = &cmd;207	t[0].len = 2;208	t[0].bits_per_word = 12;209	spi_message_add_tail(&t[0], &m);210 211	t[1].tx_buf = &out;212	t[1].len = 2;213	t[1].bits_per_word = 16;214	spi_message_add_tail(&t[1], &m);215 216	t[2].rx_buf = &status;217	t[2].len = 1;218	t[2].bits_per_word = 4;219	spi_message_add_tail(&t[2], &m);220 221	error = spi_sync(hw->spi, &m);222	if (error < 0)223		return error;224 225	dev_dbg(hw->dev, "wrote reg %d, data %x, status %x\n",226		reg, out, status);227 228	if (!(status & STAT_CLK) || !(status & STAT_WRITE))229		return -EIO;230 231	if (status & (STAT_INVALID | STAT_WP))232		return -EINVAL;233 234	return error;235}236 237static int __rmw_reg(struct tps6524x *hw, int reg, int mask, int val)238{239	int ret;240 241	ret = __read_reg(hw, reg);242	if (ret < 0)243		return ret;244 245	ret &= ~mask;246	ret |= val;247 248	ret = __write_reg(hw, reg, ret);249 250	return (ret < 0) ? ret : 0;251}252 253static int rmw_protect(struct tps6524x *hw, int reg, int mask, int val)254{255	int ret;256 257	mutex_lock(&hw->lock);258 259	ret = __write_reg(hw, REG_WRITE_ENABLE, 1);260	if (ret) {261		dev_err(hw->dev, "failed to set write enable\n");262		goto error;263	}264 265	ret = __rmw_reg(hw, reg, mask, val);266	if (ret)267		dev_err(hw->dev, "failed to rmw register %d\n", reg);268 269	ret = __write_reg(hw, REG_WRITE_ENABLE, 0);270	if (ret) {271		dev_err(hw->dev, "failed to clear write enable\n");272		goto error;273	}274 275error:276	mutex_unlock(&hw->lock);277 278	return ret;279}280 281static int read_field(struct tps6524x *hw, const struct field *field)282{283	int tmp;284 285	tmp = read_reg(hw, field->reg);286	if (tmp < 0)287		return tmp;288 289	return (tmp >> field->shift) & field->mask;290}291 292static int write_field(struct tps6524x *hw, const struct field *field,293		       int val)294{295	if (val & ~field->mask)296		return -EOVERFLOW;297 298	return rmw_protect(hw, field->reg,299				    field->mask << field->shift,300				    val << field->shift);301}302 303static const unsigned int dcdc1_voltages[] = {304	 800000,  825000,  850000,  875000,305	 900000,  925000,  950000,  975000,306	1000000, 1025000, 1050000, 1075000,307	1100000, 1125000, 1150000, 1175000,308	1200000, 1225000, 1250000, 1275000,309	1300000, 1325000, 1350000, 1375000,310	1400000, 1425000, 1450000, 1475000,311	1500000, 1525000, 1550000, 1575000,312};313 314static const unsigned int dcdc2_voltages[] = {315	1400000, 1450000, 1500000, 1550000,316	1600000, 1650000, 1700000, 1750000,317	1800000, 1850000, 1900000, 1950000,318	2000000, 2050000, 2100000, 2150000,319	2200000, 2250000, 2300000, 2350000,320	2400000, 2450000, 2500000, 2550000,321	2600000, 2650000, 2700000, 2750000,322	2800000, 2850000, 2900000, 2950000,323};324 325static const unsigned int dcdc3_voltages[] = {326	2400000, 2450000, 2500000, 2550000, 2600000,327	2650000, 2700000, 2750000, 2800000, 2850000,328	2900000, 2950000, 3000000, 3050000, 3100000,329	3150000, 3200000, 3250000, 3300000, 3350000,330	3400000, 3450000, 3500000, 3550000, 3600000,331};332 333static const unsigned int ldo1_voltages[] = {334	4300000, 4350000, 4400000, 4450000,335	4500000, 4550000, 4600000, 4650000,336	4700000, 4750000, 4800000, 4850000,337	4900000, 4950000, 5000000, 5050000,338};339 340static const unsigned int ldo2_voltages[] = {341	1100000, 1150000, 1200000, 1250000,342	1300000, 1700000, 1750000, 1800000,343	1850000, 1900000, 3150000, 3200000,344	3250000, 3300000, 3350000, 3400000,345};346 347static const unsigned int fixed_5000000_voltage[] = {348	5000000349};350 351static const unsigned int ldo_ilimsel[] = {352	400000, 1500000353};354 355static const unsigned int usb_ilimsel[] = {356	200000, 400000, 800000, 1000000357};358 359static const unsigned int fixed_2400000_ilimsel[] = {360	2400000361};362 363static const unsigned int fixed_1200000_ilimsel[] = {364	1200000365};366 367static const unsigned int fixed_400000_ilimsel[] = {368	400000369};370 371#define __MK_FIELD(_reg, _mask, _shift) \372	{ .reg = (_reg), .mask = (_mask), .shift = (_shift), }373 374static const struct supply_info supply_info[N_REGULATORS] = {375	{376		.name		= "DCDC1",377		.n_voltages	= ARRAY_SIZE(dcdc1_voltages),378		.voltages	= dcdc1_voltages,379		.n_ilimsels	= ARRAY_SIZE(fixed_2400000_ilimsel),380		.ilimsels	= fixed_2400000_ilimsel,381		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,382					     DCDCDCDC1_EN_SHIFT),383		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,384					     DCDC_VDCDC1_SHIFT),385	},386	{387		.name		= "DCDC2",388		.n_voltages	= ARRAY_SIZE(dcdc2_voltages),389		.voltages	= dcdc2_voltages,390		.n_ilimsels	= ARRAY_SIZE(fixed_1200000_ilimsel),391		.ilimsels	= fixed_1200000_ilimsel,392		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,393					     DCDCDCDC2_EN_SHIFT),394		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,395					     DCDC_VDCDC2_SHIFT),396	},397	{398		.name		= "DCDC3",399		.n_voltages	= ARRAY_SIZE(dcdc3_voltages),400		.voltages	= dcdc3_voltages,401		.n_ilimsels	= ARRAY_SIZE(fixed_1200000_ilimsel),402		.ilimsels	= fixed_1200000_ilimsel,403		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,404					DCDCDCDC3_EN_SHIFT),405		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,406					     DCDC_VDCDC3_SHIFT),407	},408	{409		.name		= "LDO1",410		.n_voltages	= ARRAY_SIZE(ldo1_voltages),411		.voltages	= ldo1_voltages,412		.n_ilimsels	= ARRAY_SIZE(ldo_ilimsel),413		.ilimsels	= ldo_ilimsel,414		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,415					     BLOCK_LDO1_SHIFT),416		.voltage	= __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,417					     LDO1_VSEL_SHIFT),418		.ilimsel	= __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,419					     LDO1_ILIM_SHIFT),420	},421	{422		.name		= "LDO2",423		.n_voltages	= ARRAY_SIZE(ldo2_voltages),424		.voltages	= ldo2_voltages,425		.n_ilimsels	= ARRAY_SIZE(ldo_ilimsel),426		.ilimsels	= ldo_ilimsel,427		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,428					     BLOCK_LDO2_SHIFT),429		.voltage	= __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,430					     LDO2_VSEL_SHIFT),431		.ilimsel	= __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,432					     LDO2_ILIM_SHIFT),433	},434	{435		.name		= "USB",436		.n_voltages	= ARRAY_SIZE(fixed_5000000_voltage),437		.voltages	= fixed_5000000_voltage,438		.n_ilimsels	= ARRAY_SIZE(usb_ilimsel),439		.ilimsels	= usb_ilimsel,440		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,441					     BLOCK_USB_SHIFT),442		.ilimsel	= __MK_FIELD(REG_USB, USB_ILIM_MASK,443					     USB_ILIM_SHIFT),444	},445	{446		.name		= "LCD",447		.n_voltages	= ARRAY_SIZE(fixed_5000000_voltage),448		.voltages	= fixed_5000000_voltage,449		.n_ilimsels	= ARRAY_SIZE(fixed_400000_ilimsel),450		.ilimsels	= fixed_400000_ilimsel,451		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,452					     BLOCK_LCD_SHIFT),453	},454};455 456static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)457{458	const struct supply_info *info;459	struct tps6524x *hw;460 461	hw	= rdev_get_drvdata(rdev);462	info	= &supply_info[rdev_get_id(rdev)];463 464	if (rdev->desc->n_voltages == 1)465		return -EINVAL;466 467	return write_field(hw, &info->voltage, selector);468}469 470static int get_voltage_sel(struct regulator_dev *rdev)471{472	const struct supply_info *info;473	struct tps6524x *hw;474	int ret;475 476	hw	= rdev_get_drvdata(rdev);477	info	= &supply_info[rdev_get_id(rdev)];478 479	if (rdev->desc->n_voltages == 1)480		return 0;481 482	ret = read_field(hw, &info->voltage);483	if (ret < 0)484		return ret;485	if (WARN_ON(ret >= info->n_voltages))486		return -EIO;487 488	return ret;489}490 491static int set_current_limit(struct regulator_dev *rdev, int min_uA,492			     int max_uA)493{494	const struct supply_info *info;495	struct tps6524x *hw;496	int i;497 498	hw	= rdev_get_drvdata(rdev);499	info	= &supply_info[rdev_get_id(rdev)];500 501	if (info->n_ilimsels == 1)502		return -EINVAL;503 504	for (i = info->n_ilimsels - 1; i >= 0; i--) {505		if (min_uA <= info->ilimsels[i] &&506		    max_uA >= info->ilimsels[i])507			return write_field(hw, &info->ilimsel, i);508	}509 510	return -EINVAL;511}512 513static int get_current_limit(struct regulator_dev *rdev)514{515	const struct supply_info *info;516	struct tps6524x *hw;517	int ret;518 519	hw	= rdev_get_drvdata(rdev);520	info	= &supply_info[rdev_get_id(rdev)];521 522	if (info->n_ilimsels == 1)523		return info->ilimsels[0];524 525	ret = read_field(hw, &info->ilimsel);526	if (ret < 0)527		return ret;528	if (WARN_ON(ret >= info->n_ilimsels))529		return -EIO;530 531	return info->ilimsels[ret];532}533 534static int enable_supply(struct regulator_dev *rdev)535{536	const struct supply_info *info;537	struct tps6524x *hw;538 539	hw	= rdev_get_drvdata(rdev);540	info	= &supply_info[rdev_get_id(rdev)];541 542	return write_field(hw, &info->enable, 1);543}544 545static int disable_supply(struct regulator_dev *rdev)546{547	const struct supply_info *info;548	struct tps6524x *hw;549 550	hw	= rdev_get_drvdata(rdev);551	info	= &supply_info[rdev_get_id(rdev)];552 553	return write_field(hw, &info->enable, 0);554}555 556static int is_supply_enabled(struct regulator_dev *rdev)557{558	const struct supply_info *info;559	struct tps6524x *hw;560 561	hw	= rdev_get_drvdata(rdev);562	info	= &supply_info[rdev_get_id(rdev)];563 564	return read_field(hw, &info->enable);565}566 567static const struct regulator_ops regulator_ops = {568	.is_enabled		= is_supply_enabled,569	.enable			= enable_supply,570	.disable		= disable_supply,571	.get_voltage_sel	= get_voltage_sel,572	.set_voltage_sel	= set_voltage_sel,573	.list_voltage		= regulator_list_voltage_table,574	.map_voltage		= regulator_map_voltage_ascend,575	.set_current_limit	= set_current_limit,576	.get_current_limit	= get_current_limit,577};578 579static int pmic_probe(struct spi_device *spi)580{581	struct tps6524x *hw;582	struct device *dev = &spi->dev;583	const struct supply_info *info = supply_info;584	struct regulator_init_data *init_data;585	struct regulator_config config = { };586	struct regulator_dev *rdev;587	int i;588 589	init_data = dev_get_platdata(dev);590	if (!init_data) {591		dev_err(dev, "could not find regulator platform data\n");592		return -EINVAL;593	}594 595	hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL);596	if (!hw)597		return -ENOMEM;598 599	spi_set_drvdata(spi, hw);600 601	memset(hw, 0, sizeof(struct tps6524x));602	hw->dev = dev;603	hw->spi = spi;604	mutex_init(&hw->lock);605 606	for (i = 0; i < N_REGULATORS; i++, info++, init_data++) {607		hw->desc[i].name	= info->name;608		hw->desc[i].id		= i;609		hw->desc[i].n_voltages	= info->n_voltages;610		hw->desc[i].volt_table	= info->voltages;611		hw->desc[i].ops		= &regulator_ops;612		hw->desc[i].type	= REGULATOR_VOLTAGE;613		hw->desc[i].owner	= THIS_MODULE;614 615		config.dev = dev;616		config.init_data = init_data;617		config.driver_data = hw;618 619		rdev = devm_regulator_register(dev, &hw->desc[i], &config);620		if (IS_ERR(rdev))621			return PTR_ERR(rdev);622	}623 624	return 0;625}626 627static struct spi_driver pmic_driver = {628	.probe		= pmic_probe,629	.driver		= {630		.name	= "tps6524x",631		.probe_type = PROBE_PREFER_ASYNCHRONOUS,632	},633};634 635module_spi_driver(pmic_driver);636 637MODULE_DESCRIPTION("TPS6524X PMIC Driver");638MODULE_AUTHOR("Cyril Chemparathy");639MODULE_LICENSE("GPL");640MODULE_ALIAS("spi:tps6524x");641