dm: core: Require users of devres to include the header
[oweals/u-boot.git] / drivers / power / domain / mtk-power-domain.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018 MediaTek Inc.
4  * Author: Ryder Lee <ryder.lee@mediatek.com>
5  */
6
7 #include <clk.h>
8 #include <common.h>
9 #include <dm.h>
10 #include <power-domain-uclass.h>
11 #include <regmap.h>
12 #include <syscon.h>
13 #include <asm/io.h>
14 #include <asm/processor.h>
15 #include <linux/err.h>
16 #include <linux/iopoll.h>
17
18 #include <dt-bindings/power/mt7623-power.h>
19 #include <dt-bindings/power/mt7629-power.h>
20
21 #define SPM_EN                  (0xb16 << 16 | 0x1)
22 #define SPM_VDE_PWR_CON         0x0210
23 #define SPM_MFG_PWR_CON         0x0214
24 #define SPM_ISP_PWR_CON         0x0238
25 #define SPM_DIS_PWR_CON         0x023c
26 #define SPM_CONN_PWR_CON        0x0280
27 #define SPM_BDP_PWR_CON         0x029c
28 #define SPM_ETH_PWR_CON         0x02a0
29 #define SPM_HIF_PWR_CON         0x02a4
30 #define SPM_IFR_MSC_PWR_CON     0x02a8
31 #define SPM_ETHSYS_PWR_CON      0x2e0
32 #define SPM_HIF0_PWR_CON        0x2e4
33 #define SPM_HIF1_PWR_CON        0x2e8
34 #define SPM_PWR_STATUS          0x60c
35 #define SPM_PWR_STATUS_2ND      0x610
36
37 #define PWR_RST_B_BIT           BIT(0)
38 #define PWR_ISO_BIT             BIT(1)
39 #define PWR_ON_BIT              BIT(2)
40 #define PWR_ON_2ND_BIT          BIT(3)
41 #define PWR_CLK_DIS_BIT         BIT(4)
42
43 #define PWR_STATUS_CONN         BIT(1)
44 #define PWR_STATUS_DISP         BIT(3)
45 #define PWR_STATUS_MFG          BIT(4)
46 #define PWR_STATUS_ISP          BIT(5)
47 #define PWR_STATUS_VDEC         BIT(7)
48 #define PWR_STATUS_BDP          BIT(14)
49 #define PWR_STATUS_ETH          BIT(15)
50 #define PWR_STATUS_HIF          BIT(16)
51 #define PWR_STATUS_IFR_MSC      BIT(17)
52 #define PWR_STATUS_ETHSYS       BIT(24)
53 #define PWR_STATUS_HIF0         BIT(25)
54 #define PWR_STATUS_HIF1         BIT(26)
55
56 /* Infrasys configuration */
57 #define INFRA_TOPDCM_CTRL       0x10
58 #define INFRA_TOPAXI_PROT_EN    0x220
59 #define INFRA_TOPAXI_PROT_STA1  0x228
60
61 #define DCM_TOP_EN              BIT(0)
62
63 enum scp_domain_type {
64         SCPSYS_MT7622,
65         SCPSYS_MT7623,
66         SCPSYS_MT7629,
67 };
68
69 struct scp_domain;
70
71 struct scp_domain_data {
72         struct scp_domain *scpd;
73         u32 sta_mask;
74         int ctl_offs;
75         u32 sram_pdn_bits;
76         u32 sram_pdn_ack_bits;
77         u32 bus_prot_mask;
78 };
79
80 struct scp_domain {
81         void __iomem *base;
82         void __iomem *infracfg;
83         enum scp_domain_type type;
84         struct scp_domain_data *data;
85 };
86
87 static struct scp_domain_data scp_domain_mt7623[] = {
88         [MT7623_POWER_DOMAIN_CONN] = {
89                 .sta_mask = PWR_STATUS_CONN,
90                 .ctl_offs = SPM_CONN_PWR_CON,
91                 .bus_prot_mask = BIT(8) | BIT(2),
92         },
93         [MT7623_POWER_DOMAIN_DISP] = {
94                 .sta_mask = PWR_STATUS_DISP,
95                 .ctl_offs = SPM_DIS_PWR_CON,
96                 .sram_pdn_bits = GENMASK(11, 8),
97                 .bus_prot_mask = BIT(2),
98         },
99         [MT7623_POWER_DOMAIN_MFG] = {
100                 .sta_mask = PWR_STATUS_MFG,
101                 .ctl_offs = SPM_MFG_PWR_CON,
102                 .sram_pdn_bits = GENMASK(11, 8),
103                 .sram_pdn_ack_bits = GENMASK(12, 12),
104         },
105         [MT7623_POWER_DOMAIN_VDEC] = {
106                 .sta_mask = PWR_STATUS_VDEC,
107                 .ctl_offs = SPM_VDE_PWR_CON,
108                 .sram_pdn_bits = GENMASK(11, 8),
109                 .sram_pdn_ack_bits = GENMASK(12, 12),
110         },
111         [MT7623_POWER_DOMAIN_ISP] = {
112                 .sta_mask = PWR_STATUS_ISP,
113                 .ctl_offs = SPM_ISP_PWR_CON,
114                 .sram_pdn_bits = GENMASK(11, 8),
115                 .sram_pdn_ack_bits = GENMASK(13, 12),
116         },
117         [MT7623_POWER_DOMAIN_BDP] = {
118                 .sta_mask = PWR_STATUS_BDP,
119                 .ctl_offs = SPM_BDP_PWR_CON,
120                 .sram_pdn_bits = GENMASK(11, 8),
121         },
122         [MT7623_POWER_DOMAIN_ETH] = {
123                 .sta_mask = PWR_STATUS_ETH,
124                 .ctl_offs = SPM_ETH_PWR_CON,
125                 .sram_pdn_bits = GENMASK(11, 8),
126                 .sram_pdn_ack_bits = GENMASK(15, 12),
127         },
128         [MT7623_POWER_DOMAIN_HIF] = {
129                 .sta_mask = PWR_STATUS_HIF,
130                 .ctl_offs = SPM_HIF_PWR_CON,
131                 .sram_pdn_bits = GENMASK(11, 8),
132                 .sram_pdn_ack_bits = GENMASK(15, 12),
133         },
134         [MT7623_POWER_DOMAIN_IFR_MSC] = {
135                 .sta_mask = PWR_STATUS_IFR_MSC,
136                 .ctl_offs = SPM_IFR_MSC_PWR_CON,
137         },
138 };
139
140 static struct scp_domain_data scp_domain_mt7629[] = {
141         [MT7629_POWER_DOMAIN_ETHSYS] = {
142                 .sta_mask = PWR_STATUS_ETHSYS,
143                 .ctl_offs = SPM_ETHSYS_PWR_CON,
144                 .sram_pdn_bits = GENMASK(11, 8),
145                 .sram_pdn_ack_bits = GENMASK(15, 12),
146                 .bus_prot_mask = (BIT(3) | BIT(17)),
147         },
148         [MT7629_POWER_DOMAIN_HIF0] = {
149                 .sta_mask = PWR_STATUS_HIF0,
150                 .ctl_offs = SPM_HIF0_PWR_CON,
151                 .sram_pdn_bits = GENMASK(11, 8),
152                 .sram_pdn_ack_bits = GENMASK(15, 12),
153                 .bus_prot_mask = GENMASK(25, 24),
154         },
155         [MT7629_POWER_DOMAIN_HIF1] = {
156                 .sta_mask = PWR_STATUS_HIF1,
157                 .ctl_offs = SPM_HIF1_PWR_CON,
158                 .sram_pdn_bits = GENMASK(11, 8),
159                 .sram_pdn_ack_bits = GENMASK(15, 12),
160                 .bus_prot_mask = GENMASK(28, 26),
161         },
162 };
163
164 /**
165  * This function enables the bus protection bits for disabled power
166  * domains so that the system does not hang when some unit accesses the
167  * bus while in power down.
168  */
169 static int mtk_infracfg_set_bus_protection(void __iomem *infracfg,
170                                            u32 mask)
171 {
172         u32 val;
173
174         clrsetbits_le32(infracfg + INFRA_TOPAXI_PROT_EN, mask, mask);
175
176         return readl_poll_timeout(infracfg + INFRA_TOPAXI_PROT_STA1, val,
177                                   (val & mask) == mask, 100);
178 }
179
180 static int mtk_infracfg_clear_bus_protection(void __iomem *infracfg,
181                                              u32 mask)
182 {
183         u32 val;
184
185         clrbits_le32(infracfg + INFRA_TOPAXI_PROT_EN, mask);
186
187         return readl_poll_timeout(infracfg + INFRA_TOPAXI_PROT_STA1, val,
188                                   !(val & mask), 100);
189 }
190
191 static int scpsys_domain_is_on(struct scp_domain_data *data)
192 {
193         struct scp_domain *scpd = data->scpd;
194         u32 sta = readl(scpd->base + SPM_PWR_STATUS) &
195                         data->sta_mask;
196         u32 sta2 = readl(scpd->base + SPM_PWR_STATUS_2ND) &
197                          data->sta_mask;
198
199         /*
200          * A domain is on when both status bits are set. If only one is set
201          * return an error. This happens while powering up a domain
202          */
203         if (sta && sta2)
204                 return true;
205         if (!sta && !sta2)
206                 return false;
207
208         return -EINVAL;
209 }
210
211 static int scpsys_power_on(struct power_domain *power_domain)
212 {
213         struct scp_domain *scpd = dev_get_priv(power_domain->dev);
214         struct scp_domain_data *data = &scpd->data[power_domain->id];
215         void __iomem *ctl_addr = scpd->base + data->ctl_offs;
216         u32 pdn_ack = data->sram_pdn_ack_bits;
217         u32 val;
218         int ret, tmp;
219
220         writel(SPM_EN, scpd->base);
221
222         val = readl(ctl_addr);
223         val |= PWR_ON_BIT;
224         writel(val, ctl_addr);
225
226         val |= PWR_ON_2ND_BIT;
227         writel(val, ctl_addr);
228
229         ret = readx_poll_timeout(scpsys_domain_is_on, data, tmp, tmp > 0,
230                                  100);
231         if (ret < 0)
232                 return ret;
233
234         val &= ~PWR_CLK_DIS_BIT;
235         writel(val, ctl_addr);
236
237         val &= ~PWR_ISO_BIT;
238         writel(val, ctl_addr);
239
240         val |= PWR_RST_B_BIT;
241         writel(val, ctl_addr);
242
243         val &= ~data->sram_pdn_bits;
244         writel(val, ctl_addr);
245
246         ret = readl_poll_timeout(ctl_addr, tmp, !(tmp & pdn_ack), 100);
247         if (ret < 0)
248                 return ret;
249
250         if (data->bus_prot_mask) {
251                 ret = mtk_infracfg_clear_bus_protection(scpd->infracfg,
252                                                         data->bus_prot_mask);
253                 if (ret)
254                         return ret;
255         }
256
257         return 0;
258 }
259
260 static int scpsys_power_off(struct power_domain *power_domain)
261 {
262         struct scp_domain *scpd = dev_get_priv(power_domain->dev);
263         struct scp_domain_data *data = &scpd->data[power_domain->id];
264         void __iomem *ctl_addr = scpd->base + data->ctl_offs;
265         u32 pdn_ack = data->sram_pdn_ack_bits;
266         u32 val;
267         int ret, tmp;
268
269         if (data->bus_prot_mask) {
270                 ret = mtk_infracfg_set_bus_protection(scpd->infracfg,
271                                                       data->bus_prot_mask);
272                 if (ret)
273                         return ret;
274         }
275
276         val = readl(ctl_addr);
277         val |= data->sram_pdn_bits;
278         writel(val, ctl_addr);
279
280         ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
281                                  100);
282         if (ret < 0)
283                 return ret;
284
285         val |= PWR_ISO_BIT;
286         writel(val, ctl_addr);
287
288         val &= ~PWR_RST_B_BIT;
289         writel(val, ctl_addr);
290
291         val |= PWR_CLK_DIS_BIT;
292         writel(val, ctl_addr);
293
294         val &= ~PWR_ON_BIT;
295         writel(val, ctl_addr);
296
297         val &= ~PWR_ON_2ND_BIT;
298         writel(val, ctl_addr);
299
300         ret = readx_poll_timeout(scpsys_domain_is_on, data, tmp, !tmp, 100);
301         if (ret < 0)
302                 return ret;
303
304         return 0;
305 }
306
307 static int scpsys_power_request(struct power_domain *power_domain)
308 {
309         struct scp_domain *scpd = dev_get_priv(power_domain->dev);
310         struct scp_domain_data *data;
311
312         data = &scpd->data[power_domain->id];
313         data->scpd = scpd;
314
315         return 0;
316 }
317
318 static int scpsys_power_free(struct power_domain *power_domain)
319 {
320         return 0;
321 }
322
323 static int mtk_power_domain_hook(struct udevice *dev)
324 {
325         struct scp_domain *scpd = dev_get_priv(dev);
326
327         scpd->type = (enum scp_domain_type)dev_get_driver_data(dev);
328
329         switch (scpd->type) {
330         case SCPSYS_MT7623:
331                 scpd->data = scp_domain_mt7623;
332                 break;
333         case SCPSYS_MT7622:
334         case SCPSYS_MT7629:
335                 scpd->data = scp_domain_mt7629;
336                 break;
337         default:
338                 return -EINVAL;
339         }
340
341         return 0;
342 }
343
344 static int mtk_power_domain_probe(struct udevice *dev)
345 {
346         struct ofnode_phandle_args args;
347         struct scp_domain *scpd = dev_get_priv(dev);
348         struct regmap *regmap;
349         struct clk_bulk bulk;
350         int err;
351
352         scpd->base = dev_read_addr_ptr(dev);
353         if (!scpd->base)
354                 return -ENOENT;
355
356         err = mtk_power_domain_hook(dev);
357         if (err)
358                 return err;
359
360         /* get corresponding syscon phandle */
361         err = dev_read_phandle_with_args(dev, "infracfg", NULL, 0, 0, &args);
362         if (err)
363                 return err;
364
365         regmap = syscon_node_to_regmap(args.node);
366         if (IS_ERR(regmap))
367                 return PTR_ERR(regmap);
368
369         scpd->infracfg = regmap_get_range(regmap, 0);
370         if (!scpd->infracfg)
371                 return -ENOENT;
372
373         /* enable Infra DCM */
374         setbits_le32(scpd->infracfg + INFRA_TOPDCM_CTRL, DCM_TOP_EN);
375
376         err = clk_get_bulk(dev, &bulk);
377         if (err)
378                 return err;
379
380         return clk_enable_bulk(&bulk);
381 }
382
383 static const struct udevice_id mtk_power_domain_ids[] = {
384         {
385                 .compatible = "mediatek,mt7622-scpsys",
386                 .data = SCPSYS_MT7622,
387         },
388         {
389                 .compatible = "mediatek,mt7623-scpsys",
390                 .data = SCPSYS_MT7623,
391         },
392         {
393                 .compatible = "mediatek,mt7629-scpsys",
394                 .data = SCPSYS_MT7629,
395         },
396         { /* sentinel */ }
397 };
398
399 struct power_domain_ops mtk_power_domain_ops = {
400         .rfree = scpsys_power_free,
401         .off = scpsys_power_off,
402         .on = scpsys_power_on,
403         .request = scpsys_power_request,
404 };
405
406 U_BOOT_DRIVER(mtk_power_domain) = {
407         .name = "mtk_power_domain",
408         .id = UCLASS_POWER_DOMAIN,
409         .ops = &mtk_power_domain_ops,
410         .probe = mtk_power_domain_probe,
411         .of_match = mtk_power_domain_ids,
412         .priv_auto_alloc_size = sizeof(struct scp_domain),
413 };