From 2b6051541b562b72d2cf784376a84552da18318d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:15 -0700 Subject: x86: ivybridge: Add early LPC init so that serial works The PCH (Platform Controller Hub) includes an LPC (Low Pin Count) device which provides a serial port. This is accessible on Chromebooks, so enable it early in the boot process. Signed-off-by: Simon Glass --- arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/cpu.c | 12 +++++++++++ arch/x86/cpu/ivybridge/lpc.c | 48 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/lpc.c (limited to 'arch/x86/cpu/ivybridge') diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 6d0a78d..4b77c9c 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -6,5 +6,6 @@ obj-y += car.o obj-y += cpu.o +obj-y += lpc.o obj-y += pci.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index ff6b7b3..5d7640b 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -11,16 +11,21 @@ */ #include +#include +#include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; int arch_cpu_init(void) { + const void *blob = gd->fdt_blob; struct pci_controller *hose; + int node; int ret; post_code(POST_CPU_INIT); @@ -34,6 +39,13 @@ int arch_cpu_init(void) if (ret) return ret; + node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC); + if (node < 0) + return -ENOENT; + ret = lpc_early_init(gd->fdt_blob, node, PCH_LPC_DEV); + if (ret) + return ret; + return 0; } diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c new file mode 100644 index 0000000..621ef2c --- /dev/null +++ b/arch/x86/cpu/ivybridge/lpc.c @@ -0,0 +1,48 @@ +/* + * From coreboot southbridge/intel/bd82x6x/lpc.c + * + * Copyright (C) 2008-2009 coresystems GmbH + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include + +int lpc_early_init(const void *blob, int node, pci_dev_t dev) +{ + struct reg_info { + u32 base; + u32 size; + } values[4], *ptr; + int count; + int i; + + count = fdtdec_get_int_array_count(blob, node, "gen-dec", + (u32 *)values, sizeof(values) / sizeof(u32)); + if (count < 0) + return -EINVAL; + + /* Set COM1/COM2 decode range */ + pci_write_config16(dev, LPC_IO_DEC, 0x0010); + + /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */ + pci_write_config16(dev, LPC_EN, KBC_LPC_EN | MC_LPC_EN | + GAMEL_LPC_EN | COMA_LPC_EN); + + /* Write all registers but use 0 if we run out of data */ + count = count * sizeof(u32) / sizeof(values[0]); + for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) { + u32 reg = 0; + + if (i < count) + reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16); + pci_write_config32(dev, LPC_GENX_DEC(i), reg); + } + + return 0; +} -- cgit v1.1