root/arch/sh/drivers/pci/pci-sh5.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. r2p2
  2. pcish5_err_irq
  3. pcish5_serr_irq
  4. sh5pci_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
   4  * Copyright (C) 2003, 2004 Paul Mundt
   5  * Copyright (C) 2004 Richard Curnow
   6  *
   7  * Support functions for the SH5 PCI hardware.
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/rwsem.h>
  12 #include <linux/smp.h>
  13 #include <linux/interrupt.h>
  14 #include <linux/init.h>
  15 #include <linux/errno.h>
  16 #include <linux/pci.h>
  17 #include <linux/delay.h>
  18 #include <linux/types.h>
  19 #include <linux/irq.h>
  20 #include <cpu/irq.h>
  21 #include <asm/io.h>
  22 #include "pci-sh5.h"
  23 
  24 unsigned long pcicr_virt;
  25 unsigned long PCI_IO_AREA;
  26 
  27 /* Rounds a number UP to the nearest power of two. Used for
  28  * sizing the PCI window.
  29  */
  30 static u32 __init r2p2(u32 num)
  31 {
  32         int i = 31;
  33         u32 tmp = num;
  34 
  35         if (num == 0)
  36                 return 0;
  37 
  38         do {
  39                 if (tmp & (1 << 31))
  40                         break;
  41                 i--;
  42                 tmp <<= 1;
  43         } while (i >= 0);
  44 
  45         tmp = 1 << i;
  46         /* If the original number isn't a power of 2, round it up */
  47         if (tmp != num)
  48                 tmp <<= 1;
  49 
  50         return tmp;
  51 }
  52 
  53 static irqreturn_t pcish5_err_irq(int irq, void *dev_id)
  54 {
  55         struct pt_regs *regs = get_irq_regs();
  56         unsigned pci_int, pci_air, pci_cir, pci_aint;
  57 
  58         pci_int = SH5PCI_READ(INT);
  59         pci_cir = SH5PCI_READ(CIR);
  60         pci_air = SH5PCI_READ(AIR);
  61 
  62         if (pci_int) {
  63                 printk("PCI INTERRUPT (at %08llx)!\n", regs->pc);
  64                 printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
  65                 printk("PCI AIR -> 0x%x\n", pci_air);
  66                 printk("PCI CIR -> 0x%x\n", pci_cir);
  67                 SH5PCI_WRITE(INT, ~0);
  68         }
  69 
  70         pci_aint = SH5PCI_READ(AINT);
  71         if (pci_aint) {
  72                 printk("PCI ARB INTERRUPT!\n");
  73                 printk("PCI AINT -> 0x%x\n", pci_aint);
  74                 printk("PCI AIR -> 0x%x\n", pci_air);
  75                 printk("PCI CIR -> 0x%x\n", pci_cir);
  76                 SH5PCI_WRITE(AINT, ~0);
  77         }
  78 
  79         return IRQ_HANDLED;
  80 }
  81 
  82 static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
  83 {
  84         printk("SERR IRQ\n");
  85 
  86         return IRQ_NONE;
  87 }
  88 
  89 static struct resource sh5_pci_resources[2];
  90 
  91 static struct pci_channel sh5pci_controller = {
  92         .pci_ops                = &sh5_pci_ops,
  93         .resources              = sh5_pci_resources,
  94         .nr_resources           = ARRAY_SIZE(sh5_pci_resources),
  95         .mem_offset             = 0x00000000,
  96         .io_offset              = 0x00000000,
  97 };
  98 
  99 static int __init sh5pci_init(void)
 100 {
 101         unsigned long memStart = __pa(memory_start);
 102         unsigned long memSize = __pa(memory_end) - memStart;
 103         u32 lsr0;
 104         u32 uval;
 105 
 106         if (request_irq(IRQ_ERR, pcish5_err_irq,
 107                         0, "PCI Error",NULL) < 0) {
 108                 printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
 109                 return -EINVAL;
 110         }
 111 
 112         if (request_irq(IRQ_SERR, pcish5_serr_irq,
 113                         0, "PCI SERR interrupt", NULL) < 0) {
 114                 printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
 115                 return -EINVAL;
 116         }
 117 
 118         pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024);
 119         if (!pcicr_virt) {
 120                 panic("Unable to remap PCICR\n");
 121         }
 122 
 123         PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000);
 124         if (!PCI_IO_AREA) {
 125                 panic("Unable to remap PCIIO\n");
 126         }
 127 
 128         /* Clear snoop registers */
 129         SH5PCI_WRITE(CSCR0, 0);
 130         SH5PCI_WRITE(CSCR1, 0);
 131 
 132         /* Switch off interrupts */
 133         SH5PCI_WRITE(INTM,  0);
 134         SH5PCI_WRITE(AINTM, 0);
 135         SH5PCI_WRITE(PINTM, 0);
 136 
 137         /* Set bus active, take it out of reset */
 138         uval = SH5PCI_READ(CR);
 139 
 140         /* Set command Register */
 141         SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE |
 142                      CR_PFCS | CR_BMAM);
 143 
 144         uval=SH5PCI_READ(CR);
 145 
 146         /* Allow it to be a master */
 147         /* NB - WE DISABLE I/O ACCESS to stop overlap */
 148         /* set WAIT bit to enable stepping, an attempt to improve stability */
 149         SH5PCI_WRITE_SHORT(CSR_CMD,
 150                             PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
 151                             PCI_COMMAND_WAIT);
 152 
 153         /*
 154         ** Set translation mapping memory in order to convert the address
 155         ** used for the main bus, to the PCI internal address.
 156         */
 157         SH5PCI_WRITE(MBR,0x40000000);
 158 
 159         /* Always set the max size 512M */
 160         SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024));
 161 
 162         /*
 163         ** I/O addresses are mapped at internal PCI specific address
 164         ** as is described into the configuration bridge table.
 165         ** These are changed to 0, to allow cards that have legacy
 166         ** io such as vga to function correctly. We set the SH5 IOBAR to
 167         ** 256K, which is a bit big as we can only have 64K of address space
 168         */
 169 
 170         SH5PCI_WRITE(IOBR,0x0);
 171 
 172         /* Set up a 256K window. Totally pointless waste  of address space */
 173         SH5PCI_WRITE(IOBMR,0);
 174 
 175         /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec.
 176          * Ideally, we would want to map the I/O region somewhere, but it
 177          * is so big this is not that easy!
 178          */
 179         SH5PCI_WRITE(CSR_IBAR0,~0);
 180         /* Set memory size value */
 181         memSize = memory_end - memory_start;
 182 
 183         /* Now we set up the mbars so the PCI bus can see the memory of
 184          * the machine */
 185         if (memSize < (1024 * 1024)) {
 186                 printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%lx?\n",
 187                        memSize);
 188                 return -EINVAL;
 189         }
 190 
 191         /* Set LSR 0 */
 192         lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 :
 193                 ((r2p2(memSize) - 0x100000) | 0x1);
 194         SH5PCI_WRITE(LSR0, lsr0);
 195 
 196         /* Set MBAR 0 */
 197         SH5PCI_WRITE(CSR_MBAR0, memory_start);
 198         SH5PCI_WRITE(LAR0, memory_start);
 199 
 200         SH5PCI_WRITE(CSR_MBAR1,0);
 201         SH5PCI_WRITE(LAR1,0);
 202         SH5PCI_WRITE(LSR1,0);
 203 
 204         /* Enable the PCI interrupts on the device */
 205         SH5PCI_WRITE(INTM,  ~0);
 206         SH5PCI_WRITE(AINTM, ~0);
 207         SH5PCI_WRITE(PINTM, ~0);
 208 
 209         sh5_pci_resources[0].start = PCI_IO_AREA;
 210         sh5_pci_resources[0].end = PCI_IO_AREA + 0x10000;
 211 
 212         sh5_pci_resources[1].start = memStart;
 213         sh5_pci_resources[1].end = memStart + memSize;
 214 
 215         return register_pci_controller(&sh5pci_controller);
 216 }
 217 arch_initcall(sh5pci_init);

/* [<][>][^][v][top][bottom][index][help] */