2 * max8907c-regulator.c -- support regulators in max8907c
4 * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/slab.h>
14 #include <linux/err.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/driver.h>
17 #include <linux/regulator/machine.h>
18 #include <linux/mfd/max8907c.h>
19 #include <linux/regulator/max8907c-regulator.h>
21 #define MAX8907C_II2RR_VERSION_MASK 0xF0
22 #define MAX8907C_II2RR_VERSION_REV_A 0x00
23 #define MAX8907C_II2RR_VERSION_REV_B 0x10
24 #define MAX8907C_II2RR_VERSION_REV_C 0x30
26 #define MAX8907C_REGULATOR_CNT (ARRAY_SIZE(max8907c_regulators))
28 struct max8907c_regulator_info {
34 struct regulator_desc desc;
35 struct i2c_client *i2c;
38 #define REG_LDO(ids, base, min, max, step) \
46 .id = MAX8907C_##ids, \
47 .n_voltages = ((max) - (min)) / (step) + 1, \
48 .ops = &max8907c_ldo_ops, \
49 .type = REGULATOR_VOLTAGE, \
50 .owner = THIS_MODULE, \
54 #define REG_FIXED(ids, voltage) \
56 .min_uV = (voltage), \
57 .max_uV = (voltage), \
60 .id = MAX8907C_##ids, \
62 .ops = &max8907c_fixed_ops, \
63 .type = REGULATOR_VOLTAGE, \
64 .owner = THIS_MODULE, \
68 #define REG_OUT5V(ids, base, voltage) \
70 .min_uV = (voltage), \
71 .max_uV = (voltage), \
75 .id = MAX8907C_##ids, \
77 .ops = &max8907c_out5v_ops, \
78 .type = REGULATOR_VOLTAGE, \
79 .owner = THIS_MODULE, \
83 #define REG_BBAT(ids, base, min, max, step) \
91 .id = MAX8907C_##ids, \
92 .n_voltages = ((max) - (min)) / (step) + 1, \
93 .ops = &max8907c_bbat_ops, \
94 .type = REGULATOR_VOLTAGE, \
95 .owner = THIS_MODULE, \
99 #define REG_WLED(ids, base, voltage) \
101 .min_uV = (voltage), \
102 .max_uV = (voltage), \
103 .reg_base = (base), \
106 .id = MAX8907C_##ids, \
108 .ops = &max8907c_wled_ops, \
109 .type = REGULATOR_CURRENT, \
110 .owner = THIS_MODULE, \
114 #define LDO_750_50(id, base) REG_LDO(id, (base), 750000, 3900000, 50000)
115 #define LDO_650_25(id, base) REG_LDO(id, (base), 650000, 2225000, 25000)
117 static int max8907c_regulator_list_voltage(struct regulator_dev *dev,
119 static int max8907c_regulator_ldo_set_voltage(struct regulator_dev *dev,
120 int min_uV, int max_uV);
121 static int max8907c_regulator_bbat_set_voltage(struct regulator_dev *dev,
122 int min_uV, int max_uV);
123 static int max8907c_regulator_ldo_get_voltage(struct regulator_dev *dev);
124 static int max8907c_regulator_fixed_get_voltage(struct regulator_dev *dev);
125 static int max8907c_regulator_bbat_get_voltage(struct regulator_dev *dev);
126 static int max8907c_regulator_wled_set_current_limit(struct regulator_dev *dev,
127 int min_uA, int max_uA);
128 static int max8907c_regulator_wled_get_current_limit(struct regulator_dev *dev);
129 static int max8907c_regulator_ldo_enable(struct regulator_dev *dev);
130 static int max8907c_regulator_out5v_enable(struct regulator_dev *dev);
131 static int max8907c_regulator_ldo_disable(struct regulator_dev *dev);
132 static int max8907c_regulator_out5v_disable(struct regulator_dev *dev);
133 static int max8907c_regulator_ldo_is_enabled(struct regulator_dev *dev);
134 static int max8907c_regulator_ldo_enable_time(struct regulator_dev *dev);
135 static int max8907c_regulator_out5v_is_enabled(struct regulator_dev *dev);
137 static struct regulator_ops max8907c_ldo_ops = {
138 .list_voltage = max8907c_regulator_list_voltage,
139 .set_voltage = max8907c_regulator_ldo_set_voltage,
140 .get_voltage = max8907c_regulator_ldo_get_voltage,
141 .enable = max8907c_regulator_ldo_enable,
142 .disable = max8907c_regulator_ldo_disable,
143 .is_enabled = max8907c_regulator_ldo_is_enabled,
144 .enable_time = max8907c_regulator_ldo_enable_time,
147 static struct regulator_ops max8907c_fixed_ops = {
148 .list_voltage = max8907c_regulator_list_voltage,
149 .get_voltage = max8907c_regulator_fixed_get_voltage,
152 static struct regulator_ops max8907c_out5v_ops = {
153 .list_voltage = max8907c_regulator_list_voltage,
154 .get_voltage = max8907c_regulator_fixed_get_voltage,
155 .enable = max8907c_regulator_out5v_enable,
156 .disable = max8907c_regulator_out5v_disable,
157 .is_enabled = max8907c_regulator_out5v_is_enabled,
160 static struct regulator_ops max8907c_bbat_ops = {
161 .list_voltage = max8907c_regulator_list_voltage,
162 .set_voltage = max8907c_regulator_bbat_set_voltage,
163 .get_voltage = max8907c_regulator_bbat_get_voltage,
166 static struct regulator_ops max8907c_wled_ops = {
167 .list_voltage = max8907c_regulator_list_voltage,
168 .set_current_limit = max8907c_regulator_wled_set_current_limit,
169 .get_current_limit = max8907c_regulator_wled_get_current_limit,
170 .get_voltage = max8907c_regulator_fixed_get_voltage,
173 static struct max8907c_regulator_info max8907c_regulators[] = {
174 REG_LDO(SD1, MAX8907C_REG_SDCTL1, 650000, 2225000, 25000),
175 REG_LDO(SD2, MAX8907C_REG_SDCTL2, 637500, 1425000, 12500),
176 REG_LDO(SD3, MAX8907C_REG_SDCTL3, 750000, 3900000, 50000),
177 LDO_750_50(LDO1, MAX8907C_REG_LDOCTL1),
178 LDO_650_25(LDO2, MAX8907C_REG_LDOCTL2),
179 LDO_650_25(LDO3, MAX8907C_REG_LDOCTL3),
180 LDO_750_50(LDO4, MAX8907C_REG_LDOCTL4),
181 LDO_750_50(LDO5, MAX8907C_REG_LDOCTL5),
182 LDO_750_50(LDO6, MAX8907C_REG_LDOCTL6),
183 LDO_750_50(LDO7, MAX8907C_REG_LDOCTL7),
184 LDO_750_50(LDO8, MAX8907C_REG_LDOCTL8),
185 LDO_750_50(LDO9, MAX8907C_REG_LDOCTL9),
186 LDO_750_50(LDO10, MAX8907C_REG_LDOCTL10),
187 LDO_750_50(LDO11, MAX8907C_REG_LDOCTL11),
188 LDO_750_50(LDO12, MAX8907C_REG_LDOCTL12),
189 LDO_750_50(LDO13, MAX8907C_REG_LDOCTL13),
190 LDO_750_50(LDO14, MAX8907C_REG_LDOCTL14),
191 LDO_750_50(LDO15, MAX8907C_REG_LDOCTL15),
192 LDO_750_50(LDO16, MAX8907C_REG_LDOCTL16),
193 LDO_650_25(LDO17, MAX8907C_REG_LDOCTL17),
194 LDO_650_25(LDO18, MAX8907C_REG_LDOCTL18),
195 LDO_750_50(LDO19, MAX8907C_REG_LDOCTL19),
196 LDO_750_50(LDO20, MAX8907C_REG_LDOCTL20),
197 REG_OUT5V(OUT5V, MAX8907C_REG_OUT5VEN, 5000000),
198 REG_OUT5V(OUT33V, MAX8907C_REG_OUT33VEN, 3300000),
199 REG_BBAT(BBAT, MAX8907C_REG_BBAT_CNFG, 2400000, 3000000, 200000),
200 REG_FIXED(SDBY, 1200000),
201 REG_FIXED(VRTC, 3300000),
202 REG_WLED(WLED, MAX8907C_REG_ILED_CNTL, 0),
205 static int max8907c_regulator_list_voltage(struct regulator_dev *rdev,
208 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
210 return info->min_uV + info->step_uV * index;
213 static int max8907c_regulator_ldo_set_voltage(struct regulator_dev *rdev,
214 int min_uV, int max_uV)
216 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
219 if (min_uV < info->min_uV || max_uV > info->max_uV)
222 val = (min_uV - info->min_uV) / info->step_uV;
224 return max8907c_reg_write(info->i2c, info->reg_base + MAX8907C_VOUT, val);
227 static int max8907c_regulator_bbat_set_voltage(struct regulator_dev *rdev,
228 int min_uV, int max_uV)
230 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
233 if (min_uV < info->min_uV || max_uV > info->max_uV)
236 val = (min_uV - info->min_uV) / info->step_uV;
238 return max8907c_set_bits(info->i2c, info->reg_base, MAX8907C_MASK_VBBATTCV,
242 static int max8907c_regulator_ldo_get_voltage(struct regulator_dev *rdev)
244 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
247 val = max8907c_reg_read(info->i2c, info->reg_base + MAX8907C_VOUT);
248 return val * info->step_uV + info->min_uV;
251 static int max8907c_regulator_fixed_get_voltage(struct regulator_dev *rdev)
253 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
258 static int max8907c_regulator_bbat_get_voltage(struct regulator_dev *rdev)
260 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
264 max8907c_reg_read(info->i2c, info->reg_base) & MAX8907C_MASK_VBBATTCV;
265 return val * info->step_uV + info->min_uV;
268 static int max8907c_regulator_wled_set_current_limit(struct regulator_dev *rdev,
269 int min_uA, int max_uA)
271 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
276 return max8907c_reg_write(info->i2c, info->reg_base, min_uA / 100);
279 static int max8907c_regulator_wled_get_current_limit(struct regulator_dev *rdev)
281 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
284 val = max8907c_reg_read(info->i2c, info->reg_base);
288 static int max8907c_regulator_ldo_enable(struct regulator_dev *rdev)
290 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
292 return max8907c_set_bits(info->i2c, info->reg_base + MAX8907C_CTL,
293 MAX8907C_MASK_LDO_EN | MAX8907C_MASK_LDO_SEQ,
294 MAX8907C_MASK_LDO_EN | MAX8907C_MASK_LDO_SEQ);
297 static int max8907c_regulator_out5v_enable(struct regulator_dev *rdev)
299 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
301 return max8907c_set_bits(info->i2c, info->reg_base,
302 MAX8907C_MASK_OUT5V_VINEN |
303 MAX8907C_MASK_OUT5V_ENSRC |
304 MAX8907C_MASK_OUT5V_EN,
305 MAX8907C_MASK_OUT5V_ENSRC |
306 MAX8907C_MASK_OUT5V_EN);
309 static int max8907c_regulator_ldo_disable(struct regulator_dev *rdev)
311 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
313 return max8907c_set_bits(info->i2c, info->reg_base + MAX8907C_CTL,
314 MAX8907C_MASK_LDO_EN | MAX8907C_MASK_LDO_SEQ,
315 MAX8907C_MASK_LDO_SEQ);
318 static int max8907c_regulator_out5v_disable(struct regulator_dev *rdev)
320 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
322 return max8907c_set_bits(info->i2c, info->reg_base,
323 MAX8907C_MASK_OUT5V_VINEN |
324 MAX8907C_MASK_OUT5V_ENSRC |
325 MAX8907C_MASK_OUT5V_EN,
326 MAX8907C_MASK_OUT5V_ENSRC);
329 static int max8907c_regulator_ldo_is_enabled(struct regulator_dev *rdev)
331 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
334 val = max8907c_reg_read(info->i2c, info->reg_base + MAX8907C_CTL);
338 return (val & MAX8907C_MASK_LDO_EN) || !(val & MAX8907C_MASK_LDO_SEQ);
341 static int max8907c_regulator_ldo_enable_time(struct regulator_dev *rdev)
343 struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
345 return info->enable_time_us;
348 static int max8907c_regulator_out5v_is_enabled(struct regulator_dev *rdev)
350 const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev);
353 val = max8907c_reg_read(info->i2c, info->reg_base);
358 (MAX8907C_MASK_OUT5V_VINEN | MAX8907C_MASK_OUT5V_ENSRC |
359 MAX8907C_MASK_OUT5V_EN))
360 == MAX8907C_MASK_OUT5V_ENSRC)
366 static int max8907c_regulator_probe(struct platform_device *pdev)
368 struct max8907c *max8907c = dev_get_drvdata(pdev->dev.parent);
369 struct max8907c_regulator_info *info;
370 struct regulator_dev *rdev;
371 struct regulator_init_data *p = pdev->dev.platform_data;
372 struct max8907c_chip_regulator_data *chip_data = p->driver_data;;
375 /* Backwards compatibility with max8907b, SD1 uses different voltages */
376 version = max8907c_reg_read(max8907c->i2c_power, MAX8907C_REG_II2RR);
377 if ((version & MAX8907C_II2RR_VERSION_MASK) == MAX8907C_II2RR_VERSION_REV_B) {
378 max8907c_regulators[MAX8907C_SD1].min_uV = 637500;
379 max8907c_regulators[MAX8907C_SD1].max_uV = 1425000;
380 max8907c_regulators[MAX8907C_SD1].step_uV = 12500;
383 info = &max8907c_regulators[pdev->id];
384 info->i2c = max8907c->i2c_power;
386 if (chip_data != NULL)
387 info->enable_time_us = chip_data->enable_time_us;
389 rdev = regulator_register(&info->desc,
390 &pdev->dev, pdev->dev.platform_data, info);
392 dev_err(&pdev->dev, "Cannot register regulator \"%s\", %ld\n",
393 info->desc.name, PTR_ERR(rdev));
397 platform_set_drvdata(pdev, rdev);
401 return PTR_ERR(rdev);
404 static int max8907c_regulator_remove(struct platform_device *pdev)
406 struct regulator_dev *rdev = platform_get_drvdata(pdev);
408 regulator_unregister(rdev);
412 static struct platform_driver max8907c_regulator_driver = {
414 .name = "max8907c-regulator",
415 .owner = THIS_MODULE,
417 .probe = max8907c_regulator_probe,
418 .remove = __devexit_p(max8907c_regulator_remove),
421 static int __init max8907c_regulator_init(void)
423 return platform_driver_register(&max8907c_regulator_driver);
426 subsys_initcall(max8907c_regulator_init);
428 static void __exit max8907c_reg_exit(void)
430 platform_driver_unregister(&max8907c_regulator_driver);
433 module_exit(max8907c_reg_exit);
435 MODULE_DESCRIPTION("MAX8907C regulator driver");
436 MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
437 MODULE_LICENSE("GPL");