*
* Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
*
- * Define the pci_ops for JMR3927.
+ * Define the pci_ops for TX3927.
*
* Much of the code is derived from the original DDB5074 port by
* Geert Uytterhoeven <geert@sonycom.com>
#include <linux/init.h>
#include <asm/addrspace.h>
-#include <asm/jmr3927/jmr3927.h>
-#include <asm/debug.h>
+#include <asm/txx9/tx3927.h>
-static inline int mkaddr(unsigned char bus, unsigned char dev_fn,
- unsigned char where)
+static int mkaddr(struct pci_bus *bus, unsigned char devfn, unsigned char where)
{
- if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) |
- ((dev_fn & 0xff) << 0x08) |
- (where & 0xfc);
+ if (bus->parent == NULL &&
+ devfn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
+ return -1;
+ tx3927_pcicptr->ica =
+ ((bus->number & 0xff) << 0x10) |
+ ((devfn & 0xff) << 0x08) |
+ (where & 0xfc) | (bus->parent ? 1 : 0);
/* clear M_ABORT and Disable M_ABORT Int. */
tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT;
-
- return PCIBIOS_SUCCESSFUL;
+ return 0;
}
static inline int check_abort(void)
{
- if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
+ if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) {
tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
+ /* flush write buffer */
+ iob();
return PCIBIOS_DEVICE_NOT_FOUND;
-
+ }
return PCIBIOS_SUCCESSFUL;
}
-static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+static int tx3927_pci_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 * val)
{
- int ret;
-
- ret = mkaddr(bus->number, devfn, where);
- if (ret)
- return ret;
+ if (mkaddr(bus, devfn, where)) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
switch (size) {
case 1:
return check_abort();
}
-static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+static int tx3927_pci_write_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
- int ret;
-
- ret = mkaddr(bus->number, devfn, where);
- if (ret)
- return ret;
+ if (mkaddr(bus, devfn, where))
+ return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
case 1:
tx3927_pcicptr->icd = cpu_to_le32(val);
}
- if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
- tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
- tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
- return PCIBIOS_DEVICE_NOT_FOUND;
-
return check_abort();
}
-struct pci_ops jmr3927_pci_ops = {
- jmr3927_pci_read_config,
- jmr3927_pci_write_config,
+static struct pci_ops tx3927_pci_ops = {
+ .read = tx3927_pci_read_config,
+ .write = tx3927_pci_write_config,
};
-
-#ifndef JMR3927_INIT_INDIRECT_PCI
-
-inline unsigned long tc_readl(volatile __u32 * addr)
-{
- return readl(addr);
-}
-
-inline void tc_writel(unsigned long data, volatile __u32 * addr)
-{
- writel(data, addr);
-}
-#else
-
-unsigned long tc_readl(volatile __u32 * addr)
-{
- unsigned long val;
-
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) CPHYSADDR(addr);
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) |
- PCI_IPCIBE_IBE_LONG;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- val =
- le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
- ipcidata);
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
- return val;
-}
-
-void tc_writel(unsigned long data, volatile __u32 * addr)
-{
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata =
- cpu_to_le32(data);
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) CPHYSADDR(addr);
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) |
- PCI_IPCIBE_IBE_LONG;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-
-unsigned char tx_ioinb(unsigned char *addr)
-{
- unsigned long val;
- __u32 ioaddr;
- int offset;
- int byte;
-
- ioaddr = (unsigned long) addr;
- offset = ioaddr & 0x3;
- byte = 0xf & ~(8 >> offset);
-
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) ioaddr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- val =
- le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
- ipcidata);
- val = val & 0xff;
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
- return val;
-}
-
-void tx_iooutb(unsigned long data, unsigned char *addr)
-{
- __u32 ioaddr;
- int offset;
- int byte;
-
- data = data | (data << 8) | (data << 16) | (data << 24);
- ioaddr = (unsigned long) addr;
- offset = ioaddr & 0x3;
- byte = 0xf & ~(8 >> offset);
-
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = data;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) ioaddr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-
-unsigned short tx_ioinw(unsigned short *addr)
-{
- unsigned long val;
- __u32 ioaddr;
- int offset;
- int byte;
-
- ioaddr = (unsigned long) addr;
- offset = ioaddr & 0x2;
- byte = 3 << offset;
-
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) ioaddr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- val =
- le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
- ipcidata);
- val = val & 0xffff;
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
- return val;
-
-}
-
-void tx_iooutw(unsigned long data, unsigned short *addr)
-{
- __u32 ioaddr;
- int offset;
- int byte;
-
- data = data | (data << 16);
- ioaddr = (unsigned long) addr;
- offset = ioaddr & 0x2;
- byte = 3 << offset;
-
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = data;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) ioaddr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-
-unsigned long tx_ioinl(unsigned int *addr)
-{
- unsigned long val;
- __u32 ioaddr;
-
- ioaddr = (unsigned long) addr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) ioaddr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) |
- PCI_IPCIBE_IBE_LONG;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- val =
- le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
- ipcidata);
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
- return val;
-}
-
-void tx_iooutl(unsigned long data, unsigned int *addr)
-{
- __u32 ioaddr;
-
- ioaddr = (unsigned long) addr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata =
- cpu_to_le32(data);
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
- (unsigned long) ioaddr;
- *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
- (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) |
- PCI_IPCIBE_IBE_LONG;
- while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
- /* clear by setting */
- tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
-}
-
-void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count)
-{
- unsigned char *ptr = (unsigned char *) buffer;
-
- while (count--) {
- *ptr++ = tx_ioinb(addr);
- }
-}
-
-void tx_insword(unsigned short *addr, void *buffer, unsigned int count)
-{
- unsigned short *ptr = (unsigned short *) buffer;
-
- while (count--) {
- *ptr++ = tx_ioinw(addr);
- }
-}
-
-void tx_inslong(unsigned int *addr, void *buffer, unsigned int count)
-{
- unsigned long *ptr = (unsigned long *) buffer;
-
- while (count--) {
- *ptr++ = tx_ioinl(addr);
- }
-}
-
-void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count)
-{
- unsigned char *ptr = (unsigned char *) buffer;
-
- while (count--) {
- tx_iooutb(*ptr++, addr);
- }
-}
-
-void tx_outsword(unsigned short *addr, void *buffer, unsigned int count)
-{
- unsigned short *ptr = (unsigned short *) buffer;
-
- while (count--) {
- tx_iooutw(*ptr++, addr);
- }
-}
-
-void tx_outslong(unsigned int *addr, void *buffer, unsigned int count)
-{
- unsigned long *ptr = (unsigned long *) buffer;
-
- while (count--) {
- tx_iooutl(*ptr++, addr);
- }
-}
+void __init tx3927_pcic_setup(struct pci_controller *channel,
+ unsigned long sdram_size, int extarb)
+{
+ unsigned long flags;
+ unsigned long io_base =
+ channel->io_resource->start + mips_io_port_base - IO_BASE;
+ unsigned long io_size =
+ channel->io_resource->end - channel->io_resource->start;
+ unsigned long io_pciaddr =
+ channel->io_resource->start - channel->io_offset;
+ unsigned long mem_base =
+ channel->mem_resource->start;
+ unsigned long mem_size =
+ channel->mem_resource->end - channel->mem_resource->start;
+ unsigned long mem_pciaddr =
+ channel->mem_resource->start - channel->mem_offset;
+
+ printk(KERN_INFO "TX3927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s",
+ tx3927_pcicptr->did, tx3927_pcicptr->vid,
+ tx3927_pcicptr->rid,
+ extarb ? "External" : "Internal");
+ channel->pci_ops = &tx3927_pci_ops;
+
+ local_irq_save(flags);
+ /* Disable External PCI Config. Access */
+ tx3927_pcicptr->lbc = TX3927_PCIC_LBC_EPCAD;
+#ifdef __BIG_ENDIAN
+ tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_IBSE |
+ TX3927_PCIC_LBC_TIBSE |
+ TX3927_PCIC_LBC_TMFBSE | TX3927_PCIC_LBC_MSDSE;
#endif
+ /* LB->PCI mappings */
+ tx3927_pcicptr->iomas = ~(io_size - 1);
+ tx3927_pcicptr->ilbioma = io_base;
+ tx3927_pcicptr->ipbioma = io_pciaddr;
+ tx3927_pcicptr->mmas = ~(mem_size - 1);
+ tx3927_pcicptr->ilbmma = mem_base;
+ tx3927_pcicptr->ipbmma = mem_pciaddr;
+ /* PCI->LB mappings */
+ tx3927_pcicptr->iobas = 0xffffffff;
+ tx3927_pcicptr->ioba = 0;
+ tx3927_pcicptr->tlbioma = 0;
+ tx3927_pcicptr->mbas = ~(sdram_size - 1);
+ tx3927_pcicptr->mba = 0;
+ tx3927_pcicptr->tlbmma = 0;
+ /* Enable Direct mapping Address Space Decoder */
+ tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_ILMDE | TX3927_PCIC_LBC_ILIDE;
+
+ /* Clear All Local Bus Status */
+ tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL;
+ /* Enable All Local Bus Interrupts */
+ tx3927_pcicptr->lbim = TX3927_PCIC_LBIM_ALL;
+ /* Clear All PCI Status Error */
+ tx3927_pcicptr->pcistat = TX3927_PCIC_PCISTATIM_ALL;
+ /* Enable All PCI Status Error Interrupts */
+ tx3927_pcicptr->pcistatim = TX3927_PCIC_PCISTATIM_ALL;
+
+ /* PCIC Int => IRC IRQ10 */
+ tx3927_pcicptr->il = TX3927_IR_PCI;
+ /* Target Control (per errata) */
+ tx3927_pcicptr->tc = TX3927_PCIC_TC_OF8E | TX3927_PCIC_TC_IF8E;
+
+ /* Enable Bus Arbiter */
+ if (!extarb)
+ tx3927_pcicptr->pbapmc = TX3927_PCIC_PBAPMC_PBAEN;
+
+ tx3927_pcicptr->pcicmd = PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ local_irq_restore(flags);
+}