• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <delay.h>
6 #include <device/device.h>
7 #include <device/pnp.h>
8 #include <pc80/keyboard.h>
9 
10 #include "ec.h"
11 #include "chip.h"
12 
13 /* helper functions from drivers/pc80/keyboard.c */
input_buffer_empty(u16 status_reg)14 static int input_buffer_empty(u16 status_reg)
15 {
16 	u32 timeout;
17 	for (timeout = KBC_TIMEOUT_IN_MS; timeout && (inb(status_reg) & KBD_IBF);
18 	    timeout--) {
19 		udelay(1000);
20 	}
21 
22 	if (!timeout) {
23 		printk(BIOS_WARNING, "EC-IT8518 Unexpected input buffer full\n");
24 		printk(BIOS_WARNING, "  Status (0x%x): 0x%x\n", status_reg, inb(status_reg));
25 	}
26 	return !!timeout;
27 }
28 
output_buffer_full(u16 status_reg)29 static int output_buffer_full(u16 status_reg)
30 {
31 	u32 timeout;
32 	for (timeout = KBC_TIMEOUT_IN_MS; timeout && ((inb(status_reg)
33 	    & KBD_OBF) == 0); timeout--) {
34 		udelay(1000);
35 	}
36 
37 	if (!timeout) {
38 		printk(BIOS_INFO, "EC-IT8518 output buffer result timeout\n");
39 		printk(BIOS_INFO, "  Status (0x%x): 0x%x\n", status_reg, inb(status_reg));
40 	}
41 	return !!timeout;
42 }
43 
44 /* The IT8518 60/64 EC registers are the same command/status IB/OB KBC pair.
45  * Check status from 64 port before each command.
46  *
47  *  Ex. Get panel ID command C43/D77
48  *  Check IBF empty. Then Write 0x43(CMD) to 0x64 Port
49  *  Check IBF empty. Then Write 0x77(DATA) to 0x60 Port
50  *  Check OBF set. Then Get Data(0x03:panel ID) from 0x60
51  * Different commands return may or may not respond and may have multiple
52  * bytes. Keep it simple for nor
53  */
54 
ec_kbc_read_ob(void)55 u8 ec_kbc_read_ob(void)
56 {
57 	if (!output_buffer_full(KBD_STATUS)) return 0;
58 	return inb(KBD_DATA);
59 }
60 
ec_kbc_write_cmd(u8 cmd)61 void ec_kbc_write_cmd(u8 cmd)
62 {
63 	if (!input_buffer_empty(KBD_STATUS)) return;
64 	outb(cmd, KBD_COMMAND);
65 }
66 
ec_kbc_write_ib(u8 data)67 void ec_kbc_write_ib(u8 data)
68 {
69 	if (!input_buffer_empty(KBD_STATUS)) return;
70 	outb(data, KBD_DATA);
71 }
72 
73 /*
74  * These functions are for accessing the IT8518 device RAM space via 0x66/0x68
75  */
76 
ec_read_ob(void)77 u8 ec_read_ob(void)
78 {
79 	if (!output_buffer_full(EC_SC)) return 0;
80 	return inb(EC_DATA);
81 }
82 
ec_write_cmd(u8 cmd)83 void ec_write_cmd(u8 cmd)
84 {
85 	if (!input_buffer_empty(EC_SC)) return;
86 	outb(cmd, EC_SC);
87 }
88 
ec_write_ib(u8 data)89 void ec_write_ib(u8 data)
90 {
91 	if (!input_buffer_empty(EC_SC)) return;
92 	outb(data, EC_DATA);
93 }
94 
ec_read(u16 addr)95 u8 ec_read(u16 addr)
96 {
97 	ec_write_cmd(RD_EC);
98 	ec_write_ib(addr);
99 	return ec_read_ob();
100 }
101 
ec_write(u16 addr,u8 data)102 void ec_write(u16 addr, u8 data)
103 {
104 	ec_write_cmd(WR_EC);
105 	ec_write_ib(addr);
106 	ec_write_ib(data);
107 }
108 
ec_it8518_get_event(void)109 u8 ec_it8518_get_event(void)
110 {
111 	u8 cmd = 0;
112 	u8 status = inb(EC_SC);
113 	if (status & SCI_EVT) {
114 		ec_write_cmd(QR_EC);
115 		cmd = ec_read_ob();
116 	} else if (status & SMI_EVT) {
117 		ec_kbc_write_cmd(EC_KBD_SMI_EVENT);
118 		cmd = ec_kbc_read_ob();
119 	}
120 	return cmd;
121 }
122 
ec_it8518_enable_wake_events(void)123 void ec_it8518_enable_wake_events(void)
124 {
125 	/*
126 	 * Set the bit in ECRAM that will enable the Lid switch as a wake source
127 	 */
128 	u8 reg8 = ec_read(EC_WAKE_SRC_ENABLE);
129 	ec_write(EC_WAKE_SRC_ENABLE, reg8 | EC_LID_WAKE_ENABLE);
130 }
131 
it8518_init(struct device * dev)132 static void it8518_init(struct device *dev)
133 {
134 	if (!dev->enabled)
135 		return;
136 
137 	printk(BIOS_DEBUG, "Quanta IT8518: Initializing keyboard.\n");
138 	pc_keyboard_init(NO_AUX_DEVICE);
139 }
140 
141 static struct device_operations ops = {
142 	.init             = it8518_init,
143 	.read_resources   = noop_read_resources,
144 	.set_resources    = noop_set_resources,
145 };
146 
147 static struct pnp_info pnp_dev_info[] = {
148 	{ NULL, 0, 0, 0, }
149 };
150 
enable_dev(struct device * dev)151 static void enable_dev(struct device *dev)
152 {
153 	pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
154 }
155 
156 struct chip_operations ec_quanta_it8518_ops = {
157 	.name = "QUANTA IT8518 EC",
158 	.enable_dev = enable_dev
159 };
160