1 // SPDX-License-Identifier: GPL-2.0
3 // SY8827N regulator driver
5 // Copyright (C) 2020 Synaptics Incorporated
7 // Author: Jisheng Zhang <jszhang@kernel.org>
9 #include <linux/gpio/consumer.h>
10 #include <linux/module.h>
11 #include <linux/i2c.h>
13 #include <linux/regmap.h>
14 #include <linux/regulator/driver.h>
15 #include <linux/regulator/of_regulator.h>
17 #define SY8827N_VSEL0 0
18 #define SY8827N_BUCK_EN (1 << 7)
19 #define SY8827N_MODE (1 << 6)
20 #define SY8827N_VSEL1 1
21 #define SY8827N_CTRL 2
24 #define SY8827N_PGOOD 5
25 #define SY8827N_MAX (SY8827N_PGOOD + 1)
27 #define SY8827N_NVOLTAGES 64
28 #define SY8827N_VSELMIN 600000
29 #define SY8827N_VSELSTEP 12500
31 struct sy8827n_device_info
{
33 struct regulator_desc desc
;
34 struct regulator_init_data
*regulator
;
35 struct gpio_desc
*en_gpio
;
36 unsigned int vsel_reg
;
39 static int sy8827n_set_mode(struct regulator_dev
*rdev
, unsigned int mode
)
41 struct sy8827n_device_info
*di
= rdev_get_drvdata(rdev
);
44 case REGULATOR_MODE_FAST
:
45 regmap_update_bits(rdev
->regmap
, di
->vsel_reg
,
46 SY8827N_MODE
, SY8827N_MODE
);
48 case REGULATOR_MODE_NORMAL
:
49 regmap_update_bits(rdev
->regmap
, di
->vsel_reg
,
58 static unsigned int sy8827n_get_mode(struct regulator_dev
*rdev
)
60 struct sy8827n_device_info
*di
= rdev_get_drvdata(rdev
);
64 ret
= regmap_read(rdev
->regmap
, di
->vsel_reg
, &val
);
67 if (val
& SY8827N_MODE
)
68 return REGULATOR_MODE_FAST
;
70 return REGULATOR_MODE_NORMAL
;
73 static const struct regulator_ops sy8827n_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
= sy8827n_set_mode
,
83 .get_mode
= sy8827n_get_mode
,
86 static int sy8827n_regulator_register(struct sy8827n_device_info
*di
,
87 struct regulator_config
*config
)
89 struct regulator_desc
*rdesc
= &di
->desc
;
90 struct regulator_dev
*rdev
;
92 rdesc
->name
= "sy8827n-reg";
93 rdesc
->supply_name
= "vin";
94 rdesc
->ops
= &sy8827n_regulator_ops
;
95 rdesc
->type
= REGULATOR_VOLTAGE
;
96 rdesc
->n_voltages
= SY8827N_NVOLTAGES
;
97 rdesc
->enable_reg
= di
->vsel_reg
;
98 rdesc
->enable_mask
= SY8827N_BUCK_EN
;
99 rdesc
->min_uV
= SY8827N_VSELMIN
;
100 rdesc
->uV_step
= SY8827N_VSELSTEP
;
101 rdesc
->vsel_reg
= di
->vsel_reg
;
102 rdesc
->vsel_mask
= rdesc
->n_voltages
- 1;
103 rdesc
->owner
= THIS_MODULE
;
105 rdev
= devm_regulator_register(di
->dev
, &di
->desc
, config
);
106 return PTR_ERR_OR_ZERO(rdev
);
109 static bool sy8827n_volatile_reg(struct device
*dev
, unsigned int reg
)
111 if (reg
== SY8827N_PGOOD
)
116 static const struct regmap_config sy8827n_regmap_config
= {
119 .volatile_reg
= sy8827n_volatile_reg
,
120 .num_reg_defaults_raw
= SY8827N_MAX
,
121 .cache_type
= REGCACHE_FLAT
,
124 static int sy8827n_i2c_probe(struct i2c_client
*client
)
126 struct device
*dev
= &client
->dev
;
127 struct device_node
*np
= dev
->of_node
;
128 struct sy8827n_device_info
*di
;
129 struct regulator_config config
= { };
130 struct regmap
*regmap
;
133 di
= devm_kzalloc(dev
, sizeof(struct sy8827n_device_info
), GFP_KERNEL
);
137 di
->regulator
= of_get_regulator_init_data(dev
, np
, &di
->desc
);
138 if (!di
->regulator
) {
139 dev_err(dev
, "Platform data not found!\n");
143 di
->en_gpio
= devm_gpiod_get_optional(dev
, "enable", GPIOD_OUT_HIGH
);
144 if (IS_ERR(di
->en_gpio
))
145 return PTR_ERR(di
->en_gpio
);
147 if (of_property_read_bool(np
, "silergy,vsel-state-high"))
148 di
->vsel_reg
= SY8827N_VSEL1
;
150 di
->vsel_reg
= SY8827N_VSEL0
;
154 regmap
= devm_regmap_init_i2c(client
, &sy8827n_regmap_config
);
155 if (IS_ERR(regmap
)) {
156 dev_err(dev
, "Failed to allocate regmap!\n");
157 return PTR_ERR(regmap
);
159 i2c_set_clientdata(client
, di
);
161 config
.dev
= di
->dev
;
162 config
.init_data
= di
->regulator
;
163 config
.regmap
= regmap
;
164 config
.driver_data
= di
;
167 ret
= sy8827n_regulator_register(di
, &config
);
169 dev_err(dev
, "Failed to register regulator!\n");
173 static const struct of_device_id sy8827n_dt_ids
[] = {
175 .compatible
= "silergy,sy8827n",
179 MODULE_DEVICE_TABLE(of
, sy8827n_dt_ids
);
181 static const struct i2c_device_id sy8827n_id
[] = {
185 MODULE_DEVICE_TABLE(i2c
, sy8827n_id
);
187 static struct i2c_driver sy8827n_regulator_driver
= {
189 .name
= "sy8827n-regulator",
190 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
191 .of_match_table
= sy8827n_dt_ids
,
193 .probe
= sy8827n_i2c_probe
,
194 .id_table
= sy8827n_id
,
196 module_i2c_driver(sy8827n_regulator_driver
);
198 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
199 MODULE_DESCRIPTION("SY8827N regulator driver");
200 MODULE_LICENSE("GPL v2");