Merge remote-tracking branches 'regulator/fix/pfuze100', 'regulator/fix/s5m8767', 'regulator/topic/ab8500', 'regulator/topic/act8865', 'regulator/topic/anatop', 'regulator/topic/arizona' and 'regulator/topic/as3722' into regulator-linus

This commit is contained in:
Mark Brown 2014-01-23 12:01:24 +00:00
13 changed files with 537 additions and 191 deletions

View File

@ -0,0 +1,60 @@
ACT8865 regulator
-------------------
Required properties:
- compatible: "active-semi,act8865"
- reg: I2C slave address
Any standard regulator properties can be used to configure the single regulator.
The valid names for regulators are:
DCDC_REG1, DCDC_REG2, DCDC_REG3, LDO_REG1, LDO_REG2, LDO_REG3, LDO_REG4.
Example:
--------
i2c1: i2c@f0018000 {
pmic: act8865@5b {
compatible = "active-semi,act8865";
reg = <0x5b>;
status = "disabled";
regulators {
vcc_1v8_reg: DCDC_REG1 {
regulator-name = "VCC_1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
vcc_1v2_reg: DCDC_REG2 {
regulator-name = "VCC_1V2";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1300000>;
regulator-suspend-mem-microvolt = <1150000>;
regulator-suspend-standby-microvolt = <1150000>;
regulator-always-on;
};
vcc_3v3_reg: DCDC_REG3 {
regulator-name = "VCC_3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vddana_reg: LDO_REG1 {
regulator-name = "VDDANA";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vddfuse_reg: LDO_REG2 {
regulator-name = "FUSE_2V5";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
};
};
};
};

View File

@ -83,7 +83,7 @@ as per the datasheet of s5m8767.
- LDOn - LDOn
- valid values for n are 1 to 28 - valid values for n are 1 to 28
- Example: LDO0, LD01, LDO28 - Example: LDO1, LD02, LDO28
- BUCKn - BUCKn
- valid values for n are 1 to 9. - valid values for n are 1 to 9.
- Example: BUCK1, BUCK2, BUCK9 - Example: BUCK1, BUCK2, BUCK9

View File

@ -3,6 +3,7 @@ Device tree binding vendor prefix registry. Keep list in alphabetical order.
This isn't an exhaustive list, but you should add new prefixes to it before This isn't an exhaustive list, but you should add new prefixes to it before
using them to avoid name-space collisions. using them to avoid name-space collisions.
active-semi Active-Semi International Inc
ad Avionic Design GmbH ad Avionic Design GmbH
adi Analog Devices, Inc. adi Analog Devices, Inc.
aeroflexgaisler Aeroflex Gaisler AB aeroflexgaisler Aeroflex Gaisler AB

View File

@ -70,6 +70,14 @@ config REGULATOR_88PM8607
help help
This driver supports 88PM8607 voltage regulator chips. This driver supports 88PM8607 voltage regulator chips.
config REGULATOR_ACT8865
tristate "Active-semi act8865 voltage regulator"
depends on I2C
select REGMAP_I2C
help
This driver controls a active-semi act8865 voltage output
regulator via I2C bus.
config REGULATOR_AD5398 config REGULATOR_AD5398
tristate "Analog Devices AD5398/AD5821 regulators" tristate "Analog Devices AD5398/AD5821 regulators"
depends on I2C depends on I2C

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o
obj-$(CONFIG_REGULATOR_ACT8865) += act8865-regulator.o
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o

View File

@ -2998,37 +2998,6 @@ static void abx500_get_regulator_info(struct ab8500 *ab8500)
} }
} }
static int ab8500_regulator_init_registers(struct platform_device *pdev,
int id, int mask, int value)
{
struct ab8500_reg_init *reg_init = abx500_regulator.init;
int err;
BUG_ON(value & ~mask);
BUG_ON(mask & ~reg_init[id].mask);
/* initialize register */
err = abx500_mask_and_set_register_interruptible(
&pdev->dev,
reg_init[id].bank,
reg_init[id].addr,
mask, value);
if (err < 0) {
dev_err(&pdev->dev,
"Failed to initialize 0x%02x, 0x%02x.\n",
reg_init[id].bank,
reg_init[id].addr);
return err;
}
dev_vdbg(&pdev->dev,
" init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
reg_init[id].bank,
reg_init[id].addr,
mask, value);
return 0;
}
static int ab8500_regulator_register(struct platform_device *pdev, static int ab8500_regulator_register(struct platform_device *pdev,
struct regulator_init_data *init_data, struct regulator_init_data *init_data,
int id, struct device_node *np) int id, struct device_node *np)
@ -3036,7 +3005,6 @@ static int ab8500_regulator_register(struct platform_device *pdev,
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_regulator_info *info = NULL; struct ab8500_regulator_info *info = NULL;
struct regulator_config config = { }; struct regulator_config config = { };
int err;
/* assign per-regulator data */ /* assign per-regulator data */
info = &abx500_regulator.info[id]; info = &abx500_regulator.info[id];
@ -3058,17 +3026,12 @@ static int ab8500_regulator_register(struct platform_device *pdev,
} }
/* register regulator with framework */ /* register regulator with framework */
info->regulator = regulator_register(&info->desc, &config); info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
&config);
if (IS_ERR(info->regulator)) { if (IS_ERR(info->regulator)) {
err = PTR_ERR(info->regulator);
dev_err(&pdev->dev, "failed to register regulator %s\n", dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name); info->desc.name);
/* when we fail, un-register all earlier regulators */ return PTR_ERR(info->regulator);
while (--id >= 0) {
info = &abx500_regulator.info[id];
regulator_unregister(info->regulator);
}
return err;
} }
return 0; return 0;
@ -3095,9 +3058,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
{ {
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct ab8500_platform_data *ppdata; int err;
struct ab8500_regulator_platform_data *pdata;
int i, err;
if (!ab8500) { if (!ab8500) {
dev_err(&pdev->dev, "null mfd parent\n"); dev_err(&pdev->dev, "null mfd parent\n");
@ -3106,83 +3067,20 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
abx500_get_regulator_info(ab8500); abx500_get_regulator_info(ab8500);
if (np) { err = of_regulator_match(&pdev->dev, np,
err = of_regulator_match(&pdev->dev, np, abx500_regulator.match,
abx500_regulator.match, abx500_regulator.match_size);
abx500_regulator.match_size); if (err < 0) {
if (err < 0) { dev_err(&pdev->dev,
dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", err);
"Error parsing regulator init data: %d\n", err);
return err;
}
err = ab8500_regulator_of_probe(pdev, np);
return err; return err;
} }
return ab8500_regulator_of_probe(pdev, np);
ppdata = dev_get_platdata(ab8500->dev);
if (!ppdata) {
dev_err(&pdev->dev, "null parent pdata\n");
return -EINVAL;
}
pdata = ppdata->regulator;
if (!pdata) {
dev_err(&pdev->dev, "null pdata\n");
return -EINVAL;
}
/* make sure the platform data has the correct size */
if (pdata->num_regulator != abx500_regulator.info_size) {
dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
return -EINVAL;
}
/* initialize debug (initial state is recorded with this call) */
err = ab8500_regulator_debug_init(pdev);
if (err)
return err;
/* initialize registers */
for (i = 0; i < pdata->num_reg_init; i++) {
int id, mask, value;
id = pdata->reg_init[i].id;
mask = pdata->reg_init[i].mask;
value = pdata->reg_init[i].value;
/* check for configuration errors */
BUG_ON(id >= abx500_regulator.init_size);
err = ab8500_regulator_init_registers(pdev, id, mask, value);
if (err < 0)
return err;
}
/* register all regulators */
for (i = 0; i < abx500_regulator.info_size; i++) {
err = ab8500_regulator_register(pdev, &pdata->regulator[i],
i, NULL);
if (err < 0)
return err;
}
return 0;
} }
static int ab8500_regulator_remove(struct platform_device *pdev) static int ab8500_regulator_remove(struct platform_device *pdev)
{ {
int i, err; int err;
for (i = 0; i < abx500_regulator.info_size; i++) {
struct ab8500_regulator_info *info = NULL;
info = &abx500_regulator.info[i];
dev_vdbg(rdev_get_dev(info->regulator),
"%s-remove\n", info->desc.name);
regulator_unregister(info->regulator);
}
/* remove regulator debug */ /* remove regulator debug */
err = ab8500_regulator_debug_exit(pdev); err = ab8500_regulator_debug_exit(pdev);

View File

@ -0,0 +1,349 @@
/*
* act8865-regulator.c - Voltage regulation for the active-semi ACT8865
* http://www.active-semi.com/sheets/ACT8865_Datasheet.pdf
*
* Copyright (C) 2013 Atmel Corporation
*
* 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.
*
* 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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/act8865.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regmap.h>
/*
* ACT8865 Global Register Map.
*/
#define ACT8865_SYS_MODE 0x00
#define ACT8865_SYS_CTRL 0x01
#define ACT8865_DCDC1_VSET1 0x20
#define ACT8865_DCDC1_VSET2 0x21
#define ACT8865_DCDC1_CTRL 0x22
#define ACT8865_DCDC2_VSET1 0x30
#define ACT8865_DCDC2_VSET2 0x31
#define ACT8865_DCDC2_CTRL 0x32
#define ACT8865_DCDC3_VSET1 0x40
#define ACT8865_DCDC3_VSET2 0x41
#define ACT8865_DCDC3_CTRL 0x42
#define ACT8865_LDO1_VSET 0x50
#define ACT8865_LDO1_CTRL 0x51
#define ACT8865_LDO2_VSET 0x54
#define ACT8865_LDO2_CTRL 0x55
#define ACT8865_LDO3_VSET 0x60
#define ACT8865_LDO3_CTRL 0x61
#define ACT8865_LDO4_VSET 0x64
#define ACT8865_LDO4_CTRL 0x65
/*
* Field Definitions.
*/
#define ACT8865_ENA 0x80 /* ON - [7] */
#define ACT8865_VSEL_MASK 0x3F /* VSET - [5:0] */
/*
* ACT8865 voltage number
*/
#define ACT8865_VOLTAGE_NUM 64
struct act8865 {
struct regulator_dev *rdev[ACT8865_REG_NUM];
struct regmap *regmap;
};
static const struct regmap_config act8865_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct regulator_linear_range act8865_volatge_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
};
static struct regulator_ops act8865_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_desc act8865_reg[] = {
{
.name = "DCDC_REG1",
.id = ACT8865_ID_DCDC1,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_DCDC1_VSET1,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_DCDC1_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
{
.name = "DCDC_REG2",
.id = ACT8865_ID_DCDC2,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_DCDC2_VSET1,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_DCDC2_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
{
.name = "DCDC_REG3",
.id = ACT8865_ID_DCDC3,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_DCDC3_VSET1,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_DCDC3_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
{
.name = "LDO_REG1",
.id = ACT8865_ID_LDO1,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_LDO1_VSET,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_LDO1_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
{
.name = "LDO_REG2",
.id = ACT8865_ID_LDO2,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_LDO2_VSET,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_LDO2_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
{
.name = "LDO_REG3",
.id = ACT8865_ID_LDO3,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_LDO3_VSET,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_LDO3_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
{
.name = "LDO_REG4",
.id = ACT8865_ID_LDO4,
.ops = &act8865_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = ACT8865_VOLTAGE_NUM,
.linear_ranges = act8865_volatge_ranges,
.n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
.vsel_reg = ACT8865_LDO4_VSET,
.vsel_mask = ACT8865_VSEL_MASK,
.enable_reg = ACT8865_LDO4_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
},
};
#ifdef CONFIG_OF
static const struct of_device_id act8865_dt_ids[] = {
{ .compatible = "active-semi,act8865" },
{ }
};
MODULE_DEVICE_TABLE(of, act8865_dt_ids);
static struct of_regulator_match act8865_matches[] = {
[ACT8865_ID_DCDC1] = { .name = "DCDC_REG1"},
[ACT8865_ID_DCDC2] = { .name = "DCDC_REG2"},
[ACT8865_ID_DCDC3] = { .name = "DCDC_REG3"},
[ACT8865_ID_LDO1] = { .name = "LDO_REG1"},
[ACT8865_ID_LDO2] = { .name = "LDO_REG2"},
[ACT8865_ID_LDO3] = { .name = "LDO_REG3"},
[ACT8865_ID_LDO4] = { .name = "LDO_REG4"},
};
static int act8865_pdata_from_dt(struct device *dev,
struct device_node **of_node,
struct act8865_platform_data *pdata)
{
int matched, i;
struct device_node *np;
struct act8865_regulator_data *regulator;
np = of_find_node_by_name(dev->of_node, "regulators");
if (!np) {
dev_err(dev, "missing 'regulators' subnode in DT\n");
return -EINVAL;
}
matched = of_regulator_match(dev, np,
act8865_matches, ARRAY_SIZE(act8865_matches));
if (matched <= 0)
return matched;
pdata->regulators = devm_kzalloc(dev,
sizeof(struct act8865_regulator_data) *
ARRAY_SIZE(act8865_matches), GFP_KERNEL);
if (!pdata->regulators) {
dev_err(dev, "%s: failed to allocate act8865 registor\n",
__func__);
return -ENOMEM;
}
pdata->num_regulators = matched;
regulator = pdata->regulators;
for (i = 0; i < ARRAY_SIZE(act8865_matches); i++) {
regulator->id = i;
regulator->name = act8865_matches[i].name;
regulator->platform_data = act8865_matches[i].init_data;
of_node[i] = act8865_matches[i].of_node;
regulator++;
}
return 0;
}
#else
static inline int act8865_pdata_from_dt(struct device *dev,
struct device_node **of_node,
struct act8865_platform_data *pdata)
{
return 0;
}
#endif
static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
struct regulator_dev **rdev;
struct device *dev = &client->dev;
struct act8865_platform_data *pdata = dev_get_platdata(dev);
struct regulator_config config = { };
struct act8865 *act8865;
struct device_node *of_node[ACT8865_REG_NUM];
int i, id;
int ret = -EINVAL;
int error;
if (dev->of_node && !pdata) {
const struct of_device_id *id;
struct act8865_platform_data pdata_of;
id = of_match_device(of_match_ptr(act8865_dt_ids), dev);
if (!id)
return -ENODEV;
ret = act8865_pdata_from_dt(dev, of_node, &pdata_of);
if (ret < 0)
return ret;
pdata = &pdata_of;
}
if (pdata->num_regulators > ACT8865_REG_NUM) {
dev_err(dev, "Too many regulators found!\n");
return -EINVAL;
}
act8865 = devm_kzalloc(dev, sizeof(struct act8865), GFP_KERNEL);
if (!act8865)
return -ENOMEM;
rdev = act8865->rdev;
act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config);
if (IS_ERR(act8865->regmap)) {
error = PTR_ERR(act8865->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
error);
return error;
}
/* Finally register devices */
for (i = 0; i < ACT8865_REG_NUM; i++) {
id = pdata->regulators[i].id;
config.dev = dev;
config.init_data = pdata->regulators[i].platform_data;
config.of_node = of_node[i];
config.driver_data = act8865;
config.regmap = act8865->regmap;
rdev[i] = devm_regulator_register(&client->dev,
&act8865_reg[i], &config);
if (IS_ERR(rdev[i])) {
dev_err(dev, "failed to register %s\n",
act8865_reg[id].name);
return PTR_ERR(rdev[i]);
}
}
i2c_set_clientdata(client, act8865);
return 0;
}
static const struct i2c_device_id act8865_ids[] = {
{ "act8865", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, act8865_ids);
static struct i2c_driver act8865_pmic_driver = {
.driver = {
.name = "act8865",
.owner = THIS_MODULE,
},
.probe = act8865_pmic_probe,
.id_table = act8865_ids,
};
module_i2c_driver(act8865_pmic_driver);
MODULE_DESCRIPTION("active-semi act8865 voltage regulator driver");
MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
MODULE_LICENSE("GPL v2");

View File

@ -122,10 +122,8 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (!sreg) if (!sreg)
return -ENOMEM; return -ENOMEM;
sreg->initdata = initdata; sreg->initdata = initdata;
sreg->name = kstrdup(of_get_property(np, "regulator-name", NULL), sreg->name = of_get_property(np, "regulator-name", NULL);
GFP_KERNEL);
rdesc = &sreg->rdesc; rdesc = &sreg->rdesc;
memset(rdesc, 0, sizeof(*rdesc));
rdesc->name = sreg->name; rdesc->name = sreg->name;
rdesc->ops = &anatop_rops; rdesc->ops = &anatop_rops;
rdesc->type = REGULATOR_VOLTAGE; rdesc->type = REGULATOR_VOLTAGE;
@ -143,37 +141,37 @@ static int anatop_regulator_probe(struct platform_device *pdev)
&sreg->control_reg); &sreg->control_reg);
if (ret) { if (ret) {
dev_err(dev, "no anatop-reg-offset property set\n"); dev_err(dev, "no anatop-reg-offset property set\n");
goto anatop_probe_end; return ret;
} }
ret = of_property_read_u32(np, "anatop-vol-bit-width", ret = of_property_read_u32(np, "anatop-vol-bit-width",
&sreg->vol_bit_width); &sreg->vol_bit_width);
if (ret) { if (ret) {
dev_err(dev, "no anatop-vol-bit-width property set\n"); dev_err(dev, "no anatop-vol-bit-width property set\n");
goto anatop_probe_end; return ret;
} }
ret = of_property_read_u32(np, "anatop-vol-bit-shift", ret = of_property_read_u32(np, "anatop-vol-bit-shift",
&sreg->vol_bit_shift); &sreg->vol_bit_shift);
if (ret) { if (ret) {
dev_err(dev, "no anatop-vol-bit-shift property set\n"); dev_err(dev, "no anatop-vol-bit-shift property set\n");
goto anatop_probe_end; return ret;
} }
ret = of_property_read_u32(np, "anatop-min-bit-val", ret = of_property_read_u32(np, "anatop-min-bit-val",
&sreg->min_bit_val); &sreg->min_bit_val);
if (ret) { if (ret) {
dev_err(dev, "no anatop-min-bit-val property set\n"); dev_err(dev, "no anatop-min-bit-val property set\n");
goto anatop_probe_end; return ret;
} }
ret = of_property_read_u32(np, "anatop-min-voltage", ret = of_property_read_u32(np, "anatop-min-voltage",
&sreg->min_voltage); &sreg->min_voltage);
if (ret) { if (ret) {
dev_err(dev, "no anatop-min-voltage property set\n"); dev_err(dev, "no anatop-min-voltage property set\n");
goto anatop_probe_end; return ret;
} }
ret = of_property_read_u32(np, "anatop-max-voltage", ret = of_property_read_u32(np, "anatop-max-voltage",
&sreg->max_voltage); &sreg->max_voltage);
if (ret) { if (ret) {
dev_err(dev, "no anatop-max-voltage property set\n"); dev_err(dev, "no anatop-max-voltage property set\n");
goto anatop_probe_end; return ret;
} }
/* read LDO ramp up setting, only for core reg */ /* read LDO ramp up setting, only for core reg */
@ -204,27 +202,11 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
dev_err(dev, "failed to register %s\n", dev_err(dev, "failed to register %s\n",
rdesc->name); rdesc->name);
ret = PTR_ERR(rdev); return PTR_ERR(rdev);
goto anatop_probe_end;
} }
platform_set_drvdata(pdev, rdev); platform_set_drvdata(pdev, rdev);
anatop_probe_end:
if (ret)
kfree(sreg->name);
return ret;
}
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);
const char *name = sreg->name;
kfree(name);
return 0; return 0;
} }
@ -240,7 +222,6 @@ static struct platform_driver anatop_regulator_driver = {
.of_match_table = of_anatop_regulator_match_tbl, .of_match_table = of_anatop_regulator_match_tbl,
}, },
.probe = anatop_regulator_probe, .probe = anatop_regulator_probe,
.remove = anatop_regulator_remove,
}; };
static int __init anatop_regulator_init(void) static int __init anatop_regulator_init(void)
@ -259,3 +240,4 @@ MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>");
MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>"); MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
MODULE_DESCRIPTION("ANATOP Regulator driver"); MODULE_DESCRIPTION("ANATOP Regulator driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:anatop_regulator");

