tps6507x-regulator.c 11.9 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
/*
 * tps6507x-regulator.c
 *
 * Regulator driver for TPS65073 PMIC
 *
 * Copyright (C) 2009 Texas Instrument 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/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
25
#include <linux/regulator/tps6507x.h>
26
#include <linux/delay.h>
27
#include <linux/slab.h>
28
#include <linux/mfd/tps6507x.h>
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98

/* DCDC's */
#define TPS6507X_DCDC_1				0
#define TPS6507X_DCDC_2				1
#define TPS6507X_DCDC_3				2
/* LDOs */
#define TPS6507X_LDO_1				3
#define TPS6507X_LDO_2				4

#define TPS6507X_MAX_REG_ID			TPS6507X_LDO_2

/* Number of step-down converters available */
#define TPS6507X_NUM_DCDC			3
/* Number of LDO voltage regulators  available */
#define TPS6507X_NUM_LDO			2
/* Number of total regulators available */
#define TPS6507X_NUM_REGULATOR		(TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO)

/* Supported voltage values for regulators (in milliVolts) */
static const u16 VDCDCx_VSEL_table[] = {
	725, 750, 775, 800,
	825, 850, 875, 900,
	925, 950, 975, 1000,
	1025, 1050, 1075, 1100,
	1125, 1150, 1175, 1200,
	1225, 1250, 1275, 1300,
	1325, 1350, 1375, 1400,
	1425, 1450, 1475, 1500,
	1550, 1600, 1650, 1700,
	1750, 1800, 1850, 1900,
	1950, 2000, 2050, 2100,
	2150, 2200, 2250, 2300,
	2350, 2400, 2450, 2500,
	2550, 2600, 2650, 2700,
	2750, 2800, 2850, 2900,
	3000, 3100, 3200, 3300,
};

static const u16 LDO1_VSEL_table[] = {
	1000, 1100, 1200, 1250,
	1300, 1350, 1400, 1500,
	1600, 1800, 2500, 2750,
	2800, 3000, 3100, 3300,
};

static const u16 LDO2_VSEL_table[] = {
	725, 750, 775, 800,
	825, 850, 875, 900,
	925, 950, 975, 1000,
	1025, 1050, 1075, 1100,
	1125, 1150, 1175, 1200,
	1225, 1250, 1275, 1300,
	1325, 1350, 1375, 1400,
	1425, 1450, 1475, 1500,
	1550, 1600, 1650, 1700,
	1750, 1800, 1850, 1900,
	1950, 2000, 2050, 2100,
	2150, 2200, 2250, 2300,
	2350, 2400, 2450, 2500,
	2550, 2600, 2650, 2700,
	2750, 2800, 2850, 2900,
	3000, 3100, 3200, 3300,
};

struct tps_info {
	const char *name;
	unsigned min_uV;
	unsigned max_uV;
	u8 table_len;
	const u16 *table;
99 100 101

	/* Does DCDC high or the low register defines output voltage? */
	bool defdcdc_default;
102 103
};

104
static struct tps_info tps6507x_pmic_regs[] = {
T
Todd Fischer 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
	{
		.name = "VDCDC1",
		.min_uV = 725000,
		.max_uV = 3300000,
		.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
		.table = VDCDCx_VSEL_table,
	},
	{
		.name = "VDCDC2",
		.min_uV = 725000,
		.max_uV = 3300000,
		.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
		.table = VDCDCx_VSEL_table,
	},
	{
		.name = "VDCDC3",
		.min_uV = 725000,
		.max_uV = 3300000,
		.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
		.table = VDCDCx_VSEL_table,
	},
	{
		.name = "LDO1",
		.min_uV = 1000000,
		.max_uV = 3300000,
		.table_len = ARRAY_SIZE(LDO1_VSEL_table),
		.table = LDO1_VSEL_table,
	},
	{
		.name = "LDO2",
		.min_uV = 725000,
		.max_uV = 3300000,
		.table_len = ARRAY_SIZE(LDO2_VSEL_table),
		.table = LDO2_VSEL_table,
	},
};

