Máté Kukri has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/55250 )
Change subject: [WIP] src/superio/smsc: Add support for the SCH5555 ......................................................................
[WIP] src/superio/smsc: Add support for the SCH5555
Signed-off-by: Mate Kukri kukri.mate@gmail.com Change-Id: I9323198f1139cd0c3dd37f977ae7693b721654f4 --- M src/superio/smsc/Makefile.inc A src/superio/smsc/sch5555/Kconfig A src/superio/smsc/sch5555/Makefile.inc A src/superio/smsc/sch5555/sch5555.h A src/superio/smsc/sch5555/sch5555_bootblock.c A src/superio/smsc/sch5555/sch5555_common.c 6 files changed, 248 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/50/55250/1
diff --git a/src/superio/smsc/Makefile.inc b/src/superio/smsc/Makefile.inc index 86cf9c5..a65789a 100644 --- a/src/superio/smsc/Makefile.inc +++ b/src/superio/smsc/Makefile.inc @@ -13,3 +13,4 @@ subdirs-y += smscsuperio subdirs-y += sio1036 subdirs-y += sch5545 +subdirs-y += sch5555 diff --git a/src/superio/smsc/sch5555/Kconfig b/src/superio/smsc/sch5555/Kconfig new file mode 100644 index 0000000..2745b68 --- /dev/null +++ b/src/superio/smsc/sch5555/Kconfig @@ -0,0 +1,4 @@ +## SPDX-License-Identifier: GPL-2.0-only + +config SUPERIO_SMSC_SCH5555 + bool diff --git a/src/superio/smsc/sch5555/Makefile.inc b/src/superio/smsc/sch5555/Makefile.inc new file mode 100644 index 0000000..58c896e --- /dev/null +++ b/src/superio/smsc/sch5555/Makefile.inc @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +bootblock-$(CONFIG_SUPERIO_SMSC_SCH5555) += sch5555_common.c sch5555_bootblock.c +# ramstage-$(CONFIG_SUPERIO_SMSC_SCH5555) += sch5555_ramstage.c diff --git a/src/superio/smsc/sch5555/sch5555.h b/src/superio/smsc/sch5555/sch5555.h new file mode 100644 index 0000000..c349580 --- /dev/null +++ b/src/superio/smsc/sch5555/sch5555.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SUPERIO_SCH5555_H +#define SUPERIO_SCH5555_H + +// Config I/O ports +#define SMSC_INDEX 0x2e +#define SMSC_DATA 0x2f + +// Global registers +#define LDN_SELECT 0x07 +#define DEVICE_ID 0x20 +#define DEVICE_REV 0x21 +#define DEVICE_MODE 0x24 + +// Logical device numbers +#define LDN_EMI 0x00 +#define LDN_8042 0x01 +#define LDN_UART1 0x07 +#define LDN_UART2 0x08 +#define LDN_RUNTIME 0x0a +#define LDN_FDC 0x0b +#define LDN_LPCI 0x0c +#define LDN_PARPORT 0x11 +#define LDN_GLOBAL 0x3f + +// Activate the current LDN (for each LDN) +#define LDN_ACTIVE 0x30 + +// LPC interface registers +#define LPCI_IRQ_CONF 0x40 // Each interrupt is at this +n bytes + +#define LPCI_EMI_BAR 0x64 // BAR offset (inside LPCI) for each LDN +#define LPCI_UART1_BAR 0x68 +#define LPCI_UART2_BAR 0x6c +#define LPCI_RUNTIME_BAR 0x70 +#define LPCI_8042_BAR 0x78 +#define LPCI_FDC_BAR 0x7c +#define LPCI_PARPORT_BAR 0x80 + +// Runtime registers (in I/O space) +#define RUNTIME_PME_STS 0x00 +#define RUNTIME_PME_EN 0x01 +#define RUNTIME_PME_EN1 0x05 +#define RUNTIME_LED 0x25 +#define RUNTIME_UNK1 0x35 // NOTE: not in the datasheet but Dell's firmware writes to it + +// +// Same mapping for these BARs as Dell firmware +// +#define EMI_IOBASE 0xa00 +#define RUNTIME_IOBASE 0xa40 + +// +// Common accessor functions +// + +void smsc_conf_enter(void); +void smsc_conf_exit(void); +uint8_t smsc_read8(uint8_t offset); +uint16_t smsc_read16(uint8_t offset); +uint32_t smsc_read32(uint8_t offset); +void smsc_write8(uint8_t offset, uint8_t value); +void smsc_write16(uint8_t offset, uint16_t value); +void smsc_write32(uint8_t offset, uint32_t value); +uint8_t emi_read8(uint16_t addr); +uint16_t emi_read16(uint16_t addr); +uint32_t emi_read32(uint16_t addr); +void emi_write8(uint16_t addr, uint8_t val); +void emi_write16(uint16_t addr, uint16_t val); +void emi_write32(uint16_t addr, uint32_t val); + +// +// Bootblock entry points +// + +void sch5555_early_init(void); + +#define SCH5555_UART1 0 +#define SCH5555_UART2 1 + +void sch5555_enable_serial(uint8_t uart_no, uint16_t serial_iobase); + +// +// Ramstage entry points +// + +#endif diff --git a/src/superio/smsc/sch5555/sch5555_bootblock.c b/src/superio/smsc/sch5555/sch5555_bootblock.c new file mode 100644 index 0000000..bdd309b --- /dev/null +++ b/src/superio/smsc/sch5555/sch5555_bootblock.c @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include "sch5555.h" + +/* + * Here we do just enough init so that the motherboard specific magic EMI + * sequences could actually be sent before the serial enable function is called + */ +void sch5555_early_init(void) +{ + smsc_conf_enter(); + + // Enable IRQs + smsc_write8(LDN_SELECT, LDN_GLOBAL); + smsc_write8(DEVICE_MODE, 0x04); + + // Map EMI and runtime registers + smsc_write8(LDN_SELECT, LDN_LPCI); + smsc_write32(LPCI_EMI_BAR, (EMI_IOBASE << 16) | 0x800f); + smsc_write32(LPCI_RUNTIME_BAR, (RUNTIME_IOBASE << 16) | 0x8a3f); + + smsc_conf_exit(); +} + +void sch5555_enable_serial(uint8_t uart_no, uint16_t serial_iobase) +{ + smsc_conf_enter(); + + // Set LPCI register to map UART into I/O space + smsc_write8(LDN_SELECT, LDN_LPCI); + + switch (uart_no) { + case SCH5555_UART1: + smsc_write32(LPCI_UART1_BAR, serial_iobase << 16 | 0x8707); + smsc_write8(LDN_SELECT, LDN_UART1); + break; + case SCH5555_UART2: + smsc_write32(LPCI_UART2_BAR, serial_iobase << 16 | 0x8707); + smsc_write8(LDN_SELECT, LDN_UART2); + break; + } + + // Setup UART's configuration registers + smsc_write8(LDN_ACTIVE, 0x01); // Activate + smsc_write8(0x0f, 0x02); // Config select + + smsc_conf_exit(); +} diff --git a/src/superio/smsc/sch5555/sch5555_common.c b/src/superio/smsc/sch5555/sch5555_common.c new file mode 100644 index 0000000..f0dc562 --- /dev/null +++ b/src/superio/smsc/sch5555/sch5555_common.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include "sch5555.h" + +// +// Super I/O register access +// + +void smsc_conf_enter(void) +{ + outb(0x55, SMSC_INDEX); +} + +void smsc_conf_exit(void) +{ + outb(0xaa, SMSC_INDEX); +} + +uint8_t smsc_read8(uint8_t offset) +{ + outb(offset, SMSC_INDEX); + return inb(SMSC_DATA); +} + +uint16_t smsc_read16(uint8_t offset) +{ + uint16_t val = 0; + val |= smsc_read8(offset); + val |= smsc_read8(offset + 1) << 8; + return val; +} + +uint32_t smsc_read32(uint8_t offset) +{ + uint32_t val = 0; + val |= smsc_read8(offset); + val |= smsc_read8(offset + 1) << 8; + val |= smsc_read8(offset + 2) << 16; + val |= smsc_read8(offset + 3) << 24; + return val; +} + +void smsc_write8(uint8_t offset, uint8_t value) +{ + outb(offset, SMSC_INDEX); + outb(value, SMSC_DATA); +} + +void smsc_write16(uint8_t offset, uint16_t value) +{ + smsc_write8(offset, value & 0xff); + smsc_write8(offset + 1, (value >> 8) & 0xff); +} + +void smsc_write32(uint8_t offset, uint32_t value) +{ + smsc_write8(offset, value & 0xff); + smsc_write8(offset + 1, (value >> 8) & 0xff); + smsc_write8(offset + 2, (value >> 16) & 0xff); + smsc_write8(offset + 3, (value >> 24) & 0xff); +} + +// +// EMI access +// + +uint8_t emi_read8(uint16_t addr) +{ + outw(addr | 0x8000, EMI_IOBASE + 2); + return inb(EMI_IOBASE + 4); +} + +uint16_t emi_read16(uint16_t addr) +{ + outw(addr | 0x8001, EMI_IOBASE + 2); + return inw(EMI_IOBASE + 4); +} + +uint32_t emi_read32(uint16_t addr) +{ + outw(addr | 0x8002, EMI_IOBASE + 2); + return inl(EMI_IOBASE + 4); +} + +void emi_write8(uint16_t addr, uint8_t val) +{ + outw(addr | 0x8000, EMI_IOBASE + 2); + outb(val, EMI_IOBASE + 4); +} + +void emi_write16(uint16_t addr, uint16_t val) +{ + outw(addr | 0x8001, EMI_IOBASE + 2); + outw(val, EMI_IOBASE + 4); +} + +void emi_write32(uint16_t addr, uint32_t val) +{ + outw(addr | 0x8002, EMI_IOBASE + 2); + outl(val, EMI_IOBASE + 4); +}