blob: f18389bf26da2a91dc381978e095a33f6c8aa1c4 [file] [log] [blame]
Zeng Zhaominga9ce0be2011-06-28 09:15:47 +08001/*
2 * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
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 as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#include <linux/kernel.h>
20#include <linux/clk.h>
21#include <linux/platform_device.h>
22#include <linux/regulator/consumer.h>
23#include <linux/pmic_external.h>
24#include <asm/io.h>
25#include <mach/hardware.h>
26#include <mach/clock.h>
27#include <asm/proc-fns.h>
28#include <asm/system.h>
Anson Huangcda08922011-07-18 12:54:13 +080029#include "crm_regs.h"
30
31#define SCU_CTRL 0x00
32#define SCU_CONFIG 0x04
33#define SCU_CPU_STATUS 0x08
34#define SCU_INVALIDATE 0x0c
35#define SCU_FPGA_REVISION 0x10
36
37void gpc_enable_wakeup(unsigned int irq)
38{
39 void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
40
41 if ((irq < 32) || (irq > 158))
42 printk(KERN_ERR "Invalid irq number!\n");
43
44 /* Enable wake up source */
45 __raw_writel(~(1 << (irq % 32)),
46 gpc_base + 0x8 + (irq / 32 - 1) * 4);
47
48}
49/* set cpu low power mode before WFI instruction */
50void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
51{
52 void __iomem *scu_base = IO_ADDRESS(SCU_BASE_ADDR);
53 void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
54 u32 scu_cr, ccm_clpcr;
55 int stop_mode = 0;
56
57 scu_cr = __raw_readl(scu_base + SCU_CTRL);
58 ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
59
60 switch (mode) {
61 case WAIT_CLOCKED:
62 break;
63 case WAIT_UNCLOCKED:
64 ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
65 break;
66 case WAIT_UNCLOCKED_POWER_OFF:
67 case STOP_POWER_OFF:
68 if (mode == WAIT_UNCLOCKED_POWER_OFF) {
69 ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
70 ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
71 ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
72 stop_mode = 0;
73 } else {
74 ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
75 ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
76 ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
77 ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
78 ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
79 stop_mode = 1;
80 }
81 /* scu standby enable, scu clk will be
82 * off after all cpu enter WFI */
83 scu_cr |= 0x20;
84 break;
85 case STOP_POWER_ON:
86 ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
87 break;
88 default:
89 printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
90 return;
91 }
92
93 if (stop_mode == 1) {
94 /* Mask all wake up source */
95 __raw_writel(0xFFFFFFFF, gpc_base + 0x8);
96 __raw_writel(0xFFFFFFFF, gpc_base + 0xC);
97 __raw_writel(0xFFFFFFFF, gpc_base + 0x10);
98 __raw_writel(0xFFFFFFFF, gpc_base + 0x14);
99 /* Power down and power up sequence */
100 __raw_writel(0xFFFFFFFF, gpc_base + 0x2a4);
101 __raw_writel(0xFFFFFFFF, gpc_base + 0x2a8);
102
103 gpc_enable_wakeup(MXC_INT_UART4_ANDED);
104 }
105
106 __raw_writel(scu_cr, scu_base + SCU_CTRL);
107 __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
108}
Zeng Zhaominga9ce0be2011-06-28 09:15:47 +0800109
110void arch_idle(void)
111{
112 cpu_do_idle();
113}