Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ops-sh7786.c
Go to the documentation of this file.
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 {
20 };
21 
22 static int sh7786_pcie_config_access(unsigned char access_type,
23  struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
24 {
25  struct pci_channel *chan = bus->sysdata;
26  int dev, func, type, reg;
27 
28  dev = PCI_SLOT(devfn);
29  func = PCI_FUNC(devfn);
30  type = !!bus->parent;
31  reg = where & ~3;
32 
33  if (bus->number > 255 || dev > 31 || func > 7)
35 
36  /*
37  * While each channel has its own memory-mapped extended config
38  * space, it's generally only accessible when in endpoint mode.
39  * When in root complex mode, the controller is unable to target
40  * itself with either type 0 or type 1 accesses, and indeed, any
41  * controller initiated target transfer to its own config space
42  * result in a completer abort.
43  *
44  * Each channel effectively only supports a single device, but as
45  * the same channel <-> device access works for any PCI_SLOT()
46  * value, we cheat a bit here and bind the controller's config
47  * space to devfn 0 in order to enable self-enumeration. In this
48  * case the regular PAR/PDR path is sidelined and the mangled
49  * config access itself is initiated as a SuperHyway transaction.
50  */
51  if (pci_is_root_bus(bus)) {
52  if (dev == 0) {
53  if (access_type == PCI_ACCESS_READ)
54  *data = pci_read_reg(chan, PCI_REG(reg));
55  else
56  pci_write_reg(chan, *data, PCI_REG(reg));
57 
58  return PCIBIOS_SUCCESSFUL;
59  } else if (dev > 1)
61  }
62 
63  /* Clear errors */
64  pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR);
65 
66  /* Set the PIO address */
67  pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
68  (func << 16) | reg, SH4A_PCIEPAR);
69 
70  /* Enable the configuration access */
71  pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR);
72 
73  /* Check for errors */
74  if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10)
76 
77  /* Check for master and target aborts */
78  if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
80 
81  if (access_type == PCI_ACCESS_READ)
82  *data = pci_read_reg(chan, SH4A_PCIEPDR);
83  else
84  pci_write_reg(chan, *data, SH4A_PCIEPDR);
85 
86  /* Disable the configuration access */
87  pci_write_reg(chan, 0, SH4A_PCIEPCTLR);
88 
89  return PCIBIOS_SUCCESSFUL;
90 }
91 
92 static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
93  int where, int size, u32 *val)
94 {
95  unsigned long flags;
96  int ret;
97  u32 data;
98 
99  if ((size == 2) && (where & 1))
101  else if ((size == 4) && (where & 3))
103 
104  raw_spin_lock_irqsave(&pci_config_lock, flags);
105  ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
106  devfn, where, &data);
107  if (ret != PCIBIOS_SUCCESSFUL) {
108  *val = 0xffffffff;
109  goto out;
110  }
111 
112  if (size == 1)
113  *val = (data >> ((where & 3) << 3)) & 0xff;
114  else if (size == 2)
115  *val = (data >> ((where & 2) << 3)) & 0xffff;
116  else
117  *val = data;
118 
119  dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
120  "where=0x%04x size=%d val=0x%08lx\n", bus->number,
121  devfn, where, size, (unsigned long)*val);
122 
123 out:
124  raw_spin_unlock_irqrestore(&pci_config_lock, flags);
125  return ret;
126 }
127 
128 static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
129  int where, int size, u32 val)
130 {
131  unsigned long flags;
132  int shift, ret;
133  u32 data;
134 
135  if ((size == 2) && (where & 1))
137  else if ((size == 4) && (where & 3))
139 
140  raw_spin_lock_irqsave(&pci_config_lock, flags);
141  ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
142  devfn, where, &data);
143  if (ret != PCIBIOS_SUCCESSFUL)
144  goto out;
145 
146  dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
147  "where=0x%04x size=%d val=%08lx\n", bus->number,
148  devfn, where, size, (unsigned long)val);
149 
150  if (size == 1) {
151  shift = (where & 3) << 3;
152  data &= ~(0xff << shift);
153  data |= ((val & 0xff) << shift);
154  } else if (size == 2) {
155  shift = (where & 2) << 3;
156  data &= ~(0xffff << shift);
157  data |= ((val & 0xffff) << shift);
158  } else
159  data = val;
160 
161  ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus,
162  devfn, where, &data);
163 out:
164  raw_spin_unlock_irqrestore(&pci_config_lock, flags);
165  return ret;
166 }
167 
169  .read = sh7786_pcie_read,
170  .write = sh7786_pcie_write,
171 };