blob: 37732f7c798d3c5258451fa014d9deccb8c3e8d3 [file] [log] [blame]
Laxman Dewangan6ffc3272012-04-04 12:44:00 +05301/*
2 * Regulator driver for RICOH RC5T583 power management chip.
3 *
4 * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
5 * Author: Laxman dewangan <ldewangan@nvidia.com>
6 *
7 * based on code
8 * Copyright (C) 2011 RICOH COMPANY,LTD
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2, as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include <linux/module.h>
26#include <linux/delay.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <linux/err.h>
30#include <linux/platform_device.h>
31#include <linux/regulator/driver.h>
32#include <linux/regulator/machine.h>
33#include <linux/gpio.h>
34#include <linux/mfd/rc5t583.h>
35
36struct rc5t583_regulator_info {
37 int deepsleep_id;
38
39 /* Regulator register address.*/
40 uint8_t reg_en_reg;
41 uint8_t en_bit;
42 uint8_t reg_disc_reg;
43 uint8_t disc_bit;
44 uint8_t vout_reg;
45 uint8_t vout_mask;
46 uint8_t deepsleep_reg;
47
48 /* Chip constraints on regulator behavior */
49 int min_uV;
50 int max_uV;
51 int step_uV;
52 int nsteps;
53
54 /* Regulator specific turn-on delay and voltage settling time*/
55 int enable_uv_per_us;
56 int change_uv_per_us;
57
58 /* Used by regulator core */
59 struct regulator_desc desc;
60};
61
62struct rc5t583_regulator {
63 struct rc5t583_regulator_info *reg_info;
64
65 /* Devices */
66 struct device *dev;
67 struct rc5t583 *mfd;
68 struct regulator_dev *rdev;
69};
70
71static int rc5t583_reg_is_enabled(struct regulator_dev *rdev)
72{
73 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
74 struct rc5t583_regulator_info *ri = reg->reg_info;
75 uint8_t control;
76 int ret;
77
78 ret = rc5t583_read(reg->mfd->dev, ri->reg_en_reg, &control);
79 if (ret < 0) {
80 dev_err(&rdev->dev,
81 "Error in reading the control register 0x%02x\n",
82 ri->reg_en_reg);
83 return ret;
84 }
85 return !!(control & BIT(ri->en_bit));
86}
87
88static int rc5t583_reg_enable(struct regulator_dev *rdev)
89{
90 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
91 struct rc5t583_regulator_info *ri = reg->reg_info;
92 int ret;
93
94 ret = rc5t583_set_bits(reg->mfd->dev, ri->reg_en_reg,
95 (1 << ri->en_bit));
96 if (ret < 0) {
97 dev_err(&rdev->dev,
98 "Error in setting bit of STATE register 0x%02x\n",
99 ri->reg_en_reg);
100 return ret;
101 }
102 return ret;
103}
104
105static int rc5t583_reg_disable(struct regulator_dev *rdev)
106{
107 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
108 struct rc5t583_regulator_info *ri = reg->reg_info;
109 int ret;
110
111 ret = rc5t583_clear_bits(reg->mfd->dev, ri->reg_en_reg,
112 (1 << ri->en_bit));
113 if (ret < 0)
114 dev_err(&rdev->dev,
115 "Error in clearing bit of STATE register 0x%02x\n",
116 ri->reg_en_reg);
117
118 return ret;
119}
120
121static int rc5t583_list_voltage(struct regulator_dev *rdev, unsigned selector)
122{
123 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
124 struct rc5t583_regulator_info *ri = reg->reg_info;
125 return ri->min_uV + (ri->step_uV * selector);
126}
127
128static int rc5t583_set_voltage_sel(struct regulator_dev *rdev,
129 unsigned int selector)
130{
131 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
132 struct rc5t583_regulator_info *ri = reg->reg_info;
133 int ret;
134 if (selector > ri->nsteps) {
135 dev_err(&rdev->dev, "Invalid selector 0x%02x\n", selector);
136 return -EINVAL;
137 }
138
139 ret = rc5t583_update(reg->mfd->dev, ri->vout_reg,
140 selector, ri->vout_mask);
141 if (ret < 0)
142 dev_err(&rdev->dev,
143 "Error in update voltage register 0x%02x\n", ri->vout_reg);
144 return ret;
145}
146
147static int rc5t583_get_voltage_sel(struct regulator_dev *rdev)
148{
149 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
150 struct rc5t583_regulator_info *ri = reg->reg_info;
151 uint8_t vsel;
152 int ret;
153 ret = rc5t583_read(reg->mfd->dev, ri->vout_reg, &vsel);
154 if (ret < 0) {
155 dev_err(&rdev->dev,
156 "Error in reading voltage register 0x%02x\n", ri->vout_reg);
157 return ret;
158 }
159 return vsel & ri->vout_mask;
160}
161
162static int rc5t583_regulator_enable_time(struct regulator_dev *rdev)
163{
164 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
165 int vsel = rc5t583_get_voltage_sel(rdev);
166 int curr_uV = rc5t583_list_voltage(rdev, vsel);
167 return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us);
168}
169
170static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev,
171 unsigned int old_selector, unsigned int new_selector)
172{
173 struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
174 int old_uV, new_uV;
175 old_uV = rc5t583_list_voltage(rdev, old_selector);
176
177 if (old_uV < 0)
178 return old_uV;
179
180 new_uV = rc5t583_list_voltage(rdev, new_selector);
181 if (new_uV < 0)
182 return new_uV;
183
184 return DIV_ROUND_UP(abs(old_uV - new_uV),
185 reg->reg_info->change_uv_per_us);
186}
187
188
189static struct regulator_ops rc5t583_ops = {
190 .is_enabled = rc5t583_reg_is_enabled,
191 .enable = rc5t583_reg_enable,
192 .disable = rc5t583_reg_disable,
193 .enable_time = rc5t583_regulator_enable_time,
194 .get_voltage_sel = rc5t583_get_voltage_sel,
195 .set_voltage_sel = rc5t583_set_voltage_sel,
196 .list_voltage = rc5t583_list_voltage,
197 .set_voltage_time_sel = rc5t583_set_voltage_time_sel,
198};
199
200#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \
201 _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _nsteps, \
202 _enable_mv) \
203{ \
204 .reg_en_reg = RC5T583_REG_##_en_reg, \
205 .en_bit = _en_bit, \
206 .reg_disc_reg = RC5T583_REG_##_disc_reg, \
207 .disc_bit = _disc_bit, \
208 .vout_reg = RC5T583_REG_##_vout_reg, \
209 .vout_mask = _vout_mask, \
210 .deepsleep_reg = RC5T583_REG_##_ds_reg, \
211 .min_uV = _min_mv * 1000, \
212 .max_uV = _max_mv * 1000, \
213 .step_uV = _step_uV, \
214 .nsteps = _nsteps, \
215 .enable_uv_per_us = _enable_mv * 1000, \
216 .change_uv_per_us = 40 * 1000, \
217 .deepsleep_id = RC5T583_DS_##_id, \
218 .desc = { \
219 .name = "rc5t583-regulator-"#_id, \
220 .id = RC5T583_REGULATOR_##_id, \
221 .n_voltages = _nsteps, \
222 .ops = &rc5t583_ops, \
223 .type = REGULATOR_VOLTAGE, \
224 .owner = THIS_MODULE, \
225 }, \
226}
227
228static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
229 RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, DC0DAC, 0x7F, DC0DAC_DS,
230 700, 1500, 12500, 0x41, 4),
231 RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, DC1DAC, 0x7F, DC1DAC_DS,
232 700, 1500, 12500, 0x41, 14),
233 RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, DC2DAC, 0x7F, DC2DAC_DS,
234 900, 2400, 12500, 0x79, 14),
235 RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, DC3DAC, 0x7F, DC3DAC_DS,
236 900, 2400, 12500, 0x79, 14),
237 RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, LDO0DAC, 0x7F, LDO0DAC_DS,
238 900, 3400, 25000, 0x65, 160),
239 RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, LDO1DAC, 0x7F, LDO1DAC_DS,
240 900, 3400, 25000, 0x65, 160),
241 RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, LDO2DAC, 0x7F, LDO2DAC_DS,
242 900, 3400, 25000, 0x65, 160),
243 RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, LDO3DAC, 0x7F, LDO3DAC_DS,
244 900, 3400, 25000, 0x65, 160),
245 RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, LDO4DAC, 0x3F, LDO4DAC_DS,
246 750, 1500, 12500, 0x3D, 133),
247 RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, LDO5DAC, 0x7F, LDO5DAC_DS,
248 900, 3400, 25000, 0x65, 267),
249 RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, LDO6DAC, 0x7F, LDO6DAC_DS,
250 900, 3400, 25000, 0x65, 133),
251 RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, LDO7DAC, 0x7F, LDO7DAC_DS,
252 900, 3400, 25000, 0x65, 233),
253 RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, LDO8DAC, 0x7F, LDO8DAC_DS,
254 900, 3400, 25000, 0x65, 233),
255 RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, LDO9DAC, 0x7F, LDO9DAC_DS,
256 900, 3400, 25000, 0x65, 133),
257};
258
259static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
260{
261 struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
262 struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
263 struct regulator_init_data *reg_data;
264 struct rc5t583_regulator *reg = NULL;
265 struct rc5t583_regulator *regs;
266 struct regulator_dev *rdev;
267 struct rc5t583_regulator_info *ri;
268 int ret;
269 int id;
270
271 if (!pdata) {
272 dev_err(&pdev->dev, "No platform data, exiting...\n");
273 return -ENODEV;
274 }
275
276 regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
277 sizeof(struct rc5t583_regulator), GFP_KERNEL);
278 if (!regs) {
279 dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
280 return -ENOMEM;
281 }
282
283
284 for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) {
285 reg_data = pdata->reg_init_data[id];
286
287 /* No need to register if there is no regulator data */
288 if (!reg_data)
289 continue;
290
291 reg = &regs[id];
292 ri = &rc5t583_reg_info[id];
293 reg->reg_info = ri;
294 reg->mfd = rc5t583;
295 reg->dev = &pdev->dev;
296
297 if (ri->deepsleep_id == RC5T583_DS_NONE)
298 goto skip_ext_pwr_config;
299
300 ret = rc5t583_ext_power_req_config(rc5t583->dev,
301 ri->deepsleep_id,
302 pdata->regulator_ext_pwr_control[id],
303 pdata->regulator_deepsleep_slot[id]);
304 /*
305 * Configuring external control is not a major issue,
306 * just give warning.
307 */
308 if (ret < 0)
309 dev_warn(&pdev->dev,
310 "Failed to configure ext control %d\n", id);
311
312skip_ext_pwr_config:
313 rdev = regulator_register(&ri->desc, &pdev->dev,
314 reg_data, reg, NULL);
315 if (IS_ERR_OR_NULL(rdev)) {
316 dev_err(&pdev->dev, "Failed to register regulator %s\n",
317 ri->desc.name);
318 ret = PTR_ERR(rdev);
319 goto clean_exit;
320 }
321 reg->rdev = rdev;
322 }
323 platform_set_drvdata(pdev, regs);
324 return 0;
325
326clean_exit:
327 while (--id > 0)
328 regulator_unregister(regs[id].rdev);
329
330 return ret;
331}
332
333static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
334{
335 struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
336 int id;
337
338 for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
339 regulator_unregister(regs[id].rdev);
340 return 0;
341}
342
343static struct platform_driver rc5t583_regulator_driver = {
344 .driver = {
345 .name = "rc5t583-regulator",
346 .owner = THIS_MODULE,
347 },
348 .probe = rc5t583_regulator_probe,
349 .remove = __devexit_p(rc5t583_regulator_remove),
350};
351
352static int __init rc5t583_regulator_init(void)
353{
354 return platform_driver_register(&rc5t583_regulator_driver);
355}
356subsys_initcall(rc5t583_regulator_init);
357
358static void __exit rc5t583_regulator_exit(void)
359{
360 platform_driver_unregister(&rc5t583_regulator_driver);
361}
362module_exit(rc5t583_regulator_exit);
363
364MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
365MODULE_DESCRIPTION("RC5T583 regulator driver");
366MODULE_ALIAS("platform:rc5t583-regulator");
367MODULE_LICENSE("GPL V2");