0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/clk/renesas.h>
0013 #include <linux/console.h>
0014 #include <linux/delay.h>
0015 #include <linux/of.h>
0016 #include <linux/of_address.h>
0017 #include <linux/pm.h>
0018 #include <linux/pm_clock.h>
0019 #include <linux/pm_domain.h>
0020 #include <linux/slab.h>
0021
0022 #include <asm/io.h>
0023
0024
0025 #define SPDCR 0x08
0026 #define SWUCR 0x14
0027 #define PSTR 0x80
0028
0029 #define PSTR_RETRIES 100
0030 #define PSTR_DELAY_US 10
0031
0032 struct rmobile_pm_domain {
0033 struct generic_pm_domain genpd;
0034 struct dev_power_governor *gov;
0035 int (*suspend)(void);
0036 void __iomem *base;
0037 unsigned int bit_shift;
0038 };
0039
0040 static inline
0041 struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
0042 {
0043 return container_of(d, struct rmobile_pm_domain, genpd);
0044 }
0045
0046 static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
0047 {
0048 struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
0049 unsigned int mask = BIT(rmobile_pd->bit_shift);
0050
0051 if (rmobile_pd->suspend) {
0052 int ret = rmobile_pd->suspend();
0053
0054 if (ret)
0055 return ret;
0056 }
0057
0058 if (readl(rmobile_pd->base + PSTR) & mask) {
0059 unsigned int retry_count;
0060 writel(mask, rmobile_pd->base + SPDCR);
0061
0062 for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
0063 if (!(readl(rmobile_pd->base + SPDCR) & mask))
0064 break;
0065 cpu_relax();
0066 }
0067 }
0068
0069 pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask,
0070 readl(rmobile_pd->base + PSTR));
0071
0072 return 0;
0073 }
0074
0075 static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
0076 {
0077 unsigned int mask = BIT(rmobile_pd->bit_shift);
0078 unsigned int retry_count;
0079 int ret = 0;
0080
0081 if (readl(rmobile_pd->base + PSTR) & mask)
0082 return ret;
0083
0084 writel(mask, rmobile_pd->base + SWUCR);
0085
0086 for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
0087 if (!(readl(rmobile_pd->base + SWUCR) & mask))
0088 break;
0089 if (retry_count > PSTR_RETRIES)
0090 udelay(PSTR_DELAY_US);
0091 else
0092 cpu_relax();
0093 }
0094 if (!retry_count)
0095 ret = -EIO;
0096
0097 pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
0098 rmobile_pd->genpd.name, mask,
0099 readl(rmobile_pd->base + PSTR));
0100
0101 return ret;
0102 }
0103
0104 static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
0105 {
0106 return __rmobile_pd_power_up(to_rmobile_pd(genpd));
0107 }
0108
0109 static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
0110 {
0111 struct generic_pm_domain *genpd = &rmobile_pd->genpd;
0112 struct dev_power_governor *gov = rmobile_pd->gov;
0113
0114 genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
0115 genpd->attach_dev = cpg_mstp_attach_dev;
0116 genpd->detach_dev = cpg_mstp_detach_dev;
0117
0118 if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
0119 genpd->power_off = rmobile_pd_power_down;
0120 genpd->power_on = rmobile_pd_power_up;
0121 __rmobile_pd_power_up(rmobile_pd);
0122 }
0123
0124 pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
0125 }
0126
0127 static int rmobile_pd_suspend_console(void)
0128 {
0129
0130
0131
0132
0133 return console_suspend_enabled ? 0 : -EBUSY;
0134 }
0135
0136 enum pd_types {
0137 PD_NORMAL,
0138 PD_CPU,
0139 PD_CONSOLE,
0140 PD_DEBUG,
0141 PD_MEMCTL,
0142 };
0143
0144 #define MAX_NUM_SPECIAL_PDS 16
0145
0146 static struct special_pd {
0147 struct device_node *pd;
0148 enum pd_types type;
0149 } special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
0150
0151 static unsigned int num_special_pds __initdata;
0152
0153 static const struct of_device_id special_ids[] __initconst = {
0154 { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
0155 { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
0156 { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
0157 { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
0158 { },
0159 };
0160
0161 static void __init add_special_pd(struct device_node *np, enum pd_types type)
0162 {
0163 unsigned int i;
0164 struct device_node *pd;
0165
0166 pd = of_parse_phandle(np, "power-domains", 0);
0167 if (!pd)
0168 return;
0169
0170 for (i = 0; i < num_special_pds; i++)
0171 if (pd == special_pds[i].pd && type == special_pds[i].type) {
0172 of_node_put(pd);
0173 return;
0174 }
0175
0176 if (num_special_pds == ARRAY_SIZE(special_pds)) {
0177 pr_warn("Too many special PM domains\n");
0178 of_node_put(pd);
0179 return;
0180 }
0181
0182 pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np);
0183
0184 special_pds[num_special_pds].pd = pd;
0185 special_pds[num_special_pds].type = type;
0186 num_special_pds++;
0187 }
0188
0189 static void __init get_special_pds(void)
0190 {
0191 struct device_node *np;
0192 const struct of_device_id *id;
0193
0194
0195 for_each_of_cpu_node(np)
0196 add_special_pd(np, PD_CPU);
0197
0198
0199 if (of_stdout)
0200 add_special_pd(of_stdout, PD_CONSOLE);
0201
0202
0203 for_each_matching_node_and_match(np, special_ids, &id)
0204 add_special_pd(np, (enum pd_types)id->data);
0205 }
0206
0207 static void __init put_special_pds(void)
0208 {
0209 unsigned int i;
0210
0211 for (i = 0; i < num_special_pds; i++)
0212 of_node_put(special_pds[i].pd);
0213 }
0214
0215 static enum pd_types __init pd_type(const struct device_node *pd)
0216 {
0217 unsigned int i;
0218
0219 for (i = 0; i < num_special_pds; i++)
0220 if (pd == special_pds[i].pd)
0221 return special_pds[i].type;
0222
0223 return PD_NORMAL;
0224 }
0225
0226 static void __init rmobile_setup_pm_domain(struct device_node *np,
0227 struct rmobile_pm_domain *pd)
0228 {
0229 const char *name = pd->genpd.name;
0230
0231 switch (pd_type(np)) {
0232 case PD_CPU:
0233
0234
0235
0236
0237 pr_debug("PM domain %s contains CPU\n", name);
0238 pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
0239 break;
0240
0241 case PD_CONSOLE:
0242 pr_debug("PM domain %s contains serial console\n", name);
0243 pd->gov = &pm_domain_always_on_gov;
0244 pd->suspend = rmobile_pd_suspend_console;
0245 break;
0246
0247 case PD_DEBUG:
0248
0249
0250
0251
0252
0253 pr_debug("PM domain %s contains Coresight-ETM\n", name);
0254 pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
0255 break;
0256
0257 case PD_MEMCTL:
0258
0259
0260
0261
0262 pr_debug("PM domain %s contains MEMCTL\n", name);
0263 pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
0264 break;
0265
0266 case PD_NORMAL:
0267 if (pd->bit_shift == ~0) {
0268
0269 pr_debug("PM domain %s is always-on domain\n", name);
0270 pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
0271 }
0272 break;
0273 }
0274
0275 rmobile_init_pm_domain(pd);
0276 }
0277
0278 static int __init rmobile_add_pm_domains(void __iomem *base,
0279 struct device_node *parent,
0280 struct generic_pm_domain *genpd_parent)
0281 {
0282 struct device_node *np;
0283
0284 for_each_child_of_node(parent, np) {
0285 struct rmobile_pm_domain *pd;
0286 u32 idx = ~0;
0287
0288 if (of_property_read_u32(np, "reg", &idx)) {
0289
0290 }
0291
0292 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
0293 if (!pd) {
0294 of_node_put(np);
0295 return -ENOMEM;
0296 }
0297
0298 pd->genpd.name = np->name;
0299 pd->base = base;
0300 pd->bit_shift = idx;
0301
0302 rmobile_setup_pm_domain(np, pd);
0303 if (genpd_parent)
0304 pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
0305 of_genpd_add_provider_simple(np, &pd->genpd);
0306
0307 rmobile_add_pm_domains(base, np, &pd->genpd);
0308 }
0309 return 0;
0310 }
0311
0312 static int __init rmobile_init_pm_domains(void)
0313 {
0314 struct device_node *np, *pmd;
0315 bool scanned = false;
0316 void __iomem *base;
0317 int ret = 0;
0318
0319 for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
0320 base = of_iomap(np, 0);
0321 if (!base) {
0322 pr_warn("%pOF cannot map reg 0\n", np);
0323 continue;
0324 }
0325
0326 pmd = of_get_child_by_name(np, "pm-domains");
0327 if (!pmd) {
0328 iounmap(base);
0329 pr_warn("%pOF lacks pm-domains node\n", np);
0330 continue;
0331 }
0332
0333 if (!scanned) {
0334
0335 get_special_pds();
0336 scanned = true;
0337 }
0338
0339 ret = rmobile_add_pm_domains(base, pmd, NULL);
0340 of_node_put(pmd);
0341 if (ret) {
0342 of_node_put(np);
0343 break;
0344 }
0345
0346 fwnode_dev_initialized(&np->fwnode, true);
0347 }
0348
0349 put_special_pds();
0350
0351 return ret;
0352 }
0353
0354 core_initcall(rmobile_init_pm_domains);