blob: 5346f33dd70b612eac93b385ab07fb8a954f702c [file] [log] [blame]
Sascha Hauerc84e3582015-06-24 08:17:04 +02001/*
2 * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#include <linux/clk.h>
Paul Gortmakere50be5c2015-09-04 19:33:54 -040014#include <linux/init.h>
James Liao6078c652016-10-20 16:56:35 +080015#include <linux/io.h>
16#include <linux/mfd/syscon.h>
Sascha Hauerc84e3582015-06-24 08:17:04 +020017#include <linux/of_device.h>
18#include <linux/platform_device.h>
19#include <linux/pm_domain.h>
Sascha Hauer4688f382015-11-30 11:41:40 +010020#include <linux/regulator/consumer.h>
James Liao6078c652016-10-20 16:56:35 +080021#include <linux/soc/mediatek/infracfg.h>
22
Shunli Wang112ef182016-10-20 16:56:38 +080023#include <dt-bindings/power/mt2701-power.h>
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +080024#include <dt-bindings/power/mt2712-power.h>
Mars Cheng36c310f2017-04-08 09:20:34 +080025#include <dt-bindings/power/mt6797-power.h>
Sean Wang52510ee2017-08-07 15:24:37 +080026#include <dt-bindings/power/mt7622-power.h>
Sascha Hauerc84e3582015-06-24 08:17:04 +020027#include <dt-bindings/power/mt8173-power.h>
28
29#define SPM_VDE_PWR_CON 0x0210
30#define SPM_MFG_PWR_CON 0x0214
31#define SPM_VEN_PWR_CON 0x0230
32#define SPM_ISP_PWR_CON 0x0238
33#define SPM_DIS_PWR_CON 0x023c
Shunli Wang112ef182016-10-20 16:56:38 +080034#define SPM_CONN_PWR_CON 0x0280
Sascha Hauerc84e3582015-06-24 08:17:04 +020035#define SPM_VEN2_PWR_CON 0x0298
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +080036#define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */
Shunli Wang112ef182016-10-20 16:56:38 +080037#define SPM_BDP_PWR_CON 0x029c /* MT2701 */
38#define SPM_ETH_PWR_CON 0x02a0
39#define SPM_HIF_PWR_CON 0x02a4
40#define SPM_IFR_MSC_PWR_CON 0x02a8
Sascha Hauerc84e3582015-06-24 08:17:04 +020041#define SPM_MFG_2D_PWR_CON 0x02c0
42#define SPM_MFG_ASYNC_PWR_CON 0x02c4
43#define SPM_USB_PWR_CON 0x02cc
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +080044#define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */
Sean Wang52510ee2017-08-07 15:24:37 +080045#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */
46#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */
47#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */
48#define SPM_WB_PWR_CON 0x02ec /* MT7622 */
49
Sascha Hauerc84e3582015-06-24 08:17:04 +020050#define SPM_PWR_STATUS 0x060c
51#define SPM_PWR_STATUS_2ND 0x0610
52
53#define PWR_RST_B_BIT BIT(0)
54#define PWR_ISO_BIT BIT(1)
55#define PWR_ON_BIT BIT(2)
56#define PWR_ON_2ND_BIT BIT(3)
57#define PWR_CLK_DIS_BIT BIT(4)
58
Shunli Wang112ef182016-10-20 16:56:38 +080059#define PWR_STATUS_CONN BIT(1)
Sascha Hauerc84e3582015-06-24 08:17:04 +020060#define PWR_STATUS_DISP BIT(3)
61#define PWR_STATUS_MFG BIT(4)
62#define PWR_STATUS_ISP BIT(5)
63#define PWR_STATUS_VDEC BIT(7)
Shunli Wang112ef182016-10-20 16:56:38 +080064#define PWR_STATUS_BDP BIT(14)
65#define PWR_STATUS_ETH BIT(15)
66#define PWR_STATUS_HIF BIT(16)
67#define PWR_STATUS_IFR_MSC BIT(17)
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +080068#define PWR_STATUS_USB2 BIT(19) /* MT2712 */
Sascha Hauerc84e3582015-06-24 08:17:04 +020069#define PWR_STATUS_VENC_LT BIT(20)
70#define PWR_STATUS_VENC BIT(21)
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +080071#define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */
72#define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */
73#define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */
74#define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */
Sean Wang52510ee2017-08-07 15:24:37 +080075#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */
76#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */
77#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */
78#define PWR_STATUS_WB BIT(27) /* MT7622 */
Sascha Hauerc84e3582015-06-24 08:17:04 +020079
80enum clk_id {
James Liao6078c652016-10-20 16:56:35 +080081 CLK_NONE,
82 CLK_MM,
83 CLK_MFG,
84 CLK_VENC,
85 CLK_VENC_LT,
Shunli Wang112ef182016-10-20 16:56:38 +080086 CLK_ETHIF,
Mars Chenga3acbbf2017-04-08 09:20:32 +080087 CLK_VDEC,
Sean Wang52510ee2017-08-07 15:24:37 +080088 CLK_HIFSEL,
weiyi.lu@mediatek.comd1fb29f2017-11-28 15:28:19 +080089 CLK_JPGDEC,
90 CLK_AUDIO,
James Liao6078c652016-10-20 16:56:35 +080091 CLK_MAX,
92};
93
94static const char * const clk_names[] = {
95 NULL,
96 "mm",
97 "mfg",
98 "venc",
99 "venc_lt",
Shunli Wang112ef182016-10-20 16:56:38 +0800100 "ethif",
Mars Chenga3acbbf2017-04-08 09:20:32 +0800101 "vdec",
Sean Wang52510ee2017-08-07 15:24:37 +0800102 "hif_sel",
weiyi.lu@mediatek.comd1fb29f2017-11-28 15:28:19 +0800103 "jpgdec",
104 "audio",
James Liao6078c652016-10-20 16:56:35 +0800105 NULL,
Sascha Hauerc84e3582015-06-24 08:17:04 +0200106};
107
weiyi.lu@mediatek.comd1fb29f2017-11-28 15:28:19 +0800108#define MAX_CLKS 3
James Liao41b3e0f2015-10-07 17:14:40 +0800109
Sascha Hauerc84e3582015-06-24 08:17:04 +0200110struct scp_domain_data {
111 const char *name;
112 u32 sta_mask;
113 int ctl_offs;
114 u32 sram_pdn_bits;
115 u32 sram_pdn_ack_bits;
116 u32 bus_prot_mask;
James Liao41b3e0f2015-10-07 17:14:40 +0800117 enum clk_id clk_id[MAX_CLKS];
Eddie Huang47e90152015-08-26 15:14:41 +0800118 bool active_wakeup;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200119};
120
Sascha Hauerc84e3582015-06-24 08:17:04 +0200121struct scp;
122
123struct scp_domain {
124 struct generic_pm_domain genpd;
125 struct scp *scp;
James Liao41b3e0f2015-10-07 17:14:40 +0800126 struct clk *clk[MAX_CLKS];
Matthias Bruggerbe295232015-12-30 09:30:40 +0100127 const struct scp_domain_data *data;
Sascha Hauer4688f382015-11-30 11:41:40 +0100128 struct regulator *supply;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200129};
130
Mars Chengf1be4c42017-04-08 09:20:31 +0800131struct scp_ctrl_reg {
132 int pwr_sta_offs;
133 int pwr_sta2nd_offs;
134};
135
Sascha Hauerc84e3582015-06-24 08:17:04 +0200136struct scp {
James Liao6078c652016-10-20 16:56:35 +0800137 struct scp_domain *domains;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200138 struct genpd_onecell_data pd_data;
139 struct device *dev;
140 void __iomem *base;
141 struct regmap *infracfg;
Mars Chengf1be4c42017-04-08 09:20:31 +0800142 struct scp_ctrl_reg ctrl_reg;
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800143 bool bus_prot_reg_update;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200144};
145
Sean Wang53fddb12017-08-07 15:24:35 +0800146struct scp_subdomain {
147 int origin;
148 int subdomain;
149};
150
151struct scp_soc_data {
152 const struct scp_domain_data *domains;
153 int num_domains;
154 const struct scp_subdomain *subdomains;
155 int num_subdomains;
156 const struct scp_ctrl_reg regs;
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800157 bool bus_prot_reg_update;
Sean Wang53fddb12017-08-07 15:24:35 +0800158};
159
Sascha Hauerc84e3582015-06-24 08:17:04 +0200160static int scpsys_domain_is_on(struct scp_domain *scpd)
161{
162 struct scp *scp = scpd->scp;
163
Mars Chengf1be4c42017-04-08 09:20:31 +0800164 u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
165 scpd->data->sta_mask;
166 u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
167 scpd->data->sta_mask;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200168
169 /*
170 * A domain is on when both status bits are set. If only one is set
171 * return an error. This happens while powering up a domain
172 */
173
174 if (status && status2)
175 return true;
176 if (!status && !status2)
177 return false;
178
179 return -EINVAL;
180}
181
182static int scpsys_power_on(struct generic_pm_domain *genpd)
183{
184 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
185 struct scp *scp = scpd->scp;
186 unsigned long timeout;
187 bool expired;
Matthias Bruggerbe295232015-12-30 09:30:40 +0100188 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
189 u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200190 u32 val;
191 int ret;
James Liao41b3e0f2015-10-07 17:14:40 +0800192 int i;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200193
Sascha Hauer4688f382015-11-30 11:41:40 +0100194 if (scpd->supply) {
195 ret = regulator_enable(scpd->supply);
196 if (ret)
197 return ret;
198 }
199
James Liao41b3e0f2015-10-07 17:14:40 +0800200 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
201 ret = clk_prepare_enable(scpd->clk[i]);
202 if (ret) {
203 for (--i; i >= 0; i--)
204 clk_disable_unprepare(scpd->clk[i]);
205
Sascha Hauerc84e3582015-06-24 08:17:04 +0200206 goto err_clk;
James Liao41b3e0f2015-10-07 17:14:40 +0800207 }
Sascha Hauerc84e3582015-06-24 08:17:04 +0200208 }
209
210 val = readl(ctl_addr);
211 val |= PWR_ON_BIT;
212 writel(val, ctl_addr);
213 val |= PWR_ON_2ND_BIT;
214 writel(val, ctl_addr);
215
216 /* wait until PWR_ACK = 1 */
217 timeout = jiffies + HZ;
218 expired = false;
219 while (1) {
220 ret = scpsys_domain_is_on(scpd);
221 if (ret > 0)
222 break;
223
224 if (expired) {
225 ret = -ETIMEDOUT;
226 goto err_pwr_ack;
227 }
228
229 cpu_relax();
230
231 if (time_after(jiffies, timeout))
232 expired = true;
233 }
234
235 val &= ~PWR_CLK_DIS_BIT;
236 writel(val, ctl_addr);
237
238 val &= ~PWR_ISO_BIT;
239 writel(val, ctl_addr);
240
241 val |= PWR_RST_B_BIT;
242 writel(val, ctl_addr);
243
Matthias Bruggerbe295232015-12-30 09:30:40 +0100244 val &= ~scpd->data->sram_pdn_bits;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200245 writel(val, ctl_addr);
246
247 /* wait until SRAM_PDN_ACK all 0 */
248 timeout = jiffies + HZ;
249 expired = false;
250 while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
251
252 if (expired) {
253 ret = -ETIMEDOUT;
254 goto err_pwr_ack;
255 }
256
257 cpu_relax();
258
259 if (time_after(jiffies, timeout))
260 expired = true;
261 }
262
Matthias Bruggerbe295232015-12-30 09:30:40 +0100263 if (scpd->data->bus_prot_mask) {
Sascha Hauerc84e3582015-06-24 08:17:04 +0200264 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800265 scpd->data->bus_prot_mask,
266 scp->bus_prot_reg_update);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200267 if (ret)
268 goto err_pwr_ack;
269 }
270
271 return 0;
272
273err_pwr_ack:
James Liao41b3e0f2015-10-07 17:14:40 +0800274 for (i = MAX_CLKS - 1; i >= 0; i--) {
275 if (scpd->clk[i])
276 clk_disable_unprepare(scpd->clk[i]);
277 }
Sascha Hauerc84e3582015-06-24 08:17:04 +0200278err_clk:
Sascha Hauer4688f382015-11-30 11:41:40 +0100279 if (scpd->supply)
280 regulator_disable(scpd->supply);
281
Sascha Hauerc84e3582015-06-24 08:17:04 +0200282 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
283
284 return ret;
285}
286
287static int scpsys_power_off(struct generic_pm_domain *genpd)
288{
289 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
290 struct scp *scp = scpd->scp;
291 unsigned long timeout;
292 bool expired;
Matthias Bruggerbe295232015-12-30 09:30:40 +0100293 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
294 u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200295 u32 val;
296 int ret;
James Liao41b3e0f2015-10-07 17:14:40 +0800297 int i;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200298
Matthias Bruggerbe295232015-12-30 09:30:40 +0100299 if (scpd->data->bus_prot_mask) {
Sascha Hauerc84e3582015-06-24 08:17:04 +0200300 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800301 scpd->data->bus_prot_mask,
302 scp->bus_prot_reg_update);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200303 if (ret)
304 goto out;
305 }
306
307 val = readl(ctl_addr);
Matthias Bruggerbe295232015-12-30 09:30:40 +0100308 val |= scpd->data->sram_pdn_bits;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200309 writel(val, ctl_addr);
310
311 /* wait until SRAM_PDN_ACK all 1 */
312 timeout = jiffies + HZ;
313 expired = false;
314 while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
315 if (expired) {
316 ret = -ETIMEDOUT;
317 goto out;
318 }
319
320 cpu_relax();
321
322 if (time_after(jiffies, timeout))
323 expired = true;
324 }
325
326 val |= PWR_ISO_BIT;
327 writel(val, ctl_addr);
328
329 val &= ~PWR_RST_B_BIT;
330 writel(val, ctl_addr);
331
332 val |= PWR_CLK_DIS_BIT;
333 writel(val, ctl_addr);
334
335 val &= ~PWR_ON_BIT;
336 writel(val, ctl_addr);
337
338 val &= ~PWR_ON_2ND_BIT;
339 writel(val, ctl_addr);
340
341 /* wait until PWR_ACK = 0 */
342 timeout = jiffies + HZ;
343 expired = false;
344 while (1) {
345 ret = scpsys_domain_is_on(scpd);
346 if (ret == 0)
347 break;
348
349 if (expired) {
350 ret = -ETIMEDOUT;
351 goto out;
352 }
353
354 cpu_relax();
355
356 if (time_after(jiffies, timeout))
357 expired = true;
358 }
359
James Liao41b3e0f2015-10-07 17:14:40 +0800360 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
361 clk_disable_unprepare(scpd->clk[i]);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200362
Sascha Hauer4688f382015-11-30 11:41:40 +0100363 if (scpd->supply)
364 regulator_disable(scpd->supply);
365
Sascha Hauerc84e3582015-06-24 08:17:04 +0200366 return 0;
367
368out:
369 dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
370
371 return ret;
372}
373
James Liao6078c652016-10-20 16:56:35 +0800374static void init_clks(struct platform_device *pdev, struct clk **clk)
375{
376 int i;
377
378 for (i = CLK_NONE + 1; i < CLK_MAX; i++)
379 clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
380}
381
382static struct scp *init_scp(struct platform_device *pdev,
Mars Chengf1be4c42017-04-08 09:20:31 +0800383 const struct scp_domain_data *scp_domain_data, int num,
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800384 const struct scp_ctrl_reg *scp_ctrl_reg,
385 bool bus_prot_reg_update)
Sascha Hauerc84e3582015-06-24 08:17:04 +0200386{
387 struct genpd_onecell_data *pd_data;
388 struct resource *res;
James Liao6078c652016-10-20 16:56:35 +0800389 int i, j;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200390 struct scp *scp;
James Liao6078c652016-10-20 16:56:35 +0800391 struct clk *clk[CLK_MAX];
Sascha Hauerc84e3582015-06-24 08:17:04 +0200392
393 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
394 if (!scp)
James Liao6078c652016-10-20 16:56:35 +0800395 return ERR_PTR(-ENOMEM);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200396
Mars Chengf1be4c42017-04-08 09:20:31 +0800397 scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
398 scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
399
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800400 scp->bus_prot_reg_update = bus_prot_reg_update;
401
Sascha Hauerc84e3582015-06-24 08:17:04 +0200402 scp->dev = &pdev->dev;
403
404 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
405 scp->base = devm_ioremap_resource(&pdev->dev, res);
406 if (IS_ERR(scp->base))
James Liao6078c652016-10-20 16:56:35 +0800407 return ERR_CAST(scp->base);
408
409 scp->domains = devm_kzalloc(&pdev->dev,
410 sizeof(*scp->domains) * num, GFP_KERNEL);
411 if (!scp->domains)
412 return ERR_PTR(-ENOMEM);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200413
414 pd_data = &scp->pd_data;
415
416 pd_data->domains = devm_kzalloc(&pdev->dev,
James Liao6078c652016-10-20 16:56:35 +0800417 sizeof(*pd_data->domains) * num, GFP_KERNEL);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200418 if (!pd_data->domains)
James Liao6078c652016-10-20 16:56:35 +0800419 return ERR_PTR(-ENOMEM);
James Liao41b3e0f2015-10-07 17:14:40 +0800420
Sascha Hauerc84e3582015-06-24 08:17:04 +0200421 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
422 "infracfg");
423 if (IS_ERR(scp->infracfg)) {
424 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
425 PTR_ERR(scp->infracfg));
James Liao6078c652016-10-20 16:56:35 +0800426 return ERR_CAST(scp->infracfg);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200427 }
428
James Liao6078c652016-10-20 16:56:35 +0800429 for (i = 0; i < num; i++) {
Sascha Hauer4688f382015-11-30 11:41:40 +0100430 struct scp_domain *scpd = &scp->domains[i];
431 const struct scp_domain_data *data = &scp_domain_data[i];
432
433 scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
434 if (IS_ERR(scpd->supply)) {
435 if (PTR_ERR(scpd->supply) == -ENODEV)
436 scpd->supply = NULL;
437 else
James Liao6078c652016-10-20 16:56:35 +0800438 return ERR_CAST(scpd->supply);
Sascha Hauer4688f382015-11-30 11:41:40 +0100439 }
440 }
441
James Liao6078c652016-10-20 16:56:35 +0800442 pd_data->num_domains = num;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200443
James Liao6078c652016-10-20 16:56:35 +0800444 init_clks(pdev, clk);
445
446 for (i = 0; i < num; i++) {
Sascha Hauerc84e3582015-06-24 08:17:04 +0200447 struct scp_domain *scpd = &scp->domains[i];
448 struct generic_pm_domain *genpd = &scpd->genpd;
449 const struct scp_domain_data *data = &scp_domain_data[i];
450
451 pd_data->domains[i] = genpd;
452 scpd->scp = scp;
453
Matthias Bruggerbe295232015-12-30 09:30:40 +0100454 scpd->data = data;
James Liao6078c652016-10-20 16:56:35 +0800455
456 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
457 struct clk *c = clk[data->clk_id[j]];
458
459 if (IS_ERR(c)) {
460 dev_err(&pdev->dev, "%s: clk unavailable\n",
461 data->name);
462 return ERR_CAST(c);
463 }
464
465 scpd->clk[j] = c;
466 }
Sascha Hauerc84e3582015-06-24 08:17:04 +0200467
468 genpd->name = data->name;
469 genpd->power_off = scpsys_power_off;
470 genpd->power_on = scpsys_power_on;
Geert Uytterhoeven7534d182017-11-07 13:48:13 +0100471 if (scpd->data->active_wakeup)
472 genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
James Liao6078c652016-10-20 16:56:35 +0800473 }
474
475 return scp;
476}
477
478static void mtk_register_power_domains(struct platform_device *pdev,
479 struct scp *scp, int num)
480{
481 struct genpd_onecell_data *pd_data;
482 int i, ret;
483
484 for (i = 0; i < num; i++) {
485 struct scp_domain *scpd = &scp->domains[i];
486 struct generic_pm_domain *genpd = &scpd->genpd;
Sascha Hauerc84e3582015-06-24 08:17:04 +0200487
488 /*
James Liaod9c9f3b2016-04-12 16:34:30 +0800489 * Initially turn on all domains to make the domains usable
490 * with !CONFIG_PM and to get the hardware in sync with the
491 * software. The unused domains will be switched off during
492 * late_init time.
Sascha Hauerc84e3582015-06-24 08:17:04 +0200493 */
James Liaod9c9f3b2016-04-12 16:34:30 +0800494 genpd->power_on(genpd);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200495
James Liaod9c9f3b2016-04-12 16:34:30 +0800496 pm_genpd_init(genpd, NULL, false);
Sascha Hauerc84e3582015-06-24 08:17:04 +0200497 }
498
499 /*
500 * We are not allowed to fail here since there is no way to unregister
501 * a power domain. Once registered above we have to keep the domains
502 * valid.
503 */
504
James Liao6078c652016-10-20 16:56:35 +0800505 pd_data = &scp->pd_data;
506
507 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
508 if (ret)
509 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
510}
511
512/*
Shunli Wang112ef182016-10-20 16:56:38 +0800513 * MT2701 power domain support
514 */
515
516static const struct scp_domain_data scp_domain_data_mt2701[] = {
517 [MT2701_POWER_DOMAIN_CONN] = {
518 .name = "conn",
519 .sta_mask = PWR_STATUS_CONN,
520 .ctl_offs = SPM_CONN_PWR_CON,
Sean Wangc59c9c82018-02-07 18:22:49 +0800521 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
522 MT2701_TOP_AXI_PROT_EN_CONN_S,
Shunli Wang112ef182016-10-20 16:56:38 +0800523 .clk_id = {CLK_NONE},
524 .active_wakeup = true,
525 },
526 [MT2701_POWER_DOMAIN_DISP] = {
527 .name = "disp",
528 .sta_mask = PWR_STATUS_DISP,
529 .ctl_offs = SPM_DIS_PWR_CON,
530 .sram_pdn_bits = GENMASK(11, 8),
531 .clk_id = {CLK_MM},
Sean Wangc59c9c82018-02-07 18:22:49 +0800532 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
Shunli Wang112ef182016-10-20 16:56:38 +0800533 .active_wakeup = true,
534 },
535 [MT2701_POWER_DOMAIN_MFG] = {
536 .name = "mfg",
537 .sta_mask = PWR_STATUS_MFG,
538 .ctl_offs = SPM_MFG_PWR_CON,
539 .sram_pdn_bits = GENMASK(11, 8),
540 .sram_pdn_ack_bits = GENMASK(12, 12),
541 .clk_id = {CLK_MFG},
542 .active_wakeup = true,
543 },
544 [MT2701_POWER_DOMAIN_VDEC] = {
545 .name = "vdec",
546 .sta_mask = PWR_STATUS_VDEC,
547 .ctl_offs = SPM_VDE_PWR_CON,
548 .sram_pdn_bits = GENMASK(11, 8),
549 .sram_pdn_ack_bits = GENMASK(12, 12),
550 .clk_id = {CLK_MM},
551 .active_wakeup = true,
552 },
553 [MT2701_POWER_DOMAIN_ISP] = {
554 .name = "isp",
555 .sta_mask = PWR_STATUS_ISP,
556 .ctl_offs = SPM_ISP_PWR_CON,
557 .sram_pdn_bits = GENMASK(11, 8),
558 .sram_pdn_ack_bits = GENMASK(13, 12),
559 .clk_id = {CLK_MM},
560 .active_wakeup = true,
561 },
562 [MT2701_POWER_DOMAIN_BDP] = {
563 .name = "bdp",
564 .sta_mask = PWR_STATUS_BDP,
565 .ctl_offs = SPM_BDP_PWR_CON,
566 .sram_pdn_bits = GENMASK(11, 8),
567 .clk_id = {CLK_NONE},
568 .active_wakeup = true,
569 },
570 [MT2701_POWER_DOMAIN_ETH] = {
571 .name = "eth",
572 .sta_mask = PWR_STATUS_ETH,
573 .ctl_offs = SPM_ETH_PWR_CON,
574 .sram_pdn_bits = GENMASK(11, 8),
575 .sram_pdn_ack_bits = GENMASK(15, 12),
576 .clk_id = {CLK_ETHIF},
577 .active_wakeup = true,
578 },
579 [MT2701_POWER_DOMAIN_HIF] = {
580 .name = "hif",
581 .sta_mask = PWR_STATUS_HIF,
582 .ctl_offs = SPM_HIF_PWR_CON,
583 .sram_pdn_bits = GENMASK(11, 8),
584 .sram_pdn_ack_bits = GENMASK(15, 12),
585 .clk_id = {CLK_ETHIF},
586 .active_wakeup = true,
587 },
588 [MT2701_POWER_DOMAIN_IFR_MSC] = {
589 .name = "ifr_msc",
590 .sta_mask = PWR_STATUS_IFR_MSC,
591 .ctl_offs = SPM_IFR_MSC_PWR_CON,
592 .clk_id = {CLK_NONE},
593 .active_wakeup = true,
594 },
595};
596
Shunli Wang112ef182016-10-20 16:56:38 +0800597/*
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +0800598 * MT2712 power domain support
599 */
600static const struct scp_domain_data scp_domain_data_mt2712[] = {
601 [MT2712_POWER_DOMAIN_MM] = {
602 .name = "mm",
603 .sta_mask = PWR_STATUS_DISP,
604 .ctl_offs = SPM_DIS_PWR_CON,
605 .sram_pdn_bits = GENMASK(8, 8),
606 .sram_pdn_ack_bits = GENMASK(12, 12),
607 .clk_id = {CLK_MM},
608 .active_wakeup = true,
609 },
610 [MT2712_POWER_DOMAIN_VDEC] = {
611 .name = "vdec",
612 .sta_mask = PWR_STATUS_VDEC,
613 .ctl_offs = SPM_VDE_PWR_CON,
614 .sram_pdn_bits = GENMASK(8, 8),
615 .sram_pdn_ack_bits = GENMASK(12, 12),
616 .clk_id = {CLK_MM, CLK_VDEC},
617 .active_wakeup = true,
618 },
619 [MT2712_POWER_DOMAIN_VENC] = {
620 .name = "venc",
621 .sta_mask = PWR_STATUS_VENC,
622 .ctl_offs = SPM_VEN_PWR_CON,
623 .sram_pdn_bits = GENMASK(11, 8),
624 .sram_pdn_ack_bits = GENMASK(15, 12),
625 .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
626 .active_wakeup = true,
627 },
628 [MT2712_POWER_DOMAIN_ISP] = {
629 .name = "isp",
630 .sta_mask = PWR_STATUS_ISP,
631 .ctl_offs = SPM_ISP_PWR_CON,
632 .sram_pdn_bits = GENMASK(11, 8),
633 .sram_pdn_ack_bits = GENMASK(13, 12),
634 .clk_id = {CLK_MM},
635 .active_wakeup = true,
636 },
637 [MT2712_POWER_DOMAIN_AUDIO] = {
638 .name = "audio",
639 .sta_mask = PWR_STATUS_AUDIO,
640 .ctl_offs = SPM_AUDIO_PWR_CON,
641 .sram_pdn_bits = GENMASK(11, 8),
642 .sram_pdn_ack_bits = GENMASK(15, 12),
643 .clk_id = {CLK_AUDIO},
644 .active_wakeup = true,
645 },
646 [MT2712_POWER_DOMAIN_USB] = {
647 .name = "usb",
648 .sta_mask = PWR_STATUS_USB,
649 .ctl_offs = SPM_USB_PWR_CON,
650 .sram_pdn_bits = GENMASK(10, 8),
651 .sram_pdn_ack_bits = GENMASK(14, 12),
652 .clk_id = {CLK_NONE},
653 .active_wakeup = true,
654 },
655 [MT2712_POWER_DOMAIN_USB2] = {
656 .name = "usb2",
657 .sta_mask = PWR_STATUS_USB2,
658 .ctl_offs = SPM_USB2_PWR_CON,
659 .sram_pdn_bits = GENMASK(10, 8),
660 .sram_pdn_ack_bits = GENMASK(14, 12),
661 .clk_id = {CLK_NONE},
662 .active_wakeup = true,
663 },
664 [MT2712_POWER_DOMAIN_MFG] = {
665 .name = "mfg",
666 .sta_mask = PWR_STATUS_MFG,
667 .ctl_offs = SPM_MFG_PWR_CON,
668 .sram_pdn_bits = GENMASK(11, 8),
669 .sram_pdn_ack_bits = GENMASK(19, 16),
670 .clk_id = {CLK_MFG},
671 .bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
672 .active_wakeup = true,
673 },
674};
675
676/*
Mars Cheng36c310f2017-04-08 09:20:34 +0800677 * MT6797 power domain support
678 */
679
680static const struct scp_domain_data scp_domain_data_mt6797[] = {
681 [MT6797_POWER_DOMAIN_VDEC] = {
682 .name = "vdec",
683 .sta_mask = BIT(7),
684 .ctl_offs = 0x300,
685 .sram_pdn_bits = GENMASK(8, 8),
686 .sram_pdn_ack_bits = GENMASK(12, 12),
687 .clk_id = {CLK_VDEC},
688 },
689 [MT6797_POWER_DOMAIN_VENC] = {
690 .name = "venc",
691 .sta_mask = BIT(21),
692 .ctl_offs = 0x304,
693 .sram_pdn_bits = GENMASK(11, 8),
694 .sram_pdn_ack_bits = GENMASK(15, 12),
695 .clk_id = {CLK_NONE},
696 },
697 [MT6797_POWER_DOMAIN_ISP] = {
698 .name = "isp",
699 .sta_mask = BIT(5),
700 .ctl_offs = 0x308,
701 .sram_pdn_bits = GENMASK(9, 8),
702 .sram_pdn_ack_bits = GENMASK(13, 12),
703 .clk_id = {CLK_NONE},
704 },
705 [MT6797_POWER_DOMAIN_MM] = {
706 .name = "mm",
707 .sta_mask = BIT(3),
708 .ctl_offs = 0x30C,
709 .sram_pdn_bits = GENMASK(8, 8),
710 .sram_pdn_ack_bits = GENMASK(12, 12),
711 .clk_id = {CLK_MM},
712 .bus_prot_mask = (BIT(1) | BIT(2)),
713 },
714 [MT6797_POWER_DOMAIN_AUDIO] = {
715 .name = "audio",
716 .sta_mask = BIT(24),
717 .ctl_offs = 0x314,
718 .sram_pdn_bits = GENMASK(11, 8),
719 .sram_pdn_ack_bits = GENMASK(15, 12),
720 .clk_id = {CLK_NONE},
721 },
722 [MT6797_POWER_DOMAIN_MFG_ASYNC] = {
723 .name = "mfg_async",
724 .sta_mask = BIT(13),
725 .ctl_offs = 0x334,
726 .sram_pdn_bits = 0,
727 .sram_pdn_ack_bits = 0,
728 .clk_id = {CLK_MFG},
729 },
730 [MT6797_POWER_DOMAIN_MJC] = {
731 .name = "mjc",
732 .sta_mask = BIT(20),
733 .ctl_offs = 0x310,
734 .sram_pdn_bits = GENMASK(8, 8),
735 .sram_pdn_ack_bits = GENMASK(12, 12),
736 .clk_id = {CLK_NONE},
737 },
738};
739
Mars Cheng36c310f2017-04-08 09:20:34 +0800740#define SPM_PWR_STATUS_MT6797 0x0180
741#define SPM_PWR_STATUS_2ND_MT6797 0x0184
742
Sean Wang53fddb12017-08-07 15:24:35 +0800743static const struct scp_subdomain scp_subdomain_mt6797[] = {
744 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
745 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
746 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
747 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
748};
Mars Cheng36c310f2017-04-08 09:20:34 +0800749
750/*
Sean Wang52510ee2017-08-07 15:24:37 +0800751 * MT7622 power domain support
752 */
753
754static const struct scp_domain_data scp_domain_data_mt7622[] = {
755 [MT7622_POWER_DOMAIN_ETHSYS] = {
756 .name = "ethsys",
757 .sta_mask = PWR_STATUS_ETHSYS,
758 .ctl_offs = SPM_ETHSYS_PWR_CON,
759 .sram_pdn_bits = GENMASK(11, 8),
760 .sram_pdn_ack_bits = GENMASK(15, 12),
761 .clk_id = {CLK_NONE},
762 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
763 .active_wakeup = true,
764 },
765 [MT7622_POWER_DOMAIN_HIF0] = {
766 .name = "hif0",
767 .sta_mask = PWR_STATUS_HIF0,
768 .ctl_offs = SPM_HIF0_PWR_CON,
769 .sram_pdn_bits = GENMASK(11, 8),
770 .sram_pdn_ack_bits = GENMASK(15, 12),
771 .clk_id = {CLK_HIFSEL},
772 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
773 .active_wakeup = true,
774 },
775 [MT7622_POWER_DOMAIN_HIF1] = {
776 .name = "hif1",
777 .sta_mask = PWR_STATUS_HIF1,
778 .ctl_offs = SPM_HIF1_PWR_CON,
779 .sram_pdn_bits = GENMASK(11, 8),
780 .sram_pdn_ack_bits = GENMASK(15, 12),
781 .clk_id = {CLK_HIFSEL},
782 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
783 .active_wakeup = true,
784 },
785 [MT7622_POWER_DOMAIN_WB] = {
786 .name = "wb",
787 .sta_mask = PWR_STATUS_WB,
788 .ctl_offs = SPM_WB_PWR_CON,
789 .sram_pdn_bits = 0,
790 .sram_pdn_ack_bits = 0,
791 .clk_id = {CLK_NONE},
792 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
793 .active_wakeup = true,
794 },
795};
796
797/*
James Liao6078c652016-10-20 16:56:35 +0800798 * MT8173 power domain support
799 */
800
801static const struct scp_domain_data scp_domain_data_mt8173[] = {
802 [MT8173_POWER_DOMAIN_VDEC] = {
803 .name = "vdec",
804 .sta_mask = PWR_STATUS_VDEC,
805 .ctl_offs = SPM_VDE_PWR_CON,
806 .sram_pdn_bits = GENMASK(11, 8),
807 .sram_pdn_ack_bits = GENMASK(12, 12),
808 .clk_id = {CLK_MM},
809 },
810 [MT8173_POWER_DOMAIN_VENC] = {
811 .name = "venc",
812 .sta_mask = PWR_STATUS_VENC,
813 .ctl_offs = SPM_VEN_PWR_CON,
814 .sram_pdn_bits = GENMASK(11, 8),
815 .sram_pdn_ack_bits = GENMASK(15, 12),
816 .clk_id = {CLK_MM, CLK_VENC},
817 },
818 [MT8173_POWER_DOMAIN_ISP] = {
819 .name = "isp",
820 .sta_mask = PWR_STATUS_ISP,
821 .ctl_offs = SPM_ISP_PWR_CON,
822 .sram_pdn_bits = GENMASK(11, 8),
823 .sram_pdn_ack_bits = GENMASK(13, 12),
824 .clk_id = {CLK_MM},
825 },
826 [MT8173_POWER_DOMAIN_MM] = {
827 .name = "mm",
828 .sta_mask = PWR_STATUS_DISP,
829 .ctl_offs = SPM_DIS_PWR_CON,
830 .sram_pdn_bits = GENMASK(11, 8),
831 .sram_pdn_ack_bits = GENMASK(12, 12),
832 .clk_id = {CLK_MM},
833 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
834 MT8173_TOP_AXI_PROT_EN_MM_M1,
835 },
836 [MT8173_POWER_DOMAIN_VENC_LT] = {
837 .name = "venc_lt",
838 .sta_mask = PWR_STATUS_VENC_LT,
839 .ctl_offs = SPM_VEN2_PWR_CON,
840 .sram_pdn_bits = GENMASK(11, 8),
841 .sram_pdn_ack_bits = GENMASK(15, 12),
842 .clk_id = {CLK_MM, CLK_VENC_LT},
843 },
844 [MT8173_POWER_DOMAIN_AUDIO] = {
845 .name = "audio",
846 .sta_mask = PWR_STATUS_AUDIO,
847 .ctl_offs = SPM_AUDIO_PWR_CON,
848 .sram_pdn_bits = GENMASK(11, 8),
849 .sram_pdn_ack_bits = GENMASK(15, 12),
850 .clk_id = {CLK_NONE},
851 },
852 [MT8173_POWER_DOMAIN_USB] = {
853 .name = "usb",
854 .sta_mask = PWR_STATUS_USB,
855 .ctl_offs = SPM_USB_PWR_CON,
856 .sram_pdn_bits = GENMASK(11, 8),
857 .sram_pdn_ack_bits = GENMASK(15, 12),
858 .clk_id = {CLK_NONE},
859 .active_wakeup = true,
860 },
861 [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
862 .name = "mfg_async",
863 .sta_mask = PWR_STATUS_MFG_ASYNC,
864 .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
865 .sram_pdn_bits = GENMASK(11, 8),
866 .sram_pdn_ack_bits = 0,
867 .clk_id = {CLK_MFG},
868 },
869 [MT8173_POWER_DOMAIN_MFG_2D] = {
870 .name = "mfg_2d",
871 .sta_mask = PWR_STATUS_MFG_2D,
872 .ctl_offs = SPM_MFG_2D_PWR_CON,
873 .sram_pdn_bits = GENMASK(11, 8),
874 .sram_pdn_ack_bits = GENMASK(13, 12),
875 .clk_id = {CLK_NONE},
876 },
877 [MT8173_POWER_DOMAIN_MFG] = {
878 .name = "mfg",
879 .sta_mask = PWR_STATUS_MFG,
880 .ctl_offs = SPM_MFG_PWR_CON,
881 .sram_pdn_bits = GENMASK(13, 8),
882 .sram_pdn_ack_bits = GENMASK(21, 16),
883 .clk_id = {CLK_NONE},
884 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
885 MT8173_TOP_AXI_PROT_EN_MFG_M0 |
886 MT8173_TOP_AXI_PROT_EN_MFG_M1 |
887 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
888 },
889};
890
Sean Wang53fddb12017-08-07 15:24:35 +0800891static const struct scp_subdomain scp_subdomain_mt8173[] = {
892 {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
893 {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
894};
James Liao6078c652016-10-20 16:56:35 +0800895
Sean Wang53fddb12017-08-07 15:24:35 +0800896static const struct scp_soc_data mt2701_data = {
897 .domains = scp_domain_data_mt2701,
898 .num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
899 .regs = {
900 .pwr_sta_offs = SPM_PWR_STATUS,
901 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800902 },
903 .bus_prot_reg_update = true,
Sean Wang53fddb12017-08-07 15:24:35 +0800904};
James Liao6078c652016-10-20 16:56:35 +0800905
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +0800906static const struct scp_soc_data mt2712_data = {
907 .domains = scp_domain_data_mt2712,
908 .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
909 .regs = {
910 .pwr_sta_offs = SPM_PWR_STATUS,
911 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
912 },
913 .bus_prot_reg_update = false,
914};
915
Sean Wang53fddb12017-08-07 15:24:35 +0800916static const struct scp_soc_data mt6797_data = {
917 .domains = scp_domain_data_mt6797,
918 .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
919 .subdomains = scp_subdomain_mt6797,
920 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
921 .regs = {
922 .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
923 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800924 },
925 .bus_prot_reg_update = true,
Sean Wang53fddb12017-08-07 15:24:35 +0800926};
Mars Chengf1be4c42017-04-08 09:20:31 +0800927
Sean Wang52510ee2017-08-07 15:24:37 +0800928static const struct scp_soc_data mt7622_data = {
929 .domains = scp_domain_data_mt7622,
930 .num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
931 .regs = {
932 .pwr_sta_offs = SPM_PWR_STATUS,
933 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800934 },
935 .bus_prot_reg_update = true,
Sean Wang52510ee2017-08-07 15:24:37 +0800936};
937
Sean Wang53fddb12017-08-07 15:24:35 +0800938static const struct scp_soc_data mt8173_data = {
939 .domains = scp_domain_data_mt8173,
940 .num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
941 .subdomains = scp_subdomain_mt8173,
942 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
943 .regs = {
944 .pwr_sta_offs = SPM_PWR_STATUS,
945 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800946 },
947 .bus_prot_reg_update = true,
Sean Wang53fddb12017-08-07 15:24:35 +0800948};
Sascha Hauerc84e3582015-06-24 08:17:04 +0200949
James Liao6078c652016-10-20 16:56:35 +0800950/*
951 * scpsys driver init
952 */
953
Sascha Hauerc84e3582015-06-24 08:17:04 +0200954static const struct of_device_id of_scpsys_match_tbl[] = {
955 {
Shunli Wang112ef182016-10-20 16:56:38 +0800956 .compatible = "mediatek,mt2701-scpsys",
Sean Wang53fddb12017-08-07 15:24:35 +0800957 .data = &mt2701_data,
Shunli Wang112ef182016-10-20 16:56:38 +0800958 }, {
weiyi.lu@mediatek.com320f4ce2017-11-28 15:28:20 +0800959 .compatible = "mediatek,mt2712-scpsys",
960 .data = &mt2712_data,
961 }, {
Mars Cheng36c310f2017-04-08 09:20:34 +0800962 .compatible = "mediatek,mt6797-scpsys",
Sean Wang53fddb12017-08-07 15:24:35 +0800963 .data = &mt6797_data,
Mars Cheng36c310f2017-04-08 09:20:34 +0800964 }, {
Sean Wang52510ee2017-08-07 15:24:37 +0800965 .compatible = "mediatek,mt7622-scpsys",
966 .data = &mt7622_data,
967 }, {
Sascha Hauerc84e3582015-06-24 08:17:04 +0200968 .compatible = "mediatek,mt8173-scpsys",
Sean Wang53fddb12017-08-07 15:24:35 +0800969 .data = &mt8173_data,
Sascha Hauerc84e3582015-06-24 08:17:04 +0200970 }, {
971 /* sentinel */
972 }
973};
974
James Liao6078c652016-10-20 16:56:35 +0800975static int scpsys_probe(struct platform_device *pdev)
976{
Sean Wang53fddb12017-08-07 15:24:35 +0800977 const struct of_device_id *match;
978 const struct scp_subdomain *sd;
979 const struct scp_soc_data *soc;
980 struct scp *scp;
981 struct genpd_onecell_data *pd_data;
982 int i, ret;
James Liao6078c652016-10-20 16:56:35 +0800983
Sean Wang53fddb12017-08-07 15:24:35 +0800984 match = of_match_device(of_scpsys_match_tbl, &pdev->dev);
985 soc = (const struct scp_soc_data *)match->data;
James Liao6078c652016-10-20 16:56:35 +0800986
weiyi.lu@mediatek.comfa7e8432017-11-28 15:28:18 +0800987 scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
988 soc->bus_prot_reg_update);
Sean Wang53fddb12017-08-07 15:24:35 +0800989 if (IS_ERR(scp))
990 return PTR_ERR(scp);
James Liao6078c652016-10-20 16:56:35 +0800991
Sean Wang53fddb12017-08-07 15:24:35 +0800992 mtk_register_power_domains(pdev, scp, soc->num_domains);
993
994 pd_data = &scp->pd_data;
995
996 for (i = 0, sd = soc->subdomains ; i < soc->num_subdomains ; i++) {
997 ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
998 pd_data->domains[sd->subdomain]);
999 if (ret && IS_ENABLED(CONFIG_PM))
1000 dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
1001 ret);
1002 }
1003
1004 return 0;
James Liao6078c652016-10-20 16:56:35 +08001005}
1006
Sascha Hauerc84e3582015-06-24 08:17:04 +02001007static struct platform_driver scpsys_drv = {
Matthias Bruggerbe295232015-12-30 09:30:40 +01001008 .probe = scpsys_probe,
Sascha Hauerc84e3582015-06-24 08:17:04 +02001009 .driver = {
1010 .name = "mtk-scpsys",
Matthias Bruggerbe295232015-12-30 09:30:40 +01001011 .suppress_bind_attrs = true,
Sascha Hauerc84e3582015-06-24 08:17:04 +02001012 .owner = THIS_MODULE,
1013 .of_match_table = of_match_ptr(of_scpsys_match_tbl),
1014 },
1015};
Matthias Bruggerbe295232015-12-30 09:30:40 +01001016builtin_platform_driver(scpsys_drv);