aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 02:59:17 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 02:59:17 -0400
commit5283ecb5ccbdb90d49fce6488d3944bba63a591c (patch)
treea58e20bd532fa5f933d099bb7b5dd0637b581d33 /arch/sh/drivers
parentd7c30c682a278abe1a52db83f69efec1a9d8f8c2 (diff)
sh: Add support for R7780RP and R7780MP boards.
This adds support for the Renesas SH7780 development boards, R7780RP and R7780MP. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers')
-rw-r--r--arch/sh/drivers/dma/Kconfig3
-rw-r--r--arch/sh/drivers/dma/dma-sh.c4
-rw-r--r--arch/sh/drivers/pci/Makefile2
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c39
-rw-r--r--arch/sh/drivers/pci/ops-r7780rp.c77
-rw-r--r--arch/sh/drivers/pci/pci-auto.c44
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c4
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c341
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.h168
9 files changed, 651 insertions, 31 deletions
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 0f15216cd39d..defc13c37d48 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -11,6 +11,8 @@ config SH_DMA
11config NR_ONCHIP_DMA_CHANNELS 11config NR_ONCHIP_DMA_CHANNELS
12 depends on SH_DMA 12 depends on SH_DMA
13 int "Number of on-chip DMAC channels" 13 int "Number of on-chip DMAC channels"
14 default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
15 default "12" if CPU_SUBTYPE_SH7780
14 default "4" 16 default "4"
15 help 17 help
16 This allows you to specify the number of channels that the on-chip 18 This allows you to specify the number of channels that the on-chip
@@ -52,4 +54,3 @@ config DMA_PAGE_OPS_CHANNEL
52 are dual-address capable. 54 are dual-address capable.
53 55
54endmenu 56endmenu
55
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index e028a2d2a4ea..4428ee809651 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -11,14 +11,10 @@
11 * License. See the file "COPYING" in the main directory of this archive 11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details. 12 * for more details.
13 */ 13 */
14
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/irq.h>
17#include <linux/interrupt.h> 15#include <linux/interrupt.h>
18#include <linux/module.h> 16#include <linux/module.h>
19#include <asm/dreamcast/dma.h> 17#include <asm/dreamcast/dma.h>
20#include <asm/signal.h>
21#include <asm/irq.h>
22#include <asm/dma.h> 18#include <asm/dma.h>
23#include <asm/io.h> 19#include <asm/io.h>
24#include "dma-sh.h" 20#include "dma-sh.h"
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 86d6d0660d4c..3d8078f1c05f 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_AUTO) += pci-auto.o
7 7
8obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o 8obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o
9obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o 9obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o
10obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o
10 11
11obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ 12obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
12 dma-dreamcast.o 13 dma-dreamcast.o
@@ -14,4 +15,5 @@ obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
14obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o 15obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o
15obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o 16obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
16obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o 17obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
18obj-$(CONFIG_SH_R7780RP) += ops-r7780rp.o fixups-r7780rp.o
17obj-$(CONFIG_SH_TITAN) += ops-titan.o 19obj-$(CONFIG_SH_TITAN) += ops-titan.o
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
new file mode 100644
index 000000000000..b656b562ec99
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -0,0 +1,39 @@
1/*
2 * arch/sh/drivers/pci/fixups-r7780rp.c
3 *
4 * Highlander R7780RP-1 PCI fixups
5 *
6 * Copyright (C) 2003 Lineo uSolutions, Inc.
7 * Copyright (C) 2004 Paul Mundt
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13#include "pci-sh7780.h"
14#include <asm/io.h>
15
16int pci_fixup_pcic(void)
17{
18 outl(0x000043ff, PCI_REG(SH7780_PCIIMR));
19 outl(0x0000380f, PCI_REG(SH7780_PCIAINTM));
20
21 outl(0xfbb00047, PCI_REG(SH7780_PCICMD));
22 outl(0x00000000, PCI_REG(SH7780_PCIIBAR));
23
24 outl(0x00011912, PCI_REG(SH7780_PCISVID));
25 outl(0x08000000, PCI_REG(SH7780_PCICSCR0));
26 outl(0x0000001b, PCI_REG(SH7780_PCICSAR0));
27 outl(0xfd000000, PCI_REG(SH7780_PCICSCR1));
28 outl(0x0000000f, PCI_REG(SH7780_PCICSAR1));
29
30 outl(0xfd000000, PCI_REG(SH7780_PCIMBR0));
31 outl(0x00fc0000, PCI_REG(SH7780_PCIMBMR0));
32
33 /* Set IOBR for windows containing area specified in pci.h */
34 outl((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1)), PCI_REG(SH7780_PCIIOBR));
35 outl(((SH7780_PCI_IO_SIZE-1) & (7<<18)), PCI_REG(SH7780_PCIIOBMR));
36
37 return 0;
38}
39
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
new file mode 100644
index 000000000000..3254c4e917a9
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-r7780rp.c
@@ -0,0 +1,77 @@
1/*
2 * Author: Ian DaSilva (idasilva@mvista.com)
3 *
4 * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pci.h>
18#include <linux/module.h>
19
20#include <asm/io.h>
21#include "pci-sh7780.h"
22#include <asm/r7780rp/r7780rp.h>
23
24int __init pcibios_map_platform_irq(u8 slot, u8 pin)
25{
26 switch (slot) {
27 case 0: return IRQ_PCISLOT1; /* PCI Interrupt #1 */
28 case 1: return IRQ_PCISLOT2; /* PCI Interrupt #2 */
29 case 2: return IRQ_PCISLOT3; /* PCI Interrupt #3 */
30 case 3: return IRQ_PCISLOT4; /* PCI Interrupt E4 */
31 default:
32 printk("PCI: Bad IRQ mapping request for slot %d, func %d\n", slot, pin-1);
33 return -1;
34 }
35}
36
37static struct resource sh7780_io_resource = {
38 .name = "SH7780_IO",
39 .start = 0x2000,
40 .end = 0x2000 + SH7780_PCI_IO_SIZE - 1,
41 .flags = IORESOURCE_IO
42};
43
44static struct resource sh7780_mem_resource = {
45 .name = "SH7780_mem",
46 .start = SH7780_PCI_MEMORY_BASE,
47 .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
48 .flags = IORESOURCE_MEM
49};
50
51extern struct pci_ops sh7780_pci_ops;
52
53struct pci_channel board_pci_channels[] = {
54 { &sh7780_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
55 { NULL, NULL, NULL, 0, 0 },
56};
57EXPORT_SYMBOL(board_pci_channels);
58
59static struct sh7780_pci_address_map sh7780_pci_map = {
60 .window0 = {
61 .base = SH7780_CS2_BASE_ADDR,
62 .size = 0x04000000,
63 },
64
65 .window1 = {
66 .base = SH7780_CS3_BASE_ADDR,
67 .size = 0x04000000,
68 },
69
70 .flags = SH7780_PCIC_NO_RESET,
71};
72
73int __init pcibios_init_platform(void)
74{
75 return sh7780_pcic_init(&sh7780_pci_map);
76}
77
diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c
index 4cef4d1d8c84..d55e46618549 100644
--- a/arch/sh/drivers/pci/pci-auto.c
+++ b/arch/sh/drivers/pci/pci-auto.c
@@ -45,11 +45,11 @@
45#include <linux/types.h> 45#include <linux/types.h>
46#include <linux/pci.h> 46#include <linux/pci.h>
47 47
48#undef DEBUG 48#define DEBUG
49#ifdef DEBUG 49#ifdef DEBUG
50#define DBG(x...) printk(x) 50#define DBG(x...) printk(x)
51#else 51#else
52#define DBG(x...) 52#define DBG(x...)
53#endif 53#endif
54 54
55/* 55/*
@@ -102,7 +102,7 @@ static u32 pciauto_upper_iospc;
102static u32 pciauto_lower_memspc; 102static u32 pciauto_lower_memspc;
103static u32 pciauto_upper_memspc; 103static u32 pciauto_upper_memspc;
104 104
105static void __init 105static void __init
106pciauto_setup_bars(struct pci_channel *hose, 106pciauto_setup_bars(struct pci_channel *hose,
107 int top_bus, 107 int top_bus,
108 int current_bus, 108 int current_bus,
@@ -116,7 +116,6 @@ pciauto_setup_bars(struct pci_channel *hose,
116 int found_mem64 = 0; 116 int found_mem64 = 0;
117 117
118 for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) { 118 for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
119#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
120 u32 bar_addr; 119 u32 bar_addr;
121 120
122 /* Read the old BAR value */ 121 /* Read the old BAR value */
@@ -125,7 +124,6 @@ pciauto_setup_bars(struct pci_channel *hose,
125 pci_devfn, 124 pci_devfn,
126 bar, 125 bar,
127 &bar_addr); 126 &bar_addr);
128#endif
129 127
130 /* Tickle the BAR and get the response */ 128 /* Tickle the BAR and get the response */
131 early_write_config_dword(hose, top_bus, 129 early_write_config_dword(hose, top_bus,
@@ -140,8 +138,7 @@ pciauto_setup_bars(struct pci_channel *hose,
140 bar, 138 bar,
141 &bar_response); 139 &bar_response);
142 140
143#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) 141 /*
144 /*
145 * Write the old BAR value back out, only update the BAR 142 * Write the old BAR value back out, only update the BAR
146 * if we implicitly want resources to be updated, which 143 * if we implicitly want resources to be updated, which
147 * is done by the generic code further down. -- PFM. 144 * is done by the generic code further down. -- PFM.
@@ -151,7 +148,6 @@ pciauto_setup_bars(struct pci_channel *hose,
151 pci_devfn, 148 pci_devfn,
152 bar, 149 bar,
153 bar_addr); 150 bar_addr);
154#endif
155 151
156 /* If BAR is not implemented go to the next BAR */ 152 /* If BAR is not implemented go to the next BAR */
157 if (!bar_response) 153 if (!bar_response)
@@ -177,7 +173,7 @@ retry:
177 PCI_BASE_ADDRESS_MEM_TYPE_64) 173 PCI_BASE_ADDRESS_MEM_TYPE_64)
178 found_mem64 = 1; 174 found_mem64 = 1;
179 175
180 addr_mask = PCI_BASE_ADDRESS_MEM_MASK; 176 addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
181 upper_limit = &pciauto_upper_memspc; 177 upper_limit = &pciauto_upper_memspc;
182 lower_limit = &pciauto_lower_memspc; 178 lower_limit = &pciauto_lower_memspc;
183 DBG(" Mem"); 179 DBG(" Mem");
@@ -193,22 +189,22 @@ retry:
193 if ((bar_value + bar_size) > *upper_limit) { 189 if ((bar_value + bar_size) > *upper_limit) {
194 if (bar_response & PCI_BASE_ADDRESS_SPACE) { 190 if (bar_response & PCI_BASE_ADDRESS_SPACE) {
195 if (io_resource_inuse->child) { 191 if (io_resource_inuse->child) {
196 io_resource_inuse = 192 io_resource_inuse =
197 io_resource_inuse->child; 193 io_resource_inuse->child;
198 pciauto_lower_iospc = 194 pciauto_lower_iospc =
199 io_resource_inuse->start; 195 io_resource_inuse->start;
200 pciauto_upper_iospc = 196 pciauto_upper_iospc =
201 io_resource_inuse->end + 1; 197 io_resource_inuse->end + 1;
202 goto retry; 198 goto retry;
203 } 199 }
204 200
205 } else { 201 } else {
206 if (mem_resource_inuse->child) { 202 if (mem_resource_inuse->child) {
207 mem_resource_inuse = 203 mem_resource_inuse =
208 mem_resource_inuse->child; 204 mem_resource_inuse->child;
209 pciauto_lower_memspc = 205 pciauto_lower_memspc =
210 mem_resource_inuse->start; 206 mem_resource_inuse->start;
211 pciauto_upper_memspc = 207 pciauto_upper_memspc =
212 mem_resource_inuse->end + 1; 208 mem_resource_inuse->end + 1;
213 goto retry; 209 goto retry;
214 } 210 }
@@ -230,7 +226,7 @@ retry:
230 * If we are a 64-bit decoder then increment to the 226 * If we are a 64-bit decoder then increment to the
231 * upper 32 bits of the bar and force it to locate 227 * upper 32 bits of the bar and force it to locate
232 * in the lower 4GB of memory. 228 * in the lower 4GB of memory.
233 */ 229 */
234 if (found_mem64) { 230 if (found_mem64) {
235 bar += 4; 231 bar += 4;
236 early_write_config_dword(hose, top_bus, 232 early_write_config_dword(hose, top_bus,
@@ -362,7 +358,7 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
362{ 358{
363 u32 temp; 359 u32 temp;
364 360
365#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) 361#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) && !defined(CONFIG_SH_R7780RP)
366 /* 362 /*
367 * [jsun] we always bump up baselines a little, so that if there 363 * [jsun] we always bump up baselines a little, so that if there
368 * nothing behind P2P bridge, we don't wind up overlapping IO/MEM 364 * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
@@ -396,7 +392,7 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
396 * configured by this routine to happily live behind a 392 * configured by this routine to happily live behind a
397 * P2P bridge in a system. 393 * P2P bridge in a system.
398 */ 394 */
399#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) 395#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) || defined(CONFIG_SH_R7780RP)
400 pciauto_lower_memspc += 0x00400000; 396 pciauto_lower_memspc += 0x00400000;
401 pciauto_lower_iospc += 0x00004000; 397 pciauto_lower_iospc += 0x00004000;
402#endif 398#endif
@@ -433,12 +429,12 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
433 int devfn_stop = 0xff; 429 int devfn_stop = 0xff;
434 430
435 sub_bus = current_bus; 431 sub_bus = current_bus;
436 432
437 if (hose->first_devfn) 433 if (hose->first_devfn)
438 devfn_start = hose->first_devfn; 434 devfn_start = hose->first_devfn;
439 if (hose->last_devfn) 435 if (hose->last_devfn)
440 devfn_stop = hose->last_devfn; 436 devfn_stop = hose->last_devfn;
441 437
442 for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) { 438 for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
443 439
444 if (PCI_FUNC(pci_devfn) && !found_multi) 440 if (PCI_FUNC(pci_devfn) && !found_multi)
@@ -471,7 +467,7 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
471 if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { 467 if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
472 DBG(" Bridge: primary=%.2x, secondary=%.2x\n", 468 DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
473 current_bus, sub_bus + 1); 469 current_bus, sub_bus + 1);
474#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) 470#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) || defined(CONFIG_SH_R7780RP)
475 pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1); 471 pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
476#endif 472#endif
477 pciauto_prescan_setup_bridge(hose, top_bus, current_bus, 473 pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
@@ -490,10 +486,10 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
490 DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); 486 DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
491 /* Place CardBus Socket/ExCA registers */ 487 /* Place CardBus Socket/ExCA registers */
492 pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0); 488 pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
493 489
494 pciauto_prescan_setup_cardbus_bridge(hose, top_bus, 490 pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
495 current_bus, pci_devfn, sub_bus); 491 current_bus, pci_devfn, sub_bus);
496 492
497 DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", 493 DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
498 sub_bus + 1, 494 sub_bus + 1,
499 pciauto_lower_iospc, pciauto_lower_memspc); 495 pciauto_lower_iospc, pciauto_lower_memspc);
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 682f3dae305d..65093ec1b55e 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -223,7 +223,7 @@ static int __init __area_sdram_check(unsigned int area)
223 223
224 word = inl(SH7751_BCR1); 224 word = inl(SH7751_BCR1);
225 /* check BCR for SDRAM in area */ 225 /* check BCR for SDRAM in area */
226 if(((word >> area) & 1) == 0) { 226 if (((word >> area) & 1) == 0) {
227 printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n", 227 printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
228 area, word); 228 area, word);
229 return 0; 229 return 0;
@@ -232,7 +232,7 @@ static int __init __area_sdram_check(unsigned int area)
232 232
233 word = (u16)inw(SH7751_BCR2); 233 word = (u16)inw(SH7751_BCR2);
234 /* check BCR2 for 32bit SDRAM interface*/ 234 /* check BCR2 for 32bit SDRAM interface*/
235 if(((word >> (area << 1)) & 0x3) != 0x3) { 235 if (((word >> (area << 1)) & 0x3) != 0x3) {
236 printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n", 236 printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
237 area, word); 237 area, word);
238 return 0; 238 return 0;
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
new file mode 100644
index 000000000000..e09721330ac2
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -0,0 +1,341 @@
1/*
2 * Low-Level PCI Support for the SH7780
3 *
4 * Dustin McIntire (dustin@sensoria.com)
5 * Derived from arch/i386/kernel/pci-*.c which bore the message:
6 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
7 *
8 * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
9 * With cleanup by Paul van Gool <pvangool@mimotech.com>
10 *
11 * May be copied or modified under the terms of the GNU General Public
12 * License. See linux/COPYING for more information.
13 *
14 */
15
16#undef DEBUG
17
18#include <linux/config.h>
19#include <linux/types.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/pci.h>
23#include <linux/sched.h>
24#include <linux/ioport.h>
25#include <linux/errno.h>
26#include <linux/irq.h>
27#include <linux/delay.h>
28
29#include <asm/machvec.h>
30#include <asm/io.h>
31#include "pci-sh7780.h"
32
33static unsigned int pci_probe = PCI_PROBE_CONF1;
34extern int pci_fixup_pcic(void);
35
36/*
37 * Direct access to PCI hardware...
38 */
39
40#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
41
42/*
43 * Functions for accessing PCI configuration space with type 1 accesses
44 */
45static int sh7780_pci_read(struct pci_bus *bus, unsigned int devfn,
46 int where, int size, u32 *val)
47{
48 unsigned long flags;
49 u32 data;
50
51 /*
52 * PCIPDR may only be accessed as 32 bit words,
53 * so we must do byte alignment by hand
54 */
55 local_irq_save(flags);
56 outl(CONFIG_CMD(bus, devfn, where), PCI_REG(SH7780_PCIPAR));
57 data = inl(PCI_REG(SH7780_PCIPDR));
58 local_irq_restore(flags);
59
60 switch (size) {
61 case 1:
62 *val = (data >> ((where & 3) << 3)) & 0xff;
63 break;
64 case 2:
65 *val = (data >> ((where & 2) << 3)) & 0xffff;
66 break;
67 case 4:
68 *val = data;
69 break;
70 default:
71 return PCIBIOS_FUNC_NOT_SUPPORTED;
72 }
73
74 return PCIBIOS_SUCCESSFUL;
75}
76
77/*
78 * Since SH7780 only does 32bit access we'll have to do a read,
79 * mask,write operation.
80 * We'll allow an odd byte offset, though it should be illegal.
81 */
82static int sh7780_pci_write(struct pci_bus *bus, unsigned int devfn,
83 int where, int size, u32 val)
84{
85 unsigned long flags;
86 int shift;
87 u32 data;
88
89 local_irq_save(flags);
90 outl(CONFIG_CMD(bus, devfn, where), PCI_REG(SH7780_PCIPAR));
91 data = inl(PCI_REG(SH7780_PCIPDR));
92 local_irq_restore(flags);
93
94 switch (size) {
95 case 1:
96 shift = (where & 3) << 3;
97 data &= ~(0xff << shift);
98 data |= ((val & 0xff) << shift);
99 break;
100 case 2:
101 shift = (where & 2) << 3;
102 data &= ~(0xffff << shift);
103 data |= ((val & 0xffff) << shift);
104 break;
105 case 4:
106 data = val;
107 break;
108 default:
109 return PCIBIOS_FUNC_NOT_SUPPORTED;
110 }
111
112 outl(data, PCI_REG(SH7780_PCIPDR));
113
114 return PCIBIOS_SUCCESSFUL;
115}
116
117#undef CONFIG_CMD
118
119struct pci_ops sh7780_pci_ops = {
120 .read = sh7780_pci_read,
121 .write = sh7780_pci_write,
122};
123
124static int __init pci_check_direct(void)
125{
126 unsigned int tmp, id;
127
128 outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
129
130 /* check for SH7780/SH7780R hardware */
131 id = inl(PCI_REG(SH7780_PCIVID));
132 if ((id != ((SH7780_DEVICE_ID << 16) | SH7780_VENDOR_ID)) &&
133 (id != ((SH7781_DEVICE_ID << 16) | SH7780_VENDOR_ID))) {
134 printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
135 return -ENODEV;
136 }
137
138 /*
139 * Check if configuration works.
140 */
141 if (pci_probe & PCI_PROBE_CONF1) {
142 tmp = inl(PCI_REG(SH7780_PCIPAR));
143 outl(0x80000000, PCI_REG(SH7780_PCIPAR));
144 if (inl(PCI_REG(SH7780_PCIPAR)) == 0x80000000) {
145 outl(tmp, PCI_REG(SH7780_PCIPAR));
146 printk(KERN_INFO "PCI: Using configuration type 1\n");
147 request_region(PCI_REG(SH7780_PCIPAR), 8, "PCI conf1");
148 return 0;
149 }
150 outl(tmp, PCI_REG(SH7780_PCIPAR));
151 }
152
153 pr_debug("PCI: pci_check_direct failed\n");
154 return -EINVAL;
155}
156
157/***************************************************************************************/
158
159/*
160 * Handle bus scanning and fixups ....
161 */
162
163static void __init pci_fixup_ide_bases(struct pci_dev *d)
164{
165 int i;
166
167 /*
168 * PCI IDE controllers use non-standard I/O port decoding, respect it.
169 */
170 if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
171 return;
172 pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
173 for(i=0; i<4; i++) {
174 struct resource *r = &d->resource[i];
175 if ((r->start & ~0x80) == 0x374) {
176 r->start |= 2;
177 r->end = r->start;
178 }
179 }
180}
181
182DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
183
184/*
185 * Called after each bus is probed, but before its children
186 * are examined.
187 */
188
189void __init pcibios_fixup_bus(struct pci_bus *b)
190{
191 pci_read_bridge_bases(b);
192}
193
194/*
195 * Initialization. Try all known PCI access methods. Note that we support
196 * using both PCI BIOS and direct access: in such cases, we use I/O ports
197 * to access config space.
198 *
199 * Note that the platform specific initialization (BSC registers, and memory
200 * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
201 * exists and via the platform defined function pcibios_init_platform().
202 * See pci_bigsur.c for implementation;
203 *
204 * The BIOS version of the pci functions is not yet implemented but it is left
205 * in for completeness. Currently an error will be genereated at compile time.
206 */
207
208static int __init sh7780_pci_init(void)
209{
210 int ret;
211
212 pr_debug("PCI: Starting intialization.\n");
213
214 /* Setup the INTC */
215 ctrl_outl(0x00200000, INTC_ICR0); /* INTC SH-4 Mode */
216 ctrl_outl(0x00078000, INTC_INT2MSKCR); /* enable PCIINTA - PCIINTD */
217 ctrl_outl(0x40000000, INTC_INTMSK1); /* disable IRL4-7 Interrupt */
218 ctrl_outl(0x0000fffe, INTC_INTMSK2); /* disable IRL4-7 Interrupt */
219 ctrl_outl(0x80000000, INTC_INTMSKCLR1); /* enable IRL0-3 Interrupt */
220 ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); /* enable IRL0-3 Interrupt */
221
222 if ((ret = pci_check_direct()) != 0)
223 return ret;
224
225 return pcibios_init_platform();
226}
227
228core_initcall(sh7780_pci_init);
229
230int __init sh7780_pcic_init(struct sh7780_pci_address_map *map)
231{
232 u32 word;
233
234 /*
235 * This code is unused for some boards as it is done in the
236 * bootloader and doing it here means the MAC addresses loaded
237 * by the bootloader get lost.
238 */
239 if (!(map->flags & SH7780_PCIC_NO_RESET)) {
240 /* toggle PCI reset pin */
241 word = SH7780_PCICR_PREFIX | SH7780_PCICR_PRST;
242 outl(word,PCI_REG(SH7780_PCICR));
243 /* Wait for a long time... not 1 sec. but long enough */
244 mdelay(100);
245 word = SH7780_PCICR_PREFIX;
246 outl(word,PCI_REG(SH7780_PCICR));
247 }
248
249 /* set the command/status bits to:
250 * Wait Cycle Control + Parity Enable + Bus Master +
251 * Mem space enable
252 */
253 outl(0x00000046, PCI_REG(SH7780_PCICMD));
254
255 /* define this host as the host bridge */
256 word = SH7780_PCI_HOST_BRIDGE << 24;
257 outl(word, PCI_REG(SH7780_PCIRID));
258
259 /* Set IO and Mem windows to local address
260 * Make PCI and local address the same for easy 1 to 1 mapping
261 * Window0 = map->window0.size @ non-cached area base = SDRAM
262 * Window1 = map->window1.size @ cached area base = SDRAM
263 */
264 word = ((map->window0.size - 1) & 0x1ff00001) | 0x01;
265 outl(0x07f00001, PCI_REG(SH7780_PCILSR0));
266 word = ((map->window1.size - 1) & 0x1ff00001) | 0x01;
267 outl(0x00000001, PCI_REG(SH7780_PCILSR1));
268 /* Set the values on window 0 PCI config registers */
269 word = P2SEGADDR(map->window0.base);
270 outl(0xa8000000, PCI_REG(SH7780_PCILAR0));
271 outl(0x08000000, PCI_REG(SH7780_PCIMBAR0));
272 /* Set the values on window 1 PCI config registers */
273 word = P2SEGADDR(map->window1.base);
274 outl(0x00000000, PCI_REG(SH7780_PCILAR1));
275 outl(0x00000000, PCI_REG(SH7780_PCIMBAR1));
276
277 /* Map IO space into PCI IO window
278 * The IO window is 64K-PCIBIOS_MIN_IO in size
279 * IO addresses will be translated to the
280 * PCI IO window base address
281 */
282 PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
283 (64*1024), SH7780_PCI_IO_BASE+PCIBIOS_MIN_IO);
284
285 /* NOTE: I'm ignoring the PCI error IRQs for now..
286 * TODO: add support for the internal error interrupts and
287 * DMA interrupts...
288 */
289
290#ifdef CONFIG_SH_R7780RP
291 pci_fixup_pcic();
292#endif
293
294 /* SH7780 init done, set central function init complete */
295 /* use round robin mode to stop a device starving/overruning */
296 word = SH7780_PCICR_PREFIX | SH7780_PCICR_CFIN | /* SH7780_PCICR_ARBM |*/ SH7780_PCICR_FTO;
297 outl(word, PCI_REG(SH7780_PCICR));
298
299 return 1;
300}
301
302char * __init pcibios_setup(char *str)
303{
304 if (!strcmp(str, "off")) {
305 pci_probe = 0;
306 return NULL;
307 }
308
309 return str;
310}
311
312/*
313 * IRQ functions
314 */
315static u8 __init sh7780_no_swizzle(struct pci_dev *dev, u8 *pin)
316{
317 /* no swizzling */
318 return PCI_SLOT(dev->devfn);
319}
320
321static int sh7780_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
322{
323 int irq = -1;
324
325 /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
326 irq = pcibios_map_platform_irq(slot,pin);
327 if( irq < 0 ) {
328 pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
329 return irq;
330 }
331
332 pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
333
334 return irq;
335}
336
337void __init pcibios_fixup_irqs(void)
338{
339 pci_fixup_irqs(sh7780_no_swizzle, sh7780_pci_lookup_irq);
340}
341
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
new file mode 100644
index 000000000000..750d5d7753a2
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7780.h
@@ -0,0 +1,168 @@
1/*
2 * Low-Level PCI Support for SH7780 targets
3 *
4 * Dustin McIntire (dustin@sensoria.com) (c) 2001
5 * Paul Mundt (lethal@linux-sh.org) (c) 2003
6 *
7 * May be copied or modified under the terms of the GNU General Public
8 * License. See linux/COPYING for more information.
9 *
10 */
11
12#ifndef _PCI_SH7780_H_
13#define _PCI_SH7780_H_
14
15#include <linux/pci.h>
16
17/* set debug level 4=verbose...1=terse */
18//#define DEBUG_PCI 3
19#undef DEBUG_PCI
20
21#ifdef DEBUG_PCI
22#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
23#else
24#define PCIDBG(n, x...)
25#endif
26
27/* startup values */
28#define PCI_PROBE_BIOS 1
29#define PCI_PROBE_CONF1 2
30#define PCI_PROBE_CONF2 4
31#define PCI_NO_SORT 0x100
32#define PCI_BIOS_SORT 0x200
33#define PCI_NO_CHECKS 0x400
34#define PCI_ASSIGN_ROMS 0x1000
35#define PCI_BIOS_IRQ_SCAN 0x2000
36
37/* Platform Specific Values */
38#define SH7780_VENDOR_ID 0x1912
39#define SH7780_DEVICE_ID 0x0002
40#define SH7781_DEVICE_ID 0x0001
41
42/* SH7780 Control Registers */
43#define SH7780_PCI_VCR0 0xFE000000
44#define SH7780_PCI_VCR1 0xFE000004
45#define SH7780_PCI_VCR2 0xFE000008
46
47/* SH7780 Specific Values */
48#define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
49#define SH7780_PCI_CONFIG_SIZE 0x01000000 /* Config space size */
50#define SH7780_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */
51#define SH7780_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */
52#if 1
53#define SH7780_PCI_IO_BASE 0xFE400000 /* IO space base address */
54#define SH7780_PCI_IO_SIZE 0x00400000 /* Size of IO window */
55#else
56#define SH7780_PCI_IO_BASE 0xFE200000 /* IO space base address */
57#define SH7780_PCI_IO_SIZE 0x00200000 /* Size of IO window */
58#endif
59
60#define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */
61#define PCI_REG(n) (SH7780_PCIREG_BASE+n)
62
63/* SH7780 PCI Config Registers */
64#define SH7780_PCIVID 0x000 /* Vendor ID */
65#define SH7780_PCIDID 0x002 /* Device ID */
66#define SH7780_PCICMD 0x004 /* Command */
67#define SH7780_PCISTATUS 0x006 /* Status */
68#define SH7780_PCIRID 0x008 /* Revision ID */
69#define SH7780_PCIPIF 0x009 /* Program Interface */
70#define SH7780_PCISUB 0x00a /* Sub class code */
71#define SH7780_PCIBCC 0x00b /* Base class code */
72#define SH7780_PCICLS 0x00c /* Cache line size */
73#define SH7780_PCILTM 0x00d /* latency timer */
74#define SH7780_PCIHDR 0x00e /* Header type */
75#define SH7780_PCIBIST 0x00f /* BIST */
76#define SH7780_PCIIBAR 0x010 /* IO Base address */
77#define SH7780_PCIMBAR0 0x014 /* Memory base address0 */
78#define SH7780_PCIMBAR1 0x018 /* Memory base address1 */
79#define SH7780_PCISVID 0x02c /* Sub system vendor ID */
80#define SH7780_PCISID 0x02e /* Sub system ID */
81#define SH7780_PCICP 0x034
82#define SH7780_PCIINTLINE 0x03c /* Interrupt line */
83#define SH7780_PCIINTPIN 0x03d /* Interrupt pin */
84#define SH7780_PCIMINGNT 0x03e /* Minumum grand */
85#define SH7780_PCIMAXLAT 0x03f /* Maxmum latency */
86#define SH7780_PCICID 0x040
87#define SH7780_PCINIP 0x041
88#define SH7780_PCIPMC 0x042
89#define SH7780_PCIPMCSR 0x044
90#define SH7780_PCIPMCSR_BSE 0x046
91#define SH7780_PCICDD 0x047
92
93/* SH7780 PCI Local Registers */
94#define SH7780_PCICR 0x100 /* PCI Control Register */
95 #define SH7780_PCICR_PREFIX 0xA5000000 /* CR prefix for write */
96 #define SH7780_PCICR_PFCS 0x00000800 /* TRDY/IRDY Enable */
97 #define SH7780_PCICR_FTO 0x00000400 /* TRDY/IRDY Enable */
98 #define SH7780_PCICR_PFE 0x00000200 /* Target Read Single */
99 #define SH7780_PCICR_TBS 0x00000100 /* Target Byte Swap */
100 #define SH7780_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */
101 #define SH7780_PCICR_IOCS 0x00000004 /* INTA output assert */
102 #define SH7780_PCICR_PRST 0x00000002 /* PCI Reset Assert */
103 #define SH7780_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */
104#define SH7780_PCILSR0 0x104 /* PCI Local Space Register0 */
105#define SH7780_PCILSR1 0x108 /* PCI Local Space Register1 */
106#define SH7780_PCILAR0 0x10C /* PCI Local Address Register1 */
107#define SH7780_PCILAR1 0x110 /* PCI Local Address Register1 */
108#define SH7780_PCIIR 0x114 /* PCI Interrupt Register */
109#define SH7780_PCIIMR 0x118 /* PCI Interrupt Mask Register */
110#define SH7780_PCIAIR 0x11C /* Error Address Register */
111#define SH7780_PCICIR 0x120 /* Error Command/Data Register */
112#define SH7780_PCIAINT 0x130 /* Arbiter Interrupt Register */
113#define SH7780_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
114#define SH7780_PCIBMIR 0x138 /* Error Bus Master Register */
115#define SH7780_PCIPAR 0x1C0 /* PIO Address Register */
116#define SH7780_PCIPINT 0x1CC /* Power Management Int. Register */
117#define SH7780_PCIPINTM 0x1D0 /* Power Management Mask Register */
118#define SH7780_PCIMBR0 0x1E0 /* Memory Bank0 Register */
119#define SH7780_PCIMBMR0 0x1E4 /* Memory Bank0 Mask Register */
120#define SH7780_PCIMBR1 0x1E8 /* Memory Bank1 Register */
121#define SH7780_PCIMBMR1 0x1EC /* Memory Bank1 Mask Register */
122#define SH7780_PCIMBR2 0x1F0 /* Memory Bank2 Register */
123#define SH7780_PCIMBMR2 0x1F4 /* Memory Bank2 Mask Register */
124#define SH7780_PCIIOBR 0x1F8 /* Bank Register */
125#define SH7780_PCIIOBMR 0x1FC /* Bank Mask Register */
126#define SH7780_PCICSCR0 0x210 /* Cache Snoop1 Cnt. Register */
127#define SH7780_PCICSCR1 0x214 /* Cache Snoop2 Cnt. Register */
128#define SH7780_PCICSAR0 0x218 /* Cache Snoop1 Addr. Register */
129#define SH7780_PCICSAR1 0x21C /* Cache Snoop2 Addr. Register */
130#define SH7780_PCIPDR 0x220 /* Port IO Data Register */
131
132/* General Memory Config Addresses */
133#define SH7780_CS0_BASE_ADDR 0x0
134#define SH7780_MEM_REGION_SIZE 0x04000000
135#define SH7780_CS1_BASE_ADDR (SH7780_CS0_BASE_ADDR + SH7780_MEM_REGION_SIZE)
136#define SH7780_CS2_BASE_ADDR (SH7780_CS1_BASE_ADDR + SH7780_MEM_REGION_SIZE)
137#define SH7780_CS3_BASE_ADDR (SH7780_CS2_BASE_ADDR + SH7780_MEM_REGION_SIZE)
138#define SH7780_CS4_BASE_ADDR (SH7780_CS3_BASE_ADDR + SH7780_MEM_REGION_SIZE)
139#define SH7780_CS5_BASE_ADDR (SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE)
140#define SH7780_CS6_BASE_ADDR (SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE)
141
142/* General PCI values */
143#define SH7780_PCI_HOST_BRIDGE 0x6
144
145/* Flags */
146#define SH7780_PCIC_NO_RESET 0x0001
147
148/* External functions defined per platform i.e. Big Sur, SE... (these could be routed
149 * through the machine vectors... */
150extern int pcibios_init_platform(void);
151extern int pcibios_map_platform_irq(u8 slot, u8 pin);
152
153struct sh7780_pci_address_space {
154 unsigned long base;
155 unsigned long size;
156};
157
158struct sh7780_pci_address_map {
159 struct sh7780_pci_address_space window0;
160 struct sh7780_pci_address_space window1;
161 unsigned long flags;
162};
163
164/* arch/sh/drivers/pci/pci-sh7780.c */
165extern int sh7780_pcic_init(struct sh7780_pci_address_map *map);
166
167#endif /* _PCI_SH7780_H_ */
168