15283ecb5SPaul Mundt /* 25283ecb5SPaul Mundt * Low-Level PCI Support for the SH7780 35283ecb5SPaul Mundt * 4*62c7ae87SPaul Mundt * Copyright (C) 2005 - 2009 Paul Mundt 55283ecb5SPaul Mundt * 6*62c7ae87SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 7*62c7ae87SPaul Mundt * License. See the file "COPYING" in the main directory of this archive 8*62c7ae87SPaul 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" 175283ecb5SPaul Mundt 18ab1363a8SPaul Mundt static int __init sh7780_pci_init(struct pci_channel *chan) 195283ecb5SPaul Mundt { 20959f85f8SPaul Mundt unsigned int id; 214e7b7fdbSPaul Mundt const char *type = NULL; 224e7b7fdbSPaul Mundt int ret; 235283ecb5SPaul Mundt 244e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Starting intialization.\n"); 255283ecb5SPaul Mundt 26e4c6a360SMagnus Damm chan->reg_base = 0xfe040000; 27ef53fdebSMagnus Damm chan->io_base = 0xfe200000; 28e4c6a360SMagnus Damm 294e7b7fdbSPaul Mundt /* Enable CPU access to the PCIC registers. */ 304e7b7fdbSPaul Mundt __raw_writel(PCIECR_ENBL, PCIECR); 31959f85f8SPaul Mundt 324e7b7fdbSPaul Mundt id = __raw_readw(chan->reg_base + SH7780_PCIVID); 334e7b7fdbSPaul Mundt if (id != SH7780_VENDOR_ID) { 344e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); 35959f85f8SPaul Mundt return -ENODEV; 36959f85f8SPaul Mundt } 37959f85f8SPaul Mundt 384e7b7fdbSPaul Mundt id = __raw_readw(chan->reg_base + SH7780_PCIDID); 394e7b7fdbSPaul Mundt type = (id == SH7763_DEVICE_ID) ? "SH7763" : 404e7b7fdbSPaul Mundt (id == SH7780_DEVICE_ID) ? "SH7780" : 414e7b7fdbSPaul Mundt (id == SH7781_DEVICE_ID) ? "SH7781" : 424e7b7fdbSPaul Mundt (id == SH7785_DEVICE_ID) ? "SH7785" : 434e7b7fdbSPaul Mundt NULL; 444e7b7fdbSPaul Mundt if (unlikely(!type)) { 454e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Found an unsupported Renesas host " 464e7b7fdbSPaul Mundt "controller, device id 0x%04x.\n", id); 474e7b7fdbSPaul Mundt return -EINVAL; 484e7b7fdbSPaul Mundt } 494e7b7fdbSPaul Mundt 504e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Found a Renesas %s host " 514e7b7fdbSPaul Mundt "controller, revision %d.\n", type, 524e7b7fdbSPaul Mundt __raw_readb(chan->reg_base + SH7780_PCIRID)); 534e7b7fdbSPaul Mundt 54d0e3db40SMagnus Damm if ((ret = sh4_pci_check_direct(chan)) != 0) 555283ecb5SPaul Mundt return ret; 565283ecb5SPaul Mundt 57c66c1d79SPaul Mundt /* 58c66c1d79SPaul Mundt * Platform specific initialization (BSC registers, and memory space 59c66c1d79SPaul Mundt * mapping) will be called via the platform defined function 60c66c1d79SPaul Mundt * pcibios_init_platform(). 61c66c1d79SPaul Mundt */ 625283ecb5SPaul Mundt return pcibios_init_platform(); 635283ecb5SPaul Mundt } 645283ecb5SPaul Mundt 65c66c1d79SPaul Mundt extern u8 pci_cache_line_size; 66c66c1d79SPaul Mundt 67ab1363a8SPaul Mundt static struct resource sh7785_io_resource = { 68ab1363a8SPaul Mundt .name = "SH7785_IO", 69ab1363a8SPaul Mundt .start = SH7780_PCI_IO_BASE, 70ab1363a8SPaul Mundt .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1, 71ab1363a8SPaul Mundt .flags = IORESOURCE_IO 72ab1363a8SPaul Mundt }; 73ab1363a8SPaul Mundt 74ab1363a8SPaul Mundt static struct resource sh7785_mem_resource = { 75ab1363a8SPaul Mundt .name = "SH7785_mem", 76ab1363a8SPaul Mundt .start = SH7780_PCI_MEMORY_BASE, 77ab1363a8SPaul Mundt .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, 78ab1363a8SPaul Mundt .flags = IORESOURCE_MEM 79ab1363a8SPaul Mundt }; 80ab1363a8SPaul Mundt 81ab1363a8SPaul Mundt struct pci_channel board_pci_channels[] = { 82ab1363a8SPaul Mundt { sh7780_pci_init, &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff }, 83ab1363a8SPaul Mundt { NULL, NULL, NULL, 0, 0 }, 84ab1363a8SPaul Mundt }; 85ab1363a8SPaul Mundt 864c7a47deSPaul Mundt static struct sh4_pci_address_map sh7780_pci_map = { 874c7a47deSPaul Mundt .window0 = { 884c7a47deSPaul Mundt #if defined(CONFIG_32BIT) 894c7a47deSPaul Mundt .base = SH7780_32BIT_DDR_BASE_ADDR, 904c7a47deSPaul Mundt .size = 0x40000000, 914c7a47deSPaul Mundt #else 924c7a47deSPaul Mundt .base = SH7780_CS0_BASE_ADDR, 934c7a47deSPaul Mundt .size = 0x20000000, 944c7a47deSPaul Mundt #endif 954c7a47deSPaul Mundt }, 964c7a47deSPaul Mundt }; 974c7a47deSPaul Mundt 984c7a47deSPaul Mundt int __init pcibios_init_platform(void) 995283ecb5SPaul Mundt { 100ab1363a8SPaul Mundt struct pci_channel *chan = &board_pci_channels[0]; 1015283ecb5SPaul Mundt u32 word; 1025283ecb5SPaul Mundt 103c66c1d79SPaul Mundt /* 104c66c1d79SPaul Mundt * Set the class and sub-class codes. 105c66c1d79SPaul Mundt */ 106ab78cbcfSPaul Mundt __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8, 107ab78cbcfSPaul Mundt chan->reg_base + SH7780_PCIBCC); 108ab78cbcfSPaul Mundt __raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff, 109ab78cbcfSPaul Mundt chan->reg_base + SH7780_PCISUB); 1100bbc9bc3SPaul Mundt 111c66c1d79SPaul Mundt pci_cache_line_size = pci_read_reg(chan, SH7780_PCICLS) / 4; 112c66c1d79SPaul Mundt 113*62c7ae87SPaul Mundt /* 114*62c7ae87SPaul Mundt * Set IO and Mem windows to local address 1155283ecb5SPaul Mundt * Make PCI and local address the same for easy 1 to 1 mapping 1165283ecb5SPaul Mundt */ 1174c7a47deSPaul Mundt pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0); 1185283ecb5SPaul Mundt /* Set the values on window 0 PCI config registers */ 1194c7a47deSPaul Mundt pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0); 1204c7a47deSPaul Mundt pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0); 1215283ecb5SPaul Mundt 122*62c7ae87SPaul Mundt pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM); 123*62c7ae87SPaul Mundt 124*62c7ae87SPaul Mundt /* Set up standard PCI config registers */ 125*62c7ae87SPaul Mundt __raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS); 126*62c7ae87SPaul Mundt __raw_writew(0x0047, chan->reg_base + SH7780_PCICMD); 127*62c7ae87SPaul Mundt __raw_writew(0x1912, chan->reg_base + SH7780_PCISVID); 128*62c7ae87SPaul Mundt __raw_writew(0x0001, chan->reg_base + SH7780_PCISID); 129*62c7ae87SPaul Mundt 130*62c7ae87SPaul Mundt __raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF); 131*62c7ae87SPaul Mundt 132b7576230SNobuhiro Iwamatsu /* Apply any last-minute PCIC fixups */ 133b8b47bfbSMagnus Damm pci_fixup_pcic(chan); 1345283ecb5SPaul Mundt 135*62c7ae87SPaul Mundt pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0); 136*62c7ae87SPaul Mundt pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0); 137*62c7ae87SPaul Mundt 138*62c7ae87SPaul Mundt #ifdef CONFIG_32BIT 139*62c7ae87SPaul Mundt pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2); 140*62c7ae87SPaul Mundt pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2); 141*62c7ae87SPaul Mundt #endif 142*62c7ae87SPaul Mundt 143*62c7ae87SPaul Mundt /* Set IOBR for windows containing area specified in pci.h */ 144*62c7ae87SPaul Mundt pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1), 145*62c7ae87SPaul Mundt SH7780_PCIIOBR); 146*62c7ae87SPaul Mundt pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)), 147*62c7ae87SPaul Mundt SH7780_PCIIOBMR); 148*62c7ae87SPaul Mundt 1495283ecb5SPaul Mundt /* SH7780 init done, set central function init complete */ 1505283ecb5SPaul Mundt /* use round robin mode to stop a device starving/overruning */ 151959f85f8SPaul Mundt word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO; 152b8b47bfbSMagnus Damm pci_write_reg(chan, word, SH4_PCICR); 1535283ecb5SPaul Mundt 154f1dcab75SPaul Mundt __set_io_port_base(SH7780_PCI_IO_BASE); 155f1dcab75SPaul Mundt 156d0e3db40SMagnus Damm return 0; 1575283ecb5SPaul Mundt } 158