Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / power / regulator / fan53555.c
1 // SPDX-License-Identifier:     GPL-2.0+
2 /*
3  * (C) 2018 Theobroma Systems Design und Consulting GmbH
4  */
5
6 #include <common.h>
7 #include <bitfield.h>
8 #include <errno.h>
9 #include <dm.h>
10 #include <fdtdec.h>
11 #include <log.h>
12 #include <asm/gpio.h>
13 #include <linux/bitops.h>
14 #include <power/fan53555.h>
15 #include <power/pmic.h>
16 #include <power/regulator.h>
17
18 /**
19  * struct ic_types - definition of fan53555-family devices
20  *
21  * @die_id: Identifies the DIE_ID (lower nibble of the ID1 register)
22  * @die_rev: Identifies the DIE_REV (lower nibble of the ID2 register)
23  * @vsel_min: starting voltage (step 0) in uV
24  * @vsel_step: increment of the voltage in uV
25  *
26  * The voltage ramp (i.e. minimum voltage and step) is selected from the
27  * combination of 2 nibbles: DIE_ID and DIE_REV.
28  *
29  * See http://www.onsemi.com/pub/Collateral/FAN53555-D.pdf for details.
30  */
31 static const struct {
32         unsigned int vendor;
33         u8 die_id;
34         u8 die_rev;
35         bool check_rev;
36         u32 vsel_min;
37         u32 vsel_step;
38 } ic_types[] = {
39         /* Option 00 */
40         { FAN53555_VENDOR_FAIRCHILD, 0x0, 0x3, true,  600000, 10000 },
41         /* Option 13 */
42         { FAN53555_VENDOR_FAIRCHILD, 0x0, 0xf, true,  800000, 10000 },
43         /* Option 23 */
44         { FAN53555_VENDOR_FAIRCHILD, 0x0, 0xc, true,  600000, 12500 },
45         /* Option 01 */
46         { FAN53555_VENDOR_FAIRCHILD, 0x1, 0x3, true,  600000, 10000 },
47         /* Option 03 */
48         { FAN53555_VENDOR_FAIRCHILD, 0x3, 0x3, true,  600000, 10000 },
49         /* Option 04 */
50         { FAN53555_VENDOR_FAIRCHILD, 0x4, 0xf, true,  603000, 12826 },
51         /* Option 05 */
52         { FAN53555_VENDOR_FAIRCHILD, 0x5, 0x3, true,  600000, 10000 },
53         /* Option 08 */
54         { FAN53555_VENDOR_FAIRCHILD, 0x8, 0x1, true,  600000, 10000 },
55         /* Option 08 */
56         { FAN53555_VENDOR_FAIRCHILD, 0x8, 0xf, true,  600000, 10000 },
57         /* Option 09 */
58         { FAN53555_VENDOR_FAIRCHILD, 0xc, 0xf, true,  603000, 12826 },
59         /* SYL82X */
60         { FAN53555_VENDOR_SILERGY,   0x8, 0x0, false, 712500, 12500 },
61         /* SYL83X */
62         { FAN53555_VENDOR_SILERGY,   0x9, 0x0, false, 712500, 12500 },
63 };
64
65 /* I2C-accessible byte-sized registers */
66 enum {
67         /* Voltage setting */
68         FAN53555_VSEL0 = 0x00,
69         FAN53555_VSEL1,
70         /* Control register */
71         FAN53555_CONTROL,
72         /* IC Type */
73         FAN53555_ID1,
74         /* IC mask version */
75         FAN53555_ID2,
76         /* Monitor register */
77         FAN53555_MONITOR,
78 };
79
80 struct fan53555_plat {
81         /* Voltage setting register */
82         unsigned int vol_reg;
83         unsigned int sleep_reg;
84
85 };
86
87 struct fan53555_priv {
88         /* IC Vendor */
89         unsigned int vendor;
90         /* IC Type and Rev */
91         unsigned int die_id;
92         unsigned int die_rev;
93         /* Voltage range and step(linear) */
94         unsigned int vsel_min;
95         unsigned int vsel_step;
96         /* Voltage slew rate limiting */
97         unsigned int slew_rate;
98         /* Sleep voltage cache */
99         unsigned int sleep_vol_cache;
100 };
101
102 static int fan53555_regulator_of_to_plat(struct udevice *dev)
103 {
104         struct fan53555_plat *plat = dev_get_plat(dev);
105         struct dm_regulator_uclass_plat *uc_pdata =
106                 dev_get_uclass_plat(dev);
107         u32 sleep_vsel;
108
109         /* This is a buck regulator */
110         uc_pdata->type = REGULATOR_TYPE_BUCK;
111
112         sleep_vsel = dev_read_u32_default(dev, "fcs,suspend-voltage-selector",
113                                           FAN53555_VSEL1);
114
115         /*
116          * Depending on the device-tree settings, the 'normal mode'
117          * voltage is either controlled by VSEL0 or VSEL1.
118          */
119         switch (sleep_vsel) {
120         case FAN53555_VSEL0:
121                 plat->sleep_reg = FAN53555_VSEL0;
122                 plat->vol_reg = FAN53555_VSEL1;
123                 break;
124         case FAN53555_VSEL1:
125                 plat->sleep_reg = FAN53555_VSEL1;
126                 plat->vol_reg = FAN53555_VSEL0;
127                 break;
128         default:
129                 pr_err("%s: invalid vsel id %d\n", dev->name, sleep_vsel);
130                 return -EINVAL;
131         }
132
133         return 0;
134 }
135
136 static int fan53555_regulator_get_value(struct udevice *dev)
137 {
138         struct fan53555_plat *pdata = dev_get_plat(dev);
139         struct fan53555_priv *priv = dev_get_priv(dev);
140         int reg;
141         int voltage;
142
143         /* We only support a single voltage selector (i.e. 'normal' mode). */
144         reg = pmic_reg_read(dev->parent, pdata->vol_reg);
145         if (reg < 0)
146                 return reg;
147         voltage = priv->vsel_min + (reg & 0x3f) * priv->vsel_step;
148
149         debug("%s: %d uV\n", __func__, voltage);
150         return voltage;
151 }
152
153 static int fan53555_regulator_set_value(struct udevice *dev, int uV)
154 {
155         struct fan53555_plat *pdata = dev_get_plat(dev);
156         struct fan53555_priv *priv = dev_get_priv(dev);
157         u8 vol;
158
159         vol = (uV - priv->vsel_min) / priv->vsel_step;
160         debug("%s: uV=%d; writing volume %d: %02x\n",
161               __func__, uV, pdata->vol_reg, vol);
162
163         return pmic_clrsetbits(dev->parent, pdata->vol_reg, GENMASK(6, 0), vol);
164 }
165
166 static int fan53555_voltages_setup(struct udevice *dev)
167 {
168         struct fan53555_priv *priv = dev_get_priv(dev);
169         int i;
170
171         /* Init voltage range and step */
172         for (i = 0; i < ARRAY_SIZE(ic_types); ++i) {
173                 if (ic_types[i].vendor != priv->vendor)
174                         continue;
175
176                 if (ic_types[i].die_id != priv->die_id)
177                         continue;
178
179                 if (ic_types[i].check_rev &&
180                     ic_types[i].die_rev != priv->die_rev)
181                         continue;
182
183                 priv->vsel_min = ic_types[i].vsel_min;
184                 priv->vsel_step = ic_types[i].vsel_step;
185
186                 return 0;
187         }
188
189         pr_err("%s: %s: die id %d rev %d not supported!\n",
190                dev->name, __func__, priv->die_id, priv->die_rev);
191         return -EINVAL;
192 }
193
194 enum {
195         DIE_ID_SHIFT = 0,
196         DIE_ID_WIDTH = 4,
197         DIE_REV_SHIFT = 0,
198         DIE_REV_WIDTH = 4,
199 };
200
201 static int fan53555_probe(struct udevice *dev)
202 {
203         struct fan53555_priv *priv = dev_get_priv(dev);
204         int ID1, ID2;
205
206         debug("%s\n", __func__);
207
208         /* read chip ID1 and ID2 (two registers, starting at ID1) */
209         ID1 = pmic_reg_read(dev->parent, FAN53555_ID1);
210         if (ID1 < 0)
211                 return ID1;
212
213         ID2 = pmic_reg_read(dev->parent, FAN53555_ID2);
214         if (ID2 < 0)
215                 return ID2;
216
217         /* extract vendor, die_id and die_rev */
218         priv->vendor = dev->driver_data;
219         priv->die_id = ID1 & GENMASK(3, 0);
220         priv->die_rev = ID2 & GENMASK(3, 0);
221
222         if (fan53555_voltages_setup(dev) < 0)
223                 return -ENODATA;
224
225         debug("%s: FAN53555 option %d rev %d detected\n",
226               __func__, priv->die_id, priv->die_rev);
227
228         return 0;
229 }
230
231 static const struct dm_regulator_ops fan53555_regulator_ops = {
232         .get_value      = fan53555_regulator_get_value,
233         .set_value      = fan53555_regulator_set_value,
234 };
235
236 U_BOOT_DRIVER(fan53555_regulator) = {
237         .name = "fan53555_regulator",
238         .id = UCLASS_REGULATOR,
239         .ops = &fan53555_regulator_ops,
240         .of_to_plat = fan53555_regulator_of_to_plat,
241         .plat_auto      = sizeof(struct fan53555_plat),
242         .priv_auto      = sizeof(struct fan53555_priv),
243         .probe = fan53555_probe,
244 };