aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Monakov <amonakov@ispras.ru>2018-03-08 17:53:03 -0500
committerMark Brown <broonie@kernel.org>2018-03-09 08:01:17 -0500
commita265b03bd29a745d85237f47739d92cb43d214b9 (patch)
treea3ab11bd3ba9e31137ff79da413c1ebc4b059c7f
parent2a254de29e995ea58d73f75b69016cf913a5447d (diff)
regulator: 88pg86x: new i2c dual regulator chip
This chip is found on Google Chromecast and Valve Steam Link devices. It provides two DC regulators with I2C voltage control, separate GPIO enable pins and one sleep mode pin. This driver does not expose GPIO functionality, but supports voltage control in 1.0-2.2V range, based on I2C register information given in Chromecast kernel driver by Jisheng Zhang. Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com> Signed-off-by: Alexander Monakov <amonakov@ispras.ru> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/regulator/88pg86x.c114
-rw-r--r--drivers/regulator/Kconfig9
-rw-r--r--drivers/regulator/Makefile1
3 files changed, 124 insertions, 0 deletions
diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c
new file mode 100644
index 000000000000..d5ef55c81185
--- /dev/null
+++ b/drivers/regulator/88pg86x.c
@@ -0,0 +1,114 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/module.h>
3#include <linux/i2c.h>
4#include <linux/of.h>
5#include <linux/regulator/driver.h>
6#include <linux/regmap.h>
7
8static const struct regulator_ops pg86x_ops = {
9 .set_voltage_sel = regulator_set_voltage_sel_regmap,
10 .get_voltage_sel = regulator_get_voltage_sel_regmap,
11 .list_voltage = regulator_list_voltage_linear_range,
12};
13
14static const struct regulator_linear_range pg86x_buck1_ranges[] = {
15 REGULATOR_LINEAR_RANGE( 0, 0, 10, 0),
16 REGULATOR_LINEAR_RANGE(1000000, 11, 34, 25000),
17 REGULATOR_LINEAR_RANGE(1600000, 35, 47, 50000),
18};
19
20static const struct regulator_linear_range pg86x_buck2_ranges[] = {
21 REGULATOR_LINEAR_RANGE( 0, 0, 15, 0),
22 REGULATOR_LINEAR_RANGE(1000000, 16, 39, 25000),
23 REGULATOR_LINEAR_RANGE(1600000, 40, 52, 50000),
24};
25
26static const struct regulator_desc pg86x_regulators[] = {
27 {
28 .id = 0,
29 .type = REGULATOR_VOLTAGE,
30 .name = "buck1",
31 .of_match = of_match_ptr("buck1"),
32 .n_voltages = 11 + 24 + 13,
33 .linear_ranges = pg86x_buck1_ranges,
34 .n_linear_ranges = 3,
35 .vsel_reg = 0x24,
36 .vsel_mask = 0xff,
37 .ops = &pg86x_ops,
38 .owner = THIS_MODULE
39 },
40 {
41 .id = 1,
42 .type = REGULATOR_VOLTAGE,
43 .name = "buck2",
44 .of_match = of_match_ptr("buck2"),
45 .n_voltages = 16 + 24 + 13,
46 .linear_ranges = pg86x_buck2_ranges,
47 .n_linear_ranges = 3,
48 .vsel_reg = 0x13,
49 .vsel_mask = 0xff,
50 .ops = &pg86x_ops,
51 .owner = THIS_MODULE
52 },
53};
54
55static const struct regmap_config pg86x_regmap = {
56 .reg_bits = 8,
57 .val_bits = 8,
58};
59
60static int pg86x_i2c_probe(struct i2c_client *i2c)
61{
62 int id, ret;
63 struct regulator_config config = {.dev = &i2c->dev};
64 struct regmap *regmap = devm_regmap_init_i2c(i2c, &pg86x_regmap);
65
66 if (IS_ERR(regmap)) {
67 ret = PTR_ERR(regmap);
68 dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
69 return ret;
70 }
71
72 for (id = 0; id < ARRAY_SIZE(pg86x_regulators); id++) {
73 struct regulator_dev *rdev;
74 rdev = devm_regulator_register(&i2c->dev,
75 &pg86x_regulators[id],
76 &config);
77 if (IS_ERR(rdev)) {
78 ret = PTR_ERR(rdev);
79 dev_err(&i2c->dev, "failed to register %s: %d\n",
80 pg86x_regulators[id].name, ret);
81 return ret;
82 }
83 }
84 return 0;
85}
86
87static const struct of_device_id pg86x_dt_ids [] = {
88 { .compatible = "marvell,88pg867" },
89 { .compatible = "marvell,88pg868" },
90 { }
91};
92MODULE_DEVICE_TABLE(of, pg86x_dt_ids);
93
94static const struct i2c_device_id pg86x_i2c_id[] = {
95 { "88pg867", },
96 { "88pg868", },
97 { }
98};
99MODULE_DEVICE_TABLE(i2c, pg86x_i2c_id);
100
101static struct i2c_driver pg86x_regulator_driver = {
102 .driver = {
103 .name = "88pg86x",
104 .of_match_table = of_match_ptr(pg86x_dt_ids),
105 },
106 .probe_new = pg86x_i2c_probe,
107 .id_table = pg86x_i2c_id,
108};
109
110module_i2c_driver(pg86x_regulator_driver);
111
112MODULE_DESCRIPTION("Marvell 88PG86X voltage regulator");
113MODULE_AUTHOR("Alexander Monakov <amonakov@gmail.com>");
114MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index b27417ca188a..097f61784a7d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -54,6 +54,15 @@ config REGULATOR_USERSPACE_CONSUMER
54 54
55 If unsure, say no. 55 If unsure, say no.
56 56
57config REGULATOR_88PG86X
58 tristate "Marvell 88PG86X voltage regulators"
59 depends on I2C
60 select REGMAP_I2C
61 help
62 This driver supports Marvell 88PG867 and 88PG868 voltage regulators.
63 They provide two I2C-controlled DC/DC step-down converters with
64 sleep mode and separate enable pins.
65
57config REGULATOR_88PM800 66config REGULATOR_88PM800
58 tristate "Marvell 88PM800 Power regulators" 67 tristate "Marvell 88PM800 Power regulators"
59 depends on MFD_88PM800 68 depends on MFD_88PM800
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 19fea09ba10a..590674fbecd7 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
10obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o 10obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
11obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o 11obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
12 12
13obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o
13obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o 14obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o
14obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o 15obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
15obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o 16obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o