1 // SPDX-License-Identifier: GPL-2.0
3 // SY8824C/SY8824E regulator driver
5 // Copyright (C) 2019 Synaptics Incorporated
7 // Author: Jisheng Zhang <jszhang@kernel.org>
9 #include <linux/module.h>
10 #include <linux/i2c.h>
11 #include <linux/of_device.h>
12 #include <linux/regmap.h>
13 #include <linux/regulator/driver.h>
14 #include <linux/regulator/of_regulator.h>
16 #define SY8824C_BUCK_EN (1 << 7)
17 #define SY8824C_MODE (1 << 6)
19 struct sy8824_config
{
22 unsigned int mode_reg
;
23 unsigned int enable_reg
;
24 /* Voltage range and step(linear) */
25 unsigned int vsel_min
;
26 unsigned int vsel_step
;
27 unsigned int vsel_count
;
30 struct sy8824_device_info
{
32 struct regulator_desc desc
;
33 struct regulator_init_data
*regulator
;
34 const struct sy8824_config
*cfg
;
37 static int sy8824_set_mode(struct regulator_dev
*rdev
, unsigned int mode
)
39 struct sy8824_device_info
*di
= rdev_get_drvdata(rdev
);
40 const struct sy8824_config
*cfg
= di
->cfg
;
43 case REGULATOR_MODE_FAST
:
44 regmap_update_bits(rdev
->regmap
, cfg
->mode_reg
,
45 SY8824C_MODE
, SY8824C_MODE
);
47 case REGULATOR_MODE_NORMAL
:
48 regmap_update_bits(rdev
->regmap
, cfg
->mode_reg
,
57 static unsigned int sy8824_get_mode(struct regulator_dev
*rdev
)
59 struct sy8824_device_info
*di
= rdev_get_drvdata(rdev
);
60 const struct sy8824_config
*cfg
= di
->cfg
;
64 ret
= regmap_read(rdev
->regmap
, cfg
->mode_reg
, &val
);
67 if (val
& SY8824C_MODE
)
68 return REGULATOR_MODE_FAST
;
70 return REGULATOR_MODE_NORMAL
;
73 static const struct regulator_ops sy8824_regulator_ops
= {
74 .set_voltage_sel
= regulator_set_voltage_sel_regmap
,
75 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
76 .set_voltage_time_sel
= regulator_set_voltage_time_sel
,
77 .map_voltage
= regulator_map_voltage_linear
,
78 .list_voltage
= regulator_list_voltage_linear
,
79 .enable
= regulator_enable_regmap
,
80 .disable
= regulator_disable_regmap
,
81 .is_enabled
= regulator_is_enabled_regmap
,
82 .set_mode
= sy8824_set_mode
,
83 .get_mode
= sy8824_get_mode
,
86 static int sy8824_regulator_register(struct sy8824_device_info
*di
,
87 struct regulator_config
*config
)
89 struct regulator_desc
*rdesc
= &di
->desc
;
90 const struct sy8824_config
*cfg
= di
->cfg
;
91 struct regulator_dev
*rdev
;
93 rdesc
->name
= "sy8824-reg";
94 rdesc
->supply_name
= "vin";
95 rdesc
->ops
= &sy8824_regulator_ops
;
96 rdesc
->type
= REGULATOR_VOLTAGE
;
97 rdesc
->n_voltages
= cfg
->vsel_count
;
98 rdesc
->enable_reg
= cfg
->enable_reg
;
99 rdesc
->enable_mask
= SY8824C_BUCK_EN
;
100 rdesc
->min_uV
= cfg
->vsel_min
;
101 rdesc
->uV_step
= cfg
->vsel_step
;
102 rdesc
->vsel_reg
= cfg
->vol_reg
;
103 rdesc
->vsel_mask
= cfg
->vsel_count
- 1;
104 rdesc
->owner
= THIS_MODULE
;
106 rdev
= devm_regulator_register(di
->dev
, &di
->desc
, config
);
107 return PTR_ERR_OR_ZERO(rdev
);
110 static const struct regmap_config sy8824_regmap_config
= {
115 static int sy8824_i2c_probe(struct i2c_client
*client
,
116 const struct i2c_device_id
*id
)
118 struct device
*dev
= &client
->dev
;
119 struct device_node
*np
= dev
->of_node
;
120 struct sy8824_device_info
*di
;
121 struct regulator_config config
= { };
122 struct regmap
*regmap
;
125 di
= devm_kzalloc(dev
, sizeof(struct sy8824_device_info
), GFP_KERNEL
);
129 di
->regulator
= of_get_regulator_init_data(dev
, np
, &di
->desc
);
130 if (!di
->regulator
) {
131 dev_err(dev
, "Platform data not found!\n");
136 di
->cfg
= of_device_get_match_data(dev
);
138 regmap
= devm_regmap_init_i2c(client
, &sy8824_regmap_config
);
139 if (IS_ERR(regmap
)) {
140 dev_err(dev
, "Failed to allocate regmap!\n");
141 return PTR_ERR(regmap
);
143 i2c_set_clientdata(client
, di
);
145 config
.dev
= di
->dev
;
146 config
.init_data
= di
->regulator
;
147 config
.regmap
= regmap
;
148 config
.driver_data
= di
;
151 ret
= sy8824_regulator_register(di
, &config
);
153 dev_err(dev
, "Failed to register regulator!\n");
157 static const struct sy8824_config sy8824c_cfg
= {
166 static const struct sy8824_config sy8824e_cfg
= {
175 static const struct sy8824_config sy20276_cfg
= {
184 static const struct sy8824_config sy20278_cfg
= {
193 static const struct of_device_id sy8824_dt_ids
[] = {
195 .compatible
= "silergy,sy8824c",
199 .compatible
= "silergy,sy8824e",
203 .compatible
= "silergy,sy20276",
207 .compatible
= "silergy,sy20278",
212 MODULE_DEVICE_TABLE(of
, sy8824_dt_ids
);
214 static const struct i2c_device_id sy8824_id
[] = {
218 MODULE_DEVICE_TABLE(i2c
, sy8824_id
);
220 static struct i2c_driver sy8824_regulator_driver
= {
222 .name
= "sy8824-regulator",
223 .of_match_table
= of_match_ptr(sy8824_dt_ids
),
225 .probe
= sy8824_i2c_probe
,
226 .id_table
= sy8824_id
,
228 module_i2c_driver(sy8824_regulator_driver
);
230 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
231 MODULE_DESCRIPTION("SY8824C/SY8824E regulator driver");
232 MODULE_LICENSE("GPL v2");