This patchset prepares the way for changing the QEMU sun4u machine to be much closer to a real Ultra 5.
The main change we are aiming for is to replicate the PCI bus topology so that onboard devices are attached behind simba A and simba B is an empty PCI bus (although devices can be added via QEMU's -device syntax).
Note that this patch does all of the preparation work but doesn't actually implement the changes required by the switch. This is because the QEMU patches are still awaiting upstream approval and change to the sun4u machine must be synchronised between QEMU and OpenBIOS.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (13): SPARC64: increase size of PCI memory space SPARC64: increase size of PCI IO space SPARC64: fix PCI memory base in host ranges SPARC64: fix PCI configuration space size SPARC64: implement custom PCI bus scan for sabre SPARC64: add custom sabre reg property to sabre_config_cb() pci: implement simba_config_cb() for programming device ranges pci: update interrupt-map-mask to include the bus during interrupt comparisons pci: don't set interrupt-map and interrupt-map-mask properties if empty pci: rename SUN4U_INTERRUPT to SUN4U_PCIAINTERRUPT pci: alter ob_configure_pci_device() to return its device phandle pci: use ob_pci_bus_set_interrupt_map() to configure interrupts for Simba PCI bus B pci: map Simba PCI bus A on-board devices to fixed interrupts
arch/sparc64/openbios.c | 12 ++-- drivers/pci.c | 175 ++++++++++++++++++++++++++++++++++++++++++----- drivers/pci_database.c | 2 +- drivers/pci_database.h | 1 + 4 files changed, 167 insertions(+), 23 deletions(-)
On a real machine the PCI memory space should be 10 times as large, however that takes us to a 64-bit value which isn't directly supported by OpenBIOS. Increase the PCI memory space by an amount which allows Linux to allocate the IOMMU correctly.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/openbios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index ef1fdae..06ceec9 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -61,13 +61,13 @@ static const struct hwdef hwdefs[] = { .cfg_len = 0x2000000, .host_pci_base = APB_MEM_BASE, .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */ - .mem_len = 0x10000000, + .mem_len = 0xf0000000, .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space .io_len = 0x10000, .host_ranges = { { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x2000000 }, { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x10000 }, - { .type = MEMORY_SPACE_32, .parentaddr = 0x100000, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0x10000000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0x100000, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0xf0000000 }, { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } }, .irqs = { 0, 1, 2, 3 },
This is required to ensure that we can fit both SUNW,simba devices within the available space.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/openbios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index 06ceec9..1703ed6 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -63,10 +63,10 @@ static const struct hwdef hwdefs[] = { .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */ .mem_len = 0xf0000000, .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space - .io_len = 0x10000, + .io_len = 0x1000000, .host_ranges = { { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x2000000 }, - { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x10000 }, + { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x1000000 }, { .type = MEMORY_SPACE_32, .parentaddr = 0x100000, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0xf0000000 }, { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } },
Previously the address of the PCI memory base in the host ranges property was offset by pci_mem_base. While technically correct, Linux incorrectly calculates the start of the Simba window based upon this address.
Change the memory base to APB_MEM_BASE to match a real Ultra 5 which prevents Linux from outputting warnings about incorrect window sizes.
Signed-off-by: Mark Cave-ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/openbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index 1703ed6..c773c1f 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -67,7 +67,7 @@ static const struct hwdef hwdefs[] = { .host_ranges = { { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x2000000 }, { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x1000000 }, - { .type = MEMORY_SPACE_32, .parentaddr = 0x100000, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0xf0000000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = APB_MEM_BASE, .len = 0xf0000000 }, { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } }, .irqs = { 0, 1, 2, 3 },
Make the PCI configuration space size match that of a real Ultra5 machine.
Currently the declared PCI configuration space is too large and actually overlaps PCI memory space.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/openbios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index c773c1f..71bd60c 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -58,14 +58,14 @@ static const struct hwdef hwdefs[] = { .cfg_addr = APB_SPECIAL_BASE + 0x1000000ULL, // PCI bus configuration space .cfg_data = APB_MEM_BASE, // PCI bus memory space .cfg_base = APB_SPECIAL_BASE, - .cfg_len = 0x2000000, + .cfg_len = 0x1000000, .host_pci_base = APB_MEM_BASE, .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */ .mem_len = 0xf0000000, .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space .io_len = 0x1000000, .host_ranges = { - { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x2000000 }, + { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x1000000 }, { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x1000000 }, { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = APB_MEM_BASE, .len = 0xf0000000 }, { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 }
The sabre on-board devices are located at devfn (1,1) which means that in a standard PCI bus scan the bus at devfn (1, 0) is enumerated first. This doesn't play well with OpenBIOS which assumes that the ebus (with legacy ioports) is mapped starting from io_base == 0x0.
Perform a custom scan to ensure that OpenBIOS doesn't crash when additional devices are added to the bus at devfn (1, 0).
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 27fb5f0..8b09d94 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1263,6 +1263,39 @@ static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base, } }
+#if defined(CONFIG_SPARC64) +static void ob_scan_sabre_pci_bus(int *bus_num, unsigned long *mem_base, + unsigned long *io_base, const char *path, + int bus) +{ + int devnum, fn, is_multi; + + PCI_DPRINTF("\nScanning sabre bus %d at %s...\n", bus, path); + + /* Horrible sabre hack: the PCI bridge with the on-board devices + is located at devfn (1,1) so if we use the standard scan function + we end up with our ioports not mapped at io_base == 0x0 which + breaks many assumptions in OpenBIOS. Hence do a custom scan for + sabre which does things in the right order. */ + for (devnum = 0; devnum < 32; devnum++) { + is_multi = 0; + + if (devnum == 1) { + ob_configure_pci_device(path, bus_num, mem_base, io_base, + bus, 1, 1, &is_multi); + + ob_configure_pci_device(path, bus_num, mem_base, io_base, + bus, 1, 0, &is_multi); + } else { + for (fn = 0; fn==0 || (is_multi && fn<8); fn++) { + ob_configure_pci_device(path, bus_num, mem_base, io_base, + bus, devnum, fn, &is_multi); + } + } + } +} +#endif + static void ob_configure_pci_bridge(pci_addr addr, int *bus_num, unsigned long *mem_base, unsigned long *io_base, @@ -1314,10 +1347,23 @@ static void ob_configure_pci_bridge(pci_addr addr, pci_config_write8(addr, PCI_IO_LIMIT, (io_scan_limit >> 8) & ~(0xf));
/* make pci bridge parent device, prepare for recursion */ + +#if defined(CONFIG_SPARC64) + /* Horrible hack for sabre */ + int vid = pci_config_read16(addr, PCI_VENDOR_ID); + int did = pci_config_read16(addr, PCI_DEVICE_ID);
+ if (vid == PCI_VENDOR_ID_SUN && did == PCI_DEVICE_ID_SUN_SABRE) { + ob_scan_sabre_pci_bus(bus_num, mem_base, io_base, + config->path, config->secondary_bus); + } else { + ob_scan_pci_bus(bus_num, mem_base, io_base, + config->path, config->secondary_bus); + } +#else ob_scan_pci_bus(bus_num, mem_base, io_base, config->path, config->secondary_bus); - +#endif /* bus scan updates *bus_num to last revealed pci bus number */ config->subordinate_bus = *bus_num; pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
Sabre has a slightly different reg property than that of other PCI host bridges. Hardcode the correct value as taken from a real Ultra 5 device tree.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/pci.c b/drivers/pci.c index 8b09d94..ec637d9 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -504,6 +504,17 @@ static int sabre_configure(phandle_t dev) { uint32_t props[28];
+ /* Sabre has a custom reg property from the default */ + props[0] = 0x1fe; + props[1] = 0x0; + props[2] = 0x0; + props[3] = 0x10000; + props[4] = 0x1fe; + props[5] = 0x1000000; + props[6] = 0x0; + props[7] = 0x100; + set_property(dev, "reg", (char *)props, 8 * sizeof(props[0])); + props[0] = 0xc0000000; props[1] = 0x20000000; set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0]));
The SUN,simba device doesn't have a ranges properties and so Linux will calculate the PCI memory/IO ranges by probing the PBM "Memory Address Map" and "I/O Address Map" registers (see apb_fake_ranges()).
Set sensible default values for both SUNW,simba devices during PCI configuration and document accordingly.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/pci_database.c | 2 +- drivers/pci_database.h | 1 + 3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/pci.c b/drivers/pci.c index ec637d9..510ebb7 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -553,6 +553,43 @@ int bridge_config_cb(const pci_config_t *config) return 0; }
+int simba_config_cb(const pci_config_t *config) +{ + bridge_config_cb(config); + + /* Configure the simba ranges as per the mostly undocumented + PCI config register in Linux's apb_fake_ranges(): + + pci@1,1 (pciA): + IO: 0x1fe02000000-0x1fe027fffff + MEM: 0x1ff20000000-0x1ff5fffffff + + pci@1 (pciB): + IO: 0x1fe02800000-0x1fe02ffffff + MEM: 0x1ff60000000-0x1ff9fffffff + */ + + switch (PCI_FN(config->dev)) { + case 1: + /* IO: 0x1fe02000000-0x1fe027fffff */ + pci_config_write8(config->dev, 0xde, 0x0f); + + /* MEM: 0x1ff20000000-0x1ff5fffffff */ + pci_config_write8(config->dev, 0xdf, 0x06); + break; + + case 0: + /* IO: 0x1fe02800000-0x1fe02ffffff */ + pci_config_write8(config->dev, 0xde, 0xf0); + + /* MEM: 0x1ff60000000-0x1ff9fffffff */ + pci_config_write8(config->dev, 0xdf, 0x18); + break; + } + + return 0; +} + int ide_config_cb2 (const pci_config_t *config) { ob_ide_init(config->path, diff --git a/drivers/pci_database.c b/drivers/pci_database.c index b220586..3155ee3 100644 --- a/drivers/pci_database.c +++ b/drivers/pci_database.c @@ -371,7 +371,7 @@ static const pci_dev_t PCIbrg_devices[] = { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA, NULL, "pci", "SUNW,simba", "pci108e,5000\0pciclass,060400\0", 3, 2, 1, - bridge_config_cb, NULL, + simba_config_cb, NULL, }, { 0xFFFF, 0xFFFF, diff --git a/drivers/pci_database.h b/drivers/pci_database.h index 1cc1e56..241bac3 100644 --- a/drivers/pci_database.h +++ b/drivers/pci_database.h @@ -36,6 +36,7 @@ extern int vga_config_cb(const pci_config_t *config); extern int host_config_cb(const pci_config_t *config); extern int sabre_config_cb(const pci_config_t *config); extern int bridge_config_cb(const pci_config_t *config); +extern int simba_config_cb(const pci_config_t *config); extern int ebus_config_cb(const pci_config_t *config); extern int i82378_config_cb(const pci_config_t *config); extern int usb_ohci_config_cb(const pci_config_t *config);
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 510ebb7..e2ab0e1 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1774,7 +1774,7 @@ static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode, } set_property(pcibus, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
- props[0] = 0x0000f800; + props[0] = 0x00fff800; props[1] = 0x0; props[2] = 0x0; props[3] = 0x7;
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index e2ab0e1..e3b2181 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1772,13 +1772,16 @@ static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode, fword("peer"); pci_childnode = POP(); } - set_property(pcibus, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
- props[0] = 0x00fff800; - props[1] = 0x0; - props[2] = 0x0; - props[3] = 0x7; - set_property(pcibus, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); + if (ncells) { + set_property(pcibus, "interrupt-map", (char *)props, ncells * sizeof(props[0])); + + props[0] = 0x00fff800; + props[1] = 0x0; + props[2] = 0x0; + props[3] = 0x7; + set_property(pcibus, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); + } }
int ob_pci_init(void)
The current interrupt mapping is only correct for PCI bus A (QEMU currently alters its PCI mappings to handle that PCI devices are plugged into the PCI root bus and not behind a Simba bridge).
Add a comment to point out that the existing mapping is deprecated and should be removed once the QEMU PCI topology has been updated.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index e3b2181..8467978 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1703,7 +1703,7 @@ static void ob_pci_host_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 #elif defined(CONFIG_SPARC64)
/* Convert device/irq pin to interrupt property */ -#define SUN4U_INTERRUPT(dev, irq_pin) \ +#define SUN4U_PCIAINTERRUPT(dev, irq_pin) \ ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
static phandle_t ob_pci_host_set_interrupt_map(phandle_t host) @@ -1713,10 +1713,13 @@ static phandle_t ob_pci_host_set_interrupt_map(phandle_t host)
static void ob_pci_host_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno) { + /* Note: this can be removed when the Simba bridges are in place + as it is impossible to physically plug hardware into the PCI + root bus */ *ncells += pci_encode_phys_addr(props + *ncells, 0, 0, addr, 0, 0); props[(*ncells)++] = intno; props[(*ncells)++] = dnode; - props[(*ncells)++] = SUN4U_INTERRUPT(addr, intno); + props[(*ncells)++] = SUN4U_PCIAINTERRUPT(addr, intno); }
#else
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 8467978..f1efc1f 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1289,7 +1289,7 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar, pci_config_write16(addr, PCI_COMMAND, cmd); }
-static void ob_configure_pci_device(const char* parent_path, +static phandle_t ob_configure_pci_device(const char* parent_path, int *bus_num, unsigned long *mem_base, unsigned long *io_base, int bus, int devnum, int fn, int *p_is_multi);
@@ -1482,7 +1482,7 @@ static int ob_pci_read_identification(int bus, int devnum, int fn, return 1; }
-static void ob_configure_pci_device(const char* parent_path, +static phandle_t ob_configure_pci_device(const char* parent_path, int *bus_num, unsigned long *mem_base, unsigned long *io_base, int bus, int devnum, int fn, int *p_is_multi) { @@ -1498,7 +1498,7 @@ static void ob_configure_pci_device(const char* parent_path, int is_host_bridge = 0;
if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) { - return; + return 0; }
addr = PCI_ADDR(bus, devnum, fn); @@ -1560,7 +1560,7 @@ static void ob_configure_pci_device(const char* parent_path,
if (get_property(phandle, "vendor-id", NULL)) { PCI_DPRINTF("host bridge already configured\n"); - return; + return 0; } }
@@ -1610,6 +1610,8 @@ static void ob_configure_pci_device(const char* parent_path,
ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config); } + + return phandle; }
static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigned long io_base)
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@iande.co.uk --- drivers/pci.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index f1efc1f..cf26779 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1312,11 +1312,31 @@ static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base, }
#if defined(CONFIG_SPARC64) + +/* Convert device/irq pin to interrupt property */ +#define SUN4U_PCIAINTERRUPT(dev, irq_pin) \ + ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f) + +#define SUN4U_PCIBINTERRUPT(dev, irq_pin) \ + ((0x10 + (((dev >> 11) << 2) + irq_pin - 1)) & 0x1f) + +static void ob_pci_simbaB_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno) +{ + *ncells += pci_encode_phys_addr(props + *ncells, 0, 0, addr, 0, 0); + props[(*ncells)++] = intno; + props[(*ncells)++] = dnode; + props[(*ncells)++] = SUN4U_PCIBINTERRUPT(addr, intno); +} + +static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode, + void (*func)(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno)); + static void ob_scan_sabre_pci_bus(int *bus_num, unsigned long *mem_base, unsigned long *io_base, const char *path, int bus) { int devnum, fn, is_multi; + phandle_t ph;
PCI_DPRINTF("\nScanning sabre bus %d at %s...\n", bus, path); @@ -1332,8 +1352,11 @@ static void ob_scan_sabre_pci_bus(int *bus_num, unsigned long *mem_base, ob_configure_pci_device(path, bus_num, mem_base, io_base, bus, 1, 1, &is_multi); - ob_configure_pci_device(path, bus_num, mem_base, io_base, + ph = ob_configure_pci_device(path, bus_num, mem_base, io_base, bus, 1, 0, &is_multi); + + /* Set up pciB interrupt map */ + ob_pci_bus_set_interrupt_map(ph, find_dev("/pci"), ob_pci_simbaB_bus_interrupt); } else { for (fn = 0; fn==0 || (is_multi && fn<8); fn++) { ob_configure_pci_device(path, bus_num, mem_base, io_base, @@ -1703,10 +1726,6 @@ static void ob_pci_host_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 }
#elif defined(CONFIG_SPARC64) - -/* Convert device/irq pin to interrupt property */ -#define SUN4U_PCIAINTERRUPT(dev, irq_pin) \ - ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
static phandle_t ob_pci_host_set_interrupt_map(phandle_t host) {
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/drivers/pci.c b/drivers/pci.c index cf26779..e4c36ce 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -555,6 +555,9 @@ int bridge_config_cb(const pci_config_t *config)
int simba_config_cb(const pci_config_t *config) { + u32 props[128]; + int ncells = 0; + bridge_config_cb(config);
/* Configure the simba ranges as per the mostly undocumented @@ -576,6 +579,25 @@ int simba_config_cb(const pci_config_t *config)
/* MEM: 0x1ff20000000-0x1ff5fffffff */ pci_config_write8(config->dev, 0xdf, 0x06); + + /* Onboard NIC: slot 1, intno 0x21 */ + ncells += pci_encode_phys_addr(props + ncells, 0, 0, PCI_ADDR(1, 1, 0), 0, 0); + props[ncells++] = 0x1; + props[ncells++] = find_dev("/pci"); + props[ncells++] = 0x21; + + /* Onboard IDE: slot 3, intno 0x20 */ + ncells += pci_encode_phys_addr(props + ncells, 0, 0, PCI_ADDR(1, 3, 0), 0, 0); + props[ncells++] = 0x1; + props[ncells++] = find_dev("/pci"); + props[ncells++] = 0x20; + set_property(get_cur_dev(), "interrupt-map", (char *)props, ncells * sizeof(props[0])); + + props[0] = 0x00fff800; + props[1] = 0x0; + props[2] = 0x0; + props[3] = 0x7; + set_property(get_cur_dev(), "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); break;
case 0:
On 08/07/17 21:35, Mark Cave-Ayland wrote:
This patchset prepares the way for changing the QEMU sun4u machine to be much closer to a real Ultra 5.
The main change we are aiming for is to replicate the PCI bus topology so that onboard devices are attached behind simba A and simba B is an empty PCI bus (although devices can be added via QEMU's -device syntax).
Note that this patch does all of the preparation work but doesn't actually implement the changes required by the switch. This is because the QEMU patches are still awaiting upstream approval and change to the sun4u machine must be synchronised between QEMU and OpenBIOS.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (13): SPARC64: increase size of PCI memory space SPARC64: increase size of PCI IO space SPARC64: fix PCI memory base in host ranges SPARC64: fix PCI configuration space size SPARC64: implement custom PCI bus scan for sabre SPARC64: add custom sabre reg property to sabre_config_cb() pci: implement simba_config_cb() for programming device ranges pci: update interrupt-map-mask to include the bus during interrupt comparisons pci: don't set interrupt-map and interrupt-map-mask properties if empty pci: rename SUN4U_INTERRUPT to SUN4U_PCIAINTERRUPT pci: alter ob_configure_pci_device() to return its device phandle pci: use ob_pci_bus_set_interrupt_map() to configure interrupts for Simba PCI bus B pci: map Simba PCI bus A on-board devices to fixed interrupts
arch/sparc64/openbios.c | 12 ++-- drivers/pci.c | 175 ++++++++++++++++++++++++++++++++++++++++++----- drivers/pci_database.c | 2 +- drivers/pci_database.h | 1 + 4 files changed, 167 insertions(+), 23 deletions(-)
Applied to master.
ATB,
Mark.