tps65217-regulator.c 9.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * tps65217-regulator.c
 *
 * Regulator driver for TPS65217 PMIC
 *
 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>

25
#include <linux/regulator/of_regulator.h>
26 27 28 29
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/tps65217.h>

30
#define TPS65217_REGULATOR(_name, _id, _of_match, _ops, _n, _vr, _vm, _em, \
31
			   _t, _lr, _nlr,  _sr, _sm)	\
32 33 34
	{						\
		.name		= _name,		\
		.id		= _id,			\
35 36
		.of_match       = of_match_ptr(_of_match),    \
		.regulators_node= of_match_ptr("regulators"), \
37 38 39 40
		.ops		= &_ops,		\
		.n_voltages	= _n,			\
		.type		= REGULATOR_VOLTAGE,	\
		.owner		= THIS_MODULE,		\
41 42 43 44
		.vsel_reg	= _vr,			\
		.vsel_mask	= _vm,			\
		.enable_reg	= TPS65217_REG_ENABLE,	\
		.enable_mask	= _em,			\
45
		.volt_table	= _t,			\
46 47
		.linear_ranges	= _lr,			\
		.n_linear_ranges = _nlr,		\
48 49
		.bypass_reg	= _sr,			\
		.bypass_mask	= _sm,			\
50 51
	}						\

52
static const unsigned int LDO1_VSEL_table[] = {
53 54 55 56 57 58
	1000000, 1100000, 1200000, 1250000,
	1300000, 1350000, 1400000, 1500000,
	1600000, 1800000, 2500000, 2750000,
	2800000, 3000000, 3100000, 3300000,
};

59
static const struct regulator_linear_range tps65217_uv1_ranges[] = {
60 61 62 63 64
	REGULATOR_LINEAR_RANGE(900000, 0, 24, 25000),
	REGULATOR_LINEAR_RANGE(1550000, 25, 30, 50000),
	REGULATOR_LINEAR_RANGE(1850000, 31, 52, 50000),
	REGULATOR_LINEAR_RANGE(3000000, 53, 55, 100000),
	REGULATOR_LINEAR_RANGE(3300000, 56, 62, 0),
65
};
66

67
static const struct regulator_linear_range tps65217_uv2_ranges[] = {
68 69 70
	REGULATOR_LINEAR_RANGE(1500000, 0, 8, 50000),
	REGULATOR_LINEAR_RANGE(2000000, 9, 13, 100000),
	REGULATOR_LINEAR_RANGE(2450000, 14, 31, 50000),
71 72
};

73
static int tps65217_pmic_enable(struct regulator_dev *dev)
74 75
{
	struct tps65217 *tps = rdev_get_drvdata(dev);
76
	int rid = rdev_get_id(dev);
77

78
	if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
79 80 81 82
		return -EINVAL;

	/* Enable the regulator and password protection is level 1 */
	return tps65217_set_bits(tps, TPS65217_REG_ENABLE,
83 84
				 dev->desc->enable_mask, dev->desc->enable_mask,
				 TPS65217_PROTECT_L1);
85 86
}

87
static int tps65217_pmic_disable(struct regulator_dev *dev)
88 89
{
	struct tps65217 *tps = rdev_get_drvdata(dev);
90
	int rid = rdev_get_id(dev);
91

92
	if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
93 94 95 96
		return -EINVAL;

	/* Disable the regulator and password protection is level 1 */
	return tps65217_clear_bits(tps, TPS65217_REG_ENABLE,
97
				   dev->desc->enable_mask, TPS65217_PROTECT_L1);
98 99
}

100 101
static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
					 unsigned selector)
102
{
103
	int ret;
104
	struct tps65217 *tps = rdev_get_drvdata(dev);
105
	unsigned int rid = rdev_get_id(dev);
106

107
	/* Set the voltage based on vsel value and write protect level is 2 */
108
	ret = tps65217_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask,
109
				selector, TPS65217_PROTECT_L2);
110

111 112 113 114 115 116 117 118
	/* Set GO bit for DCDCx to initiate voltage transistion */
	switch (rid) {
	case TPS65217_DCDC_1 ... TPS65217_DCDC_3:
		ret = tps65217_set_bits(tps, TPS65217_REG_DEFSLEW,
				       TPS65217_DEFSLEW_GO, TPS65217_DEFSLEW_GO,
				       TPS65217_PROTECT_L2);
		break;
	}
119

120
	return ret;
121 122
}

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
static int tps65217_pmic_set_suspend_enable(struct regulator_dev *dev)
{
	struct tps65217 *tps = rdev_get_drvdata(dev);
	unsigned int rid = rdev_get_id(dev);

	if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
		return -EINVAL;

	return tps65217_clear_bits(tps, dev->desc->bypass_reg,
				   dev->desc->bypass_mask,
				   TPS65217_PROTECT_L1);
}

static int tps65217_pmic_set_suspend_disable(struct regulator_dev *dev)
{
	struct tps65217 *tps = rdev_get_drvdata(dev);
	unsigned int rid = rdev_get_id(dev);

	if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
		return -EINVAL;

	if (!tps->strobes[rid])
		return -EINVAL;

	return tps65217_set_bits(tps, dev->desc->bypass_reg,
				 dev->desc->bypass_mask,
				 tps->strobes[rid], TPS65217_PROTECT_L1);
}

