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 24b6c58b1dSPaul Mundt static struct resource sh7785_pci_resources[] = { 25b6c58b1dSPaul Mundt { 263b0be1a4SPaul Mundt .name = "PCI IO", 27a45635dfSPaul Mundt .start = 0x1000, 28b6c58b1dSPaul Mundt .end = SZ_4M - 1, 29b6c58b1dSPaul Mundt .flags = IORESOURCE_IO, 30b6c58b1dSPaul Mundt }, { 31b6c58b1dSPaul Mundt .name = "PCI MEM 0", 32b6c58b1dSPaul Mundt .start = 0xfd000000, 33b6c58b1dSPaul Mundt .end = 0xfd000000 + SZ_16M - 1, 34b6c58b1dSPaul Mundt .flags = IORESOURCE_MEM, 35b6c58b1dSPaul Mundt }, { 36b6c58b1dSPaul Mundt .name = "PCI MEM 1", 37b6c58b1dSPaul Mundt .start = 0x10000000, 38b6c58b1dSPaul Mundt .end = 0x10000000 + SZ_64M - 1, 39b6c58b1dSPaul Mundt .flags = IORESOURCE_MEM, 40b6c58b1dSPaul Mundt }, { 41b6c58b1dSPaul Mundt /* 42b6c58b1dSPaul Mundt * 32-bit only resources must be last. 43b6c58b1dSPaul Mundt */ 44b6c58b1dSPaul Mundt .name = "PCI MEM 2", 45b6c58b1dSPaul Mundt .start = 0xc0000000, 46b6c58b1dSPaul Mundt .end = 0xc0000000 + SZ_512M - 1, 47b6c58b1dSPaul Mundt .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, 48b6c58b1dSPaul Mundt }, 49e79066a6SPaul Mundt }; 50e79066a6SPaul Mundt 51e79066a6SPaul Mundt static struct pci_channel sh7780_pci_controller = { 52e79066a6SPaul Mundt .pci_ops = &sh4_pci_ops, 53b6c58b1dSPaul Mundt .resources = sh7785_pci_resources, 54b6c58b1dSPaul Mundt .nr_resources = ARRAY_SIZE(sh7785_pci_resources), 55b6c58b1dSPaul Mundt .io_offset = 0, 56b6c58b1dSPaul Mundt .mem_offset = 0, 57b6c58b1dSPaul Mundt .io_map_base = 0xfe200000, 58ef407beeSPaul Mundt .serr_irq = evt2irq(0xa00), 59ef407beeSPaul Mundt .err_irq = evt2irq(0xaa0), 60e79066a6SPaul Mundt }; 61e79066a6SPaul Mundt 62ef407beeSPaul Mundt struct pci_errors { 63ef407beeSPaul Mundt unsigned int mask; 64ef407beeSPaul Mundt const char *str; 65ef407beeSPaul Mundt } pci_arbiter_errors[] = { 66ef407beeSPaul Mundt { SH4_PCIAINT_MBKN, "master broken" }, 67ef407beeSPaul Mundt { SH4_PCIAINT_TBTO, "target bus time out" }, 68ef407beeSPaul Mundt { SH4_PCIAINT_MBTO, "master bus time out" }, 69ef407beeSPaul Mundt { SH4_PCIAINT_TABT, "target abort" }, 70ef407beeSPaul Mundt { SH4_PCIAINT_MABT, "master abort" }, 71ef407beeSPaul Mundt { SH4_PCIAINT_RDPE, "read data parity error" }, 72ef407beeSPaul Mundt { SH4_PCIAINT_WDPE, "write data parity error" }, 73ef407beeSPaul Mundt }, pci_interrupt_errors[] = { 74ef407beeSPaul Mundt { SH4_PCIINT_MLCK, "master lock error" }, 75ef407beeSPaul Mundt { SH4_PCIINT_TABT, "target-target abort" }, 76ef407beeSPaul Mundt { SH4_PCIINT_TRET, "target retry time out" }, 77*ecfb68c6SMasanari Iida { SH4_PCIINT_MFDE, "master function disable error" }, 78ef407beeSPaul Mundt { SH4_PCIINT_PRTY, "address parity error" }, 79ef407beeSPaul Mundt { SH4_PCIINT_SERR, "SERR" }, 80ef407beeSPaul Mundt { SH4_PCIINT_TWDP, "data parity error for target write" }, 81ef407beeSPaul Mundt { SH4_PCIINT_TRDP, "PERR detected for target read" }, 82ef407beeSPaul Mundt { SH4_PCIINT_MTABT, "target abort for master" }, 83ef407beeSPaul Mundt { SH4_PCIINT_MMABT, "master abort for master" }, 84ef407beeSPaul Mundt { SH4_PCIINT_MWPD, "master write data parity error" }, 85ef407beeSPaul Mundt { SH4_PCIINT_MRPD, "master read data parity error" }, 86ef407beeSPaul Mundt }; 87ef407beeSPaul Mundt 88ef407beeSPaul Mundt static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id) 89ef407beeSPaul Mundt { 90ef407beeSPaul Mundt struct pci_channel *hose = dev_id; 91ef407beeSPaul Mundt unsigned long addr; 92ef407beeSPaul Mundt unsigned int status; 93ef407beeSPaul Mundt unsigned int cmd; 94ef407beeSPaul Mundt int i; 95ef407beeSPaul Mundt 96ef407beeSPaul Mundt addr = __raw_readl(hose->reg_base + SH4_PCIALR); 97ef407beeSPaul Mundt 98ef407beeSPaul Mundt /* 99ef407beeSPaul Mundt * Handle status errors. 100ef407beeSPaul Mundt */ 101ef407beeSPaul Mundt status = __raw_readw(hose->reg_base + PCI_STATUS); 102ef407beeSPaul Mundt if (status & (PCI_STATUS_PARITY | 103ef407beeSPaul Mundt PCI_STATUS_DETECTED_PARITY | 104ef407beeSPaul Mundt PCI_STATUS_SIG_TARGET_ABORT | 105ef407beeSPaul Mundt PCI_STATUS_REC_TARGET_ABORT | 106ef407beeSPaul Mundt PCI_STATUS_REC_MASTER_ABORT)) { 107ef407beeSPaul Mundt cmd = pcibios_handle_status_errors(addr, status, hose); 108ef407beeSPaul Mundt if (likely(cmd)) 109ef407beeSPaul Mundt __raw_writew(cmd, hose->reg_base + PCI_STATUS); 110ef407beeSPaul Mundt } 111ef407beeSPaul Mundt 112ef407beeSPaul Mundt /* 113ef407beeSPaul Mundt * Handle arbiter errors. 114ef407beeSPaul Mundt */ 115ef407beeSPaul Mundt status = __raw_readl(hose->reg_base + SH4_PCIAINT); 116ef407beeSPaul Mundt for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) { 117ef407beeSPaul Mundt if (status & pci_arbiter_errors[i].mask) { 118ef407beeSPaul Mundt printk(KERN_DEBUG "PCI: %s, addr=%08lx\n", 119ef407beeSPaul Mundt pci_arbiter_errors[i].str, addr); 120ef407beeSPaul Mundt cmd |= pci_arbiter_errors[i].mask; 121ef407beeSPaul Mundt } 122ef407beeSPaul Mundt } 123ef407beeSPaul Mundt __raw_writel(cmd, hose->reg_base + SH4_PCIAINT); 124ef407beeSPaul Mundt 125ef407beeSPaul Mundt /* 126ef407beeSPaul Mundt * Handle the remaining PCI errors. 127ef407beeSPaul Mundt */ 128ef407beeSPaul Mundt status = __raw_readl(hose->reg_base + SH4_PCIINT); 129ef407beeSPaul Mundt for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) { 130ef407beeSPaul Mundt if (status & pci_interrupt_errors[i].mask) { 131ef407beeSPaul Mundt printk(KERN_DEBUG "PCI: %s, addr=%08lx\n", 132ef407beeSPaul Mundt pci_interrupt_errors[i].str, addr); 133ef407beeSPaul Mundt cmd |= pci_interrupt_errors[i].mask; 134ef407beeSPaul Mundt } 135ef407beeSPaul Mundt } 136ef407beeSPaul Mundt __raw_writel(cmd, hose->reg_base + SH4_PCIINT); 137ef407beeSPaul Mundt 138ef407beeSPaul Mundt return IRQ_HANDLED; 139ef407beeSPaul Mundt } 140ef407beeSPaul Mundt 141ef407beeSPaul Mundt static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id) 142ef407beeSPaul Mundt { 143ef407beeSPaul Mundt struct pci_channel *hose = dev_id; 144ef407beeSPaul Mundt 145ef407beeSPaul Mundt printk(KERN_DEBUG "PCI: system error received: "); 146ef407beeSPaul Mundt pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1); 147ef407beeSPaul Mundt printk("\n"); 148ef407beeSPaul Mundt 149ef407beeSPaul Mundt /* Deassert SERR */ 150ef407beeSPaul Mundt __raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM); 151ef407beeSPaul Mundt 152ef407beeSPaul Mundt /* Back off the IRQ for awhile */ 1539ad62ec4SPaul Mundt disable_irq_nosync(irq); 154ef407beeSPaul Mundt hose->serr_timer.expires = jiffies + HZ; 155ef407beeSPaul Mundt add_timer(&hose->serr_timer); 156ef407beeSPaul Mundt 157ef407beeSPaul Mundt return IRQ_HANDLED; 158ef407beeSPaul Mundt } 159ef407beeSPaul Mundt 160ef407beeSPaul Mundt static int __init sh7780_pci_setup_irqs(struct pci_channel *hose) 161ef407beeSPaul Mundt { 162ef407beeSPaul Mundt int ret; 163ef407beeSPaul Mundt 164ef407beeSPaul Mundt /* Clear out PCI arbiter IRQs */ 165ef407beeSPaul Mundt __raw_writel(0, hose->reg_base + SH4_PCIAINT); 166ef407beeSPaul Mundt 167ef407beeSPaul Mundt /* Clear all error conditions */ 168ef407beeSPaul Mundt __raw_writew(PCI_STATUS_DETECTED_PARITY | \ 169ef407beeSPaul Mundt PCI_STATUS_SIG_SYSTEM_ERROR | \ 170ef407beeSPaul Mundt PCI_STATUS_REC_MASTER_ABORT | \ 171ef407beeSPaul Mundt PCI_STATUS_REC_TARGET_ABORT | \ 172ef407beeSPaul Mundt PCI_STATUS_SIG_TARGET_ABORT | \ 173ef407beeSPaul Mundt PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS); 174ef407beeSPaul Mundt 175d11584a0SYong Zhang ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0, 176ef407beeSPaul Mundt "PCI SERR interrupt", hose); 177ef407beeSPaul Mundt if (unlikely(ret)) { 178ef407beeSPaul Mundt printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n"); 179ef407beeSPaul Mundt return ret; 180ef407beeSPaul Mundt } 181ef407beeSPaul Mundt 182ef407beeSPaul Mundt /* 183ef407beeSPaul Mundt * The PCI ERR IRQ needs to be IRQF_SHARED since all of the power 184ef407beeSPaul Mundt * down IRQ vectors are routed through the ERR IRQ vector. We 185ef407beeSPaul Mundt * only request_irq() once as there is only a single masking 186ef407beeSPaul Mundt * source for multiple events. 187ef407beeSPaul Mundt */ 188ef407beeSPaul Mundt ret = request_irq(hose->err_irq, sh7780_pci_err_irq, IRQF_SHARED, 189ef407beeSPaul Mundt "PCI ERR interrupt", hose); 190ef407beeSPaul Mundt if (unlikely(ret)) { 191ef407beeSPaul Mundt free_irq(hose->serr_irq, hose); 192ef407beeSPaul Mundt return ret; 193ef407beeSPaul Mundt } 194ef407beeSPaul Mundt 195ef407beeSPaul Mundt /* Unmask all of the arbiter IRQs. */ 196ef407beeSPaul Mundt __raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \ 197ef407beeSPaul Mundt SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \ 198ef407beeSPaul Mundt SH4_PCIAINT_WDPE, hose->reg_base + SH4_PCIAINTM); 199ef407beeSPaul Mundt 200ef407beeSPaul Mundt /* Unmask all of the PCI IRQs */ 201ef407beeSPaul Mundt __raw_writel(SH4_PCIINTM_TTADIM | SH4_PCIINTM_TMTOIM | \ 202ef407beeSPaul Mundt SH4_PCIINTM_MDEIM | SH4_PCIINTM_APEDIM | \ 203ef407beeSPaul Mundt SH4_PCIINTM_SDIM | SH4_PCIINTM_DPEITWM | \ 204ef407beeSPaul Mundt SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM | \ 205ef407beeSPaul Mundt SH4_PCIINTM_MADIMM | SH4_PCIINTM_MWPDIM | \ 206ef407beeSPaul Mundt SH4_PCIINTM_MRDPEIM, hose->reg_base + SH4_PCIINTM); 207ef407beeSPaul Mundt 208ef407beeSPaul Mundt return ret; 209ef407beeSPaul Mundt } 210ef407beeSPaul Mundt 211ef407beeSPaul Mundt static inline void __init sh7780_pci_teardown_irqs(struct pci_channel *hose) 212ef407beeSPaul Mundt { 213ef407beeSPaul Mundt free_irq(hose->err_irq, hose); 214ef407beeSPaul Mundt free_irq(hose->serr_irq, hose); 215ef407beeSPaul Mundt } 216ef407beeSPaul Mundt 21785b59f5bSPaul Mundt static void __init sh7780_pci66_init(struct pci_channel *hose) 21885b59f5bSPaul Mundt { 21985b59f5bSPaul Mundt unsigned int tmp; 22085b59f5bSPaul Mundt 22185b59f5bSPaul Mundt if (!pci_is_66mhz_capable(hose, 0, 0)) 22285b59f5bSPaul Mundt return; 22385b59f5bSPaul Mundt 22485b59f5bSPaul Mundt /* Enable register access */ 22585b59f5bSPaul Mundt tmp = __raw_readl(hose->reg_base + SH4_PCICR); 22685b59f5bSPaul Mundt tmp |= SH4_PCICR_PREFIX; 22785b59f5bSPaul Mundt __raw_writel(tmp, hose->reg_base + SH4_PCICR); 22885b59f5bSPaul Mundt 22985b59f5bSPaul Mundt /* Enable 66MHz operation */ 23085b59f5bSPaul Mundt tmp = __raw_readw(hose->reg_base + PCI_STATUS); 23185b59f5bSPaul Mundt tmp |= PCI_STATUS_66MHZ; 23285b59f5bSPaul Mundt __raw_writew(tmp, hose->reg_base + PCI_STATUS); 23385b59f5bSPaul Mundt 23485b59f5bSPaul Mundt /* Done */ 23585b59f5bSPaul Mundt tmp = __raw_readl(hose->reg_base + SH4_PCICR); 23685b59f5bSPaul Mundt tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN; 23785b59f5bSPaul Mundt __raw_writel(tmp, hose->reg_base + SH4_PCICR); 23885b59f5bSPaul Mundt } 23985b59f5bSPaul Mundt 240e79066a6SPaul Mundt static int __init sh7780_pci_init(void) 2415283ecb5SPaul Mundt { 242e79066a6SPaul Mundt struct pci_channel *chan = &sh7780_pci_controller; 243a45635dfSPaul Mundt phys_addr_t memphys; 244a45635dfSPaul Mundt size_t memsize; 245959f85f8SPaul Mundt unsigned int id; 246a45635dfSPaul Mundt const char *type; 247b6c58b1dSPaul Mundt int ret, i; 2485283ecb5SPaul Mundt 2493b554c33SMatt Fleming printk(KERN_NOTICE "PCI: Starting initialization.\n"); 2505283ecb5SPaul Mundt 251e4c6a360SMagnus Damm chan->reg_base = 0xfe040000; 252e4c6a360SMagnus Damm 2534e7b7fdbSPaul Mundt /* Enable CPU access to the PCIC registers. */ 2544e7b7fdbSPaul Mundt __raw_writel(PCIECR_ENBL, PCIECR); 255959f85f8SPaul Mundt 256a45635dfSPaul Mundt /* Reset */ 257a45635dfSPaul Mundt __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST, 258a45635dfSPaul Mundt chan->reg_base + SH4_PCICR); 259a45635dfSPaul Mundt 260aee4467bSPaul Mundt /* 261aee4467bSPaul Mundt * Wait for it to come back up. The spec says to allow for up to 262aee4467bSPaul Mundt * 1 second after toggling the reset pin, but in practice 100ms 263aee4467bSPaul Mundt * is more than enough. 264aee4467bSPaul Mundt */ 265a45635dfSPaul Mundt mdelay(100); 266a45635dfSPaul Mundt 267a45635dfSPaul Mundt id = __raw_readw(chan->reg_base + PCI_VENDOR_ID); 268a45635dfSPaul Mundt if (id != PCI_VENDOR_ID_RENESAS) { 2694e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); 270959f85f8SPaul Mundt return -ENODEV; 271959f85f8SPaul Mundt } 272959f85f8SPaul Mundt 273a45635dfSPaul Mundt id = __raw_readw(chan->reg_base + PCI_DEVICE_ID); 274a45635dfSPaul Mundt type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" : 275a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" : 276a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" : 277a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" : 2784e7b7fdbSPaul Mundt NULL; 2794e7b7fdbSPaul Mundt if (unlikely(!type)) { 2804e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Found an unsupported Renesas host " 2814e7b7fdbSPaul Mundt "controller, device id 0x%04x.\n", id); 2824e7b7fdbSPaul Mundt return -EINVAL; 2834e7b7fdbSPaul Mundt } 2844e7b7fdbSPaul Mundt 2854e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Found a Renesas %s host " 2864e7b7fdbSPaul Mundt "controller, revision %d.\n", type, 287a45635dfSPaul Mundt __raw_readb(chan->reg_base + PCI_REVISION_ID)); 2884e7b7fdbSPaul Mundt 289c66c1d79SPaul Mundt /* 290a45635dfSPaul Mundt * Now throw it in to register initialization mode and 291a45635dfSPaul Mundt * start the real work. 292c66c1d79SPaul Mundt */ 293a45635dfSPaul Mundt __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR); 294a45635dfSPaul Mundt 295aee4467bSPaul Mundt memphys = __pa(memory_start); 296aee4467bSPaul Mundt memsize = roundup_pow_of_two(memory_end - memory_start); 297aee4467bSPaul Mundt 298aee4467bSPaul Mundt /* 299aee4467bSPaul Mundt * If there's more than 512MB of memory, we need to roll over to 300aee4467bSPaul Mundt * LAR1/LSR1. 301aee4467bSPaul Mundt */ 302aee4467bSPaul Mundt if (memsize > SZ_512M) { 303aee4467bSPaul Mundt __raw_writel(memphys + SZ_512M, chan->reg_base + SH4_PCILAR1); 304aee4467bSPaul Mundt __raw_writel((((memsize - SZ_512M) - SZ_1M) & 0x1ff00000) | 1, 305aee4467bSPaul Mundt chan->reg_base + SH4_PCILSR1); 306aee4467bSPaul Mundt memsize = SZ_512M; 307aee4467bSPaul Mundt } else { 308aee4467bSPaul Mundt /* 309aee4467bSPaul Mundt * Otherwise just zero it out and disable it. 310aee4467bSPaul Mundt */ 311aee4467bSPaul Mundt __raw_writel(0, chan->reg_base + SH4_PCILAR1); 312aee4467bSPaul Mundt __raw_writel(0, chan->reg_base + SH4_PCILSR1); 313aee4467bSPaul Mundt } 314aee4467bSPaul Mundt 315aee4467bSPaul Mundt /* 316aee4467bSPaul Mundt * LAR0/LSR0 covers up to the first 512MB, which is enough to 317aee4467bSPaul Mundt * cover all of lowmem on most platforms. 318aee4467bSPaul Mundt */ 319a45635dfSPaul Mundt __raw_writel(memphys, chan->reg_base + SH4_PCILAR0); 320aee4467bSPaul Mundt __raw_writel(((memsize - SZ_1M) & 0x1ff00000) | 1, 321a45635dfSPaul Mundt chan->reg_base + SH4_PCILSR0); 32262c7ae87SPaul Mundt 323ef407beeSPaul Mundt /* 324ef407beeSPaul Mundt * Hook up the ERR and SERR IRQs. 325ef407beeSPaul Mundt */ 326ef407beeSPaul Mundt ret = sh7780_pci_setup_irqs(chan); 327ef407beeSPaul Mundt if (unlikely(ret)) 328ef407beeSPaul Mundt return ret; 32962c7ae87SPaul Mundt 330a45635dfSPaul Mundt /* 331a45635dfSPaul Mundt * Disable the cache snoop controller for non-coherent DMA. 332a45635dfSPaul Mundt */ 333a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSCR0); 334a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSAR0); 335a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSCR1); 336a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSAR1); 33762c7ae87SPaul Mundt 338b6c58b1dSPaul Mundt /* 339b6c58b1dSPaul Mundt * Setup the memory BARs 340b6c58b1dSPaul Mundt */ 3413b0be1a4SPaul Mundt for (i = 1; i < chan->nr_resources; i++) { 3423b0be1a4SPaul Mundt struct resource *res = chan->resources + i; 343b6c58b1dSPaul Mundt resource_size_t size; 344a45635dfSPaul Mundt 345b6c58b1dSPaul Mundt if (unlikely(res->flags & IORESOURCE_IO)) 346b6c58b1dSPaul Mundt continue; 347b6c58b1dSPaul Mundt 348b6c58b1dSPaul Mundt /* 349b6c58b1dSPaul Mundt * Make sure we're in the right physical addressing mode 350b6c58b1dSPaul Mundt * for dealing with the resource. 351b6c58b1dSPaul Mundt */ 352b6c58b1dSPaul Mundt if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) { 353b6c58b1dSPaul Mundt chan->nr_resources--; 354b6c58b1dSPaul Mundt continue; 355b6c58b1dSPaul Mundt } 356b6c58b1dSPaul Mundt 357b6c58b1dSPaul Mundt size = resource_size(res); 358b6c58b1dSPaul Mundt 359b6c58b1dSPaul Mundt /* 360b6c58b1dSPaul Mundt * The MBMR mask is calculated in units of 256kB, which 361b6c58b1dSPaul Mundt * keeps things pretty simple. 362b6c58b1dSPaul Mundt */ 363b6c58b1dSPaul Mundt __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18, 3643b0be1a4SPaul Mundt chan->reg_base + SH7780_PCIMBMR(i - 1)); 3653b0be1a4SPaul Mundt __raw_writel(res->start, chan->reg_base + SH7780_PCIMBR(i - 1)); 366b6c58b1dSPaul Mundt } 367b6c58b1dSPaul Mundt 368b6c58b1dSPaul Mundt /* 369b6c58b1dSPaul Mundt * And I/O. 370b6c58b1dSPaul Mundt */ 371b6c58b1dSPaul Mundt __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0); 372a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCIIOBR); 373a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCIIOBMR); 374a45635dfSPaul Mundt 375ef407beeSPaul Mundt __raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \ 376ef407beeSPaul Mundt PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \ 377ef407beeSPaul Mundt PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND); 378ef407beeSPaul Mundt 379a45635dfSPaul Mundt /* 380a45635dfSPaul Mundt * Initialization mode complete, release the control register and 381a45635dfSPaul Mundt * enable round robin mode to stop device overruns/starvation. 382a45635dfSPaul Mundt */ 383a45635dfSPaul Mundt __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO, 384a45635dfSPaul Mundt chan->reg_base + SH4_PCICR); 3855283ecb5SPaul Mundt 386bcf39352SPaul Mundt ret = register_pci_controller(chan); 387bcf39352SPaul Mundt if (unlikely(ret)) 388ef407beeSPaul Mundt goto err; 389e79066a6SPaul Mundt 39085b59f5bSPaul Mundt sh7780_pci66_init(chan); 39185b59f5bSPaul Mundt 39285b59f5bSPaul Mundt printk(KERN_NOTICE "PCI: Running at %dMHz.\n", 39385b59f5bSPaul Mundt (__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ? 39485b59f5bSPaul Mundt 66 : 33); 39585b59f5bSPaul Mundt 396d0e3db40SMagnus Damm return 0; 397ef407beeSPaul Mundt 398ef407beeSPaul Mundt err: 399ef407beeSPaul Mundt sh7780_pci_teardown_irqs(chan); 400ef407beeSPaul Mundt return ret; 4015283ecb5SPaul Mundt } 402e79066a6SPaul Mundt arch_initcall(sh7780_pci_init); 403