POWER: AVS: rockchip: add rk3399 io domain support
[firefly-linux-kernel-4.4.55.git] / 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 #define RK3366_SOC_CON6                 0x418
47 #define RK3366_SOC_CON6_FLASH0          BIT(14)
48 #define RK3366_SOC_FLASH_SUPPLY_NUM     2
49
50 #define RK3368_SOC_CON15                0x43c
51 #define RK3368_SOC_CON15_FLASH0         BIT(14)
52 #define RK3368_SOC_FLASH_SUPPLY_NUM     2
53
54 #define RK3399_PMUGRF_CON0              0x180
55 #define RK3399_PMUGRF_CON0_VSEL         BIT(8)
56 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM   9
57
58 struct rockchip_iodomain;
59
60 /**
61  * @supplies: voltage settings matching the register bits.
62  */
63 struct rockchip_iodomain_soc_data {
64         int grf_offset;
65         const char *supply_names[MAX_SUPPLIES];
66         void (*init)(struct rockchip_iodomain *iod);
67 };
68
69 struct rockchip_iodomain_supply {
70         struct rockchip_iodomain *iod;
71         struct regulator *reg;
72         struct notifier_block nb;
73         int idx;
74 };
75
76 struct rockchip_iodomain {
77         struct device *dev;
78         struct regmap *grf;
79         struct rockchip_iodomain_soc_data *soc_data;
80         struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
81 };
82
83 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
84                                    int uV)
85 {
86         struct rockchip_iodomain *iod = supply->iod;
87         u32 val;
88         int ret;
89
90         /* set value bit */
91         val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
92         val <<= supply->idx;
93
94         /* apply hiword-mask */
95         val |= (BIT(supply->idx) << 16);
96
97         ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
98         if (ret)
99                 dev_err(iod->dev, "Couldn't write to GRF\n");
100
101         return ret;
102 }
103
104 static int rockchip_iodomain_notify(struct notifier_block *nb,
105                                     unsigned long event,
106                                     void *data)
107 {
108         struct rockchip_iodomain_supply *supply =
109                         container_of(nb, struct rockchip_iodomain_supply, nb);
110         int uV;
111         int ret;
112
113         /*
114          * According to Rockchip it's important to keep the SoC IO domain
115          * higher than (or equal to) the external voltage.  That means we need
116          * to change it before external voltage changes happen in the case
117          * of an increase.
118          *
119          * Note that in the "pre" change we pick the max possible voltage that
120          * the regulator might end up at (the client requests a range and we
121          * don't know for certain the exact voltage).  Right now we rely on the
122          * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients
123          * request something like a max of 3.6V when they really want 3.3V.
124          * We could attempt to come up with better rules if this fails.
125          */
126         if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
127                 struct pre_voltage_change_data *pvc_data = data;
128
129                 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
130         } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
131                             REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
132                 uV = (unsigned long)data;
133         } else {
134                 return NOTIFY_OK;
135         }
136
137         dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
138
139         if (uV > MAX_VOLTAGE_3_3) {
140                 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
141
142                 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
143                         return NOTIFY_BAD;
144         }
145
146         ret = rockchip_iodomain_write(supply, uV);
147         if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
148                 return NOTIFY_BAD;
149
150         dev_info(supply->iod->dev, "Setting to %d done\n", uV);
151         return NOTIFY_OK;
152 }
153
154 static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
155 {
156         int ret;
157         u32 val;
158
159         /* if no flash supply we should leave things alone */
160         if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
161                 return;
162
163         /*
164          * set flash0 iodomain to also use this framework
165          * instead of a special gpio.
166          */
167         val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
168         ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
169         if (ret < 0)
170                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
171 }
172
173 static void rk3366_iodomain_init(struct rockchip_iodomain *iod)
174 {
175         int ret;
176         u32 val;
177
178         /* if no flash supply we should leave things alone */
179         if (!iod->supplies[RK3366_SOC_FLASH_SUPPLY_NUM].reg)
180                 return;
181
182         /*
183          * set flash0 iodomain to also use this framework
184          * instead of a special gpio.
185          */
186         val = RK3366_SOC_CON6_FLASH0 | (RK3366_SOC_CON6_FLASH0 << 16);
187         ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
188         if (ret < 0)
189                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
190 }
191
192 static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
193 {
194         int ret;
195         u32 val;
196
197         /* if no flash supply we should leave things alone */
198         if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
199                 return;
200
201         /*
202          * set flash0 iodomain to also use this framework
203          * instead of a special gpio.
204          */
205         val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
206         ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
207         if (ret < 0)
208                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
209 }
210
211 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
212 {
213         int ret;
214         u32 val;
215
216         /* if no pmu io supply we should leave things alone */
217         if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
218                 return;
219
220         /*
221          * set pmu io iodomain to also use this framework
222          * instead of a special gpio.
223          */
224         val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
225         ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val);
226         if (ret < 0)
227                 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
228 }
229
230 /*
231  * On the rk3188 the io-domains are handled by a shared register with the
232  * lower 8 bits being still being continuing drive-strength settings.
233  */
234 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
235         .grf_offset = 0x104,
236         .supply_names = {
237                 NULL,
238                 NULL,
239                 NULL,
240                 NULL,
241                 NULL,
242                 NULL,
243                 NULL,
244                 NULL,
245                 "ap0",
246                 "ap1",
247                 "cif",
248                 "flash",
249                 "vccio0",
250                 "vccio1",
251                 "lcdc0",
252                 "lcdc1",
253         },
254 };
255
256 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
257         .grf_offset = 0x380,
258         .supply_names = {
259                 "lcdc",         /* LCDC_VDD */
260                 "dvp",          /* DVPIO_VDD */
261                 "flash0",       /* FLASH0_VDD (emmc) */
262                 "flash1",       /* FLASH1_VDD (sdio1) */
263                 "wifi",         /* APIO3_VDD  (sdio0) */
264                 "bb",           /* APIO5_VDD */
265                 "audio",        /* APIO4_VDD */
266                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
267                 "gpio30",       /* APIO1_VDD */
268                 "gpio1830",     /* APIO2_VDD */
269         },
270         .init = rk3288_iodomain_init,
271 };
272
273 static const struct rockchip_iodomain_soc_data soc_data_rk3366 = {
274         .grf_offset = 0x900,
275         .supply_names = {
276                 "lcdc",         /* LCDC_IOVDD */
277                 "dvpts",        /* DVP_IOVDD */
278                 "flash",        /* FLASH_IOVDD (emmc) */
279                 "wifibt",       /* APIO1_IOVDD */
280                 NULL,
281                 "audio",        /* AUDIO_IODVDD */
282                 "sdcard",       /* SDMMC_IOVDD (sdmmc) */
283                 "tphdsor",      /* APIO2_IOVDD */
284         },
285         .init = rk3366_iodomain_init,
286 };
287
288 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
289         .grf_offset = 0x900,
290         .supply_names = {
291                 NULL,           /* reserved */
292                 "dvp",          /* DVPIO_VDD */
293                 "flash0",       /* FLASH0_VDD (emmc) */
294                 "wifi",         /* APIO2_VDD (sdio0) */
295                 NULL,
296                 "audio",        /* APIO3_VDD */
297                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
298                 "gpio30",       /* APIO1_VDD */
299                 "gpio1830",     /* APIO4_VDD (gpujtag) */
300         },
301         .init = rk3368_iodomain_init,
302 };
303
304 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
305         .grf_offset = 0x100,
306         .supply_names = {
307                 NULL,
308                 NULL,
309                 NULL,
310                 NULL,
311                 "pmu",          /*PMU IO domain*/
312                 "vop",          /*LCDC IO domain*/
313         },
314 };
315
316 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
317         .grf_offset = 0xe640,
318         .supply_names = {
319                 "bt656",                /* APIO2_VDD */
320                 "audio",                /* APIO5_VDD */
321                 "sdmmc",                /* SDMMC0_VDD */
322                 "gpio1830",             /* APIO4_VDD */
323         },
324 };
325
326 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
327         .grf_offset = 0x180,
328         .supply_names = {
329                 NULL,
330                 NULL,
331                 NULL,
332                 NULL,
333                 NULL,
334                 NULL,
335                 NULL,
336                 NULL,
337                 NULL,
338                 "pmu1830",              /* PMUIO2_VDD */
339         },
340         .init = rk3399_pmu_iodomain_init,
341 };
342
343 static const struct of_device_id rockchip_iodomain_match[] = {
344         {
345                 .compatible = "rockchip,rk3188-io-voltage-domain",
346                 .data = (void *)&soc_data_rk3188
347         },
348         {
349                 .compatible = "rockchip,rk3288-io-voltage-domain",
350                 .data = (void *)&soc_data_rk3288
351         },
352         {
353                 .compatible = "rockchip,rk3366-io-voltage-domain",
354                 .data = (void *)&soc_data_rk3366
355         },
356         {
357                 .compatible = "rockchip,rk3368-io-voltage-domain",
358                 .data = (void *)&soc_data_rk3368
359         },
360         {
361                 .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
362                 .data = (void *)&soc_data_rk3368_pmu
363         },
364         {
365                 .compatible = "rockchip,rk3399-io-voltage-domain",
366                 .data = (void *)&soc_data_rk3399
367         },
368         {
369                 .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
370                 .data = (void *)&soc_data_rk3399_pmu
371         },
372         { /* sentinel */ },
373 };
374 MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
375
376 static int rockchip_iodomain_probe(struct platform_device *pdev)
377 {
378         struct device_node *np = pdev->dev.of_node;
379         const struct of_device_id *match;
380         struct rockchip_iodomain *iod;
381         int i, ret = 0;
382
383         if (!np)
384                 return -ENODEV;
385
386         iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
387         if (!iod)
388                 return -ENOMEM;
389
390         iod->dev = &pdev->dev;
391         platform_set_drvdata(pdev, iod);
392
393         match = of_match_node(rockchip_iodomain_match, np);
394         iod->soc_data = (struct rockchip_iodomain_soc_data *)match->data;
395
396         iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
397         if (IS_ERR(iod->grf)) {
398                 dev_err(&pdev->dev, "couldn't find grf regmap\n");
399                 return PTR_ERR(iod->grf);
400         }
401
402         for (i = 0; i < MAX_SUPPLIES; i++) {
403                 const char *supply_name = iod->soc_data->supply_names[i];
404                 struct rockchip_iodomain_supply *supply = &iod->supplies[i];
405                 struct regulator *reg;
406                 int uV;
407
408                 if (!supply_name)
409                         continue;
410
411                 reg = devm_regulator_get_optional(iod->dev, supply_name);
412                 if (IS_ERR(reg)) {
413                         ret = PTR_ERR(reg);
414
415                         /* If a supply wasn't specified, that's OK */
416                         if (ret == -ENODEV)
417                                 continue;
418                         else if (ret != -EPROBE_DEFER)
419                                 dev_err(iod->dev, "couldn't get regulator %s\n",
420                                         supply_name);
421                         goto unreg_notify;
422                 }
423
424                 /* set initial correct value */
425                 uV = regulator_get_voltage(reg);
426
427                 /* must be a regulator we can get the voltage of */
428                 if (uV < 0) {
429                         dev_err(iod->dev, "Can't determine voltage: %s\n",
430                                 supply_name);
431                         goto unreg_notify;
432                 }
433
434                 if (uV > MAX_VOLTAGE_3_3) {
435                         dev_crit(iod->dev,
436                                  "%d uV is too high. May damage SoC!\n",
437                                  uV);
438                         ret = -EINVAL;
439                         goto unreg_notify;
440                 }
441
442                 /* setup our supply */
443                 supply->idx = i;
444                 supply->iod = iod;
445                 supply->reg = reg;
446                 supply->nb.notifier_call = rockchip_iodomain_notify;
447
448                 ret = rockchip_iodomain_write(supply, uV);
449                 if (ret) {
450                         supply->reg = NULL;
451                         goto unreg_notify;
452                 }
453
454                 /* register regulator notifier */
455                 ret = regulator_register_notifier(reg, &supply->nb);
456                 if (ret) {
457                         dev_err(&pdev->dev,
458                                 "regulator notifier request failed\n");
459                         supply->reg = NULL;
460                         goto unreg_notify;
461                 }
462         }
463
464         if (iod->soc_data->init)
465                 iod->soc_data->init(iod);
466
467         return 0;
468
469 unreg_notify:
470         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
471                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
472
473                 if (io_supply->reg)
474                         regulator_unregister_notifier(io_supply->reg,
475                                                       &io_supply->nb);
476         }
477
478         return ret;
479 }
480
481 static int rockchip_iodomain_remove(struct platform_device *pdev)
482 {
483         struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
484         int i;
485
486         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
487                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
488
489                 if (io_supply->reg)
490                         regulator_unregister_notifier(io_supply->reg,
491                                                       &io_supply->nb);
492         }
493
494         return 0;
495 }
496
497 static struct platform_driver rockchip_iodomain_driver = {
498         .probe   = rockchip_iodomain_probe,
499         .remove  = rockchip_iodomain_remove,
500         .driver  = {
501                 .name  = "rockchip-iodomain",
502                 .of_match_table = rockchip_iodomain_match,
503         },
504 };
505
506 module_platform_driver(rockchip_iodomain_driver);
507
508 MODULE_DESCRIPTION("Rockchip IO-domain driver");
509 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
510 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
511 MODULE_LICENSE("GPL v2");