summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Jirman <megous@megous.com>2018-05-07 08:29:41 -0400
committerMark Brown <broonie@kernel.org>2018-05-09 05:25:06 -0400
commit8878302ebbc580d64f390c0acc509e5e8276598c (patch)
tree461c48fca9680fd04b88a0e8ca7e0d1cfa1c2077
parent32aba834f2a9fe126ff5e624371113ac1defa06e (diff)
regulator: add support for SY8106A regulator
SY8106A is an I2C attached single output regulator made by Silergy Corp, which is used on several Allwinner H3/H5 SBCs to control the power supply of the ARM cores. Add a driver for it. Signed-off-by: Ondrej Jirman <megous@megous.com> [Icenowy: Change commit message, remove enable/disable code, add default ramp_delay, add comment for go bit, add code for fixed mode voltage] Signed-off-by: Icenowy Zheng <icenowy@aosc.io> Reviewed-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/regulator/Kconfig7
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/sy8106a-regulator.c167
4 files changed, 181 insertions, 1 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 0a1410d5a621..971300930067 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13461,6 +13461,12 @@ S: Supported
13461F: net/switchdev/ 13461F: net/switchdev/
13462F: include/net/switchdev.h 13462F: include/net/switchdev.h
13463 13463
13464SY8106A REGULATOR DRIVER
13465M: Icenowy Zheng <icenowy@aosc.io>
13466S: Maintained
13467F: drivers/regulator/sy8106a-regulator.c
13468F: Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt
13469
13464SYNC FILE FRAMEWORK 13470SYNC FILE FRAMEWORK
13465M: Sumit Semwal <sumit.semwal@linaro.org> 13471M: Sumit Semwal <sumit.semwal@linaro.org>
13466R: Gustavo Padovan <gustavo@padovan.org> 13472R: Gustavo Padovan <gustavo@padovan.org>
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 097f61784a7d..4efae3b7e746 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -801,6 +801,13 @@ config REGULATOR_STW481X_VMMC
801 This driver supports the internal VMMC regulator in the STw481x 801 This driver supports the internal VMMC regulator in the STw481x
802 PMIC chips. 802 PMIC chips.
803 803
804config REGULATOR_SY8106A
805 tristate "Silergy SY8106A regulator"
806 depends on I2C && (OF || COMPILE_TEST)
807 select REGMAP_I2C
808 help
809 This driver supports SY8106A single output regulator.
810
804config REGULATOR_TPS51632 811config REGULATOR_TPS51632
805 tristate "TI TPS51632 Power Regulator" 812 tristate "TI TPS51632 Power Regulator"
806 depends on I2C 813 depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 590674fbecd7..d81fb02bd6e9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
100obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o 100obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
101obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o 101obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
102obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o 102obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
103obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
103obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o 104obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
104obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o 105obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
105obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o 106obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
@@ -125,5 +126,4 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
125obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o 126obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
126obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o 127obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
127 128
128
129ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG 129ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
new file mode 100644
index 000000000000..65fbd1f0b612
--- /dev/null
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -0,0 +1,167 @@
1// SPDX-License-Identifier: GPL-2.0+
2//
3// sy8106a-regulator.c - Regulator device driver for SY8106A
4//
5// Copyright (C) 2016 Ondřej Jirman <megous@megous.com>
6// Copyright (c) 2017-2018 Icenowy Zheng <icenowy@aosc.io>
7
8#include <linux/err.h>
9#include <linux/i2c.h>
10#include <linux/module.h>
11#include <linux/regmap.h>
12#include <linux/regulator/driver.h>
13#include <linux/regulator/of_regulator.h>
14
15#define SY8106A_REG_VOUT1_SEL 0x01
16#define SY8106A_REG_VOUT_COM 0x02
17#define SY8106A_REG_VOUT1_SEL_MASK 0x7f
18#define SY8106A_DISABLE_REG BIT(0)
19/*
20 * The I2C controlled voltage will only work when this bit is set; otherwise
21 * it will behave like a fixed regulator.
22 */
23#define SY8106A_GO_BIT BIT(7)
24
25struct sy8106a {
26 struct regulator_dev *rdev;
27 struct regmap *regmap;
28 u32 fixed_voltage;
29};
30
31static const struct regmap_config sy8106a_regmap_config = {
32 .reg_bits = 8,
33 .val_bits = 8,
34};
35
36static const struct regulator_ops sy8106a_ops = {
37 .set_voltage_sel = regulator_set_voltage_sel_regmap,
38 .set_voltage_time_sel = regulator_set_voltage_time_sel,
39 .get_voltage_sel = regulator_get_voltage_sel_regmap,
40 .list_voltage = regulator_list_voltage_linear,
41 /* Enabling/disabling the regulator is not yet implemented */
42};
43
44/* Default limits measured in millivolts */
45#define SY8106A_MIN_MV 680
46#define SY8106A_MAX_MV 1950
47#define SY8106A_STEP_MV 10
48
49static const struct regulator_desc sy8106a_reg = {
50 .name = "SY8106A",
51 .id = 0,
52 .ops = &sy8106a_ops,
53 .type = REGULATOR_VOLTAGE,
54 .n_voltages = ((SY8106A_MAX_MV - SY8106A_MIN_MV) / SY8106A_STEP_MV) + 1,
55 .min_uV = (SY8106A_MIN_MV * 1000),
56 .uV_step = (SY8106A_STEP_MV * 1000),
57 .vsel_reg = SY8106A_REG_VOUT1_SEL,
58 .vsel_mask = SY8106A_REG_VOUT1_SEL_MASK,
59 /*
60 * This ramp_delay is a conservative default value which works on
61 * H3/H5 boards VDD-CPUX situations.
62 */
63 .ramp_delay = 200,
64 .owner = THIS_MODULE,
65};
66
67/*
68 * I2C driver interface functions
69 */
70static int sy8106a_i2c_probe(struct i2c_client *i2c,
71 const struct i2c_device_id *id)
72{
73 struct sy8106a *chip;
74 struct device *dev = &i2c->dev;
75 struct regulator_dev *rdev = NULL;
76 struct regulator_config config = { };
77 unsigned int reg, vsel;
78 int error;
79
80 chip = devm_kzalloc(&i2c->dev, sizeof(struct sy8106a), GFP_KERNEL);
81 if (!chip)
82 return -ENOMEM;
83
84 error = of_property_read_u32(dev->of_node, "silergy,fixed-microvolt",
85 &chip->fixed_voltage);
86 if (error)
87 return error;
88
89 if (chip->fixed_voltage < SY8106A_MIN_MV * 1000 ||
90 chip->fixed_voltage > SY8106A_MAX_MV * 1000)
91 return -EINVAL;
92
93 chip->regmap = devm_regmap_init_i2c(i2c, &sy8106a_regmap_config);
94 if (IS_ERR(chip->regmap)) {
95 error = PTR_ERR(chip->regmap);
96 dev_err(dev, "Failed to allocate register map: %d\n", error);
97 return error;
98 }
99
100 config.dev = &i2c->dev;
101 config.regmap = chip->regmap;
102 config.driver_data = chip;
103
104 config.of_node = dev->of_node;
105 config.init_data = of_get_regulator_init_data(dev, dev->of_node,
106 &sy8106a_reg);
107
108 if (!config.init_data)
109 return -ENOMEM;
110
111 /* Ensure GO_BIT is enabled when probing */
112 error = regmap_read(chip->regmap, SY8106A_REG_VOUT1_SEL, &reg);
113 if (error)
114 return error;
115
116 if (!(reg & SY8106A_GO_BIT)) {
117 vsel = (chip->fixed_voltage / 1000 - SY8106A_MIN_MV) /
118 SY8106A_STEP_MV;
119
120 error = regmap_write(chip->regmap, SY8106A_REG_VOUT1_SEL,
121 vsel | SY8106A_GO_BIT);
122 if (error)
123 return error;
124 }
125
126 /* Probe regulator */
127 rdev = devm_regulator_register(&i2c->dev, &sy8106a_reg, &config);
128 if (IS_ERR(rdev)) {
129 error = PTR_ERR(rdev);
130 dev_err(&i2c->dev, "Failed to register SY8106A regulator: %d\n", error);
131 return error;
132 }
133
134 chip->rdev = rdev;
135
136 i2c_set_clientdata(i2c, chip);
137
138 return 0;
139}
140
141static const struct of_device_id sy8106a_i2c_of_match[] = {
142 { .compatible = "silergy,sy8106a" },
143 { },
144};
145MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match);
146
147static const struct i2c_device_id sy8106a_i2c_id[] = {
148 { "sy8106a", 0 },
149 { },
150};
151MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id);
152
153static struct i2c_driver sy8106a_regulator_driver = {
154 .driver = {
155 .name = "sy8106a",
156 .of_match_table = of_match_ptr(sy8106a_i2c_of_match),
157 },
158 .probe = sy8106a_i2c_probe,
159 .id_table = sy8106a_i2c_id,
160};
161
162module_i2c_driver(sy8106a_regulator_driver);
163
164MODULE_AUTHOR("Ondřej Jirman <megous@megous.com>");
165MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
166MODULE_DESCRIPTION("Regulator device driver for Silergy SY8106A");
167MODULE_LICENSE("GPL");