blob: 232df8e06ae4c2d5c23529523d50626666fd2ba0 [file] [log] [blame]
Angel Pons210a0082020-04-02 23:48:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Hung-Te Lina904f9e2013-04-11 15:58:12 +08003
Hung-Te Lina904f9e2013-04-11 15:58:12 +08004#include <arch/io.h>
Alexandru Gagniuc851ef962016-03-30 14:38:44 -07005#include <assert.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +10006#include <console/console.h>
Hung-Te Lina904f9e2013-04-11 15:58:12 +08007#include <delay.h>
Hung-Te Lin76720d02013-04-15 18:06:32 +08008#include <device/pnp.h>
Duncan Laurie32ca3cd2018-10-12 17:19:53 -07009#include <ec/google/common/mec.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +100010#include <stdint.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +100011
Hung-Te Lin76720d02013-04-15 18:06:32 +080012#include "chip.h"
Hung-Te Lina904f9e2013-04-11 15:58:12 +080013#include "ec.h"
14#include "ec_commands.h"
15
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070016/*
17 * Read bytes from a given LPC-mapped address.
18 *
19 * @port: Base read address
20 * @length: Number of bytes to read
21 * @dest: Destination buffer
22 * @csum: Optional parameter, sums data read
23 */
24static void read_bytes(u16 port, unsigned int length, u8 *dest, u8 *csum)
25{
26 int i;
27
Julius Wernercd49cce2019-03-05 16:53:33 -080028#if CONFIG(EC_GOOGLE_CHROMEEC_MEC)
Shawn Nematbakhsh5725ea32015-04-01 16:52:37 -070029 /* Access desired range though EMI interface */
30 if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) {
Matt DeVillier680ed1f62018-12-25 04:43:21 -060031 u8 ret = mec_io_bytes(MEC_IO_READ, MEC_EMI_BASE,
Duncan Laurie32ca3cd2018-10-12 17:19:53 -070032 port - MEC_EMI_RANGE_START,
33 dest, length);
Matt DeVillier680ed1f62018-12-25 04:43:21 -060034 if (csum)
35 *csum += ret;
Shawn Nematbakhsh5725ea32015-04-01 16:52:37 -070036 return;
37 }
38#endif
39
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070040 for (i = 0; i < length; ++i) {
41 dest[i] = inb(port + i);
42 if (csum)
43 *csum += dest[i];
44 }
45}
46
47/* Read single byte and return byte read */
48static inline u8 read_byte(u16 port)
49{
50 u8 byte;
51 read_bytes(port, 1, &byte, NULL);
52 return byte;
53}
54
55/*
56 * Write bytes to a given LPC-mapped address.
57 *
58 * @port: Base write address
59 * @length: Number of bytes to write
60 * @msg: Write data buffer
61 * @csum: Optional parameter, sums data written
62 */
63static void write_bytes(u16 port, unsigned int length, u8 *msg, u8 *csum)
64{
65 int i;
66
Julius Wernercd49cce2019-03-05 16:53:33 -080067#if CONFIG(EC_GOOGLE_CHROMEEC_MEC)
Shawn Nematbakhsh5725ea32015-04-01 16:52:37 -070068 /* Access desired range though EMI interface */
69 if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) {
Matt DeVillier680ed1f62018-12-25 04:43:21 -060070 u8 ret = mec_io_bytes(MEC_IO_WRITE, MEC_EMI_BASE,
Duncan Laurie32ca3cd2018-10-12 17:19:53 -070071 port - MEC_EMI_RANGE_START,
72 msg, length);
Matt DeVillier680ed1f62018-12-25 04:43:21 -060073 if (csum)
74 *csum += ret;
Shawn Nematbakhsh5725ea32015-04-01 16:52:37 -070075 return;
76 }
77#endif
78
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070079 for (i = 0; i < length; ++i) {
80 outb(msg[i], port + i);
81 if (csum)
82 *csum += msg[i];
83 }
84}
85
86/* Write single byte and return byte written */
87static inline u8 write_byte(u8 val, u16 port)
88{
89 u8 byte = val;
90 write_bytes(port, 1, &byte, NULL);
91 return byte;
92}
93
Furquan Shaikh63e424c2016-08-18 21:39:14 -070094static int google_chromeec_status_check(u16 port, u8 mask, u8 cond)
Hung-Te Lina904f9e2013-04-11 15:58:12 +080095{
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070096 u8 ec_status = read_byte(port);
Hung-Te Lina904f9e2013-04-11 15:58:12 +080097 u32 time_count = 0;
98
99 /*
100 * One second is more than plenty for any EC operation to complete
101 * (and the bus accessing/code execution) overhead will make the
102 * timeout even longer.
103 */
104#define MAX_EC_TIMEOUT_US 1000000
105
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700106 while ((ec_status & mask) != cond) {
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800107 udelay(1);
108 if (time_count++ == MAX_EC_TIMEOUT_US)
109 return -1;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700110 ec_status = read_byte(port);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800111 }
112 return 0;
113}
114
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700115static int google_chromeec_wait_ready(u16 port)
116{
117 return google_chromeec_status_check(port,
118 EC_LPC_CMDR_PENDING |
119 EC_LPC_CMDR_BUSY, 0);
120}
121
Julius Wernercd49cce2019-03-05 16:53:33 -0800122#if CONFIG(EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700123/* Read memmap data through ACPI port 66/62 */
124static int read_memmap(u8 *data, u8 offset)
125{
126 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
127 printk(BIOS_ERR, "Timeout waiting for EC ready!\n");
128 return -1;
129 }
130
131 /* Issue the ACPI read command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700132 write_byte(EC_CMD_ACPI_READ, EC_LPC_ADDR_ACPI_CMD);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700133
134 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
135 printk(BIOS_ERR, "Timeout waiting for EC READ_EVENT!\n");
136 return -1;
137 }
138
139 /* Write data address */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700140 write_byte(offset + EC_ACPI_MEM_MAPPED_BEGIN, EC_LPC_ADDR_ACPI_DATA);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700141
142 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
143 printk(BIOS_ERR, "Timeout waiting for EC DATA!\n");
144 return -1;
145 }
146
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700147 *data = read_byte(EC_LPC_ADDR_ACPI_DATA);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700148 return 0;
149}
150#endif
151
152static int google_chromeec_command_version(void)
153{
154 u8 id1, id2, flags;
155
Julius Wernercd49cce2019-03-05 16:53:33 -0800156#if CONFIG(EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700157 if (read_memmap(&id1, EC_MEMMAP_ID) ||
158 read_memmap(&id2, EC_MEMMAP_ID + 1) ||
159 read_memmap(&flags, EC_MEMMAP_HOST_CMD_FLAGS)) {
160 printk(BIOS_ERR, "Error reading memmap data.\n");
161 return -1;
162 }
163#else
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700164 id1 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID);
165 id2 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1);
166 flags = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700167#endif
168
169 if (id1 != 'E' || id2 != 'C') {
170 printk(BIOS_ERR, "Missing Chromium EC memory map.\n");
171 return -1;
172 }
173
174 if (flags & EC_HOST_CMD_FLAG_VERSION_3) {
175 return EC_HOST_CMD_FLAG_VERSION_3;
176 } else if (flags & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) {
177 return EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED;
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700178 }
Elyes HAOUASb5342712019-06-09 13:11:49 +0200179 printk(BIOS_ERR, "Chromium EC command version unsupported\n");
180 return -1;
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700181}
182
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700183static int google_chromeec_command_v3(struct chromeec_command *cec_command)
184{
185 struct ec_host_request rq;
186 struct ec_host_response rs;
187 const u8 *d;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700188 u8 csum = 0;
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700189 int i;
190
191 if (cec_command->cmd_size_in + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) {
Anatol Pomozove95db222015-04-09 20:58:02 -0700192 printk(BIOS_ERR, "EC cannot send %zu bytes\n",
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700193 cec_command->cmd_size_in + sizeof(rq));
194 return -1;
195 }
196
197 if (cec_command->cmd_size_out > EC_LPC_HOST_PACKET_SIZE) {
198 printk(BIOS_ERR, "EC cannot receive %d bytes\n",
199 cec_command->cmd_size_out);
200 return -1;
201 }
202
203 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
204 printk(BIOS_ERR, "Timeout waiting for EC start command %d!\n",
205 cec_command->cmd_code);
206 return -1;
207 }
208
209 /* Fill in request packet */
210 rq.struct_version = EC_HOST_REQUEST_VERSION;
211 rq.checksum = 0;
212 rq.command = cec_command->cmd_code |
213 EC_CMD_PASSTHRU_OFFSET(cec_command->cmd_dev_index);
214 rq.command_version = cec_command->cmd_version;
215 rq.reserved = 0;
216 rq.data_len = cec_command->cmd_size_in;
217
218 /* Copy data and start checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700219 write_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rq),
220 cec_command->cmd_size_in,
221 (u8*)cec_command->cmd_data_in,
222 &csum);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700223
224 /* Finish checksum */
225 for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++)
226 csum += *d;
227
228 /* Write checksum field so the entire packet sums to 0 */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700229 rq.checksum = -csum;
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700230
231 /* Copy header */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700232 write_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rq), (u8*)&rq, NULL);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700233
234 /* Start the command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700235 write_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700236
237 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
238 printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
239 cec_command->cmd_code);
240 return -1;
241 }
242
243 /* Check result */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700244 cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700245 if (cec_command->cmd_code) {
246 printk(BIOS_ERR, "EC returned error result code %d\n",
247 cec_command->cmd_code);
248 return -i;
249 }
250
251 /* Read back response header and start checksum */
252 csum = 0;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700253 read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rs), (u8*)&rs, &csum);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700254
255 if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
256 printk(BIOS_ERR, "EC response version mismatch (%d != %d)\n",
257 rs.struct_version, EC_HOST_RESPONSE_VERSION);
258 return -1;
259 }
260
261 if (rs.reserved) {
262 printk(BIOS_ERR, "EC response reserved is %d, should be 0\n",
263 rs.reserved);
264 return -1;
265 }
266
267 if (rs.data_len > cec_command->cmd_size_out) {
268 printk(BIOS_ERR, "EC returned too much data (%d > %d)\n",
269 rs.data_len, cec_command->cmd_size_out);
270 return -1;
271 }
272
273 /* Read back data and update checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700274 read_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rs),
275 rs.data_len,
276 cec_command->cmd_data_out,
277 &csum);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700278
279 /* Verify checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700280 if (csum) {
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700281 printk(BIOS_ERR, "EC response has invalid checksum\n");
282 return -1;
283 }
284
285 return 0;
286}
287
288static int google_chromeec_command_v1(struct chromeec_command *cec_command)
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800289{
290 struct ec_lpc_host_args args;
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800291 u8 cmd_code = cec_command->cmd_code;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700292 u8 csum;
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800293
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800294 /* Fill in args */
295 args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
296 args.command_version = cec_command->cmd_version;
297 args.data_size = cec_command->cmd_size_in;
298
299 /* Initialize checksum */
300 csum = cmd_code + args.flags + args.command_version + args.data_size;
301
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700302 write_bytes(EC_LPC_ADDR_HOST_PARAM,
303 cec_command->cmd_size_in,
304 (u8*)cec_command->cmd_data_in,
305 &csum);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800306
307 /* Finalize checksum and write args */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700308 args.checksum = csum;
309 write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800310
311
312 /* Issue the command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700313 write_byte(cmd_code, EC_LPC_ADDR_HOST_CMD);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800314
315 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
316 printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
317 cec_command->cmd_code);
318 return 1;
319 }
320
321 /* Check result */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700322 cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800323 if (cec_command->cmd_code)
324 return 1;
325
326 /* Read back args */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700327 read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800328
329 /*
330 * If EC didn't modify args flags, then somehow we sent a new-style
331 * command to an old EC, which means it would have read its params
332 * from the wrong place.
333 */
334 if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) {
335 printk(BIOS_ERR, "EC protocol mismatch\n");
336 return 1;
337 }
338
339 if (args.data_size > cec_command->cmd_size_out) {
340 printk(BIOS_ERR, "EC returned too much data\n");
341 return 1;
342 }
343 cec_command->cmd_size_out = args.data_size;
344
345 /* Start calculating response checksum */
346 csum = cmd_code + args.flags + args.command_version + args.data_size;
347
348 /* Read data, if any */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700349 read_bytes(EC_LPC_ADDR_HOST_PARAM,
350 args.data_size,
351 cec_command->cmd_data_out,
352 &csum);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800353
354 /* Verify checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700355 if (args.checksum != csum) {
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800356 printk(BIOS_ERR, "EC response has invalid checksum\n");
357 return 1;
358 }
359
360 return 0;
361}
362
Duncan Laurie699c7882015-08-13 12:52:08 -0700363/* Return the byte of EC switch states */
364uint8_t google_chromeec_get_switches(void)
365{
366 return read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES);
367}
368
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500369void google_chromeec_ioport_range(uint16_t *out_base, size_t *out_size)
370{
371 uint16_t base;
372 size_t size;
373
Julius Wernercd49cce2019-03-05 16:53:33 -0800374 if (CONFIG(EC_GOOGLE_CHROMEEC_MEC)) {
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500375 base = MEC_EMI_BASE;
376 size = MEC_EMI_SIZE;
377 } else {
378 base = EC_HOST_CMD_REGION0;
379 size = 2 * EC_HOST_CMD_REGION_SIZE;
380 /* Make sure MEMMAP region follows host cmd region. */
381 assert(base + size == EC_LPC_ADDR_MEMMAP);
382 size += EC_MEMMAP_SIZE;
383 }
384
385 *out_base = base;
386 *out_size = size;
387}
388
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700389int google_chromeec_command(struct chromeec_command *cec_command)
390{
Kyösti Mälkki117cf2b2019-08-20 06:01:57 +0300391 MAYBE_STATIC_BSS int command_version = 0;
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700392
393 if (command_version <= 0)
394 command_version = google_chromeec_command_version();
395
396 switch (command_version) {
397 case EC_HOST_CMD_FLAG_VERSION_3:
398 return google_chromeec_command_v3(cec_command);
399 case EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED:
400 return google_chromeec_command_v1(cec_command);
401 }
402 return -1;
403}
Hung-Te Lin76720d02013-04-15 18:06:32 +0800404
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100405static void lpc_ec_init(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800406{
Hung-Te Lin76720d02013-04-15 18:06:32 +0800407 if (!dev->enabled)
408 return;
Edward O'Callaghandef00be2014-04-30 05:01:52 +1000409
Hung-Te Lin76720d02013-04-15 18:06:32 +0800410 google_chromeec_init();
411}
412
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700413/*
414 * Declare the IO ports that we are using:
415 *
416 * All ECs (not explicitly declared):
417 * 0x60/0x64, 0x62/0x66, 0x80, 0x200->0x207
418 *
419 * mec1322: 0x800->0x807
420 * All others: 0x800->0x9ff
421 *
422 * EC_GOOGLE_CHROMEEC_ACPI_MEMMAP is only used for MEC ECs.
423 */
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100424static void lpc_ec_read_resources(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800425{
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700426 unsigned int idx = 0;
427 struct resource * res;
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500428 uint16_t base;
429 size_t size;
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700430
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500431 google_chromeec_ioport_range(&base, &size);
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700432 res = new_resource(dev, idx++);
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500433 res->base = base;
434 res->size = size;
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700435 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Hung-Te Lin76720d02013-04-15 18:06:32 +0800436}
437
Hung-Te Lin76720d02013-04-15 18:06:32 +0800438static struct device_operations ops = {
439 .init = lpc_ec_init,
440 .read_resources = lpc_ec_read_resources,
Nico Huber2f8ba692020-04-05 14:05:24 +0200441 .set_resources = noop_set_resources,
Furquan Shaikhe0060a82020-03-05 08:06:27 -0800442#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +0200443 .acpi_name = google_chromeec_acpi_name,
444 .acpi_fill_ssdt = google_chromeec_fill_ssdt_generator,
Furquan Shaikhe0060a82020-03-05 08:06:27 -0800445#endif
Hung-Te Lin76720d02013-04-15 18:06:32 +0800446};
447
448static struct pnp_info pnp_dev_info[] = {
Felix Held968ac792018-07-07 00:20:00 +0200449 { NULL, 0, 0, 0, }
Hung-Te Lin76720d02013-04-15 18:06:32 +0800450};
451
Furquan Shaikhe0060a82020-03-05 08:06:27 -0800452static void enable_dev(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800453{
Felix Held968ac792018-07-07 00:20:00 +0200454 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
Hung-Te Lin76720d02013-04-15 18:06:32 +0800455}
456
Furquan Shaikhe0060a82020-03-05 08:06:27 -0800457struct chip_operations ec_google_chromeec_ops = {
458 CHIP_NAME("Google Chrome EC")
459 .enable_dev = enable_dev,
460};
461
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700462static int google_chromeec_data_ready(u16 port)
463{
464 return google_chromeec_status_check(port, EC_LPC_CMDR_DATA,
465 EC_LPC_CMDR_DATA);
466}
467
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800468u8 google_chromeec_get_event(void)
469{
470 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
471 printk(BIOS_ERR, "Timeout waiting for EC ready!\n");
472 return 1;
473 }
474
475 /* Issue the ACPI query-event command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700476 write_byte(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800477
478 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
479 printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n");
480 return 0;
481 }
482
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700483 if (google_chromeec_data_ready(EC_LPC_ADDR_ACPI_CMD)) {
484 printk(BIOS_ERR, "Timeout waiting for data ready!\n");
485 return 0;
486 }
487
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800488 /* Event (or 0 if none) is returned directly in the data byte */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700489 return read_byte(EC_LPC_ADDR_ACPI_DATA);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800490}