1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <console/console.h>
4 #include <arch/io.h>
5 #include <delay.h>
6 #include <types.h>
7 #include "ec.h"
8
9 #define EC_POLL_DELAY_US 10
10 #define EC_SEND_TIMEOUT_US 20000 // 20ms
11 #define EC_RECV_TIMEOUT_US 320000 // 320ms
12
13 static u16 ec_cmd_reg = EC_SC;
14 static u16 ec_data_reg = EC_DATA;
15
16 /*
17 * Poll the EC status/command register for a specified
18 * state until the given timeout elapses.
19 */
wait_ec_sc(int timeout_us,u8 mask,u8 state)20 static 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
ec_ready_send(int timeout_us)30 bool ec_ready_send(int timeout_us)
31 {
32 return wait_ec_sc(timeout_us, EC_IBF, 0) == 0;
33 }
34
ec_ready_recv(int timeout_us)35 bool ec_ready_recv(int timeout_us)
36 {
37 return wait_ec_sc(timeout_us, EC_OBF, EC_OBF) == 0;
38 }
39
send_ec_command(u8 command)40 int send_ec_command(u8 command)
41 {
42 return send_ec_command_timeout(command, EC_SEND_TIMEOUT_US);
43 }
44
send_ec_command_timeout(u8 command,int timeout_us)45 int send_ec_command_timeout(u8 command, int timeout_us)
46 {
47 if (!ec_ready_send(timeout_us)) {
48 printk(BIOS_DEBUG, "Timeout while sending command 0x%02x to EC!\n",
49 command);
50 return -1;
51 }
52
53 outb(command, ec_cmd_reg);
54
55 return 0;
56 }
57
send_ec_data(u8 data)58 int send_ec_data(u8 data)
59 {
60 return send_ec_data_timeout(data, EC_SEND_TIMEOUT_US);
61 }
62
send_ec_data_timeout(u8 data,int timeout_us)63 int send_ec_data_timeout(u8 data, int timeout_us)
64 {
65 if (!ec_ready_send(timeout_us)) {
66 printk(BIOS_DEBUG, "Timeout while sending data 0x%02x to EC!\n",
67 data);
68 return -1;
69 }
70
71 outb(data, ec_data_reg);
72
73 return 0;
74 }
75
recv_ec_data(void)76 int recv_ec_data(void)
77 {
78 return recv_ec_data_timeout(EC_RECV_TIMEOUT_US);
79 }
80
recv_ec_data_timeout(int timeout_us)81 int recv_ec_data_timeout(int timeout_us)
82 {
83 u8 data;
84
85 if (!ec_ready_recv(timeout_us)) {
86 printk(BIOS_DEBUG, "Timeout while receiving data from EC!\n");
87 return -1;
88 }
89
90 data = inb(ec_data_reg);
91 printk(BIOS_SPEW, "Data from EC: 0x%02x\n", data);
92
93 return data;
94 }
95
ec_clear_out_queue(void)96 void ec_clear_out_queue(void)
97 {
98 int timeout = EC_RECV_TIMEOUT_US;
99 printk(BIOS_SPEW, "Clearing EC output queue...\n");
100 while (timeout > 0 && inb(ec_cmd_reg) & EC_OBF) {
101 u8 data = inb(ec_data_reg);
102 printk(BIOS_SPEW, "Discarding a garbage byte: 0x%02x\n", data);
103 udelay(EC_POLL_DELAY_US);
104 timeout -= EC_POLL_DELAY_US;
105 }
106 if (timeout <= 0)
107 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
ec_read(u8 addr)112 u8 ec_read(u8 addr)
113 {
114 send_ec_command(RD_EC);
115 send_ec_data(addr);
116
117 return recv_ec_data();
118 }
119
ec_write(u8 addr,u8 data)120 int ec_write(u8 addr, u8 data)
121 {
122 send_ec_command(WR_EC);
123 send_ec_data(addr);
124 return send_ec_data(data);
125 }
126
ec_status(void)127 u8 ec_status(void)
128 {
129 return inb(ec_cmd_reg);
130 }
131
ec_query(void)132 u8 ec_query(void)
133 {
134 send_ec_command(QR_EC);
135 return recv_ec_data();
136 }
137
ec_set_bit(u8 addr,u8 bit)138 void ec_set_bit(u8 addr, u8 bit)
139 {
140 ec_write(addr, ec_read(addr) | (1 << bit));
141 }
142
ec_clr_bit(u8 addr,u8 bit)143 void ec_clr_bit(u8 addr, u8 bit)
144 {
145 ec_write(addr, ec_read(addr) & ~(1 << bit));
146 }
147
ec_set_ports(u16 cmd_reg,u16 data_reg)148 void ec_set_ports(u16 cmd_reg, u16 data_reg)
149 {
150 ec_cmd_reg = cmd_reg;
151 ec_data_reg = data_reg;
152 }
153