0001
0002
0003
0004
0005
0006
0007 #include <linux/clk/imx.h>
0008 #include <linux/delay.h>
0009 #include <linux/init.h>
0010 #include <linux/io.h>
0011 #include <linux/irq.h>
0012 #include <linux/genalloc.h>
0013 #include <linux/irqchip/arm-gic.h>
0014 #include <linux/mfd/syscon.h>
0015 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_platform.h>
0019 #include <linux/regmap.h>
0020 #include <linux/suspend.h>
0021 #include <asm/cacheflush.h>
0022 #include <asm/fncpy.h>
0023 #include <asm/proc-fns.h>
0024 #include <asm/suspend.h>
0025 #include <asm/tlb.h>
0026
0027 #include "common.h"
0028 #include "hardware.h"
0029
0030 #define CCR 0x0
0031 #define BM_CCR_WB_COUNT (0x7 << 16)
0032 #define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
0033 #define BM_CCR_RBC_EN (0x1 << 27)
0034
0035 #define CLPCR 0x54
0036 #define BP_CLPCR_LPM 0
0037 #define BM_CLPCR_LPM (0x3 << 0)
0038 #define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
0039 #define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
0040 #define BM_CLPCR_SBYOS (0x1 << 6)
0041 #define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
0042 #define BM_CLPCR_VSTBY (0x1 << 8)
0043 #define BP_CLPCR_STBY_COUNT 9
0044 #define BM_CLPCR_STBY_COUNT (0x3 << 9)
0045 #define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
0046 #define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
0047 #define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
0048 #define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
0049 #define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
0050 #define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
0051 #define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
0052 #define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
0053 #define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
0054 #define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
0055 #define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
0056
0057 #define CGPR 0x64
0058 #define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17)
0059
0060 #define MX6Q_SUSPEND_OCRAM_SIZE 0x1000
0061 #define MX6_MAX_MMDC_IO_NUM 33
0062
0063 static void __iomem *ccm_base;
0064 static void __iomem *suspend_ocram_base;
0065 static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 struct imx6_pm_base {
0082 phys_addr_t pbase;
0083 void __iomem *vbase;
0084 };
0085
0086 struct imx6_pm_socdata {
0087 u32 ddr_type;
0088 const char *mmdc_compat;
0089 const char *src_compat;
0090 const char *iomuxc_compat;
0091 const char *gpc_compat;
0092 const char *pl310_compat;
0093 const u32 mmdc_io_num;
0094 const u32 *mmdc_io_offset;
0095 };
0096
0097 static const u32 imx6q_mmdc_io_offset[] __initconst = {
0098 0x5ac, 0x5b4, 0x528, 0x520,
0099 0x514, 0x510, 0x5bc, 0x5c4,
0100 0x56c, 0x578, 0x588, 0x594,
0101 0x5a8, 0x5b0, 0x524, 0x51c,
0102 0x518, 0x50c, 0x5b8, 0x5c0,
0103 0x784, 0x788, 0x794, 0x79c,
0104 0x7a0, 0x7a4, 0x7a8, 0x748,
0105 0x59c, 0x5a0, 0x750, 0x774,
0106 0x74c,
0107 };
0108
0109 static const u32 imx6dl_mmdc_io_offset[] __initconst = {
0110 0x470, 0x474, 0x478, 0x47c,
0111 0x480, 0x484, 0x488, 0x48c,
0112 0x464, 0x490, 0x4ac, 0x4b0,
0113 0x4bc, 0x4c0, 0x4c4, 0x4c8,
0114 0x4cc, 0x4d0, 0x4d4, 0x4d8,
0115 0x764, 0x770, 0x778, 0x77c,
0116 0x780, 0x784, 0x78c, 0x748,
0117 0x4b4, 0x4b8, 0x750, 0x760,
0118 0x74c,
0119 };
0120
0121 static const u32 imx6sl_mmdc_io_offset[] __initconst = {
0122 0x30c, 0x310, 0x314, 0x318,
0123 0x5c4, 0x5cc, 0x5d4, 0x5d8,
0124 0x300, 0x31c, 0x338, 0x5ac,
0125 0x33c, 0x340, 0x5b0, 0x5c0,
0126 0x330, 0x334, 0x320,
0127 };
0128
0129 static const u32 imx6sll_mmdc_io_offset[] __initconst = {
0130 0x294, 0x298, 0x29c, 0x2a0,
0131 0x544, 0x54c, 0x554, 0x558,
0132 0x530, 0x540, 0x2ac, 0x52c,
0133 0x2a4, 0x2a8,
0134 };
0135
0136 static const u32 imx6sx_mmdc_io_offset[] __initconst = {
0137 0x2ec, 0x2f0, 0x2f4, 0x2f8,
0138 0x60c, 0x610, 0x61c, 0x620,
0139 0x300, 0x2fc, 0x32c, 0x5f4,
0140 0x310, 0x314, 0x5f8, 0x608,
0141 0x330, 0x334, 0x338, 0x33c,
0142 };
0143
0144 static const u32 imx6ul_mmdc_io_offset[] __initconst = {
0145 0x244, 0x248, 0x24c, 0x250,
0146 0x27c, 0x498, 0x4a4, 0x490,
0147 0x280, 0x284, 0x260, 0x264,
0148 0x494, 0x4b0,
0149 };
0150
0151 static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
0152 .mmdc_compat = "fsl,imx6q-mmdc",
0153 .src_compat = "fsl,imx6q-src",
0154 .iomuxc_compat = "fsl,imx6q-iomuxc",
0155 .gpc_compat = "fsl,imx6q-gpc",
0156 .pl310_compat = "arm,pl310-cache",
0157 .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
0158 .mmdc_io_offset = imx6q_mmdc_io_offset,
0159 };
0160
0161 static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
0162 .mmdc_compat = "fsl,imx6q-mmdc",
0163 .src_compat = "fsl,imx6q-src",
0164 .iomuxc_compat = "fsl,imx6dl-iomuxc",
0165 .gpc_compat = "fsl,imx6q-gpc",
0166 .pl310_compat = "arm,pl310-cache",
0167 .mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
0168 .mmdc_io_offset = imx6dl_mmdc_io_offset,
0169 };
0170
0171 static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
0172 .mmdc_compat = "fsl,imx6sl-mmdc",
0173 .src_compat = "fsl,imx6sl-src",
0174 .iomuxc_compat = "fsl,imx6sl-iomuxc",
0175 .gpc_compat = "fsl,imx6sl-gpc",
0176 .pl310_compat = "arm,pl310-cache",
0177 .mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
0178 .mmdc_io_offset = imx6sl_mmdc_io_offset,
0179 };
0180
0181 static const struct imx6_pm_socdata imx6sll_pm_data __initconst = {
0182 .mmdc_compat = "fsl,imx6sll-mmdc",
0183 .src_compat = "fsl,imx6sll-src",
0184 .iomuxc_compat = "fsl,imx6sll-iomuxc",
0185 .gpc_compat = "fsl,imx6sll-gpc",
0186 .pl310_compat = "arm,pl310-cache",
0187 .mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset),
0188 .mmdc_io_offset = imx6sll_mmdc_io_offset,
0189 };
0190
0191 static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
0192 .mmdc_compat = "fsl,imx6sx-mmdc",
0193 .src_compat = "fsl,imx6sx-src",
0194 .iomuxc_compat = "fsl,imx6sx-iomuxc",
0195 .gpc_compat = "fsl,imx6sx-gpc",
0196 .pl310_compat = "arm,pl310-cache",
0197 .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
0198 .mmdc_io_offset = imx6sx_mmdc_io_offset,
0199 };
0200
0201 static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
0202 .mmdc_compat = "fsl,imx6ul-mmdc",
0203 .src_compat = "fsl,imx6ul-src",
0204 .iomuxc_compat = "fsl,imx6ul-iomuxc",
0205 .gpc_compat = "fsl,imx6ul-gpc",
0206 .pl310_compat = NULL,
0207 .mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset),
0208 .mmdc_io_offset = imx6ul_mmdc_io_offset,
0209 };
0210
0211
0212
0213
0214
0215
0216
0217
0218 struct imx6_cpu_pm_info {
0219 phys_addr_t pbase;
0220 phys_addr_t resume_addr;
0221 u32 ddr_type;
0222 u32 pm_info_size;
0223 struct imx6_pm_base mmdc_base;
0224 struct imx6_pm_base src_base;
0225 struct imx6_pm_base iomuxc_base;
0226 struct imx6_pm_base ccm_base;
0227 struct imx6_pm_base gpc_base;
0228 struct imx6_pm_base l2_base;
0229 u32 mmdc_io_num;
0230 u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2];
0231 } __aligned(8);
0232
0233 void imx6_set_int_mem_clk_lpm(bool enable)
0234 {
0235 u32 val = readl_relaxed(ccm_base + CGPR);
0236
0237 val &= ~BM_CGPR_INT_MEM_CLK_LPM;
0238 if (enable)
0239 val |= BM_CGPR_INT_MEM_CLK_LPM;
0240 writel_relaxed(val, ccm_base + CGPR);
0241 }
0242
0243 void imx6_enable_rbc(bool enable)
0244 {
0245 u32 val;
0246
0247
0248
0249
0250
0251 imx_gpc_mask_all();
0252
0253
0254 val = readl_relaxed(ccm_base + CCR);
0255 val &= ~BM_CCR_RBC_EN;
0256 val |= enable ? BM_CCR_RBC_EN : 0;
0257 writel_relaxed(val, ccm_base + CCR);
0258
0259
0260 val = readl_relaxed(ccm_base + CCR);
0261 val &= ~BM_CCR_RBC_BYPASS_COUNT;
0262 val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
0263 writel(val, ccm_base + CCR);
0264
0265
0266
0267
0268
0269
0270 udelay(65);
0271
0272
0273 imx_gpc_restore_all();
0274 }
0275
0276 static void imx6q_enable_wb(bool enable)
0277 {
0278 u32 val;
0279
0280
0281 val = readl_relaxed(ccm_base + CLPCR);
0282 val &= ~BM_CLPCR_WB_PER_AT_LPM;
0283 val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
0284 writel_relaxed(val, ccm_base + CLPCR);
0285
0286
0287 val = readl_relaxed(ccm_base + CCR);
0288 val &= ~BM_CCR_WB_COUNT;
0289 val |= enable ? BM_CCR_WB_COUNT : 0;
0290 writel_relaxed(val, ccm_base + CCR);
0291 }
0292
0293 int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
0294 {
0295 u32 val = readl_relaxed(ccm_base + CLPCR);
0296
0297 val &= ~BM_CLPCR_LPM;
0298 switch (mode) {
0299 case WAIT_CLOCKED:
0300 break;
0301 case WAIT_UNCLOCKED:
0302 val |= 0x1 << BP_CLPCR_LPM;
0303 val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
0304 break;
0305 case STOP_POWER_ON:
0306 val |= 0x2 << BP_CLPCR_LPM;
0307 val &= ~BM_CLPCR_VSTBY;
0308 val &= ~BM_CLPCR_SBYOS;
0309 if (cpu_is_imx6sl())
0310 val |= BM_CLPCR_BYPASS_PMIC_READY;
0311 if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
0312 cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz())
0313 val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
0314 else
0315 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
0316 break;
0317 case WAIT_UNCLOCKED_POWER_OFF:
0318 val |= 0x1 << BP_CLPCR_LPM;
0319 val &= ~BM_CLPCR_VSTBY;
0320 val &= ~BM_CLPCR_SBYOS;
0321 break;
0322 case STOP_POWER_OFF:
0323 val |= 0x2 << BP_CLPCR_LPM;
0324 val |= 0x3 << BP_CLPCR_STBY_COUNT;
0325 val |= BM_CLPCR_VSTBY;
0326 val |= BM_CLPCR_SBYOS;
0327 if (cpu_is_imx6sl() || cpu_is_imx6sx())
0328 val |= BM_CLPCR_BYPASS_PMIC_READY;
0329 if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
0330 cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz())
0331 val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
0332 else
0333 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
0334 break;
0335 default:
0336 return -EINVAL;
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 if (mode != WAIT_CLOCKED)
0354 imx_gpc_hwirq_unmask(0);
0355 writel_relaxed(val, ccm_base + CLPCR);
0356 if (mode != WAIT_CLOCKED)
0357 imx_gpc_hwirq_mask(0);
0358
0359 return 0;
0360 }
0361
0362 static int imx6q_suspend_finish(unsigned long val)
0363 {
0364 if (!imx6_suspend_in_ocram_fn) {
0365 cpu_do_idle();
0366 } else {
0367
0368
0369
0370
0371 local_flush_tlb_all();
0372
0373 if (!((struct imx6_cpu_pm_info *)
0374 suspend_ocram_base)->l2_base.vbase)
0375 flush_cache_all();
0376 imx6_suspend_in_ocram_fn(suspend_ocram_base);
0377 }
0378
0379 return 0;
0380 }
0381
0382 static int imx6q_pm_enter(suspend_state_t state)
0383 {
0384 switch (state) {
0385 case PM_SUSPEND_STANDBY:
0386 imx6_set_lpm(STOP_POWER_ON);
0387 imx6_set_int_mem_clk_lpm(true);
0388 imx_gpc_pre_suspend(false);
0389 if (cpu_is_imx6sl())
0390 imx6sl_set_wait_clk(true);
0391
0392 cpu_do_idle();
0393 if (cpu_is_imx6sl())
0394 imx6sl_set_wait_clk(false);
0395 imx_gpc_post_resume();
0396 imx6_set_lpm(WAIT_CLOCKED);
0397 break;
0398 case PM_SUSPEND_MEM:
0399 imx6_set_lpm(STOP_POWER_OFF);
0400 imx6_set_int_mem_clk_lpm(false);
0401 imx6q_enable_wb(true);
0402
0403
0404
0405
0406 if (!imx6_suspend_in_ocram_fn)
0407 imx6_enable_rbc(true);
0408 imx_gpc_pre_suspend(true);
0409 imx_anatop_pre_suspend();
0410
0411 cpu_suspend(0, imx6q_suspend_finish);
0412 if (cpu_is_imx6q() || cpu_is_imx6dl())
0413 imx_smp_prepare();
0414 imx_anatop_post_resume();
0415 imx_gpc_post_resume();
0416 imx6_enable_rbc(false);
0417 imx6q_enable_wb(false);
0418 imx6_set_int_mem_clk_lpm(true);
0419 imx6_set_lpm(WAIT_CLOCKED);
0420 break;
0421 default:
0422 return -EINVAL;
0423 }
0424
0425 return 0;
0426 }
0427
0428 static int imx6q_pm_valid(suspend_state_t state)
0429 {
0430 return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
0431 }
0432
0433 static const struct platform_suspend_ops imx6q_pm_ops = {
0434 .enter = imx6q_pm_enter,
0435 .valid = imx6q_pm_valid,
0436 };
0437
0438 static int __init imx6_pm_get_base(struct imx6_pm_base *base,
0439 const char *compat)
0440 {
0441 struct device_node *node;
0442 struct resource res;
0443 int ret = 0;
0444
0445 node = of_find_compatible_node(NULL, NULL, compat);
0446 if (!node)
0447 return -ENODEV;
0448
0449 ret = of_address_to_resource(node, 0, &res);
0450 if (ret)
0451 goto put_node;
0452
0453 base->pbase = res.start;
0454 base->vbase = ioremap(res.start, resource_size(&res));
0455 if (!base->vbase)
0456 ret = -ENOMEM;
0457
0458 put_node:
0459 of_node_put(node);
0460 return ret;
0461 }
0462
0463 static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
0464 {
0465 phys_addr_t ocram_pbase;
0466 struct device_node *node;
0467 struct platform_device *pdev;
0468 struct imx6_cpu_pm_info *pm_info;
0469 struct gen_pool *ocram_pool;
0470 unsigned long ocram_base;
0471 int i, ret = 0;
0472 const u32 *mmdc_offset_array;
0473
0474 suspend_set_ops(&imx6q_pm_ops);
0475
0476 if (!socdata) {
0477 pr_warn("%s: invalid argument!\n", __func__);
0478 return -EINVAL;
0479 }
0480
0481 node = of_find_compatible_node(NULL, NULL, "mmio-sram");
0482 if (!node) {
0483 pr_warn("%s: failed to find ocram node!\n", __func__);
0484 return -ENODEV;
0485 }
0486
0487 pdev = of_find_device_by_node(node);
0488 if (!pdev) {
0489 pr_warn("%s: failed to find ocram device!\n", __func__);
0490 ret = -ENODEV;
0491 goto put_node;
0492 }
0493
0494 ocram_pool = gen_pool_get(&pdev->dev, NULL);
0495 if (!ocram_pool) {
0496 pr_warn("%s: ocram pool unavailable!\n", __func__);
0497 ret = -ENODEV;
0498 goto put_device;
0499 }
0500
0501 ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
0502 if (!ocram_base) {
0503 pr_warn("%s: unable to alloc ocram!\n", __func__);
0504 ret = -ENOMEM;
0505 goto put_device;
0506 }
0507
0508 ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
0509
0510 suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
0511 MX6Q_SUSPEND_OCRAM_SIZE, false);
0512
0513 memset(suspend_ocram_base, 0, sizeof(*pm_info));
0514 pm_info = suspend_ocram_base;
0515 pm_info->pbase = ocram_pbase;
0516 pm_info->resume_addr = __pa_symbol(v7_cpu_resume);
0517 pm_info->pm_info_size = sizeof(*pm_info);
0518
0519
0520
0521
0522
0523 pm_info->ccm_base.vbase = ccm_base;
0524
0525 ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
0526 if (ret) {
0527 pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
0528 goto put_device;
0529 }
0530
0531 ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
0532 if (ret) {
0533 pr_warn("%s: failed to get src base %d!\n", __func__, ret);
0534 goto src_map_failed;
0535 }
0536
0537 ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat);
0538 if (ret) {
0539 pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret);
0540 goto iomuxc_map_failed;
0541 }
0542
0543 ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
0544 if (ret) {
0545 pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
0546 goto gpc_map_failed;
0547 }
0548
0549 if (socdata->pl310_compat) {
0550 ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
0551 if (ret) {
0552 pr_warn("%s: failed to get pl310-cache base %d!\n",
0553 __func__, ret);
0554 goto pl310_cache_map_failed;
0555 }
0556 }
0557
0558 pm_info->ddr_type = imx_mmdc_get_ddr_type();
0559 pm_info->mmdc_io_num = socdata->mmdc_io_num;
0560 mmdc_offset_array = socdata->mmdc_io_offset;
0561
0562 for (i = 0; i < pm_info->mmdc_io_num; i++) {
0563 pm_info->mmdc_io_val[i][0] =
0564 mmdc_offset_array[i];
0565 pm_info->mmdc_io_val[i][1] =
0566 readl_relaxed(pm_info->iomuxc_base.vbase +
0567 mmdc_offset_array[i]);
0568 }
0569
0570 imx6_suspend_in_ocram_fn = fncpy(
0571 suspend_ocram_base + sizeof(*pm_info),
0572 &imx6_suspend,
0573 MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
0574
0575 __arm_iomem_set_ro(suspend_ocram_base, MX6Q_SUSPEND_OCRAM_SIZE);
0576
0577 goto put_device;
0578
0579 pl310_cache_map_failed:
0580 iounmap(pm_info->gpc_base.vbase);
0581 gpc_map_failed:
0582 iounmap(pm_info->iomuxc_base.vbase);
0583 iomuxc_map_failed:
0584 iounmap(pm_info->src_base.vbase);
0585 src_map_failed:
0586 iounmap(pm_info->mmdc_base.vbase);
0587 put_device:
0588 put_device(&pdev->dev);
0589 put_node:
0590 of_node_put(node);
0591
0592 return ret;
0593 }
0594
0595 static void __init imx6_pm_common_init(const struct imx6_pm_socdata
0596 *socdata)
0597 {
0598 struct regmap *gpr;
0599 int ret;
0600
0601 WARN_ON(!ccm_base);
0602
0603 if (IS_ENABLED(CONFIG_SUSPEND)) {
0604 ret = imx6q_suspend_init(socdata);
0605 if (ret)
0606 pr_warn("%s: No DDR LPM support with suspend %d!\n",
0607 __func__, ret);
0608 }
0609
0610
0611
0612
0613
0614
0615
0616
0617 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
0618 if (!IS_ERR(gpr))
0619 regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
0620 IMX6Q_GPR1_GINT);
0621 }
0622
0623 static void imx6_pm_stby_poweroff(void)
0624 {
0625 gic_cpu_if_down(0);
0626 imx6_set_lpm(STOP_POWER_OFF);
0627 imx6q_suspend_finish(0);
0628
0629 mdelay(1000);
0630
0631 pr_emerg("Unable to poweroff system\n");
0632 }
0633
0634 static int imx6_pm_stby_poweroff_probe(void)
0635 {
0636 if (pm_power_off) {
0637 pr_warn("%s: pm_power_off already claimed %p %ps!\n",
0638 __func__, pm_power_off, pm_power_off);
0639 return -EBUSY;
0640 }
0641
0642 pm_power_off = imx6_pm_stby_poweroff;
0643 return 0;
0644 }
0645
0646 void __init imx6_pm_ccm_init(const char *ccm_compat)
0647 {
0648 struct device_node *np;
0649 u32 val;
0650
0651 np = of_find_compatible_node(NULL, NULL, ccm_compat);
0652 ccm_base = of_iomap(np, 0);
0653 BUG_ON(!ccm_base);
0654
0655
0656
0657
0658
0659 val = readl_relaxed(ccm_base + CLPCR);
0660 val &= ~BM_CLPCR_LPM;
0661 writel_relaxed(val, ccm_base + CLPCR);
0662
0663 if (of_property_read_bool(np, "fsl,pmic-stby-poweroff"))
0664 imx6_pm_stby_poweroff_probe();
0665
0666 of_node_put(np);
0667 }
0668
0669 void __init imx6q_pm_init(void)
0670 {
0671 imx6_pm_common_init(&imx6q_pm_data);
0672 }
0673
0674 void __init imx6dl_pm_init(void)
0675 {
0676 imx6_pm_common_init(&imx6dl_pm_data);
0677 }
0678
0679 void __init imx6sl_pm_init(void)
0680 {
0681 struct regmap *gpr;
0682
0683 if (cpu_is_imx6sl()) {
0684 imx6_pm_common_init(&imx6sl_pm_data);
0685 } else {
0686 imx6_pm_common_init(&imx6sll_pm_data);
0687 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
0688 if (!IS_ERR(gpr))
0689 regmap_update_bits(gpr, IOMUXC_GPR5,
0690 IMX6SLL_GPR5_AFCG_X_BYPASS_MASK, 0);
0691 }
0692 }
0693
0694 void __init imx6sx_pm_init(void)
0695 {
0696 imx6_pm_common_init(&imx6sx_pm_data);
0697 }
0698
0699 void __init imx6ul_pm_init(void)
0700 {
0701 imx6_pm_common_init(&imx6ul_pm_data);
0702 }