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