tps6507x-regulator.c 15.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 99 100 101 102 103 104

/* 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,
};

static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDCx_VSEL_table),
				ARRAY_SIZE(VDCDCx_VSEL_table),
				ARRAY_SIZE(VDCDCx_VSEL_table),
				ARRAY_SIZE(LDO1_VSEL_table),
				ARRAY_SIZE(LDO2_VSEL_table)};

struct tps_info {
	const char *name;
	unsigned min_uV;
	unsigned max_uV;
	u8 table_len;
	const u16 *table;
105 106 107

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

110
static struct tps_info tps6507x_pmic_regs[] = {
T
Todd Fischer 已提交
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 142 143 144 145 146 147
	{
		.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,
	},
};

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

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

	if (err)
		return err;

	return val;
166 167
}

168
static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
169
{
T
Todd Fischer 已提交
170
	return tps->mfd->write_dev(tps->mfd, reg, 1, &val);
171 172
}

173
static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
174 175 176 177 178
{
	int err, data;

	mutex_lock(&tps->io_lock);

179
	data = tps6507x_pmic_read(tps, reg);
180
	if (data < 0) {
T
Todd Fischer 已提交
181
		dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
182 183 184 185 186
		err = data;
		goto out;
	}

	data |= mask;
187
	err = tps6507x_pmic_write(tps, reg, data);
188
	if (err)
T
Todd Fischer 已提交
189
		dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
190 191 192 193 194 195

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

196
static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
197 198 199 200 201
{
	int err, data;

	mutex_lock(&tps->io_lock);

202
	data = tps6507x_pmic_read(tps, reg);
203
	if (data < 0) {
T
Todd Fischer 已提交
204
		dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
205 206 207 208 209
		err = data;
		goto out;
	}

	data &= ~mask;
210
	err = tps6507x_pmic_write(tps, reg, data);
211
	if (err)
T
Todd Fischer 已提交
212
		dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
213 214 215 216 217 218

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

219
static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg)
220 221 222 223 224
{
	int data;

	mutex_lock(&tps->io_lock);

225
	data = tps6507x_pmic_read(tps, reg);
226
	if (data < 0)
T
Todd Fischer 已提交
227
		dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
228 229 230 231 232

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

233
static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
234 235 236 237 238
{
	int err;

	mutex_lock(&tps->io_lock);

239
	err = tps6507x_pmic_write(tps, reg, val);
240
	if (err < 0)
T
Todd Fischer 已提交
241
		dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
242 243 244 245 246

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

247
static int tps6507x_pmic_dcdc_is_enabled(struct regulator_dev *dev)
248
{
249
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
250 251 252 253 254 255 256
	int data, dcdc = rdev_get_id(dev);
	u8 shift;

	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
		return -EINVAL;

	shift = TPS6507X_MAX_REG_ID - dcdc;
257
	data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
258 259 260 261 262 263 264

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

265
static int tps6507x_pmic_ldo_is_enabled(struct regulator_dev *dev)
266
{
267
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
268 269 270 271 272 273 274
	int data, ldo = rdev_get_id(dev);
	u8 shift;

	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
		return -EINVAL;

	shift = TPS6507X_MAX_REG_ID - ldo;
275
	data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
276 277 278 279 280 281 282

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

283
static int tps6507x_pmic_dcdc_enable(struct regulator_dev *dev)
284
{
285
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
286 287 288 289 290 291 292
	int dcdc = rdev_get_id(dev);
	u8 shift;

	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
		return -EINVAL;

	shift = TPS6507X_MAX_REG_ID - dcdc;
293
	return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
294 295
}

296
static int tps6507x_pmic_dcdc_disable(struct regulator_dev *dev)
297
{
298
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
299 300 301 302 303 304 305
	int dcdc = rdev_get_id(dev);
	u8 shift;

	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
		return -EINVAL;

	shift = TPS6507X_MAX_REG_ID - dcdc;
306 307
	return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
					1 << shift);
308 309
}

310
static int tps6507x_pmic_ldo_enable(struct regulator_dev *dev)
311
{
312
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
313 314 315 316 317 318 319
	int ldo = rdev_get_id(dev);
	u8 shift;

	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
		return -EINVAL;

	shift = TPS6507X_MAX_REG_ID - ldo;
320
	return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
321 322
}

323
static int tps6507x_pmic_ldo_disable(struct regulator_dev *dev)
324
{
325
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
326 327 328 329 330 331 332
	int ldo = rdev_get_id(dev);
	u8 shift;

	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
		return -EINVAL;

	shift = TPS6507X_MAX_REG_ID - ldo;
333 334
	return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
					1 << shift);
335 336
}

337
static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev)
338
{
339
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
340 341 342 343 344 345 346 347
	int data, dcdc = rdev_get_id(dev);
	u8 reg;

	switch (dcdc) {
	case TPS6507X_DCDC_1:
		reg = TPS6507X_REG_DEFDCDC1;
		break;
	case TPS6507X_DCDC_2:
348 349 350 351
		if (tps->info[dcdc]->defdcdc_default)
			reg = TPS6507X_REG_DEFDCDC2_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC2_LOW;
352 353
		break;
	case TPS6507X_DCDC_3:
354 355 356 357
		if (tps->info[dcdc]->defdcdc_default)
			reg = TPS6507X_REG_DEFDCDC3_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC3_LOW;
358 359 360 361 362
		break;
	default:
		return -EINVAL;
	}

363
	data = tps6507x_pmic_reg_read(tps, reg);
364 365 366 367 368 369 370
	if (data < 0)
		return data;

	data &= TPS6507X_DEFDCDCX_DCDC_MASK;
	return tps->info[dcdc]->table[data] * 1000;
}

371
static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,
372 373
				int min_uV, int max_uV)
{
374
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
375 376 377 378 379 380 381 382
	int data, vsel, dcdc = rdev_get_id(dev);
	u8 reg;

	switch (dcdc) {
	case TPS6507X_DCDC_1:
		reg = TPS6507X_REG_DEFDCDC1;
		break;
	case TPS6507X_DCDC_2:
383 384 385 386
		if (tps->info[dcdc]->defdcdc_default)
			reg = TPS6507X_REG_DEFDCDC2_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC2_LOW;
387 388
		break;
	case TPS6507X_DCDC_3:
389 390 391 392
		if (tps->info[dcdc]->defdcdc_default)
			reg = TPS6507X_REG_DEFDCDC3_HIGH;
		else
			reg = TPS6507X_REG_DEFDCDC3_LOW;
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
		break;
	default:
		return -EINVAL;
	}

	if (min_uV < tps->info[dcdc]->min_uV
		|| min_uV > tps->info[dcdc]->max_uV)
		return -EINVAL;
	if (max_uV < tps->info[dcdc]->min_uV
		|| max_uV > tps->info[dcdc]->max_uV)
		return -EINVAL;

	for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) {
		int mV = tps->info[dcdc]->table[vsel];
		int uV = mV * 1000;

		/* Break at the first in-range value */
		if (min_uV <= uV && uV <= max_uV)
			break;
	}

	/* write to the register in case we found a match */
	if (vsel == tps->info[dcdc]->table_len)
		return -EINVAL;

