From 78342989c48619accf2d3f1a175876fa91cb15ac Mon Sep 17 00:00:00 2001 From: Sean Rhodes Date: Wed, 9 Mar 2022 08:23:29 +0000 Subject: ec/starlabs/merlin: Add support for Nuvoton EC's Support was created for the NPCE9m5x series, using version 1.1 of the datasheet. The specific model tested was the NPCE985P/G, on the StarLite Mk IV with version 1.00 of the EC firmware. Signed-off-by: Sean Rhodes Change-Id: Ib66baf1e88f5d548ce955dffa00c9b88255b2f95 Reviewed-on: https://review.coreboot.org/c/coreboot/+/62702 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Paul Menzel --- src/ec/starlabs/merlin/nuvoton.c | 287 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 src/ec/starlabs/merlin/nuvoton.c (limited to 'src/ec/starlabs/merlin/nuvoton.c') diff --git a/src/ec/starlabs/merlin/nuvoton.c b/src/ec/starlabs/merlin/nuvoton.c new file mode 100644 index 0000000000..ee8a66176f --- /dev/null +++ b/src/ec/starlabs/merlin/nuvoton.c @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +#include "ec.h" +#include "ecdefs.h" + +uint16_t ec_get_version(void) +{ + return (ec_read(ECRAM_MAJOR_VERSION) << 8) | ec_read(ECRAM_MINOR_VERSION); +} + +static uint8_t get_ec_value_from_option(const char *name, + unsigned int fallback, + const uint8_t *lut, + size_t lut_size) +{ + unsigned int index = get_uint_option(name, fallback); + if (index >= lut_size) + index = fallback; + return lut[index]; +} + +static uint16_t ec_get_chip_id(unsigned int port) +{ + return pnp_read_index(port, NUVOTON_CHIPID); +} + +static void merlin_init(struct device *dev) +{ + if (!dev->enabled) + return; + + /* + * The address/data IO port pair for the Nuvoton EC are configurable + * through the EC domain and are fixed by the EC's firmware blob. If + * the value(s) passed through the "dev" structure don't match the + * expected values then output severe warnings. + */ + if (dev->path.pnp.port != NUVOTON_FIXED_ADDR) { + printk(BIOS_ERR, "NUVOTON: Incorrect ports defined in devicetree.cb.\n"); + printk(BIOS_ERR, "NUVOTON: Serious operational issues will arise.\n"); + return; + } + + const uint16_t chip_id = ec_get_chip_id(dev->path.pnp.port); + + if (chip_id != NUVOTON_CHIPID_VAL) { + printk(BIOS_ERR, "NUVOTON: Expected chip ID 0x%04x, but got 0x%04x instead.\n", + NUVOTON_CHIPID_VAL, chip_id); + return; + } + + pc_keyboard_init(NO_AUX_DEVICE); + + /* + * Restore settings from CMOS into EC RAM: + * + * kbl_timeout + * fn_ctrl_swap + * max_charge + * fan_mode + * fn_lock_state + * trackpad_state + * kbl_brightness + * kbl_state + */ + + /* + * Keyboard Backlight Timeout + * + * Setting: kbl_timeout + * + * Values: 30 Seconds, 1 Minute, 3 Minutes, 5 Minutes, Never + * Default: 30 Seconds + * + */ + const uint8_t kbl_timeout[] = { + SEC_30, + MIN_1, + MIN_3, + MIN_5, + NEVER + }; + + ec_write(ECRAM_KBL_TIMEOUT, + get_ec_value_from_option("kbl_timeout", + 0, + kbl_timeout, + ARRAY_SIZE(kbl_timeout))); + + /* + * Fn Ctrl Reverse + * + * Setting: fn_ctrl_swap + * + * Values: Enabled, Disabled + * Default: Disabled + * + */ + const uint8_t fn_ctrl_swap[] = { + FN_CTRL, + CTRL_FN + }; + + ec_write(ECRAM_FN_CTRL_REVERSE, + get_ec_value_from_option("fn_ctrl_swap", + 1, + fn_ctrl_swap, + ARRAY_SIZE(fn_ctrl_swap))); + + /* + * Maximum Charge Level + * + * Setting: max_charge + * + * Values: 60%, 80%, 100% + * Default: 100% + * + */ + const uint8_t max_charge[] = { + CHARGE_100, + CHARGE_80, + CHARGE_60 + }; + + if (CONFIG(EC_STARLABS_MAX_CHARGE)) + ec_write(ECRAM_MAX_CHARGE, + get_ec_value_from_option("max_charge", + 0, + max_charge, + ARRAY_SIZE(max_charge))); + + /* + * Fan Mode + * + * Setting: fan_mode + * + * Values: Quiet, Normal, Aggressive + * Default: Normal + * + */ + const uint8_t fan_mode[] = { + FAN_NORMAL, + FAN_AGGRESSIVE, + FAN_QUIET + }; + + if (CONFIG(EC_STARLABS_FAN)) + ec_write(ECRAM_FAN_MODE, + get_ec_value_from_option("fan_mode", + 0, + fan_mode, + ARRAY_SIZE(fan_mode))); + + /* + * Function Lock + * + * Setting: fn_lock_state + * + * Values: Locked, Unlocked + * Default: Locked + * + */ + const uint8_t fn_lock_state[] = { + UNLOCKED, + LOCKED + }; + + ec_write(ECRAM_FN_LOCK_STATE, + get_ec_value_from_option("fn_lock_state", + 1, + fn_lock_state, + ARRAY_SIZE(fn_lock_state))); + + /* + * Trackpad State + * + * Setting: trackpad_state + * + * Values: Enabled, Disabled + * Default: Enabled + * + */ + const uint8_t trackpad_state[] = { + TRACKPAD_ENABLED, + TRACKPAD_DISABLED + }; + + ec_write(ECRAM_TRACKPAD_STATE, + get_ec_value_from_option("trackpad_state", + 0, + trackpad_state, + ARRAY_SIZE(trackpad_state))); + + /* + * Keyboard Backlight Brightness + * + * Setting: kbl_brightness + * + * Values: Off, Low, High / Off, On + * Default: Low + * + */ + const uint8_t kbl_brightness[] = { + KBL_ON, + KBL_OFF, + KBL_LOW, + KBL_HIGH + }; + + if (CONFIG(EC_STARLABS_KBL_LEVELS)) + ec_write(ECRAM_KBL_BRIGHTNESS, + get_ec_value_from_option("kbl_brightness", + 2, + kbl_brightness, + ARRAY_SIZE(kbl_brightness))); + else + ec_write(ECRAM_KBL_BRIGHTNESS, + get_ec_value_from_option("kbl_brightness", + 0, + kbl_brightness, + ARRAY_SIZE(kbl_brightness))); + + /* + * Keyboard Backlight State + * + * Setting: kbl_state + * + * Values: Off, On + * Default: On + * + */ + const uint8_t kbl_state[] = { + KBL_DISABLED, + KBL_ENABLED + }; + + ec_write(ECRAM_KBL_STATE, + get_ec_value_from_option("kbl_state", + 1, + kbl_state, + ARRAY_SIZE(kbl_state))); +} + +static struct device_operations ops = { + .init = merlin_init, + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, +}; + +static struct pnp_info pnp_dev_info[] = { + /* System Wake-Up Control (SWUC) */ + { NULL, NUVOTON_MSWC, PNP_IO0 | PNP_IRQ0, 0xfff0, }, + /* KBC / Mouse Interface */ + { NULL, NUVOTON_KBCM, PNP_IRQ0, }, + /* KBC / Keyboard Interface */ + { NULL, NUVOTON_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, }, + /* Shared Memory / Flash Interface (SMFI) */ + { NULL, NUVOTON_SHM, PNP_IO0 | PNP_IRQ0, 0xfff0, }, + /* Power Management I/F Channel 1 (PMC1) */ + { NULL, NUVOTON_PM1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, }, + /* Power Management I/F Channel 2 (PMC2) */ + { NULL, NUVOTON_PM2, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0, 0x07fc, + 0x07fc, 0xfff0, }, + /* Power Management I/F Channel 3 (PMC3) */ + { NULL, NUVOTON_PM3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, }, + /* Extended Shared Memory (ESHM) */ + { NULL, NUVOTON_ESHM }, + /* Power Management I/F Channel 4 (PMC4) */ + { NULL, NUVOTON_PM4, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, }, +}; + +static void enable_dev(struct device *dev) +{ + pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info); +} + +struct chip_operations ec_starlabs_merlin_ops = { + CHIP_NAME("NUVOTON EC") + .enable_dev = enable_dev +}; -- cgit v1.2.3