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