Blame view
drivers/regulator/max8952.c
8.8 KB
1a59d1b8e treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
202f4f53e MAX8952 PMIC Driv... |
2 3 4 5 6 |
/* * max8952.c - Voltage and current regulation for the Maxim 8952 * * Copyright (C) 2010 Samsung Electronics * MyungJoo Ham <myungjoo.ham@samsung.com> |
202f4f53e MAX8952 PMIC Driv... |
7 8 9 10 11 12 13 14 15 |
*/ #include <linux/module.h> #include <linux/init.h> #include <linux/i2c.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/max8952.h> |
d7a261c2d regulator: max895... |
16 |
#include <linux/gpio/consumer.h> |
202f4f53e MAX8952 PMIC Driv... |
17 |
#include <linux/io.h> |
3ff4aa95b regulator: max895... |
18 |
#include <linux/of.h> |
3ff4aa95b regulator: max895... |
19 |
#include <linux/regulator/of_regulator.h> |
202f4f53e MAX8952 PMIC Driv... |
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <linux/slab.h> /* Registers */ enum { MAX8952_REG_MODE0, MAX8952_REG_MODE1, MAX8952_REG_MODE2, MAX8952_REG_MODE3, MAX8952_REG_CONTROL, MAX8952_REG_SYNC, MAX8952_REG_RAMP, MAX8952_REG_CHIP_ID1, MAX8952_REG_CHIP_ID2, }; struct max8952_data { struct i2c_client *client; |
202f4f53e MAX8952 PMIC Driv... |
37 |
struct max8952_platform_data *pdata; |
fd742eaab regulator: max895... |
38 39 |
struct gpio_desc *vid0_gpiod; struct gpio_desc *vid1_gpiod; |
202f4f53e MAX8952 PMIC Driv... |
40 41 |
bool vid0; bool vid1; |
202f4f53e MAX8952 PMIC Driv... |
42 43 44 45 46 |
}; static int max8952_read_reg(struct max8952_data *max8952, u8 reg) { int ret = i2c_smbus_read_byte_data(max8952->client, reg); |
a5f8f9630 regulator: max895... |
47 |
|
202f4f53e MAX8952 PMIC Driv... |
48 49 50 51 52 53 54 55 56 57 58 |
if (ret > 0) ret &= 0xff; return ret; } static int max8952_write_reg(struct max8952_data *max8952, u8 reg, u8 value) { return i2c_smbus_write_byte_data(max8952->client, reg, value); } |
202f4f53e MAX8952 PMIC Driv... |
59 60 61 62 63 64 65 |
static int max8952_list_voltage(struct regulator_dev *rdev, unsigned int selector) { struct max8952_data *max8952 = rdev_get_drvdata(rdev); if (rdev_get_id(rdev) != 0) return -EINVAL; |
b9b49af5e regulator: max895... |
66 |
return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000; |
202f4f53e MAX8952 PMIC Driv... |
67 |
} |
b9b49af5e regulator: max895... |
68 |
static int max8952_get_voltage_sel(struct regulator_dev *rdev) |
202f4f53e MAX8952 PMIC Driv... |
69 70 71 72 73 74 75 76 |
{ struct max8952_data *max8952 = rdev_get_drvdata(rdev); u8 vid = 0; if (max8952->vid0) vid += 1; if (max8952->vid1) vid += 2; |
b9b49af5e regulator: max895... |
77 |
return vid; |
202f4f53e MAX8952 PMIC Driv... |
78 |
} |
6ea67d04b regulator: Conver... |
79 80 |
static int max8952_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) |
202f4f53e MAX8952 PMIC Driv... |
81 82 |
{ struct max8952_data *max8952 = rdev_get_drvdata(rdev); |
202f4f53e MAX8952 PMIC Driv... |
83 |
|
fd742eaab regulator: max895... |
84 |
if (!max8952->vid0_gpiod || !max8952->vid1_gpiod) { |
202f4f53e MAX8952 PMIC Driv... |
85 86 87 |
/* DVS not supported */ return -EPERM; } |
6ea67d04b regulator: Conver... |
88 89 |
max8952->vid0 = selector & 0x1; max8952->vid1 = (selector >> 1) & 0x1; |
fd742eaab regulator: max895... |
90 91 |
gpiod_set_value(max8952->vid0_gpiod, max8952->vid0); gpiod_set_value(max8952->vid1_gpiod, max8952->vid1); |
202f4f53e MAX8952 PMIC Driv... |
92 93 94 |
return 0; } |
6e09f4af1 regulator: max895... |
95 |
static const struct regulator_ops max8952_ops = { |
202f4f53e MAX8952 PMIC Driv... |
96 |
.list_voltage = max8952_list_voltage, |
b9b49af5e regulator: max895... |
97 |
.get_voltage_sel = max8952_get_voltage_sel, |
6ea67d04b regulator: Conver... |
98 |
.set_voltage_sel = max8952_set_voltage_sel, |
202f4f53e MAX8952 PMIC Driv... |
99 |
}; |
bd6ff0d6a regulator: max895... |
100 |
static const struct regulator_desc regulator = { |
202f4f53e MAX8952 PMIC Driv... |
101 102 103 104 105 106 107 |
.name = "MAX8952_VOUT", .id = 0, .n_voltages = MAX8952_NUM_DVS_MODE, .ops = &max8952_ops, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }; |
3ff4aa95b regulator: max895... |
108 |
#ifdef CONFIG_OF |
cfe6e3334 regulator: max895... |
109 |
static const struct of_device_id max8952_dt_match[] = { |
3ff4aa95b regulator: max895... |
110 111 112 113 114 115 116 117 118 119 120 121 122 |
{ .compatible = "maxim,max8952" }, {}, }; MODULE_DEVICE_TABLE(of, max8952_dt_match); static struct max8952_platform_data *max8952_parse_dt(struct device *dev) { struct max8952_platform_data *pd; struct device_node *np = dev->of_node; int ret; int i; pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); |
7752d9640 regulator: max895... |
123 |
if (!pd) |
3ff4aa95b regulator: max895... |
124 |
return NULL; |
3ff4aa95b regulator: max895... |
125 |
|
3ff4aa95b regulator: max895... |
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
if (of_property_read_u32(np, "max8952,default-mode", &pd->default_mode)) dev_warn(dev, "Default mode not specified, assuming 0 "); ret = of_property_read_u32_array(np, "max8952,dvs-mode-microvolt", pd->dvs_mode, ARRAY_SIZE(pd->dvs_mode)); if (ret) { dev_err(dev, "max8952,dvs-mode-microvolt property not specified"); return NULL; } for (i = 0; i < ARRAY_SIZE(pd->dvs_mode); ++i) { if (pd->dvs_mode[i] < 770000 || pd->dvs_mode[i] > 1400000) { dev_err(dev, "DVS voltage %d out of range ", i); return NULL; } pd->dvs_mode[i] = (pd->dvs_mode[i] - 770000) / 10000; } if (of_property_read_u32(np, "max8952,sync-freq", &pd->sync_freq)) dev_warn(dev, "max8952,sync-freq property not specified, defaulting to 26MHz "); if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed)) dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us "); |
072e78b12 regulator: of: Ad... |
153 |
pd->reg_data = of_get_regulator_init_data(dev, np, ®ulator); |
3ff4aa95b regulator: max895... |
154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
if (!pd->reg_data) { dev_err(dev, "Failed to parse regulator init data "); return NULL; } return pd; } #else static struct max8952_platform_data *max8952_parse_dt(struct device *dev) { return NULL; } #endif |
a5023574d regulator: remove... |
168 |
static int max8952_pmic_probe(struct i2c_client *client, |
202f4f53e MAX8952 PMIC Driv... |
169 170 |
const struct i2c_device_id *i2c_id) { |
6b96092a6 regulator: max895... |
171 |
struct i2c_adapter *adapter = client->adapter; |
dff91d0b7 regulator: use de... |
172 |
struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); |
c172708d3 regulator: core: ... |
173 |
struct regulator_config config = { }; |
202f4f53e MAX8952 PMIC Driv... |
174 |
struct max8952_data *max8952; |
b874f41c6 regulator: max895... |
175 |
struct regulator_dev *rdev; |
d7a261c2d regulator: max895... |
176 177 |
struct gpio_desc *gpiod; enum gpiod_flags gflags; |
202f4f53e MAX8952 PMIC Driv... |
178 |
|
fd742eaab regulator: max895... |
179 |
int ret = 0; |
202f4f53e MAX8952 PMIC Driv... |
180 |
|
3ff4aa95b regulator: max895... |
181 182 |
if (client->dev.of_node) pdata = max8952_parse_dt(&client->dev); |
202f4f53e MAX8952 PMIC Driv... |
183 184 185 186 187 188 189 190 |
if (!pdata) { dev_err(&client->dev, "Require the platform data "); return -EINVAL; } if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) return -EIO; |
372de4aa5 regulator: max895... |
191 192 |
max8952 = devm_kzalloc(&client->dev, sizeof(struct max8952_data), GFP_KERNEL); |
202f4f53e MAX8952 PMIC Driv... |
193 194 195 196 |
if (!max8952) return -ENOMEM; max8952->client = client; |
202f4f53e MAX8952 PMIC Driv... |
197 |
max8952->pdata = pdata; |
202f4f53e MAX8952 PMIC Driv... |
198 |
|
b874f41c6 regulator: max895... |
199 |
config.dev = &client->dev; |
3ec6eb9cc regulator: max895... |
200 |
config.init_data = pdata->reg_data; |
c172708d3 regulator: core: ... |
201 |
config.driver_data = max8952; |
71622e15d regulator: max895... |
202 |
config.of_node = client->dev.of_node; |
c172708d3 regulator: core: ... |
203 |
|
3ec6eb9cc regulator: max895... |
204 |
if (pdata->reg_data->constraints.boot_on) |
d7a261c2d regulator: max895... |
205 206 207 |
gflags = GPIOD_OUT_HIGH; else gflags = GPIOD_OUT_LOW; |
63239e4bf regulator: Fetch ... |
208 |
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE; |
894077d5c regulator: max895... |
209 210 211 212 213 214 215 |
/* * Do not use devm* here: the regulator core takes over the * lifecycle management of the GPIO descriptor. */ gpiod = gpiod_get_optional(&client->dev, "max8952,en", gflags); |
d7a261c2d regulator: max895... |
216 217 218 219 |
if (IS_ERR(gpiod)) return PTR_ERR(gpiod); if (gpiod) config.ena_gpiod = gpiod; |
b669e0adb regulator: max895... |
220 |
|
b874f41c6 regulator: max895... |
221 |
rdev = devm_regulator_register(&client->dev, ®ulator, &config); |
b874f41c6 regulator: max895... |
222 223 224 225 |
if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(&client->dev, "regulator init failed (%d) ", ret); |
372de4aa5 regulator: max895... |
226 |
return ret; |
da05738e9 regulator: max895... |
227 |
} |
202f4f53e MAX8952 PMIC Driv... |
228 |
|
c8237f01d regulator: max895... |
229 230 |
max8952->vid0 = pdata->default_mode & 0x1; max8952->vid1 = (pdata->default_mode >> 1) & 0x1; |
202f4f53e MAX8952 PMIC Driv... |
231 |
|
fd742eaab regulator: max895... |
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
/* Fetch vid0 and vid1 GPIOs if available */ gflags = max8952->vid0 ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; max8952->vid0_gpiod = devm_gpiod_get_index_optional(&client->dev, "max8952,vid", 0, gflags); if (IS_ERR(max8952->vid0_gpiod)) return PTR_ERR(max8952->vid0_gpiod); gflags = max8952->vid1 ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; max8952->vid1_gpiod = devm_gpiod_get_index_optional(&client->dev, "max8952,vid", 1, gflags); if (IS_ERR(max8952->vid1_gpiod)) return PTR_ERR(max8952->vid1_gpiod); /* If either VID GPIO is missing just disable this */ if (!max8952->vid0_gpiod || !max8952->vid1_gpiod) { |
b874f41c6 regulator: max895... |
248 |
dev_warn(&client->dev, "VID0/1 gpio invalid: " |
fd742eaab regulator: max895... |
249 250 |
"DVS not available. "); |
202f4f53e MAX8952 PMIC Driv... |
251 252 |
max8952->vid0 = 0; max8952->vid1 = 0; |
fd742eaab regulator: max895... |
253 254 255 256 257 |
/* Make sure if we have any descriptors they get set to low */ if (max8952->vid0_gpiod) gpiod_set_value(max8952->vid0_gpiod, 0); if (max8952->vid1_gpiod) gpiod_set_value(max8952->vid1_gpiod, 0); |
202f4f53e MAX8952 PMIC Driv... |
258 259 260 |
/* Disable Pulldown of EN only */ max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x60); |
b874f41c6 regulator: max895... |
261 |
dev_err(&client->dev, "DVS modes disabled because VID0 and VID1" |
202f4f53e MAX8952 PMIC Driv... |
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
" do not have proper controls. "); } else { /* * Disable Pulldown on EN, VID0, VID1 to reduce * leakage current of MAX8952 assuming that MAX8952 * is turned on (EN==1). Note that without having VID0/1 * properly connected, turning pulldown off can be * problematic. Thus, turn this off only when they are * controllable by GPIO. */ max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x0); } max8952_write_reg(max8952, MAX8952_REG_MODE0, (max8952_read_reg(max8952, MAX8952_REG_MODE0) & 0xC0) | (pdata->dvs_mode[0] & 0x3F)); max8952_write_reg(max8952, MAX8952_REG_MODE1, (max8952_read_reg(max8952, MAX8952_REG_MODE1) & 0xC0) | (pdata->dvs_mode[1] & 0x3F)); max8952_write_reg(max8952, MAX8952_REG_MODE2, (max8952_read_reg(max8952, MAX8952_REG_MODE2) & 0xC0) | (pdata->dvs_mode[2] & 0x3F)); max8952_write_reg(max8952, MAX8952_REG_MODE3, (max8952_read_reg(max8952, MAX8952_REG_MODE3) & 0xC0) | (pdata->dvs_mode[3] & 0x3F)); max8952_write_reg(max8952, MAX8952_REG_SYNC, (max8952_read_reg(max8952, MAX8952_REG_SYNC) & 0x3F) | ((pdata->sync_freq & 0x3) << 6)); max8952_write_reg(max8952, MAX8952_REG_RAMP, (max8952_read_reg(max8952, MAX8952_REG_RAMP) & 0x1F) | ((pdata->ramp_speed & 0x7) << 5)); i2c_set_clientdata(client, max8952); |
da05738e9 regulator: max895... |
301 |
return 0; |
202f4f53e MAX8952 PMIC Driv... |
302 |
} |
202f4f53e MAX8952 PMIC Driv... |
303 304 305 306 307 308 309 310 |
static const struct i2c_device_id max8952_ids[] = { { "max8952", 0 }, { }, }; MODULE_DEVICE_TABLE(i2c, max8952_ids); static struct i2c_driver max8952_pmic_driver = { .probe = max8952_pmic_probe, |
202f4f53e MAX8952 PMIC Driv... |
311 312 |
.driver = { .name = "max8952", |
3ff4aa95b regulator: max895... |
313 |
.of_match_table = of_match_ptr(max8952_dt_match), |
202f4f53e MAX8952 PMIC Driv... |
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
}, .id_table = max8952_ids, }; static int __init max8952_pmic_init(void) { return i2c_add_driver(&max8952_pmic_driver); } subsys_initcall(max8952_pmic_init); static void __exit max8952_pmic_exit(void) { i2c_del_driver(&max8952_pmic_driver); } module_exit(max8952_pmic_exit); MODULE_DESCRIPTION("MAXIM 8952 voltage regulator driver"); MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); MODULE_LICENSE("GPL"); |