This source file includes following definitions.
- imx6_set_int_mem_clk_lpm
- imx6_enable_rbc
- imx6q_enable_wb
- imx6_set_lpm
- imx6q_suspend_finish
- imx6q_pm_enter
- imx6q_pm_valid
- imx6_pm_get_base
- imx6q_suspend_init
- imx6_pm_common_init
- imx6_pm_stby_poweroff
- imx6_pm_stby_poweroff_probe
- imx6_pm_ccm_init
- imx6q_pm_init
- imx6dl_pm_init
- imx6sl_pm_init
- imx6sx_pm_init
- imx6ul_pm_init
   1 
   2 
   3 
   4 
   5 
   6 
   7 #include <linux/delay.h>
   8 #include <linux/init.h>
   9 #include <linux/io.h>
  10 #include <linux/irq.h>
  11 #include <linux/genalloc.h>
  12 #include <linux/mfd/syscon.h>
  13 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
  14 #include <linux/of.h>
  15 #include <linux/of_address.h>
  16 #include <linux/of_platform.h>
  17 #include <linux/regmap.h>
  18 #include <linux/suspend.h>
  19 #include <asm/cacheflush.h>
  20 #include <asm/fncpy.h>
  21 #include <asm/proc-fns.h>
  22 #include <asm/suspend.h>
  23 #include <asm/tlb.h>
  24 
  25 #include "common.h"
  26 #include "hardware.h"
  27 
  28 #define CCR                             0x0
  29 #define BM_CCR_WB_COUNT                 (0x7 << 16)
  30 #define BM_CCR_RBC_BYPASS_COUNT         (0x3f << 21)
  31 #define BM_CCR_RBC_EN                   (0x1 << 27)
  32 
  33 #define CLPCR                           0x54
  34 #define BP_CLPCR_LPM                    0
  35 #define BM_CLPCR_LPM                    (0x3 << 0)
  36 #define BM_CLPCR_BYPASS_PMIC_READY      (0x1 << 2)
  37 #define BM_CLPCR_ARM_CLK_DIS_ON_LPM     (0x1 << 5)
  38 #define BM_CLPCR_SBYOS                  (0x1 << 6)
  39 #define BM_CLPCR_DIS_REF_OSC            (0x1 << 7)
  40 #define BM_CLPCR_VSTBY                  (0x1 << 8)
  41 #define BP_CLPCR_STBY_COUNT             9
  42 #define BM_CLPCR_STBY_COUNT             (0x3 << 9)
  43 #define BM_CLPCR_COSC_PWRDOWN           (0x1 << 11)
  44 #define BM_CLPCR_WB_PER_AT_LPM          (0x1 << 16)
  45 #define BM_CLPCR_WB_CORE_AT_LPM         (0x1 << 17)
  46 #define BM_CLPCR_BYP_MMDC_CH0_LPM_HS    (0x1 << 19)
  47 #define BM_CLPCR_BYP_MMDC_CH1_LPM_HS    (0x1 << 21)
  48 #define BM_CLPCR_MASK_CORE0_WFI         (0x1 << 22)
  49 #define BM_CLPCR_MASK_CORE1_WFI         (0x1 << 23)
  50 #define BM_CLPCR_MASK_CORE2_WFI         (0x1 << 24)
  51 #define BM_CLPCR_MASK_CORE3_WFI         (0x1 << 25)
  52 #define BM_CLPCR_MASK_SCU_IDLE          (0x1 << 26)
  53 #define BM_CLPCR_MASK_L2CC_IDLE         (0x1 << 27)
  54 
  55 #define CGPR                            0x64
  56 #define BM_CGPR_INT_MEM_CLK_LPM         (0x1 << 17)
  57 
  58 #define MX6Q_SUSPEND_OCRAM_SIZE         0x1000
  59 #define MX6_MAX_MMDC_IO_NUM             33
  60 
  61 static void __iomem *ccm_base;
  62 static void __iomem *suspend_ocram_base;
  63 static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 struct imx6_pm_base {
  80         phys_addr_t pbase;
  81         void __iomem *vbase;
  82 };
  83 
  84 struct imx6_pm_socdata {
  85         u32 ddr_type;
  86         const char *mmdc_compat;
  87         const char *src_compat;
  88         const char *iomuxc_compat;
  89         const char *gpc_compat;
  90         const char *pl310_compat;
  91         const u32 mmdc_io_num;
  92         const u32 *mmdc_io_offset;
  93 };
  94 
  95 static const u32 imx6q_mmdc_io_offset[] __initconst = {
  96         0x5ac, 0x5b4, 0x528, 0x520, 
  97         0x514, 0x510, 0x5bc, 0x5c4, 
  98         0x56c, 0x578, 0x588, 0x594, 
  99         0x5a8, 0x5b0, 0x524, 0x51c, 
 100         0x518, 0x50c, 0x5b8, 0x5c0, 
 101         0x784, 0x788, 0x794, 0x79c, 
 102         0x7a0, 0x7a4, 0x7a8, 0x748, 
 103         0x59c, 0x5a0, 0x750, 0x774, 
 104         0x74c,                      
 105 };
 106 
 107 static const u32 imx6dl_mmdc_io_offset[] __initconst = {
 108         0x470, 0x474, 0x478, 0x47c, 
 109         0x480, 0x484, 0x488, 0x48c, 
 110         0x464, 0x490, 0x4ac, 0x4b0, 
 111         0x4bc, 0x4c0, 0x4c4, 0x4c8, 
 112         0x4cc, 0x4d0, 0x4d4, 0x4d8, 
 113         0x764, 0x770, 0x778, 0x77c, 
 114         0x780, 0x784, 0x78c, 0x748, 
 115         0x4b4, 0x4b8, 0x750, 0x760, 
 116         0x74c,                      
 117 };
 118 
 119 static const u32 imx6sl_mmdc_io_offset[] __initconst = {
 120         0x30c, 0x310, 0x314, 0x318, 
 121         0x5c4, 0x5cc, 0x5d4, 0x5d8, 
 122         0x300, 0x31c, 0x338, 0x5ac, 
 123         0x33c, 0x340, 0x5b0, 0x5c0, 
 124         0x330, 0x334, 0x320,        
 125 };
 126 
 127 static const u32 imx6sll_mmdc_io_offset[] __initconst = {
 128         0x294, 0x298, 0x29c, 0x2a0, 
 129         0x544, 0x54c, 0x554, 0x558, 
 130         0x530, 0x540, 0x2ac, 0x52c, 
 131         0x2a4, 0x2a8,               
 132 };
 133 
 134 static const u32 imx6sx_mmdc_io_offset[] __initconst = {
 135         0x2ec, 0x2f0, 0x2f4, 0x2f8, 
 136         0x60c, 0x610, 0x61c, 0x620, 
 137         0x300, 0x2fc, 0x32c, 0x5f4, 
 138         0x310, 0x314, 0x5f8, 0x608, 
 139         0x330, 0x334, 0x338, 0x33c, 
 140 };
 141 
 142 static const u32 imx6ul_mmdc_io_offset[] __initconst = {
 143         0x244, 0x248, 0x24c, 0x250, 
 144         0x27c, 0x498, 0x4a4, 0x490, 
 145         0x280, 0x284, 0x260, 0x264, 
 146         0x494, 0x4b0,               
 147 };
 148 
 149 static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
 150         .mmdc_compat = "fsl,imx6q-mmdc",
 151         .src_compat = "fsl,imx6q-src",
 152         .iomuxc_compat = "fsl,imx6q-iomuxc",
 153         .gpc_compat = "fsl,imx6q-gpc",
 154         .pl310_compat = "arm,pl310-cache",
 155         .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
 156         .mmdc_io_offset = imx6q_mmdc_io_offset,
 157 };
 158 
 159 static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
 160         .mmdc_compat = "fsl,imx6q-mmdc",
 161         .src_compat = "fsl,imx6q-src",
 162         .iomuxc_compat = "fsl,imx6dl-iomuxc",
 163         .gpc_compat = "fsl,imx6q-gpc",
 164         .pl310_compat = "arm,pl310-cache",
 165         .mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
 166         .mmdc_io_offset = imx6dl_mmdc_io_offset,
 167 };
 168 
 169 static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
 170         .mmdc_compat = "fsl,imx6sl-mmdc",
 171         .src_compat = "fsl,imx6sl-src",
 172         .iomuxc_compat = "fsl,imx6sl-iomuxc",
 173         .gpc_compat = "fsl,imx6sl-gpc",
 174         .pl310_compat = "arm,pl310-cache",
 175         .mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
 176         .mmdc_io_offset = imx6sl_mmdc_io_offset,
 177 };
 178 
 179 static const struct imx6_pm_socdata imx6sll_pm_data __initconst = {
 180         .mmdc_compat = "fsl,imx6sll-mmdc",
 181         .src_compat = "fsl,imx6sll-src",
 182         .iomuxc_compat = "fsl,imx6sll-iomuxc",
 183         .gpc_compat = "fsl,imx6sll-gpc",
 184         .pl310_compat = "arm,pl310-cache",
 185         .mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset),
 186         .mmdc_io_offset = imx6sll_mmdc_io_offset,
 187 };
 188 
 189 static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
 190         .mmdc_compat = "fsl,imx6sx-mmdc",
 191         .src_compat = "fsl,imx6sx-src",
 192         .iomuxc_compat = "fsl,imx6sx-iomuxc",
 193         .gpc_compat = "fsl,imx6sx-gpc",
 194         .pl310_compat = "arm,pl310-cache",
 195         .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
 196         .mmdc_io_offset = imx6sx_mmdc_io_offset,
 197 };
 198 
 199 static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
 200         .mmdc_compat = "fsl,imx6ul-mmdc",
 201         .src_compat = "fsl,imx6ul-src",
 202         .iomuxc_compat = "fsl,imx6ul-iomuxc",
 203         .gpc_compat = "fsl,imx6ul-gpc",
 204         .pl310_compat = NULL,
 205         .mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset),
 206         .mmdc_io_offset = imx6ul_mmdc_io_offset,
 207 };
 208 
 209 
 210 
 211 
 212 
 213 
 214 
 215 
 216 struct imx6_cpu_pm_info {
 217         phys_addr_t pbase; 
 218         phys_addr_t resume_addr; 
 219         u32 ddr_type;
 220         u32 pm_info_size; 
 221         struct imx6_pm_base mmdc_base;
 222         struct imx6_pm_base src_base;
 223         struct imx6_pm_base iomuxc_base;
 224         struct imx6_pm_base ccm_base;
 225         struct imx6_pm_base gpc_base;
 226         struct imx6_pm_base l2_base;
 227         u32 mmdc_io_num; 
 228         u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; 
 229 } __aligned(8);
 230 
 231 void imx6_set_int_mem_clk_lpm(bool enable)
 232 {
 233         u32 val = readl_relaxed(ccm_base + CGPR);
 234 
 235         val &= ~BM_CGPR_INT_MEM_CLK_LPM;
 236         if (enable)
 237                 val |= BM_CGPR_INT_MEM_CLK_LPM;
 238         writel_relaxed(val, ccm_base + CGPR);
 239 }
 240 
 241 void imx6_enable_rbc(bool enable)
 242 {
 243         u32 val;
 244 
 245         
 246 
 247 
 248 
 249         imx_gpc_mask_all();
 250 
 251         
 252         val = readl_relaxed(ccm_base + CCR);
 253         val &= ~BM_CCR_RBC_EN;
 254         val |= enable ? BM_CCR_RBC_EN : 0;
 255         writel_relaxed(val, ccm_base + CCR);
 256 
 257         
 258         val = readl_relaxed(ccm_base + CCR);
 259         val &= ~BM_CCR_RBC_BYPASS_COUNT;
 260         val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
 261         writel(val, ccm_base + CCR);
 262 
 263         
 264 
 265 
 266 
 267 
 268         udelay(65);
 269 
 270         
 271         imx_gpc_restore_all();
 272 }
 273 
 274 static void imx6q_enable_wb(bool enable)
 275 {
 276         u32 val;
 277 
 278         
 279         val = readl_relaxed(ccm_base + CLPCR);
 280         val &= ~BM_CLPCR_WB_PER_AT_LPM;
 281         val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
 282         writel_relaxed(val, ccm_base + CLPCR);
 283 
 284         
 285         val = readl_relaxed(ccm_base + CCR);
 286         val &= ~BM_CCR_WB_COUNT;
 287         val |= enable ? BM_CCR_WB_COUNT : 0;
 288         writel_relaxed(val, ccm_base + CCR);
 289 }
 290 
 291 int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
 292 {
 293         u32 val = readl_relaxed(ccm_base + CLPCR);
 294 
 295         val &= ~BM_CLPCR_LPM;
 296         switch (mode) {
 297         case WAIT_CLOCKED:
 298                 break;
 299         case WAIT_UNCLOCKED:
 300                 val |= 0x1 << BP_CLPCR_LPM;
 301                 val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
 302                 break;
 303         case STOP_POWER_ON:
 304                 val |= 0x2 << BP_CLPCR_LPM;
 305                 val &= ~BM_CLPCR_VSTBY;
 306                 val &= ~BM_CLPCR_SBYOS;
 307                 if (cpu_is_imx6sl())
 308                         val |= BM_CLPCR_BYPASS_PMIC_READY;
 309                 if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
 310                     cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz())
 311                         val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
 312                 else
 313                         val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
 314                 break;
 315         case WAIT_UNCLOCKED_POWER_OFF:
 316                 val |= 0x1 << BP_CLPCR_LPM;
 317                 val &= ~BM_CLPCR_VSTBY;
 318                 val &= ~BM_CLPCR_SBYOS;
 319                 break;
 320         case STOP_POWER_OFF:
 321                 val |= 0x2 << BP_CLPCR_LPM;
 322                 val |= 0x3 << BP_CLPCR_STBY_COUNT;
 323                 val |= BM_CLPCR_VSTBY;
 324                 val |= BM_CLPCR_SBYOS;
 325                 if (cpu_is_imx6sl() || cpu_is_imx6sx())
 326                         val |= BM_CLPCR_BYPASS_PMIC_READY;
 327                 if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
 328                     cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz())
 329                         val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
 330                 else
 331                         val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
 332                 break;
 333         default:
 334                 return -EINVAL;
 335         }
 336 
 337         
 338 
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 
 351         if (mode != WAIT_CLOCKED)
 352                 imx_gpc_hwirq_unmask(0);
 353         writel_relaxed(val, ccm_base + CLPCR);
 354         if (mode != WAIT_CLOCKED)
 355                 imx_gpc_hwirq_mask(0);
 356 
 357         return 0;
 358 }
 359 
 360 static int imx6q_suspend_finish(unsigned long val)
 361 {
 362         if (!imx6_suspend_in_ocram_fn) {
 363                 cpu_do_idle();
 364         } else {
 365                 
 366 
 367 
 368 
 369                 local_flush_tlb_all();
 370                 
 371                 if (!((struct imx6_cpu_pm_info *)
 372                         suspend_ocram_base)->l2_base.vbase)
 373                         flush_cache_all();
 374                 imx6_suspend_in_ocram_fn(suspend_ocram_base);
 375         }
 376 
 377         return 0;
 378 }
 379 
 380 static int imx6q_pm_enter(suspend_state_t state)
 381 {
 382         switch (state) {
 383         case PM_SUSPEND_STANDBY:
 384                 imx6_set_lpm(STOP_POWER_ON);
 385                 imx6_set_int_mem_clk_lpm(true);
 386                 imx_gpc_pre_suspend(false);
 387                 if (cpu_is_imx6sl())
 388                         imx6sl_set_wait_clk(true);
 389                 
 390                 cpu_do_idle();
 391                 if (cpu_is_imx6sl())
 392                         imx6sl_set_wait_clk(false);
 393                 imx_gpc_post_resume();
 394                 imx6_set_lpm(WAIT_CLOCKED);
 395                 break;
 396         case PM_SUSPEND_MEM:
 397                 imx6_set_lpm(STOP_POWER_OFF);
 398                 imx6_set_int_mem_clk_lpm(false);
 399                 imx6q_enable_wb(true);
 400                 
 401 
 402 
 403 
 404                 if (!imx6_suspend_in_ocram_fn)
 405                         imx6_enable_rbc(true);
 406                 imx_gpc_pre_suspend(true);
 407                 imx_anatop_pre_suspend();
 408                 
 409                 cpu_suspend(0, imx6q_suspend_finish);
 410                 if (cpu_is_imx6q() || cpu_is_imx6dl())
 411                         imx_smp_prepare();
 412                 imx_anatop_post_resume();
 413                 imx_gpc_post_resume();
 414                 imx6_enable_rbc(false);
 415                 imx6q_enable_wb(false);
 416                 imx6_set_int_mem_clk_lpm(true);
 417                 imx6_set_lpm(WAIT_CLOCKED);
 418                 break;
 419         default:
 420                 return -EINVAL;
 421         }
 422 
 423         return 0;
 424 }
 425 
 426 static int imx6q_pm_valid(suspend_state_t state)
 427 {
 428         return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
 429 }
 430 
 431 static const struct platform_suspend_ops imx6q_pm_ops = {
 432         .enter = imx6q_pm_enter,
 433         .valid = imx6q_pm_valid,
 434 };
 435 
 436 static int __init imx6_pm_get_base(struct imx6_pm_base *base,
 437                                 const char *compat)
 438 {
 439         struct device_node *node;
 440         struct resource res;
 441         int ret = 0;
 442 
 443         node = of_find_compatible_node(NULL, NULL, compat);
 444         if (!node)
 445                 return -ENODEV;
 446 
 447         ret = of_address_to_resource(node, 0, &res);
 448         if (ret)
 449                 goto put_node;
 450 
 451         base->pbase = res.start;
 452         base->vbase = ioremap(res.start, resource_size(&res));
 453         if (!base->vbase)
 454                 ret = -ENOMEM;
 455 
 456 put_node:
 457         of_node_put(node);
 458         return ret;
 459 }
 460 
 461 static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
 462 {
 463         phys_addr_t ocram_pbase;
 464         struct device_node *node;
 465         struct platform_device *pdev;
 466         struct imx6_cpu_pm_info *pm_info;
 467         struct gen_pool *ocram_pool;
 468         unsigned long ocram_base;
 469         int i, ret = 0;
 470         const u32 *mmdc_offset_array;
 471 
 472         suspend_set_ops(&imx6q_pm_ops);
 473 
 474         if (!socdata) {
 475                 pr_warn("%s: invalid argument!\n", __func__);
 476                 return -EINVAL;
 477         }
 478 
 479         node = of_find_compatible_node(NULL, NULL, "mmio-sram");
 480         if (!node) {
 481                 pr_warn("%s: failed to find ocram node!\n", __func__);
 482                 return -ENODEV;
 483         }
 484 
 485         pdev = of_find_device_by_node(node);
 486         if (!pdev) {
 487                 pr_warn("%s: failed to find ocram device!\n", __func__);
 488                 ret = -ENODEV;
 489                 goto put_node;
 490         }
 491 
 492         ocram_pool = gen_pool_get(&pdev->dev, NULL);
 493         if (!ocram_pool) {
 494                 pr_warn("%s: ocram pool unavailable!\n", __func__);
 495                 ret = -ENODEV;
 496                 goto put_node;
 497         }
 498 
 499         ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
 500         if (!ocram_base) {
 501                 pr_warn("%s: unable to alloc ocram!\n", __func__);
 502                 ret = -ENOMEM;
 503                 goto put_node;
 504         }
 505 
 506         ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
 507 
 508         suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
 509                 MX6Q_SUSPEND_OCRAM_SIZE, false);
 510 
 511         memset(suspend_ocram_base, 0, sizeof(*pm_info));
 512         pm_info = suspend_ocram_base;
 513         pm_info->pbase = ocram_pbase;
 514         pm_info->resume_addr = __pa_symbol(v7_cpu_resume);
 515         pm_info->pm_info_size = sizeof(*pm_info);
 516 
 517         
 518 
 519 
 520 
 521         pm_info->ccm_base.vbase = ccm_base;
 522 
 523         ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
 524         if (ret) {
 525                 pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
 526                 goto put_node;
 527         }
 528 
 529         ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
 530         if (ret) {
 531                 pr_warn("%s: failed to get src base %d!\n", __func__, ret);
 532                 goto src_map_failed;
 533         }
 534 
 535         ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat);
 536         if (ret) {
 537                 pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret);
 538                 goto iomuxc_map_failed;
 539         }
 540 
 541         ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
 542         if (ret) {
 543                 pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
 544                 goto gpc_map_failed;
 545         }
 546 
 547         if (socdata->pl310_compat) {
 548                 ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
 549                 if (ret) {
 550                         pr_warn("%s: failed to get pl310-cache base %d!\n",
 551                                 __func__, ret);
 552                         goto pl310_cache_map_failed;
 553                 }
 554         }
 555 
 556         pm_info->ddr_type = imx_mmdc_get_ddr_type();
 557         pm_info->mmdc_io_num = socdata->mmdc_io_num;
 558         mmdc_offset_array = socdata->mmdc_io_offset;
 559 
 560         for (i = 0; i < pm_info->mmdc_io_num; i++) {
 561                 pm_info->mmdc_io_val[i][0] =
 562                         mmdc_offset_array[i];
 563                 pm_info->mmdc_io_val[i][1] =
 564                         readl_relaxed(pm_info->iomuxc_base.vbase +
 565                         mmdc_offset_array[i]);
 566         }
 567 
 568         imx6_suspend_in_ocram_fn = fncpy(
 569                 suspend_ocram_base + sizeof(*pm_info),
 570                 &imx6_suspend,
 571                 MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
 572 
 573         goto put_node;
 574 
 575 pl310_cache_map_failed:
 576         iounmap(pm_info->gpc_base.vbase);
 577 gpc_map_failed:
 578         iounmap(pm_info->iomuxc_base.vbase);
 579 iomuxc_map_failed:
 580         iounmap(pm_info->src_base.vbase);
 581 src_map_failed:
 582         iounmap(pm_info->mmdc_base.vbase);
 583 put_node:
 584         of_node_put(node);
 585 
 586         return ret;
 587 }
 588 
 589 static void __init imx6_pm_common_init(const struct imx6_pm_socdata
 590                                         *socdata)
 591 {
 592         struct regmap *gpr;
 593         int ret;
 594 
 595         WARN_ON(!ccm_base);
 596 
 597         if (IS_ENABLED(CONFIG_SUSPEND)) {
 598                 ret = imx6q_suspend_init(socdata);
 599                 if (ret)
 600                         pr_warn("%s: No DDR LPM support with suspend %d!\n",
 601                                 __func__, ret);
 602         }
 603 
 604         
 605 
 606 
 607 
 608 
 609 
 610 
 611         gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 612         if (!IS_ERR(gpr))
 613                 regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
 614                                    IMX6Q_GPR1_GINT);
 615 }
 616 
 617 static void imx6_pm_stby_poweroff(void)
 618 {
 619         imx6_set_lpm(STOP_POWER_OFF);
 620         imx6q_suspend_finish(0);
 621 
 622         mdelay(1000);
 623 
 624         pr_emerg("Unable to poweroff system\n");
 625 }
 626 
 627 static int imx6_pm_stby_poweroff_probe(void)
 628 {
 629         if (pm_power_off) {
 630                 pr_warn("%s: pm_power_off already claimed  %p %ps!\n",
 631                         __func__, pm_power_off, pm_power_off);
 632                 return -EBUSY;
 633         }
 634 
 635         pm_power_off = imx6_pm_stby_poweroff;
 636         return 0;
 637 }
 638 
 639 void __init imx6_pm_ccm_init(const char *ccm_compat)
 640 {
 641         struct device_node *np;
 642         u32 val;
 643 
 644         np = of_find_compatible_node(NULL, NULL, ccm_compat);
 645         ccm_base = of_iomap(np, 0);
 646         BUG_ON(!ccm_base);
 647 
 648         
 649 
 650 
 651 
 652         val = readl_relaxed(ccm_base + CLPCR);
 653         val &= ~BM_CLPCR_LPM;
 654         writel_relaxed(val, ccm_base + CLPCR);
 655 
 656         if (of_property_read_bool(np, "fsl,pmic-stby-poweroff"))
 657                 imx6_pm_stby_poweroff_probe();
 658 }
 659 
 660 void __init imx6q_pm_init(void)
 661 {
 662         imx6_pm_common_init(&imx6q_pm_data);
 663 }
 664 
 665 void __init imx6dl_pm_init(void)
 666 {
 667         imx6_pm_common_init(&imx6dl_pm_data);
 668 }
 669 
 670 void __init imx6sl_pm_init(void)
 671 {
 672         struct regmap *gpr;
 673 
 674         if (cpu_is_imx6sl()) {
 675                 imx6_pm_common_init(&imx6sl_pm_data);
 676         } else {
 677                 imx6_pm_common_init(&imx6sll_pm_data);
 678                 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 679                 if (!IS_ERR(gpr))
 680                         regmap_update_bits(gpr, IOMUXC_GPR5,
 681                                 IMX6SLL_GPR5_AFCG_X_BYPASS_MASK, 0);
 682         }
 683 }
 684 
 685 void __init imx6sx_pm_init(void)
 686 {
 687         imx6_pm_common_init(&imx6sx_pm_data);
 688 }
 689 
 690 void __init imx6ul_pm_init(void)
 691 {
 692         imx6_pm_common_init(&imx6ul_pm_data);
 693 }