1 /* 2 * arizona-ldo1.c -- LDO1 supply for Arizona devices 3 * 4 * Copyright 2012 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14 #include <linux/module.h> 15 #include <linux/moduleparam.h> 16 #include <linux/init.h> 17 #include <linux/bitops.h> 18 #include <linux/err.h> 19 #include <linux/of.h> 20 #include <linux/gpio/consumer.h> 21 #include <linux/platform_device.h> 22 #include <linux/regulator/driver.h> 23 #include <linux/regulator/machine.h> 24 #include <linux/regulator/of_regulator.h> 25 #include <linux/slab.h> 26 27 #include <linux/regulator/arizona-ldo1.h> 28 29 #include <linux/mfd/arizona/core.h> 30 #include <linux/mfd/arizona/pdata.h> 31 #include <linux/mfd/arizona/registers.h> 32 33 struct arizona_ldo1 { 34 struct regulator_dev *regulator; 35 struct regmap *regmap; 36 37 struct regulator_consumer_supply supply; 38 struct regulator_init_data init_data; 39 40 struct gpio_desc *ena_gpiod; 41 }; 42 43 static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, 44 unsigned int selector) 45 { 46 if (selector >= rdev->desc->n_voltages) 47 return -EINVAL; 48 49 if (selector == rdev->desc->n_voltages - 1) 50 return 1800000; 51 else 52 return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 53 } 54 55 static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev, 56 int min_uV, int max_uV) 57 { 58 int sel; 59 60 sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 61 if (sel >= rdev->desc->n_voltages) 62 sel = rdev->desc->n_voltages - 1; 63 64 return sel; 65 } 66 67 static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, 68 unsigned sel) 69 { 70 struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); 71 struct regmap *regmap = ldo->regmap; 72 unsigned int val; 73 int ret; 74 75 if (sel == rdev->desc->n_voltages - 1) 76 val = ARIZONA_LDO1_HI_PWR; 77 else 78 val = 0; 79 80 ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2, 81 ARIZONA_LDO1_HI_PWR, val); 82 if (ret != 0) 83 return ret; 84 85 if (val) 86 return 0; 87 88 val = sel << ARIZONA_LDO1_VSEL_SHIFT; 89 90 return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, 91 ARIZONA_LDO1_VSEL_MASK, val); 92 } 93 94 static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) 95 { 96 struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); 97 struct regmap *regmap = ldo->regmap; 98 unsigned int val; 99 int ret; 100 101 ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val); 102 if (ret != 0) 103 return ret; 104 105 if (val & ARIZONA_LDO1_HI_PWR) 106 return rdev->desc->n_voltages - 1; 107 108 ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val); 109 if (ret != 0) 110 return ret; 111 112 return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT; 113 } 114 115 static const struct regulator_ops arizona_ldo1_hc_ops = { 116 .list_voltage = arizona_ldo1_hc_list_voltage, 117 .map_voltage = arizona_ldo1_hc_map_voltage, 118 .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, 119 .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, 120 .get_bypass = regulator_get_bypass_regmap, 121 .set_bypass = regulator_set_bypass_regmap, 122 }; 123 124 static const struct regulator_desc arizona_ldo1_hc = { 125 .name = "LDO1", 126 .supply_name = "LDOVDD", 127 .type = REGULATOR_VOLTAGE, 128 .ops = &arizona_ldo1_hc_ops, 129 130 .bypass_reg = ARIZONA_LDO1_CONTROL_1, 131 .bypass_mask = ARIZONA_LDO1_BYPASS, 132 .min_uV = 900000, 133 .uV_step = 50000, 134 .n_voltages = 8, 135 .enable_time = 1500, 136 .ramp_delay = 24000, 137 138 .owner = THIS_MODULE, 139 }; 140 141 static const struct regulator_ops arizona_ldo1_ops = { 142 .list_voltage = regulator_list_voltage_linear, 143 .map_voltage = regulator_map_voltage_linear, 144 .get_voltage_sel = regulator_get_voltage_sel_regmap, 145 .set_voltage_sel = regulator_set_voltage_sel_regmap, 146 }; 147 148 static const struct regulator_desc arizona_ldo1 = { 149 .name = "LDO1", 150 .supply_name = "LDOVDD", 151 .type = REGULATOR_VOLTAGE, 152 .ops = &arizona_ldo1_ops, 153 154 .vsel_reg = ARIZONA_LDO1_CONTROL_1, 155 .vsel_mask = ARIZONA_LDO1_VSEL_MASK, 156 .min_uV = 900000, 157 .uV_step = 25000, 158 .n_voltages = 13, 159 .enable_time = 500, 160 .ramp_delay = 24000, 161 162 .owner = THIS_MODULE, 163 }; 164 165 static const struct regulator_init_data arizona_ldo1_dvfs = { 166 .constraints = { 167 .min_uV = 1200000, 168 .max_uV = 1800000, 169 .valid_ops_mask = REGULATOR_CHANGE_STATUS | 170 REGULATOR_CHANGE_VOLTAGE, 171 }, 172 .num_consumer_supplies = 1, 173 }; 174 175 static const struct regulator_init_data arizona_ldo1_default = { 176 .constraints = { 177 .valid_ops_mask = REGULATOR_CHANGE_STATUS, 178 }, 179 .num_consumer_supplies = 1, 180 }; 181 182 static const struct regulator_init_data arizona_ldo1_wm5110 = { 183 .constraints = { 184 .min_uV = 1175000, 185 .max_uV = 1200000, 186 .valid_ops_mask = REGULATOR_CHANGE_STATUS | 187 REGULATOR_CHANGE_VOLTAGE, 188 }, 189 .num_consumer_supplies = 1, 190 }; 191 192 static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata, 193 struct regulator_config *config, 194 const struct regulator_desc *desc, 195 bool *external_dcvdd) 196 { 197 struct arizona_ldo1 *ldo1 = config->driver_data; 198 struct device_node *np = config->dev->of_node; 199 struct device_node *init_node, *dcvdd_node; 200 struct regulator_init_data *init_data; 201 202 init_node = of_get_child_by_name(np, "ldo1"); 203 dcvdd_node = of_parse_phandle(np, "DCVDD-supply", 0); 204 205 if (init_node) { 206 config->of_node = init_node; 207 208 init_data = of_get_regulator_init_data(config->dev, init_node, 209 desc); 210 if (init_data) { 211 init_data->consumer_supplies = &ldo1->supply; 212 init_data->num_consumer_supplies = 1; 213 214 if (dcvdd_node && dcvdd_node != init_node) 215 *external_dcvdd = true; 216 217 pdata->init_data = init_data; 218 } 219 } else if (dcvdd_node) { 220 *external_dcvdd = true; 221 } 222 223 of_node_put(dcvdd_node); 224 225 return 0; 226 } 227 228 static int arizona_ldo1_common_init(struct platform_device *pdev, 229 struct arizona_ldo1 *ldo1, 230 const struct regulator_desc *desc, 231 struct arizona_ldo1_pdata *pdata, 232 bool *external_dcvdd) 233 { 234 struct device *parent_dev = pdev->dev.parent; 235 struct regulator_config config = { }; 236 int ret; 237 238 *external_dcvdd = false; 239 240 ldo1->supply.supply = "DCVDD"; 241 ldo1->init_data.consumer_supplies = &ldo1->supply; 242 ldo1->supply.dev_name = dev_name(parent_dev); 243 244 config.dev = parent_dev; 245 config.driver_data = ldo1; 246 config.regmap = ldo1->regmap; 247 248 if (IS_ENABLED(CONFIG_OF)) { 249 if (!dev_get_platdata(parent_dev)) { 250 ret = arizona_ldo1_of_get_pdata(pdata, 251 &config, desc, 252 external_dcvdd); 253 if (ret < 0) 254 return ret; 255 } 256 } 257 258 /* We assume that high output = regulator off 259 * Don't use devm, since we need to get against the parent device 260 * so clean up would happen at the wrong time 261 */ 262 config.ena_gpiod = gpiod_get_optional(parent_dev, "wlf,ldoena", 263 GPIOD_OUT_LOW); 264 if (IS_ERR(config.ena_gpiod)) 265 return PTR_ERR(config.ena_gpiod); 266 267 ldo1->ena_gpiod = config.ena_gpiod; 268 269 if (pdata->init_data) 270 config.init_data = pdata->init_data; 271 else 272 config.init_data = &ldo1->init_data; 273 274 /* 275 * LDO1 can only be used to supply DCVDD so if it has no 276 * consumers then DCVDD is supplied externally. 277 */ 278 if (config.init_data->num_consumer_supplies == 0) 279 *external_dcvdd = true; 280 281 ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); 282 283 of_node_put(config.of_node); 284 285 if (IS_ERR(ldo1->regulator)) { 286 if (config.ena_gpiod) 287 gpiod_put(config.ena_gpiod); 288 289 ret = PTR_ERR(ldo1->regulator); 290 dev_err(&pdev->dev, "Failed to register LDO1 supply: %d\n", 291 ret); 292 return ret; 293 } 294 295 platform_set_drvdata(pdev, ldo1); 296 297 return 0; 298 } 299 300 static int arizona_ldo1_probe(struct platform_device *pdev) 301 { 302 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); 303 struct arizona_ldo1 *ldo1; 304 const struct regulator_desc *desc; 305 bool external_dcvdd; 306 int ret; 307 308 ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); 309 if (!ldo1) 310 return -ENOMEM; 311 312 ldo1->regmap = arizona->regmap; 313 314 /* 315 * Since the chip usually supplies itself we provide some 316 * default init_data for it. This will be overridden with 317 * platform data if provided. 318 */ 319 switch (arizona->type) { 320 case WM5102: 321 case WM8997: 322 case WM8998: 323 case WM1814: 324 desc = &arizona_ldo1_hc; 325 ldo1->init_data = arizona_ldo1_dvfs; 326 break; 327 case WM5110: 328 case WM8280: 329 desc = &arizona_ldo1; 330 ldo1->init_data = arizona_ldo1_wm5110; 331 break; 332 default: 333 desc = &arizona_ldo1; 334 ldo1->init_data = arizona_ldo1_default; 335 break; 336 } 337 338 ret = arizona_ldo1_common_init(pdev, ldo1, desc, 339 &arizona->pdata.ldo1, 340 &external_dcvdd); 341 if (ret == 0) 342 arizona->external_dcvdd = external_dcvdd; 343 344 return ret; 345 } 346 347 static int arizona_ldo1_remove(struct platform_device *pdev) 348 { 349 struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev); 350 351 if (ldo1->ena_gpiod) 352 gpiod_put(ldo1->ena_gpiod); 353 354 return 0; 355 } 356 357 static struct platform_driver arizona_ldo1_driver = { 358 .probe = arizona_ldo1_probe, 359 .remove = arizona_ldo1_remove, 360 .driver = { 361 .name = "arizona-ldo1", 362 }, 363 }; 364 365 module_platform_driver(arizona_ldo1_driver); 366 367 /* Module information */ 368 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 369 MODULE_DESCRIPTION("Arizona LDO1 driver"); 370 MODULE_LICENSE("GPL"); 371 MODULE_ALIAS("platform:arizona-ldo1"); 372