Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.3-rc1 488 lines 12 kB view raw
1/* 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> 14#include <linux/delay.h> 15#include <linux/io.h> 16#include <linux/kernel.h> 17#include <linux/mfd/syscon.h> 18#include <linux/module.h> 19#include <linux/of_device.h> 20#include <linux/platform_device.h> 21#include <linux/pm_domain.h> 22#include <linux/regmap.h> 23#include <linux/soc/mediatek/infracfg.h> 24#include <dt-bindings/power/mt8173-power.h> 25 26#define SPM_VDE_PWR_CON 0x0210 27#define SPM_MFG_PWR_CON 0x0214 28#define SPM_VEN_PWR_CON 0x0230 29#define SPM_ISP_PWR_CON 0x0238 30#define SPM_DIS_PWR_CON 0x023c 31#define SPM_VEN2_PWR_CON 0x0298 32#define SPM_AUDIO_PWR_CON 0x029c 33#define SPM_MFG_2D_PWR_CON 0x02c0 34#define SPM_MFG_ASYNC_PWR_CON 0x02c4 35#define SPM_USB_PWR_CON 0x02cc 36#define SPM_PWR_STATUS 0x060c 37#define SPM_PWR_STATUS_2ND 0x0610 38 39#define PWR_RST_B_BIT BIT(0) 40#define PWR_ISO_BIT BIT(1) 41#define PWR_ON_BIT BIT(2) 42#define PWR_ON_2ND_BIT BIT(3) 43#define PWR_CLK_DIS_BIT BIT(4) 44 45#define PWR_STATUS_DISP BIT(3) 46#define PWR_STATUS_MFG BIT(4) 47#define PWR_STATUS_ISP BIT(5) 48#define PWR_STATUS_VDEC BIT(7) 49#define PWR_STATUS_VENC_LT BIT(20) 50#define PWR_STATUS_VENC BIT(21) 51#define PWR_STATUS_MFG_2D BIT(22) 52#define PWR_STATUS_MFG_ASYNC BIT(23) 53#define PWR_STATUS_AUDIO BIT(24) 54#define PWR_STATUS_USB BIT(25) 55 56enum clk_id { 57 MT8173_CLK_MM, 58 MT8173_CLK_MFG, 59 MT8173_CLK_NONE, 60 MT8173_CLK_MAX = MT8173_CLK_NONE, 61}; 62 63struct scp_domain_data { 64 const char *name; 65 u32 sta_mask; 66 int ctl_offs; 67 u32 sram_pdn_bits; 68 u32 sram_pdn_ack_bits; 69 u32 bus_prot_mask; 70 enum clk_id clk_id; 71}; 72 73static const struct scp_domain_data scp_domain_data[] __initconst = { 74 [MT8173_POWER_DOMAIN_VDEC] = { 75 .name = "vdec", 76 .sta_mask = PWR_STATUS_VDEC, 77 .ctl_offs = SPM_VDE_PWR_CON, 78 .sram_pdn_bits = GENMASK(11, 8), 79 .sram_pdn_ack_bits = GENMASK(12, 12), 80 .clk_id = MT8173_CLK_MM, 81 }, 82 [MT8173_POWER_DOMAIN_VENC] = { 83 .name = "venc", 84 .sta_mask = PWR_STATUS_VENC, 85 .ctl_offs = SPM_VEN_PWR_CON, 86 .sram_pdn_bits = GENMASK(11, 8), 87 .sram_pdn_ack_bits = GENMASK(15, 12), 88 .clk_id = MT8173_CLK_MM, 89 }, 90 [MT8173_POWER_DOMAIN_ISP] = { 91 .name = "isp", 92 .sta_mask = PWR_STATUS_ISP, 93 .ctl_offs = SPM_ISP_PWR_CON, 94 .sram_pdn_bits = GENMASK(11, 8), 95 .sram_pdn_ack_bits = GENMASK(13, 12), 96 .clk_id = MT8173_CLK_MM, 97 }, 98 [MT8173_POWER_DOMAIN_MM] = { 99 .name = "mm", 100 .sta_mask = PWR_STATUS_DISP, 101 .ctl_offs = SPM_DIS_PWR_CON, 102 .sram_pdn_bits = GENMASK(11, 8), 103 .sram_pdn_ack_bits = GENMASK(12, 12), 104 .clk_id = MT8173_CLK_MM, 105 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | 106 MT8173_TOP_AXI_PROT_EN_MM_M1, 107 }, 108 [MT8173_POWER_DOMAIN_VENC_LT] = { 109 .name = "venc_lt", 110 .sta_mask = PWR_STATUS_VENC_LT, 111 .ctl_offs = SPM_VEN2_PWR_CON, 112 .sram_pdn_bits = GENMASK(11, 8), 113 .sram_pdn_ack_bits = GENMASK(15, 12), 114 .clk_id = MT8173_CLK_MM, 115 }, 116 [MT8173_POWER_DOMAIN_AUDIO] = { 117 .name = "audio", 118 .sta_mask = PWR_STATUS_AUDIO, 119 .ctl_offs = SPM_AUDIO_PWR_CON, 120 .sram_pdn_bits = GENMASK(11, 8), 121 .sram_pdn_ack_bits = GENMASK(15, 12), 122 .clk_id = MT8173_CLK_NONE, 123 }, 124 [MT8173_POWER_DOMAIN_USB] = { 125 .name = "usb", 126 .sta_mask = PWR_STATUS_USB, 127 .ctl_offs = SPM_USB_PWR_CON, 128 .sram_pdn_bits = GENMASK(11, 8), 129 .sram_pdn_ack_bits = GENMASK(15, 12), 130 .clk_id = MT8173_CLK_NONE, 131 }, 132 [MT8173_POWER_DOMAIN_MFG_ASYNC] = { 133 .name = "mfg_async", 134 .sta_mask = PWR_STATUS_MFG_ASYNC, 135 .ctl_offs = SPM_MFG_ASYNC_PWR_CON, 136 .sram_pdn_bits = GENMASK(11, 8), 137 .sram_pdn_ack_bits = 0, 138 .clk_id = MT8173_CLK_MFG, 139 }, 140 [MT8173_POWER_DOMAIN_MFG_2D] = { 141 .name = "mfg_2d", 142 .sta_mask = PWR_STATUS_MFG_2D, 143 .ctl_offs = SPM_MFG_2D_PWR_CON, 144 .sram_pdn_bits = GENMASK(11, 8), 145 .sram_pdn_ack_bits = GENMASK(13, 12), 146 .clk_id = MT8173_CLK_NONE, 147 }, 148 [MT8173_POWER_DOMAIN_MFG] = { 149 .name = "mfg", 150 .sta_mask = PWR_STATUS_MFG, 151 .ctl_offs = SPM_MFG_PWR_CON, 152 .sram_pdn_bits = GENMASK(13, 8), 153 .sram_pdn_ack_bits = GENMASK(21, 16), 154 .clk_id = MT8173_CLK_NONE, 155 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | 156 MT8173_TOP_AXI_PROT_EN_MFG_M0 | 157 MT8173_TOP_AXI_PROT_EN_MFG_M1 | 158 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, 159 }, 160}; 161 162#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data) 163 164struct scp; 165 166struct scp_domain { 167 struct generic_pm_domain genpd; 168 struct scp *scp; 169 struct clk *clk; 170 u32 sta_mask; 171 void __iomem *ctl_addr; 172 u32 sram_pdn_bits; 173 u32 sram_pdn_ack_bits; 174 u32 bus_prot_mask; 175}; 176 177struct scp { 178 struct scp_domain domains[NUM_DOMAINS]; 179 struct genpd_onecell_data pd_data; 180 struct device *dev; 181 void __iomem *base; 182 struct regmap *infracfg; 183}; 184 185static int scpsys_domain_is_on(struct scp_domain *scpd) 186{ 187 struct scp *scp = scpd->scp; 188 189 u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->sta_mask; 190 u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & scpd->sta_mask; 191 192 /* 193 * A domain is on when both status bits are set. If only one is set 194 * return an error. This happens while powering up a domain 195 */ 196 197 if (status && status2) 198 return true; 199 if (!status && !status2) 200 return false; 201 202 return -EINVAL; 203} 204 205static int scpsys_power_on(struct generic_pm_domain *genpd) 206{ 207 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 208 struct scp *scp = scpd->scp; 209 unsigned long timeout; 210 bool expired; 211 void __iomem *ctl_addr = scpd->ctl_addr; 212 u32 sram_pdn_ack = scpd->sram_pdn_ack_bits; 213 u32 val; 214 int ret; 215 216 if (scpd->clk) { 217 ret = clk_prepare_enable(scpd->clk); 218 if (ret) 219 goto err_clk; 220 } 221 222 val = readl(ctl_addr); 223 val |= PWR_ON_BIT; 224 writel(val, ctl_addr); 225 val |= PWR_ON_2ND_BIT; 226 writel(val, ctl_addr); 227 228 /* wait until PWR_ACK = 1 */ 229 timeout = jiffies + HZ; 230 expired = false; 231 while (1) { 232 ret = scpsys_domain_is_on(scpd); 233 if (ret > 0) 234 break; 235 236 if (expired) { 237 ret = -ETIMEDOUT; 238 goto err_pwr_ack; 239 } 240 241 cpu_relax(); 242 243 if (time_after(jiffies, timeout)) 244 expired = true; 245 } 246 247 val &= ~PWR_CLK_DIS_BIT; 248 writel(val, ctl_addr); 249 250 val &= ~PWR_ISO_BIT; 251 writel(val, ctl_addr); 252 253 val |= PWR_RST_B_BIT; 254 writel(val, ctl_addr); 255 256 val &= ~scpd->sram_pdn_bits; 257 writel(val, ctl_addr); 258 259 /* wait until SRAM_PDN_ACK all 0 */ 260 timeout = jiffies + HZ; 261 expired = false; 262 while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) { 263 264 if (expired) { 265 ret = -ETIMEDOUT; 266 goto err_pwr_ack; 267 } 268 269 cpu_relax(); 270 271 if (time_after(jiffies, timeout)) 272 expired = true; 273 } 274 275 if (scpd->bus_prot_mask) { 276 ret = mtk_infracfg_clear_bus_protection(scp->infracfg, 277 scpd->bus_prot_mask); 278 if (ret) 279 goto err_pwr_ack; 280 } 281 282 return 0; 283 284err_pwr_ack: 285 clk_disable_unprepare(scpd->clk); 286err_clk: 287 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); 288 289 return ret; 290} 291 292static int scpsys_power_off(struct generic_pm_domain *genpd) 293{ 294 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 295 struct scp *scp = scpd->scp; 296 unsigned long timeout; 297 bool expired; 298 void __iomem *ctl_addr = scpd->ctl_addr; 299 u32 pdn_ack = scpd->sram_pdn_ack_bits; 300 u32 val; 301 int ret; 302 303 if (scpd->bus_prot_mask) { 304 ret = mtk_infracfg_set_bus_protection(scp->infracfg, 305 scpd->bus_prot_mask); 306 if (ret) 307 goto out; 308 } 309 310 val = readl(ctl_addr); 311 val |= scpd->sram_pdn_bits; 312 writel(val, ctl_addr); 313 314 /* wait until SRAM_PDN_ACK all 1 */ 315 timeout = jiffies + HZ; 316 expired = false; 317 while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) { 318 if (expired) { 319 ret = -ETIMEDOUT; 320 goto out; 321 } 322 323 cpu_relax(); 324 325 if (time_after(jiffies, timeout)) 326 expired = true; 327 } 328 329 val |= PWR_ISO_BIT; 330 writel(val, ctl_addr); 331 332 val &= ~PWR_RST_B_BIT; 333 writel(val, ctl_addr); 334 335 val |= PWR_CLK_DIS_BIT; 336 writel(val, ctl_addr); 337 338 val &= ~PWR_ON_BIT; 339 writel(val, ctl_addr); 340 341 val &= ~PWR_ON_2ND_BIT; 342 writel(val, ctl_addr); 343 344 /* wait until PWR_ACK = 0 */ 345 timeout = jiffies + HZ; 346 expired = false; 347 while (1) { 348 ret = scpsys_domain_is_on(scpd); 349 if (ret == 0) 350 break; 351 352 if (expired) { 353 ret = -ETIMEDOUT; 354 goto out; 355 } 356 357 cpu_relax(); 358 359 if (time_after(jiffies, timeout)) 360 expired = true; 361 } 362 363 if (scpd->clk) 364 clk_disable_unprepare(scpd->clk); 365 366 return 0; 367 368out: 369 dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); 370 371 return ret; 372} 373 374static int __init scpsys_probe(struct platform_device *pdev) 375{ 376 struct genpd_onecell_data *pd_data; 377 struct resource *res; 378 int i, ret; 379 struct scp *scp; 380 struct clk *clk[MT8173_CLK_MAX]; 381 382 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); 383 if (!scp) 384 return -ENOMEM; 385 386 scp->dev = &pdev->dev; 387 388 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 389 scp->base = devm_ioremap_resource(&pdev->dev, res); 390 if (IS_ERR(scp->base)) 391 return PTR_ERR(scp->base); 392 393 pd_data = &scp->pd_data; 394 395 pd_data->domains = devm_kzalloc(&pdev->dev, 396 sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL); 397 if (!pd_data->domains) 398 return -ENOMEM; 399 400 clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm"); 401 if (IS_ERR(clk[MT8173_CLK_MM])) 402 return PTR_ERR(clk[MT8173_CLK_MM]); 403 404 clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg"); 405 if (IS_ERR(clk[MT8173_CLK_MFG])) 406 return PTR_ERR(clk[MT8173_CLK_MFG]); 407 408 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 409 "infracfg"); 410 if (IS_ERR(scp->infracfg)) { 411 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", 412 PTR_ERR(scp->infracfg)); 413 return PTR_ERR(scp->infracfg); 414 } 415 416 pd_data->num_domains = NUM_DOMAINS; 417 418 for (i = 0; i < NUM_DOMAINS; i++) { 419 struct scp_domain *scpd = &scp->domains[i]; 420 struct generic_pm_domain *genpd = &scpd->genpd; 421 const struct scp_domain_data *data = &scp_domain_data[i]; 422 423 pd_data->domains[i] = genpd; 424 scpd->scp = scp; 425 426 scpd->sta_mask = data->sta_mask; 427 scpd->ctl_addr = scp->base + data->ctl_offs; 428 scpd->sram_pdn_bits = data->sram_pdn_bits; 429 scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits; 430 scpd->bus_prot_mask = data->bus_prot_mask; 431 if (data->clk_id != MT8173_CLK_NONE) 432 scpd->clk = clk[data->clk_id]; 433 434 genpd->name = data->name; 435 genpd->power_off = scpsys_power_off; 436 genpd->power_on = scpsys_power_on; 437 438 /* 439 * Initially turn on all domains to make the domains usable 440 * with !CONFIG_PM and to get the hardware in sync with the 441 * software. The unused domains will be switched off during 442 * late_init time. 443 */ 444 genpd->power_on(genpd); 445 446 pm_genpd_init(genpd, NULL, false); 447 } 448 449 /* 450 * We are not allowed to fail here since there is no way to unregister 451 * a power domain. Once registered above we have to keep the domains 452 * valid. 453 */ 454 455 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC], 456 pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]); 457 if (ret && IS_ENABLED(CONFIG_PM)) 458 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); 459 460 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D], 461 pd_data->domains[MT8173_POWER_DOMAIN_MFG]); 462 if (ret && IS_ENABLED(CONFIG_PM)) 463 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); 464 465 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); 466 if (ret) 467 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); 468 469 return 0; 470} 471 472static const struct of_device_id of_scpsys_match_tbl[] = { 473 { 474 .compatible = "mediatek,mt8173-scpsys", 475 }, { 476 /* sentinel */ 477 } 478}; 479 480static struct platform_driver scpsys_drv = { 481 .driver = { 482 .name = "mtk-scpsys", 483 .owner = THIS_MODULE, 484 .of_match_table = of_match_ptr(of_scpsys_match_tbl), 485 }, 486}; 487 488module_platform_driver_probe(scpsys_drv, scpsys_probe);