| .. | .. |
|---|
| 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 | | - */ |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 2 | +// |
|---|
| 3 | +// arizona-ldo1.c -- LDO1 supply for Arizona devices |
|---|
| 4 | +// |
|---|
| 5 | +// Copyright 2012 Wolfson Microelectronics PLC. |
|---|
| 6 | +// |
|---|
| 7 | +// Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
|---|
| 13 | 8 | |
|---|
| 14 | 9 | #include <linux/module.h> |
|---|
| 15 | 10 | #include <linux/moduleparam.h> |
|---|
| .. | .. |
|---|
| 30 | 25 | #include <linux/mfd/arizona/pdata.h> |
|---|
| 31 | 26 | #include <linux/mfd/arizona/registers.h> |
|---|
| 32 | 27 | |
|---|
| 28 | +#include <linux/mfd/madera/core.h> |
|---|
| 29 | +#include <linux/mfd/madera/pdata.h> |
|---|
| 30 | +#include <linux/mfd/madera/registers.h> |
|---|
| 31 | + |
|---|
| 33 | 32 | struct arizona_ldo1 { |
|---|
| 34 | 33 | struct regulator_dev *regulator; |
|---|
| 35 | 34 | struct regmap *regmap; |
|---|
| .. | .. |
|---|
| 40 | 39 | struct gpio_desc *ena_gpiod; |
|---|
| 41 | 40 | }; |
|---|
| 42 | 41 | |
|---|
| 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 | 42 | static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, |
|---|
| 68 | 43 | unsigned sel) |
|---|
| 69 | 44 | { |
|---|
| 70 | | - struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); |
|---|
| 71 | | - struct regmap *regmap = ldo->regmap; |
|---|
| 45 | + struct regmap *regmap = rdev_get_regmap(rdev); |
|---|
| 72 | 46 | unsigned int val; |
|---|
| 73 | 47 | int ret; |
|---|
| 74 | 48 | |
|---|
| .. | .. |
|---|
| 85 | 59 | if (val) |
|---|
| 86 | 60 | return 0; |
|---|
| 87 | 61 | |
|---|
| 88 | | - val = sel << ARIZONA_LDO1_VSEL_SHIFT; |
|---|
| 89 | | - |
|---|
| 90 | | - return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, |
|---|
| 91 | | - ARIZONA_LDO1_VSEL_MASK, val); |
|---|
| 62 | + return regulator_set_voltage_sel_regmap(rdev, sel); |
|---|
| 92 | 63 | } |
|---|
| 93 | 64 | |
|---|
| 94 | 65 | static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) |
|---|
| 95 | 66 | { |
|---|
| 96 | | - struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); |
|---|
| 97 | | - struct regmap *regmap = ldo->regmap; |
|---|
| 67 | + struct regmap *regmap = rdev_get_regmap(rdev); |
|---|
| 98 | 68 | unsigned int val; |
|---|
| 99 | 69 | int ret; |
|---|
| 100 | 70 | |
|---|
| .. | .. |
|---|
| 105 | 75 | if (val & ARIZONA_LDO1_HI_PWR) |
|---|
| 106 | 76 | return rdev->desc->n_voltages - 1; |
|---|
| 107 | 77 | |
|---|
| 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; |
|---|
| 78 | + return regulator_get_voltage_sel_regmap(rdev); |
|---|
| 113 | 79 | } |
|---|
| 114 | 80 | |
|---|
| 115 | 81 | 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, |
|---|
| 82 | + .list_voltage = regulator_list_voltage_linear_range, |
|---|
| 83 | + .map_voltage = regulator_map_voltage_linear_range, |
|---|
| 118 | 84 | .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, |
|---|
| 119 | 85 | .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, |
|---|
| 120 | 86 | .get_bypass = regulator_get_bypass_regmap, |
|---|
| 121 | 87 | .set_bypass = regulator_set_bypass_regmap, |
|---|
| 88 | +}; |
|---|
| 89 | + |
|---|
| 90 | +static const struct linear_range arizona_ldo1_hc_ranges[] = { |
|---|
| 91 | + REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000), |
|---|
| 92 | + REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0), |
|---|
| 122 | 93 | }; |
|---|
| 123 | 94 | |
|---|
| 124 | 95 | static const struct regulator_desc arizona_ldo1_hc = { |
|---|
| .. | .. |
|---|
| 127 | 98 | .type = REGULATOR_VOLTAGE, |
|---|
| 128 | 99 | .ops = &arizona_ldo1_hc_ops, |
|---|
| 129 | 100 | |
|---|
| 101 | + .vsel_reg = ARIZONA_LDO1_CONTROL_1, |
|---|
| 102 | + .vsel_mask = ARIZONA_LDO1_VSEL_MASK, |
|---|
| 130 | 103 | .bypass_reg = ARIZONA_LDO1_CONTROL_1, |
|---|
| 131 | 104 | .bypass_mask = ARIZONA_LDO1_BYPASS, |
|---|
| 132 | | - .min_uV = 900000, |
|---|
| 133 | | - .uV_step = 50000, |
|---|
| 105 | + .linear_ranges = arizona_ldo1_hc_ranges, |
|---|
| 106 | + .n_linear_ranges = ARRAY_SIZE(arizona_ldo1_hc_ranges), |
|---|
| 134 | 107 | .n_voltages = 8, |
|---|
| 135 | 108 | .enable_time = 1500, |
|---|
| 136 | 109 | .ramp_delay = 24000, |
|---|
| .. | .. |
|---|
| 185 | 158 | .max_uV = 1200000, |
|---|
| 186 | 159 | .valid_ops_mask = REGULATOR_CHANGE_STATUS | |
|---|
| 187 | 160 | REGULATOR_CHANGE_VOLTAGE, |
|---|
| 161 | + }, |
|---|
| 162 | + .num_consumer_supplies = 1, |
|---|
| 163 | +}; |
|---|
| 164 | + |
|---|
| 165 | +static const struct regulator_desc madera_ldo1 = { |
|---|
| 166 | + .name = "LDO1", |
|---|
| 167 | + .supply_name = "LDOVDD", |
|---|
| 168 | + .type = REGULATOR_VOLTAGE, |
|---|
| 169 | + .ops = &arizona_ldo1_ops, |
|---|
| 170 | + |
|---|
| 171 | + .vsel_reg = MADERA_LDO1_CONTROL_1, |
|---|
| 172 | + .vsel_mask = MADERA_LDO1_VSEL_MASK, |
|---|
| 173 | + .min_uV = 900000, |
|---|
| 174 | + .uV_step = 25000, |
|---|
| 175 | + .n_voltages = 13, |
|---|
| 176 | + .enable_time = 3000, |
|---|
| 177 | + |
|---|
| 178 | + .owner = THIS_MODULE, |
|---|
| 179 | +}; |
|---|
| 180 | + |
|---|
| 181 | +static const struct regulator_init_data madera_ldo1_default = { |
|---|
| 182 | + .constraints = { |
|---|
| 183 | + .min_uV = 1200000, |
|---|
| 184 | + .max_uV = 1200000, |
|---|
| 185 | + .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
|---|
| 188 | 186 | }, |
|---|
| 189 | 187 | .num_consumer_supplies = 1, |
|---|
| 190 | 188 | }; |
|---|
| .. | .. |
|---|
| 260 | 258 | * so clean up would happen at the wrong time |
|---|
| 261 | 259 | */ |
|---|
| 262 | 260 | config.ena_gpiod = gpiod_get_optional(parent_dev, "wlf,ldoena", |
|---|
| 263 | | - GPIOD_OUT_LOW); |
|---|
| 261 | + GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); |
|---|
| 264 | 262 | if (IS_ERR(config.ena_gpiod)) |
|---|
| 265 | 263 | return PTR_ERR(config.ena_gpiod); |
|---|
| 266 | 264 | |
|---|
| .. | .. |
|---|
| 283 | 281 | of_node_put(config.of_node); |
|---|
| 284 | 282 | |
|---|
| 285 | 283 | if (IS_ERR(ldo1->regulator)) { |
|---|
| 286 | | - if (config.ena_gpiod) |
|---|
| 287 | | - gpiod_put(config.ena_gpiod); |
|---|
| 288 | | - |
|---|
| 289 | 284 | ret = PTR_ERR(ldo1->regulator); |
|---|
| 290 | 285 | dev_err(&pdev->dev, "Failed to register LDO1 supply: %d\n", |
|---|
| 291 | 286 | ret); |
|---|
| .. | .. |
|---|
| 354 | 349 | return 0; |
|---|
| 355 | 350 | } |
|---|
| 356 | 351 | |
|---|
| 352 | +static int madera_ldo1_probe(struct platform_device *pdev) |
|---|
| 353 | +{ |
|---|
| 354 | + struct madera *madera = dev_get_drvdata(pdev->dev.parent); |
|---|
| 355 | + struct arizona_ldo1 *ldo1; |
|---|
| 356 | + bool external_dcvdd; |
|---|
| 357 | + int ret; |
|---|
| 358 | + |
|---|
| 359 | + ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); |
|---|
| 360 | + if (!ldo1) |
|---|
| 361 | + return -ENOMEM; |
|---|
| 362 | + |
|---|
| 363 | + ldo1->regmap = madera->regmap; |
|---|
| 364 | + |
|---|
| 365 | + ldo1->init_data = madera_ldo1_default; |
|---|
| 366 | + |
|---|
| 367 | + ret = arizona_ldo1_common_init(pdev, ldo1, &madera_ldo1, |
|---|
| 368 | + &madera->pdata.ldo1, |
|---|
| 369 | + &external_dcvdd); |
|---|
| 370 | + if (ret) |
|---|
| 371 | + return ret; |
|---|
| 372 | + |
|---|
| 373 | + madera->internal_dcvdd = !external_dcvdd; |
|---|
| 374 | + |
|---|
| 375 | + return 0; |
|---|
| 376 | +} |
|---|
| 377 | + |
|---|
| 357 | 378 | static struct platform_driver arizona_ldo1_driver = { |
|---|
| 358 | 379 | .probe = arizona_ldo1_probe, |
|---|
| 359 | 380 | .remove = arizona_ldo1_remove, |
|---|
| .. | .. |
|---|
| 362 | 383 | }, |
|---|
| 363 | 384 | }; |
|---|
| 364 | 385 | |
|---|
| 365 | | -module_platform_driver(arizona_ldo1_driver); |
|---|
| 386 | +static struct platform_driver madera_ldo1_driver = { |
|---|
| 387 | + .probe = madera_ldo1_probe, |
|---|
| 388 | + .remove = arizona_ldo1_remove, |
|---|
| 389 | + .driver = { |
|---|
| 390 | + .name = "madera-ldo1", |
|---|
| 391 | + }, |
|---|
| 392 | +}; |
|---|
| 393 | + |
|---|
| 394 | +static struct platform_driver * const madera_ldo1_drivers[] = { |
|---|
| 395 | + &arizona_ldo1_driver, |
|---|
| 396 | + &madera_ldo1_driver, |
|---|
| 397 | +}; |
|---|
| 398 | + |
|---|
| 399 | +static int __init arizona_ldo1_init(void) |
|---|
| 400 | +{ |
|---|
| 401 | + return platform_register_drivers(madera_ldo1_drivers, |
|---|
| 402 | + ARRAY_SIZE(madera_ldo1_drivers)); |
|---|
| 403 | +} |
|---|
| 404 | +module_init(arizona_ldo1_init); |
|---|
| 405 | + |
|---|
| 406 | +static void __exit madera_ldo1_exit(void) |
|---|
| 407 | +{ |
|---|
| 408 | + platform_unregister_drivers(madera_ldo1_drivers, |
|---|
| 409 | + ARRAY_SIZE(madera_ldo1_drivers)); |
|---|
| 410 | +} |
|---|
| 411 | +module_exit(madera_ldo1_exit); |
|---|
| 366 | 412 | |
|---|
| 367 | 413 | /* Module information */ |
|---|
| 368 | 414 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
|---|
| 369 | 415 | MODULE_DESCRIPTION("Arizona LDO1 driver"); |
|---|
| 370 | 416 | MODULE_LICENSE("GPL"); |
|---|
| 371 | 417 | MODULE_ALIAS("platform:arizona-ldo1"); |
|---|
| 418 | +MODULE_ALIAS("platform:madera-ldo1"); |
|---|