lynxpoint: lpc resource reservations
This commit updates the Lynx Point resource reservations before the coreboot allocator assigns resources. There is no need to mark anything as subtractive decode because there are no devices/buses linked to the LPC device. The I/O range reservations consists of claiming the first 4KiB of I/O space. The PMBASE, GPIOBASE, and LPC generic I/O decode ranges are checked against the default claimed range. If those ranges overlap or fall outside of the default range then those resources are added. The MMIO range reservations consist of claiming everything from the I/O APIC to 4GiB. The RCBA and the LPC Generic Memory range register are then conditionally added if they fall outside of the default MMIO range. Change-Id: I0f560a03814a2b15961fdbe61e4164cd54cff7a5 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/2682 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
26e7dd703d
commit
6f561afa4a
|
@ -574,72 +574,129 @@ static void lpc_init(struct device *dev)
|
||||||
pch_fixups(dev);
|
pch_fixups(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pch_lpc_read_resources(device_t dev)
|
static void pch_lpc_add_mmio_resources(device_t dev)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
struct resource *res;
|
||||||
|
const u32 default_decode_base = IO_APIC_ADDR;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just report all resources from IO-APIC base to 4GiB. Don't mark
|
||||||
|
* them reserved as that may upset the OS if this range is marked
|
||||||
|
* as reserved in the e820.
|
||||||
|
*/
|
||||||
|
res = new_resource(dev, OIC);
|
||||||
|
res->base = default_decode_base;
|
||||||
|
res->size = 0 - default_decode_base;
|
||||||
|
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
||||||
|
|
||||||
|
/* RCBA */
|
||||||
|
if (DEFAULT_RCBA < default_decode_base) {
|
||||||
|
res = new_resource(dev, RCBA);
|
||||||
|
res->base = DEFAULT_RCBA;
|
||||||
|
res->size = 16 * 1024;
|
||||||
|
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED |
|
||||||
|
IORESOURCE_FIXED | IORESOURCE_RESERVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check LPC Memory Decode register. */
|
||||||
|
reg = pci_read_config32(dev, LGMR);
|
||||||
|
if (reg & 1) {
|
||||||
|
reg &= ~0xffff;
|
||||||
|
if (reg < default_decode_base) {
|
||||||
|
res = new_resource(dev, LGMR);
|
||||||
|
res->base = reg;
|
||||||
|
res->size = 16 * 1024;
|
||||||
|
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED |
|
||||||
|
IORESOURCE_FIXED | IORESOURCE_RESERVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default IO range claimed by the LPC device. The upper bound is exclusive. */
|
||||||
|
#define LPC_DEFAULT_IO_RANGE_LOWER 0
|
||||||
|
#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000
|
||||||
|
|
||||||
|
static inline int pch_io_range_in_default(u16 base, u16 size)
|
||||||
|
{
|
||||||
|
/* Does it start above the range? */
|
||||||
|
if (base >= LPC_DEFAULT_IO_RANGE_UPPER)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Is it entirely contained? */
|
||||||
|
if (base >= LPC_DEFAULT_IO_RANGE_LOWER &&
|
||||||
|
(base + size) < LPC_DEFAULT_IO_RANGE_UPPER)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* This will return not in range for partial overlaps. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: this function assumes there is no overlap with the default LPC device's
|
||||||
|
* claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER.
|
||||||
|
*/
|
||||||
|
static void pch_lpc_add_io_resource(device_t dev, u16 base, u16 size, int index)
|
||||||
|
{
|
||||||
|
struct resource *res;
|
||||||
|
|
||||||
|
if (pch_io_range_in_default(base, size))
|
||||||
|
return;
|
||||||
|
|
||||||
|
res = new_resource(dev, index);
|
||||||
|
res->base = base;
|
||||||
|
res->size = size;
|
||||||
|
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pch_lpc_add_gen_io_resources(device_t dev, int reg_value, int index)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check if the register is enabled. If so and the base exceeds the
|
||||||
|
* device's deafult claim range add the resoure.
|
||||||
|
*/
|
||||||
|
if (reg_value & 1) {
|
||||||
|
u16 base = reg_value & 0xfffc;
|
||||||
|
u16 size = (0x3 | ((reg_value >> 16) & 0xfc)) + 1;
|
||||||
|
pch_lpc_add_io_resource(dev, base, size, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pch_lpc_add_io_resources(device_t dev)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
config_t *config = dev->chip_info;
|
config_t *config = dev->chip_info;
|
||||||
u8 io_index = 0;
|
|
||||||
|
|
||||||
|
/* Add the default claimed IO range for the LPC device. */
|
||||||
|
res = new_resource(dev, 0);
|
||||||
|
res->base = LPC_DEFAULT_IO_RANGE_LOWER;
|
||||||
|
res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER;
|
||||||
|
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
||||||
|
|
||||||
|
/* GPIOBASE */
|
||||||
|
pch_lpc_add_io_resource(dev, DEFAULT_GPIOBASE, DEFAULT_GPIOSIZE,
|
||||||
|
GPIO_BASE);
|
||||||
|
|
||||||
|
/* PMBASE */
|
||||||
|
pch_lpc_add_io_resource(dev, DEFAULT_PMBASE, 128, PMBASE);
|
||||||
|
|
||||||
|
/* LPC Generic IO Decode range. */
|
||||||
|
pch_lpc_add_gen_io_resources(dev, config->gen1_dec, LPC_GEN1_DEC);
|
||||||
|
pch_lpc_add_gen_io_resources(dev, config->gen2_dec, LPC_GEN2_DEC);
|
||||||
|
pch_lpc_add_gen_io_resources(dev, config->gen3_dec, LPC_GEN3_DEC);
|
||||||
|
pch_lpc_add_gen_io_resources(dev, config->gen4_dec, LPC_GEN4_DEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pch_lpc_read_resources(device_t dev)
|
||||||
|
{
|
||||||
/* Get the normal PCI resources of this device. */
|
/* Get the normal PCI resources of this device. */
|
||||||
pci_dev_read_resources(dev);
|
pci_dev_read_resources(dev);
|
||||||
|
|
||||||
/* Add an extra subtractive resource for both memory and I/O. */
|
/* Add non-standard MMIO resources. */
|
||||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
|
pch_lpc_add_mmio_resources(dev);
|
||||||
res->base = 0;
|
|
||||||
res->size = 0x1000;
|
|
||||||
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
|
|
||||||
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
|
||||||
|
|
||||||
/* GPIOBASE */
|
/* Add IO resources. */
|
||||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
|
pch_lpc_add_io_resources(dev);
|
||||||
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, io_index++); /* IOAPIC */
|
|
||||||
res->base = IO_APIC_ADDR;
|
|
||||||
res->size = 0x00001000;
|
|
||||||
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
|
||||||
|
|
||||||
/* Set PCH IO decode ranges if required.*/
|
|
||||||
if ((config->gen1_dec & 0xFFFC) > 0x1000) {
|
|
||||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
|
|
||||||
res->base = config->gen1_dec & 0xFFFC;
|
|
||||||
res->size = (config->gen1_dec >> 16) & 0xFC;
|
|
||||||
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
|
|
||||||
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((config->gen2_dec & 0xFFFC) > 0x1000) {
|
|
||||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
|
|
||||||
res->base = config->gen2_dec & 0xFFFC;
|
|
||||||
res->size = (config->gen2_dec >> 16) & 0xFC;
|
|
||||||
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
|
|
||||||
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((config->gen3_dec & 0xFFFC) > 0x1000) {
|
|
||||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
|
|
||||||
res->base = config->gen3_dec & 0xFFFC;
|
|
||||||
res->size = (config->gen3_dec >> 16) & 0xFC;
|
|
||||||
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
|
|
||||||
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((config->gen4_dec & 0xFFFC) > 0x1000) {
|
|
||||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
|
|
||||||
res->base = config->gen4_dec & 0xFFFC;
|
|
||||||
res->size = (config->gen4_dec >> 16) & 0xFC;
|
|
||||||
res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
|
|
||||||
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pch_lpc_enable_resources(device_t dev)
|
static void pch_lpc_enable_resources(device_t dev)
|
||||||
|
|
|
@ -185,6 +185,7 @@ unsigned get_gpios(const int *gpio_num_array);
|
||||||
#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */
|
#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */
|
||||||
#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */
|
#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */
|
||||||
#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */
|
#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */
|
||||||
|
#define LGMR 0x98 /* LPC Generic Memory Range */
|
||||||
|
|
||||||
/* PCI Configuration Space (D31:F1): IDE */
|
/* PCI Configuration Space (D31:F1): IDE */
|
||||||
#define PCH_IDE_DEV PCI_DEV(0, 0x1f, 1)
|
#define PCH_IDE_DEV PCI_DEV(0, 0x1f, 1)
|
||||||
|
|
Loading…
Reference in New Issue