15283ecb5SPaul Mundt /* 25283ecb5SPaul Mundt * Low-Level PCI Support for the SH7780 35283ecb5SPaul Mundt * 462c7ae87SPaul Mundt * Copyright (C) 2005 - 2009 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" 175283ecb5SPaul Mundt 18e79066a6SPaul Mundt static struct resource sh7785_io_resource = { 19e79066a6SPaul Mundt .name = "SH7785_IO", 20e79066a6SPaul Mundt .start = SH7780_PCI_IO_BASE, 21e79066a6SPaul Mundt .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1, 22e79066a6SPaul Mundt .flags = IORESOURCE_IO 23e79066a6SPaul Mundt }; 24e79066a6SPaul Mundt 25e79066a6SPaul Mundt static struct resource sh7785_mem_resource = { 26e79066a6SPaul Mundt .name = "SH7785_mem", 27e79066a6SPaul Mundt .start = SH7780_PCI_MEMORY_BASE, 28e79066a6SPaul Mundt .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, 29e79066a6SPaul Mundt .flags = IORESOURCE_MEM 30e79066a6SPaul Mundt }; 31e79066a6SPaul Mundt 32e79066a6SPaul Mundt static struct pci_channel sh7780_pci_controller = { 33e79066a6SPaul Mundt .pci_ops = &sh4_pci_ops, 34e79066a6SPaul Mundt .mem_resource = &sh7785_mem_resource, 3509cfeb13SPaul Mundt .mem_offset = 0x00000000, 36e79066a6SPaul Mundt .io_resource = &sh7785_io_resource, 3709cfeb13SPaul Mundt .io_offset = 0x00000000, 38*5582b064SPaul Mundt .io_map_base = SH7780_PCI_IO_BASE, 39e79066a6SPaul Mundt }; 40e79066a6SPaul Mundt 41e79066a6SPaul Mundt static struct sh4_pci_address_map sh7780_pci_map = { 42e79066a6SPaul Mundt .window0 = { 43e79066a6SPaul Mundt #if defined(CONFIG_32BIT) 44e79066a6SPaul Mundt .base = SH7780_32BIT_DDR_BASE_ADDR, 45e79066a6SPaul Mundt .size = 0x40000000, 46e79066a6SPaul Mundt #else 47e79066a6SPaul Mundt .base = SH7780_CS0_BASE_ADDR, 48e79066a6SPaul Mundt .size = 0x20000000, 49e79066a6SPaul Mundt #endif 50e79066a6SPaul Mundt }, 51e79066a6SPaul Mundt }; 52e79066a6SPaul Mundt 53e79066a6SPaul Mundt static int __init sh7780_pci_init(void) 545283ecb5SPaul Mundt { 55e79066a6SPaul Mundt struct pci_channel *chan = &sh7780_pci_controller; 56959f85f8SPaul Mundt unsigned int id; 574e7b7fdbSPaul Mundt const char *type = NULL; 584e7b7fdbSPaul Mundt int ret; 59e79066a6SPaul Mundt u32 word; 605283ecb5SPaul Mundt 614e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Starting intialization.\n"); 625283ecb5SPaul Mundt 63e4c6a360SMagnus Damm chan->reg_base = 0xfe040000; 64e4c6a360SMagnus Damm 654e7b7fdbSPaul Mundt /* Enable CPU access to the PCIC registers. */ 664e7b7fdbSPaul Mundt __raw_writel(PCIECR_ENBL, PCIECR); 67959f85f8SPaul Mundt 684e7b7fdbSPaul Mundt id = __raw_readw(chan->reg_base + SH7780_PCIVID); 694e7b7fdbSPaul Mundt if (id != SH7780_VENDOR_ID) { 704e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); 71959f85f8SPaul Mundt return -ENODEV; 72959f85f8SPaul Mundt } 73959f85f8SPaul Mundt 744e7b7fdbSPaul Mundt id = __raw_readw(chan->reg_base + SH7780_PCIDID); 754e7b7fdbSPaul Mundt type = (id == SH7763_DEVICE_ID) ? "SH7763" : 764e7b7fdbSPaul Mundt (id == SH7780_DEVICE_ID) ? "SH7780" : 774e7b7fdbSPaul Mundt (id == SH7781_DEVICE_ID) ? "SH7781" : 784e7b7fdbSPaul Mundt (id == SH7785_DEVICE_ID) ? "SH7785" : 794e7b7fdbSPaul Mundt NULL; 804e7b7fdbSPaul Mundt if (unlikely(!type)) { 814e7b7fdbSPaul Mundt printk(KERN_ERR "PCI: Found an unsupported Renesas host " 824e7b7fdbSPaul Mundt "controller, device id 0x%04x.\n", id); 834e7b7fdbSPaul Mundt return -EINVAL; 844e7b7fdbSPaul Mundt } 854e7b7fdbSPaul Mundt 864e7b7fdbSPaul Mundt printk(KERN_NOTICE "PCI: Found a Renesas %s host " 874e7b7fdbSPaul Mundt "controller, revision %d.\n", type, 884e7b7fdbSPaul Mundt __raw_readb(chan->reg_base + SH7780_PCIRID)); 894e7b7fdbSPaul Mundt 90d0e3db40SMagnus Damm if ((ret = sh4_pci_check_direct(chan)) != 0) 915283ecb5SPaul Mundt return ret; 925283ecb5SPaul Mundt 93c66c1d79SPaul Mundt /* 94c66c1d79SPaul Mundt * Set the class and sub-class codes. 95c66c1d79SPaul Mundt */ 96ab78cbcfSPaul Mundt __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8, 97ab78cbcfSPaul Mundt chan->reg_base + SH7780_PCIBCC); 98ab78cbcfSPaul Mundt __raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff, 99ab78cbcfSPaul Mundt chan->reg_base + SH7780_PCISUB); 1000bbc9bc3SPaul Mundt 10162c7ae87SPaul Mundt /* 10262c7ae87SPaul Mundt * Set IO and Mem windows to local address 1035283ecb5SPaul Mundt * Make PCI and local address the same for easy 1 to 1 mapping 1045283ecb5SPaul Mundt */ 1054c7a47deSPaul Mundt pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0); 1065283ecb5SPaul Mundt /* Set the values on window 0 PCI config registers */ 1074c7a47deSPaul Mundt pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0); 1084c7a47deSPaul Mundt pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0); 1095283ecb5SPaul Mundt 11062c7ae87SPaul Mundt pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM); 11162c7ae87SPaul Mundt 11262c7ae87SPaul Mundt /* Set up standard PCI config registers */ 11362c7ae87SPaul Mundt __raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS); 11462c7ae87SPaul Mundt __raw_writew(0x0047, chan->reg_base + SH7780_PCICMD); 11562c7ae87SPaul Mundt __raw_writew(0x1912, chan->reg_base + SH7780_PCISVID); 11662c7ae87SPaul Mundt __raw_writew(0x0001, chan->reg_base + SH7780_PCISID); 11762c7ae87SPaul Mundt 11862c7ae87SPaul Mundt __raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF); 11962c7ae87SPaul Mundt 120b7576230SNobuhiro Iwamatsu /* Apply any last-minute PCIC fixups */ 121b8b47bfbSMagnus Damm pci_fixup_pcic(chan); 1225283ecb5SPaul Mundt 12362c7ae87SPaul Mundt pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0); 12462c7ae87SPaul Mundt pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0); 12562c7ae87SPaul Mundt 12662c7ae87SPaul Mundt #ifdef CONFIG_32BIT 12762c7ae87SPaul Mundt pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2); 12862c7ae87SPaul Mundt pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2); 12962c7ae87SPaul Mundt #endif 13062c7ae87SPaul Mundt 13162c7ae87SPaul Mundt /* Set IOBR for windows containing area specified in pci.h */ 13262c7ae87SPaul Mundt pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1), 13362c7ae87SPaul Mundt SH7780_PCIIOBR); 13462c7ae87SPaul Mundt pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)), 13562c7ae87SPaul Mundt SH7780_PCIIOBMR); 13662c7ae87SPaul Mundt 1375283ecb5SPaul Mundt /* SH7780 init done, set central function init complete */ 1385283ecb5SPaul Mundt /* use round robin mode to stop a device starving/overruning */ 139959f85f8SPaul Mundt word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO; 140b8b47bfbSMagnus Damm pci_write_reg(chan, word, SH4_PCICR); 1415283ecb5SPaul Mundt 142e79066a6SPaul Mundt register_pci_controller(chan); 143e79066a6SPaul Mundt 144d0e3db40SMagnus Damm return 0; 1455283ecb5SPaul Mundt } 146e79066a6SPaul Mundt arch_initcall(sh7780_pci_init); 147