Commit 92aa18f8 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'regulator/topic/act8865',...

Merge remote-tracking branches 'regulator/topic/act8865', 'regulator/topic/act8945a', 'regulator/topic/axp20x' and 'regulator/topic/cs4271' into regulator-next
Device-Tree bindings for regulators of Active-semi ACT8945A Multi-Function Device
Required properties:
- compatible: "active-semi,act8945a", please refer to ../mfd/act8945a.txt.
Optional properties:
- active-semi,vsel-high: Indicates if the VSEL pin is set to logic-high.
If this property is missing, assume the VSEL pin is set to logic-low.
Optional input supply properties:
- vp1-supply: The input supply for REG_DCDC1
- vp2-supply: The input supply for REG_DCDC2
- vp3-supply: The input supply for REG_DCDC3
- inl45-supply: The input supply for REG_LDO1 and REG_LDO2
- inl67-supply: The input supply for REG_LDO3 and REG_LDO4
Any standard regulator properties can be used to configure the single regulator.
The valid names for regulators are:
REG_DCDC1, REG_DCDC2, REG_DCDC3, REG_LDO1, REG_LDO2, REG_LDO3, REG_LDO4.
Example:
pmic@5b {
compatible = "active-semi,act8945a";
reg = <0x5b>;
status = "okay";
active-semi,vsel-high;
regulators {
vdd_1v35_reg: REG_DCDC1 {
regulator-name = "VDD_1V35";
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
};
vdd_1v2_reg: REG_DCDC2 {
regulator-name = "VDD_1V2";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
};
vdd_3v3_reg: REG_DCDC3 {
regulator-name = "VDD_3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vdd_fuse_reg: REG_LDO1 {
regulator-name = "VDD_FUSE";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
regulator-always-on;
};
vdd_3v3_lp_reg: REG_LDO2 {
regulator-name = "VDD_3V3_LP";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vdd_led_reg: REG_LDO3 {
regulator-name = "VDD_LED";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vdd_sdhc_1v8_reg: REG_LDO4 {
regulator-name = "VDD_SDHC_1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
};
};
...@@ -33,12 +33,19 @@ Optional properties: ...@@ -33,12 +33,19 @@ Optional properties:
Note that this is not needed in case the clocks are stable Note that this is not needed in case the clocks are stable
throughout the entire runtime of the codec. throughout the entire runtime of the codec.
- vd-supply: Digital power
- vl-supply: Logic power
- va-supply: Analog Power
Examples: Examples:
codec_i2c: cs4271@10 { codec_i2c: cs4271@10 {
compatible = "cirrus,cs4271"; compatible = "cirrus,cs4271";
reg = <0x10>; reg = <0x10>;
reset-gpio = <&gpio 23 0>; reset-gpio = <&gpio 23 0>;
vd-supply = <&vdd_3v3_reg>;
vl-supply = <&vdd_3v3_reg>;
va-supply = <&vdd_3v3_reg>;
}; };
codec_spi: cs4271@0 { codec_spi: cs4271@0 {
......
...@@ -78,6 +78,15 @@ config REGULATOR_ACT8865 ...@@ -78,6 +78,15 @@ config REGULATOR_ACT8865
This driver controls a active-semi act8865 voltage output This driver controls a active-semi act8865 voltage output
regulator via I2C bus. regulator via I2C bus.
config REGULATOR_ACT8945A
tristate "Active-semi ACT8945A voltage regulator"
depends on MFD_ACT8945A
help
This driver controls a active-semi ACT8945A voltage regulator
via I2C bus. The ACT8945A features three step-down DC/DC converters
and four low-dropout linear regulators, along with a ActivePath
battery charger.
config REGULATOR_AD5398 config REGULATOR_AD5398
tristate "Analog Devices AD5398/AD5821 regulators" tristate "Analog Devices AD5398/AD5821 regulators"
depends on I2C depends on I2C
......
...@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o ...@@ -15,6 +15,7 @@ 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_ACT8865) += act8865-regulator.o
obj-$(CONFIG_REGULATOR_ACT8945A) += act8945a-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
......
...@@ -218,7 +218,7 @@ static const struct regulator_desc act8600_regulators[] = { ...@@ -218,7 +218,7 @@ static const struct regulator_desc act8600_regulators[] = {
.ops = &act8865_ldo_ops, .ops = &act8865_ldo_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.n_voltages = 1, .n_voltages = 1,
.fixed_uV = 1800000, .fixed_uV = 3300000,
.enable_reg = ACT8600_LDO910_CTRL, .enable_reg = ACT8600_LDO910_CTRL,
.enable_mask = ACT8865_ENA, .enable_mask = ACT8865_ENA,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -369,7 +369,7 @@ static int act8865_pdata_from_dt(struct device *dev, ...@@ -369,7 +369,7 @@ static int act8865_pdata_from_dt(struct device *dev,
for (i = 0; i < num_matches; i++) { for (i = 0; i < num_matches; i++) {
regulator->id = i; regulator->id = i;
regulator->name = matches[i].name; regulator->name = matches[i].name;
regulator->platform_data = matches[i].init_data; regulator->init_data = matches[i].init_data;
of_node[i] = matches[i].of_node; of_node[i] = matches[i].of_node;
regulator++; regulator++;
} }
...@@ -396,7 +396,7 @@ static struct regulator_init_data ...@@ -396,7 +396,7 @@ static struct regulator_init_data
for (i = 0; i < pdata->num_regulators; i++) { for (i = 0; i < pdata->num_regulators; i++) {
if (pdata->regulators[i].id == id) if (pdata->regulators[i].id == id)
return pdata->regulators[i].platform_data; return pdata->regulators[i].init_data;
} }
return NULL; return NULL;
...@@ -415,7 +415,7 @@ static void act8865_power_off(void) ...@@ -415,7 +415,7 @@ static void act8865_power_off(void)
static int act8865_pmic_probe(struct i2c_client *client, static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
static const struct regulator_desc *regulators; const struct regulator_desc *regulators;
struct act8865_platform_data pdata_of, *pdata; struct act8865_platform_data pdata_of, *pdata;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct device_node **of_node; struct device_node **of_node;
......
/*
* Voltage regulation driver for active-semi ACT8945A PMIC
*
* Copyright (C) 2015 Atmel Corporation
*
* Author: Wenyou Yang <wenyou.yang@atmel.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/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
/**
* ACT8945A Global Register Map.
*/
#define ACT8945A_SYS_MODE 0x00
#define ACT8945A_SYS_CTRL 0x01
#define ACT8945A_DCDC1_VSET1 0x20
#define ACT8945A_DCDC1_VSET2 0x21
#define ACT8945A_DCDC1_CTRL 0x22
#define ACT8945A_DCDC2_VSET1 0x30
#define ACT8945A_DCDC2_VSET2 0x31
#define ACT8945A_DCDC2_CTRL 0x32
#define ACT8945A_DCDC3_VSET1 0x40
#define ACT8945A_DCDC3_VSET2 0x41
#define ACT8945A_DCDC3_CTRL 0x42
#define ACT8945A_LDO1_VSET 0x50
#define ACT8945A_LDO1_CTRL 0x51
#define ACT8945A_LDO2_VSET 0x54
#define ACT8945A_LDO2_CTRL 0x55
#define ACT8945A_LDO3_VSET 0x60
#define ACT8945A_LDO3_CTRL 0x61
#define ACT8945A_LDO4_VSET 0x64
#define ACT8945A_LDO4_CTRL 0x65
/**
* Field Definitions.
*/
#define ACT8945A_ENA 0x80 /* ON - [7] */
#define ACT8945A_VSEL_MASK 0x3F /* VSET - [5:0] */
/**
* ACT8945A Voltage Number
*/
#define ACT8945A_VOLTAGE_NUM 64
enum {
ACT8945A_ID_DCDC1,
ACT8945A_ID_DCDC2,
ACT8945A_ID_DCDC3,
ACT8945A_ID_LDO1,
ACT8945A_ID_LDO2,
ACT8945A_ID_LDO3,
ACT8945A_ID_LDO4,
ACT8945A_REG_NUM,
};
static const struct regulator_linear_range act8945a_voltage_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 act8945a_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,
};
#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \
[_family##_ID_##_id] = { \
.name = _name, \
.supply_name = _supply, \
.of_match = of_match_ptr("REG_"#_id), \
.regulators_node = of_match_ptr("regulators"), \
.id = _family##_ID_##_id, \
.type = REGULATOR_VOLTAGE, \
.ops = &act8945a_ops, \
.n_voltages = ACT8945A_VOLTAGE_NUM, \
.linear_ranges = act8945a_voltage_ranges, \
.n_linear_ranges = ARRAY_SIZE(act8945a_voltage_ranges), \
.vsel_reg = _family##_##_id##_##_vsel_reg, \
.vsel_mask = ACT8945A_VSEL_MASK, \
.enable_reg = _family##_##_id##_CTRL, \
.enable_mask = ACT8945A_ENA, \
.owner = THIS_MODULE, \
}
static const struct regulator_desc act8945a_regulators[] = {
ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET1, "vp1"),
ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET1, "vp2"),
ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET1, "vp3"),
ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"),
ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"),
ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"),
ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"),
};
static const struct regulator_desc act8945a_alt_regulators[] = {
ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET2, "vp1"),
ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET2, "vp2"),
ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET2, "vp3"),
ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"),
ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"),
ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"),
ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"),
};
static int act8945a_pmic_probe(struct platform_device *pdev)
{
struct regulator_config config = { };
const struct regulator_desc *regulators;
struct regulator_dev *rdev;
int i, num_regulators;
bool voltage_select;
voltage_select = of_property_read_bool(pdev->dev.parent->of_node,
"active-semi,vsel-high");
if (voltage_select) {
regulators = act8945a_alt_regulators;
num_regulators = ARRAY_SIZE(act8945a_alt_regulators);
} else {
regulators = act8945a_regulators;
num_regulators = ARRAY_SIZE(act8945a_regulators);
}
config.dev = &pdev->dev;
config.dev->of_node = pdev->dev.parent->of_node;
for (i = 0; i < num_regulators; i++) {
rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
regulators[i].name);
return PTR_ERR(rdev);
}
}
return 0;
}
static struct platform_driver act8945a_pmic_driver = {
.driver = {
.name = "act8945a-regulator",
},
.probe = act8945a_pmic_probe,
};
module_platform_driver(act8945a_pmic_driver);
MODULE_DESCRIPTION("Active-semi ACT8945A voltage regulator driver");
MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
MODULE_LICENSE("GPL");
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enable_val, _disable_val) \ _vmask, _ereg, _emask, _enable_val, _disable_val) \
[_family##_##_id] = { \ [_family##_##_id] = { \
.name = #_id, \ .name = (_match), \
.supply_name = (_supply), \ .supply_name = (_supply), \
.of_match = of_match_ptr(_match), \ .of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \ .regulators_node = of_match_ptr("regulators"), \
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ #define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask) \ _vmask, _ereg, _emask) \
[_family##_##_id] = { \ [_family##_##_id] = { \
.name = #_id, \ .name = (_match), \
.supply_name = (_supply), \ .supply_name = (_supply), \
.of_match = of_match_ptr(_match), \ .of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \ .regulators_node = of_match_ptr("regulators"), \
...@@ -78,21 +78,15 @@ ...@@ -78,21 +78,15 @@
.ops = &axp20x_ops, \ .ops = &axp20x_ops, \
} }
#define AXP_DESC_SW(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ #define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \
_vmask, _ereg, _emask) \
[_family##_##_id] = { \ [_family##_##_id] = { \
.name = #_id, \ .name = (_match), \
.supply_name = (_supply), \ .supply_name = (_supply), \
.of_match = of_match_ptr(_match), \ .of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \ .regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = _family##_##_id, \ .id = _family##_##_id, \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
.uV_step = (_step) * 1000, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \ .enable_reg = (_ereg), \
.enable_mask = (_emask), \ .enable_mask = (_emask), \
.ops = &axp20x_ops_sw, \ .ops = &axp20x_ops_sw, \
...@@ -100,7 +94,7 @@ ...@@ -100,7 +94,7 @@
#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt) \ #define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt) \
[_family##_##_id] = { \ [_family##_##_id] = { \
.name = #_id, \ .name = (_match), \
.supply_name = (_supply), \ .supply_name = (_supply), \
.of_match = of_match_ptr(_match), \ .of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \ .regulators_node = of_match_ptr("regulators"), \
...@@ -112,39 +106,34 @@ ...@@ -112,39 +106,34 @@
.ops = &axp20x_ops_fixed \ .ops = &axp20x_ops_fixed \
} }
#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask, \ #define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \
_ereg, _emask) \ _vreg, _vmask, _ereg, _emask) \
[_family##_##_id] = { \ [_family##_##_id] = { \
.name = #_id, \ .name = (_match), \
.supply_name = (_supply), \ .supply_name = (_supply), \
.of_match = of_match_ptr(_match), \ .of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \ .regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = _family##_##_id, \ .id = _family##_##_id, \
.n_voltages = ARRAY_SIZE(_table), \ .n_voltages = (_n_voltages), \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.vsel_reg = (_vreg), \ .vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \ .vsel_mask = (_vmask), \
.enable_reg = (_ereg), \ .enable_reg = (_ereg), \
.enable_mask = (_emask), \ .enable_mask = (_emask), \
.volt_table = (_table), \ .linear_ranges = (_ranges), \
.ops = &axp20x_ops_table, \ .n_linear_ranges = ARRAY_SIZE(_ranges), \
.ops = &axp20x_ops_range, \
} }
static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000,
1700000, 1800000, 1900000, 2000000, 2500000,
2700000, 2800000, 3000000, 3100000, 3200000,
3300000 };
static struct regulator_ops axp20x_ops_fixed = { static struct regulator_ops axp20x_ops_fixed = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
}; };
static struct regulator_ops axp20x_ops_table = { static struct regulator_ops axp20x_ops_range = {
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_ascend,
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
...@@ -160,13 +149,17 @@ static struct regulator_ops axp20x_ops = { ...@@ -160,13 +149,17 @@ static struct regulator_ops axp20x_ops = {
}; };
static struct regulator_ops axp20x_ops_sw = { static struct regulator_ops axp20x_ops_sw = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
}; };
static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
REGULATOR_LINEAR_RANGE(2500000, 0x9, 0xf, 100000),
};
static const struct regulator_desc axp20x_regulators[] = { static const struct regulator_desc axp20x_regulators[] = {
AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25, AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10), AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
...@@ -177,8 +170,9 @@ static const struct regulator_desc axp20x_regulators[] = { ...@@ -177,8 +170,9 @@ static const struct regulator_desc axp20x_regulators[] = {
AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04), AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25, AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40), AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data, AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges,
AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08), 16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL,
0x08),
AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100, AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07, AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
AXP20X_IO_ENABLED, AXP20X_IO_DISABLED), AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
...@@ -196,8 +190,8 @@ static const struct regulator_desc axp22x_regulators[] = { ...@@ -196,8 +190,8 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50, AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)), AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
/* secondary switchable output of DCDC1 */ /* secondary switchable output of DCDC1 */
AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, 1600, 3400, 100, AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)), BIT(7)),
/* LDO regulator internally chained to DCDC5 */ /* LDO regulator internally chained to DCDC5 */
AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100, AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)), AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
......
...@@ -68,12 +68,12 @@ enum { ...@@ -68,12 +68,12 @@ enum {
* act8865_regulator_data - regulator data * act8865_regulator_data - regulator data
* @id: regulator id * @id: regulator id
* @name: regulator name * @name: regulator name
* @platform_data: regulator init data * @init_data: regulator init data
*/ */
struct act8865_regulator_data { struct act8865_regulator_data {
int id; int id;
const char *name; const char *name;
struct regulator_init_data *platform_data; struct regulator_init_data *init_data;
}; };
/** /**
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/tlv.h> #include <sound/tlv.h>
...@@ -157,6 +158,10 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) ...@@ -157,6 +158,10 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
return reg == CS4271_CHIPID; return reg == CS4271_CHIPID;
} }
static const char * const supply_names[] = {
"vd", "vl", "va"
};
struct cs4271_private { struct cs4271_private {
unsigned int mclk; unsigned int mclk;
bool master; bool master;
...@@ -170,6 +175,7 @@ struct cs4271_private { ...@@ -170,6 +175,7 @@ struct cs4271_private {
int gpio_disable; int gpio_disable;
/* enable soft reset workaround */ /* enable soft reset workaround */
bool enable_soft_reset; bool enable_soft_reset;
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
}; };
static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = { static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = {
...@@ -487,6 +493,20 @@ static struct snd_soc_dai_driver cs4271_dai = { ...@@ -487,6 +493,20 @@ static struct snd_soc_dai_driver cs4271_dai = {
.symmetric_rates = 1, .symmetric_rates = 1,
}; };
static int cs4271_reset(struct snd_soc_codec *codec)
{
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
if (gpio_is_valid(cs4271->gpio_nreset)) {
gpio_set_value(cs4271->gpio_nreset, 0);
mdelay(1);
gpio_set_value(cs4271->gpio_nreset, 1);
mdelay(1);
}
return 0;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int cs4271_soc_suspend(struct snd_soc_codec *codec) static int cs4271_soc_suspend(struct snd_soc_codec *codec)
{ {
...@@ -499,6 +519,9 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec) ...@@ -499,6 +519,9 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec)
if (ret < 0) if (ret < 0)
return ret; return ret;
regcache_mark_dirty(cs4271->regmap);
regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies);
return 0; return 0;
} }
...@@ -507,6 +530,16 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec) ...@@ -507,6 +530,16 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec)
int ret; int ret;
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
ret = regulator_bulk_enable(ARRAY_SIZE(cs4271->supplies),
cs4271->supplies);
if (ret < 0) {
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
return ret;
}
/* Do a proper reset after power up */
cs4271_reset(codec);
/* Restore codec state */ /* Restore codec state */
ret = regcache_sync(cs4271->regmap); ret = regcache_sync(cs4271->regmap);
if (ret < 0) if (ret < 0)
...@@ -553,19 +586,24 @@ static int cs4271_codec_probe(struct snd_soc_codec *codec) ...@@ -553,19 +586,24 @@ static int cs4271_codec_probe(struct snd_soc_codec *codec)
} }
#endif #endif
ret = regulator_bulk_enable(ARRAY_SIZE(cs4271->supplies),
cs4271->supplies);
if (ret < 0) {
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
return ret;
}
if (cs4271plat) { if (cs4271plat) {
amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
} }
if (gpio_is_valid(cs4271->gpio_nreset)) { /* Reset codec */
/* Reset codec */ cs4271_reset(codec);
gpio_direction_output(cs4271->gpio_nreset, 0);
mdelay(1); ret = regcache_sync(cs4271->regmap);
gpio_set_value(cs4271->gpio_nreset, 1); if (ret < 0)
/* Give the codec time to wake up */ return ret;
mdelay(1);
}
ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
CS4271_MODE2_PDN | CS4271_MODE2_CPEN, CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
...@@ -595,6 +633,9 @@ static int cs4271_codec_remove(struct snd_soc_codec *codec) ...@@ -595,6 +633,9 @@ static int cs4271_codec_remove(struct snd_soc_codec *codec)
/* Set codec to the reset state */ /* Set codec to the reset state */
gpio_set_value(cs4271->gpio_nreset, 0); gpio_set_value(cs4271->gpio_nreset, 0);
regcache_mark_dirty(cs4271->regmap);
regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies);
return 0; return 0;
}; };
...@@ -617,6 +658,7 @@ static int cs4271_common_probe(struct device *dev, ...@@ -617,6 +658,7 @@ static int cs4271_common_probe(struct device *dev,
{ {
struct cs4271_platform_data *cs4271plat = dev->platform_data; struct cs4271_platform_data *cs4271plat = dev->platform_data;
struct cs4271_private *cs4271; struct cs4271_private *cs4271;
int i, ret;
cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL); cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL);
if (!cs4271) if (!cs4271)
...@@ -638,6 +680,17 @@ static int cs4271_common_probe(struct device *dev, ...@@ -638,6 +680,17 @@ static int cs4271_common_probe(struct device *dev,
return ret; return ret;
} }
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
cs4271->supplies[i].supply = supply_names[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs4271->supplies),
cs4271->supplies);
if (ret < 0) {
dev_err(dev, "Failed to get regulators: %d\n", ret);
return ret;
}
*c = cs4271; *c = cs4271;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment