1518fb721SGraeme Gregory /*
2518fb721SGraeme Gregory  * tps65910.c  --  TI tps65910
3518fb721SGraeme Gregory  *
4518fb721SGraeme Gregory  * Copyright 2010 Texas Instruments Inc.
5518fb721SGraeme Gregory  *
6518fb721SGraeme Gregory  * Author: Graeme Gregory <gg@slimlogic.co.uk>
7518fb721SGraeme Gregory  * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
8518fb721SGraeme Gregory  *
9518fb721SGraeme Gregory  *  This program is free software; you can redistribute it and/or modify it
10518fb721SGraeme Gregory  *  under  the terms of the GNU General  Public License as published by the
11518fb721SGraeme Gregory  *  Free Software Foundation;  either version 2 of the License, or (at your
12518fb721SGraeme Gregory  *  option) any later version.
13518fb721SGraeme Gregory  *
14518fb721SGraeme Gregory  */
15518fb721SGraeme Gregory 
16518fb721SGraeme Gregory #include <linux/kernel.h>
17518fb721SGraeme Gregory #include <linux/module.h>
18518fb721SGraeme Gregory #include <linux/init.h>
19518fb721SGraeme Gregory #include <linux/err.h>
20518fb721SGraeme Gregory #include <linux/platform_device.h>
21518fb721SGraeme Gregory #include <linux/regulator/driver.h>
22518fb721SGraeme Gregory #include <linux/regulator/machine.h>
23518fb721SGraeme Gregory #include <linux/delay.h>
24518fb721SGraeme Gregory #include <linux/slab.h>
25518fb721SGraeme Gregory #include <linux/gpio.h>
26518fb721SGraeme Gregory #include <linux/mfd/tps65910.h>
27518fb721SGraeme Gregory 
28518fb721SGraeme Gregory #define TPS65910_REG_VRTC		0
29518fb721SGraeme Gregory #define TPS65910_REG_VIO		1
30518fb721SGraeme Gregory #define TPS65910_REG_VDD1		2
31518fb721SGraeme Gregory #define TPS65910_REG_VDD2		3
32518fb721SGraeme Gregory #define TPS65910_REG_VDD3		4
33518fb721SGraeme Gregory #define TPS65910_REG_VDIG1		5
34518fb721SGraeme Gregory #define TPS65910_REG_VDIG2		6
35518fb721SGraeme Gregory #define TPS65910_REG_VPLL		7
36518fb721SGraeme Gregory #define TPS65910_REG_VDAC		8
37518fb721SGraeme Gregory #define TPS65910_REG_VAUX1		9
38518fb721SGraeme Gregory #define TPS65910_REG_VAUX2		10
39518fb721SGraeme Gregory #define TPS65910_REG_VAUX33		11
40518fb721SGraeme Gregory #define TPS65910_REG_VMMC		12
41518fb721SGraeme Gregory 
42518fb721SGraeme Gregory #define TPS65910_NUM_REGULATOR		13
43518fb721SGraeme Gregory 
44518fb721SGraeme Gregory #define TPS65910_SUPPLY_STATE_ENABLED	0x1
45518fb721SGraeme Gregory 
46518fb721SGraeme Gregory /* supported VIO voltages in milivolts */
47518fb721SGraeme Gregory static const u16 VIO_VSEL_table[] = {
48518fb721SGraeme Gregory 	1500, 1800, 2500, 3300,
49518fb721SGraeme Gregory };
50518fb721SGraeme Gregory 
51518fb721SGraeme Gregory /* supported VIO voltages in milivolts */
52518fb721SGraeme Gregory static const u16 VDD3_VSEL_table[] = {
53518fb721SGraeme Gregory 	5000,
54518fb721SGraeme Gregory };
55518fb721SGraeme Gregory 
56518fb721SGraeme Gregory /* supported VDIG1 voltages in milivolts */
57518fb721SGraeme Gregory static const u16 VDIG1_VSEL_table[] = {
58518fb721SGraeme Gregory 	1200, 1500, 1800, 2700,
59518fb721SGraeme Gregory };
60518fb721SGraeme Gregory 
61518fb721SGraeme Gregory /* supported VDIG2 voltages in milivolts */
62518fb721SGraeme Gregory static const u16 VDIG2_VSEL_table[] = {
63518fb721SGraeme Gregory 	1000, 1100, 1200, 1800,
64518fb721SGraeme Gregory };
65518fb721SGraeme Gregory 
66518fb721SGraeme Gregory /* supported VPLL voltages in milivolts */
67518fb721SGraeme Gregory static const u16 VPLL_VSEL_table[] = {
68518fb721SGraeme Gregory 	1000, 1100, 1800, 2500,
69518fb721SGraeme Gregory };
70518fb721SGraeme Gregory 
71518fb721SGraeme Gregory /* supported VDAC voltages in milivolts */
72518fb721SGraeme Gregory static const u16 VDAC_VSEL_table[] = {
73518fb721SGraeme Gregory 	1800, 2600, 2800, 2850,
74518fb721SGraeme Gregory };
75518fb721SGraeme Gregory 
76518fb721SGraeme Gregory /* supported VAUX1 voltages in milivolts */
77518fb721SGraeme Gregory static const u16 VAUX1_VSEL_table[] = {
78518fb721SGraeme Gregory 	1800, 2500, 2800, 2850,
79518fb721SGraeme Gregory };
80518fb721SGraeme Gregory 
81518fb721SGraeme Gregory /* supported VAUX2 voltages in milivolts */
82518fb721SGraeme Gregory static const u16 VAUX2_VSEL_table[] = {
83518fb721SGraeme Gregory 	1800, 2800, 2900, 3300,
84518fb721SGraeme Gregory };
85518fb721SGraeme Gregory 
86518fb721SGraeme Gregory /* supported VAUX33 voltages in milivolts */
87518fb721SGraeme Gregory static const u16 VAUX33_VSEL_table[] = {
88518fb721SGraeme Gregory 	1800, 2000, 2800, 3300,
89518fb721SGraeme Gregory };
90518fb721SGraeme Gregory 
91518fb721SGraeme Gregory /* supported VMMC voltages in milivolts */
92518fb721SGraeme Gregory static const u16 VMMC_VSEL_table[] = {
93518fb721SGraeme Gregory 	1800, 2800, 3000, 3300,
94518fb721SGraeme Gregory };
95518fb721SGraeme Gregory 
96518fb721SGraeme Gregory struct tps_info {
97518fb721SGraeme Gregory 	const char *name;
98518fb721SGraeme Gregory 	unsigned min_uV;
99518fb721SGraeme Gregory 	unsigned max_uV;
100518fb721SGraeme Gregory 	u8 table_len;
101518fb721SGraeme Gregory 	const u16 *table;
102518fb721SGraeme Gregory };
103518fb721SGraeme Gregory 
104518fb721SGraeme Gregory static struct tps_info tps65910_regs[] = {
105518fb721SGraeme Gregory 	{
106518fb721SGraeme Gregory 		.name = "VRTC",
107518fb721SGraeme Gregory 	},
108518fb721SGraeme Gregory 	{
109518fb721SGraeme Gregory 		.name = "VIO",
110518fb721SGraeme Gregory 		.min_uV = 1500000,
111518fb721SGraeme Gregory 		.max_uV = 3300000,
112518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VIO_VSEL_table),
113518fb721SGraeme Gregory 		.table = VIO_VSEL_table,
114518fb721SGraeme Gregory 	},
115518fb721SGraeme Gregory 	{
116518fb721SGraeme Gregory 		.name = "VDD1",
117518fb721SGraeme Gregory 		.min_uV = 600000,
118518fb721SGraeme Gregory 		.max_uV = 4500000,
119518fb721SGraeme Gregory 	},
120518fb721SGraeme Gregory 	{
121518fb721SGraeme Gregory 		.name = "VDD2",
122518fb721SGraeme Gregory 		.min_uV = 600000,
123518fb721SGraeme Gregory 		.max_uV = 4500000,
124518fb721SGraeme Gregory 	},
125518fb721SGraeme Gregory 	{
126518fb721SGraeme Gregory 		.name = "VDD3",
127518fb721SGraeme Gregory 		.min_uV = 5000000,
128518fb721SGraeme Gregory 		.max_uV = 5000000,
129518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VDD3_VSEL_table),
130518fb721SGraeme Gregory 		.table = VDD3_VSEL_table,
131518fb721SGraeme Gregory 	},
132518fb721SGraeme Gregory 	{
133518fb721SGraeme Gregory 		.name = "VDIG1",
134518fb721SGraeme Gregory 		.min_uV = 1200000,
135518fb721SGraeme Gregory 		.max_uV = 2700000,
136518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VDIG1_VSEL_table),
137518fb721SGraeme Gregory 		.table = VDIG1_VSEL_table,
138518fb721SGraeme Gregory 	},
139518fb721SGraeme Gregory 	{
140518fb721SGraeme Gregory 		.name = "VDIG2",
141518fb721SGraeme Gregory 		.min_uV = 1000000,
142518fb721SGraeme Gregory 		.max_uV = 1800000,
143518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VDIG2_VSEL_table),
144518fb721SGraeme Gregory 		.table = VDIG2_VSEL_table,
145518fb721SGraeme Gregory 	},
146518fb721SGraeme Gregory 	{
147518fb721SGraeme Gregory 		.name = "VPLL",
148518fb721SGraeme Gregory 		.min_uV = 1000000,
149518fb721SGraeme Gregory 		.max_uV = 2500000,
150518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VPLL_VSEL_table),
151518fb721SGraeme Gregory 		.table = VPLL_VSEL_table,
152518fb721SGraeme Gregory 	},
153518fb721SGraeme Gregory 	{
154518fb721SGraeme Gregory 		.name = "VDAC",
155518fb721SGraeme Gregory 		.min_uV = 1800000,
156518fb721SGraeme Gregory 		.max_uV = 2850000,
157518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VDAC_VSEL_table),
158518fb721SGraeme Gregory 		.table = VDAC_VSEL_table,
159518fb721SGraeme Gregory 	},
160518fb721SGraeme Gregory 	{
161518fb721SGraeme Gregory 		.name = "VAUX1",
162518fb721SGraeme Gregory 		.min_uV = 1800000,
163518fb721SGraeme Gregory 		.max_uV = 2850000,
164518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VAUX1_VSEL_table),
165518fb721SGraeme Gregory 		.table = VAUX1_VSEL_table,
166518fb721SGraeme Gregory 	},
167518fb721SGraeme Gregory 	{
168518fb721SGraeme Gregory 		.name = "VAUX2",
169518fb721SGraeme Gregory 		.min_uV = 1800000,
170518fb721SGraeme Gregory 		.max_uV = 3300000,
171518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VAUX2_VSEL_table),
172518fb721SGraeme Gregory 		.table = VAUX2_VSEL_table,
173518fb721SGraeme Gregory 	},
174518fb721SGraeme Gregory 	{
175518fb721SGraeme Gregory 		.name = "VAUX33",
176518fb721SGraeme Gregory 		.min_uV = 1800000,
177518fb721SGraeme Gregory 		.max_uV = 3300000,
178518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VAUX33_VSEL_table),
179518fb721SGraeme Gregory 		.table = VAUX33_VSEL_table,
180518fb721SGraeme Gregory 	},
181518fb721SGraeme Gregory 	{
182518fb721SGraeme Gregory 		.name = "VMMC",
183518fb721SGraeme Gregory 		.min_uV = 1800000,
184518fb721SGraeme Gregory 		.max_uV = 3300000,
185518fb721SGraeme Gregory 		.table_len = ARRAY_SIZE(VMMC_VSEL_table),
186518fb721SGraeme Gregory 		.table = VMMC_VSEL_table,
187518fb721SGraeme Gregory 	},
188518fb721SGraeme Gregory };
189518fb721SGraeme Gregory 
190518fb721SGraeme Gregory struct tps65910_reg {
191518fb721SGraeme Gregory 	struct regulator_desc desc[TPS65910_NUM_REGULATOR];
192518fb721SGraeme Gregory 	struct tps65910 *mfd;
193518fb721SGraeme Gregory 	struct regulator_dev *rdev[TPS65910_NUM_REGULATOR];
194518fb721SGraeme Gregory 	struct tps_info *info[TPS65910_NUM_REGULATOR];
195518fb721SGraeme Gregory 	struct mutex mutex;
196518fb721SGraeme Gregory 	int mode;
197518fb721SGraeme Gregory };
198518fb721SGraeme Gregory 
199518fb721SGraeme Gregory static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
200518fb721SGraeme Gregory {
201518fb721SGraeme Gregory 	u8 val;
202518fb721SGraeme Gregory 	int err;
203518fb721SGraeme Gregory 
204518fb721SGraeme Gregory 	err = pmic->mfd->read(pmic->mfd, reg, 1, &val);
205518fb721SGraeme Gregory 	if (err)
206518fb721SGraeme Gregory 		return err;
207518fb721SGraeme Gregory 
208518fb721SGraeme Gregory 	return val;
209518fb721SGraeme Gregory }
210518fb721SGraeme Gregory 
211518fb721SGraeme Gregory static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val)
212518fb721SGraeme Gregory {
213518fb721SGraeme Gregory 	return pmic->mfd->write(pmic->mfd, reg, 1, &val);
214518fb721SGraeme Gregory }
215518fb721SGraeme Gregory 
216518fb721SGraeme Gregory static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
217518fb721SGraeme Gregory 					u8 set_mask, u8 clear_mask)
218518fb721SGraeme Gregory {
219518fb721SGraeme Gregory 	int err, data;
220518fb721SGraeme Gregory 
221518fb721SGraeme Gregory 	mutex_lock(&pmic->mutex);
222518fb721SGraeme Gregory 
223518fb721SGraeme Gregory 	data = tps65910_read(pmic, reg);
224518fb721SGraeme Gregory 	if (data < 0) {
225518fb721SGraeme Gregory 		dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
226518fb721SGraeme Gregory 		err = data;
227518fb721SGraeme Gregory 		goto out;
228518fb721SGraeme Gregory 	}
229518fb721SGraeme Gregory 
230518fb721SGraeme Gregory 	data &= ~clear_mask;
231518fb721SGraeme Gregory 	data |= set_mask;
232518fb721SGraeme Gregory 	err = tps65910_write(pmic, reg, data);
233518fb721SGraeme Gregory 	if (err)
234518fb721SGraeme Gregory 		dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
235518fb721SGraeme Gregory 
236518fb721SGraeme Gregory out:
237518fb721SGraeme Gregory 	mutex_unlock(&pmic->mutex);
238518fb721SGraeme Gregory 	return err;
239518fb721SGraeme Gregory }
240518fb721SGraeme Gregory 
241518fb721SGraeme Gregory static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg)
242518fb721SGraeme Gregory {
243518fb721SGraeme Gregory 	int data;
244518fb721SGraeme Gregory 
245518fb721SGraeme Gregory 	mutex_lock(&pmic->mutex);
246518fb721SGraeme Gregory 
247518fb721SGraeme Gregory 	data = tps65910_read(pmic, reg);
248518fb721SGraeme Gregory 	if (data < 0)
249518fb721SGraeme Gregory 		dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
250518fb721SGraeme Gregory 
251518fb721SGraeme Gregory 	mutex_unlock(&pmic->mutex);
252518fb721SGraeme Gregory 	return data;
253518fb721SGraeme Gregory }
254518fb721SGraeme Gregory 
255518fb721SGraeme Gregory static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val)
256518fb721SGraeme Gregory {
257518fb721SGraeme Gregory 	int err;
258518fb721SGraeme Gregory 
259518fb721SGraeme Gregory 	mutex_lock(&pmic->mutex);
260518fb721SGraeme Gregory 
261518fb721SGraeme Gregory 	err = tps65910_write(pmic, reg, val);
262518fb721SGraeme Gregory 	if (err < 0)
263518fb721SGraeme Gregory 		dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
264518fb721SGraeme Gregory 
265518fb721SGraeme Gregory 	mutex_unlock(&pmic->mutex);
266518fb721SGraeme Gregory 	return err;
267518fb721SGraeme Gregory }
268518fb721SGraeme Gregory 
269518fb721SGraeme Gregory static int tps65910_get_ctrl_register(int id)
270518fb721SGraeme Gregory {
271518fb721SGraeme Gregory 	switch (id) {
272518fb721SGraeme Gregory 	case TPS65910_REG_VRTC:
273518fb721SGraeme Gregory 		return TPS65910_VRTC;
274518fb721SGraeme Gregory 	case TPS65910_REG_VIO:
275518fb721SGraeme Gregory 		return TPS65910_VIO;
276518fb721SGraeme Gregory 	case TPS65910_REG_VDD1:
277518fb721SGraeme Gregory 		return TPS65910_VDD1;
278518fb721SGraeme Gregory 	case TPS65910_REG_VDD2:
279518fb721SGraeme Gregory 		return TPS65910_VDD2;
280518fb721SGraeme Gregory 	case TPS65910_REG_VDD3:
281518fb721SGraeme Gregory 		return TPS65910_VDD3;
282518fb721SGraeme Gregory 	case TPS65910_REG_VDIG1:
283518fb721SGraeme Gregory 		return TPS65910_VDIG1;
284518fb721SGraeme Gregory 	case TPS65910_REG_VDIG2:
285518fb721SGraeme Gregory 		return TPS65910_VDIG2;
286518fb721SGraeme Gregory 	case TPS65910_REG_VPLL:
287518fb721SGraeme Gregory 		return TPS65910_VPLL;
288518fb721SGraeme Gregory 	case TPS65910_REG_VDAC:
289518fb721SGraeme Gregory 		return TPS65910_VDAC;
290518fb721SGraeme Gregory 	case TPS65910_REG_VAUX1:
291518fb721SGraeme Gregory 		return TPS65910_VAUX1;
292518fb721SGraeme Gregory 	case TPS65910_REG_VAUX2:
293518fb721SGraeme Gregory 		return TPS65910_VAUX2;
294518fb721SGraeme Gregory 	case TPS65910_REG_VAUX33:
295518fb721SGraeme Gregory 		return TPS65910_VAUX33;
296518fb721SGraeme Gregory 	case TPS65910_REG_VMMC:
297518fb721SGraeme Gregory 		return TPS65910_VMMC;
298518fb721SGraeme Gregory 	default:
299518fb721SGraeme Gregory 		return -EINVAL;
300518fb721SGraeme Gregory 	}
301518fb721SGraeme Gregory }
302518fb721SGraeme Gregory 
303518fb721SGraeme Gregory static int tps65910_is_enabled(struct regulator_dev *dev)
304518fb721SGraeme Gregory {
305518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
306518fb721SGraeme Gregory 	int reg, value, id = rdev_get_id(dev);
307518fb721SGraeme Gregory 
308518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
309518fb721SGraeme Gregory 	if (reg < 0)
310518fb721SGraeme Gregory 		return reg;
311518fb721SGraeme Gregory 
312518fb721SGraeme Gregory 	value = tps65910_reg_read(pmic, reg);
313518fb721SGraeme Gregory 	if (value < 0)
314518fb721SGraeme Gregory 		return value;
315518fb721SGraeme Gregory 
316518fb721SGraeme Gregory 	return value & TPS65910_SUPPLY_STATE_ENABLED;
317518fb721SGraeme Gregory }
318518fb721SGraeme Gregory 
319518fb721SGraeme Gregory static int tps65910_enable(struct regulator_dev *dev)
320518fb721SGraeme Gregory {
321518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
322518fb721SGraeme Gregory 	struct tps65910 *mfd = pmic->mfd;
323518fb721SGraeme Gregory 	int reg, id = rdev_get_id(dev);
324518fb721SGraeme Gregory 
325518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
326518fb721SGraeme Gregory 	if (reg < 0)
327518fb721SGraeme Gregory 		return reg;
328518fb721SGraeme Gregory 
329518fb721SGraeme Gregory 	return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
330518fb721SGraeme Gregory }
331518fb721SGraeme Gregory 
332518fb721SGraeme Gregory static int tps65910_disable(struct regulator_dev *dev)
333518fb721SGraeme Gregory {
334518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
335518fb721SGraeme Gregory 	struct tps65910 *mfd = pmic->mfd;
336518fb721SGraeme Gregory 	int reg, id = rdev_get_id(dev);
337518fb721SGraeme Gregory 
338518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
339518fb721SGraeme Gregory 	if (reg < 0)
340518fb721SGraeme Gregory 		return reg;
341518fb721SGraeme Gregory 
342518fb721SGraeme Gregory 	return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
343518fb721SGraeme Gregory }
344518fb721SGraeme Gregory 
345518fb721SGraeme Gregory 
346518fb721SGraeme Gregory static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
347518fb721SGraeme Gregory {
348518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
349518fb721SGraeme Gregory 	struct tps65910 *mfd = pmic->mfd;
350518fb721SGraeme Gregory 	int reg, value, id = rdev_get_id(dev);
351518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
352518fb721SGraeme Gregory 	if (reg < 0)
353518fb721SGraeme Gregory 		return reg;
354518fb721SGraeme Gregory 
355518fb721SGraeme Gregory 	switch (mode) {
356518fb721SGraeme Gregory 	case REGULATOR_MODE_NORMAL:
357518fb721SGraeme Gregory 		return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT,
358518fb721SGraeme Gregory 							LDO_ST_MODE_BIT);
359518fb721SGraeme Gregory 	case REGULATOR_MODE_IDLE:
360518fb721SGraeme Gregory 		value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
361518fb721SGraeme Gregory 		return tps65910_set_bits(mfd, reg, value);
362518fb721SGraeme Gregory 	case REGULATOR_MODE_STANDBY:
363518fb721SGraeme Gregory 		return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT);
364518fb721SGraeme Gregory 	}
365518fb721SGraeme Gregory 
366518fb721SGraeme Gregory 	return -EINVAL;
367518fb721SGraeme Gregory }
368518fb721SGraeme Gregory 
369518fb721SGraeme Gregory static unsigned int tps65910_get_mode(struct regulator_dev *dev)
370518fb721SGraeme Gregory {
371518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
372518fb721SGraeme Gregory 	int reg, value, id = rdev_get_id(dev);
373518fb721SGraeme Gregory 
374518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
375518fb721SGraeme Gregory 	if (reg < 0)
376518fb721SGraeme Gregory 		return reg;
377518fb721SGraeme Gregory 
378518fb721SGraeme Gregory 	value = tps65910_reg_read(pmic, reg);
379518fb721SGraeme Gregory 	if (value < 0)
380518fb721SGraeme Gregory 		return value;
381518fb721SGraeme Gregory 
382518fb721SGraeme Gregory 	if (value & LDO_ST_ON_BIT)
383518fb721SGraeme Gregory 		return REGULATOR_MODE_STANDBY;
384518fb721SGraeme Gregory 	else if (value & LDO_ST_MODE_BIT)
385518fb721SGraeme Gregory 		return REGULATOR_MODE_IDLE;
386518fb721SGraeme Gregory 	else
387518fb721SGraeme Gregory 		return REGULATOR_MODE_NORMAL;
388518fb721SGraeme Gregory }
389518fb721SGraeme Gregory 
390518fb721SGraeme Gregory static int tps65910_get_voltage_dcdc(struct regulator_dev *dev)
391518fb721SGraeme Gregory {
392518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
393518fb721SGraeme Gregory 	int id = rdev_get_id(dev), voltage = 0;
394518fb721SGraeme Gregory 	int opvsel = 0, srvsel = 0, mult = 0, sr = 0;
395518fb721SGraeme Gregory 
396518fb721SGraeme Gregory 	switch (id) {
397518fb721SGraeme Gregory 	case TPS65910_REG_VDD1:
398518fb721SGraeme Gregory 		opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP);
399518fb721SGraeme Gregory 		mult = tps65910_reg_read(pmic, TPS65910_VDD1);
400518fb721SGraeme Gregory 		mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
401518fb721SGraeme Gregory 		srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR);
402518fb721SGraeme Gregory 		sr = opvsel & VDD1_OP_CMD_MASK;
403518fb721SGraeme Gregory 		opvsel &= VDD1_OP_SEL_MASK;
404518fb721SGraeme Gregory 		srvsel &= VDD1_SR_SEL_MASK;
405518fb721SGraeme Gregory 		break;
406518fb721SGraeme Gregory 	case TPS65910_REG_VDD2:
407518fb721SGraeme Gregory 		opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP);
408518fb721SGraeme Gregory 		mult = tps65910_reg_read(pmic, TPS65910_VDD2);
409518fb721SGraeme Gregory 		mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
410518fb721SGraeme Gregory 		srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR);
411518fb721SGraeme Gregory 		sr = opvsel & VDD2_OP_CMD_MASK;
412518fb721SGraeme Gregory 		opvsel &= VDD2_OP_SEL_MASK;
413518fb721SGraeme Gregory 		srvsel &= VDD2_SR_SEL_MASK;
414518fb721SGraeme Gregory 		break;
415518fb721SGraeme Gregory 	}
416518fb721SGraeme Gregory 
417518fb721SGraeme Gregory 	/* multiplier 0 == 1 but 2,3 normal */
418518fb721SGraeme Gregory 	if (!mult)
419518fb721SGraeme Gregory 		mult=1;
420518fb721SGraeme Gregory 
421518fb721SGraeme Gregory 	if (sr) {
422518fb721SGraeme Gregory 		/* Valid range is 3-75 so normalise */
423518fb721SGraeme Gregory 		if (srvsel < 3) srvsel = 3;
424518fb721SGraeme Gregory 		if (srvsel > 75) srvsel = 75;
425518fb721SGraeme Gregory 		srvsel -= 3;
426518fb721SGraeme Gregory 
427518fb721SGraeme Gregory 		voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100;
428518fb721SGraeme Gregory 	} else {
429518fb721SGraeme Gregory 
430518fb721SGraeme Gregory 		/* Valid range is 3-75 so normalise */
431518fb721SGraeme Gregory 		if (opvsel < 3) opvsel = 3;
432518fb721SGraeme Gregory 		if (opvsel > 75) opvsel = 75;
433518fb721SGraeme Gregory 		opvsel -= 3;
434518fb721SGraeme Gregory 
435518fb721SGraeme Gregory 		voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100;
436518fb721SGraeme Gregory 	}
437518fb721SGraeme Gregory 
438518fb721SGraeme Gregory 	voltage *= mult;
439518fb721SGraeme Gregory 
440518fb721SGraeme Gregory 	return voltage;
441518fb721SGraeme Gregory }
442518fb721SGraeme Gregory 
443518fb721SGraeme Gregory static int tps65910_get_voltage(struct regulator_dev *dev)
444518fb721SGraeme Gregory {
445518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
446518fb721SGraeme Gregory 	int reg, value, id = rdev_get_id(dev), voltage = 0;
447518fb721SGraeme Gregory 
448518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
449518fb721SGraeme Gregory 	if (reg < 0)
450518fb721SGraeme Gregory 		return reg;
451518fb721SGraeme Gregory 
452518fb721SGraeme Gregory 	value = tps65910_reg_read(pmic, reg);
453518fb721SGraeme Gregory 	if (value < 0)
454518fb721SGraeme Gregory 		return value;
455518fb721SGraeme Gregory 
456518fb721SGraeme Gregory 	switch (id) {
457518fb721SGraeme Gregory 	case TPS65910_REG_VIO:
458518fb721SGraeme Gregory 	case TPS65910_REG_VDIG1:
459518fb721SGraeme Gregory 	case TPS65910_REG_VDIG2:
460518fb721SGraeme Gregory 	case TPS65910_REG_VPLL:
461518fb721SGraeme Gregory 	case TPS65910_REG_VDAC:
462518fb721SGraeme Gregory 	case TPS65910_REG_VAUX1:
463518fb721SGraeme Gregory 	case TPS65910_REG_VAUX2:
464518fb721SGraeme Gregory 	case TPS65910_REG_VAUX33:
465518fb721SGraeme Gregory 	case TPS65910_REG_VMMC:
466518fb721SGraeme Gregory 		value &= LDO_SEL_MASK;
467518fb721SGraeme Gregory 		value >>= LDO_SEL_SHIFT;
468518fb721SGraeme Gregory 		break;
469518fb721SGraeme Gregory 	default:
470518fb721SGraeme Gregory 		return -EINVAL;
471518fb721SGraeme Gregory 	}
472518fb721SGraeme Gregory 
473518fb721SGraeme Gregory 	voltage = pmic->info[id]->table[value] * 1000;
474518fb721SGraeme Gregory 
475518fb721SGraeme Gregory 	return voltage;
476518fb721SGraeme Gregory }
477518fb721SGraeme Gregory 
478518fb721SGraeme Gregory static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
479518fb721SGraeme Gregory {
480518fb721SGraeme Gregory 	return 5 * 1000 * 1000;
481518fb721SGraeme Gregory }
482518fb721SGraeme Gregory 
483518fb721SGraeme Gregory static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
484518fb721SGraeme Gregory 				unsigned selector)
485518fb721SGraeme Gregory {
486518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
487518fb721SGraeme Gregory 	int id = rdev_get_id(dev), vsel;
488518fb721SGraeme Gregory 	int dcdc_mult;
489518fb721SGraeme Gregory 
490518fb721SGraeme Gregory 	/* Split vsel into appropriate registers */
491518fb721SGraeme Gregory 	dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
492518fb721SGraeme Gregory 	if (dcdc_mult == 1) dcdc_mult--;
493518fb721SGraeme Gregory 
494518fb721SGraeme Gregory 	vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
495518fb721SGraeme Gregory 
496518fb721SGraeme Gregory 	if (id == TPS65910_REG_VDD1) {
497518fb721SGraeme Gregory 		tps65910_modify_bits(pmic, TPS65910_VDD1,
498518fb721SGraeme Gregory 				(dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
499518fb721SGraeme Gregory 						VDD1_VGAIN_SEL_MASK);
500518fb721SGraeme Gregory 		tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
501518fb721SGraeme Gregory 	} else {
502518fb721SGraeme Gregory 		tps65910_modify_bits(pmic, TPS65910_VDD2,
503518fb721SGraeme Gregory 				(dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
504518fb721SGraeme Gregory 						VDD1_VGAIN_SEL_MASK);
505518fb721SGraeme Gregory 		tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel);
506518fb721SGraeme Gregory 	}
507518fb721SGraeme Gregory 
508518fb721SGraeme Gregory 	return 0;
509518fb721SGraeme Gregory }
510518fb721SGraeme Gregory 
511518fb721SGraeme Gregory static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector)
512518fb721SGraeme Gregory {
513518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
514518fb721SGraeme Gregory 	int reg, id = rdev_get_id(dev);
515518fb721SGraeme Gregory 
516518fb721SGraeme Gregory 	reg = tps65910_get_ctrl_register(id);
517518fb721SGraeme Gregory 	if (reg < 0)
518518fb721SGraeme Gregory 		return reg;
519518fb721SGraeme Gregory 
520518fb721SGraeme Gregory 	switch (id) {
521518fb721SGraeme Gregory 	case TPS65910_REG_VIO:
522518fb721SGraeme Gregory 	case TPS65910_REG_VDIG1:
523518fb721SGraeme Gregory 	case TPS65910_REG_VDIG2:
524518fb721SGraeme Gregory 	case TPS65910_REG_VPLL:
525518fb721SGraeme Gregory 	case TPS65910_REG_VDAC:
526518fb721SGraeme Gregory 	case TPS65910_REG_VAUX1:
527518fb721SGraeme Gregory 	case TPS65910_REG_VAUX2:
528518fb721SGraeme Gregory 	case TPS65910_REG_VAUX33:
529518fb721SGraeme Gregory 	case TPS65910_REG_VMMC:
530518fb721SGraeme Gregory 		return tps65910_modify_bits(pmic, reg,
531518fb721SGraeme Gregory 				(selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
532518fb721SGraeme Gregory 	}
533518fb721SGraeme Gregory 
534518fb721SGraeme Gregory 	return -EINVAL;
535518fb721SGraeme Gregory }
536518fb721SGraeme Gregory 
537518fb721SGraeme Gregory static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
538518fb721SGraeme Gregory 					unsigned selector)
539518fb721SGraeme Gregory {
540518fb721SGraeme Gregory 	int mult, volt;
541518fb721SGraeme Gregory 
542518fb721SGraeme Gregory 	mult = (selector / VDD1_2_NUM_VOLTS) + 1;
543518fb721SGraeme Gregory 
544518fb721SGraeme Gregory 	volt = VDD1_2_MIN_VOLT + (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
545518fb721SGraeme Gregory 
546518fb721SGraeme Gregory 	return  volt * 100 * mult;
547518fb721SGraeme Gregory }
548518fb721SGraeme Gregory 
549518fb721SGraeme Gregory static int tps65910_list_voltage(struct regulator_dev *dev,
550518fb721SGraeme Gregory 					unsigned selector)
551518fb721SGraeme Gregory {
552518fb721SGraeme Gregory 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
553518fb721SGraeme Gregory 	int id = rdev_get_id(dev), voltage;
554518fb721SGraeme Gregory 
555518fb721SGraeme Gregory 	if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC)
556518fb721SGraeme Gregory 		return -EINVAL;
557518fb721SGraeme Gregory 
558518fb721SGraeme Gregory 	if (selector >= pmic->info[id]->table_len)
559518fb721SGraeme Gregory 		return -EINVAL;
560518fb721SGraeme Gregory 	else
561518fb721SGraeme Gregory 		voltage = pmic->info[id]->table[selector] * 1000;
562518fb721SGraeme Gregory 
563518fb721SGraeme Gregory 	return voltage;
564518fb721SGraeme Gregory }
565518fb721SGraeme Gregory 
566518fb721SGraeme Gregory /* Regulator ops (except VRTC) */
567518fb721SGraeme Gregory static struct regulator_ops tps65910_ops_dcdc = {
568518fb721SGraeme Gregory 	.is_enabled		= tps65910_is_enabled,
569518fb721SGraeme Gregory 	.enable			= tps65910_enable,
570518fb721SGraeme Gregory 	.disable		= tps65910_disable,
571518fb721SGraeme Gregory 	.set_mode		= tps65910_set_mode,
572518fb721SGraeme Gregory 	.get_mode		= tps65910_get_mode,
573518fb721SGraeme Gregory 	.get_voltage		= tps65910_get_voltage_dcdc,
574518fb721SGraeme Gregory 	.set_voltage_sel	= tps65910_set_voltage_dcdc,
575518fb721SGraeme Gregory 	.list_voltage		= tps65910_list_voltage_dcdc,
576518fb721SGraeme Gregory };
577518fb721SGraeme Gregory 
578518fb721SGraeme Gregory static struct regulator_ops tps65910_ops_vdd3 = {
579518fb721SGraeme Gregory 	.is_enabled		= tps65910_is_enabled,
580518fb721SGraeme Gregory 	.enable			= tps65910_enable,
581518fb721SGraeme Gregory 	.disable		= tps65910_disable,
582518fb721SGraeme Gregory 	.set_mode		= tps65910_set_mode,
583518fb721SGraeme Gregory 	.get_mode		= tps65910_get_mode,
584518fb721SGraeme Gregory 	.get_voltage		= tps65910_get_voltage_vdd3,
585518fb721SGraeme Gregory 	.list_voltage		= tps65910_list_voltage,
586518fb721SGraeme Gregory };
587518fb721SGraeme Gregory 
588518fb721SGraeme Gregory static struct regulator_ops tps65910_ops = {
589518fb721SGraeme Gregory 	.is_enabled		= tps65910_is_enabled,
590518fb721SGraeme Gregory 	.enable			= tps65910_enable,
591518fb721SGraeme Gregory 	.disable		= tps65910_disable,
592518fb721SGraeme Gregory 	.set_mode		= tps65910_set_mode,
593518fb721SGraeme Gregory 	.get_mode		= tps65910_get_mode,
594518fb721SGraeme Gregory 	.get_voltage		= tps65910_get_voltage,
595518fb721SGraeme Gregory 	.set_voltage_sel	= tps65910_set_voltage,
596518fb721SGraeme Gregory 	.list_voltage		= tps65910_list_voltage,
597518fb721SGraeme Gregory };
598518fb721SGraeme Gregory 
599518fb721SGraeme Gregory static __devinit int tps65910_probe(struct platform_device *pdev)
600518fb721SGraeme Gregory {
601518fb721SGraeme Gregory 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
602518fb721SGraeme Gregory 	struct tps_info *info = tps65910_regs;
603518fb721SGraeme Gregory 	struct regulator_init_data *reg_data;
604518fb721SGraeme Gregory 	struct regulator_dev *rdev;
605518fb721SGraeme Gregory 	struct tps65910_reg *pmic;
606518fb721SGraeme Gregory 	struct tps65910_board *pmic_plat_data;
607518fb721SGraeme Gregory 	int i, err;
608518fb721SGraeme Gregory 
609518fb721SGraeme Gregory 	pmic_plat_data = dev_get_platdata(tps65910->dev);
610518fb721SGraeme Gregory 	if (!pmic_plat_data)
611518fb721SGraeme Gregory 		return -EINVAL;
612518fb721SGraeme Gregory 
613518fb721SGraeme Gregory 	reg_data = pmic_plat_data->tps65910_pmic_init_data;
614518fb721SGraeme Gregory 
615518fb721SGraeme Gregory 	pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
616518fb721SGraeme Gregory 	if (!pmic)
617518fb721SGraeme Gregory 		return -ENOMEM;
618518fb721SGraeme Gregory 
619518fb721SGraeme Gregory 	mutex_init(&pmic->mutex);
620518fb721SGraeme Gregory 	pmic->mfd = tps65910;
621518fb721SGraeme Gregory 	platform_set_drvdata(pdev, pmic);
622518fb721SGraeme Gregory 
623518fb721SGraeme Gregory 	/* Give control of all register to control port */
624518fb721SGraeme Gregory 	tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL,
625518fb721SGraeme Gregory 				DEVCTRL_SR_CTL_I2C_SEL_MASK);
626518fb721SGraeme Gregory 
627518fb721SGraeme Gregory 	for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) {
628518fb721SGraeme Gregory 		/* Register the regulators */
629518fb721SGraeme Gregory 		pmic->info[i] = info;
630518fb721SGraeme Gregory 
631518fb721SGraeme Gregory 		pmic->desc[i].name = info->name;
63277fa44d0SAxel Lin 		pmic->desc[i].id = i;
633518fb721SGraeme Gregory 		pmic->desc[i].n_voltages = info->table_len;
634518fb721SGraeme Gregory 
635518fb721SGraeme Gregory 		if ((i == TPS65910_REG_VDD1) || (i == TPS65910_REG_VDD2))
636518fb721SGraeme Gregory 			pmic->desc[i].ops = &tps65910_ops_dcdc;
637518fb721SGraeme Gregory 		else if (i == TPS65910_REG_VDD3)
638518fb721SGraeme Gregory 			pmic->desc[i].ops = &tps65910_ops_vdd3;
639518fb721SGraeme Gregory 		else
640518fb721SGraeme Gregory 			pmic->desc[i].ops = &tps65910_ops;
641518fb721SGraeme Gregory 
642518fb721SGraeme Gregory 		pmic->desc[i].type = REGULATOR_VOLTAGE;
643518fb721SGraeme Gregory 		pmic->desc[i].owner = THIS_MODULE;
644518fb721SGraeme Gregory 
645518fb721SGraeme Gregory 		rdev = regulator_register(&pmic->desc[i],
646518fb721SGraeme Gregory 				tps65910->dev, reg_data, pmic);
647518fb721SGraeme Gregory 		if (IS_ERR(rdev)) {
648518fb721SGraeme Gregory 			dev_err(tps65910->dev,
649518fb721SGraeme Gregory 				"failed to register %s regulator\n",
650518fb721SGraeme Gregory 				pdev->name);
651518fb721SGraeme Gregory 			err = PTR_ERR(rdev);
652518fb721SGraeme Gregory 			goto err;
653518fb721SGraeme Gregory 		}
654518fb721SGraeme Gregory 
655518fb721SGraeme Gregory 		/* Save regulator for cleanup */
656518fb721SGraeme Gregory 		pmic->rdev[i] = rdev;
657518fb721SGraeme Gregory 	}
658518fb721SGraeme Gregory 	return 0;
659518fb721SGraeme Gregory 
660518fb721SGraeme Gregory err:
661518fb721SGraeme Gregory 	while (--i >= 0)
662518fb721SGraeme Gregory 		regulator_unregister(pmic->rdev[i]);
663518fb721SGraeme Gregory 
664518fb721SGraeme Gregory 	kfree(pmic);
665518fb721SGraeme Gregory 	return err;
666518fb721SGraeme Gregory }
667518fb721SGraeme Gregory 
668518fb721SGraeme Gregory static int __devexit tps65910_remove(struct platform_device *pdev)
669518fb721SGraeme Gregory {
670518fb721SGraeme Gregory 	struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev);
671518fb721SGraeme Gregory 	int i;
672518fb721SGraeme Gregory 
673518fb721SGraeme Gregory 	for (i = 0; i < TPS65910_NUM_REGULATOR; i++)
674518fb721SGraeme Gregory 		regulator_unregister(tps65910_reg->rdev[i]);
675518fb721SGraeme Gregory 
676518fb721SGraeme Gregory 	kfree(tps65910_reg);
677518fb721SGraeme Gregory 	return 0;
678518fb721SGraeme Gregory }
679518fb721SGraeme Gregory 
680518fb721SGraeme Gregory static struct platform_driver tps65910_driver = {
681518fb721SGraeme Gregory 	.driver = {
682518fb721SGraeme Gregory 		.name = "tps65910-pmic",
683518fb721SGraeme Gregory 		.owner = THIS_MODULE,
684518fb721SGraeme Gregory 	},
685518fb721SGraeme Gregory 	.probe = tps65910_probe,
686518fb721SGraeme Gregory 	.remove = __devexit_p(tps65910_remove),
687518fb721SGraeme Gregory };
688518fb721SGraeme Gregory 
689518fb721SGraeme Gregory static int __init tps65910_init(void)
690518fb721SGraeme Gregory {
691518fb721SGraeme Gregory 	return platform_driver_register(&tps65910_driver);
692518fb721SGraeme Gregory }
693518fb721SGraeme Gregory subsys_initcall(tps65910_init);
694518fb721SGraeme Gregory 
695518fb721SGraeme Gregory static void __exit tps65910_cleanup(void)
696518fb721SGraeme Gregory {
697518fb721SGraeme Gregory 	platform_driver_unregister(&tps65910_driver);
698518fb721SGraeme Gregory }
699518fb721SGraeme Gregory module_exit(tps65910_cleanup);
700518fb721SGraeme Gregory 
701518fb721SGraeme Gregory MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
702518fb721SGraeme Gregory MODULE_DESCRIPTION("TPS6507x voltage regulator driver");
703518fb721SGraeme Gregory MODULE_LICENSE("GPL v2");
704518fb721SGraeme Gregory MODULE_ALIAS("platform:tps65910-pmic");
705