aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-10-13 18:37:01 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-10-13 18:37:01 -0400
commit61a46766c9d5d8fb5dad23da1b7cc4cb8b0107da (patch)
tree6b91ef707e1a1e4d202ab817ac066509a72b1c8b /arch/sh
parentf7fcec93b619337feb9da829b8a9ab6ba86393bc (diff)
sh: pci: Support slot 4 routing on SDK7786.
SDK7786 supports connecting either slot3 or 4 to the same PCIe port by way of FPGA muxing. By default the vertical slot 3 on the baseboard is enabled, so this adds in a command line option for forcibly enabling the slot 4 edge connector. If nothing has been specified on the command line, we fall back to reading the resistor values for card presence to figure out where to route the port to. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/drivers/pci/Makefile1
-rw-r--r--arch/sh/drivers/pci/fixups-sdk7786.c68
-rw-r--r--arch/sh/drivers/pci/pci.c2
-rw-r--r--arch/sh/include/mach-sdk7786/mach/fpga.h9
4 files changed, 79 insertions, 1 deletions
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 4a59e6890876..82f0a335fd19 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_SH_RTS7751R2D) += fixups-rts7751r2d.o
19obj-$(CONFIG_SH_SH03) += fixups-sh03.o 19obj-$(CONFIG_SH_SH03) += fixups-sh03.o
20obj-$(CONFIG_SH_HIGHLANDER) += fixups-r7780rp.o 20obj-$(CONFIG_SH_HIGHLANDER) += fixups-r7780rp.o
21obj-$(CONFIG_SH_SH7785LCR) += fixups-r7780rp.o 21obj-$(CONFIG_SH_SH7785LCR) += fixups-r7780rp.o
22obj-$(CONFIG_SH_SDK7786) += fixups-sdk7786.o
22obj-$(CONFIG_SH_SDK7780) += fixups-sdk7780.o 23obj-$(CONFIG_SH_SDK7780) += fixups-sdk7780.o
23obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += fixups-sdk7780.o 24obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += fixups-sdk7780.o
24obj-$(CONFIG_SH_TITAN) += fixups-titan.o 25obj-$(CONFIG_SH_TITAN) += fixups-titan.o
diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c
new file mode 100644
index 000000000000..058a65a1aa20
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-sdk7786.c
@@ -0,0 +1,68 @@
1/*
2 * SDK7786 FPGA PCIe mux handling
3 *
4 * Copyright (C) 2010 Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#define pr_fmt(fmt) "PCI: " fmt
11
12#include <linux/init.h>
13#include <linux/clk.h>
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <mach/fpga.h>
17
18/*
19 * The SDK7786 FPGA supports mangling of most of the slots in some way or
20 * another. Slots 3/4 are special in that only one can be supported at a
21 * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4
22 * (the horizontal edge connector) will disable slot 3 entirely.
23 *
24 * Misconfigurations can be detected through the FPGA via the slot
25 * resistors to determine card presence. Hotplug remains unsupported.
26 */
27static unsigned int slot4en __devinitdata;
28
29char *__devinit pcibios_setup(char *str)
30{
31 if (strcmp(str, "slot4en") == 0) {
32 slot4en = 1;
33 return NULL;
34 }
35
36 return str;
37}
38
39static int __init sdk7786_pci_init(void)
40{
41 u16 data = fpga_read_reg(PCIECR);
42
43 /*
44 * Enable slot #4 if it's been specified on the command line.
45 *
46 * Optionally reroute if slot #4 has a card present while slot #3
47 * does not, regardless of command line value.
48 *
49 * Card presence is logically inverted.
50 */
51 slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3));
52 if (slot4en) {
53 pr_info("Activating PCIe slot#4 (disabling slot#3)\n");
54
55 data &= ~PCIECR_PCIEMUX1;
56 fpga_write_reg(data, PCIECR);
57
58 /* Warn about forced rerouting if slot#3 is occupied */
59 if ((data & PCIECR_PRST3) == 0) {
60 pr_warning("Unreachable card detected in slot#3\n");
61 return -EBUSY;
62 }
63 } else
64 pr_info("PCIe slot#4 disabled\n");
65
66 return 0;
67}
68postcore_initcall(sdk7786_pci_init);
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index af4191bbb179..60ee09a4e121 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -268,7 +268,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
268 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 268 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
269} 269}
270 270
271char * __devinit pcibios_setup(char *str) 271char * __devinit __weak pcibios_setup(char *str)
272{ 272{
273 return str; 273 return str;
274} 274}
diff --git a/arch/sh/include/mach-sdk7786/mach/fpga.h b/arch/sh/include/mach-sdk7786/mach/fpga.h
index 416b621d94d1..8cc784147b96 100644
--- a/arch/sh/include/mach-sdk7786/mach/fpga.h
+++ b/arch/sh/include/mach-sdk7786/mach/fpga.h
@@ -31,7 +31,16 @@
31#define EXTASR 0x110 31#define EXTASR 0x110
32#define SPCAR 0x120 32#define SPCAR 0x120
33#define INTMSR 0x130 33#define INTMSR 0x130
34
34#define PCIECR 0x140 35#define PCIECR 0x140
36#define PCIECR_PCIEMUX1 BIT(15)
37#define PCIECR_PCIEMUX0 BIT(14)
38#define PCIECR_PRST4 BIT(12) /* slot 4 card present */
39#define PCIECR_PRST3 BIT(11) /* slot 3 card present */
40#define PCIECR_PRST2 BIT(10) /* slot 2 card present */
41#define PCIECR_PRST1 BIT(9) /* slot 1 card present */
42#define PCIECR_CLKEN BIT(4)
43
35#define FAER 0x150 44#define FAER 0x150
36#define USRGPIR 0x160 45#define USRGPIR 0x160
37/* 0x170 reserved */ 46/* 0x170 reserved */