xref: /aosp_15_r20/external/coreboot/src/ec/acpi/ec.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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