418
	data = tps6507x_pmic_reg_read(tps, reg);
419 420 421 422 423 424
	if (data < 0)
		return data;

	data &= ~TPS6507X_DEFDCDCX_DCDC_MASK;
	data |= vsel;

425
	return tps6507x_pmic_reg_write(tps, reg, data);
426 427
}

428
static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev)
429
{
430
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
431 432 433 434 435 436 437 438 439 440 441 442 443
	int data, ldo = rdev_get_id(dev);
	u8 reg, mask;

	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
		return -EINVAL;
	else {
		reg = (ldo == TPS6507X_LDO_1 ?
			TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2);
		mask = (ldo == TPS6507X_LDO_1 ?
			TPS6507X_REG_LDO_CTRL1_LDO1_MASK :
				TPS6507X_REG_DEFLDO2_LDO2_MASK);
	}

444
	data = tps6507x_pmic_reg_read(tps, reg);
445 446 447 448 449 450 451
	if (data < 0)
		return data;

	data &= mask;
	return tps->info[ldo]->table[data] * 1000;
}

452
static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev,
453 454
				int min_uV, int max_uV)
{
455
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
	int data, vsel, ldo = rdev_get_id(dev);
	u8 reg, mask;

	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
		return -EINVAL;
	else {
		reg = (ldo == TPS6507X_LDO_1 ?
			TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2);
		mask = (ldo == TPS6507X_LDO_1 ?
			TPS6507X_REG_LDO_CTRL1_LDO1_MASK :
				TPS6507X_REG_DEFLDO2_LDO2_MASK);
	}

	if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV)
		return -EINVAL;
	if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV)
		return -EINVAL;

	for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) {
		int mV = tps->info[ldo]->table[vsel];
		int uV = mV * 1000;

		/* Break at the first in-range value */
		if (min_uV <= uV && uV <= max_uV)
			break;
	}

	if (vsel == tps->info[ldo]->table_len)
		return -EINVAL;

