commonlib: Add new "ESE completed AUnit loading" TS
[coreboot.git] / src / ec / starlabs / merlin / nuvoton.c
blobf62bcdf3ae4c78e34d313953ace8c076aadb192a
1 /* SPDX-License-Identifier: GPL-2.0-only */
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/mc146818rtc.h>
9 #include <halt.h>
11 #include "ecdefs.h"
12 #include "option_table.h"
13 #include "ec.h"
16 uint16_t ec_get_version(void)
18 return (ec_read(ECRAM_MAJOR_VERSION) << 8) | ec_read(ECRAM_MINOR_VERSION);
21 static uint8_t get_cmos_value(uint32_t bit, uint32_t length)
23 uint32_t byte, byte_bit;
24 uint8_t uchar;
26 byte = bit / 8; // find the byte where the data starts
27 byte_bit = bit % 8; // find the bit in the byte where the data starts
29 uchar = cmos_read(byte); // load the byte
30 uchar >>= byte_bit; // shift the bits to byte align
31 // clear unspecified bits
32 return uchar & ((1U << length) - 1);
35 static uint8_t get_ec_value_from_option(const char *name,
36 uint32_t fallback,
37 const uint8_t *lut,
38 size_t lut_size,
39 uint32_t cmos_start_bit,
40 uint32_t cmos_length)
42 unsigned int index;
44 if (cmos_start_bit != UINT_MAX)
45 index = get_cmos_value(cmos_start_bit, cmos_length);
46 else
47 index = get_uint_option(name, fallback);
49 if (index >= lut_size)
50 index = fallback;
51 return lut[index];
54 static uint16_t ec_get_chip_id(unsigned int port)
56 return pnp_read_index(port, NUVOTON_CHIPID);
59 static void merlin_init(struct device *dev)
61 if (!dev->enabled)
62 return;
65 * The address/data IO port pair for the Nuvoton EC are configurable
66 * through the EC domain and are fixed by the EC's firmware blob. If
67 * the value(s) passed through the "dev" structure don't match the
68 * expected values then output severe warnings.
70 if (dev->path.pnp.port != NUVOTON_FIXED_ADDR) {
71 printk(BIOS_ERR, "NUVOTON: Incorrect ports defined in devicetree.cb.\n");
72 printk(BIOS_ERR, "NUVOTON: Serious operational issues will arise.\n");
73 return;
76 const uint16_t chip_id = ec_get_chip_id(dev->path.pnp.port);
78 if (chip_id != NUVOTON_CHIPID_VAL) {
79 printk(BIOS_ERR, "NUVOTON: Expected chip ID 0x%04x, but got 0x%04x instead.\n",
80 NUVOTON_CHIPID_VAL, chip_id);
81 return;
85 * Restore settings from CMOS into EC RAM:
87 * kbl_timeout
88 * fn_ctrl_swap
89 * max_charge
90 * fan_mode
91 * fn_lock_state
92 * trackpad_state
93 * kbl_brightness
94 * kbl_state
98 * Keyboard Backlight Timeout
100 * Setting: kbl_timeout
102 * Values: 30 Seconds, 1 Minute, 3 Minutes, 5 Minutes, Never
103 * Default: 30 Seconds
106 const uint8_t kbl_timeout[] = {
107 SEC_30,
108 MIN_1,
109 MIN_3,
110 MIN_5,
111 NEVER
114 ec_write(ECRAM_KBL_TIMEOUT,
115 get_ec_value_from_option("kbl_timeout",
117 kbl_timeout,
118 ARRAY_SIZE(kbl_timeout),
119 UINT_MAX,
120 UINT_MAX));
123 * Fn Ctrl Reverse
125 * Setting: fn_ctrl_swap
127 * Values: Enabled, Disabled
128 * Default: Disabled
131 const uint8_t fn_ctrl_swap[] = {
132 FN_CTRL,
133 CTRL_FN
136 ec_write(ECRAM_FN_CTRL_REVERSE,
137 get_ec_value_from_option("fn_ctrl_swap",
139 fn_ctrl_swap,
140 ARRAY_SIZE(fn_ctrl_swap),
141 UINT_MAX,
142 UINT_MAX));
145 * Maximum Charge Level
147 * Setting: max_charge
149 * Values: 60%, 80%, 100%
150 * Default: 100%
153 const uint8_t max_charge[] = {
154 CHARGE_100,
155 CHARGE_80,
156 CHARGE_60
159 if (CONFIG(EC_STARLABS_MAX_CHARGE))
160 ec_write(ECRAM_MAX_CHARGE,
161 get_ec_value_from_option("max_charge",
163 max_charge,
164 ARRAY_SIZE(max_charge),
165 UINT_MAX,
166 UINT_MAX));
169 * Fast Charge
171 * Setting: fast_charge
173 * Values: Normal, Fast
174 * Default: Normal
177 const uint8_t fast_charge[] = {
178 CHARGE_RATE_NORMAL,
179 CHARGE_RATE_FAST
182 if (CONFIG(EC_STARLABS_FAST_CHARGE))
183 ec_write(ECRAM_FAST_CHARGE,
184 get_ec_value_from_option("fast_charge",
186 fast_charge,
187 ARRAY_SIZE(fast_charge),
188 UINT_MAX,
189 UINT_MAX));
192 * Fan Mode
194 * Setting: fan_mode
196 * Values: Quiet, Normal, Aggressive
197 * Default: Normal
200 const uint8_t fan_mode[] = {
201 FAN_NORMAL,
202 FAN_AGGRESSIVE,
203 FAN_QUIET
206 if (CONFIG(EC_STARLABS_FAN))
207 ec_write(ECRAM_FAN_MODE,
208 get_ec_value_from_option("fan_mode",
210 fan_mode,
211 ARRAY_SIZE(fan_mode),
212 UINT_MAX,
213 UINT_MAX));
216 * Function Lock
218 * Setting: fn_lock_state
220 * Values: Locked, Unlocked
221 * Default: Locked
224 #ifdef CMOS_VLEN_fn_lock_state
225 const uint8_t fn_lock_state[] = {
226 UNLOCKED,
227 LOCKED
230 ec_write(ECRAM_FN_LOCK_STATE,
231 get_ec_value_from_option("fn_lock_state",
233 fn_lock_state,
234 ARRAY_SIZE(fn_lock_state),
235 CMOS_VSTART_fn_lock_state,
236 CMOS_VLEN_fn_lock_state));
237 #endif
240 * Trackpad State
242 * Setting: trackpad_state
244 * Values: Enabled, Disabled
245 * Default: Enabled
248 #ifdef CMOS_VSTART_trackpad_state
249 const uint8_t trackpad_state[] = {
250 TRACKPAD_ENABLED,
251 TRACKPAD_DISABLED
254 ec_write(ECRAM_TRACKPAD_STATE,
255 get_ec_value_from_option("trackpad_state",
257 trackpad_state,
258 ARRAY_SIZE(trackpad_state),
259 CMOS_VSTART_trackpad_state,
260 CMOS_VLEN_trackpad_state));
261 #endif
264 * Keyboard Backlight Brightness
266 * Setting: kbl_brightness
268 * Values: Off, Low, High / Off, On
269 * Default: Low
272 #ifdef CMOS_VSTART_kbl_brightness
273 const uint8_t kbl_brightness[] = {
274 KBL_ON,
275 KBL_OFF,
276 KBL_LOW,
277 KBL_HIGH
280 ec_write(ECRAM_KBL_BRIGHTNESS,
281 get_ec_value_from_option("kbl_brightness",
282 CONFIG(EC_STARLABS_KBL_LEVELS) ? 2 : 0,
283 kbl_brightness,
284 ARRAY_SIZE(kbl_brightness),
285 CMOS_VSTART_kbl_brightness,
286 CMOS_VLEN_kbl_brightness));
288 #endif
292 * Keyboard Backlight State
294 * Setting: kbl_state
296 * Values: Off, On
297 * Default: On
299 * Note: Always enable, as the brightness level of `off` disables it.
303 ec_write(ECRAM_KBL_STATE, KBL_ENABLED);
306 static struct device_operations ops = {
307 .init = merlin_init,
308 .read_resources = noop_read_resources,
309 .set_resources = noop_set_resources,
312 static struct pnp_info pnp_dev_info[] = {
313 /* System Wake-Up Control (SWUC) */
314 { NULL, NUVOTON_MSWC, PNP_IO0 | PNP_IRQ0, 0xfff0, },
315 /* KBC / Mouse Interface */
316 { NULL, NUVOTON_KBCM, PNP_IRQ0, },
317 /* KBC / Keyboard Interface */
318 { NULL, NUVOTON_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
319 /* Shared Memory / Flash Interface (SMFI) */
320 { NULL, NUVOTON_SHM, PNP_IO0 | PNP_IRQ0, 0xfff0, },
321 /* Power Management I/F Channel 1 (PMC1) */
322 { NULL, NUVOTON_PM1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
323 /* Power Management I/F Channel 2 (PMC2) */
324 { NULL, NUVOTON_PM2, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0, 0x07fc,
325 0x07fc, 0xfff0, },
326 /* Power Management I/F Channel 3 (PMC3) */
327 { NULL, NUVOTON_PM3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
328 /* Extended Shared Memory (ESHM) */
329 { NULL, NUVOTON_ESHM },
330 /* Power Management I/F Channel 4 (PMC4) */
331 { NULL, NUVOTON_PM4, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
334 static void enable_dev(struct device *dev)
336 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
339 struct chip_operations ec_starlabs_merlin_ops = {
340 .name = "NUVOTON EC",
341 .enable_dev = enable_dev