View File

@ -28,8 +28,6 @@
#include <linux/mfd/arizona/pdata.h> #include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h> #include <linux/mfd/arizona/registers.h>
#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f
struct arizona_micsupp { struct arizona_micsupp {
struct regulator_dev *regulator; struct regulator_dev *regulator;
struct arizona *arizona; struct arizona *arizona;
@ -40,42 +38,6 @@ struct arizona_micsupp {
struct work_struct check_cp_work; struct work_struct check_cp_work;
}; };
static int arizona_micsupp_list_voltage(struct regulator_dev *rdev,
unsigned int selector)
{
if (selector > ARIZONA_MICSUPP_MAX_SELECTOR)
return -EINVAL;
if (selector == ARIZONA_MICSUPP_MAX_SELECTOR)
return 3300000;
else
return (selector * 50000) + 1700000;
}
static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
unsigned int voltage;
int selector;
if (min_uV < 1700000)
min_uV = 1700000;
if (min_uV > 3200000)
selector = ARIZONA_MICSUPP_MAX_SELECTOR;
else
selector = DIV_ROUND_UP(min_uV - 1700000, 50000);
if (selector < 0)
return -EINVAL;
voltage = arizona_micsupp_list_voltage(rdev, selector);
if (voltage < min_uV || voltage > max_uV)
return -EINVAL;
return selector;
}
static void arizona_micsupp_check_cp(struct work_struct *work) static void arizona_micsupp_check_cp(struct work_struct *work)
{ {
struct arizona_micsupp *micsupp = struct arizona_micsupp *micsupp =
@ -145,8 +107,8 @@ static struct regulator_ops arizona_micsupp_ops = {
.disable = arizona_micsupp_disable, .disable = arizona_micsupp_disable,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.list_voltage = arizona_micsupp_list_voltage, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = arizona_micsupp_map_voltage, .map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
@ -155,11 +117,16 @@ static struct regulator_ops arizona_micsupp_ops = {
.set_bypass = arizona_micsupp_set_bypass, .set_bypass = arizona_micsupp_set_bypass,
}; };
static const struct regulator_linear_range arizona_micsupp_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 0x1e, 50000),
REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0),
};
static const struct regulator_desc arizona_micsupp = { static const struct regulator_desc arizona_micsupp = {
.name = "MICVDD", .name = "MICVDD",
.supply_name = "CPVDD", .supply_name = "CPVDD",
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1, .n_voltages = 32,
.ops = &arizona_micsupp_ops, .ops = &arizona_micsupp_ops,
.vsel_reg = ARIZONA_LDO2_CONTROL_1, .vsel_reg = ARIZONA_LDO2_CONTROL_1,
@ -169,6 +136,9 @@ static const struct regulator_desc arizona_micsupp = {
.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
.bypass_mask = ARIZONA_CPMIC_BYPASS, .bypass_mask = ARIZONA_CPMIC_BYPASS,
.linear_ranges = arizona_micsupp_ranges,
.n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ranges),
.enable_time = 3000, .enable_time = 3000,
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@ -99,7 +99,6 @@ static const struct as3722_register_mapping as3722_reg_lookup[] = {
.sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK, .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
.control_reg = AS3722_SD0_CONTROL_REG, .control_reg = AS3722_SD0_CONTROL_REG,
.mode_mask = AS3722_SD0_MODE_FAST, .mode_mask = AS3722_SD0_MODE_FAST,
.n_voltages = AS3722_SD0_VSEL_MAX + 1,
}, },
{ {
.regulator_id = AS3722_REGULATOR_ID_SD1, .regulator_id = AS3722_REGULATOR_ID_SD1,
@ -112,7 +111,6 @@ static const struct as3722_register_mapping as3722_reg_lookup[] = {
.sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK, .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
.control_reg = AS3722_SD1_CONTROL_REG, .control_reg = AS3722_SD1_CONTROL_REG,
.mode_mask = AS3722_SD1_MODE_FAST, .mode_mask = AS3722_SD1_MODE_FAST,
.n_voltages = AS3722_SD0_VSEL_MAX + 1,
}, },
{ {
.regulator_id = AS3722_REGULATOR_ID_SD2, .regulator_id = AS3722_REGULATOR_ID_SD2,
@ -181,7 +179,6 @@ static const struct as3722_register_mapping as3722_reg_lookup[] = {
.sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK, .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
.control_reg = AS3722_SD6_CONTROL_REG, .control_reg = AS3722_SD6_CONTROL_REG,
.mode_mask = AS3722_SD6_MODE_FAST, .mode_mask = AS3722_SD6_MODE_FAST,
.n_voltages = AS3722_SD0_VSEL_MAX + 1,
}, },
{ {
.regulator_id = AS3722_REGULATOR_ID_LDO0, .regulator_id = AS3722_REGULATOR_ID_LDO0,
@ -595,6 +592,22 @@ static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
return as3722_update_bits(as3722, reg, mask, val); return as3722_update_bits(as3722, reg, mask, val);
} }
static bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs)
{
int err;
unsigned val;
err = as3722_read(as3722_regs->as3722, AS3722_FUSE7_REG, &val);
if (err < 0) {
dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
AS3722_FUSE7_REG, err);
return false;
}
if (val & AS3722_FUSE7_SD0_LOW_VOLTAGE)
return true;
return false;
}
static const struct regulator_linear_range as3722_sd2345_ranges[] = { static const struct regulator_linear_range as3722_sd2345_ranges[] = {
REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500), REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000), REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
@ -820,9 +833,19 @@ static int as3722_regulator_probe(struct platform_device *pdev)
ops = &as3722_sd016_extcntrl_ops; ops = &as3722_sd016_extcntrl_ops;
else else
ops = &as3722_sd016_ops; ops = &as3722_sd016_ops;
as3722_regs->desc[id].min_uV = 610000; if (id == AS3722_REGULATOR_ID_SD0 &&
as3722_sd0_is_low_voltage(as3722_regs)) {
as3722_regs->desc[id].n_voltages =
AS3722_SD0_VSEL_LOW_VOL_MAX + 1;
as3722_regs->desc[id].min_uV = 410000;
} else {
as3722_regs->desc[id].n_voltages =
AS3722_SD0_VSEL_MAX + 1,
as3722_regs->desc[id].min_uV = 610000;
}
as3722_regs->desc[id].uV_step = 10000; as3722_regs->desc[id].uV_step = 10000;
as3722_regs->desc[id].linear_min_sel = 1; as3722_regs->desc[id].linear_min_sel = 1;
as3722_regs->desc[id].enable_time = 600;
break; break;
case AS3722_REGULATOR_ID_SD2: case AS3722_REGULATOR_ID_SD2:
case AS3722_REGULATOR_ID_SD3: case AS3722_REGULATOR_ID_SD3:
@ -842,9 +865,6 @@ static int as3722_regulator_probe(struct platform_device *pdev)
ops = &as3722_ldo_extcntrl_ops; ops = &as3722_ldo_extcntrl_ops;
else else
ops = &as3722_ldo_ops; ops = &as3722_ldo_ops;
as3722_regs->desc[id].min_uV = 825000;
as3722_regs->desc[id].uV_step = 25000;
as3722_regs->desc[id].linear_min_sel = 1;
as3722_regs->desc[id].enable_time = 500; as3722_regs->desc[id].enable_time = 500;
as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges; as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges;
as3722_regs->desc[id].n_linear_ranges = as3722_regs->desc[id].n_linear_ranges =

View File

@ -323,7 +323,7 @@ static int pfuze_identify(struct pfuze_chip *pfuze_chip)
if (ret) if (ret)
return ret; return ret;
dev_info(pfuze_chip->dev, dev_info(pfuze_chip->dev,
"Full lay: %x, Metal lay: %x\n", "Full layer: %x, Metal layer: %x\n",
(value & 0xf0) >> 4, value & 0x0f); (value & 0xf0) >> 4, value & 0x0f);
ret = regmap_read(pfuze_chip->regmap, PFUZE100_FABID, &value); ret = regmap_read(pfuze_chip->regmap, PFUZE100_FABID, &value);

View File

@ -151,6 +151,7 @@
#define AS3722_ASIC_ID1_REG 0x90 #define AS3722_ASIC_ID1_REG 0x90
#define AS3722_ASIC_ID2_REG 0x91 #define AS3722_ASIC_ID2_REG 0x91
#define AS3722_LOCK_REG 0x9E #define AS3722_LOCK_REG 0x9E
#define AS3722_FUSE7_REG 0xA7
#define AS3722_MAX_REGISTER 0xF4 #define AS3722_MAX_REGISTER 0xF4
#define AS3722_SD0_EXT_ENABLE_MASK 0x03 #define AS3722_SD0_EXT_ENABLE_MASK 0x03
@ -224,6 +225,7 @@
#define AS3722_SD_VSEL_MASK 0x7F #define AS3722_SD_VSEL_MASK 0x7F
#define AS3722_SD0_VSEL_MIN 0x01 #define AS3722_SD0_VSEL_MIN 0x01
#define AS3722_SD0_VSEL_MAX 0x5A #define AS3722_SD0_VSEL_MAX 0x5A
#define AS3722_SD0_VSEL_LOW_VOL_MAX 0x6E
#define AS3722_SD2_VSEL_MIN 0x01 #define AS3722_SD2_VSEL_MIN 0x01
#define AS3722_SD2_VSEL_MAX 0x7F #define AS3722_SD2_VSEL_MAX 0x7F
@ -341,6 +343,8 @@
#define AS3722_EXT_CONTROL_ENABLE2 0x2 #define AS3722_EXT_CONTROL_ENABLE2 0x2
#define AS3722_EXT_CONTROL_ENABLE3 0x3 #define AS3722_EXT_CONTROL_ENABLE3 0x3
#define AS3722_FUSE7_SD0_LOW_VOLTAGE BIT(4)
/* Interrupt IDs */ /* Interrupt IDs */
enum as3722_irq { enum as3722_irq {
AS3722_IRQ_LID, AS3722_IRQ_LID,

View File

@ -0,0 +1,53 @@
/*
* act8865.h -- Voltage regulation for the active-semi act8865
*
* Copyright (C) 2013 Atmel Corporation.
*
* 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 of the License.
*
* 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.
*/
#ifndef __LINUX_REGULATOR_ACT8865_H
#define __LINUX_REGULATOR_ACT8865_H
#include <linux/regulator/machine.h>
enum {
ACT8865_ID_DCDC1,
ACT8865_ID_DCDC2,
ACT8865_ID_DCDC3,
ACT8865_ID_LDO1,
ACT8865_ID_LDO2,
ACT8865_ID_LDO3,
ACT8865_ID_LDO4,
ACT8865_REG_NUM,
};
/**
* act8865_regulator_data - regulator data
* @id: regulator id
* @name: regulator name
* @platform_data: regulator init data
*/
struct act8865_regulator_data {
int id;
const char *name;
struct regulator_init_data *platform_data;
};
/**
* act8865_platform_data - platform data for act8865
* @num_regulators: number of regulators used
* @regulators: pointer to regulators used
*/
struct act8865_platform_data {
int num_regulators;
struct act8865_regulator_data *regulators;
};
#endif