486
	data = tps6507x_pmic_reg_read(tps, reg);
487 488 489 490 491 492
	if (data < 0)
		return data;

	data &= ~mask;
	data |= vsel;

493
	return tps6507x_pmic_reg_write(tps, reg, data);
494 495
}

496
static int tps6507x_pmic_dcdc_list_voltage(struct regulator_dev *dev,
497 498
					unsigned selector)
{
499
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
500 501 502 503 504 505 506 507 508 509 510
	int dcdc = rdev_get_id(dev);

	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
		return -EINVAL;

	if (selector >= tps->info[dcdc]->table_len)
		return -EINVAL;
	else
		return tps->info[dcdc]->table[selector] * 1000;
}

511
static int tps6507x_pmic_ldo_list_voltage(struct regulator_dev *dev,
512 513
					unsigned selector)
{
514
	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
515 516 517 518 519 520 521 522 523 524 525 526
	int ldo = rdev_get_id(dev);

	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
		return -EINVAL;

	if (selector >= tps->info[ldo]->table_len)
		return -EINVAL;
	else
		return tps->info[ldo]->table[selector] * 1000;
}

/* Operations permitted on VDCDCx */
527 528 529 530 531 532 533
static struct regulator_ops tps6507x_pmic_dcdc_ops = {
	.is_enabled = tps6507x_pmic_dcdc_is_enabled,
	.enable = tps6507x_pmic_dcdc_enable,
	.disable = tps6507x_pmic_dcdc_disable,
	.get_voltage = tps6507x_pmic_dcdc_get_voltage,
	.set_voltage = tps6507x_pmic_dcdc_set_voltage,
	.list_voltage = tps6507x_pmic_dcdc_list_voltage,
534 535 536
};

/* Operations permitted on LDOx */
537 538 539 540 541 542 543
static struct regulator_ops tps6507x_pmic_ldo_ops = {
	.is_enabled = tps6507x_pmic_ldo_is_enabled,
	.enable = tps6507x_pmic_ldo_enable,
	.disable = tps6507x_pmic_ldo_disable,
	.get_voltage = tps6507x_pmic_ldo_get_voltage,
	.set_voltage = tps6507x_pmic_ldo_set_voltage,
	.list_voltage = tps6507x_pmic_ldo_list_voltage,
544 545
};

