Blame view
drivers/regulator/max8925-regulator.c
7.87 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
08ff6f2a9 regulator: Add ma... |
2 3 4 5 6 |
/* * Regulators driver for Maxim max8925 * * Copyright (C) 2009 Marvell International Ltd. * Haojian Zhuang <haojian.zhuang@marvell.com> |
08ff6f2a9 regulator: Add ma... |
7 8 |
*/ #include <linux/kernel.h> |
65602c32e regulator: Add mo... |
9 |
#include <linux/module.h> |
08ff6f2a9 regulator: Add ma... |
10 11 12 13 14 15 16 |
#include <linux/init.h> #include <linux/err.h> #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/mfd/max8925.h> |
45b6f8e8f regulator: max892... |
17 18 |
#include <linux/of.h> #include <linux/regulator/of_regulator.h> |
08ff6f2a9 regulator: Add ma... |
19 20 21 22 23 24 |
#define SD1_DVM_VMIN 850000 #define SD1_DVM_VMAX 1000000 #define SD1_DVM_STEP 50000 #define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */ #define SD1_DVM_EN 6 /* SDV1 bit 6 */ |
65364e9ab regulator: max892... |
25 26 27 28 29 30 31 |
/* bit definitions in LDO control registers */ #define LDO_SEQ_I2C 0x7 /* Power U/D by i2c */ #define LDO_SEQ_MASK 0x7 /* Power U/D sequence mask */ #define LDO_SEQ_SHIFT 2 /* Power U/D sequence offset */ #define LDO_I2C_EN 0x1 /* Enable by i2c */ #define LDO_I2C_EN_MASK 0x1 /* Enable mask by i2c */ #define LDO_I2C_EN_SHIFT 0 /* Enable offset by i2c */ |
db13c0400 regulator: Enable... |
32 |
|
08ff6f2a9 regulator: Add ma... |
33 34 |
struct max8925_regulator_info { struct regulator_desc desc; |
08ff6f2a9 regulator: Add ma... |
35 |
struct i2c_client *i2c; |
08ff6f2a9 regulator: Add ma... |
36 |
|
08ff6f2a9 regulator: Add ma... |
37 |
int vol_reg; |
08ff6f2a9 regulator: Add ma... |
38 39 |
int enable_reg; }; |
cd8318cb9 regulator: max892... |
40 41 |
static int max8925_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) |
08ff6f2a9 regulator: Add ma... |
42 43 |
{ struct max8925_regulator_info *info = rdev_get_drvdata(rdev); |
cd8318cb9 regulator: max892... |
44 |
unsigned char mask = rdev->desc->n_voltages - 1; |
08ff6f2a9 regulator: Add ma... |
45 |
|
cd8318cb9 regulator: max892... |
46 |
return max8925_set_bits(info->i2c, info->vol_reg, mask, selector); |
08ff6f2a9 regulator: Add ma... |
47 |
} |
3c8983b9a regulator: max892... |
48 |
static int max8925_get_voltage_sel(struct regulator_dev *rdev) |
08ff6f2a9 regulator: Add ma... |
49 50 51 52 53 54 55 56 |
{ struct max8925_regulator_info *info = rdev_get_drvdata(rdev); unsigned char data, mask; int ret; ret = max8925_reg_read(info->i2c, info->vol_reg); if (ret < 0) return ret; |
7f52ba779 regulator: Add mi... |
57 58 |
mask = rdev->desc->n_voltages - 1; data = ret & mask; |
08ff6f2a9 regulator: Add ma... |
59 |
|
3c8983b9a regulator: max892... |
60 |
return data; |
08ff6f2a9 regulator: Add ma... |
61 62 63 64 65 66 67 |
} static int max8925_enable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, |
65364e9ab regulator: max892... |
68 69 70 71 |
LDO_SEQ_MASK << LDO_SEQ_SHIFT | LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT, LDO_SEQ_I2C << LDO_SEQ_SHIFT | LDO_I2C_EN << LDO_I2C_EN_SHIFT); |
08ff6f2a9 regulator: Add ma... |
72 73 74 75 76 77 78 |
} static int max8925_disable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, |
65364e9ab regulator: max892... |
79 80 81 |
LDO_SEQ_MASK << LDO_SEQ_SHIFT | LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT, LDO_SEQ_I2C << LDO_SEQ_SHIFT); |
08ff6f2a9 regulator: Add ma... |
82 83 84 85 86 |
} static int max8925_is_enabled(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); |
65364e9ab regulator: max892... |
87 |
int ldo_seq, ret; |
08ff6f2a9 regulator: Add ma... |
88 |
|
4b99fef02 regulator: fix en... |
89 |
ret = max8925_reg_read(info->i2c, info->enable_reg); |
08ff6f2a9 regulator: Add ma... |
90 91 |
if (ret < 0) return ret; |
65364e9ab regulator: max892... |
92 93 94 95 96 |
ldo_seq = (ret >> LDO_SEQ_SHIFT) & LDO_SEQ_MASK; if (ldo_seq != LDO_SEQ_I2C) return 1; else return ret & (LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT); |
08ff6f2a9 regulator: Add ma... |
97 98 99 100 101 102 103 104 105 |
} static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); unsigned char data, mask; if (uV < SD1_DVM_VMIN || uV > SD1_DVM_VMAX) return -EINVAL; |
5db6d09a2 regulator: max892... |
106 |
data = DIV_ROUND_UP(uV - SD1_DVM_VMIN, SD1_DVM_STEP); |
08ff6f2a9 regulator: Add ma... |
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
data <<= SD1_DVM_SHIFT; mask = 3 << SD1_DVM_SHIFT; return max8925_set_bits(info->i2c, info->enable_reg, mask, data); } static int max8925_set_dvm_enable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN, 1 << SD1_DVM_EN); } static int max8925_set_dvm_disable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN, 0); } |
85214c9a0 regulator: max892... |
127 |
static const struct regulator_ops max8925_regulator_sdv_ops = { |
cd8318cb9 regulator: max892... |
128 |
.map_voltage = regulator_map_voltage_linear, |
4093e739f regulator: max892... |
129 |
.list_voltage = regulator_list_voltage_linear, |
cd8318cb9 regulator: max892... |
130 |
.set_voltage_sel = max8925_set_voltage_sel, |
3c8983b9a regulator: max892... |
131 |
.get_voltage_sel = max8925_get_voltage_sel, |
08ff6f2a9 regulator: Add ma... |
132 133 134 135 136 137 138 |
.enable = max8925_enable, .disable = max8925_disable, .is_enabled = max8925_is_enabled, .set_suspend_voltage = max8925_set_dvm_voltage, .set_suspend_enable = max8925_set_dvm_enable, .set_suspend_disable = max8925_set_dvm_disable, }; |
85214c9a0 regulator: max892... |
139 |
static const struct regulator_ops max8925_regulator_ldo_ops = { |
cd8318cb9 regulator: max892... |
140 |
.map_voltage = regulator_map_voltage_linear, |
4093e739f regulator: max892... |
141 |
.list_voltage = regulator_list_voltage_linear, |
cd8318cb9 regulator: max892... |
142 |
.set_voltage_sel = max8925_set_voltage_sel, |
3c8983b9a regulator: max892... |
143 |
.get_voltage_sel = max8925_get_voltage_sel, |
08ff6f2a9 regulator: Add ma... |
144 145 146 147 148 149 150 151 152 |
.enable = max8925_enable, .disable = max8925_disable, .is_enabled = max8925_is_enabled, }; #define MAX8925_SDV(_id, min, max, step) \ { \ .desc = { \ .name = "SDV" #_id, \ |
6185de50e regulator: max892... |
153 154 |
.of_match = of_match_ptr("SDV" #_id), \ .regulators_node = of_match_ptr("regulators"), \ |
08ff6f2a9 regulator: Add ma... |
155 156 157 158 |
.ops = &max8925_regulator_sdv_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MAX8925_ID_SD##_id, \ .owner = THIS_MODULE, \ |
7f52ba779 regulator: Add mi... |
159 |
.n_voltages = 64, \ |
4093e739f regulator: max892... |
160 161 |
.min_uV = min * 1000, \ .uV_step = step * 1000, \ |
08ff6f2a9 regulator: Add ma... |
162 |
}, \ |
08ff6f2a9 regulator: Add ma... |
163 |
.vol_reg = MAX8925_SDV##_id, \ |
08ff6f2a9 regulator: Add ma... |
164 |
.enable_reg = MAX8925_SDCTL##_id, \ |
08ff6f2a9 regulator: Add ma... |
165 166 167 168 169 170 |
} #define MAX8925_LDO(_id, min, max, step) \ { \ .desc = { \ .name = "LDO" #_id, \ |
6185de50e regulator: max892... |
171 172 |
.of_match = of_match_ptr("LDO" #_id), \ .regulators_node = of_match_ptr("regulators"), \ |
08ff6f2a9 regulator: Add ma... |
173 174 175 176 |
.ops = &max8925_regulator_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MAX8925_ID_LDO##_id, \ .owner = THIS_MODULE, \ |
7f52ba779 regulator: Add mi... |
177 |
.n_voltages = 64, \ |
4093e739f regulator: max892... |
178 179 |
.min_uV = min * 1000, \ .uV_step = step * 1000, \ |
08ff6f2a9 regulator: Add ma... |
180 |
}, \ |
08ff6f2a9 regulator: Add ma... |
181 |
.vol_reg = MAX8925_LDOVOUT##_id, \ |
08ff6f2a9 regulator: Add ma... |
182 |
.enable_reg = MAX8925_LDOCTL##_id, \ |
08ff6f2a9 regulator: Add ma... |
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
} static struct max8925_regulator_info max8925_regulator_info[] = { MAX8925_SDV(1, 637.5, 1425, 12.5), MAX8925_SDV(2, 650, 2225, 25), MAX8925_SDV(3, 750, 3900, 50), MAX8925_LDO(1, 750, 3900, 50), MAX8925_LDO(2, 650, 2250, 25), MAX8925_LDO(3, 650, 2250, 25), MAX8925_LDO(4, 750, 3900, 50), MAX8925_LDO(5, 750, 3900, 50), MAX8925_LDO(6, 750, 3900, 50), MAX8925_LDO(7, 750, 3900, 50), MAX8925_LDO(8, 750, 3900, 50), MAX8925_LDO(9, 750, 3900, 50), MAX8925_LDO(10, 750, 3900, 50), MAX8925_LDO(11, 750, 3900, 50), MAX8925_LDO(12, 750, 3900, 50), MAX8925_LDO(13, 750, 3900, 50), MAX8925_LDO(14, 750, 3900, 50), MAX8925_LDO(15, 750, 3900, 50), MAX8925_LDO(16, 750, 3900, 50), MAX8925_LDO(17, 650, 2250, 25), MAX8925_LDO(18, 650, 2250, 25), MAX8925_LDO(19, 750, 3900, 50), MAX8925_LDO(20, 750, 3900, 50), }; |
a5023574d regulator: remove... |
211 |
static int max8925_regulator_probe(struct platform_device *pdev) |
08ff6f2a9 regulator: Add ma... |
212 213 |
{ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
dff91d0b7 regulator: use de... |
214 |
struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); |
c172708d3 regulator: core: ... |
215 |
struct regulator_config config = { }; |
3fff6c04d Regulators: max89... |
216 |
struct max8925_regulator_info *ri; |
51acdb611 mfd: max8925: Rem... |
217 |
struct resource *res; |
08ff6f2a9 regulator: Add ma... |
218 |
struct regulator_dev *rdev; |
6185de50e regulator: max892... |
219 |
int i; |
08ff6f2a9 regulator: Add ma... |
220 |
|
51acdb611 mfd: max8925: Rem... |
221 222 223 224 225 226 227 228 |
res = platform_get_resource(pdev, IORESOURCE_REG, 0); if (!res) { dev_err(&pdev->dev, "No REG resource! "); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) { ri = &max8925_regulator_info[i]; |
6185de50e regulator: max892... |
229 |
if (ri->vol_reg == res->start) |
51acdb611 mfd: max8925: Rem... |
230 231 |
break; } |
45b6f8e8f regulator: max892... |
232 |
|
51acdb611 mfd: max8925: Rem... |
233 234 235 236 |
if (i == ARRAY_SIZE(max8925_regulator_info)) { dev_err(&pdev->dev, "Failed to find regulator %llu ", (unsigned long long)res->start); |
08ff6f2a9 regulator: Add ma... |
237 238 239 |
return -EINVAL; } ri->i2c = chip->i2c; |
08ff6f2a9 regulator: Add ma... |
240 |
|
6185de50e regulator: max892... |
241 |
config.dev = chip->dev; |
c172708d3 regulator: core: ... |
242 |
config.driver_data = ri; |
6185de50e regulator: max892... |
243 244 |
if (pdata) config.init_data = pdata; |
45b6f8e8f regulator: max892... |
245 |
|
58765e24b regulator: max892... |
246 |
rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config); |
08ff6f2a9 regulator: Add ma... |
247 248 249 250 251 252 253 254 255 256 |
if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s ", ri->desc.name); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); return 0; } |
08ff6f2a9 regulator: Add ma... |
257 258 259 |
static struct platform_driver max8925_regulator_driver = { .driver = { .name = "max8925-regulator", |
08ff6f2a9 regulator: Add ma... |
260 261 |
}, .probe = max8925_regulator_probe, |
08ff6f2a9 regulator: Add ma... |
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
}; static int __init max8925_regulator_init(void) { return platform_driver_register(&max8925_regulator_driver); } subsys_initcall(max8925_regulator_init); static void __exit max8925_regulator_exit(void) { platform_driver_unregister(&max8925_regulator_driver); } module_exit(max8925_regulator_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); MODULE_DESCRIPTION("Regulator Driver for Maxim 8925 PMIC"); MODULE_ALIAS("platform:max8925-regulator"); |