aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/drivers/pci')
-rw-r--r--arch/sh/drivers/pci/Makefile2
-rw-r--r--arch/sh/drivers/pci/common.c64
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c29
-rw-r--r--arch/sh/drivers/pci/pci.c2
4 files changed, 96 insertions, 1 deletions
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 2c458b602beb..4a59e6890876 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the PCI specific kernel interface routines under Linux. 2# Makefile for the PCI specific kernel interface routines under Linux.
3# 3#
4obj-y += pci.o 4obj-y += common.o pci.o
5 5
6obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o 6obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
7obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o 7obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o
diff --git a/arch/sh/drivers/pci/common.c b/arch/sh/drivers/pci/common.c
new file mode 100644
index 000000000000..f67c946a8612
--- /dev/null
+++ b/arch/sh/drivers/pci/common.c
@@ -0,0 +1,64 @@
1#include <linux/pci.h>
2#include <linux/kernel.h>
3
4static int __init
5early_read_config_word(struct pci_channel *hose,
6 int top_bus, int bus, int devfn, int offset, u16 *value)
7{
8 struct pci_dev fake_dev;
9 struct pci_bus fake_bus;
10
11 fake_dev.bus = &fake_bus;
12 fake_dev.sysdata = hose;
13 fake_dev.devfn = devfn;
14 fake_bus.number = bus;
15 fake_bus.sysdata = hose;
16 fake_bus.ops = hose->pci_ops;
17
18 if (bus != top_bus)
19 /* Fake a parent bus structure. */
20 fake_bus.parent = &fake_bus;
21 else
22 fake_bus.parent = NULL;
23
24 return pci_read_config_word(&fake_dev, offset, value);
25}
26
27int __init pci_is_66mhz_capable(struct pci_channel *hose,
28 int top_bus, int current_bus)
29{
30 u32 pci_devfn;
31 unsigned short vid;
32 int cap66 = -1;
33 u16 stat;
34
35 printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n");
36
37 for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
38 if (PCI_FUNC(pci_devfn))
39 continue;
40 if (early_read_config_word(hose, top_bus, current_bus,
41 pci_devfn, PCI_VENDOR_ID, &vid) !=
42 PCIBIOS_SUCCESSFUL)
43 continue;
44 if (vid == 0xffff)
45 continue;
46
47 /* check 66MHz capability */
48 if (cap66 < 0)
49 cap66 = 1;
50 if (cap66) {
51 early_read_config_word(hose, top_bus, current_bus,
52 pci_devfn, PCI_STATUS, &stat);
53 if (!(stat & PCI_STATUS_66MHZ)) {
54 printk(KERN_DEBUG
55 "PCI: %02x:%02x not 66MHz capable.\n",
56 current_bus, pci_devfn);
57 cap66 = 0;
58 break;
59 }
60 }
61 }
62
63 return cap66 > 0;
64}
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index 8405c8fded6f..b68f45b6451a 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -41,6 +41,29 @@ static struct pci_channel sh7780_pci_controller = {
41 .io_map_base = SH7780_PCI_IO_BASE, 41 .io_map_base = SH7780_PCI_IO_BASE,
42}; 42};
43 43
44static void __init sh7780_pci66_init(struct pci_channel *hose)
45{
46 unsigned int tmp;
47
48 if (!pci_is_66mhz_capable(hose, 0, 0))
49 return;
50
51 /* Enable register access */
52 tmp = __raw_readl(hose->reg_base + SH4_PCICR);
53 tmp |= SH4_PCICR_PREFIX;
54 __raw_writel(tmp, hose->reg_base + SH4_PCICR);
55
56 /* Enable 66MHz operation */
57 tmp = __raw_readw(hose->reg_base + PCI_STATUS);
58 tmp |= PCI_STATUS_66MHZ;
59 __raw_writew(tmp, hose->reg_base + PCI_STATUS);
60
61 /* Done */
62 tmp = __raw_readl(hose->reg_base + SH4_PCICR);
63 tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN;
64 __raw_writel(tmp, hose->reg_base + SH4_PCICR);
65}
66
44static int __init sh7780_pci_init(void) 67static int __init sh7780_pci_init(void)
45{ 68{
46 struct pci_channel *chan = &sh7780_pci_controller; 69 struct pci_channel *chan = &sh7780_pci_controller;
@@ -176,6 +199,12 @@ static int __init sh7780_pci_init(void)
176 199
177 register_pci_controller(chan); 200 register_pci_controller(chan);
178 201
202 sh7780_pci66_init(chan);
203
204 printk(KERN_NOTICE "PCI: Running at %dMHz.\n",
205 (__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ?
206 66 : 33);
207
179 return 0; 208 return 0;
180} 209}
181arch_initcall(sh7780_pci_init); 210arch_initcall(sh7780_pci_init);
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 45a15cab01df..63b11fddffec 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -88,6 +88,8 @@ void __devinit register_pci_controller(struct pci_channel *hose)
88 mutex_unlock(&pci_scan_mutex); 88 mutex_unlock(&pci_scan_mutex);
89 } 89 }
90 90
91 return;
92
91out: 93out:
92 printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n"); 94 printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n");
93} 95}