T
Todd Fischer 已提交
546 547
static __devinit
int tps6507x_pmic_probe(struct platform_device *pdev)
548
{
T
Todd Fischer 已提交
549
	struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
550
	static int desc_id;
551
	struct tps_info *info = &tps6507x_pmic_regs[0];
552 553
	struct regulator_init_data *init_data;
	struct regulator_dev *rdev;
554
	struct tps6507x_pmic *tps;
555
	struct tps6507x_board *tps_board;
556
	int i;
557
	int error;
558

559 560 561 562 563
	/**
	 * tps_board points to pmic related constants
	 * coming from the board-evm file.
	 */

T
Todd Fischer 已提交
564
	tps_board = dev_get_platdata(tps6507x_dev->dev);
565 566 567
	if (!tps_board)
		return -EINVAL;

568 569 570 571
	/**
	 * init_data points to array of regulator_init structures
	 * coming from the board-evm file.
	 */
572
	init_data = tps_board->tps6507x_pmic_init_data;
573
	if (!init_data)
574
		return -EINVAL;
575 576 577 578 579 580 581 582

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

	mutex_init(&tps->io_lock);

	/* common for all regulators */
T
Todd Fischer 已提交
583
	tps->mfd = tps6507x_dev;
584 585 586 587

	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) {
		/* Register the regulators */
		tps->info[i] = info;
588 589 590 591 592 593
		if (init_data->driver_data) {
			struct tps6507x_reg_platform_data *data =
							init_data->driver_data;
			tps->info[i]->defdcdc_default = data->defdcdc_default;
		}

594 595 596 597
		tps->desc[i].name = info->name;
		tps->desc[i].id = desc_id++;
		tps->desc[i].n_voltages = num_voltages[i];
		tps->desc[i].ops = (i > TPS6507X_DCDC_3 ?
598
		&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);
599 600 601 602
		tps->desc[i].type = REGULATOR_VOLTAGE;
		tps->desc[i].owner = THIS_MODULE;

		rdev = regulator_register(&tps->desc[i],
T
Todd Fischer 已提交
603
					tps6507x_dev->dev, init_data, tps);
604
		if (IS_ERR(rdev)) {
T
Todd Fischer 已提交
605 606 607
			dev_err(tps6507x_dev->dev,
				"failed to register %s regulator\n",
				pdev->name);
608 609
			error = PTR_ERR(rdev);
			goto fail;
610 611 612 613 614 615
		}

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

T
Todd Fischer 已提交
616
	tps6507x_dev->pmic = tps;
617 618

	return 0;
619 620 621 622 623 624 625

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

	kfree(tps);
	return error;
626 627 628
}

/**
629
 * tps6507x_remove - TPS6507x driver i2c remove handler
630 631 632 633
 * @client: i2c driver client device structure
 *
 * Unregister TPS driver as an i2c client device driver
 */
T
Todd Fischer 已提交
634
static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
635
{
T
Todd Fischer 已提交
636 637
	struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
	struct tps6507x_pmic *tps = tps6507x_dev->pmic;
638 639 640 641 642 643 644 645 646 647
	int i;

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

	kfree(tps);

	return 0;
}

T
Todd Fischer 已提交
648
static struct platform_driver tps6507x_pmic_driver = {
649
	.driver = {
T
Todd Fischer 已提交
650
		.name = "tps6507x-pmic",
651 652
		.owner = THIS_MODULE,
	},
653 654
	.probe = tps6507x_pmic_probe,
	.remove = __devexit_p(tps6507x_pmic_remove),
655 656 657
};

/**
658
 * tps6507x_pmic_init
659 660 661
 *
 * Module init function
 */
662
static int __init tps6507x_pmic_init(void)
663
{
T
Todd Fischer 已提交
664
	return platform_driver_register(&tps6507x_pmic_driver);
665
}
666
subsys_initcall(tps6507x_pmic_init);
667 668

/**
669
 * tps6507x_pmic_cleanup
670 671 672
 *
 * Module exit function
 */
673
static void __exit tps6507x_pmic_cleanup(void)
674
{
T
Todd Fischer 已提交
675
	platform_driver_unregister(&tps6507x_pmic_driver);
676
}
677
module_exit(tps6507x_pmic_cleanup);
678 679 680

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