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