15283ecb5SPaul Mundt /* 25283ecb5SPaul Mundt * Low-Level PCI Support for the SH7780 35283ecb5SPaul Mundt * 4*a45635dfSPaul 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> 145283ecb5SPaul Mundt #include <linux/errno.h> 155283ecb5SPaul Mundt #include <linux/delay.h> 16959f85f8SPaul Mundt #include "pci-sh4.h" 17*a45635dfSPaul Mundt #include <asm/mmu.h> 18*a45635dfSPaul Mundt #include <asm/sizes.h> 195283ecb5SPaul Mundt 20e79066a6SPaul Mundt static struct resource sh7785_io_resource = { 21e79066a6SPaul Mundt .name = "SH7785_IO", 22*a45635dfSPaul Mundt .start = 0x1000, 23*a45635dfSPaul Mundt .end = SH7780_PCI_IO_SIZE - 1, 24e79066a6SPaul Mundt .flags = IORESOURCE_IO 25e79066a6SPaul Mundt }; 26e79066a6SPaul Mundt 27e79066a6SPaul Mundt static struct resource sh7785_mem_resource = { 28e79066a6SPaul Mundt .name = "SH7785_mem", 29e79066a6SPaul Mundt .start = SH7780_PCI_MEMORY_BASE, 30e79066a6SPaul Mundt .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, 31e79066a6SPaul Mundt .flags = IORESOURCE_MEM 32e79066a6SPaul Mundt }; 33e79066a6SPaul Mundt 34e79066a6SPaul Mundt static struct pci_channel sh7780_pci_controller = { 35e79066a6SPaul Mundt .pci_ops = &sh4_pci_ops, 36e79066a6SPaul Mundt .mem_resource = &sh7785_mem_resource, 3709cfeb13SPaul Mundt .mem_offset = 0x00000000, 38e79066a6SPaul Mundt .io_resource = &sh7785_io_resource, 3909cfeb13SPaul Mundt .io_offset = 0x00000000, 405582b064SPaul Mundt .io_map_base = SH7780_PCI_IO_BASE, 41e79066a6SPaul Mundt }; 42e79066a6SPaul Mundt 43e79066a6SPaul Mundt static int __init sh7780_pci_init(void) 445283ecb5SPaul Mundt { 45e79066a6SPaul Mundt struct pci_channel *chan = &sh7780_pci_controller; 46*a45635dfSPaul Mundt phys_addr_t memphys; 47*a45635dfSPaul Mundt size_t memsize; 48959f85f8SPaul Mundt unsigned int id; 49*a45635dfSPaul Mundt const char *type; 504e7b7fdbSPaul Mundt int ret; 515283ecb5SPaul Mundt 524e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Starting intialization.\n"); 535283ecb5SPaul Mundt 54e4c6a360SMagnus Damm chan->reg_base = 0xfe040000; 55e4c6a360SMagnus Damm 564e7b7fdbSPaul Mundt /* Enable CPU access to the PCIC registers. */ 574e7b7fdbSPaul Mundt __raw_writel(PCIECR_ENBL, PCIECR); 58959f85f8SPaul Mundt 59*a45635dfSPaul Mundt /* Reset */ 60*a45635dfSPaul Mundt __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST, 61*a45635dfSPaul Mundt chan->reg_base + SH4_PCICR); 62*a45635dfSPaul Mundt 63*a45635dfSPaul Mundt /* Wait for it to come back up.. */ 64*a45635dfSPaul Mundt mdelay(100); 65*a45635dfSPaul Mundt 66*a45635dfSPaul Mundt id = __raw_readw(chan->reg_base + PCI_VENDOR_ID); 67*a45635dfSPaul Mundt if (id != PCI_VENDOR_ID_RENESAS) { 684e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); 69959f85f8SPaul Mundt return -ENODEV; 70959f85f8SPaul Mundt } 71959f85f8SPaul Mundt 72*a45635dfSPaul Mundt id = __raw_readw(chan->reg_base + PCI_DEVICE_ID); 73*a45635dfSPaul Mundt type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" : 74*a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" : 75*a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" : 76*a45635dfSPaul Mundt (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" : 774e7b7fdbSPaul Mundt NULL; 784e7b7fdbSPaul Mundt if (unlikely(!type)) { 794e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Found an unsupported Renesas host " 804e7b7fdbSPaul Mundt "controller, device id 0x%04x.\n", id); 814e7b7fdbSPaul Mundt return -EINVAL; 824e7b7fdbSPaul Mundt } 834e7b7fdbSPaul Mundt 844e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Found a Renesas %s host " 854e7b7fdbSPaul Mundt "controller, revision %d.\n", type, 86*a45635dfSPaul Mundt __raw_readb(chan->reg_base + PCI_REVISION_ID)); 874e7b7fdbSPaul Mundt 88d0e3db40SMagnus Damm if ((ret = sh4_pci_check_direct(chan)) != 0) 895283ecb5SPaul Mundt return ret; 905283ecb5SPaul Mundt 91c66c1d79SPaul Mundt /* 92*a45635dfSPaul Mundt * Now throw it in to register initialization mode and 93*a45635dfSPaul Mundt * start the real work. 94c66c1d79SPaul Mundt */ 95*a45635dfSPaul Mundt __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR); 96*a45635dfSPaul Mundt 97*a45635dfSPaul Mundt memphys = __pa(memory_start); 98*a45635dfSPaul Mundt memsize = memory_end - memory_start; 990bbc9bc3SPaul Mundt 10062c7ae87SPaul Mundt /* 10162c7ae87SPaul Mundt * Set IO and Mem windows to local address 1025283ecb5SPaul Mundt * Make PCI and local address the same for easy 1 to 1 mapping 1035283ecb5SPaul Mundt */ 104*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0); 1055283ecb5SPaul Mundt 106*a45635dfSPaul Mundt __raw_writel(memphys, chan->reg_base + SH4_PCILAR0); 107*a45635dfSPaul Mundt __raw_writel((memsize - 1) << 9 | 1, 108*a45635dfSPaul Mundt chan->reg_base + SH4_PCILSR0); 10962c7ae87SPaul Mundt 110*a45635dfSPaul Mundt /* Clear out PCI arbiter IRQs */ 111*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH4_PCIAINT); 11262c7ae87SPaul Mundt 113*a45635dfSPaul Mundt /* Unmask all of the arbiter IRQs. */ 114*a45635dfSPaul Mundt __raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \ 115*a45635dfSPaul Mundt SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \ 116*a45635dfSPaul Mundt SH4_PCIAINT_WDPE, chan->reg_base + SH4_PCIAINTM); 11762c7ae87SPaul Mundt 118*a45635dfSPaul Mundt /* Clear all error conditions */ 119*a45635dfSPaul Mundt __raw_writew(PCI_STATUS_DETECTED_PARITY | \ 120*a45635dfSPaul Mundt PCI_STATUS_SIG_SYSTEM_ERROR | \ 121*a45635dfSPaul Mundt PCI_STATUS_REC_MASTER_ABORT | \ 122*a45635dfSPaul Mundt PCI_STATUS_REC_TARGET_ABORT | \ 123*a45635dfSPaul Mundt PCI_STATUS_SIG_TARGET_ABORT | \ 124*a45635dfSPaul Mundt PCI_STATUS_PARITY, chan->reg_base + PCI_STATUS); 1255283ecb5SPaul Mundt 126*a45635dfSPaul Mundt __raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \ 127*a45635dfSPaul Mundt PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \ 128*a45635dfSPaul Mundt PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND); 12962c7ae87SPaul Mundt 130*a45635dfSPaul Mundt /* Unmask all of the PCI IRQs */ 131*a45635dfSPaul Mundt __raw_writel(SH4_PCIINTM_TTADIM | SH4_PCIINTM_TMTOIM | \ 132*a45635dfSPaul Mundt SH4_PCIINTM_MDEIM | SH4_PCIINTM_APEDIM | \ 133*a45635dfSPaul Mundt SH4_PCIINTM_SDIM | SH4_PCIINTM_DPEITWM | \ 134*a45635dfSPaul Mundt SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM | \ 135*a45635dfSPaul Mundt SH4_PCIINTM_MADIMM | SH4_PCIINTM_MWPDIM | \ 136*a45635dfSPaul Mundt SH4_PCIINTM_MRDPEIM, chan->reg_base + SH4_PCIINTM); 13762c7ae87SPaul Mundt 138*a45635dfSPaul Mundt /* 139*a45635dfSPaul Mundt * Disable the cache snoop controller for non-coherent DMA. 140*a45635dfSPaul Mundt */ 141*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSCR0); 142*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSAR0); 143*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSCR1); 144*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCICSAR1); 14562c7ae87SPaul Mundt 146*a45635dfSPaul Mundt __raw_writel(0xfd000000, chan->reg_base + SH7780_PCIMBR0); 147*a45635dfSPaul Mundt __raw_writel(0x00fc0000, chan->reg_base + SH7780_PCIMBMR0); 148*a45635dfSPaul Mundt 149*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCIIOBR); 150*a45635dfSPaul Mundt __raw_writel(0, chan->reg_base + SH7780_PCIIOBMR); 151*a45635dfSPaul Mundt 152*a45635dfSPaul Mundt /* 153*a45635dfSPaul Mundt * Initialization mode complete, release the control register and 154*a45635dfSPaul Mundt * enable round robin mode to stop device overruns/starvation. 155*a45635dfSPaul Mundt */ 156*a45635dfSPaul Mundt __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO, 157*a45635dfSPaul Mundt chan->reg_base + SH4_PCICR); 1585283ecb5SPaul Mundt 159e79066a6SPaul Mundt register_pci_controller(chan); 160e79066a6SPaul Mundt 161d0e3db40SMagnus Damm return 0; 1625283ecb5SPaul Mundt } 163e79066a6SPaul Mundt arch_initcall(sh7780_pci_init); 164