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>
This commit is contained in:
Duncan Laurie 2012-12-17 11:29:10 -08:00 committed by Stefan Reinauer
parent 51254049b9
commit 045f153a4f
8 changed files with 307 additions and 31 deletions

View File

@ -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 \

View File

@ -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
})
}

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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)