1*5283ecb5SPaul Mundt /* 2*5283ecb5SPaul Mundt * Low-Level PCI Support for the SH7780 3*5283ecb5SPaul Mundt * 4*5283ecb5SPaul Mundt * Dustin McIntire (dustin@sensoria.com) 5*5283ecb5SPaul Mundt * Derived from arch/i386/kernel/pci-*.c which bore the message: 6*5283ecb5SPaul Mundt * (c) 1999--2000 Martin Mares <mj@ucw.cz> 7*5283ecb5SPaul Mundt * 8*5283ecb5SPaul Mundt * Ported to the new API by Paul Mundt <lethal@linux-sh.org> 9*5283ecb5SPaul Mundt * With cleanup by Paul van Gool <pvangool@mimotech.com> 10*5283ecb5SPaul Mundt * 11*5283ecb5SPaul Mundt * May be copied or modified under the terms of the GNU General Public 12*5283ecb5SPaul Mundt * License. See linux/COPYING for more information. 13*5283ecb5SPaul Mundt * 14*5283ecb5SPaul Mundt */ 15*5283ecb5SPaul Mundt 16*5283ecb5SPaul Mundt #undef DEBUG 17*5283ecb5SPaul Mundt 18*5283ecb5SPaul Mundt #include <linux/config.h> 19*5283ecb5SPaul Mundt #include <linux/types.h> 20*5283ecb5SPaul Mundt #include <linux/kernel.h> 21*5283ecb5SPaul Mundt #include <linux/init.h> 22*5283ecb5SPaul Mundt #include <linux/pci.h> 23*5283ecb5SPaul Mundt #include <linux/sched.h> 24*5283ecb5SPaul Mundt #include <linux/ioport.h> 25*5283ecb5SPaul Mundt #include <linux/errno.h> 26*5283ecb5SPaul Mundt #include <linux/irq.h> 27*5283ecb5SPaul Mundt #include <linux/delay.h> 28*5283ecb5SPaul Mundt 29*5283ecb5SPaul Mundt #include <asm/machvec.h> 30*5283ecb5SPaul Mundt #include <asm/io.h> 31*5283ecb5SPaul Mundt #include "pci-sh7780.h" 32*5283ecb5SPaul Mundt 33*5283ecb5SPaul Mundt static unsigned int pci_probe = PCI_PROBE_CONF1; 34*5283ecb5SPaul Mundt extern int pci_fixup_pcic(void); 35*5283ecb5SPaul Mundt 36*5283ecb5SPaul Mundt /* 37*5283ecb5SPaul Mundt * Direct access to PCI hardware... 38*5283ecb5SPaul Mundt */ 39*5283ecb5SPaul Mundt 40*5283ecb5SPaul Mundt #define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) 41*5283ecb5SPaul Mundt 42*5283ecb5SPaul Mundt /* 43*5283ecb5SPaul Mundt * Functions for accessing PCI configuration space with type 1 accesses 44*5283ecb5SPaul Mundt */ 45*5283ecb5SPaul Mundt static int sh7780_pci_read(struct pci_bus *bus, unsigned int devfn, 46*5283ecb5SPaul Mundt int where, int size, u32 *val) 47*5283ecb5SPaul Mundt { 48*5283ecb5SPaul Mundt unsigned long flags; 49*5283ecb5SPaul Mundt u32 data; 50*5283ecb5SPaul Mundt 51*5283ecb5SPaul Mundt /* 52*5283ecb5SPaul Mundt * PCIPDR may only be accessed as 32 bit words, 53*5283ecb5SPaul Mundt * so we must do byte alignment by hand 54*5283ecb5SPaul Mundt */ 55*5283ecb5SPaul Mundt local_irq_save(flags); 56*5283ecb5SPaul Mundt outl(CONFIG_CMD(bus, devfn, where), PCI_REG(SH7780_PCIPAR)); 57*5283ecb5SPaul Mundt data = inl(PCI_REG(SH7780_PCIPDR)); 58*5283ecb5SPaul Mundt local_irq_restore(flags); 59*5283ecb5SPaul Mundt 60*5283ecb5SPaul Mundt switch (size) { 61*5283ecb5SPaul Mundt case 1: 62*5283ecb5SPaul Mundt *val = (data >> ((where & 3) << 3)) & 0xff; 63*5283ecb5SPaul Mundt break; 64*5283ecb5SPaul Mundt case 2: 65*5283ecb5SPaul Mundt *val = (data >> ((where & 2) << 3)) & 0xffff; 66*5283ecb5SPaul Mundt break; 67*5283ecb5SPaul Mundt case 4: 68*5283ecb5SPaul Mundt *val = data; 69*5283ecb5SPaul Mundt break; 70*5283ecb5SPaul Mundt default: 71*5283ecb5SPaul Mundt return PCIBIOS_FUNC_NOT_SUPPORTED; 72*5283ecb5SPaul Mundt } 73*5283ecb5SPaul Mundt 74*5283ecb5SPaul Mundt return PCIBIOS_SUCCESSFUL; 75*5283ecb5SPaul Mundt } 76*5283ecb5SPaul Mundt 77*5283ecb5SPaul Mundt /* 78*5283ecb5SPaul Mundt * Since SH7780 only does 32bit access we'll have to do a read, 79*5283ecb5SPaul Mundt * mask,write operation. 80*5283ecb5SPaul Mundt * We'll allow an odd byte offset, though it should be illegal. 81*5283ecb5SPaul Mundt */ 82*5283ecb5SPaul Mundt static int sh7780_pci_write(struct pci_bus *bus, unsigned int devfn, 83*5283ecb5SPaul Mundt int where, int size, u32 val) 84*5283ecb5SPaul Mundt { 85*5283ecb5SPaul Mundt unsigned long flags; 86*5283ecb5SPaul Mundt int shift; 87*5283ecb5SPaul Mundt u32 data; 88*5283ecb5SPaul Mundt 89*5283ecb5SPaul Mundt local_irq_save(flags); 90*5283ecb5SPaul Mundt outl(CONFIG_CMD(bus, devfn, where), PCI_REG(SH7780_PCIPAR)); 91*5283ecb5SPaul Mundt data = inl(PCI_REG(SH7780_PCIPDR)); 92*5283ecb5SPaul Mundt local_irq_restore(flags); 93*5283ecb5SPaul Mundt 94*5283ecb5SPaul Mundt switch (size) { 95*5283ecb5SPaul Mundt case 1: 96*5283ecb5SPaul Mundt shift = (where & 3) << 3; 97*5283ecb5SPaul Mundt data &= ~(0xff << shift); 98*5283ecb5SPaul Mundt data |= ((val & 0xff) << shift); 99*5283ecb5SPaul Mundt break; 100*5283ecb5SPaul Mundt case 2: 101*5283ecb5SPaul Mundt shift = (where & 2) << 3; 102*5283ecb5SPaul Mundt data &= ~(0xffff << shift); 103*5283ecb5SPaul Mundt data |= ((val & 0xffff) << shift); 104*5283ecb5SPaul Mundt break; 105*5283ecb5SPaul Mundt case 4: 106*5283ecb5SPaul Mundt data = val; 107*5283ecb5SPaul Mundt break; 108*5283ecb5SPaul Mundt default: 109*5283ecb5SPaul Mundt return PCIBIOS_FUNC_NOT_SUPPORTED; 110*5283ecb5SPaul Mundt } 111*5283ecb5SPaul Mundt 112*5283ecb5SPaul Mundt outl(data, PCI_REG(SH7780_PCIPDR)); 113*5283ecb5SPaul Mundt 114*5283ecb5SPaul Mundt return PCIBIOS_SUCCESSFUL; 115*5283ecb5SPaul Mundt } 116*5283ecb5SPaul Mundt 117*5283ecb5SPaul Mundt #undef CONFIG_CMD 118*5283ecb5SPaul Mundt 119*5283ecb5SPaul Mundt struct pci_ops sh7780_pci_ops = { 120*5283ecb5SPaul Mundt .read = sh7780_pci_read, 121*5283ecb5SPaul Mundt .write = sh7780_pci_write, 122*5283ecb5SPaul Mundt }; 123*5283ecb5SPaul Mundt 124*5283ecb5SPaul Mundt static int __init pci_check_direct(void) 125*5283ecb5SPaul Mundt { 126*5283ecb5SPaul Mundt unsigned int tmp, id; 127*5283ecb5SPaul Mundt 128*5283ecb5SPaul Mundt outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */ 129*5283ecb5SPaul Mundt 130*5283ecb5SPaul Mundt /* check for SH7780/SH7780R hardware */ 131*5283ecb5SPaul Mundt id = inl(PCI_REG(SH7780_PCIVID)); 132*5283ecb5SPaul Mundt if ((id != ((SH7780_DEVICE_ID << 16) | SH7780_VENDOR_ID)) && 133*5283ecb5SPaul Mundt (id != ((SH7781_DEVICE_ID << 16) | SH7780_VENDOR_ID))) { 134*5283ecb5SPaul Mundt printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id); 135*5283ecb5SPaul Mundt return -ENODEV; 136*5283ecb5SPaul Mundt } 137*5283ecb5SPaul Mundt 138*5283ecb5SPaul Mundt /* 139*5283ecb5SPaul Mundt * Check if configuration works. 140*5283ecb5SPaul Mundt */ 141*5283ecb5SPaul Mundt if (pci_probe & PCI_PROBE_CONF1) { 142*5283ecb5SPaul Mundt tmp = inl(PCI_REG(SH7780_PCIPAR)); 143*5283ecb5SPaul Mundt outl(0x80000000, PCI_REG(SH7780_PCIPAR)); 144*5283ecb5SPaul Mundt if (inl(PCI_REG(SH7780_PCIPAR)) == 0x80000000) { 145*5283ecb5SPaul Mundt outl(tmp, PCI_REG(SH7780_PCIPAR)); 146*5283ecb5SPaul Mundt printk(KERN_INFO "PCI: Using configuration type 1\n"); 147*5283ecb5SPaul Mundt request_region(PCI_REG(SH7780_PCIPAR), 8, "PCI conf1"); 148*5283ecb5SPaul Mundt return 0; 149*5283ecb5SPaul Mundt } 150*5283ecb5SPaul Mundt outl(tmp, PCI_REG(SH7780_PCIPAR)); 151*5283ecb5SPaul Mundt } 152*5283ecb5SPaul Mundt 153*5283ecb5SPaul Mundt pr_debug("PCI: pci_check_direct failed\n"); 154*5283ecb5SPaul Mundt return -EINVAL; 155*5283ecb5SPaul Mundt } 156*5283ecb5SPaul Mundt 157*5283ecb5SPaul Mundt /***************************************************************************************/ 158*5283ecb5SPaul Mundt 159*5283ecb5SPaul Mundt /* 160*5283ecb5SPaul Mundt * Handle bus scanning and fixups .... 161*5283ecb5SPaul Mundt */ 162*5283ecb5SPaul Mundt 163*5283ecb5SPaul Mundt static void __init pci_fixup_ide_bases(struct pci_dev *d) 164*5283ecb5SPaul Mundt { 165*5283ecb5SPaul Mundt int i; 166*5283ecb5SPaul Mundt 167*5283ecb5SPaul Mundt /* 168*5283ecb5SPaul Mundt * PCI IDE controllers use non-standard I/O port decoding, respect it. 169*5283ecb5SPaul Mundt */ 170*5283ecb5SPaul Mundt if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) 171*5283ecb5SPaul Mundt return; 172*5283ecb5SPaul Mundt pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d)); 173*5283ecb5SPaul Mundt for(i=0; i<4; i++) { 174*5283ecb5SPaul Mundt struct resource *r = &d->resource[i]; 175*5283ecb5SPaul Mundt if ((r->start & ~0x80) == 0x374) { 176*5283ecb5SPaul Mundt r->start |= 2; 177*5283ecb5SPaul Mundt r->end = r->start; 178*5283ecb5SPaul Mundt } 179*5283ecb5SPaul Mundt } 180*5283ecb5SPaul Mundt } 181*5283ecb5SPaul Mundt 182*5283ecb5SPaul Mundt DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); 183*5283ecb5SPaul Mundt 184*5283ecb5SPaul Mundt /* 185*5283ecb5SPaul Mundt * Called after each bus is probed, but before its children 186*5283ecb5SPaul Mundt * are examined. 187*5283ecb5SPaul Mundt */ 188*5283ecb5SPaul Mundt 189*5283ecb5SPaul Mundt void __init pcibios_fixup_bus(struct pci_bus *b) 190*5283ecb5SPaul Mundt { 191*5283ecb5SPaul Mundt pci_read_bridge_bases(b); 192*5283ecb5SPaul Mundt } 193*5283ecb5SPaul Mundt 194*5283ecb5SPaul Mundt /* 195*5283ecb5SPaul Mundt * Initialization. Try all known PCI access methods. Note that we support 196*5283ecb5SPaul Mundt * using both PCI BIOS and direct access: in such cases, we use I/O ports 197*5283ecb5SPaul Mundt * to access config space. 198*5283ecb5SPaul Mundt * 199*5283ecb5SPaul Mundt * Note that the platform specific initialization (BSC registers, and memory 200*5283ecb5SPaul Mundt * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it 201*5283ecb5SPaul Mundt * exists and via the platform defined function pcibios_init_platform(). 202*5283ecb5SPaul Mundt * See pci_bigsur.c for implementation; 203*5283ecb5SPaul Mundt * 204*5283ecb5SPaul Mundt * The BIOS version of the pci functions is not yet implemented but it is left 205*5283ecb5SPaul Mundt * in for completeness. Currently an error will be genereated at compile time. 206*5283ecb5SPaul Mundt */ 207*5283ecb5SPaul Mundt 208*5283ecb5SPaul Mundt static int __init sh7780_pci_init(void) 209*5283ecb5SPaul Mundt { 210*5283ecb5SPaul Mundt int ret; 211*5283ecb5SPaul Mundt 212*5283ecb5SPaul Mundt pr_debug("PCI: Starting intialization.\n"); 213*5283ecb5SPaul Mundt 214*5283ecb5SPaul Mundt /* Setup the INTC */ 215*5283ecb5SPaul Mundt ctrl_outl(0x00200000, INTC_ICR0); /* INTC SH-4 Mode */ 216*5283ecb5SPaul Mundt ctrl_outl(0x00078000, INTC_INT2MSKCR); /* enable PCIINTA - PCIINTD */ 217*5283ecb5SPaul Mundt ctrl_outl(0x40000000, INTC_INTMSK1); /* disable IRL4-7 Interrupt */ 218*5283ecb5SPaul Mundt ctrl_outl(0x0000fffe, INTC_INTMSK2); /* disable IRL4-7 Interrupt */ 219*5283ecb5SPaul Mundt ctrl_outl(0x80000000, INTC_INTMSKCLR1); /* enable IRL0-3 Interrupt */ 220*5283ecb5SPaul Mundt ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); /* enable IRL0-3 Interrupt */ 221*5283ecb5SPaul Mundt 222*5283ecb5SPaul Mundt if ((ret = pci_check_direct()) != 0) 223*5283ecb5SPaul Mundt return ret; 224*5283ecb5SPaul Mundt 225*5283ecb5SPaul Mundt return pcibios_init_platform(); 226*5283ecb5SPaul Mundt } 227*5283ecb5SPaul Mundt 228*5283ecb5SPaul Mundt core_initcall(sh7780_pci_init); 229*5283ecb5SPaul Mundt 230*5283ecb5SPaul Mundt int __init sh7780_pcic_init(struct sh7780_pci_address_map *map) 231*5283ecb5SPaul Mundt { 232*5283ecb5SPaul Mundt u32 word; 233*5283ecb5SPaul Mundt 234*5283ecb5SPaul Mundt /* 235*5283ecb5SPaul Mundt * This code is unused for some boards as it is done in the 236*5283ecb5SPaul Mundt * bootloader and doing it here means the MAC addresses loaded 237*5283ecb5SPaul Mundt * by the bootloader get lost. 238*5283ecb5SPaul Mundt */ 239*5283ecb5SPaul Mundt if (!(map->flags & SH7780_PCIC_NO_RESET)) { 240*5283ecb5SPaul Mundt /* toggle PCI reset pin */ 241*5283ecb5SPaul Mundt word = SH7780_PCICR_PREFIX | SH7780_PCICR_PRST; 242*5283ecb5SPaul Mundt outl(word,PCI_REG(SH7780_PCICR)); 243*5283ecb5SPaul Mundt /* Wait for a long time... not 1 sec. but long enough */ 244*5283ecb5SPaul Mundt mdelay(100); 245*5283ecb5SPaul Mundt word = SH7780_PCICR_PREFIX; 246*5283ecb5SPaul Mundt outl(word,PCI_REG(SH7780_PCICR)); 247*5283ecb5SPaul Mundt } 248*5283ecb5SPaul Mundt 249*5283ecb5SPaul Mundt /* set the command/status bits to: 250*5283ecb5SPaul Mundt * Wait Cycle Control + Parity Enable + Bus Master + 251*5283ecb5SPaul Mundt * Mem space enable 252*5283ecb5SPaul Mundt */ 253*5283ecb5SPaul Mundt outl(0x00000046, PCI_REG(SH7780_PCICMD)); 254*5283ecb5SPaul Mundt 255*5283ecb5SPaul Mundt /* define this host as the host bridge */ 256*5283ecb5SPaul Mundt word = SH7780_PCI_HOST_BRIDGE << 24; 257*5283ecb5SPaul Mundt outl(word, PCI_REG(SH7780_PCIRID)); 258*5283ecb5SPaul Mundt 259*5283ecb5SPaul Mundt /* Set IO and Mem windows to local address 260*5283ecb5SPaul Mundt * Make PCI and local address the same for easy 1 to 1 mapping 261*5283ecb5SPaul Mundt * Window0 = map->window0.size @ non-cached area base = SDRAM 262*5283ecb5SPaul Mundt * Window1 = map->window1.size @ cached area base = SDRAM 263*5283ecb5SPaul Mundt */ 264*5283ecb5SPaul Mundt word = ((map->window0.size - 1) & 0x1ff00001) | 0x01; 265*5283ecb5SPaul Mundt outl(0x07f00001, PCI_REG(SH7780_PCILSR0)); 266*5283ecb5SPaul Mundt word = ((map->window1.size - 1) & 0x1ff00001) | 0x01; 267*5283ecb5SPaul Mundt outl(0x00000001, PCI_REG(SH7780_PCILSR1)); 268*5283ecb5SPaul Mundt /* Set the values on window 0 PCI config registers */ 269*5283ecb5SPaul Mundt word = P2SEGADDR(map->window0.base); 270*5283ecb5SPaul Mundt outl(0xa8000000, PCI_REG(SH7780_PCILAR0)); 271*5283ecb5SPaul Mundt outl(0x08000000, PCI_REG(SH7780_PCIMBAR0)); 272*5283ecb5SPaul Mundt /* Set the values on window 1 PCI config registers */ 273*5283ecb5SPaul Mundt word = P2SEGADDR(map->window1.base); 274*5283ecb5SPaul Mundt outl(0x00000000, PCI_REG(SH7780_PCILAR1)); 275*5283ecb5SPaul Mundt outl(0x00000000, PCI_REG(SH7780_PCIMBAR1)); 276*5283ecb5SPaul Mundt 277*5283ecb5SPaul Mundt /* Map IO space into PCI IO window 278*5283ecb5SPaul Mundt * The IO window is 64K-PCIBIOS_MIN_IO in size 279*5283ecb5SPaul Mundt * IO addresses will be translated to the 280*5283ecb5SPaul Mundt * PCI IO window base address 281*5283ecb5SPaul Mundt */ 282*5283ecb5SPaul Mundt PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, 283*5283ecb5SPaul Mundt (64*1024), SH7780_PCI_IO_BASE+PCIBIOS_MIN_IO); 284*5283ecb5SPaul Mundt 285*5283ecb5SPaul Mundt /* NOTE: I'm ignoring the PCI error IRQs for now.. 286*5283ecb5SPaul Mundt * TODO: add support for the internal error interrupts and 287*5283ecb5SPaul Mundt * DMA interrupts... 288*5283ecb5SPaul Mundt */ 289*5283ecb5SPaul Mundt 290*5283ecb5SPaul Mundt #ifdef CONFIG_SH_R7780RP 291*5283ecb5SPaul Mundt pci_fixup_pcic(); 292*5283ecb5SPaul Mundt #endif 293*5283ecb5SPaul Mundt 294*5283ecb5SPaul Mundt /* SH7780 init done, set central function init complete */ 295*5283ecb5SPaul Mundt /* use round robin mode to stop a device starving/overruning */ 296*5283ecb5SPaul Mundt word = SH7780_PCICR_PREFIX | SH7780_PCICR_CFIN | /* SH7780_PCICR_ARBM |*/ SH7780_PCICR_FTO; 297*5283ecb5SPaul Mundt outl(word, PCI_REG(SH7780_PCICR)); 298*5283ecb5SPaul Mundt 299*5283ecb5SPaul Mundt return 1; 300*5283ecb5SPaul Mundt } 301*5283ecb5SPaul Mundt 302*5283ecb5SPaul Mundt char * __init pcibios_setup(char *str) 303*5283ecb5SPaul Mundt { 304*5283ecb5SPaul Mundt if (!strcmp(str, "off")) { 305*5283ecb5SPaul Mundt pci_probe = 0; 306*5283ecb5SPaul Mundt return NULL; 307*5283ecb5SPaul Mundt } 308*5283ecb5SPaul Mundt 309*5283ecb5SPaul Mundt return str; 310*5283ecb5SPaul Mundt } 311*5283ecb5SPaul Mundt 312*5283ecb5SPaul Mundt /* 313*5283ecb5SPaul Mundt * IRQ functions 314*5283ecb5SPaul Mundt */ 315*5283ecb5SPaul Mundt static u8 __init sh7780_no_swizzle(struct pci_dev *dev, u8 *pin) 316*5283ecb5SPaul Mundt { 317*5283ecb5SPaul Mundt /* no swizzling */ 318*5283ecb5SPaul Mundt return PCI_SLOT(dev->devfn); 319*5283ecb5SPaul Mundt } 320*5283ecb5SPaul Mundt 321*5283ecb5SPaul Mundt static int sh7780_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) 322*5283ecb5SPaul Mundt { 323*5283ecb5SPaul Mundt int irq = -1; 324*5283ecb5SPaul Mundt 325*5283ecb5SPaul Mundt /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ 326*5283ecb5SPaul Mundt irq = pcibios_map_platform_irq(slot,pin); 327*5283ecb5SPaul Mundt if( irq < 0 ) { 328*5283ecb5SPaul Mundt pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev)); 329*5283ecb5SPaul Mundt return irq; 330*5283ecb5SPaul Mundt } 331*5283ecb5SPaul Mundt 332*5283ecb5SPaul Mundt pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq); 333*5283ecb5SPaul Mundt 334*5283ecb5SPaul Mundt return irq; 335*5283ecb5SPaul Mundt } 336*5283ecb5SPaul Mundt 337*5283ecb5SPaul Mundt void __init pcibios_fixup_irqs(void) 338*5283ecb5SPaul Mundt { 339*5283ecb5SPaul Mundt pci_fixup_irqs(sh7780_no_swizzle, sh7780_pci_lookup_irq); 340*5283ecb5SPaul Mundt } 341*5283ecb5SPaul Mundt 342