152 153
/* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
static struct regulator_ops tps65217_pmic_ops = {
154
	.is_enabled		= regulator_is_enabled_regmap,
155 156
	.enable			= tps65217_pmic_enable,
	.disable		= tps65217_pmic_disable,
157
	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
158
	.set_voltage_sel	= tps65217_pmic_set_voltage_sel,
159 160
	.list_voltage		= regulator_list_voltage_linear_range,
	.map_voltage		= regulator_map_voltage_linear_range,
161 162
	.set_suspend_enable	= tps65217_pmic_set_suspend_enable,
	.set_suspend_disable	= tps65217_pmic_set_suspend_disable,
163 164 165 166
};

/* Operations permitted on LDO1 */
static struct regulator_ops tps65217_pmic_ldo1_ops = {
167
	.is_enabled		= regulator_is_enabled_regmap,
168 169
	.enable			= tps65217_pmic_enable,
	.disable		= tps65217_pmic_disable,
170
	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
171
	.set_voltage_sel	= tps65217_pmic_set_voltage_sel,
172
	.list_voltage		= regulator_list_voltage_table,
173
	.map_voltage		= regulator_map_voltage_ascend,
174 175
	.set_suspend_enable	= tps65217_pmic_set_suspend_enable,
	.set_suspend_disable	= tps65217_pmic_set_suspend_disable,
176 177
};

178
static const struct regulator_desc regulators[] = {
179 180 181
	TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, "dcdc1",
			   tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1,
			   TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC1_EN,
182 183
			   NULL, tps65217_uv1_ranges,
			   ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ1,
184
			   TPS65217_SEQ1_DC1_SEQ_MASK),
185 186 187 188
	TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, "dcdc2",
			   tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2,
			   TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC2_EN,
			   NULL, tps65217_uv1_ranges,
189 190
			   ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ1,
			   TPS65217_SEQ1_DC2_SEQ_MASK),
191 192 193
	TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, "dcdc3",
			   tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3,
			   TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC3_EN,
194 195
			   NULL, tps65217_uv1_ranges,
			   ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ2,
196
			   TPS65217_SEQ2_DC3_SEQ_MASK),
197 198 199
	TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, "ldo1",
			   tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1,
			   TPS65217_DEFLDO1_LDO1_MASK, TPS65217_ENABLE_LDO1_EN,
200 201
			   LDO1_VSEL_table, NULL, 0, TPS65217_REG_SEQ2,
			   TPS65217_SEQ2_LDO1_SEQ_MASK),
202 203 204 205
	TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, "ldo2", tps65217_pmic_ops,
			   64, TPS65217_REG_DEFLDO2,
			   TPS65217_DEFLDO2_LDO2_MASK, TPS65217_ENABLE_LDO2_EN,
			   NULL, tps65217_uv1_ranges,
206 207
			   ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ3,
			   TPS65217_SEQ3_LDO2_SEQ_MASK),
208 209
	TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, "ldo3", tps65217_pmic_ops,
			   32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
210
			   TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
211
			   NULL, tps65217_uv2_ranges,
212 213
			   ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ3,
			   TPS65217_SEQ3_LDO3_SEQ_MASK),
214 215
	TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, "ldo4", tps65217_pmic_ops,
			   32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
216
			   TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
217
			   NULL, tps65217_uv2_ranges,
218 219
			   ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ4,
			   TPS65217_SEQ4_LDO4_SEQ_MASK),
220 221
};

222
static int tps65217_regulator_probe(struct platform_device *pdev)
223
{
224 225
	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
	struct tps65217_board *pdata = dev_get_platdata(tps->dev);
226
	struct regulator_dev *rdev;
227
	struct regulator_config config = { };
228 229
	int i, ret;
	unsigned int val;
230

231 232 233 234
	if (tps65217_chip_id(tps) != TPS65217) {
		dev_err(&pdev->dev, "Invalid tps chip version\n");
		return -ENODEV;
	}
235

236 237 238 239
	/* Allocate memory for strobes */
	tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
				    TPS65217_NUM_REGULATOR, GFP_KERNEL);

240
	platform_set_drvdata(pdev, tps);
241

242 243 244
	for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
		/* Register the regulators */
		config.dev = tps->dev;
245 246
		if (pdata)
			config.init_data = pdata->tps65217_init_data[i];
247 248 249
		config.driver_data = tps;
		config.regmap = tps->regmap;

250 251
		rdev = devm_regulator_register(&pdev->dev, &regulators[i],
					       &config);
252 253 254
		if (IS_ERR(rdev)) {
			dev_err(tps->dev, "failed to register %s regulator\n",
				pdev->name);
255
			return PTR_ERR(rdev);
256
		}
257 258 259 260

		/* Store default strobe info */
		ret = tps65217_reg_read(tps, regulators[i].bypass_reg, &val);
		tps->strobes[i] = val & regulators[i].bypass_mask;
261
	}
262

263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	return 0;
}

static struct platform_driver tps65217_regulator_driver = {
	.driver = {
		.name = "tps65217-pmic",
	},
	.probe = tps65217_regulator_probe,
};

static int __init tps65217_regulator_init(void)
{
	return platform_driver_register(&tps65217_regulator_driver);
}
subsys_initcall(tps65217_regulator_init);

static void __exit tps65217_regulator_exit(void)
{
	platform_driver_unregister(&tps65217_regulator_driver);
}
module_exit(tps65217_regulator_exit);

MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
MODULE_DESCRIPTION("TPS65217 voltage regulator driver");
MODULE_ALIAS("platform:tps65217-pmic");
MODULE_LICENSE("GPL v2");