blob: f183801e43eddbbe470e44d486d2c932dc385a01 [file] [log] [blame]
Angel Pons210a0082020-04-02 23:48:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer838c5a52010-01-17 14:08:17 +00002
3#include <console/console.h>
4#include <arch/io.h>
5#include <delay.h>
Abel Briggsc3bfbaf2022-04-14 22:08:41 -05006#include <types.h>
Stefan Reinauer838c5a52010-01-17 14:08:17 +00007#include "ec.h"
8
Abel Briggsc3bfbaf2022-04-14 22:08:41 -05009#define EC_POLL_DELAY_US 10
10#define EC_SEND_TIMEOUT_US 20000 // 20ms
11#define EC_RECV_TIMEOUT_US 320000 // 320ms
12
Kyösti Mälkki4a637802019-09-13 11:30:45 +030013static u16 ec_cmd_reg = EC_SC;
14static u16 ec_data_reg = EC_DATA;
Vladimir Serbinenkofe50d0b2013-06-07 01:55:57 +020015
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050016/*
17 * Poll the EC status/command register for a specified
18 * state until the given timeout elapses.
19 */
20static int wait_ec_sc(int timeout_us, u8 mask, u8 state)
21{
22 while (timeout_us > 0 && (inb(ec_cmd_reg) & mask) != state) {
23 udelay(EC_POLL_DELAY_US);
24 timeout_us -= EC_POLL_DELAY_US;
25 }
26
27 return timeout_us > 0 ? 0 : -1;
28}
29
30bool ec_ready_send(int timeout_us)
31{
32 return wait_ec_sc(timeout_us, EC_IBF, 0) == 0;
33}
34
35bool ec_ready_recv(int timeout_us)
36{
37 return wait_ec_sc(timeout_us, EC_OBF, EC_OBF) == 0;
38}
39
Stefan Reinauer838c5a52010-01-17 14:08:17 +000040int send_ec_command(u8 command)
41{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050042 return send_ec_command_timeout(command, EC_SEND_TIMEOUT_US);
43}
Stefan Reinauer838c5a52010-01-17 14:08:17 +000044
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050045int send_ec_command_timeout(u8 command, int timeout_us)
46{
47 if (!ec_ready_send(timeout_us)) {
Stefan Reinauer14e22772010-04-27 06:56:47 +000048 printk(BIOS_DEBUG, "Timeout while sending command 0x%02x to EC!\n",
Stefan Reinauer838c5a52010-01-17 14:08:17 +000049 command);
Abel Briggscb3c3682022-05-14 10:49:23 -050050 return -1;
Stefan Reinauer838c5a52010-01-17 14:08:17 +000051 }
52
Sven Schnelle0238a9c2011-03-14 08:18:27 +000053 outb(command, ec_cmd_reg);
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050054
Stefan Reinauer838c5a52010-01-17 14:08:17 +000055 return 0;
56}
57
58int send_ec_data(u8 data)
59{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050060 return send_ec_data_timeout(data, EC_SEND_TIMEOUT_US);
61}
Stefan Reinauer838c5a52010-01-17 14:08:17 +000062
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050063int send_ec_data_timeout(u8 data, int timeout_us)
64{
65 if (!ec_ready_send(timeout_us)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000066 printk(BIOS_DEBUG, "Timeout while sending data 0x%02x to EC!\n",
Stefan Reinauer838c5a52010-01-17 14:08:17 +000067 data);
Abel Briggscb3c3682022-05-14 10:49:23 -050068 return -1;
Stefan Reinauer838c5a52010-01-17 14:08:17 +000069 }
70
Sven Schnelle0238a9c2011-03-14 08:18:27 +000071 outb(data, ec_data_reg);
Stefan Reinauer838c5a52010-01-17 14:08:17 +000072
73 return 0;
74}
75
Abel Briggscb3c3682022-05-14 10:49:23 -050076int recv_ec_data(void)
Stefan Reinauer838c5a52010-01-17 14:08:17 +000077{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050078 return recv_ec_data_timeout(EC_RECV_TIMEOUT_US);
79}
80
Abel Briggscb3c3682022-05-14 10:49:23 -050081int recv_ec_data_timeout(int timeout_us)
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050082{
Stefan Reinauer838c5a52010-01-17 14:08:17 +000083 u8 data;
84
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050085 if (!ec_ready_recv(timeout_us)) {
86 printk(BIOS_DEBUG, "Timeout while receiving data from EC!\n");
Abel Briggscb3c3682022-05-14 10:49:23 -050087 return -1;
Stefan Reinauer838c5a52010-01-17 14:08:17 +000088 }
89
Sven Schnelle0238a9c2011-03-14 08:18:27 +000090 data = inb(ec_data_reg);
Felix Held0854f672023-04-13 20:06:22 +020091 printk(BIOS_SPEW, "Data from EC: 0x%02x\n", data);
Stefan Reinauer838c5a52010-01-17 14:08:17 +000092
93 return data;
94}
95
Bill XIEeb4ded62017-10-26 11:45:49 +080096void ec_clear_out_queue(void)
97{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -050098 int timeout = EC_RECV_TIMEOUT_US;
Bill XIEeb4ded62017-10-26 11:45:49 +080099 printk(BIOS_SPEW, "Clearing EC output queue...\n");
Abel Briggsc3bfbaf2022-04-14 22:08:41 -0500100 while (timeout > 0 && inb(ec_cmd_reg) & EC_OBF) {
Bill XIEeb4ded62017-10-26 11:45:49 +0800101 u8 data = inb(ec_data_reg);
102 printk(BIOS_SPEW, "Discarding a garbage byte: 0x%02x\n", data);
Abel Briggsc3bfbaf2022-04-14 22:08:41 -0500103 udelay(EC_POLL_DELAY_US);
104 timeout -= EC_POLL_DELAY_US;
Bill XIEeb4ded62017-10-26 11:45:49 +0800105 }
Abel Briggsc3bfbaf2022-04-14 22:08:41 -0500106 if (timeout <= 0)
Bill XIEeb4ded62017-10-26 11:45:49 +0800107 printk(BIOS_ERR, "Timeout while clearing EC output queue!\n");
108 else
109 printk(BIOS_SPEW, "EC output queue has been cleared.\n");
110}
111
Stefan Reinauer838c5a52010-01-17 14:08:17 +0000112u8 ec_read(u8 addr)
113{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -0500114 send_ec_command(RD_EC);
Stefan Reinauer838c5a52010-01-17 14:08:17 +0000115 send_ec_data(addr);
116
117 return recv_ec_data();
118}
119
120int ec_write(u8 addr, u8 data)
121{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -0500122 send_ec_command(WR_EC);
Stefan Reinauer838c5a52010-01-17 14:08:17 +0000123 send_ec_data(addr);
124 return send_ec_data(data);
125}
126
Nico Huber105d8e82017-01-23 13:54:41 +0100127u8 ec_status(void)
128{
129 return inb(ec_cmd_reg);
130}
131
Sven Schnellef9a0b922011-03-15 09:52:07 +0000132u8 ec_query(void)
133{
Abel Briggsc3bfbaf2022-04-14 22:08:41 -0500134 send_ec_command(QR_EC);
Sven Schnellef9a0b922011-03-15 09:52:07 +0000135 return recv_ec_data();
136}
137
Sven Schnelle8d94d7c2011-03-14 08:18:17 +0000138void ec_set_bit(u8 addr, u8 bit)
139{
140 ec_write(addr, ec_read(addr) | (1 << bit));
141}
142
143void ec_clr_bit(u8 addr, u8 bit)
144{
145 ec_write(addr, ec_read(addr) & ~(1 << bit));
146}
147
Sven Schnelle0238a9c2011-03-14 08:18:27 +0000148void ec_set_ports(u16 cmd_reg, u16 data_reg)
149{
Arthur Heymans6acc05e2022-05-12 18:01:13 +0200150 if (!ENV_HAS_DATA_SECTION)
Kyösti Mälkki4a637802019-09-13 11:30:45 +0300151 return;
152
Sven Schnelle0238a9c2011-03-14 08:18:27 +0000153 ec_cmd_reg = cmd_reg;
154 ec_data_reg = data_reg;
155}