1 /* 2 * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies 3 * 4 * Copyright (C) 2012 Renesas Electronics Corporation 5 * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the version 2 of the GNU General Public License as 9 * published by the Free Software Foundation 10 */ 11 12 #include <linux/err.h> 13 #include <linux/init.h> 14 #include <linux/mfd/as3711.h> 15 #include <linux/module.h> 16 #include <linux/of.h> 17 #include <linux/platform_device.h> 18 #include <linux/regmap.h> 19 #include <linux/regulator/driver.h> 20 #include <linux/regulator/of_regulator.h> 21 #include <linux/slab.h> 22 23 struct as3711_regulator_info { 24 struct regulator_desc desc; 25 unsigned int max_uV; 26 }; 27 28 struct as3711_regulator { 29 struct as3711_regulator_info *reg_info; 30 struct regulator_dev *rdev; 31 }; 32 33 static int as3711_list_voltage_sd(struct regulator_dev *rdev, 34 unsigned int selector) 35 { 36 if (selector >= rdev->desc->n_voltages) 37 return -EINVAL; 38 39 if (!selector) 40 return 0; 41 if (selector < 0x41) 42 return 600000 + selector * 12500; 43 if (selector < 0x71) 44 return 1400000 + (selector - 0x40) * 25000; 45 return 2600000 + (selector - 0x70) * 50000; 46 } 47 48 static int as3711_list_voltage_aldo(struct regulator_dev *rdev, 49 unsigned int selector) 50 { 51 if (selector >= rdev->desc->n_voltages) 52 return -EINVAL; 53 54 if (selector < 0x10) 55 return 1200000 + selector * 50000; 56 return 1800000 + (selector - 0x10) * 100000; 57 } 58 59 static int as3711_list_voltage_dldo(struct regulator_dev *rdev, 60 unsigned int selector) 61 { 62 if (selector >= rdev->desc->n_voltages || 63 (selector > 0x10 && selector < 0x20)) 64 return -EINVAL; 65 66 if (selector < 0x11) 67 return 900000 + selector * 50000; 68 return 1750000 + (selector - 0x20) * 50000; 69 } 70 71 static int as3711_bound_check(struct regulator_dev *rdev, 72 int *min_uV, int *max_uV) 73 { 74 struct as3711_regulator *reg = rdev_get_drvdata(rdev); 75 struct as3711_regulator_info *info = reg->reg_info; 76 77 dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__, 78 *min_uV, rdev->desc->min_uV, info->max_uV); 79 80 if (*max_uV < *min_uV || 81 *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV) 82 return -EINVAL; 83 84 if (rdev->desc->n_voltages == 1) 85 return 0; 86 87 if (*max_uV > info->max_uV) 88 *max_uV = info->max_uV; 89 90 if (*min_uV < rdev->desc->min_uV) 91 *min_uV = rdev->desc->min_uV; 92 93 return *min_uV; 94 } 95 96 static int as3711_sel_check(int min, int max, int bottom, int step) 97 { 98 int sel, voltage; 99 100 /* Round up min, when dividing: keeps us within the range */ 101 sel = DIV_ROUND_UP(min - bottom, step); 102 voltage = sel * step + bottom; 103 pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__, 104 min, max, bottom, step, sel); 105 if (voltage > max) 106 return -EINVAL; 107 108 return sel; 109 } 110 111 static int as3711_map_voltage_sd(struct regulator_dev *rdev, 112 int min_uV, int max_uV) 113 { 114 int ret; 115 116 ret = as3711_bound_check(rdev, &min_uV, &max_uV); 117 if (ret <= 0) 118 return ret; 119 120 if (min_uV <= 1400000) 121 return as3711_sel_check(min_uV, max_uV, 600000, 12500); 122 123 if (min_uV <= 2600000) 124 return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40; 125 126 return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70; 127 } 128 129 /* 130 * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and 131 * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: 132 * FAST: sdX_fast=1 133 * NORMAL: low_noise=1 134 * IDLE: low_noise=0 135 */ 136 137 static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode) 138 { 139 unsigned int fast_bit = rdev->desc->enable_mask, 140 low_noise_bit = fast_bit << 4; 141 u8 val; 142 143 switch (mode) { 144 case REGULATOR_MODE_FAST: 145 val = fast_bit | low_noise_bit; 146 break; 147 case REGULATOR_MODE_NORMAL: 148 val = low_noise_bit; 149 break; 150 case REGULATOR_MODE_IDLE: 151 val = 0; 152 break; 153 default: 154 return -EINVAL; 155 } 156 157 return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1, 158 low_noise_bit | fast_bit, val); 159 } 160 161 static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev) 162 { 163 unsigned int fast_bit = rdev->desc->enable_mask, 164 low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit; 165 unsigned int val; 166 int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val); 167 168 if (ret < 0) 169 return ret; 170 171 if ((val & mask) == mask) 172 return REGULATOR_MODE_FAST; 173 174 if ((val & mask) == low_noise_bit) 175 return REGULATOR_MODE_NORMAL; 176 177 if (!(val & mask)) 178 return REGULATOR_MODE_IDLE; 179 180 return -EINVAL; 181 } 182 183 static int as3711_map_voltage_aldo(struct regulator_dev *rdev, 184 int min_uV, int max_uV) 185 { 186 int ret; 187 188 ret = as3711_bound_check(rdev, &min_uV, &max_uV); 189 if (ret <= 0) 190 return ret; 191 192 if (min_uV <= 1800000) 193 return as3711_sel_check(min_uV, max_uV, 1200000, 50000); 194 195 return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10; 196 } 197 198 static int as3711_map_voltage_dldo(struct regulator_dev *rdev, 199 int min_uV, int max_uV) 200 { 201 int ret; 202 203 ret = as3711_bound_check(rdev, &min_uV, &max_uV); 204 if (ret <= 0) 205 return ret; 206 207 if (min_uV <= 1700000) 208 return as3711_sel_check(min_uV, max_uV, 900000, 50000); 209 210 return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20; 211 } 212 213 static struct regulator_ops as3711_sd_ops = { 214 .is_enabled = regulator_is_enabled_regmap, 215 .enable = regulator_enable_regmap, 216 .disable = regulator_disable_regmap, 217 .get_voltage_sel = regulator_get_voltage_sel_regmap, 218 .set_voltage_sel = regulator_set_voltage_sel_regmap, 219 .list_voltage = as3711_list_voltage_sd, 220 .map_voltage = as3711_map_voltage_sd, 221 .get_mode = as3711_get_mode_sd, 222 .set_mode = as3711_set_mode_sd, 223 }; 224 225 static struct regulator_ops as3711_aldo_ops = { 226 .is_enabled = regulator_is_enabled_regmap, 227 .enable = regulator_enable_regmap, 228 .disable = regulator_disable_regmap, 229 .get_voltage_sel = regulator_get_voltage_sel_regmap, 230 .set_voltage_sel = regulator_set_voltage_sel_regmap, 231 .list_voltage = as3711_list_voltage_aldo, 232 .map_voltage = as3711_map_voltage_aldo, 233 }; 234 235 static struct regulator_ops as3711_dldo_ops = { 236 .is_enabled = regulator_is_enabled_regmap, 237 .enable = regulator_enable_regmap, 238 .disable = regulator_disable_regmap, 239 .get_voltage_sel = regulator_get_voltage_sel_regmap, 240 .set_voltage_sel = regulator_set_voltage_sel_regmap, 241 .list_voltage = as3711_list_voltage_dldo, 242 .map_voltage = as3711_map_voltage_dldo, 243 }; 244 245 #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ 246 [AS3711_REGULATOR_ ## _id] = { \ 247 .desc = { \ 248 .name = "as3711-regulator-" # _id, \ 249 .id = AS3711_REGULATOR_ ## _id, \ 250 .n_voltages = (_vmask + 1), \ 251 .ops = &as3711_ ## _sfx ## _ops, \ 252 .type = REGULATOR_VOLTAGE, \ 253 .owner = THIS_MODULE, \ 254 .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \ 255 .vsel_mask = _vmask << _vshift, \ 256 .enable_reg = AS3711_ ## _en_reg, \ 257 .enable_mask = BIT(_en_bit), \ 258 .min_uV = _min_uV, \ 259 }, \ 260 .max_uV = _max_uV, \ 261 } 262 263 static struct as3711_regulator_info as3711_reg_info[] = { 264 AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd), 265 AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd), 266 AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd), 267 AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd), 268 AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), 269 AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), 270 AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 271 AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 272 AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 273 AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 274 AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 275 AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 276 /* StepUp output voltage depends on supplying regulator */ 277 }; 278 279 #define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info) 280 281 static struct of_regulator_match 282 as3711_regulator_matches[AS3711_REGULATOR_NUM] = { 283 [AS3711_REGULATOR_SD_1] = { .name = "sd1" }, 284 [AS3711_REGULATOR_SD_2] = { .name = "sd2" }, 285 [AS3711_REGULATOR_SD_3] = { .name = "sd3" }, 286 [AS3711_REGULATOR_SD_4] = { .name = "sd4" }, 287 [AS3711_REGULATOR_LDO_1] = { .name = "ldo1" }, 288 [AS3711_REGULATOR_LDO_2] = { .name = "ldo2" }, 289 [AS3711_REGULATOR_LDO_3] = { .name = "ldo3" }, 290 [AS3711_REGULATOR_LDO_4] = { .name = "ldo4" }, 291 [AS3711_REGULATOR_LDO_5] = { .name = "ldo5" }, 292 [AS3711_REGULATOR_LDO_6] = { .name = "ldo6" }, 293 [AS3711_REGULATOR_LDO_7] = { .name = "ldo7" }, 294 [AS3711_REGULATOR_LDO_8] = { .name = "ldo8" }, 295 }; 296 297 static int as3711_regulator_parse_dt(struct device *dev, 298 struct device_node **of_node, const int count) 299 { 300 struct as3711_regulator_pdata *pdata = dev_get_platdata(dev); 301 struct device_node *regulators = 302 of_find_node_by_name(dev->parent->of_node, "regulators"); 303 struct of_regulator_match *match; 304 int ret, i; 305 306 if (!regulators) { 307 dev_err(dev, "regulator node not found\n"); 308 return -ENODEV; 309 } 310 311 ret = of_regulator_match(dev->parent, regulators, 312 as3711_regulator_matches, count); 313 of_node_put(regulators); 314 if (ret < 0) { 315 dev_err(dev, "Error parsing regulator init data: %d\n", ret); 316 return ret; 317 } 318 319 for (i = 0, match = as3711_regulator_matches; i < count; i++, match++) 320 if (match->of_node) { 321 pdata->init_data[i] = match->init_data; 322 of_node[i] = match->of_node; 323 } 324 325 return 0; 326 } 327 328 static int as3711_regulator_probe(struct platform_device *pdev) 329 { 330 struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev); 331 struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); 332 struct regulator_init_data *reg_data; 333 struct regulator_config config = {.dev = &pdev->dev,}; 334 struct as3711_regulator *reg = NULL; 335 struct as3711_regulator *regs; 336 struct device_node *of_node[AS3711_REGULATOR_NUM] = {}; 337 struct regulator_dev *rdev; 338 struct as3711_regulator_info *ri; 339 int ret; 340 int id; 341 342 if (!pdata) { 343 dev_err(&pdev->dev, "No platform data...\n"); 344 return -ENODEV; 345 } 346 347 if (pdev->dev.parent->of_node) { 348 ret = as3711_regulator_parse_dt(&pdev->dev, of_node, AS3711_REGULATOR_NUM); 349 if (ret < 0) { 350 dev_err(&pdev->dev, "DT parsing failed: %d\n", ret); 351 return ret; 352 } 353 } 354 355 regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM * 356 sizeof(struct as3711_regulator), GFP_KERNEL); 357 if (!regs) { 358 dev_err(&pdev->dev, "Memory allocation failed exiting..\n"); 359 return -ENOMEM; 360 } 361 362 for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) { 363 reg_data = pdata->init_data[id]; 364 365 /* No need to register if there is no regulator data */ 366 if (!reg_data) 367 continue; 368 369 reg = ®s[id]; 370 reg->reg_info = ri; 371 372 config.init_data = reg_data; 373 config.driver_data = reg; 374 config.regmap = as3711->regmap; 375 config.of_node = of_node[id]; 376 377 rdev = regulator_register(&ri->desc, &config); 378 if (IS_ERR(rdev)) { 379 dev_err(&pdev->dev, "Failed to register regulator %s\n", 380 ri->desc.name); 381 ret = PTR_ERR(rdev); 382 goto eregreg; 383 } 384 reg->rdev = rdev; 385 } 386 platform_set_drvdata(pdev, regs); 387 return 0; 388 389 eregreg: 390 while (--id >= 0) 391 regulator_unregister(regs[id].rdev); 392 393 return ret; 394 } 395 396 static int as3711_regulator_remove(struct platform_device *pdev) 397 { 398 struct as3711_regulator *regs = platform_get_drvdata(pdev); 399 int id; 400 401 for (id = 0; id < AS3711_REGULATOR_NUM; ++id) 402 regulator_unregister(regs[id].rdev); 403 return 0; 404 } 405 406 static struct platform_driver as3711_regulator_driver = { 407 .driver = { 408 .name = "as3711-regulator", 409 .owner = THIS_MODULE, 410 }, 411 .probe = as3711_regulator_probe, 412 .remove = as3711_regulator_remove, 413 }; 414 415 static int __init as3711_regulator_init(void) 416 { 417 return platform_driver_register(&as3711_regulator_driver); 418 } 419 subsys_initcall(as3711_regulator_init); 420 421 static void __exit as3711_regulator_exit(void) 422 { 423 platform_driver_unregister(&as3711_regulator_driver); 424 } 425 module_exit(as3711_regulator_exit); 426 427 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 428 MODULE_DESCRIPTION("AS3711 regulator driver"); 429 MODULE_ALIAS("platform:as3711-regulator"); 430 MODULE_LICENSE("GPL v2"); 431