diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/drivers/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/drivers/pci/common.c | 64 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.c | 29 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci.c | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/pci.h | 2 |
5 files changed, 98 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 | # |
4 | obj-y += pci.o | 4 | obj-y += common.o pci.o |
5 | 5 | ||
6 | obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o | 6 | obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o |
7 | obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o | 7 | obj-$(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 | |||
4 | static int __init | ||
5 | early_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 | |||
27 | int __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 | ||
44 | static 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 | |||
44 | static int __init sh7780_pci_init(void) | 67 | static 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 | } |
181 | arch_initcall(sh7780_pci_init); | 210 | arch_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 | |||
91 | out: | 93 | out: |
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 | } |
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index d124a009889f..5849d435c441 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h | |||
@@ -32,6 +32,8 @@ struct pci_channel { | |||
32 | }; | 32 | }; |
33 | 33 | ||
34 | extern void register_pci_controller(struct pci_channel *hose); | 34 | extern void register_pci_controller(struct pci_channel *hose); |
35 | extern int pci_is_66mhz_capable(struct pci_channel *hose, | ||
36 | int top_bus, int current_bus); | ||
35 | 37 | ||
36 | extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM; | 38 | extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM; |
37 | 39 | ||