142
struct tps6507x_pmic {
143
	struct regulator_desc desc[TPS6507X_NUM_REGULATOR];
T
Todd Fischer 已提交
144
	struct tps6507x_dev *mfd;
145
	struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR];
146
	struct tps_info *info[TPS6507X_NUM_REGULATOR];
147 148
	struct mutex io_lock;
};
149
static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg)
150
{
T
Todd Fischer 已提交
151 152 153 154 155 156 157 158 159
	u8 val;
	int err;

	err = tps->mfd->read_dev(tps->mfd, reg, 1, &val);

	if (err)
		return err;

	return val;
160 161
}

162
static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
163
{
T
Todd Fischer 已提交
164
	return tps->mfd->write_dev(tps->mfd, reg, 1, &val);
165 166
}

167
static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
168 169 170 171 172
{
	int err, data;

	mutex_lock(&tps->io_lock);

173
	data = tps6507x_pmic_read(tps, reg);
174
	if (data < 0) {
T
Todd Fischer 已提交
175
		dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
176 177 178 179 180
		err = data;
		goto out;
	}

	data |= mask;
181
	err = tps6507x_pmic_write(tps, reg, data);
182
	if (err)
T
Todd Fischer 已提交
183
		dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
184 185 186 187 188 189

out:
	mutex_unlock(&tps->io_lock);
	return err;
}

190
static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
191 192 193 194 195
{
	int err, data;

	mutex_lock(&tps->io_lock);

196
	data = tps6507x_pmic_read(tps, reg);
197
	if (data < 0) {
T
Todd Fischer 已提交
198
		dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
199 200 201 202 203
		err = data;
		goto out;
	}

	data &= ~mask;
204
	err = tps6507x_pmic_write(tps, reg, data);
205
	if (err)
T
Todd Fischer 已提交
206
		dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
207 208 209 210 211 212

out:
	mutex_unlock(&tps->io_lock);
	return err;
}

213
static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg)
214 215 216 217 218
{
	int data;

	mutex_lock(&tps->io_lock);

219
	data = tps6507x_pmic_read(tps, reg);
220
	if (data < 0)
T
Todd Fischer 已提交
221
		dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
222 223 224 225 226

	mutex_unlock(&tps->io_lock);
	return data;
}

227
static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
228 229 230 231 232
{
	int err;

	mutex_lock(&tps->io_lock);

233
	err = tps6507x_pmic_write(tps, reg, val);
234
	if (err < 0)
T
Todd Fischer 已提交
235
		dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
236 237 238 239 240

	mutex_unlock(&tps->io_lock);
	return err;
}

241
static int tps6507x_pmic_is_enabled(struct regulator_dev *dev)
242
{
243
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
244
	int data, rid = rdev_get_id(dev);
245 246
	u8 shift;

247
	if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
248 249
		return -EINVAL;

250
	shift = TPS6507X_MAX_REG_ID - rid;
251
	data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
252 253 254 255 256 257 258

	if (data < 0)
		return data;
	else
		return (data & 1<<shift) ? 1 : 0;
}

259
static int tps6507x_pmic_enable(struct regulator_dev *dev)
260
{
261
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
262
	int rid = rdev_get_id(dev);
263 264
	u8 shift;

265
	if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
266 267
		return -EINVAL;

268
	shift = TPS6507X_MAX_REG_ID - rid;
269
	return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
270 271
}

272
static int tps6507x_pmic_disable(struct regulator_dev *dev)
273
{
274
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
275
	int rid = rdev_get_id(dev);
276 277
	u8 shift;

278
	if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
279 280
		return -EINVAL;

281
	shift = TPS6507X_MAX_REG_ID - rid;
282 283
	return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
					1 << shift);
284 285
}

