diff options
author | Simon Glass | 2014-11-12 22:42:15 -0700 |
---|---|---|
committer | Simon Glass | 2014-11-21 07:34:12 +0100 |
commit | 2b6051541b562b72d2cf784376a84552da18318d (patch) | |
tree | c21b6ae92539eb63628f15b52044dd164471aed7 | |
parent | 6fb3b72e8745073465b4a5875b7750cc43cbd1af (diff) |
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 <sjg@chromium.org>
-rw-r--r-- | arch/x86/cpu/ivybridge/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/cpu.c | 12 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/lpc.c | 48 | ||||
-rw-r--r-- | arch/x86/dts/link.dts | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/arch-ivybridge/pch.h | 48 | ||||
-rw-r--r-- | doc/device-tree-bindings/misc/intel-lpc.txt | 23 |
6 files changed, 133 insertions, 0 deletions
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 6d0a78d25d2..4b77c9cd835 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 ff6b7b3e7ac..5d7640b526f 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -11,16 +11,21 @@ */ #include <common.h> +#include <errno.h> +#include <fdtdec.h> #include <asm/cpu.h> #include <asm/pci.h> #include <asm/post.h> #include <asm/processor.h> +#include <asm/arch/pch.h> 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 00000000000..621ef2cee66 --- /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 <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <pci.h> +#include <asm/pci.h> +#include <asm/arch/pch.h> + +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; +} diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index f2fcb3927cb..63933aa9718 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -53,6 +53,7 @@ compatible = "intel,lpc"; #address-cells = <1>; #size-cells = <1>; + gen-dec = <0x800 0xfc 0x900 0xfc>; cros-ec@200 { compatible = "google,cros-ec"; reg = <0x204 1 0x200 1 0x880 0x80>; diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h new file mode 100644 index 00000000000..26ddeab729c --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * From Coreboot src/southbridge/intel/bd82x6x/pch.h + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_ARCH_PCH_H +#define _ASM_ARCH_PCH_H + +#include <pci.h> + +/* PCI Configuration Space (D31:F0): LPC */ +#define PCH_LPC_DEV PCI_BDF(0, 0x1f, 0) + +#define LPC_IO_DEC 0x80 /* IO Decode Ranges Register */ +#define LPC_EN 0x82 /* LPC IF Enables Register */ +#define CNF2_LPC_EN (1 << 13) /* 0x4e/0x4f */ +#define CNF1_LPC_EN (1 << 12) /* 0x2e/0x2f */ +#define MC_LPC_EN (1 << 11) /* 0x62/0x66 */ +#define KBC_LPC_EN (1 << 10) /* 0x60/0x64 */ +#define GAMEH_LPC_EN (1 << 9) /* 0x208/0x20f */ +#define GAMEL_LPC_EN (1 << 8) /* 0x200/0x207 */ +#define FDD_LPC_EN (1 << 3) /* LPC_IO_DEC[12] */ +#define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */ +#define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */ +#define COMA_LPC_EN (1 << 0) /* LPC_IO_DEC[3:2] */ +#define LPC_GEN1_DEC 0x84 /* LPC IF Generic Decode Range 1 */ +#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */ +#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */ +#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */ +#define LPC_GENX_DEC(x) (0x84 + 4 * (x)) + +/** + * lpc_early_init() - set up LPC serial ports and other early things + * + * @blob: Device tree blob + * @node: Offset of LPC node + * @dev: PCH PCI device containing the LPC + * @return 0 if OK, -ve on error + */ +int lpc_early_init(const void *blob, int node, pci_dev_t dev); + +#endif diff --git a/doc/device-tree-bindings/misc/intel-lpc.txt b/doc/device-tree-bindings/misc/intel-lpc.txt new file mode 100644 index 00000000000..7e1b3892378 --- /dev/null +++ b/doc/device-tree-bindings/misc/intel-lpc.txt @@ -0,0 +1,23 @@ +Intel LPC Device Binding +======================== + +The device tree node which describes the operation of the Intel Low Pin +Count device is as follows: + +Required properties : +- compatible = "intel,lpc" +- gen-dec : Specifies the values for the gen-dec registers. Up to four cell + pairs can be provided - the first of each pair is the base address and + the second is the size. These are written into the GENx_DEC registers of + the LPC device + + +Example +------- + +lpc { + compatible = "intel,lpc"; + #address-cells = <1>; + #size-cells = <1>; + gen-dec = <0x800 0xfc 0x900 0xfc>; +}; |