aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-davinci/cpuidle.c84
-rw-r--r--drivers/idle/intel_idle.c75
2 files changed, 51 insertions, 108 deletions
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index 9107691adbdb..5ac9e9384b15 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -25,35 +25,44 @@
25 25
26#define DAVINCI_CPUIDLE_MAX_STATES 2 26#define DAVINCI_CPUIDLE_MAX_STATES 2
27 27
28struct davinci_ops { 28static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);
29 void (*enter) (u32 flags); 29static void __iomem *ddr2_reg_base;
30 void (*exit) (u32 flags); 30static bool ddr2_pdown;
31 u32 flags; 31
32}; 32static void davinci_save_ddr_power(int enter, bool pdown)
33{
34 u32 val;
35
36 val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET);
37
38 if (enter) {
39 if (pdown)
40 val |= DDR2_SRPD_BIT;
41 else
42 val &= ~DDR2_SRPD_BIT;
43 val |= DDR2_LPMODEN_BIT;
44 } else {
45 val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT);
46 }
47
48 __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET);
49}
33 50
34/* Actual code that puts the SoC in different idle states */ 51/* Actual code that puts the SoC in different idle states */
35static int davinci_enter_idle(struct cpuidle_device *dev, 52static int davinci_enter_idle(struct cpuidle_device *dev,
36 struct cpuidle_driver *drv, 53 struct cpuidle_driver *drv,
37 int index) 54 int index)
38{ 55{
39 struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; 56 davinci_save_ddr_power(1, ddr2_pdown);
40 struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
41
42 if (ops && ops->enter)
43 ops->enter(ops->flags);
44 57
45 index = cpuidle_wrap_enter(dev, drv, index, 58 index = cpuidle_wrap_enter(dev, drv, index,
46 arm_cpuidle_simple_enter); 59 arm_cpuidle_simple_enter);
47 60
48 if (ops && ops->exit) 61 davinci_save_ddr_power(0, ddr2_pdown);
49 ops->exit(ops->flags);
50 62
51 return index; 63 return index;
52} 64}
53 65
54/* fields in davinci_ops.flags */
55#define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0)
56
57static struct cpuidle_driver davinci_idle_driver = { 66static struct cpuidle_driver davinci_idle_driver = {
58 .name = "cpuidle-davinci", 67 .name = "cpuidle-davinci",
59 .owner = THIS_MODULE, 68 .owner = THIS_MODULE,
@@ -70,45 +79,6 @@ static struct cpuidle_driver davinci_idle_driver = {
70 .state_count = DAVINCI_CPUIDLE_MAX_STATES, 79 .state_count = DAVINCI_CPUIDLE_MAX_STATES,
71}; 80};
72 81
73static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);
74static void __iomem *ddr2_reg_base;
75
76static void davinci_save_ddr_power(int enter, bool pdown)
77{
78 u32 val;
79
80 val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET);
81
82 if (enter) {
83 if (pdown)
84 val |= DDR2_SRPD_BIT;
85 else
86 val &= ~DDR2_SRPD_BIT;
87 val |= DDR2_LPMODEN_BIT;
88 } else {
89 val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT);
90 }
91
92 __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET);
93}
94
95static void davinci_c2state_enter(u32 flags)
96{
97 davinci_save_ddr_power(1, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN));
98}
99
100static void davinci_c2state_exit(u32 flags)
101{
102 davinci_save_ddr_power(0, !!(flags & DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN));
103}
104
105static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
106 [1] = {
107 .enter = davinci_c2state_enter,
108 .exit = davinci_c2state_exit,
109 },
110};
111
112static int __init davinci_cpuidle_probe(struct platform_device *pdev) 82static int __init davinci_cpuidle_probe(struct platform_device *pdev)
113{ 83{
114 int ret; 84 int ret;
@@ -124,11 +94,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
124 94
125 ddr2_reg_base = pdata->ddr2_ctlr_base; 95 ddr2_reg_base = pdata->ddr2_ctlr_base;
126 96
127 if (pdata->ddr2_pdown) 97 ddr2_pdown = pdata->ddr2_pdown;
128 davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
129 cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
130
131 device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
132 98
133 ret = cpuidle_register_driver(&davinci_idle_driver); 99 ret = cpuidle_register_driver(&davinci_idle_driver);
134 if (ret) { 100 if (ret) {
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 2df9414a72f7..b2cf489ba3e1 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -109,6 +109,16 @@ static struct cpuidle_state *cpuidle_state_table;
109#define CPUIDLE_FLAG_TLB_FLUSHED 0x10000 109#define CPUIDLE_FLAG_TLB_FLUSHED 0x10000
110 110
111/* 111/*
112 * MWAIT takes an 8-bit "hint" in EAX "suggesting"
113 * the C-state (top nibble) and sub-state (bottom nibble)
114 * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc.
115 *
116 * We store the hint at the top of our "flags" for each state.
117 */
118#define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
119#define MWAIT2flg(eax) ((eax & 0xFF) << 24)
120
121/*
112 * States are indexed by the cstate number, 122 * States are indexed by the cstate number,
113 * which is also the index into the MWAIT hint array. 123 * which is also the index into the MWAIT hint array.
114 * Thus C0 is a dummy. 124 * Thus C0 is a dummy.
@@ -118,21 +128,21 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
118 { /* MWAIT C1 */ 128 { /* MWAIT C1 */
119 .name = "C1-NHM", 129 .name = "C1-NHM",
120 .desc = "MWAIT 0x00", 130 .desc = "MWAIT 0x00",
121 .flags = CPUIDLE_FLAG_TIME_VALID, 131 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
122 .exit_latency = 3, 132 .exit_latency = 3,
123 .target_residency = 6, 133 .target_residency = 6,
124 .enter = &intel_idle }, 134 .enter = &intel_idle },
125 { /* MWAIT C2 */ 135 { /* MWAIT C2 */
126 .name = "C3-NHM", 136 .name = "C3-NHM",
127 .desc = "MWAIT 0x10", 137 .desc = "MWAIT 0x10",
128 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 138 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
129 .exit_latency = 20, 139 .exit_latency = 20,
130 .target_residency = 80, 140 .target_residency = 80,
131 .enter = &intel_idle }, 141 .enter = &intel_idle },
132 { /* MWAIT C3 */ 142 { /* MWAIT C3 */
133 .name = "C6-NHM", 143 .name = "C6-NHM",
134 .desc = "MWAIT 0x20", 144 .desc = "MWAIT 0x20",
135 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 145 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
136 .exit_latency = 200, 146 .exit_latency = 200,
137 .target_residency = 800, 147 .target_residency = 800,
138 .enter = &intel_idle }, 148 .enter = &intel_idle },
@@ -143,28 +153,28 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
143 { /* MWAIT C1 */ 153 { /* MWAIT C1 */
144 .name = "C1-SNB", 154 .name = "C1-SNB",
145 .desc = "MWAIT 0x00", 155 .desc = "MWAIT 0x00",
146 .flags = CPUIDLE_FLAG_TIME_VALID, 156 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
147 .exit_latency = 1, 157 .exit_latency = 1,
148 .target_residency = 1, 158 .target_residency = 1,
149 .enter = &intel_idle }, 159 .enter = &intel_idle },
150 { /* MWAIT C2 */ 160 { /* MWAIT C2 */
151 .name = "C3-SNB", 161 .name = "C3-SNB",
152 .desc = "MWAIT 0x10", 162 .desc = "MWAIT 0x10",
153 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 163 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
154 .exit_latency = 80, 164 .exit_latency = 80,
155 .target_residency = 211, 165 .target_residency = 211,
156 .enter = &intel_idle }, 166 .enter = &intel_idle },
157 { /* MWAIT C3 */ 167 { /* MWAIT C3 */
158 .name = "C6-SNB", 168 .name = "C6-SNB",
159 .desc = "MWAIT 0x20", 169 .desc = "MWAIT 0x20",
160 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 170 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
161 .exit_latency = 104, 171 .exit_latency = 104,
162 .target_residency = 345, 172 .target_residency = 345,
163 .enter = &intel_idle }, 173 .enter = &intel_idle },
164 { /* MWAIT C4 */ 174 { /* MWAIT C4 */
165 .name = "C7-SNB", 175 .name = "C7-SNB",
166 .desc = "MWAIT 0x30", 176 .desc = "MWAIT 0x30",
167 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 177 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
168 .exit_latency = 109, 178 .exit_latency = 109,
169 .target_residency = 345, 179 .target_residency = 345,
170 .enter = &intel_idle }, 180 .enter = &intel_idle },
@@ -175,28 +185,28 @@ static struct cpuidle_state ivb_cstates[MWAIT_MAX_NUM_CSTATES] = {
175 { /* MWAIT C1 */ 185 { /* MWAIT C1 */
176 .name = "C1-IVB", 186 .name = "C1-IVB",
177 .desc = "MWAIT 0x00", 187 .desc = "MWAIT 0x00",
178 .flags = CPUIDLE_FLAG_TIME_VALID, 188 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
179 .exit_latency = 1, 189 .exit_latency = 1,
180 .target_residency = 1, 190 .target_residency = 1,
181 .enter = &intel_idle }, 191 .enter = &intel_idle },
182 { /* MWAIT C2 */ 192 { /* MWAIT C2 */
183 .name = "C3-IVB", 193 .name = "C3-IVB",
184 .desc = "MWAIT 0x10", 194 .desc = "MWAIT 0x10",
185 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 195 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
186 .exit_latency = 59, 196 .exit_latency = 59,
187 .target_residency = 156, 197 .target_residency = 156,
188 .enter = &intel_idle }, 198 .enter = &intel_idle },
189 { /* MWAIT C3 */ 199 { /* MWAIT C3 */
190 .name = "C6-IVB", 200 .name = "C6-IVB",
191 .desc = "MWAIT 0x20", 201 .desc = "MWAIT 0x20",
192 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 202 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
193 .exit_latency = 80, 203 .exit_latency = 80,
194 .target_residency = 300, 204 .target_residency = 300,
195 .enter = &intel_idle }, 205 .enter = &intel_idle },
196 { /* MWAIT C4 */ 206 { /* MWAIT C4 */
197 .name = "C7-IVB", 207 .name = "C7-IVB",
198 .desc = "MWAIT 0x30", 208 .desc = "MWAIT 0x30",
199 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 209 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
200 .exit_latency = 87, 210 .exit_latency = 87,
201 .target_residency = 300, 211 .target_residency = 300,
202 .enter = &intel_idle }, 212 .enter = &intel_idle },
@@ -207,14 +217,14 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
207 { /* MWAIT C1 */ 217 { /* MWAIT C1 */
208 .name = "C1-ATM", 218 .name = "C1-ATM",
209 .desc = "MWAIT 0x00", 219 .desc = "MWAIT 0x00",
210 .flags = CPUIDLE_FLAG_TIME_VALID, 220 .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
211 .exit_latency = 1, 221 .exit_latency = 1,
212 .target_residency = 4, 222 .target_residency = 4,
213 .enter = &intel_idle }, 223 .enter = &intel_idle },
214 { /* MWAIT C2 */ 224 { /* MWAIT C2 */
215 .name = "C2-ATM", 225 .name = "C2-ATM",
216 .desc = "MWAIT 0x10", 226 .desc = "MWAIT 0x10",
217 .flags = CPUIDLE_FLAG_TIME_VALID, 227 .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID,
218 .exit_latency = 20, 228 .exit_latency = 20,
219 .target_residency = 80, 229 .target_residency = 80,
220 .enter = &intel_idle }, 230 .enter = &intel_idle },
@@ -222,7 +232,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
222 { /* MWAIT C4 */ 232 { /* MWAIT C4 */
223 .name = "C4-ATM", 233 .name = "C4-ATM",
224 .desc = "MWAIT 0x30", 234 .desc = "MWAIT 0x30",
225 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 235 .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
226 .exit_latency = 100, 236 .exit_latency = 100,
227 .target_residency = 400, 237 .target_residency = 400,
228 .enter = &intel_idle }, 238 .enter = &intel_idle },
@@ -230,41 +240,12 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
230 { /* MWAIT C6 */ 240 { /* MWAIT C6 */
231 .name = "C6-ATM", 241 .name = "C6-ATM",
232 .desc = "MWAIT 0x52", 242 .desc = "MWAIT 0x52",
233 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 243 .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
234 .exit_latency = 140, 244 .exit_latency = 140,
235 .target_residency = 560, 245 .target_residency = 560,
236 .enter = &intel_idle }, 246 .enter = &intel_idle },
237}; 247};
238 248
239static long get_driver_data(int cstate)
240{
241 int driver_data;
242 switch (cstate) {
243
244 case 1: /* MWAIT C1 */
245 driver_data = 0x00;
246 break;
247 case 2: /* MWAIT C2 */
248 driver_data = 0x10;
249 break;
250 case 3: /* MWAIT C3 */
251 driver_data = 0x20;
252 break;
253 case 4: /* MWAIT C4 */
254 driver_data = 0x30;
255 break;
256 case 5: /* MWAIT C5 */
257 driver_data = 0x40;
258 break;
259 case 6: /* MWAIT C6 */
260 driver_data = 0x52;
261 break;
262 default:
263 driver_data = 0x00;
264 }
265 return driver_data;
266}
267
268/** 249/**
269 * intel_idle 250 * intel_idle
270 * @dev: cpuidle_device 251 * @dev: cpuidle_device
@@ -278,8 +259,7 @@ static int intel_idle(struct cpuidle_device *dev,
278{ 259{
279 unsigned long ecx = 1; /* break on interrupt flag */ 260 unsigned long ecx = 1; /* break on interrupt flag */
280 struct cpuidle_state *state = &drv->states[index]; 261 struct cpuidle_state *state = &drv->states[index];
281 struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; 262 unsigned long eax = flg2MWAIT(state->flags);
282 unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
283 unsigned int cstate; 263 unsigned int cstate;
284 int cpu = smp_processor_id(); 264 int cpu = smp_processor_id();
285 265
@@ -558,9 +538,6 @@ static int intel_idle_cpu_init(int cpu)
558 if (cpuidle_state_table[cstate].enter == NULL) 538 if (cpuidle_state_table[cstate].enter == NULL)
559 continue; 539 continue;
560 540
561 dev->states_usage[dev->state_count].driver_data =
562 (void *)get_driver_data(cstate);
563
564 dev->state_count += 1; 541 dev->state_count += 1;
565 } 542 }
566 543