286
static int tps6507x_pmic_get_voltage(struct regulator_dev *dev)
287
{
288
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
289 290
	int data, rid = rdev_get_id(dev);
	u8 reg, mask;
291

292
	switch (rid) {
293 294
	case TPS6507X_DCDC_1:
		reg = TPS6507X_REG_DEFDCDC1;
295
		mask = TPS6507X_DEFDCDCX_DCDC_MASK;
296 297
		break;
	case TPS6507X_DCDC_2:
298
		if (tps->info[rid]->defdcdc_default)
299 300 301
			reg = TPS6507X_REG_DEFDCDC2_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC2_LOW;
302
		mask = TPS6507X_DEFDCDCX_DCDC_MASK;
303 304
		break;
	case TPS6507X_DCDC_3:
305
		if (tps->info[rid]->defdcdc_default)
306 307 308
			reg = TPS6507X_REG_DEFDCDC3_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC3_LOW;
309 310 311 312 313 314 315 316 317
		mask = TPS6507X_DEFDCDCX_DCDC_MASK;
		break;
	case TPS6507X_LDO_1:
		reg = TPS6507X_REG_LDO_CTRL1;
		mask = TPS6507X_REG_LDO_CTRL1_LDO1_MASK;
		break;
	case TPS6507X_LDO_2:
		reg = TPS6507X_REG_DEFLDO2;
		mask = TPS6507X_REG_DEFLDO2_LDO2_MASK;
318 319 320 321 322
		break;
	default:
		return -EINVAL;
	}

323
	data = tps6507x_pmic_reg_read(tps, reg);
324 325 326
	if (data < 0)
		return data;

327 328
	data &= mask;
	return tps->info[rid]->table[data] * 1000;
329 330
}

331 332
static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev,
					  unsigned selector)
333
{
334
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
335
	int data, rid = rdev_get_id(dev);
336
	u8 reg, mask;
337

338
	switch (rid) {
339 340
	case TPS6507X_DCDC_1:
		reg = TPS6507X_REG_DEFDCDC1;
341
		mask = TPS6507X_DEFDCDCX_DCDC_MASK;
342 343
		break;
	case TPS6507X_DCDC_2:
344
		if (tps->info[rid]->defdcdc_default)
345 346 347
			reg = TPS6507X_REG_DEFDCDC2_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC2_LOW;
348
		mask = TPS6507X_DEFDCDCX_DCDC_MASK;
349 350
		break;
	case TPS6507X_DCDC_3:
351
		if (tps->info[rid]->defdcdc_default)
352 353 354
			reg = TPS6507X_REG_DEFDCDC3_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC3_LOW;
355 356 357 358 359 360 361 362 363
		mask = TPS6507X_DEFDCDCX_DCDC_MASK;
		break;
	case TPS6507X_LDO_1:
		reg = TPS6507X_REG_LDO_CTRL1;
		mask = TPS6507X_REG_LDO_CTRL1_LDO1_MASK;
		break;
	case TPS6507X_LDO_2:
		reg = TPS6507X_REG_DEFLDO2;
		mask = TPS6507X_REG_DEFLDO2_LDO2_MASK;
364 365 366 367 368
		break;
	default:
		return -EINVAL;
	}

369
	data = tps6507x_pmic_reg_read(tps, reg);
370 371 372 373
	if (data < 0)
		return data;

	data &= ~mask;
374
	data |= selector;
375

376
	return tps6507x_pmic_reg_write(tps, reg, data);
377 378
}

379
static int tps6507x_pmic_list_voltage(struct regulator_dev *dev,
380 381
					unsigned selector)
{
382
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
383
	int rid = rdev_get_id(dev);
384

385
	if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
386 387
		return -EINVAL;

388
	if (selector >= tps->info[rid]->table_len)
389 390
		return -EINVAL;
	else
391
		return tps->info[rid]->table[selector] * 1000;
392 393
}

394 395 396 397 398
static struct regulator_ops tps6507x_pmic_ops = {
	.is_enabled = tps6507x_pmic_is_enabled,
	.enable = tps6507x_pmic_enable,
	.disable = tps6507x_pmic_disable,
	.get_voltage = tps6507x_pmic_get_voltage,
399
	.set_voltage_sel = tps6507x_pmic_set_voltage_sel,
400
	.list_voltage = tps6507x_pmic_list_voltage,
401 402
};

