1 /* 2 * Generic SH7786 PCI-Express operations. 3 * 4 * Copyright (C) 2009 - 2010 Paul Mundt 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License v2. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 #include <linux/kernel.h> 11 #include <linux/init.h> 12 #include <linux/pci.h> 13 #include <linux/io.h> 14 #include <linux/spinlock.h> 15 #include "pcie-sh7786.h" 16 17 enum { 18 PCI_ACCESS_READ, 19 PCI_ACCESS_WRITE, 20 }; 21 22 static DEFINE_SPINLOCK(sh7786_pcie_lock); 23 24 static int sh7786_pcie_config_access(unsigned char access_type, 25 struct pci_bus *bus, unsigned int devfn, int where, u32 *data) 26 { 27 struct pci_channel *chan = bus->sysdata; 28 int dev, func, type; 29 30 dev = PCI_SLOT(devfn); 31 func = PCI_FUNC(devfn); 32 type = !!bus->parent; 33 34 if (bus->number > 255 || dev > 31 || func > 7) 35 return PCIBIOS_FUNC_NOT_SUPPORTED; 36 if (bus->parent == NULL && dev) 37 return PCIBIOS_DEVICE_NOT_FOUND; 38 39 /* Clear errors */ 40 pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR); 41 42 /* Set the PIO address */ 43 pci_write_reg(chan, (bus->number << 24) | (dev << 19) | 44 (func << 16) | (where & ~3), SH4A_PCIEPAR); 45 46 /* Enable the configuration access */ 47 pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR); 48 49 /* Check for errors */ 50 if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10) 51 return PCIBIOS_DEVICE_NOT_FOUND; 52 /* Check for master and target aborts */ 53 if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) 54 return PCIBIOS_DEVICE_NOT_FOUND; 55 56 if (access_type == PCI_ACCESS_READ) 57 *data = pci_read_reg(chan, SH4A_PCIEPDR); 58 else 59 pci_write_reg(chan, *data, SH4A_PCIEPDR); 60 61 return PCIBIOS_SUCCESSFUL; 62 } 63 64 static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn, 65 int where, int size, u32 *val) 66 { 67 unsigned long flags; 68 int ret; 69 u32 data; 70 71 if ((size == 2) && (where & 1)) 72 return PCIBIOS_BAD_REGISTER_NUMBER; 73 else if ((size == 4) && (where & 3)) 74 return PCIBIOS_BAD_REGISTER_NUMBER; 75 76 spin_lock_irqsave(&sh7786_pcie_lock, flags); 77 ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus, 78 devfn, where, &data); 79 if (ret != PCIBIOS_SUCCESSFUL) { 80 *val = 0xffffffff; 81 goto out; 82 } 83 84 if (size == 1) 85 *val = (data >> ((where & 3) << 3)) & 0xff; 86 else if (size == 2) 87 *val = (data >> ((where & 2) << 3)) & 0xffff; 88 else 89 *val = data; 90 91 dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x " 92 "where=0x%04x size=%d val=0x%08lx\n", bus->number, 93 devfn, where, size, (unsigned long)*val); 94 95 out: 96 spin_unlock_irqrestore(&sh7786_pcie_lock, flags); 97 return ret; 98 } 99 100 static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn, 101 int where, int size, u32 val) 102 { 103 unsigned long flags; 104 int shift, ret; 105 u32 data; 106 107 if ((size == 2) && (where & 1)) 108 return PCIBIOS_BAD_REGISTER_NUMBER; 109 else if ((size == 4) && (where & 3)) 110 return PCIBIOS_BAD_REGISTER_NUMBER; 111 112 spin_lock_irqsave(&sh7786_pcie_lock, flags); 113 ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus, 114 devfn, where, &data); 115 if (ret != PCIBIOS_SUCCESSFUL) 116 goto out; 117 118 dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x " 119 "where=0x%04x size=%d val=%08lx\n", bus->number, 120 devfn, where, size, (unsigned long)val); 121 122 if (size == 1) { 123 shift = (where & 3) << 3; 124 data &= ~(0xff << shift); 125 data |= ((val & 0xff) << shift); 126 } else if (size == 2) { 127 shift = (where & 2) << 3; 128 data &= ~(0xffff << shift); 129 data |= ((val & 0xffff) << shift); 130 } else 131 data = val; 132 133 ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus, 134 devfn, where, &data); 135 out: 136 spin_unlock_irqrestore(&sh7786_pcie_lock, flags); 137 return ret; 138 } 139 140 struct pci_ops sh7786_pci_ops = { 141 .read = sh7786_pcie_read, 142 .write = sh7786_pcie_write, 143 }; 144