1 // SPDX-License-Identifier: GPL-2.0+
3 // sy8106a-regulator.c - Regulator device driver for SY8106A
5 // Copyright (C) 2016 Ondřej Jirman <megous@megous.com>
6 // Copyright (c) 2017-2018 Icenowy Zheng <icenowy@aosc.io>
10 #include <linux/module.h>
11 #include <linux/regmap.h>
12 #include <linux/regulator/driver.h>
13 #include <linux/regulator/of_regulator.h>
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)
20 * The I2C controlled voltage will only work when this bit is set; otherwise
21 * it will behave like a fixed regulator.
23 #define SY8106A_GO_BIT BIT(7)
26 struct regulator_dev
*rdev
;
27 struct regmap
*regmap
;
31 static const struct regmap_config sy8106a_regmap_config
= {
36 static 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 */
44 /* Default limits measured in millivolts */
45 #define SY8106A_MIN_MV 680
46 #define SY8106A_MAX_MV 1950
47 #define SY8106A_STEP_MV 10
49 static const struct regulator_desc sy8106a_reg
= {
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
,
60 * This ramp_delay is a conservative default value which works on
61 * H3/H5 boards VDD-CPUX situations.
68 * I2C driver interface functions
70 static int sy8106a_i2c_probe(struct i2c_client
*i2c
,
71 const struct i2c_device_id
*id
)
74 struct device
*dev
= &i2c
->dev
;
75 struct regulator_dev
*rdev
= NULL
;
76 struct regulator_config config
= { };
77 unsigned int reg
, vsel
;
80 chip
= devm_kzalloc(&i2c
->dev
, sizeof(struct sy8106a
), GFP_KERNEL
);
84 error
= of_property_read_u32(dev
->of_node
, "silergy,fixed-microvolt",
85 &chip
->fixed_voltage
);
89 if (chip
->fixed_voltage
< SY8106A_MIN_MV
* 1000 ||
90 chip
->fixed_voltage
> SY8106A_MAX_MV
* 1000)
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
);
100 config
.dev
= &i2c
->dev
;
101 config
.regmap
= chip
->regmap
;
102 config
.driver_data
= chip
;
104 config
.of_node
= dev
->of_node
;
105 config
.init_data
= of_get_regulator_init_data(dev
, dev
->of_node
,
108 if (!config
.init_data
)
111 /* Ensure GO_BIT is enabled when probing */
112 error
= regmap_read(chip
->regmap
, SY8106A_REG_VOUT1_SEL
, ®
);
116 if (!(reg
& SY8106A_GO_BIT
)) {
117 vsel
= (chip
->fixed_voltage
/ 1000 - SY8106A_MIN_MV
) /
120 error
= regmap_write(chip
->regmap
, SY8106A_REG_VOUT1_SEL
,
121 vsel
| SY8106A_GO_BIT
);
126 /* Probe regulator */
127 rdev
= devm_regulator_register(&i2c
->dev
, &sy8106a_reg
, &config
);
129 error
= PTR_ERR(rdev
);
130 dev_err(&i2c
->dev
, "Failed to register SY8106A regulator: %d\n", error
);
136 i2c_set_clientdata(i2c
, chip
);
141 static const struct of_device_id sy8106a_i2c_of_match
[] = {
142 { .compatible
= "silergy,sy8106a" },
145 MODULE_DEVICE_TABLE(of
, sy8106a_i2c_of_match
);
147 static const struct i2c_device_id sy8106a_i2c_id
[] = {
151 MODULE_DEVICE_TABLE(i2c
, sy8106a_i2c_id
);
153 static struct i2c_driver sy8106a_regulator_driver
= {
156 .of_match_table
= of_match_ptr(sy8106a_i2c_of_match
),
158 .probe
= sy8106a_i2c_probe
,
159 .id_table
= sy8106a_i2c_id
,
162 module_i2c_driver(sy8106a_regulator_driver
);
164 MODULE_AUTHOR("Ondřej Jirman <megous@megous.com>");
165 MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
166 MODULE_DESCRIPTION("Regulator device driver for Silergy SY8106A");
167 MODULE_LICENSE("GPL");