blob: 42a18e4a0ec4b02022bf09e24b10191ed0d8ea6a [file] [log] [blame]
Hung-Te Lina904f9e2013-04-11 15:58:12 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Hung-Te Lina904f9e2013-04-11 15:58:12 +080014 */
15
Hung-Te Lina904f9e2013-04-11 15:58:12 +080016#include <arch/io.h>
Alexandru Gagniuc851ef962016-03-30 14:38:44 -070017#include <assert.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +100018#include <console/console.h>
Hung-Te Lina904f9e2013-04-11 15:58:12 +080019#include <delay.h>
Hung-Te Lin76720d02013-04-15 18:06:32 +080020#include <device/pnp.h>
Edward O'Callaghane1fe6882014-04-30 20:41:41 +100021#include <pc80/keyboard.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +100022#include <stdint.h>
23#include <stdlib.h>
24
Hung-Te Lin76720d02013-04-15 18:06:32 +080025#include "chip.h"
Hung-Te Lina904f9e2013-04-11 15:58:12 +080026#include "ec.h"
27#include "ec_commands.h"
28
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070029/*
30 * Read bytes from a given LPC-mapped address.
31 *
32 * @port: Base read address
33 * @length: Number of bytes to read
34 * @dest: Destination buffer
35 * @csum: Optional parameter, sums data read
36 */
37static void read_bytes(u16 port, unsigned int length, u8 *dest, u8 *csum)
38{
39 int i;
40
Martin Rothf5c35182017-06-24 14:09:38 -060041#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)
Shawn Nematbakhsh5725ea32015-04-01 16:52:37 -070042 /* Access desired range though EMI interface */
43 if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) {
44 mec_io_bytes(0, port, length, dest, csum);
45 return;
46 }
47#endif
48
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070049 for (i = 0; i < length; ++i) {
50 dest[i] = inb(port + i);
51 if (csum)
52 *csum += dest[i];
53 }
54}
55
56/* Read single byte and return byte read */
57static inline u8 read_byte(u16 port)
58{
59 u8 byte;
60 read_bytes(port, 1, &byte, NULL);
61 return byte;
62}
63
64/*
65 * Write bytes to a given LPC-mapped address.
66 *
67 * @port: Base write address
68 * @length: Number of bytes to write
69 * @msg: Write data buffer
70 * @csum: Optional parameter, sums data written
71 */
72static void write_bytes(u16 port, unsigned int length, u8 *msg, u8 *csum)
73{
74 int i;
75
Martin Rothf5c35182017-06-24 14:09:38 -060076#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)
Shawn Nematbakhsh5725ea32015-04-01 16:52:37 -070077 /* Access desired range though EMI interface */
78 if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) {
79 mec_io_bytes(1, port, length, msg, csum);
80 return;
81 }
82#endif
83
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -070084 for (i = 0; i < length; ++i) {
85 outb(msg[i], port + i);
86 if (csum)
87 *csum += msg[i];
88 }
89}
90
91/* Write single byte and return byte written */
92static inline u8 write_byte(u8 val, u16 port)
93{
94 u8 byte = val;
95 write_bytes(port, 1, &byte, NULL);
96 return byte;
97}
98
Furquan Shaikh63e424c2016-08-18 21:39:14 -070099static int google_chromeec_status_check(u16 port, u8 mask, u8 cond)
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800100{
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700101 u8 ec_status = read_byte(port);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800102 u32 time_count = 0;
103
104 /*
105 * One second is more than plenty for any EC operation to complete
106 * (and the bus accessing/code execution) overhead will make the
107 * timeout even longer.
108 */
109#define MAX_EC_TIMEOUT_US 1000000
110
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700111 while ((ec_status & mask) != cond) {
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800112 udelay(1);
113 if (time_count++ == MAX_EC_TIMEOUT_US)
114 return -1;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700115 ec_status = read_byte(port);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800116 }
117 return 0;
118}
119
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700120static int google_chromeec_wait_ready(u16 port)
121{
122 return google_chromeec_status_check(port,
123 EC_LPC_CMDR_PENDING |
124 EC_LPC_CMDR_BUSY, 0);
125}
126
Martin Rothf5c35182017-06-24 14:09:38 -0600127#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700128/* Read memmap data through ACPI port 66/62 */
129static int read_memmap(u8 *data, u8 offset)
130{
131 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
132 printk(BIOS_ERR, "Timeout waiting for EC ready!\n");
133 return -1;
134 }
135
136 /* Issue the ACPI read command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700137 write_byte(EC_CMD_ACPI_READ, EC_LPC_ADDR_ACPI_CMD);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700138
139 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
140 printk(BIOS_ERR, "Timeout waiting for EC READ_EVENT!\n");
141 return -1;
142 }
143
144 /* Write data address */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700145 write_byte(offset + EC_ACPI_MEM_MAPPED_BEGIN, EC_LPC_ADDR_ACPI_DATA);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700146
147 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
148 printk(BIOS_ERR, "Timeout waiting for EC DATA!\n");
149 return -1;
150 }
151
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700152 *data = read_byte(EC_LPC_ADDR_ACPI_DATA);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700153 return 0;
154}
155#endif
156
157static int google_chromeec_command_version(void)
158{
159 u8 id1, id2, flags;
160
Martin Rothf5c35182017-06-24 14:09:38 -0600161#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700162 if (read_memmap(&id1, EC_MEMMAP_ID) ||
163 read_memmap(&id2, EC_MEMMAP_ID + 1) ||
164 read_memmap(&flags, EC_MEMMAP_HOST_CMD_FLAGS)) {
165 printk(BIOS_ERR, "Error reading memmap data.\n");
166 return -1;
167 }
168#else
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700169 id1 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID);
170 id2 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1);
171 flags = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS);
Shawn Nematbakhsh19ffcb32015-03-27 13:44:34 -0700172#endif
173
174 if (id1 != 'E' || id2 != 'C') {
175 printk(BIOS_ERR, "Missing Chromium EC memory map.\n");
176 return -1;
177 }
178
179 if (flags & EC_HOST_CMD_FLAG_VERSION_3) {
180 return EC_HOST_CMD_FLAG_VERSION_3;
181 } else if (flags & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) {
182 return EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED;
183 } else {
184 printk(BIOS_ERR,
185 "Chromium EC command version unsupported\n");
186 return -1;
187 }
188}
189
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700190static int google_chromeec_command_v3(struct chromeec_command *cec_command)
191{
192 struct ec_host_request rq;
193 struct ec_host_response rs;
194 const u8 *d;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700195 u8 csum = 0;
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700196 int i;
197
198 if (cec_command->cmd_size_in + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) {
Anatol Pomozove95db222015-04-09 20:58:02 -0700199 printk(BIOS_ERR, "EC cannot send %zu bytes\n",
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700200 cec_command->cmd_size_in + sizeof(rq));
201 return -1;
202 }
203
204 if (cec_command->cmd_size_out > EC_LPC_HOST_PACKET_SIZE) {
205 printk(BIOS_ERR, "EC cannot receive %d bytes\n",
206 cec_command->cmd_size_out);
207 return -1;
208 }
209
210 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
211 printk(BIOS_ERR, "Timeout waiting for EC start command %d!\n",
212 cec_command->cmd_code);
213 return -1;
214 }
215
216 /* Fill in request packet */
217 rq.struct_version = EC_HOST_REQUEST_VERSION;
218 rq.checksum = 0;
219 rq.command = cec_command->cmd_code |
220 EC_CMD_PASSTHRU_OFFSET(cec_command->cmd_dev_index);
221 rq.command_version = cec_command->cmd_version;
222 rq.reserved = 0;
223 rq.data_len = cec_command->cmd_size_in;
224
225 /* Copy data and start checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700226 write_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rq),
227 cec_command->cmd_size_in,
228 (u8*)cec_command->cmd_data_in,
229 &csum);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700230
231 /* Finish checksum */
232 for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++)
233 csum += *d;
234
235 /* Write checksum field so the entire packet sums to 0 */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700236 rq.checksum = -csum;
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700237
238 /* Copy header */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700239 write_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rq), (u8*)&rq, NULL);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700240
241 /* Start the command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700242 write_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700243
244 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
245 printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
246 cec_command->cmd_code);
247 return -1;
248 }
249
250 /* Check result */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700251 cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700252 if (cec_command->cmd_code) {
253 printk(BIOS_ERR, "EC returned error result code %d\n",
254 cec_command->cmd_code);
255 return -i;
256 }
257
258 /* Read back response header and start checksum */
259 csum = 0;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700260 read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rs), (u8*)&rs, &csum);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700261
262 if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
263 printk(BIOS_ERR, "EC response version mismatch (%d != %d)\n",
264 rs.struct_version, EC_HOST_RESPONSE_VERSION);
265 return -1;
266 }
267
268 if (rs.reserved) {
269 printk(BIOS_ERR, "EC response reserved is %d, should be 0\n",
270 rs.reserved);
271 return -1;
272 }
273
274 if (rs.data_len > cec_command->cmd_size_out) {
275 printk(BIOS_ERR, "EC returned too much data (%d > %d)\n",
276 rs.data_len, cec_command->cmd_size_out);
277 return -1;
278 }
279
280 /* Read back data and update checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700281 read_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rs),
282 rs.data_len,
283 cec_command->cmd_data_out,
284 &csum);
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700285
286 /* Verify checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700287 if (csum) {
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700288 printk(BIOS_ERR, "EC response has invalid checksum\n");
289 return -1;
290 }
291
292 return 0;
293}
294
295static int google_chromeec_command_v1(struct chromeec_command *cec_command)
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800296{
297 struct ec_lpc_host_args args;
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800298 u8 cmd_code = cec_command->cmd_code;
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700299 u8 csum;
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800300
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800301 /* Fill in args */
302 args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
303 args.command_version = cec_command->cmd_version;
304 args.data_size = cec_command->cmd_size_in;
305
306 /* Initialize checksum */
307 csum = cmd_code + args.flags + args.command_version + args.data_size;
308
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700309 write_bytes(EC_LPC_ADDR_HOST_PARAM,
310 cec_command->cmd_size_in,
311 (u8*)cec_command->cmd_data_in,
312 &csum);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800313
314 /* Finalize checksum and write args */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700315 args.checksum = csum;
316 write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800317
318
319 /* Issue the command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700320 write_byte(cmd_code, EC_LPC_ADDR_HOST_CMD);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800321
322 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
323 printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
324 cec_command->cmd_code);
325 return 1;
326 }
327
328 /* Check result */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700329 cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800330 if (cec_command->cmd_code)
331 return 1;
332
333 /* Read back args */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700334 read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800335
336 /*
337 * If EC didn't modify args flags, then somehow we sent a new-style
338 * command to an old EC, which means it would have read its params
339 * from the wrong place.
340 */
341 if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) {
342 printk(BIOS_ERR, "EC protocol mismatch\n");
343 return 1;
344 }
345
346 if (args.data_size > cec_command->cmd_size_out) {
347 printk(BIOS_ERR, "EC returned too much data\n");
348 return 1;
349 }
350 cec_command->cmd_size_out = args.data_size;
351
352 /* Start calculating response checksum */
353 csum = cmd_code + args.flags + args.command_version + args.data_size;
354
355 /* Read data, if any */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700356 read_bytes(EC_LPC_ADDR_HOST_PARAM,
357 args.data_size,
358 cec_command->cmd_data_out,
359 &csum);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800360
361 /* Verify checksum */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700362 if (args.checksum != csum) {
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800363 printk(BIOS_ERR, "EC response has invalid checksum\n");
364 return 1;
365 }
366
367 return 0;
368}
369
Duncan Laurie699c7882015-08-13 12:52:08 -0700370/* Return the byte of EC switch states */
371uint8_t google_chromeec_get_switches(void)
372{
373 return read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES);
374}
375
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500376void google_chromeec_ioport_range(uint16_t *out_base, size_t *out_size)
377{
378 uint16_t base;
379 size_t size;
380
381 if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) {
382 base = MEC_EMI_BASE;
383 size = MEC_EMI_SIZE;
384 } else {
385 base = EC_HOST_CMD_REGION0;
386 size = 2 * EC_HOST_CMD_REGION_SIZE;
387 /* Make sure MEMMAP region follows host cmd region. */
388 assert(base + size == EC_LPC_ADDR_MEMMAP);
389 size += EC_MEMMAP_SIZE;
390 }
391
392 *out_base = base;
393 *out_size = size;
394}
395
Duncan Laurie60e6bf82014-09-18 12:51:07 -0700396#ifdef __PRE_RAM__
397
398int google_chromeec_command(struct chromeec_command *cec_command)
399{
400 switch (google_chromeec_command_version()) {
401 case EC_HOST_CMD_FLAG_VERSION_3:
402 return google_chromeec_command_v3(cec_command);
403 case EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED:
404 return google_chromeec_command_v1(cec_command);
405 }
406 return -1;
407}
408
409#else /* !__PRE_RAM__ */
410
411int google_chromeec_command(struct chromeec_command *cec_command)
412{
413 static int command_version = 0;
414
415 if (command_version <= 0)
416 command_version = google_chromeec_command_version();
417
418 switch (command_version) {
419 case EC_HOST_CMD_FLAG_VERSION_3:
420 return google_chromeec_command_v3(cec_command);
421 case EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED:
422 return google_chromeec_command_v1(cec_command);
423 }
424 return -1;
425}
Hung-Te Lin76720d02013-04-15 18:06:32 +0800426
427#ifndef __SMM__
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100428static void lpc_ec_init(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800429{
Hung-Te Lin76720d02013-04-15 18:06:32 +0800430 if (!dev->enabled)
431 return;
Edward O'Callaghandef00be2014-04-30 05:01:52 +1000432
Timothy Pearson448e3862015-11-24 14:12:01 -0600433 pc_keyboard_init(NO_AUX_DEVICE);
Hung-Te Lin76720d02013-04-15 18:06:32 +0800434 google_chromeec_init();
435}
436
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700437/*
438 * Declare the IO ports that we are using:
439 *
440 * All ECs (not explicitly declared):
441 * 0x60/0x64, 0x62/0x66, 0x80, 0x200->0x207
442 *
443 * mec1322: 0x800->0x807
444 * All others: 0x800->0x9ff
445 *
446 * EC_GOOGLE_CHROMEEC_ACPI_MEMMAP is only used for MEC ECs.
447 */
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100448static void lpc_ec_read_resources(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800449{
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700450 unsigned int idx = 0;
451 struct resource * res;
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500452 uint16_t base;
453 size_t size;
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700454
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500455 google_chromeec_ioport_range(&base, &size);
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700456 res = new_resource(dev, idx++);
Aaron Durbinfbb3e6c2016-05-10 17:00:06 -0500457 res->base = base;
458 res->size = size;
Alexandru Gagniuc851ef962016-03-30 14:38:44 -0700459 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Hung-Te Lin76720d02013-04-15 18:06:32 +0800460}
461
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100462static void lpc_ec_enable_resources(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800463{
464 /* Nothing, but this function avoids an error on serial console. */
465}
466
467static struct device_operations ops = {
468 .init = lpc_ec_init,
469 .read_resources = lpc_ec_read_resources,
470 .enable_resources = lpc_ec_enable_resources
471};
472
473static struct pnp_info pnp_dev_info[] = {
Samuel Holland7daac912017-06-06 22:55:01 -0500474 { &ops, 0, 0, 0, }
Hung-Te Lin76720d02013-04-15 18:06:32 +0800475};
476
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100477static void enable_dev(struct device *dev)
Hung-Te Lin76720d02013-04-15 18:06:32 +0800478{
479 pnp_enable_devices(dev, &pnp_ops, ARRAY_SIZE(pnp_dev_info),
480 pnp_dev_info);
481}
482
483struct chip_operations ec_google_chromeec_ops = {
484 CHIP_NAME("Google Chrome EC")
485 .enable_dev = enable_dev,
486};
487
488#endif /* __SMM__ */
489
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700490static int google_chromeec_data_ready(u16 port)
491{
492 return google_chromeec_status_check(port, EC_LPC_CMDR_DATA,
493 EC_LPC_CMDR_DATA);
494}
495
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800496u8 google_chromeec_get_event(void)
497{
498 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
499 printk(BIOS_ERR, "Timeout waiting for EC ready!\n");
500 return 1;
501 }
502
503 /* Issue the ACPI query-event command */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700504 write_byte(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800505
506 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
507 printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n");
508 return 0;
509 }
510
Furquan Shaikh63e424c2016-08-18 21:39:14 -0700511 if (google_chromeec_data_ready(EC_LPC_ADDR_ACPI_CMD)) {
512 printk(BIOS_ERR, "Timeout waiting for data ready!\n");
513 return 0;
514 }
515
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800516 /* Event (or 0 if none) is returned directly in the data byte */
Shawn Nematbakhsh4f332fb2015-04-01 15:49:57 -0700517 return read_byte(EC_LPC_ADDR_ACPI_DATA);
Hung-Te Lina904f9e2013-04-11 15:58:12 +0800518}
519#endif