403
static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
404
{
T
Todd Fischer 已提交
405
	struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
406
	struct tps_info *info = &tps6507x_pmic_regs[0];
407 408
	struct regulator_init_data *init_data;
	struct regulator_dev *rdev;
409
	struct tps6507x_pmic *tps;
410
	struct tps6507x_board *tps_board;
411
	int i;
412
	int error;
413

414 415 416 417 418
	/**
	 * tps_board points to pmic related constants
	 * coming from the board-evm file.
	 */

T
Todd Fischer 已提交
419
	tps_board = dev_get_platdata(tps6507x_dev->dev);
420 421 422
	if (!tps_board)
		return -EINVAL;

423 424 425 426
	/**
	 * init_data points to array of regulator_init structures
	 * coming from the board-evm file.
	 */
427
	init_data = tps_board->tps6507x_pmic_init_data;
428
	if (!init_data)
429
		return -EINVAL;
430 431 432 433 434 435 436 437

	tps = kzalloc(sizeof(*tps), GFP_KERNEL);
	if (!tps)
		return -ENOMEM;

	mutex_init(&tps->io_lock);

	/* common for all regulators */
T
Todd Fischer 已提交
438
	tps->mfd = tps6507x_dev;
439 440 441 442

	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) {
		/* Register the regulators */
		tps->info[i] = info;
443 444 445 446 447 448
		if (init_data->driver_data) {
			struct tps6507x_reg_platform_data *data =
							init_data->driver_data;
			tps->info[i]->defdcdc_default = data->defdcdc_default;
		}

449
		tps->desc[i].name = info->name;
450
		tps->desc[i].id = i;
451
		tps->desc[i].n_voltages = info->table_len;
452
		tps->desc[i].ops = &tps6507x_pmic_ops;
453 454 455 456
		tps->desc[i].type = REGULATOR_VOLTAGE;
		tps->desc[i].owner = THIS_MODULE;

		rdev = regulator_register(&tps->desc[i],
457
					tps6507x_dev->dev, init_data, tps, NULL);
458
		if (IS_ERR(rdev)) {
T
Todd Fischer 已提交
459 460 461
			dev_err(tps6507x_dev->dev,
				"failed to register %s regulator\n",
				pdev->name);
462 463
			error = PTR_ERR(rdev);
			goto fail;
464 465 466 467 468 469
		}

		/* Save regulator for cleanup */
		tps->rdev[i] = rdev;
	}

T
Todd Fischer 已提交
470
	tps6507x_dev->pmic = tps;
471
	platform_set_drvdata(pdev, tps6507x_dev);
472 473

	return 0;
474 475 476 477 478 479 480

fail:
	while (--i >= 0)
		regulator_unregister(tps->rdev[i]);

	kfree(tps);
	return error;
481 482
}

T
Todd Fischer 已提交
483
static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
484
{
T
Todd Fischer 已提交
485 486
	struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
	struct tps6507x_pmic *tps = tps6507x_dev->pmic;
487 488 489 490 491 492 493 494 495 496
	int i;

	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
		regulator_unregister(tps->rdev[i]);

	kfree(tps);

	return 0;
}

T
Todd Fischer 已提交
497
static struct platform_driver tps6507x_pmic_driver = {
498
	.driver = {
T
Todd Fischer 已提交
499
		.name = "tps6507x-pmic",
500 501
		.owner = THIS_MODULE,
	},
502 503
	.probe = tps6507x_pmic_probe,
	.remove = __devexit_p(tps6507x_pmic_remove),
504 505
};

506
static int __init tps6507x_pmic_init(void)
507
{
T
Todd Fischer 已提交
508
	return platform_driver_register(&tps6507x_pmic_driver);
509
}
510
subsys_initcall(tps6507x_pmic_init);
511

512
static void __exit tps6507x_pmic_cleanup(void)
513
{
T
Todd Fischer 已提交
514
	platform_driver_unregister(&tps6507x_pmic_driver);
515
}
516
module_exit(tps6507x_pmic_cleanup);
517 518 519

MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("TPS6507x voltage regulator driver");
520
MODULE_LICENSE("GPL v2");
T
Todd Fischer 已提交
521
MODULE_ALIAS("platform:tps6507x-pmic");