diff options
Diffstat (limited to 'drivers/regulator')
65 files changed, 3259 insertions, 306 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 1c5ab0172ea..2b557119ada 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev, #define pm8607_regulator_dt_init(x, y, z) (-1) #endif -static int __devinit pm8607_regulator_probe(struct platform_device *pdev) +static int pm8607_regulator_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm8607_regulator_info *info = NULL; @@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit pm8607_regulator_remove(struct platform_device *pdev) +static int pm8607_regulator_remove(struct platform_device *pdev) { struct pm8607_regulator_info *info = platform_get_drvdata(pdev); @@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = { .owner = THIS_MODULE, }, .probe = pm8607_regulator_probe, - .remove = __devexit_p(pm8607_regulator_remove), + .remove = pm8607_regulator_remove, .id_table = pm8607_regulator_driver_ids, }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 67d47b59a66..e5ce11847be 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -109,6 +109,16 @@ config REGULATOR_DA9052 This driver supports the voltage regulators of DA9052-BC and DA9053-AA/Bx PMIC. +config REGULATOR_DA9055 + tristate "Dialog Semiconductor DA9055 regulators" + depends on MFD_DA9055 + help + Say y here to support the BUCKs and LDOs regulators found on + Dialog Semiconductor DA9055 PMIC. + + This driver can also be built as a module. If so, the module + will be called da9055-regulator. + config REGULATOR_FAN53555 tristate "Fairchild FAN53555 Regulator" depends on I2C @@ -335,6 +345,17 @@ config REGULATOR_PALMAS on the muxing. This is handled automatically in the driver by reading the mux info from OTP. +config REGULATOR_TPS51632 + tristate "TI TPS51632 Power Regulator" + depends on I2C + select REGMAP_I2C + help + This driver supports TPS51632 voltage regulator chip. + The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller + with Serial VID control and DVFS. + The voltage output can be configure through I2C interface or PWM + interface. + config REGULATOR_TPS6105X tristate "TI TPS6105X Power regulators" depends on TPS6105X @@ -415,6 +436,15 @@ config REGULATOR_TPS65912 help This driver supports TPS65912 voltage regulator chip. +config REGULATOR_TPS80031 + tristate "TI TPS80031/TPS80032 power regualtor driver" + depends on MFD_TPS80031 + help + TPS80031/ TPS80032 Fully Integrated Power Management with Power + Path and Battery Charger. It has 5 configurable step-down + converters, 11 general purpose LDOs, VBUS generator and digital + output to control regulators. + config REGULATOR_TWL4030 bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC" depends on TWL4030_CORE @@ -422,6 +452,13 @@ config REGULATOR_TWL4030 This driver supports the voltage regulators provided by this family of companion chips. +config REGULATOR_VEXPRESS + tristate "Versatile Express regulators" + depends on VEXPRESS_CONFIG + help + This driver provides support for voltage regulators available + on the ARM Ltd's Versatile Express platform. + config REGULATOR_WM831X tristate "Wolfson Microelectronics WM831x PMIC regulators" depends on MFD_WM831X @@ -450,5 +487,12 @@ config REGULATOR_WM8994 This driver provides support for the voltage regulators on the WM8994 CODEC. +config REGULATOR_AS3711 + tristate "AS3711 PMIC" + depends on MFD_AS3711 + help + This driver provides support for the voltage regulators on the + AS3711 PMIC + endif diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index e431eed8a87..73bfb873d4b 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o +obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o +obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o @@ -41,6 +43,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o +obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o @@ -56,7 +59,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o +obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o +obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 167c93f2198..8b5876356db 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit aat2870_regulator_remove(struct platform_device *pdev) +static int aat2870_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = { .owner = THIS_MODULE, }, .probe = aat2870_regulator_probe, - .remove = __devexit_p(aat2870_regulator_remove), + .remove = aat2870_regulator_remove, }; static int __init aat2870_regulator_init(void) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index df4ad8927f0..111ec69a3e9 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { * for all the different regulators. */ -static int __devinit ab3100_regulators_probe(struct platform_device *pdev) +static int ab3100_regulators_probe(struct platform_device *pdev) { struct ab3100_platform_data *plfdata = pdev->dev.platform_data; struct regulator_config config = { }; @@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) return 0; } -static int __devexit ab3100_regulators_remove(struct platform_device *pdev) +static int ab3100_regulators_remove(struct platform_device *pdev) { int i; @@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = { .owner = THIS_MODULE, }, .probe = ab3100_regulators_probe, - .remove = __devexit_p(ab3100_regulators_remove), + .remove = ab3100_regulators_remove, }; static __init int ab3100_regulators_init(void) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index e3d1d063025..09014f38a94 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), }; -static __devinit int +static int ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value) { int err; @@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value) return 0; } -static __devinit int ab8500_regulator_register(struct platform_device *pdev, +static int ab8500_regulator_register(struct platform_device *pdev, struct regulator_init_data *init_data, int id, struct device_node *np) @@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, }, }; -static __devinit int +static int ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) { int err, i; @@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) return 0; } -static __devinit int ab8500_regulator_probe(struct platform_device *pdev) +static int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_platform_data *pdata; @@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) return 0; } -static __devexit int ab8500_regulator_remove(struct platform_device *pdev) +static int ab8500_regulator_remove(struct platform_device *pdev) { int i; @@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev) static struct platform_driver ab8500_regulator_driver = { .probe = ab8500_regulator_probe, - .remove = __devexit_p(ab8500_regulator_remove), + .remove = ab8500_regulator_remove, .driver = { .name = "ab8500-regulator", .owner = THIS_MODULE, diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index f123f7e3b75..6b981b5faa7 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = { }; MODULE_DEVICE_TABLE(i2c, ad5398_id); -static int __devinit ad5398_probe(struct i2c_client *client, +static int ad5398_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct regulator_init_data *init_data = client->dev.platform_data; @@ -256,7 +256,7 @@ err: return ret; } -static int __devexit ad5398_remove(struct i2c_client *client) +static int ad5398_remove(struct i2c_client *client) { struct ad5398_chip_info *chip = i2c_get_clientdata(client); @@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client) static struct i2c_driver ad5398_driver = { .probe = ad5398_probe, - .remove = __devexit_p(ad5398_remove), + .remove = ad5398_remove, .driver = { .name = "ad5398", }, diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 1af97686f44..1aa5246c79d 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -87,7 +87,7 @@ static struct regulator_ops anatop_rops = { .map_voltage = regulator_map_voltage_linear, }; -static int __devinit anatop_regulator_probe(struct platform_device *pdev) +static int anatop_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -186,7 +186,7 @@ anatop_probe_end: return ret; } -static int __devexit anatop_regulator_remove(struct platform_device *pdev) +static int anatop_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); struct anatop_regulator *sreg = rdev_get_drvdata(rdev); @@ -210,7 +210,7 @@ static struct platform_driver anatop_regulator_driver = { .of_match_table = of_anatop_regulator_match_tbl, }, .probe = anatop_regulator_probe, - .remove = __devexit_p(anatop_regulator_remove), + .remove = anatop_regulator_remove, }; static int __init anatop_regulator_init(void) diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index d184aa35abc..ed7beec53af 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -34,6 +34,108 @@ struct arizona_ldo1 { struct regulator_init_data init_data; }; +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->arizona->regmap; + unsigned int val; + int ret; + + if (sel == rdev->desc->n_voltages - 1) + val = ARIZONA_LDO1_HI_PWR; + else + val = 0; + + ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2, + ARIZONA_LDO1_HI_PWR, val); + if (ret != 0) + return ret; + + ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1, + ARIZONA_SUBSYS_MAX_FREQ, val); + if (ret != 0) + return ret; + + if (val) + return 0; + + val = sel << ARIZONA_LDO1_VSEL_SHIFT; + + return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, + ARIZONA_LDO1_VSEL_MASK, val); +} + +static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) +{ + struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); + struct regmap *regmap = ldo->arizona->regmap; + unsigned int val; + int ret; + + ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val); + if (ret != 0) + return ret; + + 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; +} + +static struct regulator_ops arizona_ldo1_hc_ops = { + .list_voltage = arizona_ldo1_hc_list_voltage, + .map_voltage = arizona_ldo1_hc_map_voltage, + .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 regulator_desc arizona_ldo1_hc = { + .name = "LDO1", + .supply_name = "LDOVDD", + .type = REGULATOR_VOLTAGE, + .ops = &arizona_ldo1_hc_ops, + + .bypass_reg = ARIZONA_LDO1_CONTROL_1, + .bypass_mask = ARIZONA_LDO1_BYPASS, + .min_uV = 900000, + .uV_step = 50000, + .n_voltages = 8, + .enable_time = 500, + + .owner = THIS_MODULE, +}; + static struct regulator_ops arizona_ldo1_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = { .bypass_mask = ARIZONA_LDO1_BYPASS, .min_uV = 900000, .uV_step = 50000, - .n_voltages = 6, + .n_voltages = 7, + .enable_time = 500, .owner = THIS_MODULE, }; +static const struct regulator_init_data arizona_ldo1_dvfs = { + .constraints = { + .min_uV = 1200000, + .max_uV = 1800000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_VOLTAGE, + }, + .num_consumer_supplies = 1, +}; + static const struct regulator_init_data arizona_ldo1_default = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, @@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = { .num_consumer_supplies = 1, }; -static __devinit int arizona_ldo1_probe(struct platform_device *pdev) +static int arizona_ldo1_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + const struct regulator_desc *desc; struct regulator_config config = { }; struct arizona_ldo1 *ldo1; int ret; @@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev) * default init_data for it. This will be overridden with * platform data if provided. */ - ldo1->init_data = arizona_ldo1_default; + switch (arizona->type) { + case WM5102: + desc = &arizona_ldo1_hc; + ldo1->init_data = arizona_ldo1_dvfs; + break; + default: + desc = &arizona_ldo1; + ldo1->init_data = arizona_ldo1_default; + break; + } + ldo1->init_data.consumer_supplies = &ldo1->supply; ldo1->supply.supply = "DCVDD"; ldo1->supply.dev_name = dev_name(arizona->dev); @@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev) else config.init_data = &ldo1->init_data; - ldo1->regulator = regulator_register(&arizona_ldo1, &config); + ldo1->regulator = regulator_register(desc, &config); if (IS_ERR(ldo1->regulator)) { ret = PTR_ERR(ldo1->regulator); dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n", @@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev) return 0; } -static __devexit int arizona_ldo1_remove(struct platform_device *pdev) +static int arizona_ldo1_remove(struct platform_device *pdev) { struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev); @@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev) static struct platform_driver arizona_ldo1_driver = { .probe = arizona_ldo1_probe, - .remove = __devexit_p(arizona_ldo1_remove), + .remove = arizona_ldo1_remove, .driver = { .name = "arizona-ldo1", .owner = THIS_MODULE, diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index d9b1f82cc5b..a6d040cbf8a 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = { .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, .bypass_mask = ARIZONA_CPMIC_BYPASS, + .enable_time = 3000, + .owner = THIS_MODULE, }; @@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = { .num_consumer_supplies = 1, }; -static __devinit int arizona_micsupp_probe(struct platform_device *pdev) +static int arizona_micsupp_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; @@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev) return 0; } -static __devexit int arizona_micsupp_remove(struct platform_device *pdev) +static int arizona_micsupp_remove(struct platform_device *pdev) { struct arizona_micsupp *micsupp = platform_get_drvdata(pdev); @@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev) static struct platform_driver arizona_micsupp_driver = { .probe = arizona_micsupp_probe, - .remove = __devexit_p(arizona_micsupp_remove), + .remove = arizona_micsupp_remove, .driver = { .name = "arizona-micsupp", .owner = THIS_MODULE, diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c new file mode 100644 index 00000000000..2f1341db38a --- /dev/null +++ b/drivers/regulator/as3711-regulator.c @@ -0,0 +1,369 @@ +/* + * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies + * + * Copyright (C) 2012 Renesas Electronics Corporation + * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License as + * published by the Free Software Foundation + */ + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/mfd/as3711.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/slab.h> + +struct as3711_regulator_info { + struct regulator_desc desc; + unsigned int max_uV; +}; + +struct as3711_regulator { + struct as3711_regulator_info *reg_info; + struct regulator_dev *rdev; +}; + +static int as3711_list_voltage_sd(struct regulator_dev *rdev, + unsigned int selector) +{ + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + + if (!selector) + return 0; + if (selector < 0x41) + return 600000 + selector * 12500; + if (selector < 0x71) + return 1400000 + (selector - 0x40) * 25000; + return 2600000 + (selector - 0x70) * 50000; +} + +static int as3711_list_voltage_aldo(struct regulator_dev *rdev, + unsigned int selector) +{ + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + + if (selector < 0x10) + return 1200000 + selector * 50000; + return 1800000 + (selector - 0x10) * 100000; +} + +static int as3711_list_voltage_dldo(struct regulator_dev *rdev, + unsigned int selector) +{ + if (selector >= rdev->desc->n_voltages || + (selector > 0x10 && selector < 0x20)) + return -EINVAL; + + if (selector < 0x11) + return 900000 + selector * 50000; + return 1750000 + (selector - 0x20) * 50000; +} + +static int as3711_bound_check(struct regulator_dev *rdev, + int *min_uV, int *max_uV) +{ + struct as3711_regulator *reg = rdev_get_drvdata(rdev); + struct as3711_regulator_info *info = reg->reg_info; + + dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__, + *min_uV, rdev->desc->min_uV, info->max_uV); + + if (*max_uV < *min_uV || + *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV) + return -EINVAL; + + if (rdev->desc->n_voltages == 1) + return 0; + + if (*max_uV > info->max_uV) + *max_uV = info->max_uV; + + if (*min_uV < rdev->desc->min_uV) + *min_uV = rdev->desc->min_uV; + + return *min_uV; +} + +static int as3711_sel_check(int min, int max, int bottom, int step) +{ + int sel, voltage; + + /* Round up min, when dividing: keeps us within the range */ + sel = DIV_ROUND_UP(min - bottom, step); + voltage = sel * step + bottom; + pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__, + min, max, bottom, step, sel); + if (voltage > max) + return -EINVAL; + + return sel; +} + +static int as3711_map_voltage_sd(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret; + + ret = as3711_bound_check(rdev, &min_uV, &max_uV); + if (ret <= 0) + return ret; + + if (min_uV <= 1400000) + return as3711_sel_check(min_uV, max_uV, 600000, 12500); + + if (min_uV <= 2600000) + return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40; + + return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70; +} + +/* + * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and + * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: + * FAST: sdX_fast=1 + * NORMAL: low_noise=1 + * IDLE: low_noise=0 + */ + +static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode) +{ + unsigned int fast_bit = rdev->desc->enable_mask, + low_noise_bit = fast_bit << 4; + u8 val; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = fast_bit | low_noise_bit; + break; + case REGULATOR_MODE_NORMAL: + val = low_noise_bit; + break; + case REGULATOR_MODE_IDLE: + val = 0; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1, + low_noise_bit | fast_bit, val); +} + +static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev) +{ + unsigned int fast_bit = rdev->desc->enable_mask, + low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit; + unsigned int val; + int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val); + + if (ret < 0) + return ret; + + if ((val & mask) == mask) + return REGULATOR_MODE_FAST; + + if ((val & mask) == low_noise_bit) + return REGULATOR_MODE_NORMAL; + + if (!(val & mask)) + return REGULATOR_MODE_IDLE; + + return -EINVAL; +} + +static int as3711_map_voltage_aldo(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret; + + ret = as3711_bound_check(rdev, &min_uV, &max_uV); + if (ret <= 0) + return ret; + + if (min_uV <= 1800000) + return as3711_sel_check(min_uV, max_uV, 1200000, 50000); + + return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10; +} + +static int as3711_map_voltage_dldo(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int ret; + + ret = as3711_bound_check(rdev, &min_uV, &max_uV); + if (ret <= 0) + return ret; + + if (min_uV <= 1700000) + return as3711_sel_check(min_uV, max_uV, 900000, 50000); + + return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20; +} + +static struct regulator_ops as3711_sd_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = as3711_list_voltage_sd, + .map_voltage = as3711_map_voltage_sd, + .get_mode = as3711_get_mode_sd, + .set_mode = as3711_set_mode_sd, +}; + +static struct regulator_ops as3711_aldo_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = as3711_list_voltage_aldo, + .map_voltage = as3711_map_voltage_aldo, +}; + +static struct regulator_ops as3711_dldo_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = as3711_list_voltage_dldo, + .map_voltage = as3711_map_voltage_dldo, +}; + +#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ + [AS3711_REGULATOR_ ## _id] = { \ + .desc = { \ + .name = "as3711-regulator-" # _id, \ + .id = AS3711_REGULATOR_ ## _id, \ + .n_voltages = (_vmask + 1), \ + .ops = &as3711_ ## _sfx ## _ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \ + .vsel_mask = _vmask << _vshift, \ + .enable_reg = AS3711_ ## _en_reg, \ + .enable_mask = BIT(_en_bit), \ + .min_uV = _min_uV, \ + }, \ + .max_uV = _max_uV, \ +} + +static struct as3711_regulator_info as3711_reg_info[] = { + AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd), + AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd), + AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd), + AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd), + AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), + AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), + AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + /* StepUp output voltage depends on supplying regulator */ +}; + +#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info) + +static int as3711_regulator_probe(struct platform_device *pdev) +{ + struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev); + struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); + struct regulator_init_data *reg_data; + struct regulator_config config = {.dev = &pdev->dev,}; + struct as3711_regulator *reg = NULL; + struct as3711_regulator *regs; + struct regulator_dev *rdev; + struct as3711_regulator_info *ri; + int ret; + int id; + + if (!pdata) + dev_dbg(&pdev->dev, "No platform data...\n"); + + regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM * + sizeof(struct as3711_regulator), GFP_KERNEL); + if (!regs) { + dev_err(&pdev->dev, "Memory allocation failed exiting..\n"); + return -ENOMEM; + } + + for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) { + reg_data = pdata ? pdata->init_data[id] : NULL; + + /* No need to register if there is no regulator data */ + if (!ri->desc.name) + continue; + + reg = ®s[id]; + reg->reg_info = ri; + + config.init_data = reg_data; + config.driver_data = reg; + config.regmap = as3711->regmap; + + rdev = regulator_register(&ri->desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register regulator %s\n", + ri->desc.name); + ret = PTR_ERR(rdev); + goto eregreg; + } + reg->rdev = rdev; + } + platform_set_drvdata(pdev, regs); + return 0; + +eregreg: + while (--id >= 0) + regulator_unregister(regs[id].rdev); + + return ret; +} + +static int as3711_regulator_remove(struct platform_device *pdev) +{ + struct as3711_regulator *regs = platform_get_drvdata(pdev); + int id; + + for (id = 0; id < AS3711_REGULATOR_NUM; ++id) + regulator_unregister(regs[id].rdev); + return 0; +} + +static struct platform_driver as3711_regulator_driver = { + .driver = { + .name = "as3711-regulator", + .owner = THIS_MODULE, + }, + .probe = as3711_regulator_probe, + .remove = as3711_regulator_remove, +}; + +static int __init as3711_regulator_init(void) +{ + return platform_driver_register(&as3711_regulator_driver); +} +subsys_initcall(as3711_regulator_init); + +static void __exit as3711_regulator_exit(void) +{ + platform_driver_unregister(&as3711_regulator_driver); +} +module_exit(as3711_regulator_exit); + +MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); +MODULE_DESCRIPTION("AS3711 regulator driver"); +MODULE_ALIAS("platform:as3711-regulator"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a..35c149bb2ad 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev, *min_uV = regulator->min_uV; } - if (*min_uV > *max_uV) + if (*min_uV > *max_uV) { + dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n", + regulator->min_uV, regulator->max_uV); return -EINVAL; + } return 0; } @@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, /* final: [min_uV..max_uV] valid iff constraints valid */ if (max_uV < min_uV) { - rdev_err(rdev, "unsupportable voltage constraints\n"); + rdev_err(rdev, + "unsupportable voltage constraints %u-%uuV\n", + min_uV, max_uV); return -EINVAL; } @@ -1381,22 +1386,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) } EXPORT_SYMBOL_GPL(regulator_get_exclusive); -/** - * regulator_put - "free" the regulator source - * @regulator: regulator source - * - * Note: drivers must ensure that all regulator_enable calls made on this - * regulator source are balanced by regulator_disable calls prior to calling - * this function. - */ -void regulator_put(struct regulator *regulator) +/* Locks held by regulator_put() */ +static void _regulator_put(struct regulator *regulator) { struct regulator_dev *rdev; if (regulator == NULL || IS_ERR(regulator)) return; - mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; debugfs_remove_recursive(regulator->debugfs); @@ -1412,6 +1409,20 @@ void regulator_put(struct regulator *regulator) rdev->exclusive = 0; module_put(rdev->owner); +} + +/** + * regulator_put - "free" the regulator source + * @regulator: regulator source + * + * Note: drivers must ensure that all regulator_enable calls made on this + * regulator source are balanced by regulator_disable calls prior to calling + * this function. + */ +void regulator_put(struct regulator *regulator) +{ + mutex_lock(®ulator_list_mutex); + _regulator_put(regulator); mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_put); @@ -1861,6 +1872,28 @@ int regulator_is_enabled(struct regulator *regulator) EXPORT_SYMBOL_GPL(regulator_is_enabled); /** + * regulator_can_change_voltage - check if regulator can change voltage + * @regulator: regulator source + * + * Returns positive if the regulator driver backing the source/client + * can change its voltage, false otherwise. Usefull for detecting fixed + * or dummy regulators and disabling voltage change logic in the client + * driver. + */ +int regulator_can_change_voltage(struct regulator *regulator) +{ + struct regulator_dev *rdev = regulator->rdev; + + if (rdev->constraints && + rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE && + rdev->desc->n_voltages > 1) + return 1; + + return 0; +} +EXPORT_SYMBOL_GPL(regulator_can_change_voltage); + +/** * regulator_count_voltages - count regulator_list_voltage() selectors * @regulator: regulator source * @@ -1974,11 +2007,16 @@ int regulator_is_supported_voltage(struct regulator *regulator, if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) - return (min_uV >= ret && ret <= max_uV); + return (min_uV <= ret && ret <= max_uV); else return ret; } + /* Any voltage within constrains range is fine? */ + if (rdev->desc->continuous_voltage_range) + return min_uV >= rdev->constraints->min_uV && + max_uV <= rdev->constraints->max_uV; + ret = regulator_count_voltages(regulator); if (ret < 0) return ret; @@ -3365,7 +3403,7 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", config->ena_gpio, ret); - goto clean; + goto wash; } rdev->ena_gpio = config->ena_gpio; @@ -3445,10 +3483,11 @@ unset_supplies: scrub: if (rdev->supply) - regulator_put(rdev->supply); + _regulator_put(rdev->supply); if (rdev->ena_gpio) gpio_free(rdev->ena_gpio); kfree(rdev->constraints); +wash: device_unregister(&rdev->dev); /* device core frees rdev */ rdev = ERR_PTR(ret); diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 36c5b92fe0a..2afa5730f32 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id) return NULL; } -static int __devinit da903x_regulator_probe(struct platform_device *pdev) +static int da903x_regulator_probe(struct platform_device *pdev) { struct da903x_regulator_info *ri = NULL; struct regulator_dev *rdev; @@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit da903x_regulator_remove(struct platform_device *pdev) +static int da903x_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = { .owner = THIS_MODULE, }, .probe = da903x_regulator_probe, - .remove = __devexit_p(da903x_regulator_remove), + .remove = da903x_regulator_remove, }; static int __init da903x_regulator_init(void) diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 27355b1199e..d0963090442 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, else if (offset == 0) row = 1; - if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] || - max_uA < da9052_current_limits[row][DA9052_MIN_UA]) - return -EINVAL; - for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) { - if (da9052_current_limits[row][i] <= max_uA) { + if ((min_uA <= da9052_current_limits[row][i]) && + (da9052_current_limits[row][i] <= max_uA)) { reg_val = i; break; } } + if (i < 0) + return -EINVAL; + /* Determine the even or odd position of the buck current limit * register field */ @@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, return NULL; } -static int __devinit da9052_regulator_probe(struct platform_device *pdev) +static int da9052_regulator_probe(struct platform_device *pdev) { struct regulator_config config = { }; struct da9052_regulator *regulator; @@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit da9052_regulator_remove(struct platform_device *pdev) +static int da9052_regulator_remove(struct platform_device *pdev) { struct da9052_regulator *regulator = platform_get_drvdata(pdev); @@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev) static struct platform_driver da9052_regulator_driver = { .probe = da9052_regulator_probe, - .remove = __devexit_p(da9052_regulator_remove), + .remove = da9052_regulator_remove, .driver = { .name = "da9052-regulator", .owner = THIS_MODULE, diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c new file mode 100644 index 00000000000..db59ce7534c --- /dev/null +++ b/drivers/regulator/da9055-regulator.c @@ -0,0 +1,680 @@ +/* +* Regulator driver for DA9055 PMIC +* +* Copyright(c) 2012 Dialog Semiconductor Ltd. +* +* Author: David Dajun Chen <dchen@diasemi.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. +* +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> + +#include <linux/mfd/da9055/core.h> +#include <linux/mfd/da9055/reg.h> +#include <linux/mfd/da9055/pdata.h> + +#define DA9055_MIN_UA 0 +#define DA9055_MAX_UA 3 + +#define DA9055_LDO_MODE_SYNC 0 +#define DA9055_LDO_MODE_SLEEP 1 + +#define DA9055_BUCK_MODE_SLEEP 1 +#define DA9055_BUCK_MODE_SYNC 2 +#define DA9055_BUCK_MODE_AUTO 3 + +/* DA9055 REGULATOR IDs */ +#define DA9055_ID_BUCK1 0 +#define DA9055_ID_BUCK2 1 +#define DA9055_ID_LDO1 2 +#define DA9055_ID_LDO2 3 +#define DA9055_ID_LDO3 4 +#define DA9055_ID_LDO4 5 +#define DA9055_ID_LDO5 6 +#define DA9055_ID_LDO6 7 + +/* DA9055 BUCK current limit */ +static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 }; + +struct da9055_conf_reg { + int reg; + int sel_mask; + int en_mask; +}; + +struct da9055_volt_reg { + int reg_a; + int reg_b; + int sl_shift; + int v_offset; + int v_mask; + int v_shift; +}; + +struct da9055_mode_reg { + int reg; + int mask; + int shift; +}; + +struct da9055_regulator_info { + struct regulator_desc reg_desc; + struct da9055_conf_reg conf; + struct da9055_volt_reg volt; + struct da9055_mode_reg mode; +}; + +struct da9055_regulator { + struct da9055 *da9055; + struct da9055_regulator_info *info; + struct regulator_dev *rdev; + enum gpio_select reg_rselect; +}; + +static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int ret, mode = 0; + + ret = da9055_reg_read(regulator->da9055, info->mode.reg); + if (ret < 0) + return ret; + + switch ((ret & info->mode.mask) >> info->mode.shift) { + case DA9055_BUCK_MODE_SYNC: + mode = REGULATOR_MODE_FAST; + break; + case DA9055_BUCK_MODE_AUTO: + mode = REGULATOR_MODE_NORMAL; + break; + case DA9055_BUCK_MODE_SLEEP: + mode = REGULATOR_MODE_STANDBY; + break; + } + + return mode; +} + +static int da9055_buck_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int val = 0; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = DA9055_BUCK_MODE_SYNC << info->mode.shift; + break; + case REGULATOR_MODE_NORMAL: + val = DA9055_BUCK_MODE_AUTO << info->mode.shift; + break; + case REGULATOR_MODE_STANDBY: + val = DA9055_BUCK_MODE_SLEEP << info->mode.shift; + break; + } + + return da9055_reg_update(regulator->da9055, info->mode.reg, + info->mode.mask, val); +} + +static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int ret; + + ret = da9055_reg_read(regulator->da9055, info->volt.reg_b); + if (ret < 0) + return ret; + + if (ret >> info->volt.sl_shift) + return REGULATOR_MODE_STANDBY; + else + return REGULATOR_MODE_NORMAL; +} + +static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + struct da9055_volt_reg volt = info->volt; + int val = 0; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + case REGULATOR_MODE_FAST: + val = DA9055_LDO_MODE_SYNC; + break; + case REGULATOR_MODE_STANDBY: + val = DA9055_LDO_MODE_SLEEP; + break; + } + + return da9055_reg_update(regulator->da9055, volt.reg_b, + 1 << volt.sl_shift, + val << volt.sl_shift); +} + +static int da9055_buck_get_current_limit(struct regulator_dev *rdev) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int ret; + + ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM); + if (ret < 0) + return ret; + + ret &= info->mode.mask; + return da9055_current_limits[ret >> info->mode.shift]; +} + +static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA, + int max_uA) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int i; + + for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) { + if ((min_uA <= da9055_current_limits[i]) && + (da9055_current_limits[i] <= max_uA)) + return da9055_reg_update(regulator->da9055, + DA9055_REG_BUCK_LIM, + info->mode.mask, + i << info->mode.shift); + } + + return -EINVAL; +} + +static int da9055_list_voltage(struct regulator_dev *rdev, unsigned selector) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + + if (selector < info->volt.v_offset) + return 0; + + selector -= info->volt.v_offset; + return rdev->desc->min_uV + (rdev->desc->uV_step * selector); +} + +static int da9055_map_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int sel, voltage; + + if (min_uV < rdev->desc->min_uV) + min_uV = rdev->desc->min_uV; + + sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); + sel += info->volt.v_offset; + + voltage = da9055_list_voltage(rdev, sel); + if (voltage < min_uV || voltage > max_uV) + return -EINVAL; + + return sel; +} + +static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + struct da9055_volt_reg volt = info->volt; + int ret, sel; + + /* + * There are two voltage register set A & B for voltage ramping but + * either one of then can be active therefore we first determine + * the active register set. + */ + ret = da9055_reg_read(regulator->da9055, info->conf.reg); + if (ret < 0) + return ret; + + ret &= info->conf.sel_mask; + + /* Get the voltage for the active register set A/B */ + if (ret == DA9055_REGUALTOR_SET_A) + ret = da9055_reg_read(regulator->da9055, volt.reg_a); + else + ret = da9055_reg_read(regulator->da9055, volt.reg_b); + + if (ret < 0) + return ret; + + sel = (ret & volt.v_mask); + if (sel <= volt.v_offset) + return 0; + else + return sel; +} + +static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int ret; + + /* + * Regulator register set A/B is not selected through GPIO therefore + * we use default register set A for voltage ramping. + */ + if (regulator->reg_rselect == NO_GPIO) { + /* Select register set A */ + ret = da9055_reg_update(regulator->da9055, info->conf.reg, + info->conf.sel_mask, DA9055_SEL_REG_A); + if (ret < 0) + return ret; + + /* Set the voltage */ + return da9055_reg_update(regulator->da9055, info->volt.reg_a, + info->volt.v_mask, selector); + } + + /* + * Here regulator register set A/B is selected through GPIO. + * Therefore we first determine the selected register set A/B and + * then set the desired voltage for that register set A/B. + */ + ret = da9055_reg_read(regulator->da9055, info->conf.reg); + if (ret < 0) + return ret; + + ret &= info->conf.sel_mask; + + /* Set the voltage */ + if (ret == DA9055_REGUALTOR_SET_A) + return da9055_reg_update(regulator->da9055, info->volt.reg_a, + info->volt.v_mask, selector); + else + return da9055_reg_update(regulator->da9055, info->volt.reg_b, + info->volt.v_mask, selector); +} + +static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev, + int uV) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + int ret; + + /* Select register set B for suspend voltage ramping. */ + if (regulator->reg_rselect == NO_GPIO) { + ret = da9055_reg_update(regulator->da9055, info->conf.reg, + info->conf.sel_mask, DA9055_SEL_REG_B); + if (ret < 0) + return ret; + } + + ret = da9055_map_voltage(rdev, uV, uV); + if (ret < 0) + return ret; + + return da9055_reg_update(regulator->da9055, info->volt.reg_b, + info->volt.v_mask, ret); +} + +static int da9055_suspend_enable(struct regulator_dev *rdev) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + + /* Select register set B for voltage ramping. */ + if (regulator->reg_rselect == NO_GPIO) + return da9055_reg_update(regulator->da9055, info->conf.reg, + info->conf.sel_mask, DA9055_SEL_REG_B); + else + return 0; +} + +static int da9055_suspend_disable(struct regulator_dev *rdev) +{ + struct da9055_regulator *regulator = rdev_get_drvdata(rdev); + struct da9055_regulator_info *info = regulator->info; + + /* Diselect register set B. */ + if (regulator->reg_rselect == NO_GPIO) + return da9055_reg_update(regulator->da9055, info->conf.reg, + info->conf.sel_mask, DA9055_SEL_REG_A); + else + return 0; +} + +static struct regulator_ops da9055_buck_ops = { + .get_mode = da9055_buck_get_mode, + .set_mode = da9055_buck_set_mode, + + .get_current_limit = da9055_buck_get_current_limit, + .set_current_limit = da9055_buck_set_current_limit, + + .get_voltage_sel = da9055_regulator_get_voltage_sel, + .set_voltage_sel = da9055_regulator_set_voltage_sel, + .list_voltage = da9055_list_voltage, + .map_voltage = da9055_map_voltage, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + + .set_suspend_voltage = da9055_regulator_set_suspend_voltage, + .set_suspend_enable = da9055_suspend_enable, + .set_suspend_disable = da9055_suspend_disable, + .set_suspend_mode = da9055_buck_set_mode, +}; + +static struct regulator_ops da9055_ldo_ops = { + .get_mode = da9055_ldo_get_mode, + .set_mode = da9055_ldo_set_mode, + + .get_voltage_sel = da9055_regulator_get_voltage_sel, + .set_voltage_sel = da9055_regulator_set_voltage_sel, + .list_voltage = da9055_list_voltage, + .map_voltage = da9055_map_voltage, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + + .set_suspend_voltage = da9055_regulator_set_suspend_voltage, + .set_suspend_enable = da9055_suspend_enable, + .set_suspend_disable = da9055_suspend_disable, + .set_suspend_mode = da9055_ldo_set_mode, + +}; + +#define DA9055_LDO(_id, step, min, max, vbits, voffset) \ +{\ + .reg_desc = {\ + .name = #_id,\ + .ops = &da9055_ldo_ops,\ + .type = REGULATOR_VOLTAGE,\ + .id = DA9055_ID_##_id,\ + .n_voltages = (max - min) / step + 1 + (voffset), \ + .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \ + .enable_mask = 1, \ + .min_uV = (min) * 1000,\ + .uV_step = (step) * 1000,\ + .owner = THIS_MODULE,\ + },\ + .conf = {\ + .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \ + .sel_mask = (1 << 4),\ + .en_mask = 1,\ + },\ + .volt = {\ + .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \ + .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ + .sl_shift = 7,\ + .v_offset = (voffset),\ + .v_mask = (1 << (vbits)) - 1,\ + .v_shift = (vbits),\ + },\ +} + +#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \ +{\ + .reg_desc = {\ + .name = #_id,\ + .ops = &da9055_buck_ops,\ + .type = REGULATOR_VOLTAGE,\ + .id = DA9055_ID_##_id,\ + .n_voltages = (max - min) / step + 1 + (voffset), \ + .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \ + .enable_mask = 1,\ + .min_uV = (min) * 1000,\ + .uV_step = (step) * 1000,\ + .owner = THIS_MODULE,\ + },\ + .conf = {\ + .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \ + .sel_mask = (1 << 4),\ + .en_mask = 1,\ + },\ + .volt = {\ + .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \ + .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ + .sl_shift = 7,\ + .v_offset = (voffset),\ + .v_mask = (1 << (vbits)) - 1,\ + .v_shift = (vbits),\ + },\ + .mode = {\ + .reg = DA9055_REG_BCORE_MODE,\ + .mask = (mbits),\ + .shift = (sbits),\ + },\ +} + +static struct da9055_regulator_info da9055_regulator_info[] = { + DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2), + DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0), + DA9055_LDO(LDO1, 50, 900, 3300, 6, 2), + DA9055_LDO(LDO2, 50, 900, 3300, 6, 3), + DA9055_LDO(LDO3, 50, 900, 3300, 6, 2), + DA9055_LDO(LDO4, 50, 900, 3300, 6, 2), + DA9055_LDO(LDO5, 50, 900, 2750, 6, 2), + DA9055_LDO(LDO6, 20, 900, 3300, 7, 0), +}; + +/* + * Configures regulator to be controlled either through GPIO 1 or 2. + * GPIO can control regulator state and/or select the regulator register + * set A/B for voltage ramping. + */ +static __devinit int da9055_gpio_init(struct da9055_regulator *regulator, + struct regulator_config *config, + struct da9055_pdata *pdata, int id) +{ + struct da9055_regulator_info *info = regulator->info; + int ret = 0; + + if (pdata->gpio_ren && pdata->gpio_ren[id]) { + char name[18]; + int gpio_mux = pdata->gpio_ren[id]; + + config->ena_gpio = pdata->ena_gpio[id]; + config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH; + config->ena_gpio_invert = 1; + + /* + * GPI pin is muxed with regulator to control the + * regulator state. + */ + sprintf(name, "DA9055 GPI %d", gpio_mux); + ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN, + name); + if (ret < 0) + goto err; + + /* + * Let the regulator know that its state is controlled + * through GPI. + */ + ret = da9055_reg_update(regulator->da9055, info->conf.reg, + DA9055_E_GPI_MASK, + pdata->reg_ren[id] + << DA9055_E_GPI_SHIFT); + if (ret < 0) + goto err; + } + + if (pdata->gpio_rsel && pdata->gpio_rsel[id]) { + char name[18]; + int gpio_mux = pdata->gpio_rsel[id]; + + regulator->reg_rselect = pdata->reg_rsel[id]; + + /* + * GPI pin is muxed with regulator to select the + * regulator register set A/B for voltage ramping. + */ + sprintf(name, "DA9055 GPI %d", gpio_mux); + ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN, + name); + if (ret < 0) + goto err; + + /* + * Let the regulator know that its register set A/B + * will be selected through GPI for voltage ramping. + */ + ret = da9055_reg_update(regulator->da9055, info->conf.reg, + DA9055_V_GPI_MASK, + pdata->reg_rsel[id] + << DA9055_V_GPI_SHIFT); + } + +err: + return ret; +} + +static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data) +{ + struct da9055_regulator *regulator = data; + + regulator_notifier_call_chain(regulator->rdev, + REGULATOR_EVENT_OVER_CURRENT, NULL); + + return IRQ_HANDLED; +} + +static inline struct da9055_regulator_info *find_regulator_info(int id) +{ + struct da9055_regulator_info *info; + int i; + + for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) { + info = &da9055_regulator_info[i]; + if (info->reg_desc.id == id) + return info; + } + + return NULL; +} + +static int __devinit da9055_regulator_probe(struct platform_device *pdev) +{ + struct regulator_config config = { }; + struct da9055_regulator *regulator; + struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent); + struct da9055_pdata *pdata = da9055->dev->platform_data; + int ret, irq; + + if (pdata == NULL || pdata->regulators[pdev->id] == NULL) + return -ENODEV; + + regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator), + GFP_KERNEL); + if (!regulator) + return -ENOMEM; + + regulator->info = find_regulator_info(pdev->id); + if (regulator->info == NULL) { + dev_err(&pdev->dev, "invalid regulator ID specified\n"); + return -EINVAL; + } + + regulator->da9055 = da9055; + config.dev = &pdev->dev; + config.driver_data = regulator; + config.regmap = da9055->regmap; + + if (pdata && pdata->regulators) + config.init_data = pdata->regulators[pdev->id]; + + ret = da9055_gpio_init(regulator, &config, pdata, pdev->id); + if (ret < 0) + return ret; + + regulator->rdev = regulator_register(®ulator->info->reg_desc, + &config); + if (IS_ERR(regulator->rdev)) { + dev_err(&pdev->dev, "Failed to register regulator %s\n", + regulator->info->reg_desc.name); + ret = PTR_ERR(regulator->rdev); + return ret; + } + + /* Only LDO 5 and 6 has got the over current interrupt */ + if (pdev->id == DA9055_ID_LDO5 || pdev->id == DA9055_ID_LDO6) { + irq = platform_get_irq_byname(pdev, "REGULATOR"); + irq = regmap_irq_get_virq(da9055->irq_data, irq); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + da9055_ldo5_6_oc_irq, + IRQF_TRIGGER_HIGH | + IRQF_ONESHOT | + IRQF_PROBE_SHARED, + pdev->name, regulator); + if (ret != 0) { + if (ret != -EBUSY) { + dev_err(&pdev->dev, + "Failed to request Regulator IRQ %d: %d\n", + irq, ret); + goto err_regulator; + } + } + } + + platform_set_drvdata(pdev, regulator); + + return 0; + +err_regulator: + regulator_unregister(regulator->rdev); + return ret; +} + +static int __devexit da9055_regulator_remove(struct platform_device *pdev) +{ + struct da9055_regulator *regulator = platform_get_drvdata(pdev); + + regulator_unregister(regulator->rdev); + + return 0; +} + +static struct platform_driver da9055_regulator_driver = { + .probe = da9055_regulator_probe, + .remove = __devexit_p(da9055_regulator_remove), + .driver = { + .name = "da9055-regulator", + .owner = THIS_MODULE, + }, +}; + +static int __init da9055_regulator_init(void) +{ + return platform_driver_register(&da9055_regulator_driver); +} +subsys_initcall(da9055_regulator_init); + +static void __exit da9055_regulator_exit(void) +{ + platform_driver_unregister(&da9055_regulator_driver); +} +module_exit(da9055_regulator_exit); + +MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); +MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9055-regulator"); diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 359f8d18fc3..219d162b651 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = { }, }; -static __devinit int db8500_regulator_register(struct platform_device *pdev, +static int db8500_regulator_register(struct platform_device *pdev, struct regulator_init_data *init_data, int id, struct device_node *np) @@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = { { .name = "db8500_esram34_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, }, }; -static __devinit int +static int db8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) { @@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev, return 0; } -static int __devinit db8500_regulator_probe(struct platform_device *pdev) +static int db8500_regulator_probe(struct platform_device *pdev) { struct regulator_init_data *db8500_init_data = dev_get_platdata(&pdev->dev); diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index f2e5ecdc586..261f3d2299b 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c @@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase( return 0; } -int __devinit +int ux500_regulator_debug_init(struct platform_device *pdev, struct dbx500_regulator_info *regulator_info, int num_regulators) @@ -230,7 +230,7 @@ exit_no_debugfs: return -ENOMEM; } -int __devexit ux500_regulator_debug_exit(void) +int ux500_regulator_debug_exit(void) { debugfs_remove_recursive(rdebug.dir); kfree(rdebug.state_after_suspend); diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index 03a1d7c11ef..df9f42524ab 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = { .ops = &dummy_ops, }; -static int __devinit dummy_regulator_probe(struct platform_device *pdev) +static int dummy_regulator_probe(struct platform_device *pdev) { struct regulator_config config = { }; int ret; diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 339f4d732e9..9165b0c40ed 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = { .val_bits = 8, }; -static int __devinit fan53555_regulator_probe(struct i2c_client *client, +static int fan53555_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct fan53555_device_info *di; @@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client, } -static int __devexit fan53555_regulator_remove(struct i2c_client *client) +static int fan53555_regulator_remove(struct i2c_client *client) { struct fan53555_device_info *di = i2c_get_clientdata(client); @@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = { .name = "fan53555-regulator", }, .probe = fan53555_regulator_probe, - .remove = __devexit_p(fan53555_regulator_remove), + .remove = fan53555_regulator_remove, .id_table = fan53555_id, }; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 185468c4d38..48d5b7608b0 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = { .list_voltage = fixed_voltage_list_voltage, }; -static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) +static int reg_fixed_voltage_probe(struct platform_device *pdev) { struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; @@ -234,7 +234,7 @@ err: return ret; } -static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) +static int reg_fixed_voltage_remove(struct platform_device *pdev) { struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); @@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match); static struct platform_driver regulator_fixed_voltage_driver = { .probe = reg_fixed_voltage_probe, - .remove = __devexit_p(reg_fixed_voltage_remove), + .remove = reg_fixed_voltage_remove, .driver = { .name = "reg-fixed-voltage", .owner = THIS_MODULE, diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 8b5944f2d7d..2cfd9d3079e 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -28,9 +28,12 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> #include <linux/regulator/gpio-regulator.h> #include <linux/gpio.h> #include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_gpio.h> struct gpio_regulator_data { struct regulator_desc desc; @@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = { .list_voltage = gpio_regulator_list_voltage, }; +struct gpio_regulator_config * +of_get_gpio_regulator_config(struct device *dev, struct device_node *np) +{ + struct gpio_regulator_config *config; + struct property *prop; + const char *regtype; + int proplen, gpio, i; + + config = devm_kzalloc(dev, + sizeof(struct gpio_regulator_config), + GFP_KERNEL); + if (!config) + return ERR_PTR(-ENOMEM); + + config->init_data = of_get_regulator_init_data(dev, np); + if (!config->init_data) + return ERR_PTR(-EINVAL); + + config->supply_name = config->init_data->constraints.name; + + if (of_property_read_bool(np, "enable-active-high")) + config->enable_high = true; + + if (of_property_read_bool(np, "enable-at-boot")) + config->enabled_at_boot = true; + + of_property_read_u32(np, "startup-delay-us", &config->startup_delay); + + config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); + + /* Fetch GPIOs. */ + for (i = 0; ; i++) + if (of_get_named_gpio(np, "gpios", i) < 0) + break; + config->nr_gpios = i; + + config->gpios = devm_kzalloc(dev, + sizeof(struct gpio) * config->nr_gpios, + GFP_KERNEL); + if (!config->gpios) + return ERR_PTR(-ENOMEM); + + for (i = 0; config->nr_gpios; i++) { + gpio = of_get_named_gpio(np, "gpios", i); + if (gpio < 0) + break; + config->gpios[i].gpio = gpio; + } + + /* Fetch states. */ + prop = of_find_property(np, "states", NULL); + if (!prop) { + dev_err(dev, "No 'states' property found\n"); + return ERR_PTR(-EINVAL); + } + + proplen = prop->length / sizeof(int); + + config->states = devm_kzalloc(dev, + sizeof(struct gpio_regulator_state) + * (proplen / 2), + GFP_KERNEL); + if (!config->states) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < proplen / 2; i++) { + config->states[i].value = + be32_to_cpup((int *)prop->value + (i * 2)); + config->states[i].gpios = + be32_to_cpup((int *)prop->value + (i * 2 + 1)); + } + config->nr_states = i; + + of_property_read_string(np, "regulator-type", ®type); + + if (!strncmp("voltage", regtype, 7)) + config->type = REGULATOR_VOLTAGE; + else if (!strncmp("current", regtype, 7)) + config->type = REGULATOR_CURRENT; + + return config; +} + static struct regulator_ops gpio_regulator_current_ops = { .get_current_limit = gpio_regulator_get_value, .set_current_limit = gpio_regulator_set_current_limit, }; -static int __devinit gpio_regulator_probe(struct platform_device *pdev) +static int gpio_regulator_probe(struct platform_device *pdev) { struct gpio_regulator_config *config = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct gpio_regulator_data *drvdata; struct regulator_config cfg = { }; int ptr, ret, state; + if (np) { + config = of_get_gpio_regulator_config(&pdev->dev, np); + if (IS_ERR(config)) + return PTR_ERR(config); + } + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); if (drvdata == NULL) { @@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) cfg.dev = &pdev->dev; cfg.init_data = config->init_data; cfg.driver_data = drvdata; + cfg.of_node = np; if (config->enable_gpio >= 0) cfg.ena_gpio = config->enable_gpio; @@ -254,7 +348,7 @@ err: return ret; } -static int __devexit gpio_regulator_remove(struct platform_device *pdev) +static int gpio_regulator_remove(struct platform_device *pdev) { struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev); @@ -270,12 +364,20 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id regulator_gpio_of_match[] __devinitconst = { + { .compatible = "regulator-gpio", }, + {}, +}; +#endif + static struct platform_driver gpio_regulator_driver = { .probe = gpio_regulator_probe, - .remove = __devexit_p(gpio_regulator_remove), + .remove = gpio_regulator_remove, .driver = { .name = "gpio-regulator", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(regulator_gpio_of_match), }, }; diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index d8ecf49a577..d1e5bee2a26 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = { }, }; -static int __devinit isl6271a_probe(struct i2c_client *i2c, +static int isl6271a_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct regulator_config config = { }; @@ -151,7 +151,7 @@ error: return err; } -static int __devexit isl6271a_remove(struct i2c_client *i2c) +static int isl6271a_remove(struct i2c_client *i2c) { struct isl_pmic *pmic = i2c_get_clientdata(i2c); int i; @@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = { .owner = THIS_MODULE, }, .probe = isl6271a_probe, - .remove = __devexit_p(isl6271a_remove), + .remove = isl6271a_remove, .id_table = isl6271a_id, }; diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 7c6e3b8ff48..5f68ff11a29 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val) return ret; } -static int __devinit setup_regulators(struct lp3971 *lp3971, +static int setup_regulators(struct lp3971 *lp3971, struct lp3971_platform_data *pdata) { int i, err; @@ -429,7 +429,7 @@ err_nomem: return err; } -static int __devinit lp3971_i2c_probe(struct i2c_client *i2c, +static int lp3971_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct lp3971 *lp3971; @@ -472,7 +472,7 @@ err_detect: return ret; } -static int __devexit lp3971_i2c_remove(struct i2c_client *i2c) +static int lp3971_i2c_remove(struct i2c_client *i2c) { struct lp3971 *lp3971 = i2c_get_clientdata(i2c); int i; @@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = { .owner = THIS_MODULE, }, .probe = lp3971_i2c_probe, - .remove = __devexit_p(lp3971_i2c_remove), + .remove = lp3971_i2c_remove, .id_table = lp3971_i2c_id, }; diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 3cdc755d9b2..69c42c318b8 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = { }, }; -static int __devinit setup_regulators(struct lp3972 *lp3972, +static int setup_regulators(struct lp3972 *lp3972, struct lp3972_platform_data *pdata) { int i, err; @@ -523,7 +523,7 @@ err_nomem: return err; } -static int __devinit lp3972_i2c_probe(struct i2c_client *i2c, +static int lp3972_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct lp3972 *lp3972; @@ -569,7 +569,7 @@ err_detect: return ret; } -static int __devexit lp3972_i2c_remove(struct i2c_client *i2c) +static int lp3972_i2c_remove(struct i2c_client *i2c) { struct lp3972 *lp3972 = i2c_get_clientdata(i2c); int i; @@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = { .owner = THIS_MODULE, }, .probe = lp3972_i2c_probe, - .remove = __devexit_p(lp3972_i2c_remove), + .remove = lp3972_i2c_remove, .id_table = lp3972_i2c_id, }; diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 708f4b6a17d..9289ead715c 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -893,7 +893,7 @@ err_dev: return ret; } -static int __devexit lp872x_remove(struct i2c_client *cl) +static int lp872x_remove(struct i2c_client *cl) { struct lp872x *lp = i2c_get_clientdata(cl); @@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = { .owner = THIS_MODULE, }, .probe = lp872x_probe, - .remove = __devexit_p(lp872x_remove), + .remove = lp872x_remove, .id_table = lp872x_ids, }; diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index fab2590dc58..aef3f2b0c5e 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c @@ -494,7 +494,7 @@ set_default_dvs_mode: default_dvs_mode[id]); } -static __devinit int lp8788_buck_probe(struct platform_device *pdev) +static int lp8788_buck_probe(struct platform_device *pdev) { struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); int id = pdev->id; @@ -532,7 +532,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev) return 0; } -static int __devexit lp8788_buck_remove(struct platform_device *pdev) +static int lp8788_buck_remove(struct platform_device *pdev) { struct lp8788_buck *buck = platform_get_drvdata(pdev); @@ -544,7 +544,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev) static struct platform_driver lp8788_buck_driver = { .probe = lp8788_buck_probe, - .remove = __devexit_p(lp8788_buck_remove), + .remove = lp8788_buck_remove, .driver = { .name = LP8788_DEV_BUCK, .owner = THIS_MODULE, diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index 40897eb2c29..3792741708c 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -703,7 +703,7 @@ set_default_ldo_enable_mode: return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0); } -static __devinit int lp8788_dldo_probe(struct platform_device *pdev) +static int lp8788_dldo_probe(struct platform_device *pdev) { struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); int id = pdev->id; @@ -740,7 +740,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev) return 0; } -static int __devexit lp8788_dldo_remove(struct platform_device *pdev) +static int lp8788_dldo_remove(struct platform_device *pdev) { struct lp8788_ldo *ldo = platform_get_drvdata(pdev); @@ -752,14 +752,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev) static struct platform_driver lp8788_dldo_driver = { .probe = lp8788_dldo_probe, - .remove = __devexit_p(lp8788_dldo_remove), + .remove = lp8788_dldo_remove, .driver = { .name = LP8788_DEV_DLDO, .owner = THIS_MODULE, }, }; -static __devinit int lp8788_aldo_probe(struct platform_device *pdev) +static int lp8788_aldo_probe(struct platform_device *pdev) { struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); int id = pdev->id; @@ -796,7 +796,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev) return 0; } -static int __devexit lp8788_aldo_remove(struct platform_device *pdev) +static int lp8788_aldo_remove(struct platform_device *pdev) { struct lp8788_ldo *ldo = platform_get_drvdata(pdev); @@ -808,7 +808,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev) static struct platform_driver lp8788_aldo_driver = { .probe = lp8788_aldo_probe, - .remove = __devexit_p(lp8788_aldo_remove), + .remove = lp8788_aldo_remove, .driver = { .name = LP8788_DEV_ALDO, .owner = THIS_MODULE, diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index f67af3c1b96..3a035ece83c 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -125,7 +125,7 @@ static struct regulator_desc max1586_reg[] = { }, }; -static int __devinit max1586_pmic_probe(struct i2c_client *client, +static int max1586_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct regulator_dev **rdev; @@ -188,7 +188,7 @@ err: return ret; } -static int __devexit max1586_pmic_remove(struct i2c_client *client) +static int max1586_pmic_remove(struct i2c_client *client) { struct max1586_data *max1586 = i2c_get_clientdata(client); int i; @@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id); static struct i2c_driver max1586_pmic_driver = { .probe = max1586_pmic_probe, - .remove = __devexit_p(max1586_pmic_remove), + .remove = max1586_pmic_remove, .driver = { .name = "max1586", .owner = THIS_MODULE, diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 2a67d08658a..cb99e9031a6 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -280,7 +280,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, } #endif /* CONFIG_OF */ -static __devinit int max77686_pmic_probe(struct platform_device *pdev) +static int max77686_pmic_probe(struct platform_device *pdev) { struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev); @@ -337,7 +337,7 @@ err: return ret; } -static int __devexit max77686_pmic_remove(struct platform_device *pdev) +static int max77686_pmic_remove(struct platform_device *pdev) { struct max77686_data *max77686 = platform_get_drvdata(pdev); int i; @@ -360,7 +360,7 @@ static struct platform_driver max77686_pmic_driver = { .owner = THIS_MODULE, }, .probe = max77686_pmic_probe, - .remove = __devexit_p(max77686_pmic_remove), + .remove = max77686_pmic_remove, .id_table = max77686_pmic_id, }; diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 9d540cd02da..3ca14380f22 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = { .val_bits = 8, }; -static int __devinit max8649_regulator_probe(struct i2c_client *client, +static int max8649_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max8649_platform_data *pdata = client->dev.platform_data; @@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, return 0; } -static int __devexit max8649_regulator_remove(struct i2c_client *client) +static int max8649_regulator_remove(struct i2c_client *client) { struct max8649_regulator_info *info = i2c_get_clientdata(client); @@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id); static struct i2c_driver max8649_driver = { .probe = max8649_regulator_probe, - .remove = __devexit_p(max8649_regulator_remove), + .remove = max8649_regulator_remove, .driver = { .name = "max8649", }, diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 8d531742f59..4d7c635c36c 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = { }, }; -static int __devinit max8660_probe(struct i2c_client *client, +static int max8660_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct regulator_dev **rdev; @@ -420,7 +420,7 @@ err_out: return ret; } -static int __devexit max8660_remove(struct i2c_client *client) +static int max8660_remove(struct i2c_client *client) { struct max8660 *max8660 = i2c_get_clientdata(client); int i; @@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id); static struct i2c_driver max8660_driver = { .probe = max8660_probe, - .remove = __devexit_p(max8660_remove), + .remove = max8660_remove, .driver = { .name = "max8660", .owner = THIS_MODULE, diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index af7607515ab..d1a77512d83 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index) } #endif -static __devinit int max8907_regulator_probe(struct platform_device *pdev) +static int max8907_regulator_probe(struct platform_device *pdev) { struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev); @@ -368,7 +368,7 @@ err_unregister_regulator: return ret; } -static __devexit int max8907_regulator_remove(struct platform_device *pdev) +static int max8907_regulator_remove(struct platform_device *pdev) { struct max8907_regulator *pmic = platform_get_drvdata(pdev); int i; @@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = { .owner = THIS_MODULE, }, .probe = max8907_regulator_probe, - .remove = __devexit_p(max8907_regulator_remove), + .remove = max8907_regulator_remove, }; static int __init max8907_regulator_init(void) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 9bb0be37495..446a8544555 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -17,6 +17,8 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/mfd/max8925.h> +#include <linux/of.h> +#include <linux/regulator/of_regulator.h> #define SD1_DVM_VMIN 850000 #define SD1_DVM_VMAX 1000000 @@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .enable_reg = MAX8925_LDOCTL##_id, \ } +#ifdef CONFIG_OF +static struct of_regulator_match max8925_regulator_matches[] = { + { .name = "SDV1",}, + { .name = "SDV2",}, + { .name = "SDV3",}, + { .name = "LDO1",}, + { .name = "LDO2",}, + { .name = "LDO3",}, + { .name = "LDO4",}, + { .name = "LDO5",}, + { .name = "LDO6",}, + { .name = "LDO7",}, + { .name = "LDO8",}, + { .name = "LDO9",}, + { .name = "LDO10",}, + { .name = "LDO11",}, + { .name = "LDO12",}, + { .name = "LDO13",}, + { .name = "LDO14",}, + { .name = "LDO15",}, + { .name = "LDO16",}, + { .name = "LDO17",}, + { .name = "LDO18",}, + { .name = "LDO19",}, + { .name = "LDO20",}, +}; +#endif + static struct max8925_regulator_info max8925_regulator_info[] = { MAX8925_SDV(1, 637.5, 1425, 12.5), MAX8925_SDV(2, 650, 2225, 25), @@ -214,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = { MAX8925_LDO(20, 750, 3900, 50), }; -static int __devinit max8925_regulator_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static int max8925_regulator_dt_init(struct platform_device *pdev, + struct max8925_regulator_info *info, + struct regulator_config *config, + int ridx) +{ + struct device_node *nproot, *np; + int rcount; + nproot = pdev->dev.parent->of_node; + if (!nproot) + return -ENODEV; + np = of_find_node_by_name(nproot, "regulators"); + if (!np) { + dev_err(&pdev->dev, "failed to find regulators node\n"); + return -ENODEV; + } + + rcount = of_regulator_match(&pdev->dev, np, + &max8925_regulator_matches[ridx], 1); + if (rcount < 0) + return -ENODEV; + config->init_data = max8925_regulator_matches[ridx].init_data; + config->of_node = max8925_regulator_matches[ridx].of_node; + + return 0; +} +#else +#define max8925_regulator_dt_init(w, x, y, z) (-1) +#endif + +static int max8925_regulator_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); struct regulator_init_data *pdata = pdev->dev.platform_data; @@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) struct max8925_regulator_info *ri; struct resource *res; struct regulator_dev *rdev; - int i; + int i, regulator_idx; res = platform_get_resource(pdev, IORESOURCE_REG, 0); if (!res) { @@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) } for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) { ri = &max8925_regulator_info[i]; - if (ri->vol_reg == res->start) + if (ri->vol_reg == res->start) { + regulator_idx = i; break; + } } + if (i == ARRAY_SIZE(max8925_regulator_info)) { dev_err(&pdev->dev, "Failed to find regulator %llu\n", (unsigned long long)res->start); @@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) ri->chip = chip; config.dev = &pdev->dev; - config.init_data = pdata; config.driver_data = ri; + if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx)) + if (pdata) + config.init_data = pdata; + rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", @@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit max8925_regulator_remove(struct platform_device *pdev) +static int max8925_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = { .owner = THIS_MODULE, }, .probe = max8925_regulator_probe, - .remove = __devexit_p(max8925_regulator_remove), + .remove = max8925_regulator_remove, }; static int __init max8925_regulator_init(void) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 355ca7bad9d..fc7935a19e3 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -126,7 +126,7 @@ static const struct regulator_desc regulator = { .owner = THIS_MODULE, }; -static int __devinit max8952_pmic_probe(struct i2c_client *client, +static int max8952_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); @@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, return 0; } -static int __devexit max8952_pmic_remove(struct i2c_client *client) +static int max8952_pmic_remove(struct i2c_client *client) { struct max8952_data *max8952 = i2c_get_clientdata(client); struct max8952_platform_data *pdata = max8952->pdata; @@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids); static struct i2c_driver max8952_pmic_driver = { .probe = max8952_pmic_probe, - .remove = __devexit_p(max8952_pmic_remove), + .remove = max8952_pmic_remove, .driver = { .name = "max8952", }, diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index e39a0c7260d..cea9ec9093e 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -933,7 +933,7 @@ static struct regulator_desc regulators[] = { max8997_charger_fixedstate_ops), }; -static __devinit int max8997_pmic_probe(struct platform_device *pdev) +static int max8997_pmic_probe(struct platform_device *pdev) { struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); @@ -1120,7 +1120,7 @@ err_out: return ret; } -static int __devexit max8997_pmic_remove(struct platform_device *pdev) +static int max8997_pmic_remove(struct platform_device *pdev) { struct max8997_data *max8997 = platform_get_drvdata(pdev); struct regulator_dev **rdev = max8997->rdev; @@ -1143,7 +1143,7 @@ static struct platform_driver max8997_pmic_driver = { .owner = THIS_MODULE, }, .probe = max8997_pmic_probe, - .remove = __devexit_p(max8997_pmic_remove), + .remove = max8997_pmic_remove, .id_table = max8997_pmic_id, }; diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 5dfa920ff0c..b821d08eb64 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = { } }; -static __devinit int max8998_pmic_probe(struct platform_device *pdev) +static int max8998_pmic_probe(struct platform_device *pdev) { struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); @@ -818,7 +818,7 @@ err_out: return ret; } -static int __devexit max8998_pmic_remove(struct platform_device *pdev) +static int max8998_pmic_remove(struct platform_device *pdev) { struct max8998_data *max8998 = platform_get_drvdata(pdev); struct regulator_dev **rdev = max8998->rdev; @@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = { .owner = THIS_MODULE, }, .probe = max8998_pmic_probe, - .remove = __devexit_p(max8998_pmic_remove), + .remove = max8998_pmic_remove, .id_table = max8998_pmic_id, }; diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 0801a6d0c12..c46c6705cd7 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = { .set_voltage = mc13xxx_fixed_regulator_set_voltage, }; -static int __devinit mc13783_regulator_probe(struct platform_device *pdev) +static int mc13783_regulator_probe(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv; struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); @@ -445,7 +445,7 @@ err: return ret; } -static int __devexit mc13783_regulator_remove(struct platform_device *pdev) +static int mc13783_regulator_remove(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); struct mc13xxx_regulator_platform_data *pdata = @@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = { .name = "mc13783-regulator", .owner = THIS_MODULE, }, - .remove = __devexit_p(mc13783_regulator_remove), + .remove = mc13783_regulator_remove, .probe = mc13783_regulator_probe, }; diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 1fa63812f7a..0d84b1f3319 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) } -static int __devinit mc13892_regulator_probe(struct platform_device *pdev) +static int mc13892_regulator_probe(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv; struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); @@ -588,7 +588,7 @@ err_unlock: return ret; } -static int __devexit mc13892_regulator_remove(struct platform_device *pdev) +static int mc13892_regulator_remove(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); int i; @@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = { .name = "mc13892-regulator", .owner = THIS_MODULE, }, - .remove = __devexit_p(mc13892_regulator_remove), + .remove = mc13892_regulator_remove, .probe = mc13892_regulator_probe, }; diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 88cbb832d55..4ed89c65411 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = { EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); #ifdef CONFIG_OF -int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev) +int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) { struct device_node *parent, *child; int num = 0; @@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt); -struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt( +struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, int num_regulators) { diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 07aee694ba9..3d445929cc8 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -595,7 +595,7 @@ static struct of_regulator_match palmas_matches[] = { { .name = "ldousb", }, }; -static void __devinit palmas_dt_to_pdata(struct device *dev, +static void palmas_dt_to_pdata(struct device *dev, struct device_node *node, struct palmas_pmic_platform_data *pdata) { @@ -663,7 +663,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev, } -static __devinit int palmas_probe(struct platform_device *pdev) +static int palmas_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data; @@ -868,7 +868,7 @@ err_unregister_regulator: return ret; } -static int __devexit palmas_remove(struct platform_device *pdev) +static int palmas_remove(struct platform_device *pdev) { struct palmas_pmic *pmic = platform_get_drvdata(pdev); int id; @@ -890,7 +890,7 @@ static struct platform_driver palmas_driver = { .owner = THIS_MODULE, }, .probe = palmas_probe, - .remove = __devexit_p(palmas_remove), + .remove = palmas_remove, }; static int __init palmas_init(void) diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 68777acc099..4899342f1fc 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = { VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2), }; -static int __devinit pcap_regulator_probe(struct platform_device *pdev) +static int pcap_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; void *pcap = dev_get_drvdata(pdev->dev.parent); @@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit pcap_regulator_remove(struct platform_device *pdev) +static int pcap_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = { .owner = THIS_MODULE, }, .probe = pcap_regulator_probe, - .remove = __devexit_p(pcap_regulator_remove), + .remove = pcap_regulator_remove, }; static int __init pcap_regulator_init(void) diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 092e5cb848a..d776f518aa0 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -196,7 +196,7 @@ static const struct regulator_desc regulators[] = { [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28), }; -static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) +static int pcf50633_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct pcf50633 *pcf; @@ -222,7 +222,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit pcf50633_regulator_remove(struct platform_device *pdev) +static int pcf50633_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -237,7 +237,7 @@ static struct platform_driver pcf50633_regulator_driver = { .name = "pcf50633-regltr", }, .probe = pcf50633_regulator_probe, - .remove = __devexit_p(pcf50633_regulator_remove), + .remove = pcf50633_regulator_remove, }; static int __init pcf50633_regulator_init(void) diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 8bf4e8c9de9..9e6f78694bf 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = { RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133), }; -static int __devinit rc5t583_regulator_probe(struct platform_device *pdev) +static int rc5t583_regulator_probe(struct platform_device *pdev) { struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); @@ -198,7 +198,7 @@ clean_exit: return ret; } -static int __devexit rc5t583_regulator_remove(struct platform_device *pdev) +static int rc5t583_regulator_remove(struct platform_device *pdev) { struct rc5t583_regulator *regs = platform_get_drvdata(pdev); int id; @@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = { .owner = THIS_MODULE, }, .probe = rc5t583_regulator_probe, - .remove = __devexit_p(rc5t583_regulator_remove), + .remove = rc5t583_regulator_remove, }; static int __init rc5t583_regulator_init(void) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 926f9c8f2fa..85fc086c131 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = { regulator_desc_buck10, }; -static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) +static int s2mps11_pmic_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); @@ -307,7 +307,7 @@ err: return ret; } -static int __devexit s2mps11_pmic_remove(struct platform_device *pdev) +static int s2mps11_pmic_remove(struct platform_device *pdev) { struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev); int i; @@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = { .owner = THIS_MODULE, }, .probe = s2mps11_pmic_probe, - .remove = __devexit_p(s2mps11_pmic_remove), + .remove = s2mps11_pmic_remove, .id_table = s2mps11_pmic_id, }; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index abe64a32aed..2b822bec3c2 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -499,7 +499,7 @@ static struct regulator_desc regulators[] = { s5m8767_regulator_desc(BUCK9), }; -static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) +static int s5m8767_pmic_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); @@ -773,7 +773,7 @@ err: return ret; } -static int __devexit s5m8767_pmic_remove(struct platform_device *pdev) +static int s5m8767_pmic_remove(struct platform_device *pdev) { struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev); struct regulator_dev **rdev = s5m8767->rdev; @@ -798,7 +798,7 @@ static struct platform_driver s5m8767_pmic_driver = { .owner = THIS_MODULE, }, .probe = s5m8767_pmic_probe, - .remove = __devexit_p(s5m8767_pmic_remove), + .remove = s5m8767_pmic_remove, .id_table = s5m8767_pmic_id, }; diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c new file mode 100644 index 00000000000..a9c3a4a6cca --- /dev/null +++ b/drivers/regulator/tps51632-regulator.c @@ -0,0 +1,332 @@ +/* + * tps51632-regulator.c -- TI TPS51632 + * + * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless + * Controller with serial VID control and DVFS. + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * Author: Laxman Dewangan <ldewangan@nvidia.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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, + * whether express or implied; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/tps51632-regulator.h> +#include <linux/slab.h> + +/* Register definitions */ +#define TPS51632_VOLTAGE_SELECT_REG 0x0 +#define TPS51632_VOLTAGE_BASE_REG 0x1 +#define TPS51632_OFFSET_REG 0x2 +#define TPS51632_IMON_REG 0x3 +#define TPS51632_VMAX_REG 0x4 +#define TPS51632_DVFS_CONTROL_REG 0x5 +#define TPS51632_POWER_STATE_REG 0x6 +#define TPS51632_SLEW_REGS 0x7 +#define TPS51632_FAULT_REG 0x14 + +#define TPS51632_MAX_REG 0x15 + +#define TPS51632_VOUT_MASK 0x7F +#define TPS51632_VOUT_OFFSET_MASK 0x1F +#define TPS51632_VMAX_MASK 0x7F +#define TPS51632_VMAX_LOCK 0x80 + +/* TPS51632_DVFS_CONTROL_REG */ +#define TPS51632_DVFS_PWMEN 0x1 +#define TPS51632_DVFS_STEP_20 0x2 +#define TPS51632_DVFS_VMAX_PG 0x4 +#define TPS51632_DVFS_PWMRST 0x8 +#define TPS51632_DVFS_OCA_EN 0x10 +#define TPS51632_DVFS_FCCM 0x20 + +/* TPS51632_POWER_STATE_REG */ +#define TPS51632_POWER_STATE_MASK 0x03 +#define TPS51632_POWER_STATE_MULTI_PHASE_CCM 0x0 +#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM 0x1 +#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM 0x2 + +#define TPS51632_MIN_VOLATGE 500000 +#define TPS51632_MAX_VOLATGE 1520000 +#define TPS51632_VOLATGE_STEP_10mV 10000 +#define TPS51632_VOLATGE_STEP_20mV 20000 +#define TPS51632_MAX_VSEL 0x7F +#define TPS51632_MIN_VSEL 0x19 +#define TPS51632_DEFAULT_RAMP_DELAY 6000 +#define TPS51632_VOLT_VSEL(uV) \ + (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE, \ + TPS51632_VOLATGE_STEP_10mV) + \ + TPS51632_MIN_VSEL) + +/* TPS51632 chip information */ +struct tps51632_chip { + struct device *dev; + struct regulator_desc desc; + struct regulator_dev *rdev; + struct regmap *regmap; + bool enable_pwm_dvfs; +}; + +static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev) +{ + struct tps51632_chip *tps = rdev_get_drvdata(rdev); + unsigned int data; + int ret; + unsigned int reg = TPS51632_VOLTAGE_SELECT_REG; + int vsel; + + if (tps->enable_pwm_dvfs) + reg = TPS51632_VOLTAGE_BASE_REG; + + ret = regmap_read(tps->regmap, reg, &data); + if (ret < 0) { + dev_err(tps->dev, "reg read failed, err %d\n", ret); + return ret; + } + + vsel = data & TPS51632_VOUT_MASK; + + if (vsel < TPS51632_MIN_VSEL) + return 0; + else + return vsel - TPS51632_MIN_VSEL; +} + +static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) +{ + struct tps51632_chip *tps = rdev_get_drvdata(rdev); + int vsel; + int ret; + unsigned int reg = TPS51632_VOLTAGE_SELECT_REG; + + if (tps->enable_pwm_dvfs) + reg = TPS51632_VOLTAGE_BASE_REG; + + vsel = selector + TPS51632_MIN_VSEL; + if (vsel > TPS51632_MAX_VSEL) + return -EINVAL; + + ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel); + if (ret < 0) + dev_err(tps->dev, "reg write failed, err %d\n", ret); + return ret; +} + +static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, + int ramp_delay) +{ + struct tps51632_chip *tps = rdev_get_drvdata(rdev); + int bit = ramp_delay/6000; + int ret; + + if (bit) + bit--; + ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit)); + if (ret < 0) + dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret); + return ret; +} + +static struct regulator_ops tps51632_dcdc_ops = { + .get_voltage_sel = tps51632_dcdc_get_voltage_sel, + .set_voltage_sel = tps51632_dcdc_set_voltage_sel, + .list_voltage = regulator_list_voltage_linear, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = tps51632_dcdc_set_ramp_delay, +}; + +static int tps51632_init_dcdc(struct tps51632_chip *tps, + struct tps51632_regulator_platform_data *pdata) +{ + int ret; + uint8_t control = 0; + int vsel; + + if (!pdata->enable_pwm_dvfs) + goto skip_pwm_config; + + control |= TPS51632_DVFS_PWMEN; + tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs; + vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV); + ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel); + if (ret < 0) { + dev_err(tps->dev, "BASE reg write failed, err %d\n", ret); + return ret; + } + + if (pdata->dvfs_step_20mV) + control |= TPS51632_DVFS_STEP_20; + + if (pdata->max_voltage_uV) { + unsigned int vmax; + /** + * TPS51632 hw behavior: VMAX register can be write only + * once as it get locked after first write. The lock get + * reset only when device is power-reset. + * Write register only when lock bit is not enabled. + */ + ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax); + if (ret < 0) { + dev_err(tps->dev, "VMAX read failed, err %d\n", ret); + return ret; + } + if (!(vmax & TPS51632_VMAX_LOCK)) { + vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV); + ret = regmap_write(tps->regmap, TPS51632_VMAX_REG, + vsel); + if (ret < 0) { + dev_err(tps->dev, + "VMAX write failed, err %d\n", ret); + return ret; + } + } + } + +skip_pwm_config: + ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control); + if (ret < 0) + dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret); + return ret; +} + +static bool rd_wr_reg(struct device *dev, unsigned int reg) +{ + if ((reg >= 0x8) && (reg <= 0x10)) + return false; + return true; +} + +static const struct regmap_config tps51632_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = rd_wr_reg, + .readable_reg = rd_wr_reg, + .max_register = TPS51632_MAX_REG - 1, + .cache_type = REGCACHE_RBTREE, +}; + +static int tps51632_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tps51632_regulator_platform_data *pdata; + struct regulator_dev *rdev; + struct tps51632_chip *tps; + int ret; + struct regulator_config config = { }; + + pdata = client->dev.platform_data; + if (!pdata) { + dev_err(&client->dev, "No Platform data\n"); + return -EINVAL; + } + + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) { + dev_err(&client->dev, "Memory allocation failed\n"); + return -ENOMEM; + } + + tps->dev = &client->dev; + tps->desc.name = id->name; + tps->desc.id = 0; + tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY; + tps->desc.min_uV = TPS51632_MIN_VOLATGE; + tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV; + tps->desc.n_voltages = (TPS51632_MAX_VSEL - TPS51632_MIN_VSEL) + 1; + tps->desc.ops = &tps51632_dcdc_ops; + tps->desc.type = REGULATOR_VOLTAGE; + tps->desc.owner = THIS_MODULE; + + tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config); + if (IS_ERR(tps->regmap)) { + ret = PTR_ERR(tps->regmap); + dev_err(&client->dev, "regmap init failed, err %d\n", ret); + return ret; + } + i2c_set_clientdata(client, tps); + + ret = tps51632_init_dcdc(tps, pdata); + if (ret < 0) { + dev_err(tps->dev, "Init failed, err = %d\n", ret); + return ret; + } + + /* Register the regulators */ + config.dev = &client->dev; + config.init_data = pdata->reg_init_data; + config.driver_data = tps; + config.regmap = tps->regmap; + config.of_node = client->dev.of_node; + + rdev = regulator_register(&tps->desc, &config); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "regulator register failed\n"); + return PTR_ERR(rdev); + } + + tps->rdev = rdev; + return 0; +} + +static int tps51632_remove(struct i2c_client *client) +{ + struct tps51632_chip *tps = i2c_get_clientdata(client); + + regulator_unregister(tps->rdev); + return 0; +} + +static const struct i2c_device_id tps51632_id[] = { + {.name = "tps51632",}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, tps51632_id); + +static struct i2c_driver tps51632_i2c_driver = { + .driver = { + .name = "tps51632", + .owner = THIS_MODULE, + }, + .probe = tps51632_probe, + .remove = tps51632_remove, + .id_table = tps51632_id, +}; + +static int __init tps51632_init(void) +{ + return i2c_add_driver(&tps51632_i2c_driver); +} +subsys_initcall(tps51632_init); + +static void __exit tps51632_cleanup(void) +{ + i2c_del_driver(&tps51632_i2c_driver); +} +module_exit(tps51632_cleanup); + +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_DESCRIPTION("TPS51632 voltage regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 1378409efae..ec9453ffb77 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = { /* * Registers the chip as a voltage regulator */ -static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) +static int tps6105x_regulator_probe(struct platform_device *pdev) { struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); struct tps6105x_platform_data *pdata = tps6105x->pdata; @@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit tps6105x_regulator_remove(struct platform_device *pdev) +static int tps6105x_regulator_remove(struct platform_device *pdev) { struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev); regulator_unregister(tps6105x->regulator); @@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = { .owner = THIS_MODULE, }, .probe = tps6105x_regulator_probe, - .remove = __devexit_p(tps6105x_regulator_remove), + .remove = tps6105x_regulator_remove, }; static __init int tps6105x_regulator_init(void) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 68729a7c870..acbd63fde41 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = { .get_mode = tps62360_get_mode, }; -static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps, +static int tps62360_init_dcdc(struct tps62360_chip *tps, struct tps62360_regulator_platform_data *pdata) { int ret; @@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = { MODULE_DEVICE_TABLE(of, tps62360_of_match); #endif -static int __devinit tps62360_probe(struct i2c_client *client, +static int tps62360_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct regulator_config config = { }; @@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, * * Unregister TPS driver as an i2c client device driver */ -static int __devexit tps62360_remove(struct i2c_client *client) +static int tps62360_remove(struct i2c_client *client) { struct tps62360_chip *tps = i2c_get_clientdata(client); @@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = { .of_match_table = of_match_ptr(tps62360_of_match), }, .probe = tps62360_probe, - .remove = __devexit_p(tps62360_remove), + .remove = tps62360_remove, .shutdown = tps62360_shutdown, .id_table = tps62360_id, }; diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 6998d579d07..9b9af6d889c 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = { .val_bits = 8, }; -static int __devinit tps_65023_probe(struct i2c_client *client, +static int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct tps_driver_data *drv_data = (void *)id->driver_data; @@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, return error; } -static int __devexit tps_65023_remove(struct i2c_client *client) +static int tps_65023_remove(struct i2c_client *client) { struct tps_pmic *tps = i2c_get_clientdata(client); int i; @@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = { .owner = THIS_MODULE, }, .probe = tps_65023_probe, - .remove = __devexit_p(tps_65023_remove), + .remove = tps_65023_remove, .id_table = tps_65023_id, }; diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 07d01ccdf30..0233cfb5656 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = { .list_voltage = regulator_list_voltage_table, }; -static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) +static int tps6507x_pmic_probe(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); struct tps_info *info = &tps6507x_pmic_regs[0]; @@ -439,7 +439,7 @@ fail: return error; } -static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) +static int tps6507x_pmic_remove(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); struct tps6507x_pmic *tps = tps6507x_dev->pmic; @@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = { .owner = THIS_MODULE, }, .probe = tps6507x_pmic_probe, - .remove = __devexit_p(tps6507x_pmic_remove), + .remove = tps6507x_pmic_remove, }; static int __init tps6507x_pmic_init(void) diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 001ad554ac6..3974a992220 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -18,119 +18,240 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/gpio.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/mfd/tps65090.h> -#include <linux/regulator/tps65090-regulator.h> struct tps65090_regulator { - int id; - /* used by regulator core */ - struct regulator_desc desc; - - /* Device */ struct device *dev; + struct regulator_desc *desc; + struct regulator_dev *rdev; +}; + +static struct regulator_ops tps65090_ext_control_ops = { +}; + +static struct regulator_ops tps65090_reg_contol_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, }; -static struct regulator_ops tps65090_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, +static struct regulator_ops tps65090_ldo_ops = { }; -#define tps65090_REG(_id) \ +#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops) \ { \ - .id = TPS65090_ID_##_id, \ - .desc = { \ - .name = tps65090_rails(_id), \ - .id = TPS65090_ID_##_id, \ - .ops = &tps65090_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .enable_reg = (TPS65090_ID_##_id) + 12, \ - .enable_mask = BIT(0), \ - }, \ + .name = "TPS65090_RAILS"#_id, \ + .supply_name = _sname, \ + .id = TPS65090_REGULATOR_##_id, \ + .ops = &_ops, \ + .enable_reg = _en_reg, \ + .enable_mask = BIT(0), \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ } -static struct tps65090_regulator TPS65090_regulator[] = { - tps65090_REG(DCDC1), - tps65090_REG(DCDC2), - tps65090_REG(DCDC3), - tps65090_REG(FET1), - tps65090_REG(FET2), - tps65090_REG(FET3), - tps65090_REG(FET4), - tps65090_REG(FET5), - tps65090_REG(FET6), - tps65090_REG(FET7), +static struct regulator_desc tps65090_regulator_desc[] = { + tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops), + tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops), + tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops), + tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops), + tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops), + tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops), }; -static inline struct tps65090_regulator *find_regulator_info(int id) +static inline bool is_dcdc(int id) { - struct tps65090_regulator *ri; - int i; + switch (id) { + case TPS65090_REGULATOR_DCDC1: + case TPS65090_REGULATOR_DCDC2: + case TPS65090_REGULATOR_DCDC3: + return true; + default: + return false; + } +} + +static int tps65090_config_ext_control( + struct tps65090_regulator *ri, bool enable) +{ + int ret; + struct device *parent = ri->dev->parent; + unsigned int reg_en_reg = ri->desc->enable_reg; + + if (enable) + ret = tps65090_set_bits(parent, reg_en_reg, 1); + else + ret = tps65090_clr_bits(parent, reg_en_reg, 1); + if (ret < 0) + dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg); + return ret; +} + +static int tps65090_regulator_disable_ext_control( + struct tps65090_regulator *ri, + struct tps65090_regulator_plat_data *tps_pdata) +{ + int ret = 0; + struct device *parent = ri->dev->parent; + unsigned int reg_en_reg = ri->desc->enable_reg; + + /* + * First enable output for internal control if require. + * And then disable external control. + */ + if (tps_pdata->reg_init_data->constraints.always_on || + tps_pdata->reg_init_data->constraints.boot_on) { + ret = tps65090_set_bits(parent, reg_en_reg, 0); + if (ret < 0) { + dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg); + return ret; + } + } + return tps65090_config_ext_control(ri, false); +} + +static void tps65090_configure_regulator_config( + struct tps65090_regulator_plat_data *tps_pdata, + struct regulator_config *config) +{ + if (gpio_is_valid(tps_pdata->gpio)) { + int gpio_flag = GPIOF_OUT_INIT_LOW; + + if (tps_pdata->reg_init_data->constraints.always_on || + tps_pdata->reg_init_data->constraints.boot_on) + gpio_flag = GPIOF_OUT_INIT_HIGH; - for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) { - ri = &TPS65090_regulator[i]; - if (ri->desc.id == id) - return ri; + config->ena_gpio = tps_pdata->gpio; + config->ena_gpio_flags = gpio_flag; } - return NULL; } -static int __devinit tps65090_regulator_probe(struct platform_device *pdev) +static int tps65090_regulator_probe(struct platform_device *pdev) { struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent); struct tps65090_regulator *ri = NULL; struct regulator_config config = { }; struct regulator_dev *rdev; - struct tps65090_regulator_platform_data *tps_pdata; - int id = pdev->id; + struct tps65090_regulator_plat_data *tps_pdata; + struct tps65090_regulator *pmic; + struct tps65090_platform_data *tps65090_pdata; + int num; + int ret; - dev_dbg(&pdev->dev, "Probing regulator %d\n", id); + dev_dbg(&pdev->dev, "Probing regulator\n"); - ri = find_regulator_info(id); - if (ri == NULL) { - dev_err(&pdev->dev, "invalid regulator ID specified\n"); + tps65090_pdata = dev_get_platdata(pdev->dev.parent); + if (!tps65090_pdata) { + dev_err(&pdev->dev, "Platform data missing\n"); return -EINVAL; } - tps_pdata = pdev->dev.platform_data; - ri->dev = &pdev->dev; - - config.dev = &pdev->dev; - config.init_data = &tps_pdata->regulator; - config.driver_data = ri; - config.regmap = tps65090_mfd->rmap; - - rdev = regulator_register(&ri->desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, "failed to register regulator %s\n", - ri->desc.name); - return PTR_ERR(rdev); + + pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), + GFP_KERNEL); + if (!pmic) { + dev_err(&pdev->dev, "mem alloc for pmic failed\n"); + return -ENOMEM; + } + + for (num = 0; num < TPS65090_REGULATOR_MAX; num++) { + tps_pdata = tps65090_pdata->reg_pdata[num]; + + ri = &pmic[num]; + ri->dev = &pdev->dev; + ri->desc = &tps65090_regulator_desc[num]; + + /* + * TPS5090 DCDC support the control from external digital input. + * Configure it as per platform data. + */ + if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) { + if (tps_pdata->enable_ext_control) { + tps65090_configure_regulator_config( + tps_pdata, &config); + ri->desc->ops = &tps65090_ext_control_ops; + } else { + ret = tps65090_regulator_disable_ext_control( + ri, tps_pdata); + if (ret < 0) { + dev_err(&pdev->dev, + "failed disable ext control\n"); + goto scrub; + } + } + } + + config.dev = &pdev->dev; + config.driver_data = ri; + config.regmap = tps65090_mfd->rmap; + if (tps_pdata) + config.init_data = tps_pdata->reg_init_data; + else + config.init_data = NULL; + + rdev = regulator_register(ri->desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + ri->desc->name); + ret = PTR_ERR(rdev); + goto scrub; + } + ri->rdev = rdev; + + /* Enable external control if it is require */ + if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data && + tps_pdata->enable_ext_control) { + ret = tps65090_config_ext_control(ri, true); + if (ret < 0) { + /* Increment num to get unregister rdev */ + num++; + goto scrub; + } + } } - platform_set_drvdata(pdev, rdev); + platform_set_drvdata(pdev, pmic); return 0; + +scrub: + while (--num >= 0) { + ri = &pmic[num]; + regulator_unregister(ri->rdev); + } + return ret; } -static int __devexit tps65090_regulator_remove(struct platform_device *pdev) +static int tps65090_regulator_remove(struct platform_device *pdev) { - struct regulator_dev *rdev = platform_get_drvdata(pdev); + struct tps65090_regulator *pmic = platform_get_drvdata(pdev); + struct tps65090_regulator *ri; + int num; - regulator_unregister(rdev); + for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) { + ri = &pmic[num]; + regulator_unregister(ri->rdev); + } return 0; } static struct platform_driver tps65090_regulator_driver = { .driver = { - .name = "tps65090-regulator", + .name = "tps65090-pmic", .owner = THIS_MODULE, }, .probe = tps65090_regulator_probe, - .remove = __devexit_p(tps65090_regulator_remove), + .remove = tps65090_regulator_remove, }; static int __init tps65090_regulator_init(void) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index ab00cab905b..73dce766412 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) } #endif -static int __devinit tps65217_regulator_probe(struct platform_device *pdev) +static int tps65217_regulator_probe(struct platform_device *pdev) { struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); struct tps65217_board *pdata = dev_get_platdata(tps->dev); @@ -397,7 +397,7 @@ err_unregister_regulator: return ret; } -static int __devexit tps65217_regulator_remove(struct platform_device *pdev) +static int tps65217_regulator_remove(struct platform_device *pdev) { struct tps65217 *tps = platform_get_drvdata(pdev); unsigned int i; @@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = { .name = "tps65217-pmic", }, .probe = tps65217_regulator_probe, - .remove = __devexit_p(tps65217_regulator_remove), + .remove = tps65217_regulator_remove, }; static int __init tps65217_regulator_init(void) diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 058d2f2675e..843ee0a9bb9 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi) return 0; } -static int __devinit pmic_probe(struct spi_device *spi) +static int pmic_probe(struct spi_device *spi) { struct tps6524x *hw; struct device *dev = &spi->dev; @@ -649,7 +649,7 @@ fail: static struct spi_driver pmic_driver = { .probe = pmic_probe, - .remove = __devexit_p(pmic_remove), + .remove = pmic_remove, .driver = { .name = "tps6524x", .owner = THIS_MODULE, diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index ce1e7cb8d51..9ce44109f2a 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -17,10 +17,12 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/err.h> +#include <linux/of.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> #include <linux/mfd/tps6586x.h> /* supply control and voltage setting */ @@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent, 1 << ri->enable_bit[1]); } -static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev) +static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev, + int id, struct regulator_init_data *p) { struct device *parent = pdev->dev.parent; - struct regulator_init_data *p = pdev->dev.platform_data; struct tps6586x_settings *setting = p->driver_data; uint8_t reg; @@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev) return 0; /* only SM0 and SM1 can have the slew rate settings */ - switch (pdev->id) { + switch (id) { case TPS6586X_ID_SM_0: reg = TPS6586X_SM0SL; break; @@ -298,58 +300,185 @@ static inline struct tps6586x_regulator *find_regulator_info(int id) return NULL; } -static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct of_regulator_match tps6586x_matches[] = { + { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS }, + { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 }, + { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 }, + { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 }, + { .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 }, + { .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 }, + { .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 }, + { .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 }, + { .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 }, + { .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 }, + { .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 }, + { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC }, +}; + +static struct tps6586x_platform_data *tps6586x_parse_regulator_dt( + struct platform_device *pdev, + struct of_regulator_match **tps6586x_reg_matches) +{ + const unsigned int num = ARRAY_SIZE(tps6586x_matches); + struct device_node *np = pdev->dev.parent->of_node; + struct device_node *regs; + const char *sys_rail = NULL; + unsigned int i; + struct tps6586x_platform_data *pdata; + int err; + + regs = of_find_node_by_name(np, "regulators"); + if (!regs) { + dev_err(&pdev->dev, "regulator node not found\n"); + return NULL; + } + + err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num); + if (err < 0) { + dev_err(&pdev->dev, "Regulator match failed, e %d\n", err); + of_node_put(regs); + return NULL; + } + + of_node_put(regs); + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "Memory alloction failed\n"); + return NULL; + } + + for (i = 0; i < num; i++) { + int id; + if (!tps6586x_matches[i].init_data) + continue; + + pdata->reg_init_data[i] = tps6586x_matches[i].init_data; + id = (int)tps6586x_matches[i].driver_data; + if (id == TPS6586X_ID_SYS) + sys_rail = pdata->reg_init_data[i]->constraints.name; + + if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC)) + pdata->reg_init_data[i]->supply_regulator = sys_rail; + } + *tps6586x_reg_matches = tps6586x_matches; + return pdata; +} +#else +static struct tps6586x_platform_data *tps6586x_parse_regulator_dt( + struct platform_device *pdev, + struct of_regulator_match **tps6586x_reg_matches) +{ + *tps6586x_reg_matches = NULL; + return NULL; +} +#endif + +static int tps6586x_regulator_probe(struct platform_device *pdev) { struct tps6586x_regulator *ri = NULL; struct regulator_config config = { }; - struct regulator_dev *rdev; - int id = pdev->id; + struct regulator_dev **rdev; + struct regulator_init_data *reg_data; + struct tps6586x_platform_data *pdata; + struct of_regulator_match *tps6586x_reg_matches = NULL; + int id; int err; dev_dbg(&pdev->dev, "Probing regulator %d\n", id); - ri = find_regulator_info(id); - if (ri == NULL) { - dev_err(&pdev->dev, "invalid regulator ID specified\n"); - return -EINVAL; - } + pdata = dev_get_platdata(pdev->dev.parent); + if ((!pdata) && (pdev->dev.parent->of_node)) + pdata = tps6586x_parse_regulator_dt(pdev, + &tps6586x_reg_matches); - err = tps6586x_regulator_preinit(pdev->dev.parent, ri); - if (err) - return err; + if (!pdata) { + dev_err(&pdev->dev, "Platform data not available, exiting\n"); + return -ENODEV; + } - config.dev = pdev->dev.parent; - config.of_node = pdev->dev.of_node; - config.init_data = pdev->dev.platform_data; - config.driver_data = ri; + rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR * + sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + dev_err(&pdev->dev, "Mmemory alloc failed\n"); + return -ENOMEM; + } - rdev = regulator_register(&ri->desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, "failed to register regulator %s\n", - ri->desc.name); - return PTR_ERR(rdev); + for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) { + reg_data = pdata->reg_init_data[id]; + + ri = find_regulator_info(id); + if (!ri) { + dev_err(&pdev->dev, "invalid regulator ID specified\n"); + err = -EINVAL; + goto fail; + } + + err = tps6586x_regulator_preinit(pdev->dev.parent, ri); + if (err) { + dev_err(&pdev->dev, + "regulator %d preinit failed, e %d\n", id, err); + goto fail; + } + + config.dev = pdev->dev.parent; + config.init_data = reg_data; + config.driver_data = ri; + + if (tps6586x_reg_matches) + config.of_node = tps6586x_reg_matches[id].of_node; + + rdev[id] = regulator_register(&ri->desc, &config); + if (IS_ERR(rdev[id])) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + ri->desc.name); + err = PTR_ERR(rdev[id]); + goto fail; + } + + if (reg_data) { + err = tps6586x_regulator_set_slew_rate(pdev, id, + reg_data); + if (err < 0) { + dev_err(&pdev->dev, + "Slew rate config failed, e %d\n", err); + regulator_unregister(rdev[id]); + goto fail; + } + } } platform_set_drvdata(pdev, rdev); + return 0; - return tps6586x_regulator_set_slew_rate(pdev); +fail: + while (--id >= 0) + regulator_unregister(rdev[id]); + return err; } -static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) +static int tps6586x_regulator_remove(struct platform_device *pdev) { - struct regulator_dev *rdev = platform_get_drvdata(pdev); + struct regulator_dev **rdev = platform_get_drvdata(pdev); + int id = TPS6586X_ID_MAX_REGULATOR; + + while (--id >= 0) + regulator_unregister(rdev[id]); - regulator_unregister(rdev); return 0; } static struct platform_driver tps6586x_regulator_driver = { .driver = { - .name = "tps6586x-regulator", + .name = "tps6586x-pmic", .owner = THIS_MODULE, }, .probe = tps6586x_regulator_probe, - .remove = __devexit_p(tps6586x_regulator_remove), + .remove = tps6586x_regulator_remove, }; static int __init tps6586x_regulator_init(void) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 793adda560c..6b77bbf32eb 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1026,7 +1026,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data( } #endif -static __devinit int tps65910_probe(struct platform_device *pdev) +static int tps65910_probe(struct platform_device *pdev) { struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; @@ -1184,7 +1184,7 @@ err_unregister_regulator: return err; } -static int __devexit tps65910_remove(struct platform_device *pdev) +static int tps65910_remove(struct platform_device *pdev) { struct tps65910_reg *pmic = platform_get_drvdata(pdev); int i; @@ -1231,7 +1231,7 @@ static struct platform_driver tps65910_driver = { .owner = THIS_MODULE, }, .probe = tps65910_probe, - .remove = __devexit_p(tps65910_remove), + .remove = tps65910_remove, .shutdown = tps65910_shutdown, }; diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 18b2a1dcb4b..17e994e47dc 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = { .list_voltage = tps65912_list_voltage, }; -static __devinit int tps65912_probe(struct platform_device *pdev) +static int tps65912_probe(struct platform_device *pdev) { struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; @@ -525,7 +525,7 @@ err: return err; } -static int __devexit tps65912_remove(struct platform_device *pdev) +static int tps65912_remove(struct platform_device *pdev) { struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev); int i; @@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = { .owner = THIS_MODULE, }, .probe = tps65912_probe, - .remove = __devexit_p(tps65912_remove), + .remove = tps65912_remove, }; static int __init tps65912_init(void) diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c new file mode 100644 index 00000000000..127d1754fcd --- /dev/null +++ b/drivers/regulator/tps80031-regulator.c @@ -0,0 +1,793 @@ +/* + * tps80031-regulator.c -- TI TPS80031 regulator driver. + * + * Regulator driver for TITPS80031/TPS80032 Fully Integrated Power + * Management with Power Path and Battery Charger. + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * Author: Laxman Dewangan <ldewangan@nvidia.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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, + * whether express or implied; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mfd/tps80031.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/slab.h> + +/* Flags for DCDC Voltage reading */ +#define DCDC_OFFSET_EN BIT(0) +#define DCDC_EXTENDED_EN BIT(1) +#define TRACK_MODE_ENABLE BIT(2) + +#define SMPS_MULTOFFSET_VIO BIT(1) +#define SMPS_MULTOFFSET_SMPS1 BIT(3) +#define SMPS_MULTOFFSET_SMPS2 BIT(4) +#define SMPS_MULTOFFSET_SMPS3 BIT(6) +#define SMPS_MULTOFFSET_SMPS4 BIT(0) + +#define SMPS_CMD_MASK 0xC0 +#define SMPS_VSEL_MASK 0x3F +#define LDO_VSEL_MASK 0x1F +#define LDO_TRACK_VSEL_MASK 0x3F + +#define MISC2_LDOUSB_IN_VSYS BIT(4) +#define MISC2_LDOUSB_IN_PMID BIT(3) +#define MISC2_LDOUSB_IN_MASK 0x18 + +#define MISC2_LDO3_SEL_VIB_VAL BIT(0) +#define MISC2_LDO3_SEL_VIB_MASK 0x1 + +#define BOOST_HW_PWR_EN BIT(5) +#define BOOST_HW_PWR_EN_MASK BIT(5) + +#define OPA_MODE_EN BIT(6) +#define OPA_MODE_EN_MASK BIT(6) + +#define USB_VBUS_CTRL_SET 0x04 +#define USB_VBUS_CTRL_CLR 0x05 +#define VBUS_DISCHRG 0x20 + +struct tps80031_regulator_info { + /* Regulator register address.*/ + u8 trans_reg; + u8 state_reg; + u8 force_reg; + u8 volt_reg; + u8 volt_id; + + /*Power request bits */ + int preq_bit; + + /* used by regulator core */ + struct regulator_desc desc; + +}; + +struct tps80031_regulator { + struct device *dev; + struct regulator_dev *rdev; + struct tps80031_regulator_info *rinfo; + + u8 device_flags; + unsigned int config_flags; + unsigned int ext_ctrl_flag; +}; + +static inline struct device *to_tps80031_dev(struct regulator_dev *rdev) +{ + return rdev_get_dev(rdev)->parent->parent; +} + +static int tps80031_reg_is_enabled(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + u8 reg_val; + int ret; + + if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ) + return true; + + ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg, + ®_val); + if (ret < 0) { + dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n", + ri->rinfo->state_reg, ret); + return ret; + } + return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON); +} + +static int tps80031_reg_enable(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret; + + if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ) + return 0; + + ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg, + TPS80031_STATE_ON, TPS80031_STATE_MASK); + if (ret < 0) { + dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n", + ri->rinfo->state_reg, ret); + return ret; + } + return ret; +} + +static int tps80031_reg_disable(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret; + + if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ) + return 0; + + ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg, + TPS80031_STATE_OFF, TPS80031_STATE_MASK); + if (ret < 0) + dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n", + ri->rinfo->state_reg, ret); + return ret; +} + +/* DCDC voltages for the selector of 58 to 63 */ +static int tps80031_dcdc_voltages[4][5] = { + { 1350, 1500, 1800, 1900, 2100}, + { 1350, 1500, 1800, 1900, 2100}, + { 2084, 2315, 2778, 2932, 3241}, + { 4167, 2315, 2778, 2932, 3241}, +}; + +static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + int volt_index = ri->device_flags & 0x3; + + if (sel == 0) + return 0; + else if (sel < 58) + return regulator_list_voltage_linear(rdev, sel - 1); + else + return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000; +} + +static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev, + unsigned vsel) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret; + u8 reg_val; + + if (ri->rinfo->force_reg) { + ret = tps80031_read(parent, ri->rinfo->volt_id, + ri->rinfo->force_reg, ®_val); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + ri->rinfo->force_reg, ret); + return ret; + } + if (!(reg_val & SMPS_CMD_MASK)) { + ret = tps80031_update(parent, ri->rinfo->volt_id, + ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK); + if (ret < 0) + dev_err(ri->dev, + "reg 0x%02x update failed, e = %d\n", + ri->rinfo->force_reg, ret); + return ret; + } + } + ret = tps80031_update(parent, ri->rinfo->volt_id, + ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK); + if (ret < 0) + dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n", + ri->rinfo->volt_reg, ret); + return ret; +} + +static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + uint8_t vsel = 0; + int ret; + + if (ri->rinfo->force_reg) { + ret = tps80031_read(parent, ri->rinfo->volt_id, + ri->rinfo->force_reg, &vsel); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + ri->rinfo->force_reg, ret); + return ret; + } + + if (!(vsel & SMPS_CMD_MASK)) + return vsel & SMPS_VSEL_MASK; + } + ret = tps80031_read(parent, ri->rinfo->volt_id, + ri->rinfo->volt_reg, &vsel); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + ri->rinfo->volt_reg, ret); + return ret; + } + return vsel & SMPS_VSEL_MASK; +} + +static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev, + unsigned sel) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret; + + /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */ + if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) && + (ri->device_flags & TRACK_MODE_ENABLE)) { + unsigned nvsel = (sel) & 0x1F; + if (((tps80031_get_chip_info(parent) == TPS80031) || + ((tps80031_get_chip_info(parent) == TPS80032) && + (tps80031_get_pmu_version(parent) == 0x0))) && + ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) { + dev_err(ri->dev, + "Invalid sel %d in track mode LDO2\n", + nvsel); + return -EINVAL; + } + } + + ret = tps80031_write(parent, ri->rinfo->volt_id, + ri->rinfo->volt_reg, sel); + if (ret < 0) + dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n", + ri->rinfo->volt_reg, ret); + return ret; +} + +static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + uint8_t vsel; + int ret; + + ret = tps80031_read(parent, ri->rinfo->volt_id, + ri->rinfo->volt_reg, &vsel); + if (ret < 0) { + dev_err(ri->dev, "Error in writing the Voltage register\n"); + return ret; + } + return vsel & rdev->desc->vsel_mask; +} + +static int tps80031_ldo_list_voltage(struct regulator_dev *rdev, unsigned sel) +{ + if (sel == 0) + return 0; + else + return regulator_list_voltage_linear(rdev, sel - 1); +} + +static int tps80031_vbus_is_enabled(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret = -EIO; + uint8_t ctrl1 = 0; + uint8_t ctrl3 = 0; + + ret = tps80031_read(parent, TPS80031_SLAVE_ID2, + TPS80031_CHARGERUSB_CTRL1, &ctrl1); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + TPS80031_CHARGERUSB_CTRL1, ret); + return ret; + } + ret = tps80031_read(parent, TPS80031_SLAVE_ID2, + TPS80031_CHARGERUSB_CTRL3, &ctrl3); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + TPS80031_CHARGERUSB_CTRL1, ret); + return ret; + } + if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN)) + return 1; + return ret; +} + +static int tps80031_vbus_enable(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret; + + ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2, + TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + TPS80031_CHARGERUSB_CTRL1, ret); + return ret; + } + + ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2, + TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n", + TPS80031_CHARGERUSB_CTRL3, ret); + return ret; + } + return ret; +} + +static int tps80031_vbus_disable(struct regulator_dev *rdev) +{ + struct tps80031_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_tps80031_dev(rdev); + int ret = 0; + + if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) { + ret = tps80031_write(parent, TPS80031_SLAVE_ID2, + USB_VBUS_CTRL_SET, VBUS_DISCHRG); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n", + USB_VBUS_CTRL_SET, ret); + return ret; + } + } + + ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2, + TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n", + TPS80031_CHARGERUSB_CTRL1, ret); + return ret; + } + + ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2, + TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n", + TPS80031_CHARGERUSB_CTRL3, ret); + return ret; + } + + mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000)); + if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) { + ret = tps80031_write(parent, TPS80031_SLAVE_ID2, + USB_VBUS_CTRL_CLR, VBUS_DISCHRG); + if (ret < 0) { + dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n", + USB_VBUS_CTRL_CLR, ret); + return ret; + } + } + return ret; +} + +static struct regulator_ops tps80031_dcdc_ops = { + .list_voltage = tps80031_dcdc_list_voltage, + .set_voltage_sel = tps80031_dcdc_set_voltage_sel, + .get_voltage_sel = tps80031_dcdc_get_voltage_sel, + .enable = tps80031_reg_enable, + .disable = tps80031_reg_disable, + .is_enabled = tps80031_reg_is_enabled, +}; + +static struct regulator_ops tps80031_ldo_ops = { + .list_voltage = tps80031_ldo_list_voltage, + .set_voltage_sel = tps80031_ldo_set_voltage_sel, + .get_voltage_sel = tps80031_ldo_get_voltage_sel, + .enable = tps80031_reg_enable, + .disable = tps80031_reg_disable, + .is_enabled = tps80031_reg_is_enabled, +}; + +static struct regulator_ops tps80031_vbus_sw_ops = { + .enable = tps80031_vbus_enable, + .disable = tps80031_vbus_disable, + .is_enabled = tps80031_vbus_is_enabled, +}; + +static struct regulator_ops tps80031_vbus_hw_ops = { +}; + +static struct regulator_ops tps80031_ext_reg_ops = { + .enable = tps80031_reg_enable, + .disable = tps80031_reg_disable, + .is_enabled = tps80031_reg_is_enabled, +}; + +/* Non-exiting default definition for some register */ +#define TPS80031_SMPS3_CFG_FORCE 0 +#define TPS80031_SMPS4_CFG_FORCE 0 + +#define TPS80031_VBUS_CFG_TRANS 0 +#define TPS80031_VBUS_CFG_STATE 0 + +#define TPS80031_REG_SMPS(_id, _volt_id, _pbit) \ +{ \ + .trans_reg = TPS80031_##_id##_CFG_TRANS, \ + .state_reg = TPS80031_##_id##_CFG_STATE, \ + .force_reg = TPS80031_##_id##_CFG_FORCE, \ + .volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \ + .volt_id = TPS80031_SLAVE_##_volt_id, \ + .preq_bit = _pbit, \ + .desc = { \ + .name = "tps80031_"#_id, \ + .id = TPS80031_REGULATOR_##_id, \ + .n_voltages = 63, \ + .ops = &tps80031_dcdc_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .enable_time = 500, \ + }, \ +} + +#define TPS80031_REG_LDO(_id, _preq_bit) \ +{ \ + .trans_reg = TPS80031_##_id##_CFG_TRANS, \ + .state_reg = TPS80031_##_id##_CFG_STATE, \ + .volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \ + .volt_id = TPS80031_SLAVE_ID1, \ + .preq_bit = _preq_bit, \ + .desc = { \ + .owner = THIS_MODULE, \ + .name = "tps80031_"#_id, \ + .id = TPS80031_REGULATOR_##_id, \ + .ops = &tps80031_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = 1000000, \ + .uV_step = 100000, \ + .n_voltages = 25, \ + .vsel_mask = LDO_VSEL_MASK, \ + .enable_time = 500, \ + }, \ +} + +#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit) \ +{ \ + .trans_reg = TPS80031_##_id##_CFG_TRANS, \ + .state_reg = TPS80031_##_id##_CFG_STATE, \ + .volt_id = TPS80031_SLAVE_ID1, \ + .preq_bit = _pbit, \ + .desc = { \ + .name = "tps80031_"#_id, \ + .id = TPS80031_REGULATOR_##_id, \ + .n_voltages = 2, \ + .ops = &_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .enable_time = _delay, \ + }, \ +} + +static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = { + TPS80031_REG_SMPS(VIO, ID0, 4), + TPS80031_REG_SMPS(SMPS1, ID0, 0), + TPS80031_REG_SMPS(SMPS2, ID0, 1), + TPS80031_REG_SMPS(SMPS3, ID1, 2), + TPS80031_REG_SMPS(SMPS4, ID1, 3), + TPS80031_REG_LDO(VANA, -1), + TPS80031_REG_LDO(LDO1, 8), + TPS80031_REG_LDO(LDO2, 9), + TPS80031_REG_LDO(LDO3, 10), + TPS80031_REG_LDO(LDO4, 11), + TPS80031_REG_LDO(LDO5, 12), + TPS80031_REG_LDO(LDO6, 13), + TPS80031_REG_LDO(LDO7, 14), + TPS80031_REG_LDO(LDOLN, 15), + TPS80031_REG_LDO(LDOUSB, 5), + TPS80031_REG_FIXED(VBUS, 5000, tps80031_vbus_hw_ops, 100000, -1), + TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16), + TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17), + TPS80031_REG_FIXED(SYSEN, 3300, tps80031_ext_reg_ops, 0, 18), +}; + +static int tps80031_power_req_config(struct device *parent, + struct tps80031_regulator *ri, + struct tps80031_regulator_platform_data *tps80031_pdata) +{ + int ret = 0; + + if (ri->rinfo->preq_bit < 0) + goto skip_pwr_req_config; + + ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag, + ri->rinfo->preq_bit, ri->rinfo->state_reg, + ri->rinfo->trans_reg); + if (ret < 0) { + dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret); + return ret; + } + +skip_pwr_req_config: + if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) { + ret = tps80031_update(parent, TPS80031_SLAVE_ID1, + ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON, + TPS80031_TRANS_SLEEP_MASK); + if (ret < 0) { + dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n", + ri->rinfo->trans_reg, ret); + return ret; + } + } + return ret; +} + +static int tps80031_regulator_config(struct device *parent, + struct tps80031_regulator *ri, + struct tps80031_regulator_platform_data *tps80031_pdata) +{ + int ret = 0; + + switch (ri->rinfo->desc.id) { + case TPS80031_REGULATOR_LDOUSB: + if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS | + TPS80031_USBLDO_INPUT_PMID)) { + unsigned val = 0; + if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS) + val = MISC2_LDOUSB_IN_VSYS; + else + val = MISC2_LDOUSB_IN_PMID; + + ret = tps80031_update(parent, TPS80031_SLAVE_ID1, + TPS80031_MISC2, val, + MISC2_LDOUSB_IN_MASK); + if (ret < 0) { + dev_err(ri->dev, + "LDOUSB config failed, e= %d\n", ret); + return ret; + } + } + break; + + case TPS80031_REGULATOR_LDO3: + if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) { + ret = tps80031_update(parent, TPS80031_SLAVE_ID1, + TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL, + MISC2_LDO3_SEL_VIB_MASK); + if (ret < 0) { + dev_err(ri->dev, + "LDO3 config failed, e = %d\n", ret); + return ret; + } + } + break; + + case TPS80031_REGULATOR_VBUS: + /* Provide SW control Ops if VBUS is SW control */ + if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY)) + ri->rinfo->desc.ops = &tps80031_vbus_sw_ops; + break; + default: + break; + } + + /* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */ + ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg, + TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF | + TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK | + TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK); + if (ret < 0) { + dev_err(ri->dev, "trans reg update failed, e %d\n", ret); + return ret; + } + + return ret; +} + +static int check_smps_mode_mult(struct device *parent, + struct tps80031_regulator *ri) +{ + int mult_offset; + int ret; + u8 smps_offset; + u8 smps_mult; + + ret = tps80031_read(parent, TPS80031_SLAVE_ID1, + TPS80031_SMPS_OFFSET, &smps_offset); + if (ret < 0) { + dev_err(parent, "Error in reading smps offset register\n"); + return ret; + } + + ret = tps80031_read(parent, TPS80031_SLAVE_ID1, + TPS80031_SMPS_MULT, &smps_mult); + if (ret < 0) { + dev_err(parent, "Error in reading smps mult register\n"); + return ret; + } + + switch (ri->rinfo->desc.id) { + case TPS80031_REGULATOR_VIO: + mult_offset = SMPS_MULTOFFSET_VIO; + break; + case TPS80031_REGULATOR_SMPS1: + mult_offset = SMPS_MULTOFFSET_SMPS1; + break; + case TPS80031_REGULATOR_SMPS2: + mult_offset = SMPS_MULTOFFSET_SMPS2; + break; + case TPS80031_REGULATOR_SMPS3: + mult_offset = SMPS_MULTOFFSET_SMPS3; + break; + case TPS80031_REGULATOR_SMPS4: + mult_offset = SMPS_MULTOFFSET_SMPS4; + break; + case TPS80031_REGULATOR_LDO2: + ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0; + /* TRACK mode the ldo2 varies from 600mV to 1300mV */ + if (ri->device_flags & TRACK_MODE_ENABLE) { + ri->rinfo->desc.min_uV = 600000; + ri->rinfo->desc.uV_step = 12500; + ri->rinfo->desc.n_voltages = 57; + ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK; + } + return 0; + default: + return 0; + } + + ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0; + ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0; + switch (ri->device_flags) { + case 0: + ri->rinfo->desc.min_uV = 607700; + ri->rinfo->desc.uV_step = 12660; + break; + case DCDC_OFFSET_EN: + ri->rinfo->desc.min_uV = 700000; + ri->rinfo->desc.uV_step = 12500; + break; + case DCDC_EXTENDED_EN: + ri->rinfo->desc.min_uV = 1852000; + ri->rinfo->desc.uV_step = 38600; + break; + case DCDC_OFFSET_EN | DCDC_EXTENDED_EN: + ri->rinfo->desc.min_uV = 2161000; + ri->rinfo->desc.uV_step = 38600; + break; + } + return 0; +} + +static int tps80031_regulator_probe(struct platform_device *pdev) +{ + struct tps80031_platform_data *pdata; + struct tps80031_regulator_platform_data *tps_pdata; + struct tps80031_regulator_info *rinfo; + struct tps80031_regulator *ri; + struct tps80031_regulator *pmic; + struct regulator_dev *rdev; + struct regulator_config config = { }; + int ret; + int num; + + pdata = dev_get_platdata(pdev->dev.parent); + + if (!pdata) { + dev_err(&pdev->dev, "No platform data\n"); + return -EINVAL; + } + + pmic = devm_kzalloc(&pdev->dev, + TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL); + if (!pmic) { + dev_err(&pdev->dev, "mem alloc for pmic failed\n"); + return -ENOMEM; + } + + for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) { + tps_pdata = pdata->regulator_pdata[num]; + rinfo = &tps80031_rinfo[num]; + ri = &pmic[num]; + ri->rinfo = rinfo; + ri->dev = &pdev->dev; + + check_smps_mode_mult(pdev->dev.parent, ri); + config.dev = &pdev->dev; + config.init_data = NULL; + config.driver_data = ri; + if (tps_pdata) { + config.init_data = tps_pdata->reg_init_data; + ri->config_flags = tps_pdata->config_flags; + ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag; + ret = tps80031_regulator_config(pdev->dev.parent, + ri, tps_pdata); + if (ret < 0) { + dev_err(&pdev->dev, + "regulator config failed, e %d\n", ret); + goto fail; + } + + ret = tps80031_power_req_config(pdev->dev.parent, + ri, tps_pdata); + if (ret < 0) { + dev_err(&pdev->dev, + "pwr_req config failed, err %d\n", ret); + goto fail; + } + } + rdev = regulator_register(&ri->rinfo->desc, &config); + if (IS_ERR_OR_NULL(rdev)) { + dev_err(&pdev->dev, + "register regulator failed %s\n", + ri->rinfo->desc.name); + ret = PTR_ERR(rdev); + goto fail; + } + ri->rdev = rdev; + } + + platform_set_drvdata(pdev, pmic); + return 0; +fail: + while (--num >= 0) { + ri = &pmic[num]; + regulator_unregister(ri->rdev); + } + return ret; +} + +static int tps80031_regulator_remove(struct platform_device *pdev) +{ + struct tps80031_regulator *pmic = platform_get_drvdata(pdev); + struct tps80031_regulator *ri = NULL; + int num; + + for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) { + ri = &pmic[num]; + regulator_unregister(ri->rdev); + } + return 0; +} + +static struct platform_driver tps80031_regulator_driver = { + .driver = { + .name = "tps80031-pmic", + .owner = THIS_MODULE, + }, + .probe = tps80031_regulator_probe, + .remove = tps80031_regulator_remove, +}; + +static int __init tps80031_regulator_init(void) +{ + return platform_driver_register(&tps80031_regulator_driver); +} +subsys_initcall(tps80031_regulator_init); + +static void __exit tps80031_regulator_exit(void) +{ + platform_driver_unregister(&tps80031_regulator_driver); +} +module_exit(tps80031_regulator_exit); + +MODULE_ALIAS("platform:tps80031-regulator"); +MODULE_DESCRIPTION("Regulator Driver for TI TPS80031 PMIC"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 7eb986a4074..493c8c6a241 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = { }; MODULE_DEVICE_TABLE(of, twl_of_match); -static int __devinit twlreg_probe(struct platform_device *pdev) +static int twlreg_probe(struct platform_device *pdev) { int i, id; struct twlreg_info *info; @@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) return 0; } -static int __devexit twlreg_remove(struct platform_device *pdev) +static int twlreg_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); struct twlreg_info *info = rdev->reg_data; @@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg"); static struct platform_driver twlreg_driver = { .probe = twlreg_probe, - .remove = __devexit_p(twlreg_remove), + .remove = twlreg_remove, /* NOTE: short name, to work around driver model truncation of * "twl_regulator.12" (and friends) to "twl_regulator.1". */ diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c new file mode 100644 index 00000000000..4668c7f8133 --- /dev/null +++ b/drivers/regulator/vexpress.c @@ -0,0 +1,147 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2012 ARM Limited + */ + +#define DRVNAME "vexpress-regulator" +#define pr_fmt(fmt) DRVNAME ": " fmt + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/vexpress.h> + +struct vexpress_regulator { + struct regulator_desc desc; + struct regulator_dev *regdev; + struct vexpress_config_func *func; +}; + +static int vexpress_regulator_get_voltage(struct regulator_dev *regdev) +{ + struct vexpress_regulator *reg = rdev_get_drvdata(regdev); + u32 uV; + int err = vexpress_config_read(reg->func, 0, &uV); + + return err ? err : uV; +} + +static int vexpress_regulator_set_voltage(struct regulator_dev *regdev, + int min_uV, int max_uV, unsigned *selector) +{ + struct vexpress_regulator *reg = rdev_get_drvdata(regdev); + + return vexpress_config_write(reg->func, 0, min_uV); +} + +static struct regulator_ops vexpress_regulator_ops_ro = { + .get_voltage = vexpress_regulator_get_voltage, +}; + +static struct regulator_ops vexpress_regulator_ops = { + .get_voltage = vexpress_regulator_get_voltage, + .set_voltage = vexpress_regulator_set_voltage, +}; + +static int vexpress_regulator_probe(struct platform_device *pdev) +{ + int err; + struct vexpress_regulator *reg; + struct regulator_init_data *init_data; + struct regulator_config config = { }; + + reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL); + if (!reg) { + err = -ENOMEM; + goto error_kzalloc; + } + + reg->func = vexpress_config_func_get_by_dev(&pdev->dev); + if (!reg->func) { + err = -ENXIO; + goto error_get_func; + } + + reg->desc.name = dev_name(&pdev->dev); + reg->desc.type = REGULATOR_VOLTAGE; + reg->desc.owner = THIS_MODULE; + reg->desc.continuous_voltage_range = true; + + init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); + if (!init_data) { + err = -EINVAL; + goto error_get_regulator_init_data; + } + + init_data->constraints.apply_uV = 0; + if (init_data->constraints.min_uV && init_data->constraints.max_uV) + reg->desc.ops = &vexpress_regulator_ops; + else + reg->desc.ops = &vexpress_regulator_ops_ro; + + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = reg; + config.of_node = pdev->dev.of_node; + + reg->regdev = regulator_register(®->desc, &config); + if (IS_ERR(reg->regdev)) { + err = PTR_ERR(reg->regdev); + goto error_regulator_register; + } + + platform_set_drvdata(pdev, reg); + + return 0; + +error_regulator_register: +error_get_regulator_init_data: + vexpress_config_func_put(reg->func); +error_get_func: +error_kzalloc: + return err; +} + +static int vexpress_regulator_remove(struct platform_device *pdev) +{ + struct vexpress_regulator *reg = platform_get_drvdata(pdev); + + vexpress_config_func_put(reg->func); + regulator_unregister(reg->regdev); + + return 0; +} + +static struct of_device_id vexpress_regulator_of_match[] = { + { .compatible = "arm,vexpress-volt", }, + { } +}; + +static struct platform_driver vexpress_regulator_driver = { + .probe = vexpress_regulator_probe, + .remove = vexpress_regulator_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + .of_match_table = vexpress_regulator_of_match, + }, +}; + +module_platform_driver(vexpress_regulator_driver); + +MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>"); +MODULE_DESCRIPTION("Versatile Express regulator"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:vexpress-regulator"); diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c index c038e742253..01c66e9712a 100644 --- a/drivers/regulator/virtual.c +++ b/drivers/regulator/virtual.c @@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = { .attrs = regulator_virtual_attributes, }; -static int __devinit regulator_virtual_probe(struct platform_device *pdev) +static int regulator_virtual_probe(struct platform_device *pdev) { char *reg_id = pdev->dev.platform_data; struct virtual_consumer_data *drvdata; @@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev) return 0; } -static int __devexit regulator_virtual_remove(struct platform_device *pdev) +static int regulator_virtual_remove(struct platform_device *pdev) { struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev); @@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev) static struct platform_driver regulator_virtual_consumer_driver = { .probe = regulator_virtual_probe, - .remove = __devexit_p(regulator_virtual_remove), + .remove = regulator_virtual_remove, .driver = { .name = "reg-virt-consumer", .owner = THIS_MODULE, diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 782c228a19b..bce25658e12 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev, if (vsel > dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, - dcdc->dvs_vsel); + vsel); if (ret == 0) dcdc->dvs_vsel = vsel; else @@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = { * Set up DVS control. We just log errors since we can still run * (with reduced performance) if we fail. */ -static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, +static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, struct wm831x_buckv_pdata *pdata) { struct wm831x *wm831x = dcdc->wm831x; @@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, } } -static __devinit int wm831x_buckv_probe(struct platform_device *pdev) +static int wm831x_buckv_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -562,7 +562,7 @@ err: return ret; } -static __devexit int wm831x_buckv_remove(struct platform_device *pdev) +static int wm831x_buckv_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); struct wm831x *wm831x = dcdc->wm831x; @@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev) static struct platform_driver wm831x_buckv_driver = { .probe = wm831x_buckv_probe, - .remove = __devexit_p(wm831x_buckv_remove), + .remove = wm831x_buckv_remove, .driver = { .name = "wm831x-buckv", .owner = THIS_MODULE, @@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = { .set_suspend_mode = wm831x_dcdc_set_suspend_mode, }; -static __devinit int wm831x_buckp_probe(struct platform_device *pdev) +static int wm831x_buckp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -710,7 +710,7 @@ err: return ret; } -static __devexit int wm831x_buckp_remove(struct platform_device *pdev) +static int wm831x_buckp_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); @@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev) static struct platform_driver wm831x_buckp_driver = { .probe = wm831x_buckp_probe, - .remove = __devexit_p(wm831x_buckp_remove), + .remove = wm831x_buckp_remove, .driver = { .name = "wm831x-buckp", .owner = THIS_MODULE, @@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = { .disable = regulator_disable_regmap, }; -static __devinit int wm831x_boostp_probe(struct platform_device *pdev) +static int wm831x_boostp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -845,7 +845,7 @@ err: return ret; } -static __devexit int wm831x_boostp_remove(struct platform_device *pdev) +static int wm831x_boostp_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); @@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev) static struct platform_driver wm831x_boostp_driver = { .probe = wm831x_boostp_probe, - .remove = __devexit_p(wm831x_boostp_remove), + .remove = wm831x_boostp_remove, .driver = { .name = "wm831x-boostp", .owner = THIS_MODULE, @@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = { .get_status = wm831x_dcdc_get_status, }; -static __devinit int wm831x_epe_probe(struct platform_device *pdev) +static int wm831x_epe_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -936,7 +936,7 @@ err: return ret; } -static __devexit int wm831x_epe_remove(struct platform_device *pdev) +static int wm831x_epe_remove(struct platform_device *pdev) { struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); @@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev) static struct platform_driver wm831x_epe_driver = { .probe = wm831x_epe_probe, - .remove = __devexit_p(wm831x_epe_remove), + .remove = wm831x_epe_remove, .driver = { .name = "wm831x-epe", .owner = THIS_MODULE, diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 2646a1902b3..68586ee3e1c 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data) } -static __devinit int wm831x_isink_probe(struct platform_device *pdev) +static int wm831x_isink_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -221,7 +221,7 @@ err: return ret; } -static __devexit int wm831x_isink_remove(struct platform_device *pdev) +static int wm831x_isink_remove(struct platform_device *pdev) { struct wm831x_isink *isink = platform_get_drvdata(pdev); @@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev) static struct platform_driver wm831x_isink_driver = { .probe = wm831x_isink_probe, - .remove = __devexit_p(wm831x_isink_remove), + .remove = wm831x_isink_remove, .driver = { .name = "wm831x-isink", .owner = THIS_MODULE, diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index c2dc03993dc..1ec379a9a95 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = { .disable = regulator_disable_regmap, }; -static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) +static int wm831x_gp_ldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -334,7 +334,7 @@ err: return ret; } -static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev) +static int wm831x_gp_ldo_remove(struct platform_device *pdev) { struct wm831x_ldo *ldo = platform_get_drvdata(pdev); @@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev) static struct platform_driver wm831x_gp_ldo_driver = { .probe = wm831x_gp_ldo_probe, - .remove = __devexit_p(wm831x_gp_ldo_remove), + .remove = wm831x_gp_ldo_remove, .driver = { .name = "wm831x-ldo", .owner = THIS_MODULE, @@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = { .disable = regulator_disable_regmap, }; -static __devinit int wm831x_aldo_probe(struct platform_device *pdev) +static int wm831x_aldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -590,7 +590,7 @@ err: return ret; } -static __devexit int wm831x_aldo_remove(struct platform_device *pdev) +static int wm831x_aldo_remove(struct platform_device *pdev) { struct wm831x_ldo *ldo = platform_get_drvdata(pdev); @@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev) static struct platform_driver wm831x_aldo_driver = { .probe = wm831x_aldo_probe, - .remove = __devexit_p(wm831x_aldo_remove), + .remove = wm831x_aldo_remove, .driver = { .name = "wm831x-aldo", .owner = THIS_MODULE, @@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = { .disable = regulator_disable_regmap, }; -static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) +static int wm831x_alive_ldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -737,7 +737,7 @@ err: return ret; } -static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev) +static int wm831x_alive_ldo_remove(struct platform_device *pdev) { struct wm831x_ldo *ldo = platform_get_drvdata(pdev); @@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev) static struct platform_driver wm831x_alive_ldo_driver = { .probe = wm831x_alive_ldo_probe, - .remove = __devexit_p(wm831x_alive_ldo_remove), + .remove = wm831x_alive_ldo_remove, .driver = { .name = "wm831x-alive-ldo", .owner = THIS_MODULE, diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 27c746ef063..c6a32ea80b9 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = { }, }; -static int __devinit wm8400_regulator_probe(struct platform_device *pdev) +static int wm8400_regulator_probe(struct platform_device *pdev) { struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]); struct regulator_config config = { }; @@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev) return 0; } -static int __devexit wm8400_regulator_remove(struct platform_device *pdev) +static int wm8400_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = { .name = "wm8400-regulator", }, .probe = wm8400_regulator_probe, - .remove = __devexit_p(wm8400_regulator_remove), + .remove = wm8400_regulator_remove, }; /** diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 86bb48db149..6ff87234264 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = { }, }; -static __devinit int wm8994_ldo_probe(struct platform_device *pdev) +static int wm8994_ldo_probe(struct platform_device *pdev) { struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); struct wm8994_pdata *pdata = wm8994->dev->platform_data; @@ -142,7 +142,7 @@ err: return ret; } -static __devexit int wm8994_ldo_remove(struct platform_device *pdev) +static int wm8994_ldo_remove(struct platform_device *pdev) { struct wm8994_ldo *ldo = platform_get_drvdata(pdev); @@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev) static struct platform_driver wm8994_ldo_driver = { .probe = wm8994_ldo_probe, - .remove = __devexit_p(wm8994_ldo_remove), + .remove = wm8994_ldo_remove, .driver = { .name = "wm8994-ldo", .owner = THIS_MODULE, |