blob: 15c04003c3f9489c95247eb8d112449d7c36b2e7 [file] [log] [blame]
Angel Pons210a0082020-04-02 23:48:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -08003
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -07004#include <arch/io.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +10005#include <console/console.h>
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -08006#include <device/device.h>
7#include <device/pnp.h>
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -08008#include <delay.h>
9#include <elog.h>
Edward O'Callaghane1fe6882014-04-30 20:41:41 +100010#include <pc80/keyboard.h>
Edward O'Callaghanb57fef92014-06-17 20:13:08 +100011
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -080012#include "ec.h"
13#include "chip.h"
14
15/* kbc helper functions from drivers/pc80/keyboard.c */
16static int ec_input_buffer_empty(u8 status_port)
17{
18 u32 timeout;
Elyes HAOUAS2b010b82016-08-25 20:57:08 +020019 for (timeout = KBC_TIMEOUT_IN_MS; timeout && (inb(status_port) & KBD_IBF);
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -080020 timeout--) {
21 mdelay(1);
22 }
23
24 if (!timeout) {
25 printk(BIOS_WARNING, "Unexpected EC/KBD input buffer full\n");
26 }
27 return !!timeout;
28}
29
30
31static int ec_output_buffer_full(u8 status_port)
32{
33 u32 timeout;
Elyes HAOUAS2b010b82016-08-25 20:57:08 +020034 for (timeout = KBC_TIMEOUT_IN_MS; timeout && ((inb(status_port)
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -080035 & KBD_OBF) == 0); timeout--) {
36 mdelay(1);
37 }
38
39 if (!timeout) {
40 printk(BIOS_INFO, "EC/KBD output buffer result timeout\n");
41 }
42 return !!timeout;
43}
44
45
46
47/* The ENE 60/64 EC registers are the same command/status IB/OB KBC pair.
48 * Check status from 64 port before each command.
49 *
50 * Ex. Get panel ID command C43/D77
51 * Check IBF empty. Then Write 0x43(CMD) to 0x64 Port
52 * Check IBF empty. Then Write 0x77(DATA) to 0x60 Port
53 * Check OBF set. Then Get Data(0x03:panel ID) from 0x60
54 * Different commands return may or may not respond and may have multiple
55 * bytes. Keep it simple for now
56 */
57
58u8 ec_kbc_read_ob(void)
59{
60 if (!ec_output_buffer_full(KBD_STATUS)) return 0;
61 return inb(KBD_DATA);
62}
63
64void ec_kbc_write_cmd(u8 cmd)
65{
66 if (!ec_input_buffer_empty(KBD_STATUS)) return;
67 outb(cmd, KBD_COMMAND);
68}
69
70void ec_kbc_write_ib(u8 data)
71{
72 if (!ec_input_buffer_empty(KBD_STATUS)) return;
73 outb(data, KBD_DATA);
74}
75
76/* EC Host Control Protocol routines */
77u8 ec_read_ob(void)
78{
79 if (!ec_output_buffer_full(EC_SC)) return 0;
80 return inb(EC_DATA);
81}
82
83void ec_write_cmd(u8 cmd)
84{
85 if (!ec_input_buffer_empty(EC_SC)) return;
86 outb(cmd, EC_COMMAND);
87}
88
89void ec_write_ib(u8 data)
90{
91 if (!ec_input_buffer_empty(EC_SC)) return;
92 outb(data, EC_DATA);
93}
94
95/*
96 * These functions are for accessing the ENE932 device RAM space
97 */
98u8 ec_mem_read(u8 addr)
99{
100 ec_write_cmd(EC_CMD_READ_RAM);
101 ec_write_ib(addr);
102 return ec_read_ob();
103}
104
105void ec_mem_write(u8 addr, u8 data)
106{
107 ec_write_cmd(EC_CMD_WRITE_RAM);
108 ec_write_ib(addr);
109 ec_write_ib(data);
110 return;
111}
112
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800113static void ene_kb3940q_log_events(void)
114{
Kyösti Mälkkibe5317f2019-11-06 12:07:21 +0200115 if (CONFIG(ELOG)) {
116 u8 reason = ec_mem_read(EC_SHUTDOWN_REASON);
117 if (reason)
118 elog_add_event_byte(ELOG_TYPE_EC_SHUTDOWN, reason);
119 }
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800120}
121
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100122static void ene_kb3940q_init(struct device *dev)
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800123{
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800124 if (!dev->enabled)
125 return;
126
127 printk(BIOS_DEBUG, "Quanta EnE KB3940Q: Initializing keyboard.\n");
Timothy Pearson448e3862015-11-24 14:12:01 -0600128 pc_keyboard_init(NO_AUX_DEVICE);
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800129
130 ene_kb3940q_log_events();
131}
132
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800133static struct device_operations ops = {
134 .init = ene_kb3940q_init,
Edward O'Callaghan5f19eb62014-11-29 00:03:03 +1100135 .read_resources = DEVICE_NOOP,
136 .enable_resources = DEVICE_NOOP,
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800137};
138
139static struct pnp_info pnp_dev_info[] = {
Felix Held1d9199c2018-07-07 00:27:44 +0200140 { NULL, 0, 0, 0, }
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800141};
142
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100143static void enable_dev(struct device *dev)
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800144{
Felix Held1d9199c2018-07-07 00:27:44 +0200145 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
Stefan Reinauerd7bd4eb2013-02-11 11:11:36 -0800146}
147
148struct chip_operations ec_quanta_ene_kb3940q_ops = {
149 CHIP_NAME("QUANTA EnE KB3940Q EC")
150 .enable_dev = enable_dev
151};