diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 1004 |
1 files changed, 857 insertions, 147 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fdf143b405be..1ac5731d45e5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | #include <linux/interrupt.h> | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | #include <acpi/acpi_bus.h> | 36 | #include <acpi/acpi_bus.h> |
36 | #include <acpi/acpi_drivers.h> | 37 | #include <acpi/acpi_drivers.h> |
@@ -49,60 +50,149 @@ ACPI_MODULE_NAME ("acpi_ec") | |||
49 | 50 | ||
50 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 51 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
51 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 52 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
53 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ | ||
52 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ | 54 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ |
53 | 55 | ||
54 | #define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ | 56 | #define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ |
55 | #define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ | 57 | #define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ |
56 | 58 | ||
57 | #define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ | 59 | #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ |
58 | #define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ | ||
59 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 60 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
60 | 61 | ||
62 | #define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ | ||
63 | #define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ | ||
64 | |||
61 | #define ACPI_EC_COMMAND_READ 0x80 | 65 | #define ACPI_EC_COMMAND_READ 0x80 |
62 | #define ACPI_EC_COMMAND_WRITE 0x81 | 66 | #define ACPI_EC_COMMAND_WRITE 0x81 |
67 | #define ACPI_EC_BURST_ENABLE 0x82 | ||
68 | #define ACPI_EC_BURST_DISABLE 0x83 | ||
63 | #define ACPI_EC_COMMAND_QUERY 0x84 | 69 | #define ACPI_EC_COMMAND_QUERY 0x84 |
64 | 70 | ||
65 | static int acpi_ec_add (struct acpi_device *device); | 71 | #define EC_POLLING 0xFF |
72 | #define EC_BURST 0x00 | ||
73 | |||
74 | |||
66 | static int acpi_ec_remove (struct acpi_device *device, int type); | 75 | static int acpi_ec_remove (struct acpi_device *device, int type); |
67 | static int acpi_ec_start (struct acpi_device *device); | 76 | static int acpi_ec_start (struct acpi_device *device); |
68 | static int acpi_ec_stop (struct acpi_device *device, int type); | 77 | static int acpi_ec_stop (struct acpi_device *device, int type); |
78 | static int acpi_ec_burst_add ( struct acpi_device *device); | ||
79 | static int acpi_ec_polling_add ( struct acpi_device *device); | ||
69 | 80 | ||
70 | static struct acpi_driver acpi_ec_driver = { | 81 | static struct acpi_driver acpi_ec_driver = { |
71 | .name = ACPI_EC_DRIVER_NAME, | 82 | .name = ACPI_EC_DRIVER_NAME, |
72 | .class = ACPI_EC_CLASS, | 83 | .class = ACPI_EC_CLASS, |
73 | .ids = ACPI_EC_HID, | 84 | .ids = ACPI_EC_HID, |
74 | .ops = { | 85 | .ops = { |
75 | .add = acpi_ec_add, | 86 | .add = acpi_ec_polling_add, |
76 | .remove = acpi_ec_remove, | 87 | .remove = acpi_ec_remove, |
77 | .start = acpi_ec_start, | 88 | .start = acpi_ec_start, |
78 | .stop = acpi_ec_stop, | 89 | .stop = acpi_ec_stop, |
79 | }, | 90 | }, |
80 | }; | 91 | }; |
81 | 92 | union acpi_ec { | |
82 | struct acpi_ec { | 93 | struct { |
83 | acpi_handle handle; | 94 | u32 mode; |
84 | unsigned long uid; | 95 | acpi_handle handle; |
85 | unsigned long gpe_bit; | 96 | unsigned long uid; |
86 | struct acpi_generic_address status_addr; | 97 | unsigned long gpe_bit; |
87 | struct acpi_generic_address command_addr; | 98 | struct acpi_generic_address status_addr; |
88 | struct acpi_generic_address data_addr; | 99 | struct acpi_generic_address command_addr; |
89 | unsigned long global_lock; | 100 | struct acpi_generic_address data_addr; |
90 | spinlock_t lock; | 101 | unsigned long global_lock; |
102 | } common; | ||
103 | |||
104 | struct { | ||
105 | u32 mode; | ||
106 | acpi_handle handle; | ||
107 | unsigned long uid; | ||
108 | unsigned long gpe_bit; | ||
109 | struct acpi_generic_address status_addr; | ||
110 | struct acpi_generic_address command_addr; | ||
111 | struct acpi_generic_address data_addr; | ||
112 | unsigned long global_lock; | ||
113 | unsigned int expect_event; | ||
114 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ | ||
115 | atomic_t pending_gpe; | ||
116 | struct semaphore sem; | ||
117 | wait_queue_head_t wait; | ||
118 | }burst; | ||
119 | |||
120 | struct { | ||
121 | u32 mode; | ||
122 | acpi_handle handle; | ||
123 | unsigned long uid; | ||
124 | unsigned long gpe_bit; | ||
125 | struct acpi_generic_address status_addr; | ||
126 | struct acpi_generic_address command_addr; | ||
127 | struct acpi_generic_address data_addr; | ||
128 | unsigned long global_lock; | ||
129 | spinlock_t lock; | ||
130 | }polling; | ||
91 | }; | 131 | }; |
92 | 132 | ||
133 | static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event); | ||
134 | static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event); | ||
135 | static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data); | ||
136 | static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data); | ||
137 | static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data); | ||
138 | static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data); | ||
139 | static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data); | ||
140 | static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data); | ||
141 | static void acpi_ec_gpe_polling_query ( void *ec_cxt); | ||
142 | static void acpi_ec_gpe_burst_query ( void *ec_cxt); | ||
143 | static u32 acpi_ec_gpe_polling_handler ( void *data); | ||
144 | static u32 acpi_ec_gpe_burst_handler ( void *data); | ||
145 | static acpi_status __init | ||
146 | acpi_fake_ecdt_polling_callback ( | ||
147 | acpi_handle handle, | ||
148 | u32 Level, | ||
149 | void *context, | ||
150 | void **retval); | ||
151 | |||
152 | static acpi_status __init | ||
153 | acpi_fake_ecdt_burst_callback ( | ||
154 | acpi_handle handle, | ||
155 | u32 Level, | ||
156 | void *context, | ||
157 | void **retval); | ||
158 | |||
159 | static int __init | ||
160 | acpi_ec_polling_get_real_ecdt(void); | ||
161 | static int __init | ||
162 | acpi_ec_burst_get_real_ecdt(void); | ||
93 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 163 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
94 | static struct acpi_ec *ec_ecdt; | 164 | static union acpi_ec *ec_ecdt; |
95 | 165 | ||
96 | /* External interfaces use first EC only, so remember */ | 166 | /* External interfaces use first EC only, so remember */ |
97 | static struct acpi_device *first_ec; | 167 | static struct acpi_device *first_ec; |
168 | static int acpi_ec_polling_mode = EC_POLLING; | ||
98 | 169 | ||
99 | /* -------------------------------------------------------------------------- | 170 | /* -------------------------------------------------------------------------- |
100 | Transaction Management | 171 | Transaction Management |
101 | -------------------------------------------------------------------------- */ | 172 | -------------------------------------------------------------------------- */ |
102 | 173 | ||
174 | static inline u32 acpi_ec_read_status(union acpi_ec *ec) | ||
175 | { | ||
176 | u32 status = 0; | ||
177 | |||
178 | acpi_hw_low_level_read(8, &status, &ec->common.status_addr); | ||
179 | return status; | ||
180 | } | ||
181 | |||
103 | static int | 182 | static int |
104 | acpi_ec_wait ( | 183 | acpi_ec_wait ( |
105 | struct acpi_ec *ec, | 184 | union acpi_ec *ec, |
185 | u8 event) | ||
186 | { | ||
187 | if (acpi_ec_polling_mode) | ||
188 | return acpi_ec_polling_wait (ec, event); | ||
189 | else | ||
190 | return acpi_ec_burst_wait (ec, event); | ||
191 | } | ||
192 | |||
193 | static int | ||
194 | acpi_ec_polling_wait ( | ||
195 | union acpi_ec *ec, | ||
106 | u8 event) | 196 | u8 event) |
107 | { | 197 | { |
108 | u32 acpi_ec_status = 0; | 198 | u32 acpi_ec_status = 0; |
@@ -115,7 +205,7 @@ acpi_ec_wait ( | |||
115 | switch (event) { | 205 | switch (event) { |
116 | case ACPI_EC_EVENT_OBF: | 206 | case ACPI_EC_EVENT_OBF: |
117 | do { | 207 | do { |
118 | acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); | 208 | acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); |
119 | if (acpi_ec_status & ACPI_EC_FLAG_OBF) | 209 | if (acpi_ec_status & ACPI_EC_FLAG_OBF) |
120 | return 0; | 210 | return 0; |
121 | udelay(ACPI_EC_UDELAY); | 211 | udelay(ACPI_EC_UDELAY); |
@@ -123,7 +213,7 @@ acpi_ec_wait ( | |||
123 | break; | 213 | break; |
124 | case ACPI_EC_EVENT_IBE: | 214 | case ACPI_EC_EVENT_IBE: |
125 | do { | 215 | do { |
126 | acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); | 216 | acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); |
127 | if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) | 217 | if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) |
128 | return 0; | 218 | return 0; |
129 | udelay(ACPI_EC_UDELAY); | 219 | udelay(ACPI_EC_UDELAY); |
@@ -135,11 +225,129 @@ acpi_ec_wait ( | |||
135 | 225 | ||
136 | return -ETIME; | 226 | return -ETIME; |
137 | } | 227 | } |
228 | static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) | ||
229 | { | ||
230 | int result = 0; | ||
231 | |||
232 | ACPI_FUNCTION_TRACE("acpi_ec_wait"); | ||
233 | |||
234 | ec->burst.expect_event = event; | ||
235 | smp_mb(); | ||
236 | |||
237 | result = wait_event_interruptible_timeout(ec->burst.wait, | ||
238 | !ec->burst.expect_event, | ||
239 | msecs_to_jiffies(ACPI_EC_DELAY)); | ||
240 | |||
241 | ec->burst.expect_event = 0; | ||
242 | smp_mb(); | ||
243 | |||
244 | if (result < 0){ | ||
245 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR," result = %d ", result)); | ||
246 | return_VALUE(result); | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Verify that the event in question has actually happened by | ||
251 | * querying EC status. Do the check even if operation timed-out | ||
252 | * to make sure that we did not miss interrupt. | ||
253 | */ | ||
254 | switch (event) { | ||
255 | case ACPI_EC_EVENT_OBF: | ||
256 | if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) | ||
257 | return_VALUE(0); | ||
258 | break; | ||
259 | |||
260 | case ACPI_EC_EVENT_IBE: | ||
261 | if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) | ||
262 | return_VALUE(0); | ||
263 | break; | ||
264 | } | ||
265 | |||
266 | return_VALUE(-ETIME); | ||
267 | } | ||
268 | |||
269 | |||
270 | |||
271 | static int | ||
272 | acpi_ec_enter_burst_mode ( | ||
273 | union acpi_ec *ec) | ||
274 | { | ||
275 | u32 tmp = 0; | ||
276 | int status = 0; | ||
277 | |||
278 | ACPI_FUNCTION_TRACE("acpi_ec_enter_burst_mode"); | ||
279 | |||
280 | status = acpi_ec_read_status(ec); | ||
281 | if (status != -EINVAL && | ||
282 | !(status & ACPI_EC_FLAG_BURST)){ | ||
283 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); | ||
284 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
285 | if (status){ | ||
286 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
287 | return_VALUE(-EINVAL); | ||
288 | } | ||
289 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); | ||
290 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
291 | if(tmp != 0x90 ) {/* Burst ACK byte*/ | ||
292 | return_VALUE(-EINVAL); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | atomic_set(&ec->burst.leaving_burst , 0); | ||
297 | return_VALUE(0); | ||
298 | } | ||
138 | 299 | ||
300 | static int | ||
301 | acpi_ec_leave_burst_mode ( | ||
302 | union acpi_ec *ec) | ||
303 | { | ||
304 | int status =0; | ||
305 | |||
306 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); | ||
307 | |||
308 | atomic_set(&ec->burst.leaving_burst , 1); | ||
309 | status = acpi_ec_read_status(ec); | ||
310 | if (status != -EINVAL && | ||
311 | (status & ACPI_EC_FLAG_BURST)){ | ||
312 | acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); | ||
313 | status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); | ||
314 | if (status){ | ||
315 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
316 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); | ||
317 | return_VALUE(-EINVAL); | ||
318 | } | ||
319 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
320 | status = acpi_ec_read_status(ec); | ||
321 | } | ||
322 | |||
323 | return_VALUE(0); | ||
324 | } | ||
139 | 325 | ||
140 | static int | 326 | static int |
141 | acpi_ec_read ( | 327 | acpi_ec_read ( |
142 | struct acpi_ec *ec, | 328 | union acpi_ec *ec, |
329 | u8 address, | ||
330 | u32 *data) | ||
331 | { | ||
332 | if (acpi_ec_polling_mode) | ||
333 | return acpi_ec_polling_read(ec, address, data); | ||
334 | else | ||
335 | return acpi_ec_burst_read(ec, address, data); | ||
336 | } | ||
337 | static int | ||
338 | acpi_ec_write ( | ||
339 | union acpi_ec *ec, | ||
340 | u8 address, | ||
341 | u8 data) | ||
342 | { | ||
343 | if (acpi_ec_polling_mode) | ||
344 | return acpi_ec_polling_write(ec, address, data); | ||
345 | else | ||
346 | return acpi_ec_burst_write(ec, address, data); | ||
347 | } | ||
348 | static int | ||
349 | acpi_ec_polling_read ( | ||
350 | union acpi_ec *ec, | ||
143 | u8 address, | 351 | u8 address, |
144 | u32 *data) | 352 | u32 *data) |
145 | { | 353 | { |
@@ -155,34 +363,33 @@ acpi_ec_read ( | |||
155 | 363 | ||
156 | *data = 0; | 364 | *data = 0; |
157 | 365 | ||
158 | if (ec->global_lock) { | 366 | if (ec->common.global_lock) { |
159 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 367 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
160 | if (ACPI_FAILURE(status)) | 368 | if (ACPI_FAILURE(status)) |
161 | return_VALUE(-ENODEV); | 369 | return_VALUE(-ENODEV); |
162 | } | 370 | } |
163 | |||
164 | spin_lock_irqsave(&ec->lock, flags); | ||
165 | 371 | ||
166 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); | 372 | spin_lock_irqsave(&ec->polling.lock, flags); |
373 | |||
374 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); | ||
167 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 375 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
168 | if (result) | 376 | if (result) |
169 | goto end; | 377 | goto end; |
170 | 378 | ||
171 | acpi_hw_low_level_write(8, address, &ec->data_addr); | 379 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
172 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 380 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
173 | if (result) | 381 | if (result) |
174 | goto end; | 382 | goto end; |
175 | 383 | ||
176 | 384 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | |
177 | acpi_hw_low_level_read(8, data, &ec->data_addr); | ||
178 | 385 | ||
179 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", | 386 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", |
180 | *data, address)); | 387 | *data, address)); |
181 | 388 | ||
182 | end: | 389 | end: |
183 | spin_unlock_irqrestore(&ec->lock, flags); | 390 | spin_unlock_irqrestore(&ec->polling.lock, flags); |
184 | 391 | ||
185 | if (ec->global_lock) | 392 | if (ec->common.global_lock) |
186 | acpi_release_global_lock(glk); | 393 | acpi_release_global_lock(glk); |
187 | 394 | ||
188 | return_VALUE(result); | 395 | return_VALUE(result); |
@@ -190,8 +397,8 @@ end: | |||
190 | 397 | ||
191 | 398 | ||
192 | static int | 399 | static int |
193 | acpi_ec_write ( | 400 | acpi_ec_polling_write ( |
194 | struct acpi_ec *ec, | 401 | union acpi_ec *ec, |
195 | u8 address, | 402 | u8 address, |
196 | u8 data) | 403 | u8 data) |
197 | { | 404 | { |
@@ -205,25 +412,25 @@ acpi_ec_write ( | |||
205 | if (!ec) | 412 | if (!ec) |
206 | return_VALUE(-EINVAL); | 413 | return_VALUE(-EINVAL); |
207 | 414 | ||
208 | if (ec->global_lock) { | 415 | if (ec->common.global_lock) { |
209 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 416 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
210 | if (ACPI_FAILURE(status)) | 417 | if (ACPI_FAILURE(status)) |
211 | return_VALUE(-ENODEV); | 418 | return_VALUE(-ENODEV); |
212 | } | 419 | } |
213 | 420 | ||
214 | spin_lock_irqsave(&ec->lock, flags); | 421 | spin_lock_irqsave(&ec->polling.lock, flags); |
215 | 422 | ||
216 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); | 423 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); |
217 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 424 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
218 | if (result) | 425 | if (result) |
219 | goto end; | 426 | goto end; |
220 | 427 | ||
221 | acpi_hw_low_level_write(8, address, &ec->data_addr); | 428 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
222 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 429 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
223 | if (result) | 430 | if (result) |
224 | goto end; | 431 | goto end; |
225 | 432 | ||
226 | acpi_hw_low_level_write(8, data, &ec->data_addr); | 433 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); |
227 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 434 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
228 | if (result) | 435 | if (result) |
229 | goto end; | 436 | goto end; |
@@ -232,21 +439,172 @@ acpi_ec_write ( | |||
232 | data, address)); | 439 | data, address)); |
233 | 440 | ||
234 | end: | 441 | end: |
235 | spin_unlock_irqrestore(&ec->lock, flags); | 442 | spin_unlock_irqrestore(&ec->polling.lock, flags); |
236 | 443 | ||
237 | if (ec->global_lock) | 444 | if (ec->common.global_lock) |
238 | acpi_release_global_lock(glk); | 445 | acpi_release_global_lock(glk); |
239 | 446 | ||
240 | return_VALUE(result); | 447 | return_VALUE(result); |
241 | } | 448 | } |
242 | 449 | ||
450 | static int | ||
451 | acpi_ec_burst_read ( | ||
452 | union acpi_ec *ec, | ||
453 | u8 address, | ||
454 | u32 *data) | ||
455 | { | ||
456 | int status = 0; | ||
457 | u32 glk; | ||
458 | |||
459 | ACPI_FUNCTION_TRACE("acpi_ec_read"); | ||
460 | |||
461 | if (!ec || !data) | ||
462 | return_VALUE(-EINVAL); | ||
463 | |||
464 | retry: | ||
465 | *data = 0; | ||
466 | |||
467 | if (ec->common.global_lock) { | ||
468 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | ||
469 | if (ACPI_FAILURE(status)) | ||
470 | return_VALUE(-ENODEV); | ||
471 | } | ||
472 | |||
473 | WARN_ON(in_interrupt()); | ||
474 | down(&ec->burst.sem); | ||
475 | |||
476 | if(acpi_ec_enter_burst_mode(ec)) | ||
477 | goto end; | ||
478 | |||
479 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); | ||
480 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
481 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
482 | if (status) { | ||
483 | goto end; | ||
484 | } | ||
485 | |||
486 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | ||
487 | status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
488 | if (status){ | ||
489 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
490 | goto end; | ||
491 | } | ||
492 | |||
493 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | ||
494 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
495 | |||
496 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", | ||
497 | *data, address)); | ||
498 | |||
499 | end: | ||
500 | acpi_ec_leave_burst_mode(ec); | ||
501 | up(&ec->burst.sem); | ||
502 | |||
503 | if (ec->common.global_lock) | ||
504 | acpi_release_global_lock(glk); | ||
505 | |||
506 | if(atomic_read(&ec->burst.leaving_burst) == 2){ | ||
507 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | ||
508 | while(atomic_read(&ec->burst.pending_gpe)){ | ||
509 | msleep(1); | ||
510 | } | ||
511 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
512 | goto retry; | ||
513 | } | ||
514 | |||
515 | return_VALUE(status); | ||
516 | } | ||
517 | |||
518 | |||
519 | static int | ||
520 | acpi_ec_burst_write ( | ||
521 | union acpi_ec *ec, | ||
522 | u8 address, | ||
523 | u8 data) | ||
524 | { | ||
525 | int status = 0; | ||
526 | u32 glk; | ||
527 | u32 tmp; | ||
528 | |||
529 | ACPI_FUNCTION_TRACE("acpi_ec_write"); | ||
530 | |||
531 | if (!ec) | ||
532 | return_VALUE(-EINVAL); | ||
533 | retry: | ||
534 | if (ec->common.global_lock) { | ||
535 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | ||
536 | if (ACPI_FAILURE(status)) | ||
537 | return_VALUE(-ENODEV); | ||
538 | } | ||
539 | |||
540 | WARN_ON(in_interrupt()); | ||
541 | down(&ec->burst.sem); | ||
542 | |||
543 | if(acpi_ec_enter_burst_mode(ec)) | ||
544 | goto end; | ||
545 | |||
546 | status = acpi_ec_read_status(ec); | ||
547 | if (status != -EINVAL && | ||
548 | !(status & ACPI_EC_FLAG_BURST)){ | ||
549 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); | ||
550 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
551 | if (status) | ||
552 | goto end; | ||
553 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); | ||
554 | if(tmp != 0x90 ) /* Burst ACK byte*/ | ||
555 | goto end; | ||
556 | } | ||
557 | /*Now we are in burst mode*/ | ||
558 | |||
559 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); | ||
560 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
561 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
562 | if (status){ | ||
563 | goto end; | ||
564 | } | ||
565 | |||
566 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | ||
567 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
568 | if (status){ | ||
569 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
570 | goto end; | ||
571 | } | ||
572 | |||
573 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); | ||
574 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
575 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
576 | if (status) | ||
577 | goto end; | ||
578 | |||
579 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", | ||
580 | data, address)); | ||
581 | |||
582 | end: | ||
583 | acpi_ec_leave_burst_mode(ec); | ||
584 | up(&ec->burst.sem); | ||
585 | |||
586 | if (ec->common.global_lock) | ||
587 | acpi_release_global_lock(glk); | ||
588 | |||
589 | if(atomic_read(&ec->burst.leaving_burst) == 2){ | ||
590 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | ||
591 | while(atomic_read(&ec->burst.pending_gpe)){ | ||
592 | msleep(1); | ||
593 | } | ||
594 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
595 | goto retry; | ||
596 | } | ||
597 | |||
598 | return_VALUE(status); | ||
599 | } | ||
600 | |||
243 | /* | 601 | /* |
244 | * Externally callable EC access functions. For now, assume 1 EC only | 602 | * Externally callable EC access functions. For now, assume 1 EC only |
245 | */ | 603 | */ |
246 | int | 604 | int |
247 | ec_read(u8 addr, u8 *val) | 605 | ec_read(u8 addr, u8 *val) |
248 | { | 606 | { |
249 | struct acpi_ec *ec; | 607 | union acpi_ec *ec; |
250 | int err; | 608 | int err; |
251 | u32 temp_data; | 609 | u32 temp_data; |
252 | 610 | ||
@@ -269,7 +627,7 @@ EXPORT_SYMBOL(ec_read); | |||
269 | int | 627 | int |
270 | ec_write(u8 addr, u8 val) | 628 | ec_write(u8 addr, u8 val) |
271 | { | 629 | { |
272 | struct acpi_ec *ec; | 630 | union acpi_ec *ec; |
273 | int err; | 631 | int err; |
274 | 632 | ||
275 | if (!first_ec) | 633 | if (!first_ec) |
@@ -283,10 +641,19 @@ ec_write(u8 addr, u8 val) | |||
283 | } | 641 | } |
284 | EXPORT_SYMBOL(ec_write); | 642 | EXPORT_SYMBOL(ec_write); |
285 | 643 | ||
286 | |||
287 | static int | 644 | static int |
288 | acpi_ec_query ( | 645 | acpi_ec_query ( |
289 | struct acpi_ec *ec, | 646 | union acpi_ec *ec, |
647 | u32 *data) | ||
648 | { | ||
649 | if (acpi_ec_polling_mode) | ||
650 | return acpi_ec_polling_query(ec, data); | ||
651 | else | ||
652 | return acpi_ec_burst_query(ec, data); | ||
653 | } | ||
654 | static int | ||
655 | acpi_ec_polling_query ( | ||
656 | union acpi_ec *ec, | ||
290 | u32 *data) | 657 | u32 *data) |
291 | { | 658 | { |
292 | int result = 0; | 659 | int result = 0; |
@@ -301,7 +668,7 @@ acpi_ec_query ( | |||
301 | 668 | ||
302 | *data = 0; | 669 | *data = 0; |
303 | 670 | ||
304 | if (ec->global_lock) { | 671 | if (ec->common.global_lock) { |
305 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 672 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
306 | if (ACPI_FAILURE(status)) | 673 | if (ACPI_FAILURE(status)) |
307 | return_VALUE(-ENODEV); | 674 | return_VALUE(-ENODEV); |
@@ -312,32 +679,86 @@ acpi_ec_query ( | |||
312 | * Note that successful completion of the query causes the ACPI_EC_SCI | 679 | * Note that successful completion of the query causes the ACPI_EC_SCI |
313 | * bit to be cleared (and thus clearing the interrupt source). | 680 | * bit to be cleared (and thus clearing the interrupt source). |
314 | */ | 681 | */ |
315 | spin_lock_irqsave(&ec->lock, flags); | 682 | spin_lock_irqsave(&ec->polling.lock, flags); |
316 | 683 | ||
317 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); | 684 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); |
318 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 685 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
319 | if (result) | 686 | if (result) |
320 | goto end; | 687 | goto end; |
321 | 688 | ||
322 | acpi_hw_low_level_read(8, data, &ec->data_addr); | 689 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
323 | if (!*data) | 690 | if (!*data) |
324 | result = -ENODATA; | 691 | result = -ENODATA; |
325 | 692 | ||
326 | end: | 693 | end: |
327 | spin_unlock_irqrestore(&ec->lock, flags); | 694 | spin_unlock_irqrestore(&ec->polling.lock, flags); |
328 | 695 | ||
329 | if (ec->global_lock) | 696 | if (ec->common.global_lock) |
330 | acpi_release_global_lock(glk); | 697 | acpi_release_global_lock(glk); |
331 | 698 | ||
332 | return_VALUE(result); | 699 | return_VALUE(result); |
333 | } | 700 | } |
701 | static int | ||
702 | acpi_ec_burst_query ( | ||
703 | union acpi_ec *ec, | ||
704 | u32 *data) | ||
705 | { | ||
706 | int status = 0; | ||
707 | u32 glk; | ||
708 | |||
709 | ACPI_FUNCTION_TRACE("acpi_ec_query"); | ||
710 | |||
711 | if (!ec || !data) | ||
712 | return_VALUE(-EINVAL); | ||
713 | *data = 0; | ||
714 | |||
715 | if (ec->common.global_lock) { | ||
716 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | ||
717 | if (ACPI_FAILURE(status)) | ||
718 | return_VALUE(-ENODEV); | ||
719 | } | ||
720 | |||
721 | down(&ec->burst.sem); | ||
722 | if(acpi_ec_enter_burst_mode(ec)) | ||
723 | goto end; | ||
724 | /* | ||
725 | * Query the EC to find out which _Qxx method we need to evaluate. | ||
726 | * Note that successful completion of the query causes the ACPI_EC_SCI | ||
727 | * bit to be cleared (and thus clearing the interrupt source). | ||
728 | */ | ||
729 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); | ||
730 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
731 | if (status){ | ||
732 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
733 | goto end; | ||
734 | } | ||
735 | |||
736 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | ||
737 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
738 | if (!*data) | ||
739 | status = -ENODATA; | ||
740 | |||
741 | end: | ||
742 | acpi_ec_leave_burst_mode(ec); | ||
743 | up(&ec->burst.sem); | ||
744 | |||
745 | if (ec->common.global_lock) | ||
746 | acpi_release_global_lock(glk); | ||
747 | |||
748 | if(atomic_read(&ec->burst.leaving_burst) == 2){ | ||
749 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | ||
750 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
751 | status = -ENODATA; | ||
752 | } | ||
753 | return_VALUE(status); | ||
754 | } | ||
334 | 755 | ||
335 | 756 | ||
336 | /* -------------------------------------------------------------------------- | 757 | /* -------------------------------------------------------------------------- |
337 | Event Management | 758 | Event Management |
338 | -------------------------------------------------------------------------- */ | 759 | -------------------------------------------------------------------------- */ |
339 | 760 | ||
340 | struct acpi_ec_query_data { | 761 | union acpi_ec_query_data { |
341 | acpi_handle handle; | 762 | acpi_handle handle; |
342 | u8 data; | 763 | u8 data; |
343 | }; | 764 | }; |
@@ -346,7 +767,17 @@ static void | |||
346 | acpi_ec_gpe_query ( | 767 | acpi_ec_gpe_query ( |
347 | void *ec_cxt) | 768 | void *ec_cxt) |
348 | { | 769 | { |
349 | struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; | 770 | if (acpi_ec_polling_mode) |
771 | acpi_ec_gpe_polling_query(ec_cxt); | ||
772 | else | ||
773 | acpi_ec_gpe_burst_query(ec_cxt); | ||
774 | } | ||
775 | |||
776 | static void | ||
777 | acpi_ec_gpe_polling_query ( | ||
778 | void *ec_cxt) | ||
779 | { | ||
780 | union acpi_ec *ec = (union acpi_ec *) ec_cxt; | ||
350 | u32 value = 0; | 781 | u32 value = 0; |
351 | unsigned long flags = 0; | 782 | unsigned long flags = 0; |
352 | static char object_name[5] = {'_','Q','0','0','\0'}; | 783 | static char object_name[5] = {'_','Q','0','0','\0'}; |
@@ -356,11 +787,11 @@ acpi_ec_gpe_query ( | |||
356 | ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); | 787 | ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); |
357 | 788 | ||
358 | if (!ec_cxt) | 789 | if (!ec_cxt) |
359 | goto end; | 790 | goto end; |
360 | 791 | ||
361 | spin_lock_irqsave(&ec->lock, flags); | 792 | spin_lock_irqsave(&ec->polling.lock, flags); |
362 | acpi_hw_low_level_read(8, &value, &ec->command_addr); | 793 | acpi_hw_low_level_read(8, &value, &ec->common.command_addr); |
363 | spin_unlock_irqrestore(&ec->lock, flags); | 794 | spin_unlock_irqrestore(&ec->polling.lock, flags); |
364 | 795 | ||
365 | /* TBD: Implement asynch events! | 796 | /* TBD: Implement asynch events! |
366 | * NOTE: All we care about are EC-SCI's. Other EC events are | 797 | * NOTE: All we care about are EC-SCI's. Other EC events are |
@@ -373,29 +804,67 @@ acpi_ec_gpe_query ( | |||
373 | 804 | ||
374 | if (acpi_ec_query(ec, &value)) | 805 | if (acpi_ec_query(ec, &value)) |
375 | goto end; | 806 | goto end; |
376 | 807 | ||
377 | object_name[2] = hex[((value >> 4) & 0x0F)]; | 808 | object_name[2] = hex[((value >> 4) & 0x0F)]; |
378 | object_name[3] = hex[(value & 0x0F)]; | 809 | object_name[3] = hex[(value & 0x0F)]; |
379 | 810 | ||
380 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); | 811 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); |
381 | 812 | ||
382 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 813 | acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); |
383 | 814 | ||
384 | end: | 815 | end: |
385 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 816 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
817 | } | ||
818 | static void | ||
819 | acpi_ec_gpe_burst_query ( | ||
820 | void *ec_cxt) | ||
821 | { | ||
822 | union acpi_ec *ec = (union acpi_ec *) ec_cxt; | ||
823 | u32 value; | ||
824 | int result = -ENODATA; | ||
825 | static char object_name[5] = {'_','Q','0','0','\0'}; | ||
826 | const char hex[] = {'0','1','2','3','4','5','6','7', | ||
827 | '8','9','A','B','C','D','E','F'}; | ||
828 | |||
829 | ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); | ||
830 | |||
831 | if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) | ||
832 | result = acpi_ec_query(ec, &value); | ||
833 | |||
834 | if (result) | ||
835 | goto end; | ||
836 | |||
837 | object_name[2] = hex[((value >> 4) & 0x0F)]; | ||
838 | object_name[3] = hex[(value & 0x0F)]; | ||
839 | |||
840 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); | ||
841 | |||
842 | acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); | ||
843 | end: | ||
844 | atomic_dec(&ec->burst.pending_gpe); | ||
845 | return; | ||
386 | } | 846 | } |
387 | 847 | ||
388 | static u32 | 848 | static u32 |
389 | acpi_ec_gpe_handler ( | 849 | acpi_ec_gpe_handler ( |
390 | void *data) | 850 | void *data) |
391 | { | 851 | { |
852 | if (acpi_ec_polling_mode) | ||
853 | return acpi_ec_gpe_polling_handler(data); | ||
854 | else | ||
855 | return acpi_ec_gpe_burst_handler(data); | ||
856 | } | ||
857 | static u32 | ||
858 | acpi_ec_gpe_polling_handler ( | ||
859 | void *data) | ||
860 | { | ||
392 | acpi_status status = AE_OK; | 861 | acpi_status status = AE_OK; |
393 | struct acpi_ec *ec = (struct acpi_ec *) data; | 862 | union acpi_ec *ec = (union acpi_ec *) data; |
394 | 863 | ||
395 | if (!ec) | 864 | if (!ec) |
396 | return ACPI_INTERRUPT_NOT_HANDLED; | 865 | return ACPI_INTERRUPT_NOT_HANDLED; |
397 | 866 | ||
398 | acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 867 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
399 | 868 | ||
400 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 869 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, |
401 | acpi_ec_gpe_query, ec); | 870 | acpi_ec_gpe_query, ec); |
@@ -405,6 +874,55 @@ acpi_ec_gpe_handler ( | |||
405 | else | 874 | else |
406 | return ACPI_INTERRUPT_NOT_HANDLED; | 875 | return ACPI_INTERRUPT_NOT_HANDLED; |
407 | } | 876 | } |
877 | static u32 | ||
878 | acpi_ec_gpe_burst_handler ( | ||
879 | void *data) | ||
880 | { | ||
881 | acpi_status status = AE_OK; | ||
882 | u32 value; | ||
883 | union acpi_ec *ec = (union acpi_ec *) data; | ||
884 | |||
885 | if (!ec) | ||
886 | return ACPI_INTERRUPT_NOT_HANDLED; | ||
887 | |||
888 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | ||
889 | |||
890 | value = acpi_ec_read_status(ec); | ||
891 | |||
892 | if((value & ACPI_EC_FLAG_IBF) && | ||
893 | !(value & ACPI_EC_FLAG_BURST) && | ||
894 | (atomic_read(&ec->burst.leaving_burst) == 0)) { | ||
895 | /* | ||
896 | * the embedded controller disables | ||
897 | * burst mode for any reason other | ||
898 | * than the burst disable command | ||
899 | * to process critical event. | ||
900 | */ | ||
901 | atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction | ||
902 | and retry */ | ||
903 | wake_up(&ec->burst.wait); | ||
904 | }else { | ||
905 | if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && | ||
906 | (value & ACPI_EC_FLAG_OBF)) || | ||
907 | (ec->burst.expect_event == ACPI_EC_EVENT_IBE && | ||
908 | !(value & ACPI_EC_FLAG_IBF))) { | ||
909 | ec->burst.expect_event = 0; | ||
910 | wake_up(&ec->burst.wait); | ||
911 | return ACPI_INTERRUPT_HANDLED; | ||
912 | } | ||
913 | } | ||
914 | |||
915 | if (value & ACPI_EC_FLAG_SCI){ | ||
916 | atomic_add(1, &ec->burst.pending_gpe) ; | ||
917 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | ||
918 | acpi_ec_gpe_query, ec); | ||
919 | return status == AE_OK ? | ||
920 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | ||
921 | } | ||
922 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | ||
923 | return status == AE_OK ? | ||
924 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | ||
925 | } | ||
408 | 926 | ||
409 | /* -------------------------------------------------------------------------- | 927 | /* -------------------------------------------------------------------------- |
410 | Address Space Management | 928 | Address Space Management |
@@ -421,10 +939,8 @@ acpi_ec_space_setup ( | |||
421 | * The EC object is in the handler context and is needed | 939 | * The EC object is in the handler context and is needed |
422 | * when calling the acpi_ec_space_handler. | 940 | * when calling the acpi_ec_space_handler. |
423 | */ | 941 | */ |
424 | if(function == ACPI_REGION_DEACTIVATE) | 942 | *return_context = (function != ACPI_REGION_DEACTIVATE) ? |
425 | *return_context = NULL; | 943 | handler_context : NULL; |
426 | else | ||
427 | *return_context = handler_context; | ||
428 | 944 | ||
429 | return AE_OK; | 945 | return AE_OK; |
430 | } | 946 | } |
@@ -440,8 +956,8 @@ acpi_ec_space_handler ( | |||
440 | void *region_context) | 956 | void *region_context) |
441 | { | 957 | { |
442 | int result = 0; | 958 | int result = 0; |
443 | struct acpi_ec *ec = NULL; | 959 | union acpi_ec *ec = NULL; |
444 | u32 temp = 0; | 960 | u64 temp = *value; |
445 | acpi_integer f_v = 0; | 961 | acpi_integer f_v = 0; |
446 | int i = 0; | 962 | int i = 0; |
447 | 963 | ||
@@ -450,22 +966,21 @@ acpi_ec_space_handler ( | |||
450 | if ((address > 0xFF) || !value || !handler_context) | 966 | if ((address > 0xFF) || !value || !handler_context) |
451 | return_VALUE(AE_BAD_PARAMETER); | 967 | return_VALUE(AE_BAD_PARAMETER); |
452 | 968 | ||
453 | if(bit_width != 8) { | 969 | if (bit_width != 8 && acpi_strict) { |
454 | printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n"); | 970 | printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n"); |
455 | if (acpi_strict) | 971 | return_VALUE(AE_BAD_PARAMETER); |
456 | return_VALUE(AE_BAD_PARAMETER); | ||
457 | } | 972 | } |
458 | 973 | ||
459 | ec = (struct acpi_ec *) handler_context; | 974 | ec = (union acpi_ec *) handler_context; |
460 | 975 | ||
461 | next_byte: | 976 | next_byte: |
462 | switch (function) { | 977 | switch (function) { |
463 | case ACPI_READ: | 978 | case ACPI_READ: |
464 | result = acpi_ec_read(ec, (u8) address, &temp); | 979 | temp = 0; |
465 | *value = (acpi_integer) temp; | 980 | result = acpi_ec_read(ec, (u8) address, (u32 *)&temp); |
466 | break; | 981 | break; |
467 | case ACPI_WRITE: | 982 | case ACPI_WRITE: |
468 | result = acpi_ec_write(ec, (u8) address, (u8) *value); | 983 | result = acpi_ec_write(ec, (u8) address, (u8) temp); |
469 | break; | 984 | break; |
470 | default: | 985 | default: |
471 | result = -EINVAL; | 986 | result = -EINVAL; |
@@ -474,19 +989,18 @@ next_byte: | |||
474 | } | 989 | } |
475 | 990 | ||
476 | bit_width -= 8; | 991 | bit_width -= 8; |
477 | if(bit_width){ | 992 | if (bit_width) { |
478 | 993 | if (function == ACPI_READ) | |
479 | if(function == ACPI_READ) | 994 | f_v |= temp << 8 * i; |
480 | f_v |= (acpi_integer) (*value) << 8*i; | 995 | if (function == ACPI_WRITE) |
481 | if(function == ACPI_WRITE) | 996 | temp >>= 8; |
482 | (*value) >>=8; | ||
483 | i++; | 997 | i++; |
998 | address++; | ||
484 | goto next_byte; | 999 | goto next_byte; |
485 | } | 1000 | } |
486 | 1001 | ||
487 | 1002 | if (function == ACPI_READ) { | |
488 | if(function == ACPI_READ){ | 1003 | f_v |= temp << 8 * i; |
489 | f_v |= (acpi_integer) (*value) << 8*i; | ||
490 | *value = f_v; | 1004 | *value = f_v; |
491 | } | 1005 | } |
492 | 1006 | ||
@@ -505,8 +1019,6 @@ out: | |||
505 | default: | 1019 | default: |
506 | return_VALUE(AE_OK); | 1020 | return_VALUE(AE_OK); |
507 | } | 1021 | } |
508 | |||
509 | |||
510 | } | 1022 | } |
511 | 1023 | ||
512 | 1024 | ||
@@ -520,7 +1032,7 @@ static struct proc_dir_entry *acpi_ec_dir; | |||
520 | static int | 1032 | static int |
521 | acpi_ec_read_info (struct seq_file *seq, void *offset) | 1033 | acpi_ec_read_info (struct seq_file *seq, void *offset) |
522 | { | 1034 | { |
523 | struct acpi_ec *ec = (struct acpi_ec *) seq->private; | 1035 | union acpi_ec *ec = (union acpi_ec *) seq->private; |
524 | 1036 | ||
525 | ACPI_FUNCTION_TRACE("acpi_ec_read_info"); | 1037 | ACPI_FUNCTION_TRACE("acpi_ec_read_info"); |
526 | 1038 | ||
@@ -528,11 +1040,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset) | |||
528 | goto end; | 1040 | goto end; |
529 | 1041 | ||
530 | seq_printf(seq, "gpe bit: 0x%02x\n", | 1042 | seq_printf(seq, "gpe bit: 0x%02x\n", |
531 | (u32) ec->gpe_bit); | 1043 | (u32) ec->common.gpe_bit); |
532 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", | 1044 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", |
533 | (u32) ec->status_addr.address, (u32) ec->data_addr.address); | 1045 | (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address); |
534 | seq_printf(seq, "use global lock: %s\n", | 1046 | seq_printf(seq, "use global lock: %s\n", |
535 | ec->global_lock?"yes":"no"); | 1047 | ec->common.global_lock?"yes":"no"); |
1048 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
536 | 1049 | ||
537 | end: | 1050 | end: |
538 | return_VALUE(0); | 1051 | return_VALUE(0); |
@@ -602,13 +1115,14 @@ acpi_ec_remove_fs ( | |||
602 | Driver Interface | 1115 | Driver Interface |
603 | -------------------------------------------------------------------------- */ | 1116 | -------------------------------------------------------------------------- */ |
604 | 1117 | ||
1118 | |||
605 | static int | 1119 | static int |
606 | acpi_ec_add ( | 1120 | acpi_ec_polling_add ( |
607 | struct acpi_device *device) | 1121 | struct acpi_device *device) |
608 | { | 1122 | { |
609 | int result = 0; | 1123 | int result = 0; |
610 | acpi_status status = AE_OK; | 1124 | acpi_status status = AE_OK; |
611 | struct acpi_ec *ec = NULL; | 1125 | union acpi_ec *ec = NULL; |
612 | unsigned long uid; | 1126 | unsigned long uid; |
613 | 1127 | ||
614 | ACPI_FUNCTION_TRACE("acpi_ec_add"); | 1128 | ACPI_FUNCTION_TRACE("acpi_ec_add"); |
@@ -616,36 +1130,107 @@ acpi_ec_add ( | |||
616 | if (!device) | 1130 | if (!device) |
617 | return_VALUE(-EINVAL); | 1131 | return_VALUE(-EINVAL); |
618 | 1132 | ||
619 | ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1133 | ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
620 | if (!ec) | 1134 | if (!ec) |
621 | return_VALUE(-ENOMEM); | 1135 | return_VALUE(-ENOMEM); |
622 | memset(ec, 0, sizeof(struct acpi_ec)); | 1136 | memset(ec, 0, sizeof(union acpi_ec)); |
623 | 1137 | ||
624 | ec->handle = device->handle; | 1138 | ec->common.handle = device->handle; |
625 | ec->uid = -1; | 1139 | ec->common.uid = -1; |
626 | spin_lock_init(&ec->lock); | 1140 | spin_lock_init(&ec->polling.lock); |
627 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | 1141 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |
628 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | 1142 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
629 | acpi_driver_data(device) = ec; | 1143 | acpi_driver_data(device) = ec; |
630 | 1144 | ||
631 | /* Use the global lock for all EC transactions? */ | 1145 | /* Use the global lock for all EC transactions? */ |
632 | acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); | 1146 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); |
633 | 1147 | ||
634 | /* If our UID matches the UID for the ECDT-enumerated EC, | 1148 | /* If our UID matches the UID for the ECDT-enumerated EC, |
635 | we now have the *real* EC info, so kill the makeshift one.*/ | 1149 | we now have the *real* EC info, so kill the makeshift one.*/ |
636 | acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid); | 1150 | acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); |
637 | if (ec_ecdt && ec_ecdt->uid == uid) { | 1151 | if (ec_ecdt && ec_ecdt->common.uid == uid) { |
638 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, | 1152 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, |
639 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); | 1153 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); |
640 | 1154 | ||
641 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); | 1155 | acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); |
1156 | |||
1157 | kfree(ec_ecdt); | ||
1158 | } | ||
1159 | |||
1160 | /* Get GPE bit assignment (EC events). */ | ||
1161 | /* TODO: Add support for _GPE returning a package */ | ||
1162 | status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); | ||
1163 | if (ACPI_FAILURE(status)) { | ||
1164 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
1165 | "Error obtaining GPE bit assignment\n")); | ||
1166 | result = -ENODEV; | ||
1167 | goto end; | ||
1168 | } | ||
1169 | |||
1170 | result = acpi_ec_add_fs(device); | ||
1171 | if (result) | ||
1172 | goto end; | ||
1173 | |||
1174 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", | ||
1175 | acpi_device_name(device), acpi_device_bid(device), | ||
1176 | (u32) ec->common.gpe_bit); | ||
1177 | |||
1178 | if (!first_ec) | ||
1179 | first_ec = device; | ||
1180 | |||
1181 | end: | ||
1182 | if (result) | ||
1183 | kfree(ec); | ||
1184 | |||
1185 | return_VALUE(result); | ||
1186 | } | ||
1187 | static int | ||
1188 | acpi_ec_burst_add ( | ||
1189 | struct acpi_device *device) | ||
1190 | { | ||
1191 | int result = 0; | ||
1192 | acpi_status status = AE_OK; | ||
1193 | union acpi_ec *ec = NULL; | ||
1194 | unsigned long uid; | ||
1195 | |||
1196 | ACPI_FUNCTION_TRACE("acpi_ec_add"); | ||
1197 | |||
1198 | if (!device) | ||
1199 | return_VALUE(-EINVAL); | ||
1200 | |||
1201 | ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); | ||
1202 | if (!ec) | ||
1203 | return_VALUE(-ENOMEM); | ||
1204 | memset(ec, 0, sizeof(union acpi_ec)); | ||
1205 | |||
1206 | ec->common.handle = device->handle; | ||
1207 | ec->common.uid = -1; | ||
1208 | atomic_set(&ec->burst.pending_gpe, 0); | ||
1209 | atomic_set(&ec->burst.leaving_burst , 1); | ||
1210 | init_MUTEX(&ec->burst.sem); | ||
1211 | init_waitqueue_head(&ec->burst.wait); | ||
1212 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | ||
1213 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | ||
1214 | acpi_driver_data(device) = ec; | ||
1215 | |||
1216 | /* Use the global lock for all EC transactions? */ | ||
1217 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); | ||
1218 | |||
1219 | /* If our UID matches the UID for the ECDT-enumerated EC, | ||
1220 | we now have the *real* EC info, so kill the makeshift one.*/ | ||
1221 | acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); | ||
1222 | if (ec_ecdt && ec_ecdt->common.uid == uid) { | ||
1223 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, | ||
1224 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); | ||
1225 | |||
1226 | acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); | ||
642 | 1227 | ||
643 | kfree(ec_ecdt); | 1228 | kfree(ec_ecdt); |
644 | } | 1229 | } |
645 | 1230 | ||
646 | /* Get GPE bit assignment (EC events). */ | 1231 | /* Get GPE bit assignment (EC events). */ |
647 | /* TODO: Add support for _GPE returning a package */ | 1232 | /* TODO: Add support for _GPE returning a package */ |
648 | status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); | 1233 | status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); |
649 | if (ACPI_FAILURE(status)) { | 1234 | if (ACPI_FAILURE(status)) { |
650 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1235 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
651 | "Error obtaining GPE bit assignment\n")); | 1236 | "Error obtaining GPE bit assignment\n")); |
@@ -659,7 +1244,7 @@ acpi_ec_add ( | |||
659 | 1244 | ||
660 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", | 1245 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", |
661 | acpi_device_name(device), acpi_device_bid(device), | 1246 | acpi_device_name(device), acpi_device_bid(device), |
662 | (u32) ec->gpe_bit); | 1247 | (u32) ec->common.gpe_bit); |
663 | 1248 | ||
664 | if (!first_ec) | 1249 | if (!first_ec) |
665 | first_ec = device; | 1250 | first_ec = device; |
@@ -677,7 +1262,7 @@ acpi_ec_remove ( | |||
677 | struct acpi_device *device, | 1262 | struct acpi_device *device, |
678 | int type) | 1263 | int type) |
679 | { | 1264 | { |
680 | struct acpi_ec *ec = NULL; | 1265 | union acpi_ec *ec = NULL; |
681 | 1266 | ||
682 | ACPI_FUNCTION_TRACE("acpi_ec_remove"); | 1267 | ACPI_FUNCTION_TRACE("acpi_ec_remove"); |
683 | 1268 | ||
@@ -699,7 +1284,7 @@ acpi_ec_io_ports ( | |||
699 | struct acpi_resource *resource, | 1284 | struct acpi_resource *resource, |
700 | void *context) | 1285 | void *context) |
701 | { | 1286 | { |
702 | struct acpi_ec *ec = (struct acpi_ec *) context; | 1287 | union acpi_ec *ec = (union acpi_ec *) context; |
703 | struct acpi_generic_address *addr; | 1288 | struct acpi_generic_address *addr; |
704 | 1289 | ||
705 | if (resource->id != ACPI_RSTYPE_IO) { | 1290 | if (resource->id != ACPI_RSTYPE_IO) { |
@@ -711,10 +1296,10 @@ acpi_ec_io_ports ( | |||
711 | * the second address region returned is the status/command | 1296 | * the second address region returned is the status/command |
712 | * port. | 1297 | * port. |
713 | */ | 1298 | */ |
714 | if (ec->data_addr.register_bit_width == 0) { | 1299 | if (ec->common.data_addr.register_bit_width == 0) { |
715 | addr = &ec->data_addr; | 1300 | addr = &ec->common.data_addr; |
716 | } else if (ec->command_addr.register_bit_width == 0) { | 1301 | } else if (ec->common.command_addr.register_bit_width == 0) { |
717 | addr = &ec->command_addr; | 1302 | addr = &ec->common.command_addr; |
718 | } else { | 1303 | } else { |
719 | return AE_CTRL_TERMINATE; | 1304 | return AE_CTRL_TERMINATE; |
720 | } | 1305 | } |
@@ -733,7 +1318,7 @@ acpi_ec_start ( | |||
733 | struct acpi_device *device) | 1318 | struct acpi_device *device) |
734 | { | 1319 | { |
735 | acpi_status status = AE_OK; | 1320 | acpi_status status = AE_OK; |
736 | struct acpi_ec *ec = NULL; | 1321 | union acpi_ec *ec = NULL; |
737 | 1322 | ||
738 | ACPI_FUNCTION_TRACE("acpi_ec_start"); | 1323 | ACPI_FUNCTION_TRACE("acpi_ec_start"); |
739 | 1324 | ||
@@ -748,35 +1333,36 @@ acpi_ec_start ( | |||
748 | /* | 1333 | /* |
749 | * Get I/O port addresses. Convert to GAS format. | 1334 | * Get I/O port addresses. Convert to GAS format. |
750 | */ | 1335 | */ |
751 | status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, | 1336 | status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, |
752 | acpi_ec_io_ports, ec); | 1337 | acpi_ec_io_ports, ec); |
753 | if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) { | 1338 | if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) { |
754 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); | 1339 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); |
755 | return_VALUE(-ENODEV); | 1340 | return_VALUE(-ENODEV); |
756 | } | 1341 | } |
757 | 1342 | ||
758 | ec->status_addr = ec->command_addr; | 1343 | ec->common.status_addr = ec->common.command_addr; |
759 | 1344 | ||
760 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", | 1345 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", |
761 | (u32) ec->gpe_bit, (u32) ec->command_addr.address, | 1346 | (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address, |
762 | (u32) ec->data_addr.address)); | 1347 | (u32) ec->common.data_addr.address)); |
1348 | |||
763 | 1349 | ||
764 | /* | 1350 | /* |
765 | * Install GPE handler | 1351 | * Install GPE handler |
766 | */ | 1352 | */ |
767 | status = acpi_install_gpe_handler(NULL, ec->gpe_bit, | 1353 | status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, |
768 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); | 1354 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); |
769 | if (ACPI_FAILURE(status)) { | 1355 | if (ACPI_FAILURE(status)) { |
770 | return_VALUE(-ENODEV); | 1356 | return_VALUE(-ENODEV); |
771 | } | 1357 | } |
772 | acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); | 1358 | acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); |
773 | acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR); | 1359 | acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR); |
774 | 1360 | ||
775 | status = acpi_install_address_space_handler (ec->handle, | 1361 | status = acpi_install_address_space_handler (ec->common.handle, |
776 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, | 1362 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, |
777 | &acpi_ec_space_setup, ec); | 1363 | &acpi_ec_space_setup, ec); |
778 | if (ACPI_FAILURE(status)) { | 1364 | if (ACPI_FAILURE(status)) { |
779 | acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); | 1365 | acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); |
780 | return_VALUE(-ENODEV); | 1366 | return_VALUE(-ENODEV); |
781 | } | 1367 | } |
782 | 1368 | ||
@@ -790,7 +1376,7 @@ acpi_ec_stop ( | |||
790 | int type) | 1376 | int type) |
791 | { | 1377 | { |
792 | acpi_status status = AE_OK; | 1378 | acpi_status status = AE_OK; |
793 | struct acpi_ec *ec = NULL; | 1379 | union acpi_ec *ec = NULL; |
794 | 1380 | ||
795 | ACPI_FUNCTION_TRACE("acpi_ec_stop"); | 1381 | ACPI_FUNCTION_TRACE("acpi_ec_stop"); |
796 | 1382 | ||
@@ -799,12 +1385,12 @@ acpi_ec_stop ( | |||
799 | 1385 | ||
800 | ec = acpi_driver_data(device); | 1386 | ec = acpi_driver_data(device); |
801 | 1387 | ||
802 | status = acpi_remove_address_space_handler(ec->handle, | 1388 | status = acpi_remove_address_space_handler(ec->common.handle, |
803 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); | 1389 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); |
804 | if (ACPI_FAILURE(status)) | 1390 | if (ACPI_FAILURE(status)) |
805 | return_VALUE(-ENODEV); | 1391 | return_VALUE(-ENODEV); |
806 | 1392 | ||
807 | status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); | 1393 | status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); |
808 | if (ACPI_FAILURE(status)) | 1394 | if (ACPI_FAILURE(status)) |
809 | return_VALUE(-ENODEV); | 1395 | return_VALUE(-ENODEV); |
810 | 1396 | ||
@@ -818,27 +1404,76 @@ acpi_fake_ecdt_callback ( | |||
818 | void *context, | 1404 | void *context, |
819 | void **retval) | 1405 | void **retval) |
820 | { | 1406 | { |
1407 | |||
1408 | if (acpi_ec_polling_mode) | ||
1409 | return acpi_fake_ecdt_polling_callback(handle, | ||
1410 | Level, context, retval); | ||
1411 | else | ||
1412 | return acpi_fake_ecdt_burst_callback(handle, | ||
1413 | Level, context, retval); | ||
1414 | } | ||
1415 | |||
1416 | static acpi_status __init | ||
1417 | acpi_fake_ecdt_polling_callback ( | ||
1418 | acpi_handle handle, | ||
1419 | u32 Level, | ||
1420 | void *context, | ||
1421 | void **retval) | ||
1422 | { | ||
1423 | acpi_status status; | ||
1424 | |||
1425 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
1426 | acpi_ec_io_ports, ec_ecdt); | ||
1427 | if (ACPI_FAILURE(status)) | ||
1428 | return status; | ||
1429 | ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; | ||
1430 | |||
1431 | ec_ecdt->common.uid = -1; | ||
1432 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); | ||
1433 | |||
1434 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); | ||
1435 | if (ACPI_FAILURE(status)) | ||
1436 | return status; | ||
1437 | spin_lock_init(&ec_ecdt->polling.lock); | ||
1438 | ec_ecdt->common.global_lock = TRUE; | ||
1439 | ec_ecdt->common.handle = handle; | ||
1440 | |||
1441 | printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", | ||
1442 | (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, | ||
1443 | (u32) ec_ecdt->common.data_addr.address); | ||
1444 | |||
1445 | return AE_CTRL_TERMINATE; | ||
1446 | } | ||
1447 | |||
1448 | static acpi_status __init | ||
1449 | acpi_fake_ecdt_burst_callback ( | ||
1450 | acpi_handle handle, | ||
1451 | u32 Level, | ||
1452 | void *context, | ||
1453 | void **retval) | ||
1454 | { | ||
821 | acpi_status status; | 1455 | acpi_status status; |
822 | 1456 | ||
1457 | init_MUTEX(&ec_ecdt->burst.sem); | ||
1458 | init_waitqueue_head(&ec_ecdt->burst.wait); | ||
823 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | 1459 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, |
824 | acpi_ec_io_ports, ec_ecdt); | 1460 | acpi_ec_io_ports, ec_ecdt); |
825 | if (ACPI_FAILURE(status)) | 1461 | if (ACPI_FAILURE(status)) |
826 | return status; | 1462 | return status; |
827 | ec_ecdt->status_addr = ec_ecdt->command_addr; | 1463 | ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; |
828 | 1464 | ||
829 | ec_ecdt->uid = -1; | 1465 | ec_ecdt->common.uid = -1; |
830 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); | 1466 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); |
831 | 1467 | ||
832 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); | 1468 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); |
833 | if (ACPI_FAILURE(status)) | 1469 | if (ACPI_FAILURE(status)) |
834 | return status; | 1470 | return status; |
835 | spin_lock_init(&ec_ecdt->lock); | 1471 | ec_ecdt->common.global_lock = TRUE; |
836 | ec_ecdt->global_lock = TRUE; | 1472 | ec_ecdt->common.handle = handle; |
837 | ec_ecdt->handle = handle; | ||
838 | 1473 | ||
839 | printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", | 1474 | printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", |
840 | (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address, | 1475 | (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, |
841 | (u32) ec_ecdt->data_addr.address); | 1476 | (u32) ec_ecdt->common.data_addr.address); |
842 | 1477 | ||
843 | return AE_CTRL_TERMINATE; | 1478 | return AE_CTRL_TERMINATE; |
844 | } | 1479 | } |
@@ -861,12 +1496,12 @@ acpi_ec_fake_ecdt(void) | |||
861 | 1496 | ||
862 | printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); | 1497 | printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); |
863 | 1498 | ||
864 | ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1499 | ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
865 | if (!ec_ecdt) { | 1500 | if (!ec_ecdt) { |
866 | ret = -ENOMEM; | 1501 | ret = -ENOMEM; |
867 | goto error; | 1502 | goto error; |
868 | } | 1503 | } |
869 | memset(ec_ecdt, 0, sizeof(struct acpi_ec)); | 1504 | memset(ec_ecdt, 0, sizeof(union acpi_ec)); |
870 | 1505 | ||
871 | status = acpi_get_devices (ACPI_EC_HID, | 1506 | status = acpi_get_devices (ACPI_EC_HID, |
872 | acpi_fake_ecdt_callback, | 1507 | acpi_fake_ecdt_callback, |
@@ -887,6 +1522,15 @@ error: | |||
887 | static int __init | 1522 | static int __init |
888 | acpi_ec_get_real_ecdt(void) | 1523 | acpi_ec_get_real_ecdt(void) |
889 | { | 1524 | { |
1525 | if (acpi_ec_polling_mode) | ||
1526 | return acpi_ec_polling_get_real_ecdt(); | ||
1527 | else | ||
1528 | return acpi_ec_burst_get_real_ecdt(); | ||
1529 | } | ||
1530 | |||
1531 | static int __init | ||
1532 | acpi_ec_polling_get_real_ecdt(void) | ||
1533 | { | ||
890 | acpi_status status; | 1534 | acpi_status status; |
891 | struct acpi_table_ecdt *ecdt_ptr; | 1535 | struct acpi_table_ecdt *ecdt_ptr; |
892 | 1536 | ||
@@ -900,21 +1544,67 @@ acpi_ec_get_real_ecdt(void) | |||
900 | /* | 1544 | /* |
901 | * Generate a temporary ec context to use until the namespace is scanned | 1545 | * Generate a temporary ec context to use until the namespace is scanned |
902 | */ | 1546 | */ |
903 | ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1547 | ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
904 | if (!ec_ecdt) | 1548 | if (!ec_ecdt) |
905 | return -ENOMEM; | 1549 | return -ENOMEM; |
906 | memset(ec_ecdt, 0, sizeof(struct acpi_ec)); | 1550 | memset(ec_ecdt, 0, sizeof(union acpi_ec)); |
1551 | |||
1552 | ec_ecdt->common.command_addr = ecdt_ptr->ec_control; | ||
1553 | ec_ecdt->common.status_addr = ecdt_ptr->ec_control; | ||
1554 | ec_ecdt->common.data_addr = ecdt_ptr->ec_data; | ||
1555 | ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; | ||
1556 | spin_lock_init(&ec_ecdt->polling.lock); | ||
1557 | /* use the GL just to be safe */ | ||
1558 | ec_ecdt->common.global_lock = TRUE; | ||
1559 | ec_ecdt->common.uid = ecdt_ptr->uid; | ||
1560 | |||
1561 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); | ||
1562 | if (ACPI_FAILURE(status)) { | ||
1563 | goto error; | ||
1564 | } | ||
1565 | |||
1566 | return 0; | ||
1567 | error: | ||
1568 | printk(KERN_ERR PREFIX "Could not use ECDT\n"); | ||
1569 | kfree(ec_ecdt); | ||
1570 | ec_ecdt = NULL; | ||
1571 | |||
1572 | return -ENODEV; | ||
1573 | } | ||
1574 | |||
1575 | |||
1576 | static int __init | ||
1577 | acpi_ec_burst_get_real_ecdt(void) | ||
1578 | { | ||
1579 | acpi_status status; | ||
1580 | struct acpi_table_ecdt *ecdt_ptr; | ||
1581 | |||
1582 | status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, | ||
1583 | (struct acpi_table_header **) &ecdt_ptr); | ||
1584 | if (ACPI_FAILURE(status)) | ||
1585 | return -ENODEV; | ||
1586 | |||
1587 | printk(KERN_INFO PREFIX "Found ECDT\n"); | ||
907 | 1588 | ||
908 | ec_ecdt->command_addr = ecdt_ptr->ec_control; | 1589 | /* |
909 | ec_ecdt->status_addr = ecdt_ptr->ec_control; | 1590 | * Generate a temporary ec context to use until the namespace is scanned |
910 | ec_ecdt->data_addr = ecdt_ptr->ec_data; | 1591 | */ |
911 | ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; | 1592 | ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); |
912 | spin_lock_init(&ec_ecdt->lock); | 1593 | if (!ec_ecdt) |
1594 | return -ENOMEM; | ||
1595 | memset(ec_ecdt, 0, sizeof(union acpi_ec)); | ||
1596 | |||
1597 | init_MUTEX(&ec_ecdt->burst.sem); | ||
1598 | init_waitqueue_head(&ec_ecdt->burst.wait); | ||
1599 | ec_ecdt->common.command_addr = ecdt_ptr->ec_control; | ||
1600 | ec_ecdt->common.status_addr = ecdt_ptr->ec_control; | ||
1601 | ec_ecdt->common.data_addr = ecdt_ptr->ec_data; | ||
1602 | ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; | ||
913 | /* use the GL just to be safe */ | 1603 | /* use the GL just to be safe */ |
914 | ec_ecdt->global_lock = TRUE; | 1604 | ec_ecdt->common.global_lock = TRUE; |
915 | ec_ecdt->uid = ecdt_ptr->uid; | 1605 | ec_ecdt->common.uid = ecdt_ptr->uid; |
916 | 1606 | ||
917 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); | 1607 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); |
918 | if (ACPI_FAILURE(status)) { | 1608 | if (ACPI_FAILURE(status)) { |
919 | goto error; | 1609 | goto error; |
920 | } | 1610 | } |
@@ -947,20 +1637,20 @@ acpi_ec_ecdt_probe (void) | |||
947 | /* | 1637 | /* |
948 | * Install GPE handler | 1638 | * Install GPE handler |
949 | */ | 1639 | */ |
950 | status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, | 1640 | status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, |
951 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, | 1641 | ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, |
952 | ec_ecdt); | 1642 | ec_ecdt); |
953 | if (ACPI_FAILURE(status)) { | 1643 | if (ACPI_FAILURE(status)) { |
954 | goto error; | 1644 | goto error; |
955 | } | 1645 | } |
956 | acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); | 1646 | acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); |
957 | acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); | 1647 | acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); |
958 | 1648 | ||
959 | status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, | 1649 | status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, |
960 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, | 1650 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, |
961 | &acpi_ec_space_setup, ec_ecdt); | 1651 | &acpi_ec_space_setup, ec_ecdt); |
962 | if (ACPI_FAILURE(status)) { | 1652 | if (ACPI_FAILURE(status)) { |
963 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, | 1653 | acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, |
964 | &acpi_ec_gpe_handler); | 1654 | &acpi_ec_gpe_handler); |
965 | goto error; | 1655 | goto error; |
966 | } | 1656 | } |
@@ -1021,4 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str) | |||
1021 | acpi_fake_ecdt_enabled = 1; | 1711 | acpi_fake_ecdt_enabled = 1; |
1022 | return 0; | 1712 | return 0; |
1023 | } | 1713 | } |
1714 | |||
1024 | __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); | 1715 | __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); |
1716 | static int __init acpi_ec_set_polling_mode(char *str) | ||
1717 | { | ||
1718 | int burst; | ||
1719 | |||
1720 | if (!get_option(&str, &burst)) | ||
1721 | return 0; | ||
1722 | |||
1723 | if (burst) { | ||
1724 | acpi_ec_polling_mode = EC_BURST; | ||
1725 | acpi_ec_driver.ops.add = acpi_ec_burst_add; | ||
1726 | } else { | ||
1727 | acpi_ec_polling_mode = EC_POLLING; | ||
1728 | acpi_ec_driver.ops.add = acpi_ec_polling_add; | ||
1729 | } | ||
1730 | printk(KERN_INFO PREFIX "EC %s mode.\n", | ||
1731 | burst ? "burst": "polling"); | ||
1732 | return 0; | ||
1733 | } | ||
1734 | __setup("ec_burst=", acpi_ec_set_polling_mode); | ||