diff options
Diffstat (limited to 'drivers/regulator/arizona-ldo1.c')
| -rw-r--r-- | drivers/regulator/arizona-ldo1.c | 164 |
1 files changed, 107 insertions, 57 deletions
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index b9a93049e41e..501843996faa 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -1,15 +1,10 @@ -/* - * arizona-ldo1.c -- LDO1 supply for Arizona devices - * - * Copyright 2012 Wolfson Microelectronics PLC. - * - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// arizona-ldo1.c -- LDO1 supply for Arizona devices +// +// Copyright 2012 Wolfson Microelectronics PLC. +// +// Author: Mark Brown <broonie@opensource.wolfsonmicro.com> #include <linux/module.h> #include <linux/moduleparam.h> @@ -30,6 +25,10 @@ #include <linux/mfd/arizona/pdata.h> #include <linux/mfd/arizona/registers.h> +#include <linux/mfd/madera/core.h> +#include <linux/mfd/madera/pdata.h> +#include <linux/mfd/madera/registers.h> + struct arizona_ldo1 { struct regulator_dev *regulator; struct regmap *regmap; @@ -40,35 +39,10 @@ struct arizona_ldo1 { struct gpio_desc *ena_gpiod; }; -static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - - if (selector == rdev->desc->n_voltages - 1) - return 1800000; - else - return rdev->desc->min_uV + (rdev->desc->uV_step * selector); -} - -static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int sel; - - sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - if (sel >= rdev->desc->n_voltages) - sel = rdev->desc->n_voltages - 1; - - return sel; -} - static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { - struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); - struct regmap *regmap = ldo->regmap; + struct regmap *regmap = rdev_get_regmap(rdev); unsigned int val; int ret; @@ -85,16 +59,12 @@ static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, if (val) return 0; - val = sel << ARIZONA_LDO1_VSEL_SHIFT; - - return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, - ARIZONA_LDO1_VSEL_MASK, val); + return regulator_set_voltage_sel_regmap(rdev, sel); } static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) { - struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); - struct regmap *regmap = ldo->regmap; + struct regmap *regmap = rdev_get_regmap(rdev); unsigned int val; int ret; @@ -105,32 +75,35 @@ static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) if (val & ARIZONA_LDO1_HI_PWR) return rdev->desc->n_voltages - 1; - ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val); - if (ret != 0) - return ret; - - return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT; + return regulator_get_voltage_sel_regmap(rdev); } static const struct regulator_ops arizona_ldo1_hc_ops = { - .list_voltage = arizona_ldo1_hc_list_voltage, - .map_voltage = arizona_ldo1_hc_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, }; +static const struct linear_range arizona_ldo1_hc_ranges[] = { + REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000), + REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0), +}; + static const struct regulator_desc arizona_ldo1_hc = { .name = "LDO1", .supply_name = "LDOVDD", .type = REGULATOR_VOLTAGE, .ops = &arizona_ldo1_hc_ops, + .vsel_reg = ARIZONA_LDO1_CONTROL_1, + .vsel_mask = ARIZONA_LDO1_VSEL_MASK, .bypass_reg = ARIZONA_LDO1_CONTROL_1, .bypass_mask = ARIZONA_LDO1_BYPASS, - .min_uV = 900000, - .uV_step = 50000, + .linear_ranges = arizona_ldo1_hc_ranges, + .n_linear_ranges = ARRAY_SIZE(arizona_ldo1_hc_ranges), .n_voltages = 8, .enable_time = 1500, .ramp_delay = 24000, @@ -189,6 +162,31 @@ static const struct regulator_init_data arizona_ldo1_wm5110 = { .num_consumer_supplies = 1, }; +static const struct regulator_desc madera_ldo1 = { + .name = "LDO1", + .supply_name = "LDOVDD", + .type = REGULATOR_VOLTAGE, + .ops = &arizona_ldo1_ops, + + .vsel_reg = MADERA_LDO1_CONTROL_1, + .vsel_mask = MADERA_LDO1_VSEL_MASK, + .min_uV = 900000, + .uV_step = 25000, + .n_voltages = 13, + .enable_time = 3000, + + .owner = THIS_MODULE, +}; + +static const struct regulator_init_data madera_ldo1_default = { + .constraints = { + .min_uV = 1200000, + .max_uV = 1200000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, +}; + static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata, struct regulator_config *config, const struct regulator_desc *desc, @@ -341,12 +339,36 @@ static int arizona_ldo1_probe(struct platform_device *pdev) return ret; } -static int arizona_ldo1_remove(struct platform_device *pdev) +static void arizona_ldo1_remove(struct platform_device *pdev) { struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev); if (ldo1->ena_gpiod) gpiod_put(ldo1->ena_gpiod); +} + +static int madera_ldo1_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct arizona_ldo1 *ldo1; + bool external_dcvdd; + int ret; + + ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); + if (!ldo1) + return -ENOMEM; + + ldo1->regmap = madera->regmap; + + ldo1->init_data = madera_ldo1_default; + + ret = arizona_ldo1_common_init(pdev, ldo1, &madera_ldo1, + &madera->pdata.ldo1, + &external_dcvdd); + if (ret) + return ret; + + madera->internal_dcvdd = !external_dcvdd; return 0; } @@ -354,15 +376,43 @@ static int arizona_ldo1_remove(struct platform_device *pdev) static struct platform_driver arizona_ldo1_driver = { .probe = arizona_ldo1_probe, .remove = arizona_ldo1_remove, - .driver = { - .name = "arizona-ldo1", + .driver = { + .name = "arizona-ldo1", + .probe_type = PROBE_FORCE_SYNCHRONOUS, + }, +}; + +static struct platform_driver madera_ldo1_driver = { + .probe = madera_ldo1_probe, + .remove = arizona_ldo1_remove, + .driver = { + .name = "madera-ldo1", + .probe_type = PROBE_FORCE_SYNCHRONOUS, }, }; -module_platform_driver(arizona_ldo1_driver); +static struct platform_driver * const madera_ldo1_drivers[] = { + &arizona_ldo1_driver, + &madera_ldo1_driver, +}; + +static int __init arizona_ldo1_init(void) +{ + return platform_register_drivers(madera_ldo1_drivers, + ARRAY_SIZE(madera_ldo1_drivers)); +} +module_init(arizona_ldo1_init); + +static void __exit madera_ldo1_exit(void) +{ + platform_unregister_drivers(madera_ldo1_drivers, + ARRAY_SIZE(madera_ldo1_drivers)); +} +module_exit(madera_ldo1_exit); /* Module information */ MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_DESCRIPTION("Arizona LDO1 driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:arizona-ldo1"); +MODULE_ALIAS("platform:madera-ldo1"); |
