15283ecb5SPaul Mundt /* 25283ecb5SPaul Mundt * Low-Level PCI Support for the SH7780 35283ecb5SPaul Mundt * 4a45635dfSPaul Mundt * Copyright (C) 2005 - 2010 Paul Mundt 55283ecb5SPaul Mundt * 662c7ae87SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 762c7ae87SPaul Mundt * License. See the file "COPYING" in the main directory of this archive 862c7ae87SPaul Mundt * for more details. 95283ecb5SPaul Mundt */ 105283ecb5SPaul Mundt #include <linux/types.h> 115283ecb5SPaul Mundt #include <linux/kernel.h> 125283ecb5SPaul Mundt #include <linux/init.h> 135283ecb5SPaul Mundt #include <linux/pci.h> 14ef407beeSPaul Mundt #include <linux/interrupt.h> 15ef407beeSPaul Mundt #include <linux/timer.h> 16ef407beeSPaul Mundt #include <linux/irq.h> 175283ecb5SPaul Mundt #include <linux/errno.h> 185283ecb5SPaul Mundt #include <linux/delay.h> 19aee4467bSPaul Mundt #include <linux/log2.h> 20959f85f8SPaul Mundt #include "pci-sh4.h" 21a45635dfSPaul Mundt #include <asm/mmu.h> 22a45635dfSPaul Mundt #include <asm/sizes.h> 235283ecb5SPaul Mundt 24*bfc906d8SThomas Schwinge #if defined(CONFIG_CPU_BIG_ENDIAN) 25*bfc906d8SThomas Schwinge # define PCICR_ENDIANNESS SH4_PCICR_BSWP 26*bfc906d8SThomas Schwinge #else 27*bfc906d8SThomas Schwinge # define PCICR_ENDIANNESS 0 28*bfc906d8SThomas Schwinge #endif 29*bfc906d8SThomas Schwinge 30*bfc906d8SThomas Schwinge 31b6c58b1dSPaul Mundt static struct resource sh7785_pci_resources[] = { 32b6c58b1dSPaul Mundt { 333b0be1a4SPaul Mundt .name = "PCI IO", 34a45635dfSPaul Mundt .start = 0x1000, 35b6c58b1dSPaul Mundt .end = SZ_4M - 1, 36b6c58b1dSPaul Mundt .flags = IORESOURCE_IO, 37b6c58b1dSPaul Mundt }, { 38b6c58b1dSPaul Mundt .name = "PCI MEM 0", 39b6c58b1dSPaul Mundt .start = 0xfd000000, 40b6c58b1dSPaul Mundt .end = 0xfd000000 + SZ_16M - 1, 41b6c58b1dSPaul Mundt .flags = IORESOURCE_MEM, 42b6c58b1dSPaul Mundt }, { 43b6c58b1dSPaul Mundt .name = "PCI MEM 1", 44b6c58b1dSPaul Mundt .start = 0x10000000, 45b6c58b1dSPaul Mundt .end = 0x10000000 + SZ_64M - 1, 46b6c58b1dSPaul Mundt .flags = IORESOURCE_MEM, 47b6c58b1dSPaul Mundt }, { 48b6c58b1dSPaul Mundt /* 49b6c58b1dSPaul Mundt * 32-bit only resources must be last. 50b6c58b1dSPaul Mundt */ 51b6c58b1dSPaul Mundt .name = "PCI MEM 2", 52b6c58b1dSPaul Mundt .start = 0xc0000000, 53b6c58b1dSPaul Mundt .end = 0xc0000000 + SZ_512M - 1, 54b6c58b1dSPaul Mundt .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, 55b6c58b1dSPaul Mundt }, 56e79066a6SPaul Mundt }; 57e79066a6SPaul Mundt 58e79066a6SPaul Mundt static struct pci_channel sh7780_pci_controller = { 59e79066a6SPaul Mundt .pci_ops = &sh4_pci_ops, 60b6c58b1dSPaul Mundt .resources = sh7785_pci_resources, 61b6c58b1dSPaul Mundt .nr_resources = ARRAY_SIZE(sh7785_pci_resources), 62b6c58b1dSPaul Mundt .io_offset = 0, 63b6c58b1dSPaul Mundt .mem_offset = 0, 64b6c58b1dSPaul Mundt .io_map_base = 0xfe200000, 65ef407beeSPaul Mundt .serr_irq = evt2irq(0xa00), 66ef407beeSPaul Mundt .err_irq = evt2irq(0xaa0), 67e79066a6SPaul Mundt }; 68e79066a6SPaul Mundt 69ef407beeSPaul Mundt struct pci_errors { 70ef407beeSPaul Mundt unsigned int mask; 71ef407beeSPaul Mundt const char *str; 72ef407beeSPaul Mundt } pci_arbiter_errors[] = { 73ef407beeSPaul Mundt { SH4_PCIAINT_MBKN, "master broken" }, 74ef407beeSPaul Mundt { SH4_PCIAINT_TBTO, "target bus time out" }, 75ef407beeSPaul Mundt { SH4_PCIAINT_MBTO, "master bus time out" }, 76ef407beeSPaul Mundt { SH4_PCIAINT_TABT, "target abort" }, 77ef407beeSPaul Mundt { SH4_PCIAINT_MABT, "master abort" }, 78ef407beeSPaul Mundt { SH4_PCIAINT_RDPE, "read data parity error" }, 79ef407beeSPaul Mundt { SH4_PCIAINT_WDPE, "write data parity error" }, 80ef407beeSPaul Mundt }, pci_interrupt_errors[] = { 81ef407beeSPaul Mundt { SH4_PCIINT_MLCK, "master lock error" }, 82ef407beeSPaul Mundt { SH4_PCIINT_TABT, "target-target abort" }, 83ef407beeSPaul Mundt { SH4_PCIINT_TRET, "target retry time out" }, 84ecfb68c6SMasanari Iida { SH4_PCIINT_MFDE, "master function disable error" }, 85ef407beeSPaul Mundt { SH4_PCIINT_PRTY, "address parity error" }, 86ef407beeSPaul Mundt { SH4_PCIINT_SERR, "SERR" }, 87ef407beeSPaul Mundt { SH4_PCIINT_TWDP, "data parity error for target write" }, 88ef407beeSPaul Mundt { SH4_PCIINT_TRDP, "PERR detected for target read" }, 89ef407beeSPaul Mundt { SH4_PCIINT_MTABT, "target abort for master" }, 90ef407beeSPaul Mundt { SH4_PCIINT_MMABT, "master abort for master" }, 91ef407beeSPaul Mundt { SH4_PCIINT_MWPD, "master write data parity error" }, 92ef407beeSPaul Mundt { SH4_PCIINT_MRPD, "master read data parity error" }, 93ef407beeSPaul Mundt }; 94ef407beeSPaul Mundt 95ef407beeSPaul Mundt static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id) 96ef407beeSPaul Mundt { 97ef407beeSPaul Mundt struct pci_channel *hose = dev_id; 98ef407beeSPaul Mundt unsigned long addr; 99ef407beeSPaul Mundt unsigned int status; 100ef407beeSPaul Mundt unsigned int cmd; 101ef407beeSPaul Mundt int i; 102ef407beeSPaul Mundt 103ef407beeSPaul Mundt addr = __raw_readl(hose->reg_base + SH4_PCIALR); 104ef407beeSPaul Mundt 105ef407beeSPaul Mundt /* 106ef407beeSPaul Mundt * Handle status errors. 107ef407beeSPaul Mundt */ 108ef407beeSPaul Mundt status = __raw_readw(hose->reg_base + PCI_STATUS); 109ef407beeSPaul Mundt if (status & (PCI_STATUS_PARITY | 110ef407beeSPaul Mundt PCI_STATUS_DETECTED_PARITY | 111ef407beeSPaul Mundt PCI_STATUS_SIG_TARGET_ABORT | 112ef407beeSPaul Mundt PCI_STATUS_REC_TARGET_ABORT | 113ef407beeSPaul Mundt PCI_STATUS_REC_MASTER_ABORT)) { 114ef407beeSPaul Mundt cmd = pcibios_handle_status_errors(addr, status, hose); 115ef407beeSPaul Mundt if (likely(cmd)) 116ef407beeSPaul Mundt __raw_writew(cmd, hose->reg_base + PCI_STATUS); 117ef407beeSPaul Mundt } 118ef407beeSPaul Mundt 119ef407beeSPaul Mundt /* 120ef407beeSPaul Mundt * Handle arbiter errors. 121ef407beeSPaul Mundt */ 122ef407beeSPaul Mundt status = __raw_readl(hose->reg_base + SH4_PCIAINT); 123ef407beeSPaul Mundt for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) { 124ef407beeSPaul Mundt if (status & pci_arbiter_errors[i].mask) { 125ef407beeSPaul Mundt printk(KERN_DEBUG "PCI: %s, addr=%08lx\n", 126ef407beeSPaul Mundt pci_arbiter_errors[i].str, addr); 127ef407beeSPaul Mundt cmd |= pci_arbiter_errors[i].mask; 128ef407beeSPaul Mundt } 129ef407beeSPaul Mundt } 130ef407beeSPaul Mundt __raw_writel(cmd, hose->reg_base + SH4_PCIAINT); 131ef407beeSPaul Mundt 132ef407beeSPaul Mundt /* 133ef407beeSPaul Mundt * Handle the remaining PCI errors. 134ef407beeSPaul Mundt */ 135ef407beeSPaul Mundt status = __raw_readl(hose->reg_base + SH4_PCIINT); 136ef407beeSPaul Mundt for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) { 137ef407beeSPaul Mundt if (status & pci_interrupt_errors[i].mask) { 138ef407beeSPaul Mundt printk(KERN_DEBUG "PCI: %s, addr=%08lx\n", 139ef407beeSPaul Mundt pci_interrupt_errors[i].str, addr); 140ef407beeSPaul Mundt cmd |= pci_interrupt_errors[i].mask; 141ef407beeSPaul Mundt } 142ef407beeSPaul Mundt } 143ef407beeSPaul Mundt __raw_writel(cmd, hose->reg_base + SH4_PCIINT); 144ef407beeSPaul Mundt 145ef407beeSPaul Mundt return IRQ_HANDLED; 146ef407beeSPaul Mundt } 147ef407beeSPaul Mundt 148ef407beeSPaul Mundt static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id) 149ef407beeSPaul Mundt { 150ef407beeSPaul Mundt struct pci_channel *hose = dev_id; 151ef407beeSPaul Mundt 152ef407beeSPaul Mundt printk(KERN_DEBUG "PCI: system error received: "); 153ef407beeSPaul Mundt pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1); 154ef407beeSPaul Mundt printk("\n"); 155ef407beeSPaul Mundt 156ef407beeSPaul Mundt /* Deassert SERR */ 157ef407beeSPaul Mundt __raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM); 158ef407beeSPaul Mundt 159ef407beeSPaul Mundt /* Back off the IRQ for awhile */ 1609ad62ec4SPaul Mundt disable_irq_nosync(irq); 161ef407beeSPaul Mundt hose->serr_timer.expires = jiffies + HZ; 162ef407beeSPaul Mundt add_timer(&hose->serr_timer); 163ef407beeSPaul Mundt 164ef407beeSPaul Mundt return IRQ_HANDLED; 165ef407beeSPaul Mundt } 166ef407beeSPaul Mundt 167ef407beeSPaul Mundt static int __init sh7780_pci_setup_irqs(struct pci_channel *hose) 168ef407beeSPaul Mundt { 169ef407beeSPaul Mundt int ret; 170ef407beeSPaul Mundt 171ef407beeSPaul Mundt /* Clear out PCI arbiter IRQs */ 172ef407beeSPaul Mundt __raw_writel(0, hose->reg_base + SH4_PCIAINT); 173ef407beeSPaul Mundt 174ef407beeSPaul Mundt /* Clear all error conditions */ 175ef407beeSPaul Mundt __raw_writew(PCI_STATUS_DETECTED_PARITY | \ 176ef407beeSPaul Mundt PCI_STATUS_SIG_SYSTEM_ERROR | \ 177ef407beeSPaul Mundt PCI_STATUS_REC_MASTER_ABORT | \ 178ef407beeSPaul Mundt PCI_STATUS_REC_TARGET_ABORT | \ 179ef407beeSPaul Mundt PCI_STATUS_SIG_TARGET_ABORT | \ 180ef407beeSPaul Mundt PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS); 181ef407beeSPaul Mundt 182d11584a0SYong Zhang ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0, 183ef407beeSPaul Mundt "PCI SERR interrupt", hose); 184ef407beeSPaul Mundt if (unlikely(ret)) { 185ef407beeSPaul Mundt printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n"); 186ef407beeSPaul Mundt return ret; 187ef407beeSPaul Mundt } 188ef407beeSPaul Mundt 189ef407beeSPaul Mundt /* 190ef407beeSPaul Mundt * The PCI ERR IRQ needs to be IRQF_SHARED since all of the power 191ef407beeSPaul Mundt * down IRQ vectors are routed through the ERR IRQ vector. We 192ef407beeSPaul Mundt * only request_irq() once as there is only a single masking 193ef407beeSPaul Mundt * source for multiple events. 194ef407beeSPaul Mundt */ 195ef407beeSPaul Mundt ret = request_irq(hose->err_irq, sh7780_pci_err_irq, IRQF_SHARED, 196ef407beeSPaul Mundt "PCI ERR interrupt", hose); 197ef407beeSPaul Mundt if (unlikely(ret)) { 198ef407beeSPaul Mundt free_irq(hose->serr_irq, hose); 199ef407beeSPaul Mundt return ret; 200ef407beeSPaul Mundt } 201ef407beeSPaul Mundt 202ef407beeSPaul Mundt /* Unmask all of the arbiter IRQs. */ 203ef407beeSPaul Mundt __raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \ 204ef407beeSPaul Mundt SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \ 205ef407beeSPaul Mundt SH4_PCIAINT_WDPE, hose->reg_base + SH4_PCIAINTM); 206ef407beeSPaul Mundt 207ef407beeSPaul Mundt /* Unmask all of the PCI IRQs */ 208ef407beeSPaul Mundt __raw_writel(SH4_PCIINTM_TTADIM | SH4_PCIINTM_TMTOIM | \ 209ef407beeSPaul Mundt SH4_PCIINTM_MDEIM | SH4_PCIINTM_APEDIM | \ 210ef407beeSPaul Mundt SH4_PCIINTM_SDIM | SH4_PCIINTM_DPEITWM | \ 211ef407beeSPaul Mundt SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM | \ 212ef407beeSPaul Mundt SH4_PCIINTM_MADIMM | SH4_PCIINTM_MWPDIM | \ 213ef407beeSPaul Mundt SH4_PCIINTM_MRDPEIM, hose->reg_base + SH4_PCIINTM); 214ef407beeSPaul Mundt 215ef407beeSPaul Mundt return ret; 216ef407beeSPaul Mundt } 217ef407beeSPaul Mundt 218ef407beeSPaul Mundt static inline void __init sh7780_pci_teardown_irqs(struct pci_channel *hose) 219ef407beeSPaul Mundt { 220ef407beeSPaul Mundt free_irq(hose->err_irq, hose); 221ef407beeSPaul Mundt free_irq(hose->serr_irq, hose); 222ef407beeSPaul Mundt } 223ef407beeSPaul Mundt 22485b59f5bSPaul Mundt static void __init sh7780_pci66_init(struct pci_channel *hose) 22585b59f5bSPaul Mundt { 22685b59f5bSPaul Mundt unsigned int tmp; 22785b59f5bSPaul Mundt 22885b59f5bSPaul Mundt if (!pci_is_66mhz_capable(hose, 0, 0)) 22985b59f5bSPaul Mundt return; 23085b59f5bSPaul Mundt 23185b59f5bSPaul Mundt /* Enable register access */ 23285b59f5bSPaul Mundt tmp = __raw_readl(hose->reg_base + SH4_PCICR); 23385b59f5bSPaul Mundt tmp |= SH4_PCICR_PREFIX; 23485b59f5bSPaul Mundt __raw_writel(tmp, hose->reg_base + SH4_PCICR); 23585b59f5bSPaul Mundt 23685b59f5bSPaul Mundt /* Enable 66MHz operation */ 23785b59f5bSPaul Mundt tmp = __raw_readw(hose->reg_base + PCI_STATUS); 23885b59f5bSPaul Mundt tmp |= PCI_STATUS_66MHZ; 23985b59f5bSPaul Mundt __raw_writew(tmp, hose->reg_base + PCI_STATUS); 24085b59f5bSPaul Mundt 24185b59f5bSPaul Mundt /* Done */ 24285b59f5bSPaul Mundt tmp = __raw_readl(hose->reg_base + SH4_PCICR); 24385b59f5bSPaul Mundt tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN; 24485b59f5bSPaul Mundt __raw_writel(tmp, hose->reg_base + SH4_PCICR); 24585b59f5bSPaul Mundt } 24685b59f5bSPaul Mundt 247e79066a6SPaul Mundt static int __init sh7780_pci_init(void) 2485283ecb5SPaul Mundt { 249e79066a6SPaul Mundt struct pci_channel *chan = &sh7780_pci_controller; 250a45635dfSPaul Mundt phys_addr_t memphys; 251a45635dfSPaul Mundt size_t memsize; 252959f85f8SPaul Mundt unsigned int id; 253a45635dfSPaul Mundt const char *type; 254b6c58b1dSPaul Mundt int ret, i; 2555283ecb5SPaul Mundt 2563b554c33SMatt Fleming printk(KERN_NOTICE "PCI: Starting initialization.\n"); 2575283ecb5SPaul Mundt 258e4c6a360SMagnus Damm chan->reg_base = 0xfe040000; 259e4c6a360SMagnus Damm 2604e7b7fdbSPaul Mundt /* Enable CPU access to the PCIC registers. */ 2614e7b7fdbSPaul Mundt __raw_writel(PCIECR_ENBL, PCIECR); 262959f85f8SPaul Mundt 263a45635dfSPaul Mundt /* Reset */ 264*bfc906d8SThomas Schwinge __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST | PCICR_ENDIANNESS, 265a45635dfSPaul Mundt chan->reg_base + SH4_PCICR); 266a45635dfSPaul Mundt 267aee4467bSPaul Mundt /* 268aee4467bSPaul Mundt * Wait for it to come back up. The spec says to allow for up to 269aee4467bSPaul Mundt * 1 second after toggling the reset pin, but in practice 100ms 270aee4467bSPaul Mundt * is more than enough. 271aee4467bSPaul Mundt */ 272a45635dfSPaul Mundt mdelay(100); 273a45635dfSPaul Mundt 274a45635dfSPaul Mundt id = __raw_readw(chan->reg_base + PCI_VENDOR_ID); 275a45635dfSPaul Mundt if (id != PCI_VENDOR_ID_RENESAS) { 2764e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); 277959f85f8SPaul Mundt return -ENODEV; 278959f85f8SPaul Mundt } 279959f85f8SPaul Mundt 280a45635dfSPaul Mundt id = __raw_readw(chan->reg_base + PCI_DEVICE_ID); 281a45635dfSPaul Mundt type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" : 282a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" : 283a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" : 284a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" : 2854e7b7fdbSPaul Mundt NULL; 2864e7b7fdbSPaul Mundt if (unlikely(!type)) { 2874e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Found an unsupported Renesas host " 2884e7b7fdbSPaul Mundt "controller, device id 0x%04x.\n", id); 2894e7b7fdbSPaul Mundt return -EINVAL; 2904e7b7fdbSPaul Mundt } 2914e7b7fdbSPaul Mundt 2924e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Found a Renesas %s host " 2934e7b7fdbSPaul Mundt "controller, revision %d.\n", type, 294a45635dfSPaul Mundt __raw_readb(chan->reg_base + PCI_REVISION_ID)); 2954e7b7fdbSPaul Mundt 296c66c1d79SPaul Mundt /* 297a45635dfSPaul Mundt * Now throw it in to register initialization mode and 298a45635dfSPaul Mundt * start the real work. 299c66c1d79SPaul Mundt */ 300*bfc906d8SThomas Schwinge __raw_writel(SH4_PCICR_PREFIX | PCICR_ENDIANNESS, 301*bfc906d8SThomas Schwinge chan->reg_base + SH4_PCICR); 302a45635dfSPaul Mundt 303aee4467bSPaul Mundt memphys = __pa(memory_start); 304aee4467bSPaul Mundt memsize = roundup_pow_of_two(memory_end - memory_start); 305aee4467bSPaul Mundt 306aee4467bSPaul Mundt /* 307aee4467bSPaul Mundt * If there's more than 512MB of memory, we need to roll over to 308aee4467bSPaul Mundt * LAR1/LSR1. 309aee4467bSPaul Mundt */ 310aee4467bSPaul Mundt if (memsize > SZ_512M) { 311aee4467bSPaul Mundt __raw_writel(memphys + SZ_512M, chan->reg_base + SH4_PCILAR1); 312aee4467bSPaul Mundt __raw_writel((((memsize - SZ_512M) - SZ_1M) & 0x1ff00000) | 1, 313aee4467bSPaul Mundt chan->reg_base + SH4_PCILSR1); 314aee4467bSPaul Mundt memsize = SZ_512M; 315aee4467bSPaul Mundt } else { 316aee4467bSPaul Mundt /* 317aee4467bSPaul Mundt * Otherwise just zero it out and disable it. 318aee4467bSPaul Mundt */ 319aee4467bSPaul Mundt __raw_writel(0, chan->reg_base + SH4_PCILAR1); 320aee4467bSPaul Mundt __raw_writel(0, chan->reg_base + SH4_PCILSR1); 321aee4467bSPaul Mundt } 322aee4467bSPaul Mundt 323aee4467bSPaul Mundt /* 324aee4467bSPaul Mundt * LAR0/LSR0 covers up to the first 512MB, which is enough to 325aee4467bSPaul Mundt * cover all of lowmem on most platforms. 326aee4467bSPaul Mundt */ 327a45635dfSPaul Mundt __raw_writel(memphys, chan->reg_base + SH4_PCILAR0); 328aee4467bSPaul Mundt __raw_writel(((memsize - SZ_1M) & 0x1ff00000) | 1, 329a45635dfSPaul Mundt chan->reg_base + SH4_PCILSR0); 33062c7ae87SPaul Mundt 331ef407beeSPaul Mundt /* 332ef407beeSPaul Mundt * Hook up the ERR and SERR IRQs. 333ef407beeSPaul Mundt */ 334ef407beeSPaul Mundt ret = sh7780_pci_setup_irqs(chan); 335ef407beeSPaul Mundt if (unlikely(ret)) 336ef407beeSPaul Mundt return ret; 33762c7ae87SPaul Mundt 338a45635dfSPaul Mundt /* 339a45635dfSPaul Mundt * Disable the cache snoop controller for non-coherent DMA. 340a45635dfSPaul Mundt */ 341a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSCR0); 342a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSAR0); 343a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSCR1); 344a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSAR1); 34562c7ae87SPaul Mundt 346b6c58b1dSPaul Mundt /* 347b6c58b1dSPaul Mundt * Setup the memory BARs 348b6c58b1dSPaul Mundt */ 3493b0be1a4SPaul Mundt for (i = 1; i < chan->nr_resources; i++) { 3503b0be1a4SPaul Mundt struct resource *res = chan->resources + i; 351b6c58b1dSPaul Mundt resource_size_t size; 352a45635dfSPaul Mundt 353b6c58b1dSPaul Mundt if (unlikely(res->flags & IORESOURCE_IO)) 354b6c58b1dSPaul Mundt continue; 355b6c58b1dSPaul Mundt 356b6c58b1dSPaul Mundt /* 357b6c58b1dSPaul Mundt * Make sure we're in the right physical addressing mode 358b6c58b1dSPaul Mundt * for dealing with the resource. 359b6c58b1dSPaul Mundt */ 360b6c58b1dSPaul Mundt if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) { 361b6c58b1dSPaul Mundt chan->nr_resources--; 362b6c58b1dSPaul Mundt continue; 363b6c58b1dSPaul Mundt } 364b6c58b1dSPaul Mundt 365b6c58b1dSPaul Mundt size = resource_size(res); 366b6c58b1dSPaul Mundt 367b6c58b1dSPaul Mundt /* 368b6c58b1dSPaul Mundt * The MBMR mask is calculated in units of 256kB, which 369b6c58b1dSPaul Mundt * keeps things pretty simple. 370b6c58b1dSPaul Mundt */ 371b6c58b1dSPaul Mundt __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18, 3723b0be1a4SPaul Mundt chan->reg_base + SH7780_PCIMBMR(i - 1)); 3733b0be1a4SPaul Mundt __raw_writel(res->start, chan->reg_base + SH7780_PCIMBR(i - 1)); 374b6c58b1dSPaul Mundt } 375b6c58b1dSPaul Mundt 376b6c58b1dSPaul Mundt /* 377b6c58b1dSPaul Mundt * And I/O. 378b6c58b1dSPaul Mundt */ 379b6c58b1dSPaul Mundt __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0); 380a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCIIOBR); 381a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCIIOBMR); 382a45635dfSPaul Mundt 383ef407beeSPaul Mundt __raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \ 384ef407beeSPaul Mundt PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \ 385ef407beeSPaul Mundt PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND); 386ef407beeSPaul Mundt 387a45635dfSPaul Mundt /* 388a45635dfSPaul Mundt * Initialization mode complete, release the control register and 389a45635dfSPaul Mundt * enable round robin mode to stop device overruns/starvation. 390a45635dfSPaul Mundt */ 391*bfc906d8SThomas Schwinge __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO | 392*bfc906d8SThomas Schwinge PCICR_ENDIANNESS, 393a45635dfSPaul Mundt chan->reg_base + SH4_PCICR); 3945283ecb5SPaul Mundt 395bcf39352SPaul Mundt ret = register_pci_controller(chan); 396bcf39352SPaul Mundt if (unlikely(ret)) 397ef407beeSPaul Mundt goto err; 398e79066a6SPaul Mundt 39985b59f5bSPaul Mundt sh7780_pci66_init(chan); 40085b59f5bSPaul Mundt 40185b59f5bSPaul Mundt printk(KERN_NOTICE "PCI: Running at %dMHz.\n", 40285b59f5bSPaul Mundt (__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ? 40385b59f5bSPaul Mundt 66 : 33); 40485b59f5bSPaul Mundt 405d0e3db40SMagnus Damm return 0; 406ef407beeSPaul Mundt 407ef407beeSPaul Mundt err: 408ef407beeSPaul Mundt sh7780_pci_teardown_irqs(chan); 409ef407beeSPaul Mundt return ret; 4105283ecb5SPaul Mundt } 411e79066a6SPaul Mundt arch_initcall(sh7780_pci_init); 412