drivers/uart: Replace 'unsigned long int' by 'unsigned long'
[coreboot2.git] / src / ec / google / chromeec / ec_lpc.c
blobe661cf582d8e36d9bdf80818892e89b3fcc60159
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <assert.h>
5 #include <console/console.h>
6 #include <delay.h>
7 #include <device/pnp.h>
8 #include <ec/google/common/mec.h>
9 #include <stdint.h>
10 #include <timer.h>
12 #include "chip.h"
13 #include "ec.h"
14 #include "ec_commands.h"
17 * Read bytes from a given LPC-mapped address.
19 * @port: Base read address
20 * @length: Number of bytes to read
21 * @dest: Destination buffer
22 * @csum: Optional parameter, sums data read
24 static void read_bytes(u16 port, unsigned int length, u8 *dest, u8 *csum)
26 int i;
28 #if CONFIG(EC_GOOGLE_CHROMEEC_MEC)
29 /* Access desired range though EMI interface */
30 if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) {
31 u8 ret = mec_io_bytes(MEC_IO_READ, MEC_EMI_BASE,
32 port - MEC_EMI_RANGE_START,
33 dest, length);
34 if (csum)
35 *csum += ret;
36 return;
38 #endif
40 for (i = 0; i < length; ++i) {
41 dest[i] = inb(port + i);
42 if (csum)
43 *csum += dest[i];
47 /* Read single byte and return byte read */
48 static inline u8 read_byte(u16 port)
50 u8 byte;
51 read_bytes(port, 1, &byte, NULL);
52 return byte;
55 #if CONFIG(EC_GOOGLE_CHROMEEC_MEMMAP_INDEXED_IO)
56 /* Read singe byte and return byte read using indexed IO*/
57 static inline u8 read_byte_indexed_io(u8 offset)
59 outb(offset, CONFIG_EC_GOOGLE_CHROMEEC_MEMMAP_INDEXED_IO_PORT);
60 return inb(CONFIG_EC_GOOGLE_CHROMEEC_MEMMAP_INDEXED_IO_PORT + 1);
62 #endif
65 * Write bytes to a given LPC-mapped address.
67 * @port: Base write address
68 * @length: Number of bytes to write
69 * @msg: Write data buffer
70 * @csum: Optional parameter, sums data written
72 static void write_bytes(u16 port, unsigned int length, u8 *msg, u8 *csum)
74 int i;
76 #if CONFIG(EC_GOOGLE_CHROMEEC_MEC)
77 /* Access desired range though EMI interface */
78 if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) {
79 u8 ret = mec_io_bytes(MEC_IO_WRITE, MEC_EMI_BASE,
80 port - MEC_EMI_RANGE_START,
81 msg, length);
82 if (csum)
83 *csum += ret;
84 return;
86 #endif
88 for (i = 0; i < length; ++i) {
89 outb(msg[i], port + i);
90 if (csum)
91 *csum += msg[i];
95 /* Write single byte and return byte written */
96 static inline u8 write_byte(u8 val, u16 port)
98 u8 byte = val;
99 write_bytes(port, 1, &byte, NULL);
100 return byte;
103 static int google_chromeec_status_check(u16 port, u8 mask, u8 cond)
105 struct stopwatch timeout_sw;
106 /* One second is more than plenty for any EC operation to complete */
107 const uint64_t ec_status_timeout_us = 1 * USECS_PER_SEC;
108 /* Wait 1 usec between read attempts */
109 const uint64_t ec_status_read_period_us = 1;
111 stopwatch_init_usecs_expire(&timeout_sw, ec_status_timeout_us);
112 do {
113 if ((read_byte(port) & mask) == cond)
114 return 0;
115 udelay(ec_status_read_period_us);
116 } while (!stopwatch_expired(&timeout_sw));
117 return -1;
120 static int google_chromeec_wait_ready(u16 port)
122 return google_chromeec_status_check(port,
123 EC_LPC_CMDR_PENDING |
124 EC_LPC_CMDR_BUSY, 0);
127 #if CONFIG(EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
128 /* Read memmap data through ACPI port 66/62 */
129 static int read_memmap(u8 *data, u8 offset)
131 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
132 printk(BIOS_ERR, "Timeout waiting for EC ready!\n");
133 return -1;
136 /* Issue the ACPI read command */
137 write_byte(EC_CMD_ACPI_READ, EC_LPC_ADDR_ACPI_CMD);
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;
144 /* Write data address */
145 write_byte(offset + EC_ACPI_MEM_MAPPED_BEGIN, EC_LPC_ADDR_ACPI_DATA);
147 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
148 printk(BIOS_ERR, "Timeout waiting for EC DATA!\n");
149 return -1;
152 *data = read_byte(EC_LPC_ADDR_ACPI_DATA);
153 return 0;
155 #endif
157 static int google_chromeec_command_version(void)
159 u8 id1, id2, flags;
161 #if CONFIG(EC_GOOGLE_CHROMEEC_ACPI_MEMMAP)
162 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;
168 #elif CONFIG(EC_GOOGLE_CHROMEEC_MEMMAP_INDEXED_IO)
169 id1 = read_byte_indexed_io(EC_MEMMAP_ID);
170 id2 = read_byte_indexed_io(EC_MEMMAP_ID + 1);
171 flags = read_byte_indexed_io(EC_MEMMAP_HOST_CMD_FLAGS);
172 #else
173 id1 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID);
174 id2 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1);
175 flags = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS);
176 #endif
178 if (id1 != 'E' || id2 != 'C') {
179 printk(BIOS_ERR, "Missing Chromium EC memory map.\n");
180 return -1;
183 if (flags & EC_HOST_CMD_FLAG_VERSION_3) {
184 return EC_HOST_CMD_FLAG_VERSION_3;
185 } else if (flags & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) {
186 return EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED;
188 printk(BIOS_ERR, "Chromium EC command version unsupported\n");
189 return -1;
192 static int google_chromeec_command_v3(struct chromeec_command *cec_command)
194 struct ec_host_request rq;
195 struct ec_host_response rs;
196 const u8 *d;
197 u8 csum = 0;
198 int i;
200 if (cec_command->cmd_size_in + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) {
201 printk(BIOS_ERR, "EC cannot send %zu bytes\n",
202 cec_command->cmd_size_in + sizeof(rq));
203 return -1;
206 if (cec_command->cmd_size_out > EC_LPC_HOST_PACKET_SIZE) {
207 printk(BIOS_ERR, "EC cannot receive %d bytes\n",
208 cec_command->cmd_size_out);
209 return -1;
212 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
213 printk(BIOS_ERR, "Timeout waiting for EC start command %d!\n",
214 cec_command->cmd_code);
215 return -1;
218 /* Fill in request packet */
219 rq.struct_version = EC_HOST_REQUEST_VERSION;
220 rq.checksum = 0;
221 rq.command = cec_command->cmd_code |
222 EC_CMD_PASSTHRU_OFFSET(cec_command->cmd_dev_index);
223 rq.command_version = cec_command->cmd_version;
224 rq.reserved = 0;
225 rq.data_len = cec_command->cmd_size_in;
227 /* Copy data and start checksum */
228 write_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rq),
229 cec_command->cmd_size_in,
230 (u8*)cec_command->cmd_data_in,
231 &csum);
233 /* Finish checksum */
234 for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++)
235 csum += *d;
237 /* Write checksum field so the entire packet sums to 0 */
238 rq.checksum = -csum;
240 /* Copy header */
241 write_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rq), (u8*)&rq, NULL);
243 /* Start the command */
244 write_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
246 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
247 printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
248 cec_command->cmd_code);
249 return -1;
252 /* Check result */
253 cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA);
254 if (cec_command->cmd_code) {
255 printk(BIOS_SPEW, "EC returned error result code %d\n",
256 cec_command->cmd_code);
257 return -i;
260 /* Read back response header and start checksum */
261 csum = 0;
262 read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rs), (u8*)&rs, &csum);
264 if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
265 printk(BIOS_ERR, "EC response version mismatch (%d != %d)\n",
266 rs.struct_version, EC_HOST_RESPONSE_VERSION);
267 return -1;
270 if (rs.reserved) {
271 printk(BIOS_ERR, "EC response reserved is %d, should be 0\n",
272 rs.reserved);
273 return -1;
276 if (rs.data_len > cec_command->cmd_size_out) {
277 printk(BIOS_ERR, "EC returned too much data (%d > %d)\n",
278 rs.data_len, cec_command->cmd_size_out);
279 return -1;
282 /* Read back data and update checksum */
283 read_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rs),
284 rs.data_len,
285 cec_command->cmd_data_out,
286 &csum);
288 /* Verify checksum */
289 if (csum) {
290 printk(BIOS_ERR, "EC response has invalid checksum\n");
291 return -1;
294 return 0;
297 static int google_chromeec_command_v1(struct chromeec_command *cec_command)
299 struct ec_lpc_host_args args;
300 u8 cmd_code = cec_command->cmd_code;
301 u8 csum;
303 /* Fill in args */
304 args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
305 args.command_version = cec_command->cmd_version;
306 args.data_size = cec_command->cmd_size_in;
308 /* Initialize checksum */
309 csum = cmd_code + args.flags + args.command_version + args.data_size;
311 write_bytes(EC_LPC_ADDR_HOST_PARAM,
312 cec_command->cmd_size_in,
313 (u8*)cec_command->cmd_data_in,
314 &csum);
316 /* Finalize checksum and write args */
317 args.checksum = csum;
318 write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
320 /* Issue the command */
321 write_byte(cmd_code, EC_LPC_ADDR_HOST_CMD);
323 if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
324 printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
325 cec_command->cmd_code);
326 return 1;
329 /* Check result */
330 cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA);
331 if (cec_command->cmd_code)
332 return 1;
334 /* Read back args */
335 read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
338 * If EC didn't modify args flags, then somehow we sent a new-style
339 * command to an old EC, which means it would have read its params
340 * from the wrong place.
342 if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) {
343 printk(BIOS_ERR, "EC protocol mismatch\n");
344 return 1;
347 if (args.data_size > cec_command->cmd_size_out) {
348 printk(BIOS_ERR, "EC returned too much data\n");
349 return 1;
351 cec_command->cmd_size_out = args.data_size;
353 /* Start calculating response checksum */
354 csum = cmd_code + args.flags + args.command_version + args.data_size;
356 /* Read data, if any */
357 read_bytes(EC_LPC_ADDR_HOST_PARAM,
358 args.data_size,
359 cec_command->cmd_data_out,
360 &csum);
362 /* Verify checksum */
363 if (args.checksum != csum) {
364 printk(BIOS_ERR, "EC response has invalid checksum\n");
365 return 1;
368 return 0;
371 /* Return the byte of EC switch states */
372 uint8_t google_chromeec_get_switches(void)
374 #if CONFIG(EC_GOOGLE_CHROMEEC_MEMMAP_INDEXED_IO)
375 return read_byte_indexed_io(EC_MEMMAP_SWITCHES);
376 #else
377 return read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES);
378 #endif
381 void google_chromeec_ioport_range(uint16_t *out_base, size_t *out_size)
383 uint16_t base;
384 size_t size;
386 if (CONFIG(EC_GOOGLE_CHROMEEC_MEC)) {
387 base = MEC_EMI_BASE;
388 size = MEC_EMI_SIZE;
389 } else {
390 base = EC_HOST_CMD_REGION0;
391 size = 2 * EC_HOST_CMD_REGION_SIZE;
392 /* Make sure MEMMAP region follows host cmd region. */
393 assert(base + size == EC_LPC_ADDR_MEMMAP);
394 size += EC_MEMMAP_SIZE;
397 *out_base = base;
398 *out_size = size;
401 int google_chromeec_command(struct chromeec_command *cec_command)
403 static int command_version;
405 if (command_version <= 0)
406 command_version = google_chromeec_command_version();
408 switch (command_version) {
409 case EC_HOST_CMD_FLAG_VERSION_3:
410 return google_chromeec_command_v3(cec_command);
411 case EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED:
412 return google_chromeec_command_v1(cec_command);
414 return -1;
417 static void lpc_ec_init(struct device *dev)
419 if (!dev->enabled)
420 return;
422 google_chromeec_init();
426 * Declare the IO ports that we are using:
428 * All ECs (not explicitly declared):
429 * 0x60/0x64, 0x62/0x66, 0x80, 0x200->0x207
431 * mec1322: 0x800->0x807
432 * All others: 0x800->0x9ff
434 * EC_GOOGLE_CHROMEEC_ACPI_MEMMAP is only used for MEC ECs.
436 static void lpc_ec_read_resources(struct device *dev)
438 unsigned int idx = 0;
439 struct resource * res;
440 uint16_t base;
441 size_t size;
443 google_chromeec_ioport_range(&base, &size);
444 res = new_resource(dev, idx++);
445 res->base = base;
446 res->size = size;
447 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
450 static struct device_operations ops = {
451 .init = lpc_ec_init,
452 .read_resources = lpc_ec_read_resources,
453 .set_resources = noop_set_resources,
454 .scan_bus = scan_static_bus,
455 #if CONFIG(HAVE_ACPI_TABLES)
456 .acpi_name = google_chromeec_acpi_name,
457 .acpi_fill_ssdt = google_chromeec_fill_ssdt_generator,
458 #endif
461 static struct pnp_info pnp_dev_info[] = {
462 { NULL, 0, 0, 0, }
465 static void enable_dev(struct device *dev)
467 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
470 struct chip_operations ec_google_chromeec_ops = {
471 .name = "Google Chrome EC",
472 .enable_dev = enable_dev,
475 static int google_chromeec_data_ready(u16 port)
477 return google_chromeec_status_check(port, EC_LPC_CMDR_DATA,
478 EC_LPC_CMDR_DATA);
481 enum host_event_code google_chromeec_get_event(void)
483 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
484 printk(BIOS_ERR, "Timeout waiting for EC ready!\n");
485 return EC_HOST_EVENT_NONE;
488 /* Issue the ACPI query-event command */
489 write_byte(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD);
491 if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
492 printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n");
493 return EC_HOST_EVENT_NONE;
496 if (google_chromeec_data_ready(EC_LPC_ADDR_ACPI_CMD)) {
497 printk(BIOS_ERR, "Timeout waiting for data ready!\n");
498 return EC_HOST_EVENT_NONE;
501 /* Event (or 0 if none) is returned directly in the data byte */
502 return read_byte(EC_LPC_ADDR_ACPI_DATA);