aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2006-12-16 00:32:42 -0500
committerLen Brown <len.brown@intel.com>2006-12-16 00:32:42 -0500
commit678f2b7df24c34f90fee264fa3a8069bca9c99ad (patch)
tree5569d1a0b1efb603ad9576c7af0a46a36dae531d
parentd1998ef38a13c4e74c69df55ccd38b0440c429b2 (diff)
parent6ccedb10e39c34a4cb68f6c8dae67ecdd3e0b138 (diff)
Pull ec into test branch
-rw-r--r--drivers/acpi/ec.c343
1 files changed, 153 insertions, 190 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e6d4b084dca2..d713f769b72d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -45,35 +45,34 @@ ACPI_MODULE_NAME("acpi_ec")
45#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" 45#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
46#define ACPI_EC_DEVICE_NAME "Embedded Controller" 46#define ACPI_EC_DEVICE_NAME "Embedded Controller"
47#define ACPI_EC_FILE_INFO "info" 47#define ACPI_EC_FILE_INFO "info"
48 48#undef PREFIX
49#define PREFIX "ACPI: EC: "
49/* EC status register */ 50/* EC status register */
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 */
52#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ 53#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
53#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ 54#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
54
55/* EC commands */ 55/* EC commands */
56#define ACPI_EC_COMMAND_READ 0x80 56enum ec_command {
57#define ACPI_EC_COMMAND_WRITE 0x81 57 ACPI_EC_COMMAND_READ = 0x80,
58#define ACPI_EC_BURST_ENABLE 0x82 58 ACPI_EC_COMMAND_WRITE = 0x81,
59#define ACPI_EC_BURST_DISABLE 0x83 59 ACPI_EC_BURST_ENABLE = 0x82,
60#define ACPI_EC_COMMAND_QUERY 0x84 60 ACPI_EC_BURST_DISABLE = 0x83,
61 61 ACPI_EC_COMMAND_QUERY = 0x84,
62};
62/* EC events */ 63/* EC events */
63enum { 64enum ec_event {
64 ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ 65 ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
65 ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ 66 ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
66}; 67};
67 68
68#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ 69#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
69#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 70#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
70#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
71#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
72 71
73enum { 72static enum ec_mode {
74 EC_INTR = 1, /* Output buffer full */ 73 EC_INTR = 1, /* Output buffer full */
75 EC_POLL, /* Input buffer empty */ 74 EC_POLL, /* Input buffer empty */
76}; 75} acpi_ec_mode = EC_INTR;
77 76
78static int acpi_ec_remove(struct acpi_device *device, int type); 77static int acpi_ec_remove(struct acpi_device *device, int type);
79static int acpi_ec_start(struct acpi_device *device); 78static int acpi_ec_start(struct acpi_device *device);
@@ -96,19 +95,18 @@ static struct acpi_driver acpi_ec_driver = {
96struct acpi_ec { 95struct acpi_ec {
97 acpi_handle handle; 96 acpi_handle handle;
98 unsigned long uid; 97 unsigned long uid;
99 unsigned long gpe_bit; 98 unsigned long gpe;
100 unsigned long command_addr; 99 unsigned long command_addr;
101 unsigned long data_addr; 100 unsigned long data_addr;
102 unsigned long global_lock; 101 unsigned long global_lock;
103 struct semaphore sem; 102 struct mutex lock;
104 unsigned int expect_event; 103 atomic_t query_pending;
105 atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ 104 atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
106 wait_queue_head_t wait; 105 wait_queue_head_t wait;
107} *ec_ecdt; 106} *ec_ecdt;
108 107
109/* External interfaces use first EC only, so remember */ 108/* External interfaces use first EC only, so remember */
110static struct acpi_device *first_ec; 109static struct acpi_device *first_ec;
111static int acpi_ec_mode = EC_INTR;
112 110
113/* -------------------------------------------------------------------------- 111/* --------------------------------------------------------------------------
114 Transaction Management 112 Transaction Management
@@ -134,54 +132,41 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
134 outb(data, ec->data_addr); 132 outb(data, ec->data_addr);
135} 133}
136 134
137static int acpi_ec_check_status(u8 status, u8 event) 135static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
138{ 136{
139 switch (event) { 137 u8 status = acpi_ec_read_status(ec);
140 case ACPI_EC_EVENT_OBF_1: 138
139 if (event == ACPI_EC_EVENT_OBF_1) {
141 if (status & ACPI_EC_FLAG_OBF) 140 if (status & ACPI_EC_FLAG_OBF)
142 return 1; 141 return 1;
143 break; 142 } else if (event == ACPI_EC_EVENT_IBF_0) {
144 case ACPI_EC_EVENT_IBF_0:
145 if (!(status & ACPI_EC_FLAG_IBF)) 143 if (!(status & ACPI_EC_FLAG_IBF))
146 return 1; 144 return 1;
147 break;
148 default:
149 break;
150 } 145 }
151 146
152 return 0; 147 return 0;
153} 148}
154 149
155static int acpi_ec_wait(struct acpi_ec *ec, u8 event) 150static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event)
156{ 151{
157 int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0; 152 if (acpi_ec_mode == EC_POLL) {
158 long time_left; 153 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
159 154 while (time_before(jiffies, delay)) {
160 ec->expect_event = event; 155 if (acpi_ec_check_status(ec, event))
161 if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
162 ec->expect_event = 0;
163 return 0;
164 }
165
166 do {
167 if (acpi_ec_mode == EC_POLL) {
168 udelay(ACPI_EC_UDELAY);
169 } else {
170 time_left = wait_event_timeout(ec->wait,
171 !ec->expect_event,
172 msecs_to_jiffies(ACPI_EC_DELAY));
173 if (time_left > 0) {
174 ec->expect_event = 0;
175 return 0; 156 return 0;
176 }
177 } 157 }
178 if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { 158 } else {
179 ec->expect_event = 0; 159 if (wait_event_timeout(ec->wait,
160 acpi_ec_check_status(ec, event),
161 msecs_to_jiffies(ACPI_EC_DELAY)) ||
162 acpi_ec_check_status(ec, event)) {
180 return 0; 163 return 0;
164 } else {
165 printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
166 " status = %d, expect_event = %d\n",
167 acpi_ec_read_status(ec), event);
181 } 168 }
182 } while (--i > 0); 169 }
183
184 ec->expect_event = 0;
185 170
186 return -ETIME; 171 return -ETIME;
187} 172}
@@ -196,7 +181,6 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
196 u8 tmp = 0; 181 u8 tmp = 0;
197 u8 status = 0; 182 u8 status = 0;
198 183
199
200 status = acpi_ec_read_status(ec); 184 status = acpi_ec_read_status(ec);
201 if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { 185 if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
202 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); 186 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
@@ -212,7 +196,7 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
212 196
213 atomic_set(&ec->leaving_burst, 0); 197 atomic_set(&ec->leaving_burst, 0);
214 return 0; 198 return 0;
215 end: 199 end:
216 ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode")); 200 ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
217 return -1; 201 return -1;
218} 202}
@@ -221,58 +205,68 @@ int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
221{ 205{
222 u8 status = 0; 206 u8 status = 0;
223 207
224
225 status = acpi_ec_read_status(ec); 208 status = acpi_ec_read_status(ec);
226 if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ 209 if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) {
227 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); 2