diff options
author | Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> | 2007-03-07 14:28:00 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-03-09 23:27:28 -0500 |
commit | c45aac43fec2d6ca8d0be8408f94e8176c8110ef (patch) | |
tree | 61dda3eea672ad1bd10acc0ca6a0c8b0fb8c70d0 /drivers/acpi | |
parent | 33c7a0738c5f753a7d94fd3b2ec7d84e79a141a8 (diff) |
ACPI: EC: enable burst functionality in EC.
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/ec.c | 89 |
1 files changed, 37 insertions, 52 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 5999abd9909d..e7ce6e449424 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -101,7 +101,6 @@ static struct acpi_ec { | |||
101 | struct mutex lock; | 101 | struct mutex lock; |
102 | atomic_t query_pending; | 102 | atomic_t query_pending; |
103 | atomic_t event_count; | 103 | atomic_t event_count; |
104 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ | ||
105 | wait_queue_head_t wait; | 104 | wait_queue_head_t wait; |
106 | } *ec_ecdt; | 105 | } *ec_ecdt; |
107 | 106 | ||
@@ -173,56 +172,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) | |||
173 | return -ETIME; | 172 | return -ETIME; |
174 | } | 173 | } |
175 | 174 | ||
176 | #ifdef ACPI_FUTURE_USAGE | ||
177 | /* | ||
178 | * Note: samsung nv5000 doesn't work with ec burst mode. | ||
179 | * http://bugzilla.kernel.org/show_bug.cgi?id=4980 | ||
180 | */ | ||
181 | int acpi_ec_enter_burst_mode(struct acpi_ec *ec) | ||
182 | { | ||
183 | u8 tmp = 0; | ||
184 | u8 status = 0; | ||
185 | |||
186 | status = acpi_ec_read_status(ec); | ||
187 | if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { | ||
188 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | ||
189 | if (status) | ||
190 | goto end; | ||
191 | acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE); | ||
192 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); | ||
193 | tmp = acpi_ec_read_data(ec); | ||
194 | if (tmp != 0x90) { /* Burst ACK byte */ | ||
195 | return -EINVAL; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | atomic_set(&ec->leaving_burst, 0); | ||
200 | return 0; | ||
201 | end: | ||
202 | ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode")); | ||
203 | return -1; | ||
204 | } | ||
205 | |||
206 | int acpi_ec_leave_burst_mode(struct acpi_ec *ec) | ||
207 | { | ||
208 | u8 status = 0; | ||
209 | |||
210 | status = acpi_ec_read_status(ec); | ||
211 | if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) { | ||
212 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | ||
213 | if (status) | ||
214 | goto end; | ||
215 | acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE); | ||
216 | acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | ||
217 | } | ||
218 | atomic_set(&ec->leaving_burst, 1); | ||
219 | return 0; | ||
220 | end: | ||
221 | ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode")); | ||
222 | return -1; | ||
223 | } | ||
224 | #endif /* ACPI_FUTURE_USAGE */ | ||
225 | |||
226 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | 175 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, |
227 | const u8 * wdata, unsigned wdata_len, | 176 | const u8 * wdata, unsigned wdata_len, |
228 | u8 * rdata, unsigned rdata_len) | 177 | u8 * rdata, unsigned rdata_len) |
@@ -312,6 +261,21 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | |||
312 | return status; | 261 | return status; |
313 | } | 262 | } |
314 | 263 | ||
264 | /* | ||
265 | * Note: samsung nv5000 doesn't work with ec burst mode. | ||
266 | * http://bugzilla.kernel.org/show_bug.cgi?id=4980 | ||
267 | */ | ||
268 | int acpi_ec_burst_enable(struct acpi_ec *ec) | ||
269 | { | ||
270 | u8 d; | ||
271 | return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1); | ||
272 | } | ||
273 | |||
274 | int acpi_ec_burst_disable(struct acpi_ec *ec) | ||
275 | { | ||
276 | return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0); | ||
277 | } | ||
278 | |||
315 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) | 279 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) |
316 | { | 280 | { |
317 | int result; | 281 | int result; |
@@ -333,6 +297,28 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) | |||
333 | /* | 297 | /* |
334 | * Externally callable EC access functions. For now, assume 1 EC only | 298 | * Externally callable EC access functions. For now, assume 1 EC only |
335 | */ | 299 | */ |
300 | int ec_burst_enable(void) | ||
301 | { | ||
302 | struct acpi_ec *ec; | ||
303 | if (!first_ec) | ||
304 | return -ENODEV; | ||
305 | ec = acpi_driver_data(first_ec); | ||
306 | return acpi_ec_burst_enable(ec); | ||
307 | } | ||
308 | |||
309 | EXPORT_SYMBOL(ec_burst_enable); | ||
310 | |||
311 | int ec_burst_disable(void) | ||
312 | { | ||
313 | struct acpi_ec *ec; | ||
314 | if (!first_ec) | ||
315 | return -ENODEV; | ||
316 | ec = acpi_driver_data(first_ec); | ||
317 | return acpi_ec_burst_disable(ec); | ||
318 | } | ||
319 | |||
320 | EXPORT_SYMBOL(ec_burst_disable); | ||
321 | |||
336 | int ec_read(u8 addr, u8 * val) | 322 | int ec_read(u8 addr, u8 * val) |
337 | { | 323 | { |
338 | struct acpi_ec *ec; | 324 | struct acpi_ec *ec; |
@@ -639,7 +625,6 @@ static int acpi_ec_add(struct acpi_device *device) | |||
639 | atomic_set(&ec->query_pending, 0); | 625 | atomic_set(&ec->query_pending, 0); |
640 | atomic_set(&ec->event_count, 1); | 626 | atomic_set(&ec->event_count, 1); |
641 | if (acpi_ec_mode == EC_INTR) { | 627 | if (acpi_ec_mode == EC_INTR) { |
642 | atomic_set(&ec->leaving_burst, 1); | ||
643 | init_waitqueue_head(&ec->wait); | 628 | init_waitqueue_head(&ec->wait); |
644 | } | 629 | } |
645 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | 630 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |