blob: d0b119f8cde41723fd2afedbe5d6f4c577bd3baf [file] [log] [blame]
Sean Rhodes78342982022-03-09 08:23:29 +00001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#include <device/device.h>
5#include <device/pnp.h>
6#include <ec/acpi/ec.h>
7#include <option.h>
8#include <pc80/keyboard.h>
9
10#include "ec.h"
11#include "ecdefs.h"
12
13uint16_t ec_get_version(void)
14{
15 return (ec_read(ECRAM_MAJOR_VERSION) << 8) | ec_read(ECRAM_MINOR_VERSION);
16}
17
18static uint8_t get_ec_value_from_option(const char *name,
19 unsigned int fallback,
20 const uint8_t *lut,
21 size_t lut_size)
22{
23 unsigned int index = get_uint_option(name, fallback);
24 if (index >= lut_size)
25 index = fallback;
26 return lut[index];
27}
28
29static uint16_t ec_get_chip_id(unsigned int port)
30{
31 return pnp_read_index(port, NUVOTON_CHIPID);
32}
33
34static void merlin_init(struct device *dev)
35{
36 if (!dev->enabled)
37 return;
38
39 /*
40 * The address/data IO port pair for the Nuvoton EC are configurable
41 * through the EC domain and are fixed by the EC's firmware blob. If
42 * the value(s) passed through the "dev" structure don't match the
43 * expected values then output severe warnings.
44 */
45 if (dev->path.pnp.port != NUVOTON_FIXED_ADDR) {
46 printk(BIOS_ERR, "NUVOTON: Incorrect ports defined in devicetree.cb.\n");
47 printk(BIOS_ERR, "NUVOTON: Serious operational issues will arise.\n");
48 return;
49 }
50
51 const uint16_t chip_id = ec_get_chip_id(dev->path.pnp.port);
52
53 if (chip_id != NUVOTON_CHIPID_VAL) {
54 printk(BIOS_ERR, "NUVOTON: Expected chip ID 0x%04x, but got 0x%04x instead.\n",
55 NUVOTON_CHIPID_VAL, chip_id);
56 return;
57 }
58
59 pc_keyboard_init(NO_AUX_DEVICE);
60
61 /*
62 * Restore settings from CMOS into EC RAM:
63 *
64 * kbl_timeout
65 * fn_ctrl_swap
66 * max_charge
67 * fan_mode
68 * fn_lock_state
69 * trackpad_state
70 * kbl_brightness
71 * kbl_state
72 */
73
74 /*
75 * Keyboard Backlight Timeout
76 *
77 * Setting: kbl_timeout
78 *
79 * Values: 30 Seconds, 1 Minute, 3 Minutes, 5 Minutes, Never
80 * Default: 30 Seconds
81 *
82 */
83 const uint8_t kbl_timeout[] = {
84 SEC_30,
85 MIN_1,
86 MIN_3,
87 MIN_5,
88 NEVER
89 };
90
91 ec_write(ECRAM_KBL_TIMEOUT,
92 get_ec_value_from_option("kbl_timeout",
93 0,
94 kbl_timeout,
95 ARRAY_SIZE(kbl_timeout)));
96
97 /*
98 * Fn Ctrl Reverse
99 *
100 * Setting: fn_ctrl_swap
101 *
102 * Values: Enabled, Disabled
103 * Default: Disabled
104 *
105 */
106 const uint8_t fn_ctrl_swap[] = {
107 FN_CTRL,
108 CTRL_FN
109 };
110
111 ec_write(ECRAM_FN_CTRL_REVERSE,
112 get_ec_value_from_option("fn_ctrl_swap",
Sean Rhodes543bba82023-05-02 10:54:49 +0100113 0,
Sean Rhodes78342982022-03-09 08:23:29 +0000114 fn_ctrl_swap,
115 ARRAY_SIZE(fn_ctrl_swap)));
116
117 /*
118 * Maximum Charge Level
119 *
120 * Setting: max_charge
121 *
122 * Values: 60%, 80%, 100%
123 * Default: 100%
124 *
125 */
126 const uint8_t max_charge[] = {
127 CHARGE_100,
128 CHARGE_80,
129 CHARGE_60
130 };
131
132 if (CONFIG(EC_STARLABS_MAX_CHARGE))
133 ec_write(ECRAM_MAX_CHARGE,
134 get_ec_value_from_option("max_charge",
135 0,
136 max_charge,
137 ARRAY_SIZE(max_charge)));
138
139 /*
Sean Rhodes8de7c012022-07-31 17:35:28 +0100140 * Fast Charge
141 *
142 * Setting: fast_charge
143 *
144 * Values: Normal, Fast
145 * Default: Normal
146 *
147 */
148 const uint8_t fast_charge[] = {
149 CHARGE_RATE_NORMAL,
150 CHARGE_RATE_FAST
151 };
152
153 if (CONFIG(EC_STARLABS_FAST_CHARGE))
154 ec_write(ECRAM_FAST_CHARGE,
155 get_ec_value_from_option("fast_charge",
156 0,
157 fast_charge,
158 ARRAY_SIZE(fast_charge)));
159
160 /*
Sean Rhodes78342982022-03-09 08:23:29 +0000161 * Fan Mode
162 *
163 * Setting: fan_mode
164 *
165 * Values: Quiet, Normal, Aggressive
166 * Default: Normal
167 *
168 */
169 const uint8_t fan_mode[] = {
170 FAN_NORMAL,
171 FAN_AGGRESSIVE,
172 FAN_QUIET
173 };
174
175 if (CONFIG(EC_STARLABS_FAN))
176 ec_write(ECRAM_FAN_MODE,
177 get_ec_value_from_option("fan_mode",
178 0,
179 fan_mode,
180 ARRAY_SIZE(fan_mode)));
181
182 /*
183 * Function Lock
184 *
185 * Setting: fn_lock_state
186 *
187 * Values: Locked, Unlocked
188 * Default: Locked
189 *
190 */
191 const uint8_t fn_lock_state[] = {
192 UNLOCKED,
193 LOCKED
194 };
195
196 ec_write(ECRAM_FN_LOCK_STATE,
197 get_ec_value_from_option("fn_lock_state",
198 1,
199 fn_lock_state,
200 ARRAY_SIZE(fn_lock_state)));
201
202 /*
203 * Trackpad State
204 *
205 * Setting: trackpad_state
206 *
207 * Values: Enabled, Disabled
208 * Default: Enabled
209 *
210 */
211 const uint8_t trackpad_state[] = {
212 TRACKPAD_ENABLED,
213 TRACKPAD_DISABLED
214 };
215
216 ec_write(ECRAM_TRACKPAD_STATE,
217 get_ec_value_from_option("trackpad_state",
218 0,
219 trackpad_state,
220 ARRAY_SIZE(trackpad_state)));
221
222 /*
223 * Keyboard Backlight Brightness
224 *
225 * Setting: kbl_brightness
226 *
227 * Values: Off, Low, High / Off, On
228 * Default: Low
229 *
230 */
231 const uint8_t kbl_brightness[] = {
232 KBL_ON,
233 KBL_OFF,
234 KBL_LOW,
235 KBL_HIGH
236 };
237
238 if (CONFIG(EC_STARLABS_KBL_LEVELS))
239 ec_write(ECRAM_KBL_BRIGHTNESS,
240 get_ec_value_from_option("kbl_brightness",
241 2,
242 kbl_brightness,
243 ARRAY_SIZE(kbl_brightness)));
244 else
245 ec_write(ECRAM_KBL_BRIGHTNESS,
246 get_ec_value_from_option("kbl_brightness",
247 0,
248 kbl_brightness,
249 ARRAY_SIZE(kbl_brightness)));
250
251 /*
252 * Keyboard Backlight State
253 *
254 * Setting: kbl_state
255 *
256 * Values: Off, On
257 * Default: On
258 *
Sean Rhodescbedae12023-08-16 09:25:42 +0100259 * Note: Always enable, as the brightness level of `off` disables it.
260 *
Sean Rhodes78342982022-03-09 08:23:29 +0000261 */
Sean Rhodes78342982022-03-09 08:23:29 +0000262
Sean Rhodescbedae12023-08-16 09:25:42 +0100263 ec_write(ECRAM_KBL_STATE, KBL_ENABLED);
Sean Rhodes78342982022-03-09 08:23:29 +0000264}
265
266static struct device_operations ops = {
267 .init = merlin_init,
268 .read_resources = noop_read_resources,
269 .set_resources = noop_set_resources,
270};
271
272static struct pnp_info pnp_dev_info[] = {
273 /* System Wake-Up Control (SWUC) */
274 { NULL, NUVOTON_MSWC, PNP_IO0 | PNP_IRQ0, 0xfff0, },
275 /* KBC / Mouse Interface */
276 { NULL, NUVOTON_KBCM, PNP_IRQ0, },
277 /* KBC / Keyboard Interface */
278 { NULL, NUVOTON_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
279 /* Shared Memory / Flash Interface (SMFI) */
280 { NULL, NUVOTON_SHM, PNP_IO0 | PNP_IRQ0, 0xfff0, },
281 /* Power Management I/F Channel 1 (PMC1) */
282 { NULL, NUVOTON_PM1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
283 /* Power Management I/F Channel 2 (PMC2) */
284 { NULL, NUVOTON_PM2, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0, 0x07fc,
285 0x07fc, 0xfff0, },
286 /* Power Management I/F Channel 3 (PMC3) */
287 { NULL, NUVOTON_PM3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
288 /* Extended Shared Memory (ESHM) */
289 { NULL, NUVOTON_ESHM },
290 /* Power Management I/F Channel 4 (PMC4) */
291 { NULL, NUVOTON_PM4, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
292};
293
294static void enable_dev(struct device *dev)
295{
296 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
297}
298
299struct chip_operations ec_starlabs_merlin_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +0900300 .name = "NUVOTON EC",
Sean Rhodes78342982022-03-09 08:23:29 +0000301 .enable_dev = enable_dev
302};