Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / power / avs / rockchip-io-domain.c
1 /*
2  * Rockchip IO Voltage Domain driver
3  *
4  * Copyright 2014 MundoReader S.L.
5  * Copyright 2014 Google, Inc.
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/err.h>
20 #include <linux/mfd/syscon.h>
21 #include <linux/of.h>
22 #include <linux/platform_device.h>
23 #include <linux/regmap.h>
24 #include <linux/regulator/consumer.h>
25
26 #define MAX_SUPPLIES            16
27
28 /*
29  * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
30  * "Recommended Operating Conditions" for "Digital GPIO".   When the typical
31  * is 3.3V the max is 3.6V.  When the typical is 1.8V the max is 1.98V.
32  *
33  * They are used like this:
34  * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
35  *   SoC we're at 3.3.
36  * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
37  *   that to be an error.
38  */
39 #define MAX_VOLTAGE_1_8         1980000
40 #define MAX_VOLTAGE_3_3         3600000
41
42 #define RK3288_SOC_CON2                 0x24c
43 #define RK3288_SOC_CON2_FLASH0          BIT(7)
44 #define RK3288_SOC_FLASH_SUPPLY_NUM     2
45
46 struct rockchip_iodomain;
47
48 /**
49  * @supplies: voltage settings matching the register bits.
50  */
51 struct rockchip_iodomain_soc_data {
52         int grf_offset;
53         const char *supply_names[MAX_SUPPLIES];
54         void (*init)(struct rockchip_iodomain *iod);
55 };
56
57 struct rockchip_iodomain_supply {
58         struct rockchip_iodomain *iod;
59         struct regulator *reg;
60         struct notifier_block nb;
61         int idx;
62 };
63
64 struct rockchip_iodomain {
65         struct device *dev;
66         struct regmap *grf;
67         struct rockchip_iodomain_soc_data *soc_data;
68         struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
69 };
70
71 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
72                                    int uV)
73 {
74         struct rockchip_iodomain *iod = supply->iod;
75         u32 val;
76         int ret;
77
78         /* set value bit */
79         val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
80         val <<= supply->idx;
81
82         /* apply hiword-mask */
83         val |= (BIT(supply->idx) << 16);
84
85         ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
86         if (ret)
87                 dev_err(iod->dev, "Couldn't write to GRF\n");
88
89         return ret;
90 }
91
92 static int rockchip_iodomain_notify(struct notifier_block *nb,
93                                     unsigned long event,
94                                     void *data)
95 {
96         struct rockchip_iodomain_supply *supply =
97                         container_of(nb, struct rockchip_iodomain_supply, nb);
98         int uV;
99         int ret;
100
101         /*
102          * According to Rockchip it's important to keep the SoC IO domain
103          * higher than (or equal to) the external voltage.  That means we need
104          * to change it before external voltage changes happen in the case
105          * of an increase.
106          *
107          * Note that in the "pre" change we pick the max possible voltage that
108          * the regulator might end up at (the client requests a range and we
109          * don't know for certain the exact voltage).  Right now we rely on the
110          * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients
111          * request something like a max of 3.6V when they really want 3.3V.
112          * We could attempt to come up with better rules if this fails.
113          */
114         if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
115                 struct pre_voltage_change_data *pvc_data = data;
116
117                 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
118         } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
119                             REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
120                 uV = (unsigned long)data;
121         } else {
122                 return NOTIFY_OK;
123         }
124
125         dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
126
127         if (uV > MAX_VOLTAGE_3_3) {
128                 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
129
130                 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
131                         return NOTIFY_BAD;
132         }
133
134         ret = rockchip_iodomain_write(supply, uV);
135         if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
136                 return NOTIFY_BAD;
137
138         dev_info(supply->iod->dev, "Setting to %d done\n", uV);
139         return NOTIFY_OK;
140 }
141
142 static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
143 {
144         int ret;
145         u32 val;
146
147         /* if no flash supply we should leave things alone */
148         if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
149                 return;
150
151         /*
152          * set flash0 iodomain to also use this framework
153          * instead of a special gpio.
154          */
155         val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
156         ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
157         if (ret < 0)
158                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
159 }
160
161 /*
162  * On the rk3188 the io-domains are handled by a shared register with the
163  * lower 8 bits being still being continuing drive-strength settings.
164  */
165 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
166         .grf_offset = 0x104,
167         .supply_names = {
168                 NULL,
169                 NULL,
170                 NULL,
171                 NULL,
172                 NULL,
173                 NULL,
174                 NULL,
175                 NULL,
176                 "ap0",
177                 "ap1",
178                 "cif",
179                 "flash",
180                 "vccio0",
181                 "vccio1",
182                 "lcdc0",
183                 "lcdc1",
184         },
185 };
186
187 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
188         .grf_offset = 0x380,
189         .supply_names = {
190                 "lcdc",         /* LCDC_VDD */
191                 "dvp",          /* DVPIO_VDD */
192                 "flash0",       /* FLASH0_VDD (emmc) */
193                 "flash1",       /* FLASH1_VDD (sdio1) */
194                 "wifi",         /* APIO3_VDD  (sdio0) */
195                 "bb",           /* APIO5_VDD */
196                 "audio",        /* APIO4_VDD */
197                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
198                 "gpio30",       /* APIO1_VDD */
199                 "gpio1830",     /* APIO2_VDD */
200         },
201         .init = rk3288_iodomain_init,
202 };
203
204 static const struct of_device_id rockchip_iodomain_match[] = {
205         {
206                 .compatible = "rockchip,rk3188-io-voltage-domain",
207                 .data = (void *)&soc_data_rk3188
208         },
209         {
210                 .compatible = "rockchip,rk3288-io-voltage-domain",
211                 .data = (void *)&soc_data_rk3288
212         },
213         { /* sentinel */ },
214 };
215
216 static int rockchip_iodomain_probe(struct platform_device *pdev)
217 {
218         struct device_node *np = pdev->dev.of_node;
219         const struct of_device_id *match;
220         struct rockchip_iodomain *iod;
221         int i, ret = 0;
222
223         if (!np)
224                 return -ENODEV;
225
226         iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
227         if (!iod)
228                 return -ENOMEM;
229
230         iod->dev = &pdev->dev;
231         platform_set_drvdata(pdev, iod);
232
233         match = of_match_node(rockchip_iodomain_match, np);
234         iod->soc_data = (struct rockchip_iodomain_soc_data *)match->data;
235
236         iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
237         if (IS_ERR(iod->grf)) {
238                 dev_err(&pdev->dev, "couldn't find grf regmap\n");
239                 return PTR_ERR(iod->grf);
240         }
241
242         for (i = 0; i < MAX_SUPPLIES; i++) {
243                 const char *supply_name = iod->soc_data->supply_names[i];
244                 struct rockchip_iodomain_supply *supply = &iod->supplies[i];
245                 struct regulator *reg;
246                 int uV;
247
248                 if (!supply_name)
249                         continue;
250
251                 reg = devm_regulator_get_optional(iod->dev, supply_name);
252                 if (IS_ERR(reg)) {
253                         ret = PTR_ERR(reg);
254
255                         /* If a supply wasn't specified, that's OK */
256                         if (ret == -ENODEV)
257                                 continue;
258                         else if (ret != -EPROBE_DEFER)
259                                 dev_err(iod->dev, "couldn't get regulator %s\n",
260                                         supply_name);
261                         goto unreg_notify;
262                 }
263
264                 /* set initial correct value */
265                 uV = regulator_get_voltage(reg);
266
267                 /* must be a regulator we can get the voltage of */
268                 if (uV < 0) {
269                         dev_err(iod->dev, "Can't determine voltage: %s\n",
270                                 supply_name);
271                         goto unreg_notify;
272                 }
273
274                 if (uV > MAX_VOLTAGE_3_3) {
275                         dev_crit(iod->dev,
276                                  "%d uV is too high. May damage SoC!\n",
277                                  uV);
278                         ret = -EINVAL;
279                         goto unreg_notify;
280                 }
281
282                 /* setup our supply */
283                 supply->idx = i;
284                 supply->iod = iod;
285                 supply->reg = reg;
286                 supply->nb.notifier_call = rockchip_iodomain_notify;
287
288                 ret = rockchip_iodomain_write(supply, uV);
289                 if (ret) {
290                         supply->reg = NULL;
291                         goto unreg_notify;
292                 }
293
294                 /* register regulator notifier */
295                 ret = regulator_register_notifier(reg, &supply->nb);
296                 if (ret) {
297                         dev_err(&pdev->dev,
298                                 "regulator notifier request failed\n");
299                         supply->reg = NULL;
300                         goto unreg_notify;
301                 }
302         }
303
304         if (iod->soc_data->init)
305                 iod->soc_data->init(iod);
306
307         return 0;
308
309 unreg_notify:
310         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
311                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
312
313                 if (io_supply->reg)
314                         regulator_unregister_notifier(io_supply->reg,
315                                                       &io_supply->nb);
316         }
317
318         return ret;
319 }
320
321 static int rockchip_iodomain_remove(struct platform_device *pdev)
322 {
323         struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
324         int i;
325
326         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
327                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
328
329                 if (io_supply->reg)
330                         regulator_unregister_notifier(io_supply->reg,
331                                                       &io_supply->nb);
332         }
333
334         return 0;
335 }
336
337 static struct platform_driver rockchip_iodomain_driver = {
338         .probe   = rockchip_iodomain_probe,
339         .remove  = rockchip_iodomain_remove,
340         .driver  = {
341                 .name  = "rockchip-iodomain",
342                 .of_match_table = rockchip_iodomain_match,
343         },
344 };
345
346 module_platform_driver(rockchip_iodomain_driver);
347
348 MODULE_DESCRIPTION("Rockchip IO-domain driver");
349 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
350 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
351 MODULE_LICENSE("GPL v2");