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/of_gpio.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/gpio.h> 26 #include <linux/slab.h> 27 28 #include <linux/regulator/arizona-ldo1.h> 29 30 #include <linux/mfd/arizona/core.h> 31 #include <linux/mfd/arizona/pdata.h> 32 #include <linux/mfd/arizona/registers.h> 33 34 struct arizona_ldo1 { 35 struct regulator_dev *regulator; 36 struct regmap *regmap; 37 38 struct regulator_consumer_supply supply; 39 struct regulator_init_data init_data; 40 }; 41 42 static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, 43 unsigned int selector) 44 { 45 if (selector >= rdev->desc->n_voltages) 46 return -EINVAL; 47 48 if (selector == rdev->desc->n_voltages - 1) 49 return 1800000; 50 else 51 return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 52 } 53 54 static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev, 55 int min_uV, int max_uV) 56 { 57 int sel; 58 59 sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 60 if (sel >= rdev->desc->n_voltages) 61 sel = rdev->desc->n_voltages - 1; 62 63 return sel; 64 } 65 66 static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, 67 unsigned sel) 68 { 69 struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); 70 struct regmap *regmap = ldo->regmap; 71 unsigned int val; 72 int ret; 73 74 if (sel == rdev->desc->n_voltages - 1) 75 val = ARIZONA_LDO1_HI_PWR; 76 else 77 val = 0; 78 79 ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2, 80 ARIZONA_LDO1_HI_PWR, val); 81 if (ret != 0) 82 return ret; 83 84 if (val) 85 return 0; 86 87 val = sel << ARIZONA_LDO1_VSEL_SHIFT; 88 89 return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, 90 ARIZONA_LDO1_VSEL_MASK, val); 91 } 92 93 static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) 94 { 95 struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); 96 struct regmap *regmap = ldo->regmap; 97 unsigned int val; 98 int ret; 99 100 ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val); 101 if (ret != 0) 102 return ret; 103 104 if (val & ARIZONA_LDO1_HI_PWR) 105 return rdev->desc->n_voltages - 1; 106 107 ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val); 108 if (ret != 0) 109 return ret; 110 111 return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT; 112 } 113 114 static const struct regulator_ops arizona_ldo1_hc_ops = { 115 .list_voltage = arizona_ldo1_hc_list_voltage, 116 .map_voltage = arizona_ldo1_hc_map_voltage, 117 .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, 118 .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, 119 .get_bypass = regulator_get_bypass_regmap, 120 .set_bypass = regulator_set_bypass_regmap, 121 }; 122 123 static const struct regulator_desc arizona_ldo1_hc = { 124 .name = "LDO1", 125 .supply_name = "LDOVDD", 126 .type = REGULATOR_VOLTAGE, 127 .ops = &arizona_ldo1_hc_ops, 128 129 .bypass_reg = ARIZONA_LDO1_CONTROL_1, 130 .bypass_mask = ARIZONA_LDO1_BYPASS, 131 .min_uV = 900000, 132 .uV_step = 50000, 133 .n_voltages = 8, 134 .enable_time = 1500, 135 .ramp_delay = 24000, 136 137 .owner = THIS_MODULE, 138 }; 139 140 static const struct regulator_ops arizona_ldo1_ops = { 141 .list_voltage = regulator_list_voltage_linear, 142 .map_voltage = regulator_map_voltage_linear, 143 .get_voltage_sel = regulator_get_voltage_sel_regmap, 144 .set_voltage_sel = regulator_set_voltage_sel_regmap, 145 }; 146 147 static const struct regulator_desc arizona_ldo1 = { 148 .name = "LDO1", 149 .supply_name = "LDOVDD", 150 .type = REGULATOR_VOLTAGE, 151 .ops = &arizona_ldo1_ops, 152 153 .vsel_reg = ARIZONA_LDO1_CONTROL_1, 154 .vsel_mask = ARIZONA_LDO1_VSEL_MASK, 155 .min_uV = 900000, 156 .uV_step = 25000, 157 .n_voltages = 13, 158 .enable_time = 500, 159 .ramp_delay = 24000, 160 161 .owner = THIS_MODULE, 162 }; 163 164 static const struct regulator_init_data arizona_ldo1_dvfs = { 165 .constraints = { 166 .min_uV = 1200000, 167 .max_uV = 1800000, 168 .valid_ops_mask = REGULATOR_CHANGE_STATUS | 169 REGULATOR_CHANGE_VOLTAGE, 170 }, 171 .num_consumer_supplies = 1, 172 }; 173 174 static const struct regulator_init_data arizona_ldo1_default = { 175 .constraints = { 176 .valid_ops_mask = REGULATOR_CHANGE_STATUS, 177 }, 178 .num_consumer_supplies = 1, 179 }; 180 181 static const struct regulator_init_data arizona_ldo1_wm5110 = { 182 .constraints = { 183 .min_uV = 1175000, 184 .max_uV = 1200000, 185 .valid_ops_mask = REGULATOR_CHANGE_STATUS | 186 REGULATOR_CHANGE_VOLTAGE, 187 }, 188 .num_consumer_supplies = 1, 189 }; 190 191 static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata, 192 struct regulator_config *config, 193 const struct regulator_desc *desc, 194 bool *external_dcvdd) 195 { 196 struct arizona_ldo1 *ldo1 = config->driver_data; 197 struct device_node *np = config->dev->of_node; 198 struct device_node *init_node, *dcvdd_node; 199 struct regulator_init_data *init_data; 200 201 pdata->ldoena = of_get_named_gpio(np, "wlf,ldoena", 0); 202 if (pdata->ldoena < 0) { 203 dev_warn(config->dev, 204 "LDOENA GPIO property missing/malformed: %d\n", 205 pdata->ldoena); 206 pdata->ldoena = 0; 207 } else { 208 config->ena_gpio_initialized = true; 209 } 210 211 init_node = of_get_child_by_name(np, "ldo1"); 212 dcvdd_node = of_parse_phandle(np, "DCVDD-supply", 0); 213 214 if (init_node) { 215 config->of_node = init_node; 216 217 init_data = of_get_regulator_init_data(config->dev, init_node, 218 desc); 219 if (init_data) { 220 init_data->consumer_supplies = &ldo1->supply; 221 init_data->num_consumer_supplies = 1; 222 223 if (dcvdd_node && dcvdd_node != init_node) 224 *external_dcvdd = true; 225 226 pdata->init_data = init_data; 227 } 228 } else if (dcvdd_node) { 229 *external_dcvdd = true; 230 } 231 232 of_node_put(dcvdd_node); 233 234 return 0; 235 } 236 237 static int arizona_ldo1_common_init(struct platform_device *pdev, 238 struct arizona_ldo1 *ldo1, 239 const struct regulator_desc *desc, 240 struct arizona_ldo1_pdata *pdata, 241 bool *external_dcvdd) 242 { 243 struct device *parent_dev = pdev->dev.parent; 244 struct regulator_config config = { }; 245 int ret; 246 247 *external_dcvdd = false; 248 249 ldo1->supply.supply = "DCVDD"; 250 ldo1->init_data.consumer_supplies = &ldo1->supply; 251 ldo1->supply.dev_name = dev_name(parent_dev); 252 253 config.dev = parent_dev; 254 config.driver_data = ldo1; 255 config.regmap = ldo1->regmap; 256 257 if (IS_ENABLED(CONFIG_OF)) { 258 if (!dev_get_platdata(parent_dev)) { 259 ret = arizona_ldo1_of_get_pdata(pdata, 260 &config, desc, 261 external_dcvdd); 262 if (ret < 0) 263 return ret; 264 } 265 } 266 267 config.ena_gpio = pdata->ldoena; 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 ret = PTR_ERR(ldo1->regulator); 287 dev_err(&pdev->dev, "Failed to register LDO1 supply: %d\n", 288 ret); 289 return ret; 290 } 291 292 platform_set_drvdata(pdev, ldo1); 293 294 return 0; 295 } 296 297 static int arizona_ldo1_probe(struct platform_device *pdev) 298 { 299 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); 300 struct arizona_ldo1 *ldo1; 301 const struct regulator_desc *desc; 302 bool external_dcvdd; 303 int ret; 304 305 ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); 306 if (!ldo1) 307 return -ENOMEM; 308 309 ldo1->regmap = arizona->regmap; 310 311 /* 312 * Since the chip usually supplies itself we provide some 313 * default init_data for it. This will be overridden with 314 * platform data if provided. 315 */ 316 switch (arizona->type) { 317 case WM5102: 318 case WM8997: 319 case WM8998: 320 case WM1814: 321 desc = &arizona_ldo1_hc; 322 ldo1->init_data = arizona_ldo1_dvfs; 323 break; 324 case WM5110: 325 case WM8280: 326 desc = &arizona_ldo1; 327 ldo1->init_data = arizona_ldo1_wm5110; 328 break; 329 default: 330 desc = &arizona_ldo1; 331 ldo1->init_data = arizona_ldo1_default; 332 break; 333 } 334 335 ret = arizona_ldo1_common_init(pdev, ldo1, desc, 336 &arizona->pdata.ldo1, 337 &external_dcvdd); 338 if (ret == 0) 339 arizona->external_dcvdd = external_dcvdd; 340 341 return ret; 342 } 343 344 static struct platform_driver arizona_ldo1_driver = { 345 .probe = arizona_ldo1_probe, 346 .driver = { 347 .name = "arizona-ldo1", 348 }, 349 }; 350 351 module_platform_driver(arizona_ldo1_driver); 352 353 /* Module information */ 354 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 355 MODULE_DESCRIPTION("Arizona LDO1 driver"); 356 MODULE_LICENSE("GPL"); 357 MODULE_ALIAS("platform:arizona-ldo1"); 358