aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2013-03-21 10:58:06 -0400
committerShawn Guo <shawn.guo@linaro.org>2013-04-12 07:01:43 -0400
commit263475d4e0b0623fb7a22f8ac0a5c01017eabf20 (patch)
tree9d8ffb5e1df3cf19d0b7881e514f585d6387b546 /arch/arm
parente7b82d645d8b0345508d4b7be85e10f961fbfa3e (diff)
ARM: imx: enable RBC to support anatop LPM mode
RBC is to control whether some ANATOP sub modules can enter lpm mode when SOC is into STOP mode, if RBC is enabled and PMIC_VSTBY_REQ is set, ANATOP will have below behaviors: 1. Digital LDOs(CORE, SOC and PU) are bypassed; 2. Analog LDOs(1P1, 2P5, 3P0) are disabled; As the 2P5 is necessary for DRAM IO pre-drive in STOP mode, so we need to enable weak 2P5 in STOP mode when 2P5 LDO is disabled. For RBC settings, there are some rules as below due to hardware design: 1. All interrupts must be masked during operating RBC registers; 2. At least 2 CKIL(32K) cycles is needed after the RBC setting is changed. Signed-off-by: Anson Huang <b20788@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-imx/anatop.c19
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c43
-rw-r--r--arch/arm/mach-imx/common.h2
-rw-r--r--arch/arm/mach-imx/gpc.c23
4 files changed, 86 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
index b396b92526d3..8b18b3c3bcf0 100644
--- a/arch/arm/mach-imx/anatop.c
+++ b/arch/arm/mach-imx/anatop.c
@@ -19,17 +19,34 @@
19#define REG_SET 0x4 19#define REG_SET 0x4
20#define REG_CLR 0x8 20#define REG_CLR 0x8
21 21
22#define ANADIG_REG_2P5 0x130
22#define ANADIG_REG_CORE 0x140 23#define ANADIG_REG_CORE 0x140
24#define ANADIG_ANA_MISC0 0x150
23#define ANADIG_USB1_CHRG_DETECT 0x1b0 25#define ANADIG_USB1_CHRG_DETECT 0x1b0
24#define ANADIG_USB2_CHRG_DETECT 0x210 26#define ANADIG_USB2_CHRG_DETECT 0x210
25#define ANADIG_DIGPROG 0x260 27#define ANADIG_DIGPROG 0x260
26 28
29#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
27#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000 30#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
31#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000
28#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000 32#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000
29#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000 33#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000
30 34
31static struct regmap *anatop; 35static struct regmap *anatop;
32 36
37static void imx_anatop_enable_weak2p5(bool enable)
38{
39 u32 reg, val;
40
41 regmap_read(anatop, ANADIG_ANA_MISC0, &val);
42
43 /* can only be enabled when stop_mode_config is clear. */
44 reg = ANADIG_REG_2P5;
45 reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
46 REG_SET : REG_CLR;
47 regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
48}
49
33static void imx_anatop_enable_fet_odrive(bool enable) 50static void imx_anatop_enable_fet_odrive(bool enable)
34{ 51{
35 regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR), 52 regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR),
@@ -38,12 +55,14 @@ static void imx_anatop_enable_fet_odrive(bool enable)
38 55
39void imx_anatop_pre_suspend(void) 56void imx_anatop_pre_suspend(void)
40{ 57{
58 imx_anatop_enable_weak2p5(true);
41 imx_anatop_enable_fet_odrive(true); 59 imx_anatop_enable_fet_odrive(true);
42} 60}
43 61
44void imx_anatop_post_resume(void) 62void imx_anatop_post_resume(void)
45{ 63{
46 imx_anatop_enable_fet_odrive(false); 64 imx_anatop_enable_fet_odrive(false);
65 imx_anatop_enable_weak2p5(false);
47} 66}
48 67
49void imx_anatop_usb_chrg_detect_disable(void) 68void imx_anatop_usb_chrg_detect_disable(void)
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 262b7b6c79aa..23b799a51e6c 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -14,6 +14,7 @@
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/clk.h> 15#include <linux/clk.h>
16#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/delay.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include <linux/io.h> 19#include <linux/io.h>
19#include <linux/of.h> 20#include <linux/of.h>
@@ -25,6 +26,8 @@
25 26
26#define CCR 0x0 27#define CCR 0x0
27#define BM_CCR_WB_COUNT (0x7 << 16) 28#define BM_CCR_WB_COUNT (0x7 << 16)
29#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
30#define BM_CCR_RBC_EN (0x1 << 27)
28 31
29#define CCGR0 0x68 32#define CCGR0 0x68
30#define CCGR1 0x6c 33#define CCGR1 0x6c
@@ -70,6 +73,44 @@ void imx6q_set_chicken_bit(void)
70 writel_relaxed(val, ccm_base + CGPR); 73 writel_relaxed(val, ccm_base + CGPR);
71} 74}
72 75
76static void imx6q_enable_rbc(bool enable)
77{
78 u32 val;
79 static bool last_rbc_mode;
80
81 if (last_rbc_mode == enable)
82 return;
83 /*
84 * need to mask all interrupts in GPC before
85 * operating RBC configurations
86 */
87 imx_gpc_mask_all();
88
89 /* configure RBC enable bit */
90 val = readl_relaxed(ccm_base + CCR);
91 val &= ~BM_CCR_RBC_EN;
92 val |= enable ? BM_CCR_RBC_EN : 0;
93 writel_relaxed(val, ccm_base + CCR);
94
95 /* configure RBC count */
96 val = readl_relaxed(ccm_base + CCR);
97 val &= ~BM_CCR_RBC_BYPASS_COUNT;
98 val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
99 writel(val, ccm_base + CCR);
100
101 /*
102 * need to delay at least 2 cycles of CKIL(32K)
103 * due to hardware design requirement, which is
104 * ~61us, here we use 65us for safe
105 */
106 udelay(65);
107
108 /* restore GPC interrupt mask settings */
109 imx_gpc_restore_all();
110
111 last_rbc_mode = enable;
112}
113
73static void imx6q_enable_wb(bool enable) 114static void imx6q_enable_wb(bool enable)
74{ 115{
75 u32 val; 116 u32 val;
@@ -101,6 +142,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
101 switch (mode) { 142 switch (mode) {
102 case WAIT_CLOCKED: 143 case WAIT_CLOCKED:
103 imx6q_enable_wb(false); 144 imx6q_enable_wb(false);
145 imx6q_enable_rbc(false);
104 break; 146 break;
105 case WAIT_UNCLOCKED: 147 case WAIT_UNCLOCKED:
106 val |= 0x1 << BP_CLPCR_LPM; 148 val |= 0x1 << BP_CLPCR_LPM;
@@ -120,6 +162,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
120 val |= BM_CLPCR_VSTBY; 162 val |= BM_CLPCR_VSTBY;
121 val |= BM_CLPCR_SBYOS; 163 val |= BM_CLPCR_SBYOS;
122 imx6q_enable_wb(true); 164 imx6q_enable_wb(true);
165 imx6q_enable_rbc(true);
123 break; 166 break;
124 default: 167 default:
125 return -EINVAL; 168 return -EINVAL;
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index d557bf383289..bcb11b1751d8 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -128,6 +128,8 @@ extern void imx_src_prepare_restart(void);
128extern void imx_gpc_init(void); 128extern void imx_gpc_init(void);
129extern void imx_gpc_pre_suspend(void); 129extern void imx_gpc_pre_suspend(void);
130extern void imx_gpc_post_resume(void); 130extern void imx_gpc_post_resume(void);
131extern void imx_gpc_mask_all(void);
132extern void imx_gpc_restore_all(void);
131extern void imx_anatop_init(void); 133extern void imx_anatop_init(void);
132extern void imx_anatop_pre_suspend(void); 134extern void imx_anatop_pre_suspend(void);
133extern void imx_anatop_post_resume(void); 135extern void imx_anatop_post_resume(void);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index a96ccc7f5012..c20445c56032 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2011 Freescale Semiconductor, Inc. 2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd. 3 * Copyright 2011 Linaro Ltd.
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -68,6 +68,27 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
68 return 0; 68 return 0;
69} 69}
70 70
71void imx_gpc_mask_all(void)
72{
73 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
74 int i;
75
76 for (i = 0; i < IMR_NUM; i++) {
77 gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
78 writel_relaxed(~0, reg_imr1 + i * 4);
79 }
80
81}
82
83void imx_gpc_restore_all(void)
84{
85 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
86 int i;
87
88 for (i = 0; i < IMR_NUM; i++)
89 writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
90}
91
71static void imx_gpc_irq_unmask(struct irq_data *d) 92static void imx_gpc_irq_unmask(struct irq_data *d)
72{ 93{
73 void __iomem *reg; 94 void __iomem *reg;