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