Allocating resource for Expansion ROM
More correct resource allocation for legacy VGA on K8 git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1829 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
@@ -37,6 +37,7 @@ static uint8_t pci_moving_config8(struct device *dev, unsigned reg)
|
|||||||
|
|
||||||
return ones ^ zeroes;
|
return ones ^ zeroes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t pci_moving_config16(struct device *dev, unsigned reg)
|
static uint16_t pci_moving_config16(struct device *dev, unsigned reg)
|
||||||
{
|
{
|
||||||
uint16_t value, ones, zeroes;
|
uint16_t value, ones, zeroes;
|
||||||
@@ -81,7 +82,7 @@ unsigned pci_find_capability(device_t dev, unsigned cap)
|
|||||||
if (pos > PCI_CAP_LIST_NEXT) {
|
if (pos > PCI_CAP_LIST_NEXT) {
|
||||||
pos = pci_read_config8(dev, pos);
|
pos = pci_read_config8(dev, pos);
|
||||||
}
|
}
|
||||||
while(pos != 0) { /* loop through the linked list */
|
while (pos != 0) { /* loop through the linked list */
|
||||||
int this_cap;
|
int this_cap;
|
||||||
this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
|
this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
|
||||||
if (this_cap == cap) {
|
if (this_cap == cap) {
|
||||||
@@ -111,7 +112,7 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
|
|||||||
|
|
||||||
/* See which bits move */
|
/* See which bits move */
|
||||||
moving = pci_moving_config32(dev, index);
|
moving = pci_moving_config32(dev, index);
|
||||||
|
|
||||||
/* Initialize attr to the bits that do not move */
|
/* Initialize attr to the bits that do not move */
|
||||||
attr = value & ~moving;
|
attr = value & ~moving;
|
||||||
|
|
||||||
@@ -153,9 +154,8 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
|
|||||||
*/
|
*/
|
||||||
if (moving == 0) {
|
if (moving == 0) {
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
printk_debug(
|
printk_debug("%s register %02x(%08x), read-only ignoring it\n",
|
||||||
"%s register %02x(%08x), read-only ignoring it\n",
|
dev_path(dev), index, value);
|
||||||
dev_path(dev), index, value);
|
|
||||||
}
|
}
|
||||||
resource->flags = 0;
|
resource->flags = 0;
|
||||||
}
|
}
|
||||||
@@ -199,9 +199,9 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
|
|||||||
#if 0
|
#if 0
|
||||||
if (resource->flags) {
|
if (resource->flags) {
|
||||||
printk_debug("%s %02x ->",
|
printk_debug("%s %02x ->",
|
||||||
dev_path(dev), resource->index);
|
dev_path(dev), resource->index);
|
||||||
printk_debug(" value: 0x%08Lx zeroes: 0x%08Lx ones: 0x%08Lx attr: %08lx\n",
|
printk_debug(" value: 0x%08Lx zeroes: 0x%08Lx ones: 0x%08Lx attr: %08lx\n",
|
||||||
value, zeroes, ones, attr);
|
value, zeroes, ones, attr);
|
||||||
printk_debug(
|
printk_debug(
|
||||||
"%s %02x -> size: 0x%08Lx max: 0x%08Lx %s%s\n ",
|
"%s %02x -> size: 0x%08Lx max: 0x%08Lx %s%s\n ",
|
||||||
dev_path(dev),
|
dev_path(dev),
|
||||||
@@ -225,7 +225,7 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
|
|||||||
{
|
{
|
||||||
unsigned long index;
|
unsigned long index;
|
||||||
|
|
||||||
for(index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
|
for (index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
|
||||||
struct resource *resource;
|
struct resource *resource;
|
||||||
resource = pci_get_resource(dev, index);
|
resource = pci_get_resource(dev, index);
|
||||||
index += (resource->flags & IORESOURCE_PCI64)?8:4;
|
index += (resource->flags & IORESOURCE_PCI64)?8:4;
|
||||||
@@ -233,11 +233,63 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
|
|||||||
compact_resources(dev);
|
compact_resources(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_read_rom_resource(struct device *dev, unsigned long index)
|
||||||
|
{
|
||||||
|
struct resource *resource;
|
||||||
|
unsigned long value, attr;
|
||||||
|
resource_t moving, limit;
|
||||||
|
|
||||||
|
/* Initialize the resources to nothing */
|
||||||
|
resource = new_resource(dev, index);
|
||||||
|
|
||||||
|
/* Get the initial value */
|
||||||
|
value = pci_read_config32(dev, index);
|
||||||
|
|
||||||
|
/* See which bits move */
|
||||||
|
moving = pci_moving_config32(dev, index);
|
||||||
|
/* clear the Enable bit */
|
||||||
|
moving = moving & 0xffffffffe;
|
||||||
|
|
||||||
|
/* Find the resource constraints.
|
||||||
|
*
|
||||||
|
* Start by finding the bits that move. From there:
|
||||||
|
* - Size is the least significant bit of the bits that move.
|
||||||
|
* - Limit is all of the bits that move plus all of the lower bits.
|
||||||
|
* See PCI Spec 6.2.5.1 ...
|
||||||
|
*/
|
||||||
|
limit = 0;
|
||||||
|
|
||||||
|
if (moving) {
|
||||||
|
resource->size = 1;
|
||||||
|
resource->align = resource->gran = 0;
|
||||||
|
while(!(moving & resource->size)) {
|
||||||
|
resource->size <<= 1;
|
||||||
|
resource->align += 1;
|
||||||
|
resource->gran += 1;
|
||||||
|
}
|
||||||
|
resource->limit = limit = moving | (resource->size - 1);
|
||||||
|
printk_debug("%s, rom size: %x, limit: %x\n",
|
||||||
|
dev_path(dev), resource->size, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moving == 0) {
|
||||||
|
if (value != 0) {
|
||||||
|
printk_debug("%s register %02x(%08x), read-only ignoring it\n",
|
||||||
|
dev_path(dev), index, value);
|
||||||
|
}
|
||||||
|
resource->flags = 0;
|
||||||
|
} else {
|
||||||
|
resource->flags |= IORESOURCE_MEM | IORESOURCE_READONLY;
|
||||||
|
}
|
||||||
|
compact_resources(dev);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void pci_set_resource(struct device *dev, struct resource *resource);
|
static void pci_set_resource(struct device *dev, struct resource *resource);
|
||||||
|
|
||||||
static void pci_record_bridge_resource(
|
static void pci_record_bridge_resource( struct device *dev, resource_t moving,
|
||||||
struct device *dev, resource_t moving,
|
unsigned index, unsigned long mask,
|
||||||
unsigned index, unsigned long mask, unsigned long type)
|
unsigned long type)
|
||||||
{
|
{
|
||||||
/* Initiliaze the constraints on the current bus */
|
/* Initiliaze the constraints on the current bus */
|
||||||
struct resource *resource;
|
struct resource *resource;
|
||||||
@@ -272,7 +324,6 @@ static void pci_record_bridge_resource(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pci_bridge_read_bases(struct device *dev)
|
static void pci_bridge_read_bases(struct device *dev)
|
||||||
{
|
{
|
||||||
resource_t moving_base, moving_limit, moving;
|
resource_t moving_base, moving_limit, moving;
|
||||||
@@ -329,8 +380,7 @@ void pci_dev_read_resources(struct device *dev)
|
|||||||
|
|
||||||
pci_read_bases(dev, 6);
|
pci_read_bases(dev, 6);
|
||||||
|
|
||||||
addr = pci_read_config32(dev, PCI_ROM_ADDRESS);
|
pci_read_rom_resource(dev, PCI_ROM_ADDRESS);
|
||||||
dev->rom_address = (addr == 0xffffffff)? 0 : addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_bus_read_resources(struct device *dev)
|
void pci_bus_read_resources(struct device *dev)
|
||||||
@@ -339,9 +389,8 @@ void pci_bus_read_resources(struct device *dev)
|
|||||||
|
|
||||||
pci_bridge_read_bases(dev);
|
pci_bridge_read_bases(dev);
|
||||||
pci_read_bases(dev, 2);
|
pci_read_bases(dev, 2);
|
||||||
|
|
||||||
addr = pci_read_config32(dev, PCI_ROM_ADDRESS1);
|
pci_read_rom_resource(dev, PCI_ROM_ADDRESS1);
|
||||||
dev->rom_address = (addr == 0xffffffff)? 0 : addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_set_resource(struct device *dev, struct resource *resource)
|
static void pci_set_resource(struct device *dev, struct resource *resource)
|
||||||
@@ -450,10 +499,10 @@ void pci_dev_set_resources(struct device *dev)
|
|||||||
|
|
||||||
last = &dev->resource[dev->resources];
|
last = &dev->resource[dev->resources];
|
||||||
|
|
||||||
for(resource = &dev->resource[0]; resource < last; resource++) {
|
for (resource = &dev->resource[0]; resource < last; resource++) {
|
||||||
pci_set_resource(dev, resource);
|
pci_set_resource(dev, resource);
|
||||||
}
|
}
|
||||||
for(link = 0; link < dev->links; link++) {
|
for (link = 0; link < dev->links; link++) {
|
||||||
struct bus *bus;
|
struct bus *bus;
|
||||||
bus = &dev->link[link];
|
bus = &dev->link[link];
|
||||||
if (bus->children) {
|
if (bus->children) {
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
struct bus *get_pbus_smbus(device_t dev)
|
struct bus *get_pbus_smbus(device_t dev)
|
||||||
{
|
{
|
||||||
struct bus *pbus = dev->bus;
|
struct bus *pbus = dev->bus;
|
||||||
while(pbus && pbus->dev && !ops_smbus_bus(pbus)) {
|
while (pbus && pbus->dev && !ops_smbus_bus(pbus)) {
|
||||||
pbus = pbus->dev->bus;
|
pbus = pbus->dev->bus;
|
||||||
}
|
}
|
||||||
if (!pbus || !pbus->dev || !pbus->dev->ops || !pbus->dev->ops->ops_smbus_bus) {
|
if (!pbus || !pbus->dev || !pbus->dev->ops || !pbus->dev->ops->ops_smbus_bus) {
|
||||||
@@ -18,9 +18,10 @@ struct bus *get_pbus_smbus(device_t dev)
|
|||||||
return pbus;
|
return pbus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*multi level i2c MUX??? may need to find the first i2c device and then set link down to current dev
|
/*multi level i2c MUX??? may need to find the first i2c device and then set link
|
||||||
1 store get_pbus_smbus list link
|
* down to current dev
|
||||||
2 reverse the link and call set link */
|
1 store get_pbus_smbus list link
|
||||||
|
2 reverse the link and call set link */
|
||||||
|
|
||||||
int smbus_set_link(device_t dev)
|
int smbus_set_link(device_t dev)
|
||||||
{
|
{
|
||||||
@@ -33,10 +34,10 @@ int smbus_set_link(device_t dev)
|
|||||||
pbus = pbus->dev->bus;
|
pbus = pbus->dev->bus;
|
||||||
}
|
}
|
||||||
// printk_info("smbus_set_link: ");
|
// printk_info("smbus_set_link: ");
|
||||||
for(i=pbus_num-1; i>=0; i--) {
|
for (i=pbus_num-1; i>=0; i--) {
|
||||||
// printk_info(" %s[%d] -> ", dev_path(pbus_a[i]->dev), pbus_a[i]->link);
|
// printk_info(" %s[%d] -> ", dev_path(pbus_a[i]->dev), pbus_a[i]->link);
|
||||||
if(ops_smbus_bus(get_pbus_smbus(pbus_a[i]->dev))) {
|
if (ops_smbus_bus(get_pbus_smbus(pbus_a[i]->dev))) {
|
||||||
if(pbus_a[i]->dev->ops && pbus_a[i]->dev->ops->set_link)
|
if (pbus_a[i]->dev->ops && pbus_a[i]->dev->ops->set_link)
|
||||||
pbus_a[i]->dev->ops->set_link(pbus_a[i]->dev, pbus_a[i]->link);
|
pbus_a[i]->dev->ops->set_link(pbus_a[i]->dev, pbus_a[i]->link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -424,6 +424,8 @@ static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
|
|||||||
{
|
{
|
||||||
struct resource *resource;
|
struct resource *resource;
|
||||||
unsigned link;
|
unsigned link;
|
||||||
|
uint32_t base, limit;
|
||||||
|
unsigned reg;
|
||||||
for (link = 0; link < dev->links; link++) {
|
for (link = 0; link < dev->links; link++) {
|
||||||
if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
|
if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
|
||||||
printk_info("%s: bridge on link %d has VGA device\n",
|
printk_info("%s: bridge on link %d has VGA device\n",
|
||||||
@@ -433,12 +435,29 @@ static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
|
|||||||
resource = amdk8_find_mempair(dev, nodeid, link);
|
resource = amdk8_find_mempair(dev, nodeid, link);
|
||||||
printk_info("MEM pair register %x\n", resource->index - 0x100);
|
printk_info("MEM pair register %x\n", resource->index - 0x100);
|
||||||
resource->base = 0xa0000;
|
resource->base = 0xa0000;
|
||||||
resource->size = 0x00000;
|
resource->size = 0x20000;
|
||||||
resource->gran = 16;
|
resource->gran = 16;
|
||||||
resource->align = 16;
|
resource->align = 16;
|
||||||
resource->flags = IORESOURCE_PREFETCH | IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
|
resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
|
reg = resource->index & 0xfc;
|
||||||
|
base = f1_read_config32(reg);
|
||||||
|
limit = f1_read_config32(reg + 0x4);
|
||||||
|
base &= 0x000000f0;
|
||||||
|
base |= (resource->base >> 8) & 0xffffff00;
|
||||||
|
base |= 3;
|
||||||
|
limit &= 0x00000048;
|
||||||
|
limit |= ((resource->base + resource->size) >> 8) & 0xffffff00;
|
||||||
|
limit |= (resource->index & 3) << 4;
|
||||||
|
limit |= (nodeid & 7);
|
||||||
|
f1_write_config32(reg + 0x4, limit);
|
||||||
|
f1_write_config32(reg, base);
|
||||||
|
|
||||||
|
/* release the resource */
|
||||||
|
resource->flags = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static void amdk8_set_resources(device_t dev)
|
static void amdk8_set_resources(device_t dev)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user