summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2012-12-17 11:29:10 -0800
committerStefan Reinauer <stefan.reinauer@coreboot.org>2013-03-14 18:24:32 +0100
commit045f153a4fe2b6e1cb193db01866218d0316f253 (patch)
tree653af6488dfe46d3b8d15d3df74740632b2b3cc5 /src/southbridge
parent51254049b91a816c53b5cadf72d254f11e882818 (diff)
downloadcoreboot-045f153a4fe2b6e1cb193db01866218d0316f253.tar.xz
lynxpoint: Add new GPIO interface for Lynxpoint-LP
The low power variant of the chipset introduces a completely new interface to the GPIOs. This is a 1KB region and so needs to be moved as well so it does not conflict with other IO regions. Also expose the gpio_get functions to ramstage and move the prototypes to pch.h so they can be used for both GPIO interfaces. Change-Id: I20bc18669525af16de8cdf99f0ccfa9612be63ad Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/2648 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones <marc.jones@se-eng.com>
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/intel/lynxpoint/Makefile.inc10
-rw-r--r--src/southbridge/intel/lynxpoint/acpi/lpc.asl17
-rw-r--r--src/southbridge/intel/lynxpoint/gpio.c20
-rw-r--r--src/southbridge/intel/lynxpoint/gpio.h24
-rw-r--r--src/southbridge/intel/lynxpoint/lp_gpio.c113
-rw-r--r--src/southbridge/intel/lynxpoint/lp_gpio.h110
-rw-r--r--src/southbridge/intel/lynxpoint/lpc.c9
-rw-r--r--src/southbridge/intel/lynxpoint/pch.h35
8 files changed, 307 insertions, 31 deletions
diff --git a/src/southbridge/intel/lynxpoint/Makefile.inc b/src/southbridge/intel/lynxpoint/Makefile.inc
index d4522c35fd..c14a53881d 100644
--- a/src/southbridge/intel/lynxpoint/Makefile.inc
+++ b/src/southbridge/intel/lynxpoint/Makefile.inc
@@ -45,10 +45,18 @@ smm-$(CONFIG_SPI_FLASH_SMM) += spi.c
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me_9.x.c finalize.c
-romstage-y += early_usb.c early_smbus.c early_me.c me_status.c gpio.c
+romstage-y += early_usb.c early_smbus.c early_me.c me_status.c
romstage-$(CONFIG_USBDEBUG) += usb_debug.c
romstage-y += reset.c early_spi.c
+ifeq ($(CONFIG_INTEL_LYNXPOINT_LP),y)
+romstage-y += lp_gpio.c
+ramstage-y += lp_gpio.c
+else
+romstage-y += gpio.c
+ramstage-y += gpio.c
+endif
+
lynxpoint_add_me: $(obj)/coreboot.pre $(IFDTOOL)
printf " DD Adding Intel Firmware Descriptor\n"
dd if=3rdparty/mainboard/$(MAINBOARDDIR)/descriptor.bin \
diff --git a/src/southbridge/intel/lynxpoint/acpi/lpc.asl b/src/southbridge/intel/lynxpoint/acpi/lpc.asl
index cc59850ec4..03d61ebd3b 100644
--- a/src/southbridge/intel/lynxpoint/acpi/lpc.asl
+++ b/src/southbridge/intel/lynxpoint/acpi/lpc.asl
@@ -194,7 +194,22 @@ Device (LPCB)
IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI
//IO (Decode16, 0x800, 0x800, 0x1, 0x10) // ACPI I/O trap
IO (Decode16, DEFAULT_PMBASE, DEFAULT_PMBASE, 0x1, 0x80) // ICH7-M ACPI
- IO (Decode16, DEFAULT_GPIOBASE, DEFAULT_GPIOBASE, 0x1, 0x40) // ICH7-M GPIO
+
+#if CONFIG_INTEL_LYNXPOINT_LP
+ // LynxPoint LP GPIO is 1KB
+ IO (Decode16, DEFAULT_GPIOBASE,
+ DEFAULT_GPIOBASE, 0x1, 0xff)
+ IO (Decode16, Add(DEFAULT_GPIOBASE, 0x100),
+ Add(DEFAULT_GPIOBASE, 0x100), 0x1, 0xff)
+ IO (Decode16, Add(DEFAULT_GPIOBASE, 0x200),
+ Add(DEFAULT_GPIOBASE, 0x200), 0x1, 0xff)
+ IO (Decode16, Add(DEFAULT_GPIOBASE, 0x300),
+ Add(DEFAULT_GPIOBASE, 0x300), 0x1, 0xff)
+#else
+ // LynxPoint GPIO is 128 bytes
+ IO (Decode16, DEFAULT_GPIOBASE,
+ DEFAULT_GPIOBASE, 0x1, DEFAULT_GPIOSIZE)
+#endif
})
}
diff --git a/src/southbridge/intel/lynxpoint/gpio.c b/src/southbridge/intel/lynxpoint/gpio.c
index 25eda9a74c..9d36887dd1 100644
--- a/src/southbridge/intel/lynxpoint/gpio.c
+++ b/src/southbridge/intel/lynxpoint/gpio.c
@@ -20,16 +20,32 @@
#include <stdint.h>
#include <string.h>
#include <arch/io.h>
+
+#ifdef __PRE_RAM__
#include <arch/romcc_io.h>
+#else
+#include <device/device.h>
+#include <device/pci.h>
+#endif
#include "pch.h"
#include "gpio.h"
#define MAX_GPIO_NUMBER 75 /* zero based */
+static u16 get_gpio_base(void)
+{
+#ifdef __PRE_RAM__
+ return pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
+#else
+ return pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)),
+ GPIO_BASE) & 0xfffc;
+#endif
+}
+
void setup_pch_gpios(const struct pch_gpio_map *gpio)
{
- u16 gpiobase = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
+ u16 gpiobase = get_gpio_base();
/* GPIO Set 1 */
if (gpio->set1.level)
@@ -69,7 +85,7 @@ void setup_pch_gpios(const struct pch_gpio_map *gpio)
int get_gpio(int gpio_num)
{
static const int gpio_reg_offsets[] = {0xc, 0x38, 0x48};
- u16 gpio_base = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
+ u16 gpio_base = get_gpio_base();
int index, bit;
if (gpio_num > MAX_GPIO_NUMBER)
diff --git a/src/southbridge/intel/lynxpoint/gpio.h b/src/southbridge/intel/lynxpoint/gpio.h
index a6f99f681d..20e2eea0af 100644
--- a/src/southbridge/intel/lynxpoint/gpio.h
+++ b/src/southbridge/intel/lynxpoint/gpio.h
@@ -20,6 +20,22 @@
#ifndef INTEL_LYNXPOINT_GPIO_H
#define INTEL_LYNXPOINT_GPIO_H
+/* ICH7 GPIOBASE */
+#define GPIO_USE_SEL 0x00
+#define GP_IO_SEL 0x04
+#define GP_LVL 0x0c
+#define GPO_BLINK 0x18
+#define GPI_INV 0x2c
+#define GPIO_USE_SEL2 0x30
+#define GP_IO_SEL2 0x34
+#define GP_LVL2 0x38
+#define GPIO_USE_SEL3 0x40
+#define GP_IO_SEL3 0x44
+#define GP_LVL3 0x48
+#define GP_RST_SEL1 0x60
+#define GP_RST_SEL2 0x64
+#define GP_RST_SEL3 0x68
+
#define GPIO_MODE_NATIVE 0
#define GPIO_MODE_GPIO 1
#define GPIO_MODE_NONE 1
@@ -150,12 +166,4 @@ struct pch_gpio_map {
/* Configure GPIOs with mainboard provided settings */
void setup_pch_gpios(const struct pch_gpio_map *gpio);
-/* get GPIO pin value */
-int get_gpio(int gpio_num);
-/*
- * get a number comprised of multiple GPIO values. gpio_num_array points to
- * the array of gpio pin numbers to scan, terminated by -1.
- */
-unsigned get_gpios(const int *gpio_num_array);
-
#endif
diff --git a/src/southbridge/intel/lynxpoint/lp_gpio.c b/src/southbridge/intel/lynxpoint/lp_gpio.c
new file mode 100644
index 0000000000..2d2e0576ea
--- /dev/null
+++ b/src/southbridge/intel/lynxpoint/lp_gpio.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <arch/io.h>
+#ifdef __PRE_RAM__
+#include <arch/romcc_io.h>
+#else
+#include <device/device.h>
+#include <device/pci.h>
+#endif
+
+#include "pch.h"
+#include "lp_gpio.h"
+
+static u16 get_gpio_base(void)
+{
+#ifdef __PRE_RAM__
+ return pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
+#else
+ return pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)),
+ GPIO_BASE) & 0xfffc;
+#endif
+}
+
+void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[])
+{
+ u16 gpio_base = get_gpio_base();
+ const struct pch_lp_gpio_map *config;
+ u32 owner[3] = {0};
+ u32 route[3] = {0};
+ u32 irqen[3] = {0};
+ u32 reset[3] = {0};
+ u32 blink = 0;
+ int set, bit;
+
+ for (config = map; config->gpio != GPIO_LIST_END; config++) {
+ if (config->gpio > MAX_GPIO_NUMBER)
+ continue;
+
+ /* Setup Configuration registers 1 and 2 */
+ outl(config->conf0, gpio_base + GPIO_CONFIG0(config->gpio));
+ outl(config->conf1, gpio_base + GPIO_CONFIG1(config->gpio));
+
+ /* Determine set and bit based on GPIO number */
+ set = config->gpio >> 5;
+ bit = config->gpio % 32;
+
+ /* Apply settings to set specific bits */
+ owner[set] |= config->owner << bit;
+ route[set] |= config->route << bit;
+ irqen[set] |= config->irqen << bit;
+ reset[set] |= config->reset << bit;
+
+ if (set == 0)
+ blink |= config->blink << bit;
+ }
+
+ for (set = 0; set <= 2; set++) {
+ outl(owner[set], gpio_base + GPIO_OWNER(set));
+ outl(route[set], gpio_base + GPIO_ROUTE(set));
+ outl(irqen[set], gpio_base + GPIO_IRQ_IE(set));
+ outl(reset[set], gpio_base + GPIO_RESET(set));
+ }
+
+ outl(blink, gpio_base + GPIO_BLINK);
+}
+
+int get_gpio(int gpio_num)
+{
+ u16 gpio_base = get_gpio_base();
+
+ if (gpio_num < MAX_GPIO_NUMBER)
+ return 0;
+
+ return !!(inl(gpio_base + GPIO_CONFIG0(gpio_num)) & GPI_LEVEL);
+}
+
+/*
+ * get a number comprised of multiple GPIO values. gpio_num_array points to
+ * the array of gpio pin numbers to scan, terminated by -1.
+ */
+unsigned get_gpios(const int *gpio_num_array)
+{
+ int gpio;
+ unsigned bitmask = 1;
+ unsigned vector = 0;
+
+ while (bitmask &&
+ ((gpio = *gpio_num_array++) != -1)) {
+ if (get_gpio(gpio))
+ vector |= bitmask;
+ bitmask <<= 1;
+ }
+ return vector;
+}
diff --git a/src/southbridge/intel/lynxpoint/lp_gpio.h b/src/southbridge/intel/lynxpoint/lp_gpio.h
new file mode 100644
index 0000000000..067b6e2060
--- /dev/null
+++ b/src/southbridge/intel/lynxpoint/lp_gpio.h
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef INTEL_LYNXPOINT_LP_GPIO_H
+#define INTEL_LYNXPOINT_LP_GPIO_H
+
+/* LynxPoint LP GPIOBASE Registers */
+#define GPIO_OWNER(set) (0x00 + ((set) * 4))
+#define GPIO_PIRQ_APIC_EN 0x10
+#define GPIO_BLINK 0x18
+#define GPIO_SER_BLINK 0x1c
+#define GPIO_SER_BLINK_CS 0x20
+#define GPIO_SER_BLINK_DATA 0x24
+#define GPIO_ROUTE(set) (0x30 + ((set) * 4))
+#define GPIO_ALT_GPI_SMI_STS 0x50
+#define GPIO_ALT_GPI_SMI_EN 0x54
+#define GPIO_RESET(set) (0x60 + ((set) * 4))
+#define GPIO_GLOBAL_CONFIG 0x7c
+#define GPIO_IRQ_IS(set) (0x80 + ((set) * 4))
+#define GPIO_IRQ_IE(set) (0x90 + ((set) * 4))
+#define GPIO_CONFIG0(gpio) (0x100 + ((gpio) * 8))
+#define GPIO_CONFIG1(gpio) (0x104 + ((gpio) * 8))
+
+#define MAX_GPIO_NUMBER 94 /* zero based */
+#define GPIO_LIST_END 0xff
+
+/* conf0 */
+
+#define GPIO_MODE_NATIVE (0 << 0)
+#define GPIO_MODE_GPIO (1 << 0)
+
+#define GPIO_DIR_OUTPUT (0 << 2)
+#define GPIO_DIR_INPUT (1 << 2)
+
+#define GPIO_NO_INVERT (0 << 3)
+#define GPIO_INVERT (1 << 3)
+
+#define GPIO_IRQ_EDGE (0 << 4)
+#define GPIO_IRQ_LEVEL (1 << 4)
+
+#define GPI_LEVEL (1 << 30)
+
+#define GPO_LEVEL_LOW (0 << 31)
+#define GPO_LEVEL_HIGH (1 << 31)
+
+/* conf1 */
+
+#define GPIO_PULL_NONE (0 << 0)
+#define GPIO_PULL_DOWN (1 << 0)
+#define GPIO_PULL_UP (2 << 0)
+
+#define GPIO_SENSE_ENABLE (0 << 2)
+#define GPIO_SENSE_DISABLE (1 << 2)
+
+/* owner */
+
+#define GPIO_OWNER_ACPI 0
+#define GPIO_OWNER_GPIO 1
+
+/* route */
+
+#define GPIO_ROUTE_SCI 0
+#define GPIO_ROUTE_SMI 1
+
+/* irqen */
+
+#define GPIO_IRQ_DISABLE 0
+#define GPIO_IRQ_ENABLE 1
+
+/* blink */
+
+#define GPO_NO_BLINK 0
+#define GPO_BLINK 1
+
+/* reset */
+
+#define GPIO_RESET_PWROK 0
+#define GPIO_RESET_RSMRST 1
+
+struct pch_lp_gpio_map {
+ u8 gpio;
+ u32 conf0;
+ u32 conf1;
+ u8 owner;
+ u8 route;
+ u8 irqen;
+ u8 reset;
+ u8 blink;
+} __attribute__ ((packed));
+
+/* Configure GPIOs with mainboard provided settings */
+void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]);
+
+#endif
diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c
index a121e49874..378d62477b 100644
--- a/src/southbridge/intel/lynxpoint/lpc.c
+++ b/src/southbridge/intel/lynxpoint/lpc.c
@@ -561,13 +561,20 @@ static void pch_lpc_read_resources(device_t dev)
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+ /* GPIOBASE */
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
+ res->base = DEFAULT_GPIOBASE;
+ res->size = DEFAULT_GPIOSIZE;
+ res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
+ IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
res->base = 0xff800000;
res->size = 0x00800000; /* 8 MB for flash */
res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
- res = new_resource(dev, 3); /* IOAPIC */
+ res = new_resource(dev, io_index++); /* IOAPIC */
res->base = IO_APIC_ADDR;
res->size = 0x00001000;
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h
index e1d9db4378..f6707f7bdb 100644
--- a/src/southbridge/intel/lynxpoint/pch.h
+++ b/src/southbridge/intel/lynxpoint/pch.h
@@ -63,10 +63,16 @@
*/
#define SMBUS_IO_BASE 0x0400
#define SMBUS_SLAVE_ADDR 0x24
-/* TODO Make sure these don't get changed by stage2 */
-#define DEFAULT_GPIOBASE 0x0480
#define DEFAULT_PMBASE 0x0500
+#if CONFIG_INTEL_LYNXPOINT_LP
+#define DEFAULT_GPIOBASE 0x1000
+#define DEFAULT_GPIOSIZE 0x400
+#else
+#define DEFAULT_GPIOBASE 0x480
+#define DEFAULT_GPIOSIZE 0x80
+#endif
+
#define HPET_ADDR 0xfed00000
#define DEFAULT_RCBA 0xfed1c000
@@ -97,6 +103,15 @@ void enable_usb_bar(void);
int smbus_read_byte(unsigned device, unsigned address);
int early_spi_read(u32 offset, u32 size, u8 *buffer);
#endif
+/*
+ * get GPIO pin value
+ */
+int get_gpio(int gpio_num);
+/*
+ * get a number comprised of multiple GPIO values. gpio_num_array points to
+ * the array of gpio pin numbers to scan, terminated by -1.
+ */
+unsigned get_gpios(const int *gpio_num_array);
#endif
#define MAINBOARD_POWER_OFF 0
@@ -438,22 +453,6 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer);
#define PCH_DISABLE_MEI1 (1 << 1)
#define PCH_ENABLE_DBDF (1 << 0)
-/* ICH7 GPIOBASE */
-#define GPIO_USE_SEL 0x00
-#define GP_IO_SEL 0x04
-#define GP_LVL 0x0c
-#define GPO_BLINK 0x18
-#define GPI_INV 0x2c
-#define GPIO_USE_SEL2 0x30
-#define GP_IO_SEL2 0x34
-#define GP_LVL2 0x38
-#define GPIO_USE_SEL3 0x40
-#define GP_IO_SEL3 0x44
-#define GP_LVL3 0x48
-#define GP_RST_SEL1 0x60
-#define GP_RST_SEL2 0x64
-#define GP_RST_SEL3 0x68
-
/* ICH7 PMBASE */
#define PM1_STS 0x00
#define WAK_STS (1 << 15)