o) Program the Lanner MR-320 for 32-bit mode, too.

o) Give a virtual address for I/O ports on n64.
o) On the Portwell CAM-0100, return the right IRQ for the on-board SATA.
o) Except on bridges, only set PORTEN and MEMEN on devices that have I/O or
   memory BARs respectively.
o) Disable PORTEN and MEMEN while reprogramming BARs.
o) On the Lanner MR-955, set the Tx DMA power register for the on-board Promise
   SATA controller.
This commit is contained in:
Juli Mallett 2010-09-27 20:12:57 +00:00
parent 9e1bef6f31
commit a71199dab4

View File

@ -92,7 +92,7 @@ static void octopci_write_config(device_t, u_int, u_int, u_int, u_int,
uint32_t, int);
static int octopci_route_interrupt(device_t, device_t, int);
static void octopci_init_bar(device_t, unsigned, unsigned, unsigned, unsigned);
static void octopci_init_bar(device_t, unsigned, unsigned, unsigned, unsigned, uint8_t *);
static unsigned octopci_init_device(device_t, unsigned, unsigned, unsigned, unsigned);
static unsigned octopci_init_bus(device_t, unsigned);
static uint64_t octopci_cs_addr(unsigned, unsigned, unsigned, unsigned);
@ -148,6 +148,7 @@ octopci_attach(device_t dev)
*/
switch (cvmx_sysinfo_get()->board_type) {
#if defined(OCTEON_VENDOR_LANNER)
case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
/* 32-bit PCI-X */
cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0);
@ -422,14 +423,14 @@ octopci_alloc_resource(device_t bus, device_t child, int type, int *rid,
break;
case SYS_RES_IOPORT:
rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_IO)) + rman_get_start(res));
#if __mips_n64
rman_set_virtual(res, (void *)rman_get_bushandle(res));
#else
/*
* XXX
* We should just disallow use of io ports on !n64 since without
* 64-bit PTEs we can't even do a 32-bit virtual address
* mapped to them.
* We can't access ports via a 32-bit pointer.
*/
#if 0
rman_set_virtual(res, (void *)rman_get_bushandle(res));
rman_set_virtual(res, NULL);
#endif
break;
}
@ -549,8 +550,19 @@ octopci_route_interrupt(device_t dev, device_t child, int pin)
slot = pci_get_slot(child);
func = pci_get_function(child);
#if defined(OCTEON_VENDOR_LANNER)
/*
* Board types we have to know at compile-time.
*/
#if defined(OCTEON_BOARD_CAPK_0100ND)
if (bus == 0 && slot == 12 && func == 0)
return (CVMX_IRQ_PCI_INT2);
#endif
/*
* For board types we can determine at runtime.
*/
switch (cvmx_sysinfo_get()->board_type) {
#if defined(OCTEON_VENDOR_LANNER)
case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
return (CVMX_IRQ_PCI_INT0 + pin - 1);
case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
@ -562,10 +574,10 @@ octopci_route_interrupt(device_t dev, device_t child, int pin)
return (CVMX_IRQ_PCI_INT0 + (irq & 3));
}
break;
#endif
default:
break;
}
#endif
irq = slot + pin - 3;
@ -573,7 +585,7 @@ octopci_route_interrupt(device_t dev, device_t child, int pin)
}
static void
octopci_init_bar(device_t dev, unsigned b, unsigned s, unsigned f, unsigned barnum)
octopci_init_bar(device_t dev, unsigned b, unsigned s, unsigned f, unsigned barnum, uint8_t *commandp)
{
struct octopci_softc *sc;
uint32_t bar;
@ -603,6 +615,11 @@ octopci_init_bar(device_t dev, unsigned b, unsigned s, unsigned f, unsigned barn
octopci_write_config(dev, b, s, f, PCIR_BAR(barnum),
CVMX_OCT_PCI_IO_BASE + sc->sc_io_next, 4);
sc->sc_io_next += size;
/*
* Enable I/O ports.
*/
*commandp |= PCIM_CMD_PORTEN;
} else {
size = ~(bar & (uint32_t)PCIM_BAR_MEM_BASE) + 1;
@ -615,6 +632,11 @@ octopci_init_bar(device_t dev, unsigned b, unsigned s, unsigned f, unsigned barn
octopci_write_config(dev, b, s, f, PCIR_BAR(barnum),
CVMX_OCT_PCI_MEM1_BASE + sc->sc_mem1_next, 4);
sc->sc_mem1_next += size;
/*
* Enable memory access.
*/
*commandp |= PCIM_CMD_MEMEN;
}
}
@ -630,6 +652,13 @@ octopci_init_device(device_t dev, unsigned b, unsigned s, unsigned f, unsigned s
/* Read header type (again.) */
hdrtype = octopci_read_config(dev, b, s, f, PCIR_HDRTYPE, 1);
/*
* Disable memory and I/O while programming BARs.
*/
command = octopci_read_config(dev, b, s, f, PCIR_COMMAND, 1);
command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
octopci_write_config(dev, b, s, f, PCIR_COMMAND, command, 1);
/* Program BARs. */
switch (hdrtype & PCIM_HDRTYPE) {
case PCIM_HDRTYPE_NORMAL:
@ -648,14 +677,12 @@ octopci_init_device(device_t dev, unsigned b, unsigned s, unsigned f, unsigned s
}
for (barnum = 0; barnum < bars; barnum++)
octopci_init_bar(dev, b, s, f, barnum);
/* Enable memory and I/O. */
command = octopci_read_config(dev, b, s, f, PCIR_COMMAND, 1);
command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
octopci_init_bar(dev, b, s, f, barnum, &command);
/* Enable bus mastering. */
command |= PCIM_CMD_BUSMASTEREN;
/* Enable whatever facilities the BARs require. */
octopci_write_config(dev, b, s, f, PCIR_COMMAND, command, 1);
/*
@ -668,6 +695,38 @@ octopci_init_device(device_t dev, unsigned b, unsigned s, unsigned f, unsigned s
/* Set latency timer. */
octopci_write_config(dev, b, s, f, PCIR_LATTIMER, 48, 1);
/* Board-specific or device-specific fixups and workarounds. */
switch (cvmx_sysinfo_get()->board_type) {
#if defined(OCTEON_VENDOR_LANNER)
case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
if (b == 1 && s == 7 && f == 0) {
bus_addr_t busaddr, unitbusaddr;
uint32_t bar;
uint32_t tmp;
unsigned unit;
/*
* Set Tx DMA power.
*/
bar = octopci_read_config(dev, b, s, f,
PCIR_BAR(3), 4);
busaddr = CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI,
CVMX_OCT_SUBDID_PCI_MEM1));
busaddr += (bar & (uint32_t)PCIM_BAR_MEM_BASE);
for (unit = 0; unit < 4; unit++) {
unitbusaddr = busaddr + 0x430 + (unit << 8);
tmp = le32toh(cvmx_read64_uint32(unitbusaddr));
tmp &= ~0x700;
tmp |= 0x300;
cvmx_write64_uint32(unitbusaddr, htole32(tmp));
}
}
break;
#endif
default:
break;
}
/* Configure PCI-PCI bridges. */
class = octopci_read_config(dev, b, s, f, PCIR_CLASS, 1);
if (class != PCIC_BRIDGE)
@ -677,6 +736,10 @@ octopci_init_device(device_t dev, unsigned b, unsigned s, unsigned f, unsigned s
if (subclass != PCIS_BRIDGE_PCI)
return (secbus);
/* Enable memory and I/O access. */
command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
octopci_write_config(dev, b, s, f, PCIR_COMMAND, command, 1);
/* Enable errors and parity checking. Do a bus reset. */
brctl = octopci_read_config(dev, b, s, f, PCIR_BRIDGECTL_1, 1);
brctl |= PCIB_BCR_PERR_ENABLE | PCIB_BCR_SERR_ENABLE;