in pci/pci-vr41xx.c [97:307]
static int __init vr41xx_pciu_init(void)
{
struct pci_controller_unit_setup *setup;
struct pci_master_address_conversion *master;
struct pci_target_address_conversion *target;
struct pci_mailbox_address *mailbox;
struct pci_target_address_window *window;
unsigned long vtclock, pci_clock_max;
uint32_t val;
setup = &vr41xx_pci_controller_unit_setup;
if (request_mem_region(PCIU_BASE, PCIU_SIZE, "PCIU") == NULL)
return -EBUSY;
pciu_base = ioremap(PCIU_BASE, PCIU_SIZE);
if (pciu_base == NULL) {
release_mem_region(PCIU_BASE, PCIU_SIZE);
return -EBUSY;
}
/* Disable PCI interrupt */
vr41xx_disable_pciint();
/* Supply VTClock to PCIU */
vr41xx_supply_clock(PCIU_CLOCK);
/* Dummy write, waiting for supply of VTClock. */
vr41xx_disable_pciint();
/* Select PCI clock */
if (setup->pci_clock_max != 0)
pci_clock_max = setup->pci_clock_max;
else
pci_clock_max = PCI_CLOCK_MAX;
vtclock = vr41xx_get_vtclock_frequency();
if (vtclock < pci_clock_max)
pciu_write(PCICLKSELREG, EQUAL_VTCLOCK);
else if ((vtclock / 2) < pci_clock_max)
pciu_write(PCICLKSELREG, HALF_VTCLOCK);
else if (current_cpu_data.processor_id >= PRID_VR4131_REV2_1 &&
(vtclock / 3) < pci_clock_max)
pciu_write(PCICLKSELREG, ONE_THIRD_VTCLOCK);
else if ((vtclock / 4) < pci_clock_max)
pciu_write(PCICLKSELREG, QUARTER_VTCLOCK);
else {
printk(KERN_ERR "PCI Clock is over 33MHz.\n");
iounmap(pciu_base);
return -EINVAL;
}
/* Supply PCI clock by PCI bus */
vr41xx_supply_clock(PCI_CLOCK);
if (setup->master_memory1 != NULL) {
master = setup->master_memory1;
val = IBA(master->bus_base_address) |
MASTER_MSK(master->address_mask) |
WINEN |
PCIA(master->pci_base_address);
pciu_write(PCIMMAW1REG, val);
} else {
val = pciu_read(PCIMMAW1REG);
val &= ~WINEN;
pciu_write(PCIMMAW1REG, val);
}
if (setup->master_memory2 != NULL) {
master = setup->master_memory2;
val = IBA(master->bus_base_address) |
MASTER_MSK(master->address_mask) |
WINEN |
PCIA(master->pci_base_address);
pciu_write(PCIMMAW2REG, val);
} else {
val = pciu_read(PCIMMAW2REG);
val &= ~WINEN;
pciu_write(PCIMMAW2REG, val);
}
if (setup->target_memory1 != NULL) {
target = setup->target_memory1;
val = TARGET_MSK(target->address_mask) |
WINEN |
ITA(target->bus_base_address);
pciu_write(PCITAW1REG, val);
} else {
val = pciu_read(PCITAW1REG);
val &= ~WINEN;
pciu_write(PCITAW1REG, val);
}
if (setup->target_memory2 != NULL) {
target = setup->target_memory2;
val = TARGET_MSK(target->address_mask) |
WINEN |
ITA(target->bus_base_address);
pciu_write(PCITAW2REG, val);
} else {
val = pciu_read(PCITAW2REG);
val &= ~WINEN;
pciu_write(PCITAW2REG, val);
}
if (setup->master_io != NULL) {
master = setup->master_io;
val = IBA(master->bus_base_address) |
MASTER_MSK(master->address_mask) |
WINEN |
PCIIA(master->pci_base_address);
pciu_write(PCIMIOAWREG, val);
} else {
val = pciu_read(PCIMIOAWREG);
val &= ~WINEN;
pciu_write(PCIMIOAWREG, val);
}
if (setup->exclusive_access == CANNOT_LOCK_FROM_DEVICE)
pciu_write(PCIEXACCREG, UNLOCK);
else
pciu_write(PCIEXACCREG, 0);
if (current_cpu_type() == CPU_VR4122)
pciu_write(PCITRDYVREG, TRDYV(setup->wait_time_limit_from_irdy_to_trdy));
pciu_write(LATTIMEREG, MLTIM(setup->master_latency_timer));
if (setup->mailbox != NULL) {
mailbox = setup->mailbox;
val = MBADD(mailbox->base_address) | TYPE_32BITSPACE |
MSI_MEMORY | PREF_APPROVAL;
pciu_write(MAILBAREG, val);
}
if (setup->target_window1) {
window = setup->target_window1;
val = PMBA(window->base_address) | TYPE_32BITSPACE |
MSI_MEMORY | PREF_APPROVAL;
pciu_write(PCIMBA1REG, val);
}
if (setup->target_window2) {
window = setup->target_window2;
val = PMBA(window->base_address) | TYPE_32BITSPACE |
MSI_MEMORY | PREF_APPROVAL;
pciu_write(PCIMBA2REG, val);
}
val = pciu_read(RETVALREG);
val &= ~RTYVAL_MASK;
val |= RTYVAL(setup->retry_limit);
pciu_write(RETVALREG, val);
val = pciu_read(PCIAPCNTREG);
val &= ~(TKYGNT | PAPC);
switch (setup->arbiter_priority_control) {
case PCI_ARBITRATION_MODE_ALTERNATE_0:
val |= PAPC_ALTERNATE_0;
break;
case PCI_ARBITRATION_MODE_ALTERNATE_B:
val |= PAPC_ALTERNATE_B;
break;
default:
val |= PAPC_FAIR;
break;
}
if (setup->take_away_gnt_mode == PCI_TAKE_AWAY_GNT_ENABLE)
val |= TKYGNT_ENABLE;
pciu_write(PCIAPCNTREG, val);
pciu_write(COMMANDREG, PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_PARITY |
PCI_COMMAND_SERR);
/* Clear bus error */
pciu_read(BUSERRADREG);
pciu_write(PCIENREG, PCIU_CONFIG_DONE);
if (setup->mem_resource != NULL)
vr41xx_pci_controller.mem_resource = setup->mem_resource;
if (setup->io_resource != NULL) {
vr41xx_pci_controller.io_resource = setup->io_resource;
} else {
set_io_port_base(IO_PORT_BASE);
ioport_resource.start = IO_PORT_RESOURCE_START;
ioport_resource.end = IO_PORT_RESOURCE_END;
}
if (setup->master_io) {
void __iomem *io_map_base;
struct resource *res = vr41xx_pci_controller.io_resource;
master = setup->master_io;
io_map_base = ioremap(master->bus_base_address,
resource_size(res));
if (!io_map_base) {
iounmap(pciu_base);
return -EBUSY;
}
vr41xx_pci_controller.io_map_base = (unsigned long)io_map_base;
}
register_pci_controller(&vr41xx_pci_controller);
return 0;
}