diff options
Diffstat (limited to 'arch/mips/pci')
62 files changed, 8147 insertions, 0 deletions
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile new file mode 100644 index 000000000000..c53e4cb359ba --- /dev/null +++ b/arch/mips/pci/Makefile | |||
@@ -0,0 +1,54 @@ | |||
1 | # | ||
2 | # Makefile for the PCI specific kernel interface routines under Linux. | ||
3 | # | ||
4 | |||
5 | obj-y += pci.o | ||
6 | |||
7 | # | ||
8 | # PCI bus host bridge specific code | ||
9 | # | ||
10 | obj-$(CONFIG_ITE_BOARD_GEN) += ops-it8172.o | ||
11 | obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o | ||
12 | obj-$(CONFIG_MIPS_GT64111) += ops-gt64111.o | ||
13 | obj-$(CONFIG_MIPS_GT64120) += ops-gt64120.o | ||
14 | obj-$(CONFIG_MIPS_GT96100) += ops-gt96100.o | ||
15 | obj-$(CONFIG_PCI_MARVELL) += ops-marvell.o | ||
16 | obj-$(CONFIG_MIPS_MSC) += ops-msc.o | ||
17 | obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o | ||
18 | obj-$(CONFIG_MIPS_TX3927) += ops-jmr3927.o | ||
19 | obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o | ||
20 | obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o | ||
21 | |||
22 | # | ||
23 | # These are still pretty much in the old state, watch, go blind. | ||
24 | # | ||
25 | obj-$(CONFIG_DDB5074) += fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o | ||
26 | obj-$(CONFIG_DDB5476) += ops-ddb5476.o pci-ddb5476.o | ||
27 | obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o | ||
28 | obj-$(CONFIG_LASAT) += pci-lasat.o | ||
29 | obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o | ||
30 | obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o | ||
31 | obj-$(CONFIG_MIPS_EV96100) += fixup-ev64120.o | ||
32 | obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o pci-ev96100.o | ||
33 | obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o | ||
34 | obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o | ||
35 | obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o | ||
36 | obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o | ||
37 | obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o | ||
38 | obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o | ||
39 | obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o | ||
40 | obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o | ||
41 | obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o | ||
42 | obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o | ||
43 | obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ | ||
44 | pci-yosemite.o | ||
45 | obj-$(CONFIG_SGI_IP27) += pci-ip27.o | ||
46 | obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o | ||
47 | obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o | ||
48 | obj-$(CONFIG_SNI_RM200_PCI) += fixup-sni.o ops-sni.o | ||
49 | obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o | ||
50 | obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o | ||
51 | obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o pci-jmr3927.o | ||
52 | obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o | ||
53 | obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o | ||
54 | obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o | ||
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c new file mode 100644 index 000000000000..2406835833d6 --- /dev/null +++ b/arch/mips/pci/fixup-atlas.c | |||
@@ -0,0 +1,69 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/pci.h> | ||
4 | #include <asm/mips-boards/atlasint.h> | ||
5 | |||
6 | #define INTD ATLASINT_INTD | ||
7 | #define INTC ATLASINT_INTC | ||
8 | #define INTB ATLASINT_INTB | ||
9 | #define INTA ATLASINT_INTA | ||
10 | #define SCSI ATLASINT_SCSI | ||
11 | #define ETH ATLASINT_ETH | ||
12 | |||
13 | static char irq_tab[][5] __initdata = { | ||
14 | /* INTA INTB INTC INTD */ | ||
15 | {0, 0, 0, 0, 0 }, /* 0: Unused */ | ||
16 | {0, 0, 0, 0, 0 }, /* 1: Unused */ | ||
17 | {0, 0, 0, 0, 0 }, /* 2: Unused */ | ||
18 | {0, 0, 0, 0, 0 }, /* 3: Unused */ | ||
19 | {0, 0, 0, 0, 0 }, /* 4: Unused */ | ||
20 | {0, 0, 0, 0, 0 }, /* 5: Unused */ | ||
21 | {0, 0, 0, 0, 0 }, /* 6: Unused */ | ||
22 | {0, 0, 0, 0, 0 }, /* 7: Unused */ | ||
23 | {0, 0, 0, 0, 0 }, /* 8: Unused */ | ||
24 | {0, 0, 0, 0, 0 }, /* 9: Unused */ | ||
25 | {0, 0, 0, 0, 0 }, /* 10: Unused */ | ||
26 | {0, 0, 0, 0, 0 }, /* 11: Unused */ | ||
27 | {0, 0, 0, 0, 0 }, /* 12: Unused */ | ||
28 | {0, 0, 0, 0, 0 }, /* 13: Unused */ | ||
29 | {0, 0, 0, 0, 0 }, /* 14: Unused */ | ||
30 | {0, 0, 0, 0, 0 }, /* 15: Unused */ | ||
31 | {0, SCSI, 0, 0, 0 }, /* 16: SYM53C810A SCSI */ | ||
32 | {0, 0, 0, 0, 0 }, /* 17: Core */ | ||
33 | {0, INTA, INTB, INTC, INTD }, /* 18: PCI Slot 1 */ | ||
34 | {0, ETH, 0, 0, 0 }, /* 19: SAA9730 Ethernet */ | ||
35 | {0, 0, 0, 0, 0 }, /* 20: PCI Slot 3 */ | ||
36 | {0, 0, 0, 0, 0 } /* 21: PCI Slot 4 */ | ||
37 | }; | ||
38 | |||
39 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
40 | { | ||
41 | return irq_tab[slot][pin]; | ||
42 | } | ||
43 | |||
44 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
45 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | #ifdef CONFIG_KGDB | ||
51 | /* | ||
52 | * The PCI scan may have moved the saa9730 I/O address, so reread | ||
53 | * the address here. | ||
54 | * This does mean that it's not possible to debug the PCI bus configuration | ||
55 | * code, but it is better than nothing... | ||
56 | */ | ||
57 | |||
58 | static void atlas_saa9730_base_fixup (struct pci_dev *pdev) | ||
59 | { | ||
60 | extern void *saa9730_base; | ||
61 | if (pdev->bus == 0 && PCI_SLOT(pdev->devfn) == 19) | ||
62 | (void) pci_read_config_dword (pdev, 0x14, (u32 *)&saa9730_base); | ||
63 | printk ("saa9730_base = %x\n", saa9730_base); | ||
64 | } | ||
65 | |||
66 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730, | ||
67 | atlas_saa9730_base_fixup); | ||
68 | |||
69 | #endif | ||
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c new file mode 100644 index 000000000000..39fe2b16fcec --- /dev/null +++ b/arch/mips/pci/fixup-au1000.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * BRIEF MODULE DESCRIPTION | ||
3 | * Board specific pci fixups. | ||
4 | * | ||
5 | * Copyright 2001-2003 MontaVista Software Inc. | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * ppopov@mvista.com or source@mvista.com | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
17 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
20 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | #include <linux/config.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <asm/mach-au1x00/au1000.h> | ||
36 | |||
37 | /* | ||
38 | * Shortcut | ||
39 | */ | ||
40 | #ifdef CONFIG_SOC_AU1500 | ||
41 | #define INTA AU1000_PCI_INTA | ||
42 | #define INTB AU1000_PCI_INTB | ||
43 | #define INTC AU1000_PCI_INTC | ||
44 | #define INTD AU1000_PCI_INTD | ||
45 | #endif | ||
46 | |||
47 | #ifdef CONFIG_SOC_AU1550 | ||
48 | #define INTA AU1550_PCI_INTA | ||
49 | #define INTB AU1550_PCI_INTB | ||
50 | #define INTC AU1550_PCI_INTC | ||
51 | #define INTD AU1550_PCI_INTD | ||
52 | #endif | ||
53 | |||
54 | #define INTX 0xFF /* not valid */ | ||
55 | |||
56 | #ifdef CONFIG_MIPS_DB1500 | ||
57 | static char irq_tab_alchemy[][5] __initdata = { | ||
58 | [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - HPT371 */ | ||
59 | [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ | ||
60 | }; | ||
61 | #endif | ||
62 | |||
63 | #ifdef CONFIG_MIPS_BOSPORUS | ||
64 | static char irq_tab_alchemy[][5] __initdata = { | ||
65 | [11] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 11 - miniPCI */ | ||
66 | [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - SN1741 */ | ||
67 | [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ | ||
68 | }; | ||
69 | #endif | ||
70 | |||
71 | #ifdef CONFIG_MIPS_MIRAGE | ||
72 | static char irq_tab_alchemy[][5] __initdata = { | ||
73 | [11] = { -1, INTD, INTX, INTX, INTX}, /* IDSEL 11 - SMI VGX */ | ||
74 | [12] = { -1, INTX, INTX, INTC, INTX}, /* IDSEL 12 - PNX1300 */ | ||
75 | [13] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 13 - miniPCI */ | ||
76 | }; | ||
77 | #endif | ||
78 | |||
79 | #ifdef CONFIG_MIPS_DB1550 | ||
80 | static char irq_tab_alchemy[][5] __initdata = { | ||
81 | [11] = { -1, INTC, INTX, INTX, INTX}, /* IDSEL 11 - on-board HPT371 */ | ||
82 | [12] = { -1, INTB, INTC, INTD, INTA}, /* IDSEL 12 - PCI slot 2 (left) */ | ||
83 | [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ | ||
84 | }; | ||
85 | #endif | ||
86 | |||
87 | #ifdef CONFIG_MIPS_PB1500 | ||
88 | static char irq_tab_alchemy[][5] __initdata = { | ||
89 | [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - HPT370 */ | ||
90 | [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ | ||
91 | }; | ||
92 | #endif | ||
93 | |||
94 | #ifdef CONFIG_MIPS_PB1550 | ||
95 | static char irq_tab_alchemy[][5] __initdata = { | ||
96 | [12] = { -1, INTB, INTC, INTD, INTA}, /* IDSEL 12 - PCI slot 2 (left) */ | ||
97 | [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ | ||
98 | }; | ||
99 | #endif | ||
100 | |||
101 | #ifdef CONFIG_MIPS_MTX1 | ||
102 | static char irq_tab_alchemy[][5] __initdata = { | ||
103 | [0] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 00 - AdapterA-Slot0 (top) */ | ||
104 | [1] = { -1, INTB, INTA, INTX, INTX}, /* IDSEL 01 - AdapterA-Slot1 (bottom) */ | ||
105 | [2] = { -1, INTC, INTD, INTX, INTX}, /* IDSEL 02 - AdapterB-Slot0 (top) */ | ||
106 | [3] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 03 - AdapterB-Slot1 (bottom) */ | ||
107 | [4] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 04 - AdapterC-Slot0 (top) */ | ||
108 | [5] = { -1, INTB, INTA, INTX, INTX}, /* IDSEL 05 - AdapterC-Slot1 (bottom) */ | ||
109 | [6] = { -1, INTC, INTD, INTX, INTX}, /* IDSEL 06 - AdapterD-Slot0 (top) */ | ||
110 | [7] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 07 - AdapterD-Slot1 (bottom) */ | ||
111 | }; | ||
112 | #endif | ||
113 | |||
114 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
115 | { | ||
116 | return irq_tab_alchemy[slot][pin]; | ||
117 | } | ||
118 | |||
119 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
120 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
121 | { | ||
122 | return 0; | ||
123 | } | ||
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c new file mode 100644 index 000000000000..f2fc82c1c7c5 --- /dev/null +++ b/arch/mips/pci/fixup-capcella.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups. | ||
3 | * | ||
4 | * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/pci.h> | ||
22 | |||
23 | #include <asm/vr41xx/capcella.h> | ||
24 | |||
25 | /* | ||
26 | * Shortcuts | ||
27 | */ | ||
28 | #define INT1 RTL8139_1_IRQ | ||
29 | #define INT2 RTL8139_2_IRQ | ||
30 | #define INTA PC104PLUS_INTA_IRQ | ||
31 | #define INTB PC104PLUS_INTB_IRQ | ||
32 | #define INTC PC104PLUS_INTC_IRQ | ||
33 | #define INTD PC104PLUS_INTD_IRQ | ||
34 | |||
35 | static char irq_tab_capcella[][5] __initdata = { | ||
36 | [11] = { -1, INT1, INT1, INT1, INT1 }, | ||
37 | [12] = { -1, INT2, INT2, INT2, INT2 }, | ||
38 | [14] = { -1, INTA, INTB, INTC, INTD } | ||
39 | }; | ||
40 | |||
41 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
42 | { | ||
43 | return irq_tab_capcella[slot][pin]; | ||
44 | } | ||
45 | |||
46 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
47 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c new file mode 100644 index 000000000000..57e1ca2116bb --- /dev/null +++ b/arch/mips/pci/fixup-cobalt.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Cobalt Qube/Raq PCI support | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 1995, 1996, 1997, 2002, 2003 by Ralf Baechle | ||
9 | * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/pci.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | #include <asm/pci.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/gt64120.h> | ||
19 | |||
20 | #include <asm/cobalt/cobalt.h> | ||
21 | |||
22 | extern int cobalt_board_id; | ||
23 | |||
24 | static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) | ||
25 | { | ||
26 | unsigned short cfgword; | ||
27 | unsigned char lt; | ||
28 | |||
29 | /* Enable Bus Mastering and fast back to back. */ | ||
30 | pci_read_config_word(dev, PCI_COMMAND, &cfgword); | ||
31 | cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER); | ||
32 | pci_write_config_word(dev, PCI_COMMAND, cfgword); | ||
33 | |||
34 | /* Enable both ide interfaces. ROM only enables primary one. */ | ||
35 | pci_write_config_byte(dev, 0x40, 0xb); | ||
36 | |||
37 | /* Set latency timer to reasonable value. */ | ||
38 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, <); | ||
39 | if (lt < 64) | ||
40 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); | ||
41 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); | ||
42 | } | ||
43 | |||
44 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, | ||
45 | qube_raq_via_bmIDE_fixup); | ||
46 | |||
47 | static void qube_raq_galileo_fixup(struct pci_dev *dev) | ||
48 | { | ||
49 | unsigned short galileo_id; | ||
50 | |||
51 | /* Fix PCI latency-timer and cache-line-size values in Galileo | ||
52 | * host bridge. | ||
53 | */ | ||
54 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); | ||
55 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); | ||
56 | |||
57 | /* | ||
58 | * On all machines prior to Q2, we had the STOP line disconnected | ||
59 | * from Galileo to VIA on PCI. The new Galileo does not function | ||
60 | * correctly unless we have it connected. | ||
61 | * | ||
62 | * Therefore we must set the disconnect/retry cycle values to | ||
63 | * something sensible when using the new Galileo. | ||
64 | */ | ||
65 | pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id); | ||
66 | galileo_id &= 0xff; /* mask off class info */ | ||
67 | if (galileo_id >= 0x10) { | ||
68 | /* New Galileo, assumes PCI stop line to VIA is connected. */ | ||
69 | GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS); | ||
70 | } else if (galileo_id == 0x1 || galileo_id == 0x2) { | ||
71 | signed int timeo; | ||
72 | /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */ | ||
73 | timeo = GALILEO_INL(GT_PCI0_TOR_OFS); | ||
74 | /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */ | ||
75 | GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, | ||
80 | qube_raq_galileo_fixup); | ||
81 | |||
82 | static char irq_tab_cobalt[] __initdata = { | ||
83 | [COBALT_PCICONF_CPU] = 0, | ||
84 | [COBALT_PCICONF_ETH0] = COBALT_ETH0_IRQ, | ||
85 | [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ, | ||
86 | [COBALT_PCICONF_VIA] = 0, | ||
87 | [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ, | ||
88 | [COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ | ||
89 | }; | ||
90 | |||
91 | static char irq_tab_raq2[] __initdata = { | ||
92 | [COBALT_PCICONF_CPU] = 0, | ||
93 | [COBALT_PCICONF_ETH0] = COBALT_ETH0_IRQ, | ||
94 | [COBALT_PCICONF_RAQSCSI] = COBALT_RAQ_SCSI_IRQ, | ||
95 | [COBALT_PCICONF_VIA] = 0, | ||
96 | [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ, | ||
97 | [COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ | ||
98 | }; | ||
99 | |||
100 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
101 | { | ||
102 | if (cobalt_board_id == COBALT_BRD_ID_RAQ2) | ||
103 | return irq_tab_raq2[slot]; | ||
104 | |||
105 | return irq_tab_cobalt[slot]; | ||
106 | } | ||
107 | |||
108 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
109 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c new file mode 100644 index 000000000000..b345e528a53c --- /dev/null +++ b/arch/mips/pci/fixup-ddb5074.c | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * It's nice to have the LEDs on the GPIO pins available for debugging | ||
3 | */ | ||
4 | static void ddb5074_fixup(struct pci_dev *dev) | ||
5 | { | ||
6 | extern struct pci_dev *pci_pmu; | ||
7 | u8 t8; | ||
8 | |||
9 | pci_pmu = dev; /* for LEDs D2 and D3 */ | ||
10 | /* Program the lines for LEDs D2 and D3 to output */ | ||
11 | pci_read_config_byte(dev, 0x7d, &t8); | ||
12 | t8 |= 0xc0; | ||
13 | pci_write_config_byte(dev, 0x7d, t8); | ||
14 | /* Turn LEDs D2 and D3 off */ | ||
15 | pci_read_config_byte(dev, 0x7e, &t8); | ||
16 | t8 |= 0xc0; | ||
17 | pci_write_config_byte(dev, 0x7e, t8); | ||
18 | } | ||
19 | |||
20 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | ||
21 | ddb5074_fixup); | ||
diff --git a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c new file mode 100644 index 000000000000..6abdc88bab1e --- /dev/null +++ b/arch/mips/pci/fixup-ddb5477.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * Board specific pci fixups. | ||
5 | * | ||
6 | * Copyright 2001, 2002, 2003 MontaVista Software Inc. | ||
7 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
17 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
20 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | |||
30 | #include <linux/types.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | static void ddb5477_fixup(struct pci_dev *dev) | ||
36 | { | ||
37 | u8 old; | ||
38 | |||
39 | printk(KERN_NOTICE "Enabling ALI M1533/35 PS2 keyboard/mouse.\n"); | ||
40 | pci_read_config_byte(dev, 0x41, &old); | ||
41 | pci_write_config_byte(dev, 0x41, old | 0xd0); | ||
42 | } | ||
43 | |||
44 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | ||
45 | ddb5477_fixup); | ||
46 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535, | ||
47 | ddb5477_fixup); | ||
48 | |||
49 | /* | ||
50 | * Fixup baseboard AMD chip so that tx does not underflow. | ||
51 | * bcr_18 |= 0x0800 | ||
52 | * This sets NOUFLO bit which makes tx not start until whole pkt | ||
53 | * is fetched to the chip. | ||
54 | */ | ||
55 | #define PCNET32_WIO_RDP 0x10 | ||
56 | #define PCNET32_WIO_RAP 0x12 | ||
57 | #define PCNET32_WIO_RESET 0x14 | ||
58 | #define PCNET32_WIO_BDP 0x16 | ||
59 | |||
60 | static void ddb5477_amd_lance_fixup(struct pci_dev *dev) | ||
61 | { | ||
62 | unsigned long ioaddr; | ||
63 | u16 temp; | ||
64 | |||
65 | ioaddr = pci_resource_start(dev, 0); | ||
66 | |||
67 | inw(ioaddr + PCNET32_WIO_RESET); /* reset chip */ | ||
68 | |||
69 | /* bcr_18 |= 0x0800 */ | ||
70 | outw(18, ioaddr + PCNET32_WIO_RAP); | ||
71 | temp = inw(ioaddr + PCNET32_WIO_BDP); | ||
72 | temp |= 0x0800; | ||
73 | outw(18, ioaddr + PCNET32_WIO_RAP); | ||
74 | outw(temp, ioaddr + PCNET32_WIO_BDP); | ||
75 | } | ||
76 | |||
77 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, | ||
78 | ddb5477_amd_lance_fixup); | ||
diff --git a/arch/mips/pci/fixup-ev64120.c b/arch/mips/pci/fixup-ev64120.c new file mode 100644 index 000000000000..8dbb90d63f0a --- /dev/null +++ b/arch/mips/pci/fixup-ev64120.c | |||
@@ -0,0 +1,34 @@ | |||
1 | #include <linux/pci.h> | ||
2 | #include <linux/init.h> | ||
3 | |||
4 | int pci_range_ck(unsigned char bus, unsigned char dev) | ||
5 | { | ||
6 | if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) | ||
7 | return 0; | ||
8 | |||
9 | return -1; | ||
10 | } | ||
11 | |||
12 | /* | ||
13 | * After detecting all agents over the PCI , this function is called | ||
14 | * in order to give an interrupt number for each PCI device starting | ||
15 | * from IRQ 20. It does also enables master for each device. | ||
16 | */ | ||
17 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||
18 | { | ||
19 | unsigned int irq = 20; | ||
20 | struct pci_bus *current_bus = bus; | ||
21 | struct pci_dev *dev; | ||
22 | struct list_head *devices_link; | ||
23 | |||
24 | list_for_each(devices_link, &(current_bus->devices)) { | ||
25 | dev = pci_dev_b(devices_link); | ||
26 | if (dev != NULL) { | ||
27 | dev->irq = irq++; | ||
28 | |||
29 | /* Assign an interrupt number for the device */ | ||
30 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
31 | pcibios_set_master(dev); | ||
32 | } | ||
33 | } | ||
34 | } | ||
diff --git a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c new file mode 100644 index 000000000000..e2bc977b6d58 --- /dev/null +++ b/arch/mips/pci/fixup-ev96100.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * EV96100 Board specific pci fixups. | ||
5 | * | ||
6 | * Copyright 2001 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ppopov@mvista.com or source@mvista.com | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
18 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
21 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License along | ||
27 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
28 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | */ | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/pci.h> | ||
33 | |||
34 | static char irq_tab_ev96100[][5] __initdata = { | ||
35 | [8] = { 0, 5, 5, 5, 5 }, | ||
36 | [9] = { 0, 2, 2, 2, 2 } | ||
37 | }; | ||
38 | |||
39 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
40 | { | ||
41 | return irq_tab_ev96100[slot][pin]; | ||
42 | } | ||
43 | |||
44 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
45 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c new file mode 100644 index 000000000000..3e66b0aa63ca --- /dev/null +++ b/arch/mips/pci/fixup-ip32.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/pci.h> | ||
4 | #include <asm/ip32/ip32_ints.h> | ||
5 | /* | ||
6 | * O2 has up to 5 PCI devices connected into the MACE bridge. The device | ||
7 | * map looks like this: | ||
8 | * | ||
9 | * 0 aic7xxx 0 | ||
10 | * 1 aic7xxx 1 | ||
11 | * 2 expansion slot | ||
12 | * 3 N/C | ||
13 | * 4 N/C | ||
14 | */ | ||
15 | |||
16 | #define SCSI0 MACEPCI_SCSI0_IRQ | ||
17 | #define SCSI1 MACEPCI_SCSI1_IRQ | ||
18 | #define INTA0 MACEPCI_SLOT0_IRQ | ||
19 | #define INTA1 MACEPCI_SLOT1_IRQ | ||
20 | #define INTA2 MACEPCI_SLOT2_IRQ | ||
21 | #define INTB MACEPCI_SHARED0_IRQ | ||
22 | #define INTC MACEPCI_SHARED1_IRQ | ||
23 | #define INTD MACEPCI_SHARED2_IRQ | ||
24 | static char irq_tab_mace[][5] __initdata = { | ||
25 | /* Dummy INT#A INT#B INT#C INT#D */ | ||
26 | {0, 0, 0, 0, 0}, /* This is placeholder row - never used */ | ||
27 | {0, SCSI0, SCSI0, SCSI0, SCSI0}, | ||
28 | {0, SCSI1, SCSI1, SCSI1, SCSI1}, | ||
29 | {0, INTA0, INTB, INTC, INTD}, | ||
30 | {0, INTA1, INTC, INTD, INTB}, | ||
31 | {0, INTA2, INTD, INTB, INTC}, | ||
32 | }; | ||
33 | |||
34 | |||
35 | /* | ||
36 | * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of | ||
37 | * the device (1-4 => A-D), tell what irq to use. Note that we don't | ||
38 | * in theory have slots 4 and 5, and we never normally use the shared | ||
39 | * irqs. I suppose a device without a pin A will thank us for doing it | ||
40 | * right if there exists such a broken piece of crap. | ||
41 | */ | ||
42 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
43 | { | ||
44 | return irq_tab_mace[slot][pin]; | ||
45 | } | ||
46 | |||
47 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
48 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
diff --git a/arch/mips/pci/fixup-ite8172g.c b/arch/mips/pci/fixup-ite8172g.c new file mode 100644 index 000000000000..2290ea4228dd --- /dev/null +++ b/arch/mips/pci/fixup-ite8172g.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * BRIEF MODULE DESCRIPTION | ||
3 | * Board specific pci fixups. | ||
4 | * | ||
5 | * Copyright 2000 MontaVista Software Inc. | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * ppopov@mvista.com or source@mvista.com | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
17 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
20 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/init.h> | ||
33 | |||
34 | #include <asm/it8172/it8172.h> | ||
35 | #include <asm/it8172/it8172_pci.h> | ||
36 | #include <asm/it8172/it8172_int.h> | ||
37 | |||
38 | /* | ||
39 | * Shortcuts | ||
40 | */ | ||
41 | #define INTA IT8172_PCI_INTA_IRQ | ||
42 | #define INTB IT8172_PCI_INTB_IRQ | ||
43 | #define INTC IT8172_PCI_INTC_IRQ | ||
44 | #define INTD IT8172_PCI_INTD_IRQ | ||
45 | |||
46 | static const int internal_func_irqs[7] __initdata = { | ||
47 | IT8172_AC97_IRQ, | ||
48 | IT8172_DMA_IRQ, | ||
49 | IT8172_CDMA_IRQ, | ||
50 | IT8172_USB_IRQ, | ||
51 | IT8172_BRIDGE_MASTER_IRQ, | ||
52 | IT8172_IDE_IRQ, | ||
53 | IT8172_MC68K_IRQ | ||
54 | }; | ||
55 | |||
56 | static char irq_tab_ite8172g[][5] __initdata = { | ||
57 | [0x10] = { 0, INTA, INTB, INTC, INTD }, | ||
58 | [0x11] = { 0, INTA, INTB, INTC, INTD }, | ||
59 | [0x12] = { 0, INTB, INTC, INTD, INTA }, | ||
60 | [0x13] = { 0, INTC, INTD, INTA, INTB }, | ||
61 | [0x14] = { 0, INTD, INTA, INTB, INTC }, | ||
62 | }; | ||
63 | |||
64 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
65 | { | ||
66 | /* | ||
67 | * Internal device 1 is actually 7 different internal devices on the | ||
68 | * IT8172G (a multifunction device). | ||
69 | */ | ||
70 | if (slot == 1) | ||
71 | return internal_func_irqs[PCI_FUNC(dev->devfn)]; | ||
72 | |||
73 | return irq_tab_ite8172g[slot][pin]; | ||
74 | } | ||
75 | |||
76 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
77 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
78 | { | ||
79 | return 0; | ||
80 | } | ||
diff --git a/arch/mips/pci/fixup-ivr.c b/arch/mips/pci/fixup-ivr.c new file mode 100644 index 000000000000..0c7c16464c11 --- /dev/null +++ b/arch/mips/pci/fixup-ivr.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * Globespan IVR board-specific pci fixups. | ||
5 | * | ||
6 | * Copyright 2000 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ppopov@mvista.com or source@mvista.com | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
18 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
21 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License along | ||
27 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
28 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | */ | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <asm/it8172/it8172.h> | ||
36 | #include <asm/it8172/it8172_pci.h> | ||
37 | #include <asm/it8172/it8172_int.h> | ||
38 | |||
39 | /* | ||
40 | * Shortcuts | ||
41 | */ | ||
42 | #define INTA IT8172_PCI_INTA_IRQ | ||
43 | #define INTB IT8172_PCI_INTB_IRQ | ||
44 | #define INTC IT8172_PCI_INTC_IRQ | ||
45 | #define INTD IT8172_PCI_INTD_IRQ | ||
46 | |||
47 | static const int internal_func_irqs[7] __initdata = { | ||
48 | IT8172_AC97_IRQ, | ||
49 | IT8172_DMA_IRQ, | ||
50 | IT8172_CDMA_IRQ, | ||
51 | IT8172_USB_IRQ, | ||
52 | IT8172_BRIDGE_MASTER_IRQ, | ||
53 | IT8172_IDE_IRQ, | ||
54 | IT8172_MC68K_IRQ | ||
55 | }; | ||
56 | |||
57 | static char irq_tab_ivr[][5] __initdata = { | ||
58 | [0x11] = { INTC, INTC, INTD, INTA, INTB }, /* Realtek RTL-8139 */ | ||
59 | [0x12] = { INTB, INTB, INTB, INTC, INTC }, /* IVR slot */ | ||
60 | [0x13] = { INTA, INTA, INTB, INTC, INTD } /* Expansion slot */ | ||
61 | }; | ||
62 | |||
63 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
64 | { | ||
65 | if (slot == 1) | ||
66 | return internal_func_irqs[PCI_FUNC(dev->devfn)]; | ||
67 | |||
68 | return irq_tab_ivr[slot][pin]; | ||
69 | } | ||
70 | |||
71 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
72 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c new file mode 100644 index 000000000000..6c5e1d47179c --- /dev/null +++ b/arch/mips/pci/fixup-jaguar.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Marvell MV64340 interrupt fixup code. | ||
7 | * | ||
8 | * Marvell wants an NDA for their docs so this was written without | ||
9 | * documentation. You've been warned. | ||
10 | * | ||
11 | * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/pci.h> | ||
16 | |||
17 | #include <asm/mipsregs.h> | ||
18 | |||
19 | /* | ||
20 | * WARNING: Example of how _NOT_ to do it. | ||
21 | */ | ||
22 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
23 | { | ||
24 | int bus = dev->bus->number; | ||
25 | |||
26 | if (bus == 0 && slot == 1) | ||
27 | return 3; /* PCI-X A */ | ||
28 | if (bus == 0 && slot == 2) | ||
29 | return 4; /* PCI-X B */ | ||
30 | if (bus == 1 && slot == 1) | ||
31 | return 5; /* PCI A */ | ||
32 | if (bus == 1 && slot == 2) | ||
33 | return 6; /* PCI B */ | ||
34 | |||
35 | return 0; | ||
36 | panic("Whooops in pcibios_map_irq"); | ||
37 | } | ||
38 | |||
39 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
40 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c new file mode 100644 index 000000000000..f8696081c5b1 --- /dev/null +++ b/arch/mips/pci/fixup-jmr3927.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * Board specific pci fixups. | ||
5 | * | ||
6 | * Copyright 2001 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ppopov@mvista.com or source@mvista.com | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
18 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
21 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License along | ||
27 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
28 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | */ | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <asm/jmr3927/jmr3927.h> | ||
36 | |||
37 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
38 | { | ||
39 | unsigned char irq = pin; | ||
40 | |||
41 | /* IRQ rotation (PICMG) */ | ||
42 | irq--; /* 0-3 */ | ||
43 | if (dev->bus->parent == NULL && | ||
44 | slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) { | ||
45 | /* PCI CardSlot (IDSEL=A23, DevNu=12) */ | ||
46 | /* PCIA => PCIC (IDSEL=A23) */ | ||
47 | /* NOTE: JMR3927 JP1 must be set to OPEN */ | ||
48 | irq = (irq + 2) % 4; | ||
49 | } else if (dev->bus->parent == NULL && | ||
50 | slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) { | ||
51 | /* PCI CardSlot (IDSEL=A22, DevNu=11) */ | ||
52 | /* PCIA => PCIA (IDSEL=A22) */ | ||
53 | /* NOTE: JMR3927 JP1 must be set to OPEN */ | ||
54 | irq = (irq + 0) % 4; | ||
55 | } else { | ||
56 | /* PCI Backplane */ | ||
57 | irq = (irq + 3 + slot) % 4; | ||
58 | } | ||
59 | irq++; /* 1-4 */ | ||
60 | |||
61 | switch (irq) { | ||
62 | case 1: | ||
63 | irq = JMR3927_IRQ_IOC_PCIA; | ||
64 | break; | ||
65 | case 2: | ||
66 | // wrong for backplane irq = JMR3927_IRQ_IOC_PCIB; | ||
67 | irq = JMR3927_IRQ_IOC_PCID; | ||
68 | break; | ||
69 | case 3: | ||
70 | irq = JMR3927_IRQ_IOC_PCIC; | ||
71 | break; | ||
72 | case 4: | ||
73 | // wrong for backplane irq = JMR3927_IRQ_IOC_PCID; | ||
74 | irq = JMR3927_IRQ_IOC_PCIB; | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | /* Check OnBoard Ethernet (IDSEL=A24, DevNu=13) */ | ||
79 | if (dev->bus->parent == NULL && | ||
80 | slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) { | ||
81 | extern int jmr3927_ether1_irq; | ||
82 | /* check this irq line was reserved for ether1 */ | ||
83 | if (jmr3927_ether1_irq != JMR3927_IRQ_ETHER0) | ||
84 | irq = JMR3927_IRQ_ETHER0; | ||
85 | else | ||
86 | irq = 0; /* disable */ | ||
87 | } | ||
88 | return irq; | ||
89 | } | ||
90 | |||
91 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
92 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
98 | { | ||
99 | /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ | ||
100 | if (!(dev->vendor == PCI_VENDOR_ID_EFAR && | ||
101 | dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1)) | ||
102 | return pci_get_irq(dev, pin); | ||
103 | |||
104 | dev->irq = irq; | ||
105 | } | ||
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c new file mode 100644 index 000000000000..b9296d9942b3 --- /dev/null +++ b/arch/mips/pci/fixup-malta.c | |||
@@ -0,0 +1,103 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/pci.h> | ||
3 | |||
4 | /* PCI interrupt pins */ | ||
5 | #define PCIA 1 | ||
6 | #define PCIB 2 | ||
7 | #define PCIC 3 | ||
8 | #define PCID 4 | ||
9 | |||
10 | /* This table is filled in by interrogating the PIIX4 chip */ | ||
11 | static char pci_irq[5] __initdata; | ||
12 | |||
13 | static char irq_tab[][5] __initdata = { | ||
14 | /* INTA INTB INTC INTD */ | ||
15 | {0, 0, 0, 0, 0 }, /* 0: GT64120 PCI bridge */ | ||
16 | {0, 0, 0, 0, 0 }, /* 1: Unused */ | ||
17 | {0, 0, 0, 0, 0 }, /* 2: Unused */ | ||
18 | {0, 0, 0, 0, 0 }, /* 3: Unused */ | ||
19 | {0, 0, 0, 0, 0 }, /* 4: Unused */ | ||
20 | {0, 0, 0, 0, 0 }, /* 5: Unused */ | ||
21 | {0, 0, 0, 0, 0 }, /* 6: Unused */ | ||
22 | {0, 0, 0, 0, 0 }, /* 7: Unused */ | ||
23 | {0, 0, 0, 0, 0 }, /* 8: Unused */ | ||
24 | {0, 0, 0, 0, 0 }, /* 9: Unused */ | ||
25 | {0, 0, 0, 0, PCID }, /* 10: PIIX4 USB */ | ||
26 | {0, PCIB, 0, 0, 0 }, /* 11: AMD 79C973 Ethernet */ | ||
27 | {0, PCIC, 0, 0, 0 }, /* 12: Crystal 4281 Sound */ | ||
28 | {0, 0, 0, 0, 0 }, /* 13: Unused */ | ||
29 | {0, 0, 0, 0, 0 }, /* 14: Unused */ | ||
30 | {0, 0, 0, 0, 0 }, /* 15: Unused */ | ||
31 | {0, 0, 0, 0, 0 }, /* 16: Unused */ | ||
32 | {0, 0, 0, 0, 0 }, /* 17: Bonito/SOC-it PCI Bridge*/ | ||
33 | {0, PCIA, PCIB, PCIC, PCID }, /* 18: PCI Slot 1 */ | ||
34 | {0, PCIB, PCIC, PCID, PCIA }, /* 19: PCI Slot 2 */ | ||
35 | {0, PCIC, PCID, PCIA, PCIB }, /* 20: PCI Slot 3 */ | ||
36 | {0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */ | ||
37 | }; | ||
38 | |||
39 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
40 | { | ||
41 | int virq; | ||
42 | virq = irq_tab[slot][pin]; | ||
43 | return pci_irq[virq]; | ||
44 | } | ||
45 | |||
46 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
47 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static void __init malta_piix_func0_fixup(struct pci_dev *pdev) | ||
53 | { | ||
54 | unsigned char reg_val; | ||
55 | static int piixirqmap[16] __initdata = { /* PIIX PIRQC[A:D] irq mappings */ | ||
56 | 0, 0, 0, 3, | ||
57 | 4, 5, 6, 7, | ||
58 | 0, 9, 10, 11, | ||
59 | 12, 0, 14, 15 | ||
60 | }; | ||
61 | int i; | ||
62 | |||
63 | /* Interrogate PIIX4 to get PCI IRQ mapping */ | ||
64 | for (i = 0; i <= 3; i++) { | ||
65 | pci_read_config_byte(pdev, 0x60+i, ®_val); | ||
66 | if (reg_val & 0x80) | ||
67 | pci_irq[PCIA+i] = 0; /* Disabled */ | ||
68 | else | ||
69 | pci_irq[PCIA+i] = piixirqmap[reg_val & 15]; | ||
70 | } | ||
71 | |||
72 | /* Done by YAMON 2.00 onwards */ | ||
73 | if (PCI_SLOT(pdev->devfn) == 10) { | ||
74 | /* | ||
75 | * Set top of main memory accessible by ISA or DMA | ||
76 | * devices to 16 Mb. | ||
77 | */ | ||
78 | pci_read_config_byte(pdev, 0x69, ®_val); | ||
79 | pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, | ||
84 | malta_piix_func0_fixup); | ||
85 | |||
86 | static void __init malta_piix_func1_fixup(struct pci_dev *pdev) | ||
87 | { | ||
88 | unsigned char reg_val; | ||
89 | |||
90 | /* Done by YAMON 2.02 onwards */ | ||
91 | if (PCI_SLOT(pdev->devfn) == 10) { | ||
92 | /* | ||
93 | * IDE Decode enable. | ||
94 | */ | ||
95 | pci_read_config_byte(pdev, 0x41, ®_val); | ||
96 | pci_write_config_byte(pdev, 0x41, reg_val|0x80); | ||
97 | pci_read_config_byte(pdev, 0x43, ®_val); | ||
98 | pci_write_config_byte(pdev, 0x43, reg_val|0x80); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, | ||
103 | malta_piix_func1_fixup); | ||
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c new file mode 100644 index 000000000000..4975846da75a --- /dev/null +++ b/arch/mips/pci/fixup-mpc30x.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups. | ||
3 | * | ||
4 | * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/pci.h> | ||
22 | |||
23 | #include <asm/vr41xx/mpc30x.h> | ||
24 | #include <asm/vr41xx/vrc4173.h> | ||
25 | |||
26 | static const int internal_func_irqs[] __initdata = { | ||
27 | VRC4173_CASCADE_IRQ, | ||
28 | VRC4173_AC97_IRQ, | ||
29 | VRC4173_USB_IRQ, | ||
30 | }; | ||
31 | |||
32 | static const int irq_tab_mpc30x[] __initdata = { | ||
33 | [12] = VRC4173_PCMCIA1_IRQ, | ||
34 | [13] = VRC4173_PCMCIA2_IRQ, | ||
35 | [29] = MQ200_IRQ, | ||
36 | }; | ||
37 | |||
38 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
39 | { | ||
40 | if (slot == 30) | ||
41 | return internal_func_irqs[PCI_FUNC(dev->devfn)]; | ||
42 | |||
43 | return irq_tab_mpc30x[slot]; | ||
44 | } | ||
45 | |||
46 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
47 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c new file mode 100644 index 000000000000..d45494807a33 --- /dev/null +++ b/arch/mips/pci/fixup-ocelot-c.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright 2002 Momentum Computer Inc. | ||
3 | * Author: Matthew Dharm <mdharm@momenco.com> | ||
4 | * | ||
5 | * Based on work for the Linux port to the Ocelot board, which is | ||
6 | * Copyright 2001 MontaVista Software Inc. | ||
7 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
8 | * | ||
9 | * arch/mips/momentum/ocelot_g/pci.c | ||
10 | * Board-specific PCI routines for mv64340 controller. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | |||
22 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
23 | { | ||
24 | int bus = dev->bus->number; | ||
25 | |||
26 | if (bus == 0 && slot == 1) | ||
27 | return 2; /* PCI-X A */ | ||
28 | if (bus == 1 && slot == 1) | ||
29 | return 12; /* PCI-X B */ | ||
30 | if (bus == 1 && slot == 2) | ||
31 | return 4; /* PCI B */ | ||
32 | |||
33 | return 0; | ||
34 | panic("Whooops in pcibios_map_irq"); | ||
35 | } | ||
36 | |||
37 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
38 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c new file mode 100644 index 000000000000..d7a652e326c5 --- /dev/null +++ b/arch/mips/pci/fixup-ocelot-g.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2 of the License, or (at your | ||
5 | * option) any later version. | ||
6 | * | ||
7 | * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) | ||
8 | */ | ||
9 | #include <linux/types.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | |||
14 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
15 | { | ||
16 | int bus = dev->bus->number; | ||
17 | |||
18 | if (bus == 0 && slot == 1) /* Intel 82543 Gigabit MAC */ | ||
19 | return 2; /* irq_nr is 2 for INT0 */ | ||
20 | |||
21 | if (bus == 0 && slot == 2) /* Intel 82543 Gigabit MAC */ | ||
22 | return 3; /* irq_nr is 3 for INT1 */ | ||
23 | |||
24 | if (bus == 1 && slot == 3) /* Intel 21555 bridge */ | ||
25 | return 5; /* irq_nr is 8 for INT6 */ | ||
26 | |||
27 | if (bus == 1 && slot == 4) /* PMC Slot */ | ||
28 | return 9; /* irq_nr is 9 for INT7 */ | ||
29 | |||
30 | return -1; | ||
31 | } | ||
32 | |||
33 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
34 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
35 | { | ||
36 | return 0; | ||
37 | } | ||
diff --git a/arch/mips/pci/fixup-ocelot.c b/arch/mips/pci/fixup-ocelot.c new file mode 100644 index 000000000000..99629bd047ce --- /dev/null +++ b/arch/mips/pci/fixup-ocelot.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * arch/mips/gt64120/momenco_ocelot/pci.c | ||
6 | * Board-specific PCI routines for gt64120 controller. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <asm/pci.h> | ||
18 | |||
19 | |||
20 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||
21 | { | ||
22 | struct pci_bus *current_bus = bus; | ||
23 | struct pci_dev *devices; | ||
24 | struct list_head *devices_link; | ||
25 | u16 cmd; | ||
26 | |||
27 | list_for_each(devices_link, &(current_bus->devices)) { | ||
28 | |||
29 | devices = pci_dev_b(devices_link); | ||
30 | if (devices == NULL) | ||
31 | continue; | ||
32 | |||
33 | if (PCI_SLOT(devices->devfn) == 1) { | ||
34 | /* | ||
35 | * Slot 1 is primary ether port, i82559 | ||
36 | * we double-check against that assumption | ||
37 | */ | ||
38 | if ((devices->vendor != 0x8086) || | ||
39 | (devices->device != 0x1209)) { | ||
40 | panic("pcibios_fixup_bus: found " | ||
41 | "unexpected PCI device in slot 1."); | ||
42 | } | ||
43 | devices->irq = 2; /* irq_nr is 2 for INT0 */ | ||
44 | } else if (PCI_SLOT(devices->devfn) == 2) { | ||
45 | /* | ||
46 | * Slot 2 is secondary ether port, i21143 | ||
47 | * we double-check against that assumption | ||
48 | */ | ||
49 | if ((devices->vendor != 0x1011) || | ||
50 | (devices->device != 0x19)) { | ||
51 | panic("galileo_pcibios_fixup_bus: " | ||
52 | "found unexpected PCI device in slot 2."); | ||
53 | } | ||
54 | devices->irq = 3; /* irq_nr is 3 for INT1 */ | ||
55 | } else if (PCI_SLOT(devices->devfn) == 4) { | ||
56 | /* PMC Slot 1 */ | ||
57 | devices->irq = 8; /* irq_nr is 8 for INT6 */ | ||
58 | } else if (PCI_SLOT(devices->devfn) == 5) { | ||
59 | /* PMC Slot 1 */ | ||
60 | devices->irq = 9; /* irq_nr is 9 for INT7 */ | ||
61 | } else { | ||
62 | /* We don't have assign interrupts for other devices. */ | ||
63 | devices->irq = 0xff; | ||
64 | } | ||
65 | |||
66 | /* Assign an interrupt number for the device */ | ||
67 | bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, | ||
68 | devices->irq); | ||
69 | |||
70 | /* enable master */ | ||
71 | bus->ops->read_word(devices, PCI_COMMAND, &cmd); | ||
72 | cmd |= PCI_COMMAND_MASTER; | ||
73 | bus->ops->write_word(devices, PCI_COMMAND, cmd); | ||
74 | } | ||
75 | } | ||
diff --git a/arch/mips/pci/fixup-ocelot3.c b/arch/mips/pci/fixup-ocelot3.c new file mode 100644 index 000000000000..ececc03ec620 --- /dev/null +++ b/arch/mips/pci/fixup-ocelot3.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2004 Montavista Software Inc. | ||
7 | * Author: Manish Lachwani (mlachwani@mvista.com) | ||
8 | * | ||
9 | * Looking at the schematics for the Ocelot-3 board, there are | ||
10 | * two PCI busses and each bus has two PCI slots. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <asm/mipsregs.h> | ||
16 | |||
17 | /* | ||
18 | * Do platform specific device initialization at | ||
19 | * pci_enable_device() time | ||
20 | */ | ||
21 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
22 | { | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
27 | { | ||
28 | int bus = dev->bus->number; | ||
29 | |||
30 | if (bus == 0 && slot == 1) | ||
31 | return 2; /* PCI-X A */ | ||
32 | if (bus == 0 && slot == 2) | ||
33 | return 3; /* PCI-X B */ | ||
34 | if (bus == 1 && slot == 1) | ||
35 | return 4; /* PCI A */ | ||
36 | if (bus == 1 && slot == 2) | ||
37 | return 5; /* PCI B */ | ||
38 | |||
39 | return 0; | ||
40 | panic("Whooops in pcibios_map_irq"); | ||
41 | } | ||
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c new file mode 100644 index 000000000000..de4e443da208 --- /dev/null +++ b/arch/mips/pci/fixup-rbtx4927.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * Board specific pci fixups for the Toshiba rbtx4927 | ||
5 | * | ||
6 | * Copyright 2001 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ppopov@mvista.com or source@mvista.com | ||
9 | * | ||
10 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
11 | * | ||
12 | * Copyright (C) 2004 MontaVista Software Inc. | ||
13 | * Author: Manish Lachwani (mlachwani@mvista.com) | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
23 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
26 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License along | ||
32 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
33 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
34 | */ | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/init.h> | ||
39 | |||
40 | #include <asm/tx4927/tx4927.h> | ||
41 | #include <asm/tx4927/tx4927_pci.h> | ||
42 | |||
43 | #undef DEBUG | ||
44 | #ifdef DEBUG | ||
45 | #define DBG(x...) printk(x) | ||
46 | #else | ||
47 | #define DBG(x...) | ||
48 | #endif | ||
49 | |||
50 | /* look up table for backplane pci irq for slots 17-20 by pin # */ | ||
51 | static unsigned char backplane_pci_irq[4][4] = { | ||
52 | /* PJ6 SLOT: 17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA, | ||
53 | /* PJ6 SLOT: 17, PIN: 2 */ | ||
54 | TX4927_IRQ_IOC_PCIB, | ||
55 | /* PJ6 SLOT: 17, PIN: 3 */ | ||
56 | TX4927_IRQ_IOC_PCIC, | ||
57 | /* PJ6 SLOT: 17, PIN: 4 */ | ||
58 | TX4927_IRQ_IOC_PCID}, | ||
59 | /* SB SLOT: 18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB, | ||
60 | /* SB SLOT: 18, PIN: 2 */ | ||
61 | TX4927_IRQ_IOC_PCIC, | ||
62 | /* SB SLOT: 18, PIN: 3 */ | ||
63 | TX4927_IRQ_IOC_PCID, | ||
64 | /* SB SLOT: 18, PIN: 4 */ | ||
65 | TX4927_IRQ_IOC_PCIA}, | ||
66 | /* PJ5 SLOT: 19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC, | ||
67 | /* PJ5 SLOT: 19, PIN: 2 */ | ||
68 | TX4927_IRQ_IOC_PCID, | ||
69 | /* PJ5 SLOT: 19, PIN: 3 */ | ||
70 | TX4927_IRQ_IOC_PCIA, | ||
71 | /* PJ5 SLOT: 19, PIN: 4 */ | ||
72 | TX4927_IRQ_IOC_PCIB}, | ||
73 | /* PJ4 SLOT: 20, PIN: 1 */ {TX4927_IRQ_IOC_PCID, | ||
74 | /* PJ4 SLOT: 20, PIN: 2 */ | ||
75 | TX4927_IRQ_IOC_PCIA, | ||
76 | /* PJ4 SLOT: 20, PIN: 3 */ | ||
77 | TX4927_IRQ_IOC_PCIB, | ||
78 | /* PJ4 SLOT: 20, PIN: 4 */ | ||
79 | TX4927_IRQ_IOC_PCIC} | ||
80 | }; | ||
81 | |||
82 | int pci_get_irq(struct pci_dev *dev, int pin) | ||
83 | { | ||
84 | unsigned char irq = pin; | ||
85 | |||
86 | DBG("pci_get_irq: pin is %d\n", pin); | ||
87 | /* IRQ rotation */ | ||
88 | irq--; /* 0-3 */ | ||
89 | if (dev->bus->parent == NULL && | ||
90 | PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) { | ||
91 | printk("Onboard PCI_SLOT(dev->devfn) is %d\n", | ||
92 | PCI_SLOT(dev->devfn)); | ||
93 | /* IDSEL=A23 is tx4927 onboard pci slot */ | ||
94 | irq = (irq + PCI_SLOT(dev->devfn)) % 4; | ||
95 | irq++; /* 1-4 */ | ||
96 | DBG("irq is now %d\n", irq); | ||
97 | |||
98 | switch (irq) { | ||
99 | case 1: | ||
100 | irq = TX4927_IRQ_IOC_PCIA; | ||
101 | break; | ||
102 | case 2: | ||
103 | irq = TX4927_IRQ_IOC_PCIB; | ||
104 | break; | ||
105 | case 3: | ||
106 | irq = TX4927_IRQ_IOC_PCIC; | ||
107 | break; | ||
108 | case 4: | ||
109 | irq = TX4927_IRQ_IOC_PCID; | ||
110 | break; | ||
111 | } | ||
112 | } else { | ||
113 | /* PCI Backplane */ | ||
114 | DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n", | ||
115 | PCI_SLOT(dev->devfn)); | ||
116 | irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq]; | ||
117 | } | ||
118 | DBG("assigned irq %d\n", irq); | ||
119 | return irq; | ||
120 | } | ||
121 | |||
122 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
123 | { | ||
124 | unsigned char irq; | ||
125 | |||
126 | printk("PCI Setup for pin %d \n", pin); | ||
127 | |||
128 | if (dev->device == 0x9130) /* IDE */ | ||
129 | irq = 14; | ||
130 | else | ||
131 | irq = pci_get_irq(dev, pin); | ||
132 | |||
133 | return irq; | ||
134 | } | ||
135 | |||
136 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
137 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
138 | { | ||
139 | return 0; | ||
140 | } | ||
diff --git a/arch/mips/pci/fixup-sb1250.c b/arch/mips/pci/fixup-sb1250.c new file mode 100644 index 000000000000..13791b78e598 --- /dev/null +++ b/arch/mips/pci/fixup-sb1250.c | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * arch/mips/pci/fixup-sb1250.c | ||
3 | * | ||
4 | * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved. | ||
5 | * Author: Maciej W. Rozycki <macro@mips.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/pci.h> | ||
15 | |||
16 | /* | ||
17 | * The BCM1250, etc. PCI/HT bridge reports as a host bridge. | ||
18 | */ | ||
19 | static void __init quirk_sb1250_ht(struct pci_dev *dev) | ||
20 | { | ||
21 | dev->class = PCI_CLASS_BRIDGE_PCI << 8; | ||
22 | } | ||
23 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT, | ||
24 | quirk_sb1250_ht); | ||
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c new file mode 100644 index 000000000000..c8ef01a017cc --- /dev/null +++ b/arch/mips/pci/fixup-sni.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * SNI specific PCI support for RM200/RM300. | ||
7 | * | ||
8 | * Copyright (C) 1997 - 2000, 2003, 04 Ralf Baechle (ralf@linux-mips.org) | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/pci.h> | ||
13 | |||
14 | #include <asm/mipsregs.h> | ||
15 | #include <asm/sni.h> | ||
16 | |||
17 | /* | ||
18 | * Shortcuts ... | ||
19 | */ | ||
20 | #define SCSI PCIMT_IRQ_SCSI | ||
21 | #define ETH PCIMT_IRQ_ETHERNET | ||
22 | #define INTA PCIMT_IRQ_INTA | ||
23 | #define INTB PCIMT_IRQ_INTB | ||
24 | #define INTC PCIMT_IRQ_INTC | ||
25 | #define INTD PCIMT_IRQ_INTD | ||
26 | |||
27 | /* | ||
28 | * Device 0: PCI EISA Bridge (directly routed) | ||
29 | * Device 1: NCR53c810 SCSI (directly routed) | ||
30 | * Device 2: PCnet32 Ethernet (directly routed) | ||
31 | * Device 3: VGA (routed to INTB) | ||
32 | * Device 4: Unused | ||
33 | * Device 5: Slot 2 | ||
34 | * Device 6: Slot 3 | ||
35 | * Device 7: Slot 4 | ||
36 | * | ||
37 | * Documentation says the VGA is device 5 and device 3 is unused but that | ||
38 | * seem to be a documentation error. At least on my RM200C the Cirrus | ||
39 | * Logic CL-GD5434 VGA is device 3. | ||
40 | */ | ||
41 | static char irq_tab_rm200[8][5] __initdata = { | ||
42 | /* INTA INTB INTC INTD */ | ||
43 | { 0, 0, 0, 0, 0 }, /* EISA bridge */ | ||
44 | { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ | ||
45 | { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */ | ||
46 | { INTB, INTB, INTB, INTB, INTB }, /* VGA */ | ||
47 | { 0, 0, 0, 0, 0 }, /* Unused */ | ||
48 | { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ | ||
49 | { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ | ||
50 | { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ | ||
51 | }; | ||
52 | |||
53 | /* | ||
54 | * In Revision D of the RM300 Device 2 has become a normal purpose Slot 1 | ||
55 | * | ||
56 | * The VGA card is optional for RM300 systems. | ||
57 | */ | ||
58 | static char irq_tab_rm300d[8][5] __initdata = { | ||
59 | /* INTA INTB INTC INTD */ | ||
60 | { 0, 0, 0, 0, 0 }, /* EISA bridge */ | ||
61 | { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ | ||
62 | { 0, INTC, INTD, INTA, INTB }, /* Slot 1 */ | ||
63 | { INTB, INTB, INTB, INTB, INTB }, /* VGA */ | ||
64 | { 0, 0, 0, 0, 0 }, /* Unused */ | ||
65 | { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ | ||
66 | { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ | ||
67 | { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ | ||
68 | }; | ||
69 | |||
70 | static inline int is_rm300_revd(void) | ||
71 | { | ||
72 | unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR; | ||
73 | |||
74 | return (csmsr & 0xa0) == 0x20; | ||
75 | } | ||
76 | |||
77 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
78 | { | ||
79 | if (is_rm300_revd()) | ||
80 | return irq_tab_rm300d[slot][pin]; | ||
81 | |||
82 | return irq_tab_rm200[slot][pin]; | ||
83 | } | ||
84 | |||
85 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
86 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
87 | { | ||
88 | return 0; | ||
89 | } | ||
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c new file mode 100644 index 000000000000..850a900f0eb4 --- /dev/null +++ b/arch/mips/pci/fixup-tb0219.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. | ||
3 | * | ||
4 | * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> | ||
5 | * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/pci.h> | ||
23 | |||
24 | #include <asm/vr41xx/tb0219.h> | ||
25 | |||
26 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
27 | { | ||
28 | int irq = -1; | ||
29 | |||
30 | switch (slot) { | ||
31 | case 12: | ||
32 | vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN, | ||
33 | TRIGGER_LEVEL, | ||
34 | SIGNAL_THROUGH); | ||
35 | vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN, | ||
36 | LEVEL_LOW); | ||
37 | irq = TB0219_PCI_SLOT1_IRQ; | ||
38 | break; | ||
39 | case 13: | ||
40 | vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN, | ||
41 | TRIGGER_LEVEL, | ||
42 | SIGNAL_THROUGH); | ||
43 | vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN, | ||
44 | LEVEL_LOW); | ||
45 | irq = TB0219_PCI_SLOT2_IRQ; | ||
46 | break; | ||
47 | case 14: | ||
48 | vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN, | ||
49 | TRIGGER_LEVEL, | ||
50 | SIGNAL_THROUGH); | ||
51 | vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, | ||
52 | LEVEL_LOW); | ||
53 | irq = TB0219_PCI_SLOT3_IRQ; | ||
54 | break; | ||
55 | default: | ||
56 | break; | ||
57 | } | ||
58 | |||
59 | return irq; | ||
60 | } | ||
61 | |||
62 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
63 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
64 | { | ||
65 | return 0; | ||
66 | } | ||
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c new file mode 100644 index 000000000000..61513d5d97da --- /dev/null +++ b/arch/mips/pci/fixup-tb0226.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups. | ||
3 | * | ||
4 | * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/pci.h> | ||
22 | |||
23 | #include <asm/vr41xx/tb0226.h> | ||
24 | |||
25 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
26 | { | ||
27 | int irq = -1; | ||
28 | |||
29 | switch (slot) { | ||
30 | case 12: | ||
31 | vr41xx_set_irq_trigger(GD82559_1_PIN, | ||
32 | TRIGGER_LEVEL, | ||
33 | SIGNAL_THROUGH); | ||
34 | vr41xx_set_irq_level(GD82559_1_PIN, LEVEL_LOW); | ||
35 | irq = GD82559_1_IRQ; | ||
36 | break; | ||
37 | case 13: | ||
38 | vr41xx_set_irq_trigger(GD82559_2_PIN, | ||
39 | TRIGGER_LEVEL, | ||
40 | SIGNAL_THROUGH); | ||
41 | vr41xx_set_irq_level(GD82559_2_PIN, LEVEL_LOW); | ||
42 | irq = GD82559_2_IRQ; | ||
43 | break; | ||
44 | case 14: | ||
45 | switch (pin) { | ||
46 | case 1: | ||
47 | vr41xx_set_irq_trigger(UPD720100_INTA_PIN, | ||
48 | TRIGGER_LEVEL, | ||
49 | SIGNAL_THROUGH); | ||
50 | vr41xx_set_irq_level(UPD720100_INTA_PIN, | ||
51 | LEVEL_LOW); | ||
52 | irq = UPD720100_INTA_IRQ; | ||
53 | break; | ||
54 | case 2: | ||
55 | vr41xx_set_irq_trigger(UPD720100_INTB_PIN, | ||
56 | TRIGGER_LEVEL, | ||
57 | SIGNAL_THROUGH); | ||
58 | vr41xx_set_irq_level(UPD720100_INTB_PIN, | ||
59 | LEVEL_LOW); | ||
60 | irq = UPD720100_INTB_IRQ; | ||
61 | break; | ||
62 | case 3: | ||
63 | vr41xx_set_irq_trigger(UPD720100_INTC_PIN, | ||
64 | TRIGGER_LEVEL, | ||
65 | SIGNAL_THROUGH); | ||
66 | vr41xx_set_irq_level(UPD720100_INTC_PIN, | ||
67 | LEVEL_LOW); | ||
68 | irq = UPD720100_INTC_IRQ; | ||
69 | break; | ||
70 | default: | ||
71 | break; | ||
72 | } | ||
73 | break; | ||
74 | default: | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | return irq; | ||
79 | } | ||
80 | |||
81 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
82 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c new file mode 100644 index 000000000000..03a0ff2fc993 --- /dev/null +++ b/arch/mips/pci/fixup-vr4133.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * arch/mips/vr41xx/nec-cmbvr4133/pci_fixup.c | ||
3 | * | ||
4 | * The NEC CMB-VR4133 Board specific PCI fixups. | ||
5 | * | ||
6 | * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and | ||
7 | * Alex Sapkov <asapkov@ru.mvista.com> | ||
8 | * | ||
9 | * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | * | ||
14 | * Modified for support in 2.6 | ||
15 | * Author: Manish Lachwani (mlachwani@mvista.com) | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/config.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/pci.h> | ||
21 | |||
22 | #include <asm/io.h> | ||
23 | #include <asm/vr41xx/cmbvr4133.h> | ||
24 | |||
25 | extern int vr4133_rockhopper; | ||
26 | extern void ali_m1535plus_init(struct pci_dev *dev); | ||
27 | extern void ali_m5229_init(struct pci_dev *dev); | ||
28 | |||
29 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
30 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
31 | { | ||
32 | /* | ||
33 | * We have to reset AMD PCnet adapter on Rockhopper since | ||
34 | * PMON leaves it enabled and generating interrupts. This leads | ||
35 | * to a lock if some PCI device driver later enables the IRQ line | ||
36 | * shared with PCnet and there is no AMD PCnet driver to catch its | ||
37 | * interrupts. | ||
38 | */ | ||
39 | #ifdef CONFIG_ROCKHOPPER | ||
40 | if (dev->vendor == PCI_VENDOR_ID_AMD && | ||
41 | dev->device == PCI_DEVICE_ID_AMD_LANCE) { | ||
42 | inl(pci_resource_start(dev, 0) + 0x18); | ||
43 | } | ||
44 | #endif | ||
45 | |||
46 | /* | ||
47 | * we have to open the bridges' windows down to 0 because otherwise | ||
48 | * we cannot access ISA south bridge I/O registers that get mapped from | ||
49 | * 0. for example, 8259 PIC would be unaccessible without that | ||
50 | */ | ||
51 | if(dev->vendor == PCI_VENDOR_ID_INTEL && dev->device == PCI_DEVICE_ID_INTEL_S21152BB) { | ||
52 | pci_write_config_byte(dev, PCI_IO_BASE, 0); | ||
53 | if(dev->bus->number == 0) { | ||
54 | pci_write_config_word(dev, PCI_IO_BASE_UPPER16, 0); | ||
55 | } else { | ||
56 | pci_write_config_word(dev, PCI_IO_BASE_UPPER16, 1); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * M1535 IRQ mapping | ||
65 | * Feel free to change this, although it shouldn't be needed | ||
66 | */ | ||
67 | #define M1535_IRQ_INTA 7 | ||
68 | #define M1535_IRQ_INTB 9 | ||
69 | #define M1535_IRQ_INTC 10 | ||
70 | #define M1535_IRQ_INTD 11 | ||
71 | |||
72 | #define M1535_IRQ_USB 9 | ||
73 | #define M1535_IRQ_IDE 14 | ||
74 | #define M1535_IRQ_IDE2 15 | ||
75 | #define M1535_IRQ_PS2 12 | ||
76 | #define M1535_IRQ_RTC 8 | ||
77 | #define M1535_IRQ_FDC 6 | ||
78 | #define M1535_IRQ_AUDIO 5 | ||
79 | #define M1535_IRQ_COM1 4 | ||
80 | #define M1535_IRQ_COM2 4 | ||
81 | #define M1535_IRQ_IRDA 3 | ||
82 | #define M1535_IRQ_KBD 1 | ||
83 | #define M1535_IRQ_TMR 0 | ||
84 | |||
85 | /* Rockhopper "slots" assignment; this is hard-coded ... */ | ||
86 | #define ROCKHOPPER_M5451_SLOT 1 | ||
87 | #define ROCKHOPPER_M1535_SLOT 2 | ||
88 | #define ROCKHOPPER_M5229_SLOT 11 | ||
89 | #define ROCKHOPPER_M5237_SLOT 15 | ||
90 | #define ROCKHOPPER_PMU_SLOT 12 | ||
91 | /* ... and hard-wired. */ | ||
92 | #define ROCKHOPPER_PCI1_SLOT 3 | ||
93 | #define ROCKHOPPER_PCI2_SLOT 4 | ||
94 | #define ROCKHOPPER_PCI3_SLOT 5 | ||
95 | #define ROCKHOPPER_PCI4_SLOT 6 | ||
96 | #define ROCKHOPPER_PCNET_SLOT 1 | ||
97 | |||
98 | #define M1535_IRQ_MASK(n) (1 << (n)) | ||
99 | |||
100 | #define M1535_IRQ_EDGE (M1535_IRQ_MASK(M1535_IRQ_TMR) | \ | ||
101 | M1535_IRQ_MASK(M1535_IRQ_KBD) | \ | ||
102 | M1535_IRQ_MASK(M1535_IRQ_COM1) | \ | ||
103 | M1535_IRQ_MASK(M1535_IRQ_COM2) | \ | ||
104 | M1535_IRQ_MASK(M1535_IRQ_IRDA) | \ | ||
105 | M1535_IRQ_MASK(M1535_IRQ_RTC) | \ | ||
106 | M1535_IRQ_MASK(M1535_IRQ_FDC) | \ | ||
107 | M1535_IRQ_MASK(M1535_IRQ_PS2)) | ||
108 | |||
109 | #define M1535_IRQ_LEVEL (M1535_IRQ_MASK(M1535_IRQ_IDE) | \ | ||
110 | M1535_IRQ_MASK(M1535_IRQ_USB) | \ | ||
111 | M1535_IRQ_MASK(M1535_IRQ_INTA) | \ | ||
112 | M1535_IRQ_MASK(M1535_IRQ_INTB) | \ | ||
113 | M1535_IRQ_MASK(M1535_IRQ_INTC) | \ | ||
114 | M1535_IRQ_MASK(M1535_IRQ_INTD)) | ||
115 | |||
116 | struct irq_map_entry { | ||
117 | u16 bus; | ||
118 | u8 slot; | ||
119 | u8 irq; | ||
120 | }; | ||
121 | static struct irq_map_entry int_map[] = { | ||
122 | {1, ROCKHOPPER_M5451_SLOT, M1535_IRQ_AUDIO}, /* Audio controller */ | ||
123 | {1, ROCKHOPPER_PCI1_SLOT, M1535_IRQ_INTD}, /* PCI slot #1 */ | ||
124 | {1, ROCKHOPPER_PCI2_SLOT, M1535_IRQ_INTC}, /* PCI slot #2 */ | ||
125 | {1, ROCKHOPPER_M5237_SLOT, M1535_IRQ_USB}, /* USB host controller */ | ||
126 | {1, ROCKHOPPER_M5229_SLOT, IDE_PRIMARY_IRQ}, /* IDE controller */ | ||
127 | {2, ROCKHOPPER_PCNET_SLOT, M1535_IRQ_INTD}, /* AMD Am79c973 on-board | ||
128 | ethernet */ | ||
129 | {2, ROCKHOPPER_PCI3_SLOT, M1535_IRQ_INTB}, /* PCI slot #3 */ | ||
130 | {2, ROCKHOPPER_PCI4_SLOT, M1535_IRQ_INTC} /* PCI slot #4 */ | ||
131 | }; | ||
132 | |||
133 | static int pci_intlines[] = | ||
134 | { M1535_IRQ_INTA, M1535_IRQ_INTB, M1535_IRQ_INTC, M1535_IRQ_INTD }; | ||
135 | |||
136 | /* Determine the Rockhopper IRQ line number for the PCI device */ | ||
137 | int rockhopper_get_irq(struct pci_dev *dev, u8 pin, u8 slot) | ||
138 | { | ||
139 | struct pci_bus *bus; | ||
140 | int i; | ||
141 | |||
142 | bus = dev->bus; | ||
143 | if (bus == NULL) | ||
144 | return -1; | ||
145 | |||
146 | for (i = 0; i < sizeof (int_map) / sizeof (int_map[0]); i++) { | ||
147 | if (int_map[i].bus == bus->number && int_map[i].slot == slot) { | ||
148 | int line; | ||
149 | for (line = 0; line < 4; line++) | ||
150 | if (pci_intlines[line] == int_map[i].irq) | ||
151 | break; | ||
152 | if (line < 4) | ||
153 | return pci_intlines[(line + (pin - 1)) % 4]; | ||
154 | else | ||
155 | return int_map[i].irq; | ||
156 | } | ||
157 | } | ||
158 | return -1; | ||
159 | } | ||
160 | |||
161 | #ifdef CONFIG_ROCKHOPPER | ||
162 | void i8259_init(void) | ||
163 | { | ||
164 | outb(0x11, 0x20); /* Master ICW1 */ | ||
165 | outb(I8259_IRQ_BASE, 0x21); /* Master ICW2 */ | ||
166 | outb(0x04, 0x21); /* Master ICW3 */ | ||
167 | outb(0x01, 0x21); /* Master ICW4 */ | ||
168 | outb(0xff, 0x21); /* Master IMW */ | ||
169 | |||
170 | outb(0x11, 0xa0); /* Slave ICW1 */ | ||
171 | outb(I8259_IRQ_BASE + 8, 0xa1); /* Slave ICW2 */ | ||
172 | outb(0x02, 0xa1); /* Slave ICW3 */ | ||
173 | outb(0x01, 0xa1); /* Slave ICW4 */ | ||
174 | outb(0xff, 0xa1); /* Slave IMW */ | ||
175 | |||
176 | outb(0x00, 0x4d0); | ||
177 | outb(0x02, 0x4d1); /* USB IRQ9 is level */ | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
182 | { | ||
183 | extern int pci_probe_only; | ||
184 | pci_probe_only = 1; | ||
185 | |||
186 | #ifdef CONFIG_ROCKHOPPER | ||
187 | if( dev->bus->number == 1 && vr4133_rockhopper ) { | ||
188 | if(slot == ROCKHOPPER_PCI1_SLOT || slot == ROCKHOPPER_PCI2_SLOT) | ||
189 | dev->irq = CMBVR41XX_INTA_IRQ; | ||
190 | else | ||
191 | dev->irq = rockhopper_get_irq(dev, pin, slot); | ||
192 | } else | ||
193 | dev->irq = CMBVR41XX_INTA_IRQ; | ||
194 | #else | ||
195 | dev->irq = CMBVR41XX_INTA_IRQ; | ||
196 | #endif | ||
197 | |||
198 | return dev->irq; | ||
199 | } | ||
200 | |||
201 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, ali_m1535plus_init); | ||
202 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, ali_m5229_init); | ||
203 | |||
204 | |||
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c new file mode 100644 index 000000000000..81d77a587a51 --- /dev/null +++ b/arch/mips/pci/fixup-yosemite.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PMC-Sierra | ||
3 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
11 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
13 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
14 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
15 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
16 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
17 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
19 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/pci.h> | ||
28 | |||
29 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
30 | { | ||
31 | if (pin == 0) | ||
32 | return -1; | ||
33 | |||
34 | return 3; /* Everything goes to one irq bit */ | ||
35 | } | ||
36 | |||
37 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
38 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
diff --git a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c new file mode 100644 index 000000000000..c1c91ca0f9c2 --- /dev/null +++ b/arch/mips/pci/ops-au1000.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * BRIEF MODULE DESCRIPTION | ||
3 | * Alchemy/AMD Au1x00 pci support. | ||
4 | * | ||
5 | * Copyright 2001,2002,2003 MontaVista Software Inc. | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * ppopov@mvista.com or source@mvista.com | ||
8 | * | ||
9 | * Support for all devices (greater than 16) added by David Gathright. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
19 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License along | ||
28 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | */ | ||
31 | #include <linux/config.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | |||
38 | #include <asm/mach-au1x00/au1000.h> | ||
39 | |||
40 | #undef DEBUG | ||
41 | #ifdef DEBUG | ||
42 | #define DBG(x...) printk(x) | ||
43 | #else | ||
44 | #define DBG(x...) | ||
45 | #endif | ||
46 | |||
47 | #define PCI_ACCESS_READ 0 | ||
48 | #define PCI_ACCESS_WRITE 1 | ||
49 | |||
50 | |||
51 | int (*board_pci_idsel)(unsigned int devsel, int assert); | ||
52 | |||
53 | /* CP0 hazard avoidance. */ | ||
54 | #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ | ||
55 | "nop; nop; nop; nop;\t" \ | ||
56 | ".set reorder\n\t") | ||
57 | |||
58 | void mod_wired_entry(int entry, unsigned long entrylo0, | ||
59 | unsigned long entrylo1, unsigned long entryhi, | ||
60 | unsigned long pagemask) | ||
61 | { | ||
62 | unsigned long old_pagemask; | ||
63 | unsigned long old_ctx; | ||
64 | |||
65 | /* Save old context and create impossible VPN2 value */ | ||
66 | old_ctx = read_c0_entryhi() & 0xff; | ||
67 | old_pagemask = read_c0_pagemask(); | ||
68 | write_c0_index(entry); | ||
69 | BARRIER; | ||
70 | write_c0_pagemask(pagemask); | ||
71 | write_c0_entryhi(entryhi); | ||
72 | write_c0_entrylo0(entrylo0); | ||
73 | write_c0_entrylo1(entrylo1); | ||
74 | BARRIER; | ||
75 | tlb_write_indexed(); | ||
76 | BARRIER; | ||
77 | write_c0_entryhi(old_ctx); | ||
78 | BARRIER; | ||
79 | write_c0_pagemask(old_pagemask); | ||
80 | } | ||
81 | |||
82 | struct vm_struct *pci_cfg_vm; | ||
83 | static int pci_cfg_wired_entry; | ||
84 | static int first_cfg = 1; | ||
85 | unsigned long last_entryLo0, last_entryLo1; | ||
86 | |||
87 | static int config_access(unsigned char access_type, struct pci_bus *bus, | ||
88 | unsigned int dev_fn, unsigned char where, | ||
89 | u32 * data) | ||
90 | { | ||
91 | #if defined( CONFIG_SOC_AU1500 ) || defined( CONFIG_SOC_AU1550 ) | ||
92 | unsigned int device = PCI_SLOT(dev_fn); | ||
93 | unsigned int function = PCI_FUNC(dev_fn); | ||
94 | unsigned long offset, status; | ||
95 | unsigned long cfg_base; | ||
96 | unsigned long flags; | ||
97 | int error = PCIBIOS_SUCCESSFUL; | ||
98 | unsigned long entryLo0, entryLo1; | ||
99 | |||
100 | if (device > 19) { | ||
101 | *data = 0xffffffff; | ||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | local_irq_save(flags); | ||
106 | au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)), | ||
107 | Au1500_PCI_STATCMD); | ||
108 | au_sync_udelay(1); | ||
109 | |||
110 | /* | ||
111 | * We can't ioremap the entire pci config space because it's | ||
112 | * too large. Nor can we call ioremap dynamically because some | ||
113 | * device drivers use the pci config routines from within | ||
114 | * interrupt handlers and that becomes a problem in get_vm_area(). | ||
115 | * We use one wired tlb to handle all config accesses for all | ||
116 | * busses. To improve performance, if the current device | ||
117 | * is the same as the last device accessed, we don't touch the | ||
118 | * tlb. | ||
119 | */ | ||
120 | if (first_cfg) { | ||
121 | /* reserve a wired entry for pci config accesses */ | ||
122 | first_cfg = 0; | ||
123 | pci_cfg_vm = get_vm_area(0x2000, 0); | ||
124 | if (!pci_cfg_vm) | ||
125 | panic (KERN_ERR "PCI unable to get vm area\n"); | ||
126 | pci_cfg_wired_entry = read_c0_wired(); | ||
127 | add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, PM_4K); | ||
128 | last_entryLo0 = last_entryLo1 = 0xffffffff; | ||
129 | } | ||
130 | |||
131 | /* Since the Au1xxx doesn't do the idsel timing exactly to spec, | ||
132 | * many board vendors implement their own off-chip idsel, so call | ||
133 | * it now. If it doesn't succeed, may as well bail out at this point. | ||
134 | */ | ||
135 | if (board_pci_idsel) { | ||
136 | if (board_pci_idsel(device, 1) == 0) { | ||
137 | *data = 0xffffffff; | ||
138 | local_irq_restore(flags); | ||
139 | return -1; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /* setup the config window */ | ||
144 | if (bus->number == 0) { | ||
145 | cfg_base = ((1<<device)<<11); | ||
146 | } else { | ||
147 | cfg_base = 0x80000000 | (bus->number<<16) | (device<<11); | ||
148 | } | ||
149 | |||
150 | /* setup the lower bits of the 36 bit address */ | ||
151 | offset = (function << 8) | (where & ~0x3); | ||
152 | /* pick up any address that falls below the page mask */ | ||
153 | offset |= cfg_base & ~PAGE_MASK; | ||
154 | |||
155 | /* page boundary */ | ||
156 | cfg_base = cfg_base & PAGE_MASK; | ||
157 | |||
158 | entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7; | ||
159 | entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7; | ||
160 | |||
161 | if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) { | ||
162 | mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1, | ||
163 | (unsigned long)pci_cfg_vm->addr, PM_4K); | ||
164 | last_entryLo0 = entryLo0; | ||
165 | last_entryLo1 = entryLo1; | ||
166 | } | ||
167 | |||
168 | if (access_type == PCI_ACCESS_WRITE) { | ||
169 | au_writel(*data, (int)(pci_cfg_vm->addr + offset)); | ||
170 | } else { | ||
171 | *data = au_readl((int)(pci_cfg_vm->addr + offset)); | ||
172 | } | ||
173 | au_sync_udelay(2); | ||
174 | |||
175 | DBG("cfg_access %d bus->number %d dev %d at %x *data %x conf %x\n", | ||
176 | access_type, bus->number, device, where, *data, offset); | ||
177 | |||
178 | /* check master abort */ | ||
179 | status = au_readl(Au1500_PCI_STATCMD); | ||
180 | |||
181 | if (status & (1<<29)) { | ||
182 | *data = 0xffffffff; | ||
183 | error = -1; | ||
184 | DBG("Au1x Master Abort\n"); | ||
185 | } else if ((status >> 28) & 0xf) { | ||
186 | DBG("PCI ERR detected: status %x\n", status); | ||
187 | *data = 0xffffffff; | ||
188 | error = -1; | ||
189 | } | ||
190 | |||
191 | /* Take away the idsel. | ||
192 | */ | ||
193 | if (board_pci_idsel) { | ||
194 | (void)board_pci_idsel(device, 0); | ||
195 | } | ||
196 | |||
197 | local_irq_restore(flags); | ||
198 | return error; | ||
199 | #endif | ||
200 | } | ||
201 | |||
202 | static int read_config_byte(struct pci_bus *bus, unsigned int devfn, | ||
203 | int where, u8 * val) | ||
204 | { | ||
205 | u32 data; | ||
206 | int ret; | ||
207 | |||
208 | ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data); | ||
209 | if (where & 1) | ||
210 | data >>= 8; | ||
211 | if (where & 2) | ||
212 | data >>= 16; | ||
213 | *val = data & 0xff; | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | |||
218 | static int read_config_word(struct pci_bus *bus, unsigned int devfn, | ||
219 | int where, u16 * val) | ||
220 | { | ||
221 | u32 data; | ||
222 | int ret; | ||
223 | |||
224 | ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data); | ||
225 | if (where & 2) | ||
226 | data >>= 16; | ||
227 | *val = data & 0xffff; | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static int read_config_dword(struct pci_bus *bus, unsigned int devfn, | ||
232 | int where, u32 * val) | ||
233 | { | ||
234 | int ret; | ||
235 | |||
236 | ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static int | ||
241 | write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, | ||
242 | u8 val) | ||
243 | { | ||
244 | u32 data = 0; | ||
245 | |||
246 | if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) | ||
247 | return -1; | ||
248 | |||
249 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
250 | (val << ((where & 3) << 3)); | ||
251 | |||
252 | if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) | ||
253 | return -1; | ||
254 | |||
255 | return PCIBIOS_SUCCESSFUL; | ||
256 | } | ||
257 | |||
258 | static int | ||
259 | write_config_word(struct pci_bus *bus, unsigned int devfn, int where, | ||
260 | u16 val) | ||
261 | { | ||
262 | u32 data = 0; | ||
263 | |||
264 | if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) | ||
265 | return -1; | ||
266 | |||
267 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
268 | (val << ((where & 3) << 3)); | ||
269 | |||
270 | if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) | ||
271 | return -1; | ||
272 | |||
273 | |||
274 | return PCIBIOS_SUCCESSFUL; | ||
275 | } | ||
276 | |||
277 | static int | ||
278 | write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, | ||
279 | u32 val) | ||
280 | { | ||
281 | if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val)) | ||
282 | return -1; | ||
283 | |||
284 | return PCIBIOS_SUCCESSFUL; | ||
285 | } | ||
286 | |||
287 | static int config_read(struct pci_bus *bus, unsigned int devfn, | ||
288 | int where, int size, u32 * val) | ||
289 | { | ||
290 | switch (size) { | ||
291 | case 1: { | ||
292 | u8 _val; | ||
293 | int rc = read_config_byte(bus, devfn, where, &_val); | ||
294 | *val = _val; | ||
295 | return rc; | ||
296 | } | ||
297 | case 2: { | ||
298 | u16 _val; | ||
299 | int rc = read_config_word(bus, devfn, where, &_val); | ||
300 | *val = _val; | ||
301 | return rc; | ||
302 | } | ||
303 | default: | ||
304 | return read_config_dword(bus, devfn, where, val); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | static int config_write(struct pci_bus *bus, unsigned int devfn, | ||
309 | int where, int size, u32 val) | ||
310 | { | ||
311 | switch (size) { | ||
312 | case 1: | ||
313 | return write_config_byte(bus, devfn, where, (u8) val); | ||
314 | case 2: | ||
315 | return write_config_word(bus, devfn, where, (u16) val); | ||
316 | default: | ||
317 | return write_config_dword(bus, devfn, where, val); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | |||
322 | struct pci_ops au1x_pci_ops = { | ||
323 | config_read, | ||
324 | config_write | ||
325 | }; | ||
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c new file mode 100644 index 000000000000..4b4e086a7eb1 --- /dev/null +++ b/arch/mips/pci/ops-bonito64.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * MIPS boards specific PCI support. | ||
19 | */ | ||
20 | #include <linux/config.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | |||
26 | #include <asm/mips-boards/bonito64.h> | ||
27 | |||
28 | #define PCI_ACCESS_READ 0 | ||
29 | #define PCI_ACCESS_WRITE 1 | ||
30 | |||
31 | /* | ||
32 | * PCI configuration cycle AD bus definition | ||
33 | */ | ||
34 | /* Type 0 */ | ||
35 | #define PCI_CFG_TYPE0_REG_SHF 0 | ||
36 | #define PCI_CFG_TYPE0_FUNC_SHF 8 | ||
37 | |||
38 | /* Type 1 */ | ||
39 | #define PCI_CFG_TYPE1_REG_SHF 0 | ||
40 | #define PCI_CFG_TYPE1_FUNC_SHF 8 | ||
41 | #define PCI_CFG_TYPE1_DEV_SHF 11 | ||
42 | #define PCI_CFG_TYPE1_BUS_SHF 16 | ||
43 | |||
44 | static int bonito64_pcibios_config_access(unsigned char access_type, | ||
45 | struct pci_bus *bus, | ||
46 | unsigned int devfn, int where, | ||
47 | u32 * data) | ||
48 | { | ||
49 | unsigned char busnum = bus->number; | ||
50 | u32 dummy; | ||
51 | u64 pci_addr; | ||
52 | |||
53 | /* Algorithmics Bonito64 system controller. */ | ||
54 | |||
55 | if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) { | ||
56 | /* We number bus 0 devices from 0..21 */ | ||
57 | return -1; | ||
58 | } | ||
59 | |||
60 | #ifdef CONFIG_MIPS_BOARDS_GEN | ||
61 | if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) { | ||
62 | /* MIPS Core boards have Bonito connected as device 17 */ | ||
63 | return -1; | ||
64 | } | ||
65 | #endif | ||
66 | |||
67 | /* Clear cause register bits */ | ||
68 | BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | | ||
69 | BONITO_PCICMD_MTABORT_CLR); | ||
70 | |||
71 | /* | ||
72 | * Setup pattern to be used as PCI "address" for | ||
73 | * Type 0 cycle | ||
74 | */ | ||
75 | if (busnum == 0) { | ||
76 | /* IDSEL */ | ||
77 | pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10); | ||
78 | } else { | ||
79 | /* Bus number */ | ||
80 | pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF; | ||
81 | |||
82 | /* Device number */ | ||
83 | pci_addr |= | ||
84 | PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF; | ||
85 | } | ||
86 | |||
87 | /* Function (same for Type 0/1) */ | ||
88 | pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF; | ||
89 | |||
90 | /* Register number (same for Type 0/1) */ | ||
91 | pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF; | ||
92 | |||
93 | if (busnum == 0) { | ||
94 | /* Type 0 */ | ||
95 | BONITO_PCIMAP_CFG = pci_addr >> 16; | ||
96 | } else { | ||
97 | /* Type 1 */ | ||
98 | BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000; | ||
99 | } | ||
100 | |||
101 | pci_addr &= 0xffff; | ||
102 | |||
103 | /* Flush Bonito register block */ | ||
104 | dummy = BONITO_PCIMAP_CFG; | ||
105 | iob(); /* sync */ | ||
106 | |||
107 | /* Perform access */ | ||
108 | if (access_type == PCI_ACCESS_WRITE) { | ||
109 | *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data; | ||
110 | |||
111 | /* Wait till done */ | ||
112 | while (BONITO_PCIMSTAT & 0xF); | ||
113 | } else { | ||
114 | *(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr); | ||
115 | } | ||
116 | |||
117 | /* Detect Master/Target abort */ | ||
118 | if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | | ||
119 | BONITO_PCICMD_MTABORT_CLR)) { | ||
120 | /* Error occurred */ | ||
121 | |||
122 | /* Clear bits */ | ||
123 | BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | | ||
124 | BONITO_PCICMD_MTABORT_CLR); | ||
125 | |||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | |||
133 | /* | ||
134 | * We can't address 8 and 16 bit words directly. Instead we have to | ||
135 | * read/write a 32bit word and mask/modify the data we actually want. | ||
136 | */ | ||
137 | static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
138 | int where, int size, u32 * val) | ||
139 | { | ||
140 | u32 data = 0; | ||
141 | |||
142 | if ((size == 2) && (where & 1)) | ||
143 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
144 | else if ((size == 4) && (where & 3)) | ||
145 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
146 | |||
147 | if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | ||
148 | &data)) | ||
149 | return -1; | ||
150 | |||
151 | if (size == 1) | ||
152 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
153 | else if (size == 2) | ||
154 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
155 | else | ||
156 | *val = data; | ||
157 | |||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | |||
161 | static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
162 | int where, int size, u32 val) | ||
163 | { | ||
164 | u32 data = 0; | ||
165 | |||
166 | if ((size == 2) && (where & 1)) | ||
167 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
168 | else if ((size == 4) && (where & 3)) | ||
169 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
170 | |||
171 | if (size == 4) | ||
172 | data = val; | ||
173 | else { | ||
174 | if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, | ||
175 | where, &data)) | ||
176 | return -1; | ||
177 | |||
178 | if (size == 1) | ||
179 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
180 | (val << ((where & 3) << 3)); | ||
181 | else if (size == 2) | ||
182 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
183 | (val << ((where & 3) << 3)); | ||
184 | } | ||
185 | |||
186 | if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, | ||
187 | &data)) | ||
188 | return -1; | ||
189 | |||
190 | return PCIBIOS_SUCCESSFUL; | ||
191 | } | ||
192 | |||
193 | struct pci_ops bonito64_pci_ops = { | ||
194 | .read = bonito64_pcibios_read, | ||
195 | .write = bonito64_pcibios_write | ||
196 | }; | ||
diff --git a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c new file mode 100644 index 000000000000..89f97bef4fc4 --- /dev/null +++ b/arch/mips/pci/ops-ddb5074.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * arch/mips/ddb5xxx/ddb5476/pci_ops.c | ||
6 | * Define the pci_ops for DB5477. | ||
7 | * | ||
8 | * Much of the code is derived from the original DDB5074 port by | ||
9 | * Geert Uytterhoeven <geert@sonycom.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | |||
21 | #include <asm/addrspace.h> | ||
22 | #include <asm/debug.h> | ||
23 | |||
24 | #include <asm/ddb5xxx/ddb5xxx.h> | ||
25 | |||
26 | /* | ||
27 | * config_swap structure records what set of pdar/pmr are used | ||
28 | * to access pci config space. It also provides a place hold the | ||
29 | * original values for future restoring. | ||
30 | */ | ||
31 | struct pci_config_swap { | ||
32 | u32 pdar; | ||
33 | u32 pmr; | ||
34 | u32 config_base; | ||
35 | u32 config_size; | ||
36 | u32 pdar_backup; | ||
37 | u32 pmr_backup; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * On DDB5476, we have one set of swap registers | ||
42 | */ | ||
43 | struct pci_config_swap ext_pci_swap = { | ||
44 | DDB_PCIW0, | ||
45 | DDB_PCIINIT0, | ||
46 | DDB_PCI_CONFIG_BASE, | ||
47 | DDB_PCI_CONFIG_SIZE | ||
48 | }; | ||
49 | |||
50 | static int pci_config_workaround = 1; | ||
51 | |||
52 | /* | ||
53 | * access config space | ||
54 | */ | ||
55 | static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ | ||
56 | u32 slot_num) | ||
57 | { | ||
58 | u32 pci_addr = 0; | ||
59 | u32 pciinit_offset = 0; | ||
60 | u32 virt_addr = swap->config_base; | ||
61 | u32 option; | ||
62 | |||
63 | if (pci_config_workaround) { | ||
64 | if (slot_num == 5) | ||
65 | slot_num = 14; | ||
66 | } else { | ||
67 | if (slot_num == 5) | ||
68 | return DDB_BASE + DDB_PCI_BASE; | ||
69 | } | ||
70 | |||
71 | /* minimum pdar (window) size is 2MB */ | ||
72 | db_assert(swap->config_size >= (2 << 20)); | ||
73 | |||
74 | db_assert(slot_num < (1 << 5)); | ||
75 | db_assert(bus < (1 << 8)); | ||
76 | |||
77 | /* backup registers */ | ||
78 | swap->pdar_backup = ddb_in32(swap->pdar); | ||
79 | swap->pmr_backup = ddb_in32(swap->pmr); | ||
80 | |||
81 | /* set the pdar (pci window) register */ | ||
82 | ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ | ||
83 | 0, /* not on local memory bus */ | ||
84 | 0); /* not visible from PCI bus (N/A) */ | ||
85 | |||
86 | /* | ||
87 | * calcuate the absolute pci config addr; | ||
88 | * according to the spec, we start scanning from adr:11 (0x800) | ||
89 | */ | ||
90 | if (bus == 0) { | ||
91 | /* type 0 config */ | ||
92 | pci_addr = 0x00040000 << slot_num; | ||
93 | } else { | ||
94 | /* type 1 config */ | ||
95 | pci_addr = 0x00040000 << slot_num; | ||
96 | panic | ||
97 | ("ddb_access_config_base: we don't support type 1 config Yet"); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * if pci_addr is less than pci config window size, we set | ||
102 | * pciinit_offset to 0 and adjust the virt_address. | ||
103 | * Otherwise we will try to adjust pciinit_offset. | ||
104 | */ | ||
105 | if (pci_addr < swap->config_size) { | ||
106 | virt_addr = KSEG1ADDR(swap->config_base + pci_addr); | ||
107 | pciinit_offset = 0; | ||
108 | } else { | ||
109 | db_assert((pci_addr & (swap->config_size - 1)) == 0); | ||
110 | virt_addr = KSEG1ADDR(swap->config_base); | ||
111 | pciinit_offset = pci_addr; | ||
112 | } | ||
113 | |||
114 | /* set the pmr register */ | ||
115 | option = DDB_PCI_ACCESS_32; | ||
116 | if (bus != 0) | ||
117 | option |= DDB_PCI_CFGTYPE1; | ||
118 | ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); | ||
119 | |||
120 | return virt_addr; | ||
121 | } | ||
122 | |||
123 | static inline void ddb_close_config_base(struct pci_config_swap *swap) | ||
124 | { | ||
125 | ddb_out32(swap->pdar, swap->pdar_backup); | ||
126 | ddb_out32(swap->pmr, swap->pmr_backup); | ||
127 | } | ||
128 | |||
129 | static int read_config_dword(struct pci_config_swap *swap, | ||
130 | struct pci_dev *dev, u32 where, u32 * val) | ||
131 | { | ||
132 | u32 bus, slot_num, func_num; | ||
133 | u32 base; | ||
134 | |||
135 | db_assert((where & 3) == 0); | ||
136 | db_assert(where < (1 << 8)); | ||
137 | |||
138 | /* check if the bus is top-level */ | ||
139 | if (dev->bus->parent != NULL) { | ||
140 | bus = dev->bus->number; | ||
141 | db_assert(bus != 0); | ||
142 | } else { | ||
143 | bus = 0; | ||
144 | } | ||
145 | |||
146 | slot_num = PCI_SLOT(dev->devfn); | ||
147 | func_num = PCI_FUNC(dev->devfn); | ||
148 | base = ddb_access_config_base(swap, bus, slot_num); | ||
149 | *val = *(volatile u32 *) (base + (func_num << 8) + where); | ||
150 | ddb_close_config_base(swap); | ||
151 | return PCIBIOS_SUCCESSFUL; | ||
152 | } | ||
153 | |||
154 | static int read_config_word(struct pci_config_swap *swap, | ||
155 | struct pci_dev *dev, u32 where, u16 * val) | ||
156 | { | ||
157 | int status; | ||
158 | u32 result; | ||
159 | |||
160 | db_assert((where & 1) == 0); | ||
161 | |||
162 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
163 | if (where & 2) | ||
164 | result >>= 16; | ||
165 | *val = result & 0xffff; | ||
166 | return status; | ||
167 | } | ||
168 | |||
169 | static int read_config_byte(struct pci_config_swap *swap, | ||
170 | struct pci_dev *dev, u32 where, u8 * val) | ||
171 | { | ||
172 | int status; | ||
173 | u32 result; | ||
174 | |||
175 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
176 | if (where & 1) | ||
177 | result >>= 8; | ||
178 | if (where & 2) | ||
179 | result >>= 16; | ||
180 | *val = result & 0xff; | ||
181 | return status; | ||
182 | } | ||
183 | |||
184 | static int write_config_dword(struct pci_config_swap *swap, | ||
185 | struct pci_dev *dev, u32 where, u32 val) | ||
186 | { | ||
187 | u32 bus, slot_num, func_num; | ||
188 | u32 base; | ||
189 | |||
190 | db_assert((where & 3) == 0); | ||
191 | db_assert(where < (1 << 8)); | ||
192 | |||
193 | /* check if the bus is top-level */ | ||
194 | if (dev->bus->parent != NULL) { | ||
195 | bus = dev->bus->number; | ||
196 | db_assert(bus != 0); | ||
197 | } else { | ||
198 | bus = 0; | ||
199 | } | ||
200 | |||
201 | slot_num = PCI_SLOT(dev->devfn); | ||
202 | func_num = PCI_FUNC(dev->devfn); | ||
203 | base = ddb_access_config_base(swap, bus, slot_num); | ||
204 | *(volatile u32 *) (base + (func_num << 8) + where) = val; | ||
205 | ddb_close_config_base(swap); | ||
206 | return PCIBIOS_SUCCESSFUL; | ||
207 | } | ||
208 | |||
209 | static int write_config_word(struct pci_config_swap *swap, | ||
210 | struct pci_dev *dev, u32 where, u16 val) | ||
211 | { | ||
212 | int status, shift = 0; | ||
213 | u32 result; | ||
214 | |||
215 | db_assert((where & 1) == 0); | ||
216 | |||
217 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
218 | if (status != PCIBIOS_SUCCESSFUL) | ||
219 | return status; | ||
220 | |||
221 | if (where & 2) | ||
222 | shift += 16; | ||
223 | result &= ~(0xffff << shift); | ||
224 | result |= val << shift; | ||
225 | return write_config_dword(swap, dev, where & ~3, result); | ||
226 | } | ||
227 | |||
228 | static int write_config_byte(struct pci_config_swap *swap, | ||
229 | struct pci_dev *dev, u32 where, u8 val) | ||
230 | { | ||
231 | int status, shift = 0; | ||
232 | u32 result; | ||
233 | |||
234 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
235 | if (status != PCIBIOS_SUCCESSFUL) | ||
236 | return status; | ||
237 | |||
238 | if (where & 2) | ||
239 | shift += 16; | ||
240 | if (where & 1) | ||
241 | shift += 8; | ||
242 | result &= ~(0xff << shift); | ||
243 | result |= val << shift; | ||
244 | return write_config_dword(swap, dev, where & ~3, result); | ||
245 | } | ||
246 | |||
247 | #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ | ||
248 | static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ | ||
249 | { \ | ||
250 | return rw##_config_##unitname(pciswap, \ | ||
251 | dev, \ | ||
252 | where, \ | ||
253 | val); \ | ||
254 | } | ||
255 | |||
256 | MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) | ||
257 | MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) | ||
258 | MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) | ||
259 | |||
260 | MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) | ||
261 | MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) | ||
262 | MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) | ||
263 | |||
264 | struct pci_ops ddb5476_ext_pci_ops = { | ||
265 | extpci_read_config_byte, | ||
266 | extpci_read_config_word, | ||
267 | extpci_read_config_dword, | ||
268 | extpci_write_config_byte, | ||
269 | extpci_write_config_word, | ||
270 | extpci_write_config_dword | ||
271 | }; | ||
diff --git a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c new file mode 100644 index 000000000000..12da58e75ec7 --- /dev/null +++ b/arch/mips/pci/ops-ddb5476.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * arch/mips/ddb5xxx/ddb5476/pci_ops.c | ||
6 | * Define the pci_ops for DB5477. | ||
7 | * | ||
8 | * Much of the code is derived from the original DDB5074 port by | ||
9 | * Geert Uytterhoeven <geert@sonycom.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | |||
21 | #include <asm/addrspace.h> | ||
22 | #include <asm/debug.h> | ||
23 | |||
24 | #include <asm/ddb5xxx/ddb5xxx.h> | ||
25 | |||
26 | /* | ||
27 | * config_swap structure records what set of pdar/pmr are used | ||
28 | * to access pci config space. It also provides a place hold the | ||
29 | * original values for future restoring. | ||
30 | */ | ||
31 | struct pci_config_swap { | ||
32 | u32 pdar; | ||
33 | u32 pmr; | ||
34 | u32 config_base; | ||
35 | u32 config_size; | ||
36 | u32 pdar_backup; | ||
37 | u32 pmr_backup; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * On DDB5476, we have one set of swap registers | ||
42 | */ | ||
43 | struct pci_config_swap ext_pci_swap = { | ||
44 | DDB_PCIW0, | ||
45 | DDB_PCIINIT0, | ||
46 | DDB_PCI_CONFIG_BASE, | ||
47 | DDB_PCI_CONFIG_SIZE | ||
48 | }; | ||
49 | |||
50 | static int pci_config_workaround = 1; | ||
51 | |||
52 | /* | ||
53 | * access config space | ||
54 | */ | ||
55 | static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ | ||
56 | u32 slot_num) | ||
57 | { | ||
58 | u32 pci_addr = 0; | ||
59 | u32 pciinit_offset = 0; | ||
60 | u32 virt_addr = swap->config_base; | ||
61 | u32 option; | ||
62 | |||
63 | if (pci_config_workaround) { | ||
64 | /* [jsun] work around Vrc5476 controller itself, returnning | ||
65 | * slot 0 essentially makes vrc5476 invisible | ||
66 | */ | ||
67 | if (slot_num == 12) | ||
68 | slot_num = 0; | ||
69 | |||
70 | #if 0 | ||
71 | /* BUG : skip P2P bridge for now */ | ||
72 | if (slot_num == 5) | ||
73 | slot_num = 0; | ||
74 | #endif | ||
75 | |||
76 | } else { | ||
77 | /* now we have to be hornest, returning the true | ||
78 | * PCI config headers for vrc5476 | ||
79 | */ | ||
80 | if (slot_num == 12) { | ||
81 | swap->pdar_backup = ddb_in32(swap->pdar); | ||
82 | swap->pmr_backup = ddb_in32(swap->pmr); | ||
83 | return DDB_BASE + DDB_PCI_BASE; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | /* minimum pdar (window) size is 2MB */ | ||
88 | db_assert(swap->config_size >= (2 << 20)); | ||
89 | |||
90 | db_assert(slot_num < (1 << 5)); | ||
91 | db_assert(bus < (1 << 8)); | ||
92 | |||
93 | /* backup registers */ | ||
94 | swap->pdar_backup = ddb_in32(swap->pdar); | ||
95 | swap->pmr_backup = ddb_in32(swap->pmr); | ||
96 | |||
97 | /* set the pdar (pci window) register */ | ||
98 | ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ | ||
99 | 0, /* not on local memory bus */ | ||
100 | 0); /* not visible from PCI bus (N/A) */ | ||
101 | |||
102 | /* | ||
103 | * calcuate the absolute pci config addr; | ||
104 | * according to the spec, we start scanning from adr:11 (0x800) | ||
105 | */ | ||
106 | if (bus == 0) { | ||
107 | /* type 0 config */ | ||
108 | pci_addr = 0x800 << slot_num; | ||
109 | } else { | ||
110 | /* type 1 config */ | ||
111 | pci_addr = (bus << 16) | (slot_num << 11); | ||
112 | /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */ | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * if pci_addr is less than pci config window size, we set | ||
117 | * pciinit_offset to 0 and adjust the virt_address. | ||
118 | * Otherwise we will try to adjust pciinit_offset. | ||
119 | */ | ||
120 | if (pci_addr < swap->config_size) { | ||
121 | virt_addr = KSEG1ADDR(swap->config_base + pci_addr); | ||
122 | pciinit_offset = 0; | ||
123 | } else { | ||
124 | db_assert((pci_addr & (swap->config_size - 1)) == 0); | ||
125 | virt_addr = KSEG1ADDR(swap->config_base); | ||
126 | pciinit_offset = pci_addr; | ||
127 | } | ||
128 | |||
129 | /* set the pmr register */ | ||
130 | option = DDB_PCI_ACCESS_32; | ||
131 | if (bus != 0) | ||
132 | option |= DDB_PCI_CFGTYPE1; | ||
133 | ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); | ||
134 | |||
135 | return virt_addr; | ||
136 | } | ||
137 | |||
138 | static inline void ddb_close_config_base(struct pci_config_swap *swap) | ||
139 | { | ||
140 | ddb_out32(swap->pdar, swap->pdar_backup); | ||
141 | ddb_out32(swap->pmr, swap->pmr_backup); | ||
142 | } | ||
143 | |||
144 | static int read_config_dword(struct pci_config_swap *swap, | ||
145 | struct pci_dev *dev, u32 where, u32 * val) | ||
146 | { | ||
147 | u32 bus, slot_num, func_num; | ||
148 | u32 base; | ||
149 | |||
150 | db_assert((where & 3) == 0); | ||
151 | db_assert(where < (1 << 8)); | ||
152 | |||
153 | /* check if the bus is top-level */ | ||
154 | if (dev->bus->parent != NULL) { | ||
155 | bus = dev->bus->number; | ||
156 | db_assert(bus != 0); | ||
157 | } else { | ||
158 | bus = 0; | ||
159 | } | ||
160 | |||
161 | slot_num = PCI_SLOT(dev->devfn); | ||
162 | func_num = PCI_FUNC(dev->devfn); | ||
163 | base = ddb_access_config_base(swap, bus, slot_num); | ||
164 | *val = *(volatile u32 *) (base + (func_num << 8) + where); | ||
165 | ddb_close_config_base(swap); | ||
166 | return PCIBIOS_SUCCESSFUL; | ||
167 | } | ||
168 | |||
169 | static int read_config_word(struct pci_config_swap *swap, | ||
170 | struct pci_dev *dev, u32 where, u16 * val) | ||
171 | { | ||
172 | int status; | ||
173 | u32 result; | ||
174 | |||
175 | db_assert((where & 1) == 0); | ||
176 | |||
177 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
178 | if (where & 2) | ||
179 | result >>= 16; | ||
180 | *val = result & 0xffff; | ||
181 | return status; | ||
182 | } | ||
183 | |||
184 | static int read_config_byte(struct pci_config_swap *swap, | ||
185 | struct pci_dev *dev, u32 where, u8 * val) | ||
186 | { | ||
187 | int status; | ||
188 | u32 result; | ||
189 | |||
190 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
191 | if (where & 1) | ||
192 | result >>= 8; | ||
193 | if (where & 2) | ||
194 | result >>= 16; | ||
195 | *val = result & 0xff; | ||
196 | return status; | ||
197 | } | ||
198 | |||
199 | static int write_config_dword(struct pci_config_swap *swap, | ||
200 | struct pci_dev *dev, u32 where, u32 val) | ||
201 | { | ||
202 | u32 bus, slot_num, func_num; | ||
203 | u32 base; | ||
204 | |||
205 | db_assert((where & 3) == 0); | ||
206 | db_assert(where < (1 << 8)); | ||
207 | |||
208 | /* check if the bus is top-level */ | ||
209 | if (dev->bus->parent != NULL) { | ||
210 | bus = dev->bus->number; | ||
211 | db_assert(bus != 0); | ||
212 | } else { | ||
213 | bus = 0; | ||
214 | } | ||
215 | |||
216 | slot_num = PCI_SLOT(dev->devfn); | ||
217 | func_num = PCI_FUNC(dev->devfn); | ||
218 | base = ddb_access_config_base(swap, bus, slot_num); | ||
219 | *(volatile u32 *) (base + (func_num << 8) + where) = val; | ||
220 | ddb_close_config_base(swap); | ||
221 | return PCIBIOS_SUCCESSFUL; | ||
222 | } | ||
223 | |||
224 | static int write_config_word(struct pci_config_swap *swap, | ||
225 | struct pci_dev *dev, u32 where, u16 val) | ||
226 | { | ||
227 | int status, shift = 0; | ||
228 | u32 result; | ||
229 | |||
230 | db_assert((where & 1) == 0); | ||
231 | |||
232 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
233 | if (status != PCIBIOS_SUCCESSFUL) | ||
234 | return status; | ||
235 | |||
236 | if (where & 2) | ||
237 | shift += 16; | ||
238 | result &= ~(0xffff << shift); | ||
239 | result |= val << shift; | ||
240 | return write_config_dword(swap, dev, where & ~3, result); | ||
241 | } | ||
242 | |||
243 | static int write_config_byte(struct pci_config_swap *swap, | ||
244 | struct pci_dev *dev, u32 where, u8 val) | ||
245 | { | ||
246 | int status, shift = 0; | ||
247 | u32 result; | ||
248 | |||
249 | status = read_config_dword(swap, dev, where & ~3, &result); | ||
250 | if (status != PCIBIOS_SUCCESSFUL) | ||
251 | return status; | ||
252 | |||
253 | if (where & 2) | ||
254 | shift += 16; | ||
255 | if (where & 1) | ||
256 | shift += 8; | ||
257 | result &= ~(0xff << shift); | ||
258 | result |= val << shift; | ||
259 | return write_config_dword(swap, dev, where & ~3, result); | ||
260 | } | ||
261 | |||
262 | #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ | ||
263 | static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ | ||
264 | { \ | ||
265 | return rw##_config_##unitname(pciswap, \ | ||
266 | dev, \ | ||
267 | where, \ | ||
268 | val); \ | ||
269 | } | ||
270 | |||
271 | MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) | ||
272 | MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) | ||
273 | MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) | ||
274 | |||
275 | MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) | ||
276 | MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) | ||
277 | MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) | ||
278 | |||
279 | struct pci_ops ddb5476_ext_pci_ops = { | ||
280 | extpci_read_config_byte, | ||
281 | extpci_read_config_word, | ||
282 | extpci_read_config_dword, | ||
283 | extpci_write_config_byte, | ||
284 | extpci_write_config_word, | ||
285 | extpci_write_config_dword | ||
286 | }; | ||
diff --git a/arch/mips/pci/ops-ddb5477.c b/arch/mips/pci/ops-ddb5477.c new file mode 100644 index 000000000000..e955443fedf9 --- /dev/null +++ b/arch/mips/pci/ops-ddb5477.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /*********************************************************************** | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * arch/mips/ddb5xxx/ddb5477/pci_ops.c | ||
6 | * Define the pci_ops for DB5477. | ||
7 | * | ||
8 | * Much of the code is derived from the original DDB5074 port by | ||
9 | * Geert Uytterhoeven <geert@sonycom.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | *********************************************************************** | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * DDB5477 has two PCI channels, external PCI and IOPIC (internal) | ||
20 | * Therefore we provide two sets of pci_ops. | ||
21 | */ | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/types.h> | ||
25 | |||
26 | #include <asm/addrspace.h> | ||
27 | #include <asm/debug.h> | ||
28 | |||
29 | #include <asm/ddb5xxx/ddb5xxx.h> | ||
30 | |||
31 | /* | ||
32 | * config_swap structure records what set of pdar/pmr are used | ||
33 | * to access pci config space. It also provides a place hold the | ||
34 | * original values for future restoring. | ||
35 | */ | ||
36 | struct pci_config_swap { | ||
37 | u32 pdar; | ||
38 | u32 pmr; | ||
39 | u32 config_base; | ||
40 | u32 config_size; | ||
41 | u32 pdar_backup; | ||
42 | u32 pmr_backup; | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI. | ||
47 | */ | ||
48 | struct pci_config_swap ext_pci_swap = { | ||
49 | DDB_PCIW0, | ||
50 | DDB_PCIINIT00, | ||
51 | DDB_PCI0_CONFIG_BASE, | ||
52 | DDB_PCI0_CONFIG_SIZE | ||
53 | }; | ||
54 | struct pci_config_swap io_pci_swap = { | ||
55 | DDB_IOPCIW0, | ||
56 | DDB_PCIINIT01, | ||
57 | DDB_PCI1_CONFIG_BASE, | ||
58 | DDB_PCI1_CONFIG_SIZE | ||
59 | }; | ||
60 | |||
61 | |||
62 | /* | ||
63 | * access config space | ||
64 | */ | ||
65 | static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ | ||
66 | u32 slot_num) | ||
67 | { | ||
68 | u32 pci_addr = 0; | ||
69 | u32 pciinit_offset = 0; | ||
70 | u32 virt_addr; | ||
71 | u32 option; | ||
72 | |||
73 | /* minimum pdar (window) size is 2MB */ | ||
74 | db_assert(swap->config_size >= (2 << 20)); | ||
75 | |||
76 | db_assert(slot_num < (1 << 5)); | ||
77 | db_assert(bus < (1 << 8)); | ||
78 | |||
79 | /* backup registers */ | ||
80 | swap->pdar_backup = ddb_in32(swap->pdar); | ||
81 | swap->pmr_backup = ddb_in32(swap->pmr); | ||
82 | |||
83 | /* set the pdar (pci window) register */ | ||
84 | ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ | ||
85 | 0, /* not on local memory bus */ | ||
86 | 0); /* not visible from PCI bus (N/A) */ | ||
87 | |||
88 | /* | ||
89 | * calcuate the absolute pci config addr; | ||
90 | * according to the spec, we start scanning from adr:11 (0x800) | ||
91 | */ | ||
92 | if (bus == 0) { | ||
93 | /* type 0 config */ | ||
94 | pci_addr = 0x800 << slot_num; | ||
95 | } else { | ||
96 | /* type 1 config */ | ||
97 | pci_addr = (bus << 16) | (slot_num << 11); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * if pci_addr is less than pci config window size, we set | ||
102 | * pciinit_offset to 0 and adjust the virt_address. | ||
103 | * Otherwise we will try to adjust pciinit_offset. | ||
104 | */ | ||
105 | if (pci_addr < swap->config_size) { | ||
106 | virt_addr = KSEG1ADDR(swap->config_base + pci_addr); | ||
107 | pciinit_offset = 0; | ||
108 | } else { | ||
109 | db_assert((pci_addr & (swap->config_size - 1)) == 0); | ||
110 | virt_addr = KSEG1ADDR(swap->config_base); | ||
111 | pciinit_offset = pci_addr; | ||
112 | } | ||
113 | |||
114 | /* set the pmr register */ | ||
115 | option = DDB_PCI_ACCESS_32; | ||
116 | if (bus != 0) | ||
117 | option |= DDB_PCI_CFGTYPE1; | ||
118 | ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); | ||
119 | |||
120 | return virt_addr; | ||
121 | } | ||
122 | |||
123 | static inline void ddb_close_config_base(struct pci_config_swap *swap) | ||
124 | { | ||
125 | ddb_out32(swap->pdar, swap->pdar_backup); | ||
126 | ddb_out32(swap->pmr, swap->pmr_backup); | ||
127 | } | ||
128 | |||
129 | static int read_config_dword(struct pci_config_swap *swap, | ||
130 | struct pci_bus *bus, u32 devfn, u32 where, | ||
131 | u32 * val) | ||
132 | { | ||
133 | u32 bus_num, slot_num, func_num; | ||
134 | u32 base; | ||
135 | |||
136 | db_assert((where & 3) == 0); | ||
137 | db_assert(where < (1 << 8)); | ||
138 | |||
139 | /* check if the bus is top-level */ | ||
140 | if (bus->parent != NULL) { | ||
141 | bus_num = bus->number; | ||
142 | db_assert(bus_num != 0); | ||
143 | } else { | ||
144 | bus_num = 0; | ||
145 | } | ||
146 | |||
147 | slot_num = PCI_SLOT(devfn); | ||
148 | func_num = PCI_FUNC(devfn); | ||
149 | base = ddb_access_config_base(swap, bus_num, slot_num); | ||
150 | *val = *(volatile u32 *) (base + (func_num << 8) + where); | ||
151 | ddb_close_config_base(swap); | ||
152 | return PCIBIOS_SUCCESSFUL; | ||
153 | } | ||
154 | |||
155 | static int read_config_word(struct pci_config_swap *swap, | ||
156 | struct pci_bus *bus, u32 devfn, u32 where, | ||
157 | u16 * val) | ||
158 | { | ||
159 | int status; | ||
160 | u32 result; | ||
161 | |||
162 | db_assert((where & 1) == 0); | ||
163 | |||
164 | status = read_config_dword(swap, bus, devfn, where & ~3, &result); | ||
165 | if (where & 2) | ||
166 | result >>= 16; | ||
167 | *val = result & 0xffff; | ||
168 | return status; | ||
169 | } | ||
170 | |||
171 | static int read_config_byte(struct pci_config_swap *swap, | ||
172 | struct pci_bus *bus, u32 devfn, u32 where, | ||
173 | u8 * val) | ||
174 | { | ||
175 | int status; | ||
176 | u32 result; | ||
177 | |||
178 | status = read_config_dword(swap, bus, devfn, where & ~3, &result); | ||
179 | if (where & 1) | ||
180 | result >>= 8; | ||
181 | if (where & 2) | ||
182 | result >>= 16; | ||
183 | *val = result & 0xff; | ||
184 | |||
185 | return status; | ||
186 | } | ||
187 | |||
188 | static int write_config_dword(struct pci_config_swap *swap, | ||
189 | struct pci_bus *bus, u32 devfn, u32 where, | ||
190 | u32 val) | ||
191 | { | ||
192 | u32 bus_num, slot_num, func_num; | ||
193 | u32 base; | ||
194 | |||
195 | db_assert((where & 3) == 0); | ||
196 | db_assert(where < (1 << 8)); | ||
197 | |||
198 | /* check if the bus is top-level */ | ||
199 | if (bus->parent != NULL) { | ||
200 | bus_num = bus->number; | ||
201 | db_assert(bus_num != 0); | ||
202 | } else { | ||
203 | bus_num = 0; | ||
204 | } | ||
205 | |||
206 | slot_num = PCI_SLOT(devfn); | ||
207 | func_num = PCI_FUNC(devfn); | ||
208 | base = ddb_access_config_base(swap, bus_num, slot_num); | ||
209 | *(volatile u32 *) (base + (func_num << 8) + where) = val; | ||
210 | ddb_close_config_base(swap); | ||
211 | return PCIBIOS_SUCCESSFUL; | ||
212 | } | ||
213 | |||
214 | static int write_config_word(struct pci_config_swap *swap, | ||
215 | struct pci_bus *bus, u32 devfn, u32 where, u16 val) | ||
216 | { | ||
217 | int status, shift = 0; | ||
218 | u32 result; | ||
219 | |||
220 | db_assert((where & 1) == 0); | ||
221 | |||
222 | status = read_config_dword(swap, bus, devfn, where & ~3, &result); | ||
223 | if (status != PCIBIOS_SUCCESSFUL) | ||
224 | return status; | ||
225 | |||
226 | if (where & 2) | ||
227 | shift += 16; | ||
228 | result &= ~(0xffff << shift); | ||
229 | result |= val << shift; | ||
230 | return write_config_dword(swap, bus, devfn, where & ~3, result); | ||
231 | } | ||
232 | |||
233 | static int write_config_byte(struct pci_config_swap *swap, | ||
234 | struct pci_bus *bus, u32 devfn, u32 where, u8 val) | ||
235 | { | ||
236 | int status, shift = 0; | ||
237 | u32 result; | ||
238 | |||
239 | status = read_config_dword(swap, bus, devfn, where & ~3, &result); | ||
240 | if (status != PCIBIOS_SUCCESSFUL) | ||
241 | return status; | ||
242 | |||
243 | if (where & 2) | ||
244 | shift += 16; | ||
245 | if (where & 1) | ||
246 | shift += 8; | ||
247 | result &= ~(0xff << shift); | ||
248 | result |= val << shift; | ||
249 | return write_config_dword(swap, bus, devfn, where & ~3, result); | ||
250 | } | ||
251 | |||
252 | #define MAKE_PCI_OPS(prefix, rw, pciswap, star) \ | ||
253 | static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \ | ||
254 | { \ | ||
255 | if (size == 1) \ | ||
256 | return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \ | ||
257 | else if (size == 2) \ | ||
258 | return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \ | ||
259 | /* Size must be 4 */ \ | ||
260 | return rw##_config_dword(pciswap, bus, devfn, where, val); \ | ||
261 | } | ||
262 | |||
263 | MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *) | ||
264 | MAKE_PCI_OPS(extpci, write, &ext_pci_swap,) | ||
265 | |||
266 | MAKE_PCI_OPS(iopci, read, &io_pci_swap, *) | ||
267 | MAKE_PCI_OPS(iopci, write, &io_pci_swap,) | ||
268 | |||
269 | struct pci_ops ddb5477_ext_pci_ops = { | ||
270 | .read = extpci_read_config, | ||
271 | .write = extpci_write_config | ||
272 | }; | ||
273 | |||
274 | |||
275 | struct pci_ops ddb5477_io_pci_ops = { | ||
276 | .read = iopci_read_config, | ||
277 | .write = iopci_write_config | ||
278 | }; | ||
diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c new file mode 100644 index 000000000000..c5b0fc184c2a --- /dev/null +++ b/arch/mips/pci/ops-gt64111.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 1995, 1996, 1997, 2002 by Ralf Baechle | ||
7 | * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) | ||
8 | */ | ||
9 | #include <linux/types.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | |||
14 | #include <asm/pci.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <asm/gt64120.h> | ||
17 | |||
18 | #include <asm/cobalt/cobalt.h> | ||
19 | |||
20 | /* | ||
21 | * Accessing device 31 hangs the GT64120. Not sure if this will also hang | ||
22 | * the GT64111, let's be paranoid for now. | ||
23 | */ | ||
24 | static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn) | ||
25 | { | ||
26 | if (bus->number == 0 && devfn == PCI_DEVFN(31, 0)) | ||
27 | return -1; | ||
28 | |||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
33 | int where, int size, u32 * val) | ||
34 | { | ||
35 | if (pci_range_ck(bus, devfn)) | ||
36 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
37 | |||
38 | switch (size) { | ||
39 | case 4: | ||
40 | PCI_CFG_SET(devfn, where); | ||
41 | *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS); | ||
42 | return PCIBIOS_SUCCESSFUL; | ||
43 | |||
44 | case 2: | ||
45 | PCI_CFG_SET(devfn, (where & ~0x3)); | ||
46 | *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) | ||
47 | >> ((where & 3) * 8); | ||
48 | return PCIBIOS_SUCCESSFUL; | ||
49 | |||
50 | case 1: | ||
51 | PCI_CFG_SET(devfn, (where & ~0x3)); | ||
52 | *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) | ||
53 | >> ((where & 3) * 8); | ||
54 | return PCIBIOS_SUCCESSFUL; | ||
55 | } | ||
56 | |||
57 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
58 | } | ||
59 | |||
60 | static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
61 | int where, int size, u32 val) | ||
62 | { | ||
63 | u32 tmp; | ||
64 | |||
65 | if (pci_range_ck(bus, devfn)) | ||
66 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
67 | |||
68 | switch (size) { | ||
69 | case 4: | ||
70 | PCI_CFG_SET(devfn, where); | ||
71 | GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS); | ||
72 | |||
73 | return PCIBIOS_SUCCESSFUL; | ||
74 | |||
75 | case 2: | ||
76 | PCI_CFG_SET(devfn, (where & ~0x3)); | ||
77 | tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); | ||
78 | tmp &= ~(0xffff << ((where & 0x3) * 8)); | ||
79 | tmp |= (val << ((where & 0x3) * 8)); | ||
80 | GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); | ||
81 | |||
82 | return PCIBIOS_SUCCESSFUL; | ||
83 | |||
84 | case 1: | ||
85 | PCI_CFG_SET(devfn, (where & ~0x3)); | ||
86 | tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); | ||
87 | tmp &= ~(0xff << ((where & 0x3) * 8)); | ||
88 | tmp |= (val << ((where & 0x3) * 8)); | ||
89 | GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); | ||
90 | |||
91 | return PCIBIOS_SUCCESSFUL; | ||
92 | } | ||
93 | |||
94 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
95 | } | ||
96 | |||
97 | struct pci_ops gt64111_pci_ops = { | ||
98 | .read = gt64111_pci_read_config, | ||
99 | .write = gt64111_pci_write_config, | ||
100 | }; | ||
diff --git a/arch/mips/pci/ops-gt64120.c b/arch/mips/pci/ops-gt64120.c new file mode 100644 index 000000000000..7b99dfa33dfc --- /dev/null +++ b/arch/mips/pci/ops-gt64120.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | */ | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #include <asm/gt64120.h> | ||
23 | |||
24 | #define PCI_ACCESS_READ 0 | ||
25 | #define PCI_ACCESS_WRITE 1 | ||
26 | |||
27 | /* | ||
28 | * PCI configuration cycle AD bus definition | ||
29 | */ | ||
30 | /* Type 0 */ | ||
31 | #define PCI_CFG_TYPE0_REG_SHF 0 | ||
32 | #define PCI_CFG_TYPE0_FUNC_SHF 8 | ||
33 | |||
34 | /* Type 1 */ | ||
35 | #define PCI_CFG_TYPE1_REG_SHF 0 | ||
36 | #define PCI_CFG_TYPE1_FUNC_SHF 8 | ||
37 | #define PCI_CFG_TYPE1_DEV_SHF 11 | ||
38 | #define PCI_CFG_TYPE1_BUS_SHF 16 | ||
39 | |||
40 | static int gt64120_pcibios_config_access(unsigned char access_type, | ||
41 | struct pci_bus *bus, unsigned int devfn, int where, u32 * data) | ||
42 | { | ||
43 | unsigned char busnum = bus->number; | ||
44 | u32 intr; | ||
45 | |||
46 | if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) | ||
47 | /* Galileo itself is devfn 0, don't move it around */ | ||
48 | return -1; | ||
49 | |||
50 | if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0))) | ||
51 | return -1; /* Because of a bug in the galileo (for slot 31). */ | ||
52 | |||
53 | /* Clear cause register bits */ | ||
54 | GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | | ||
55 | GT_INTRCAUSE_TARABORT0_BIT)); | ||
56 | |||
57 | /* Setup address */ | ||
58 | GT_WRITE(GT_PCI0_CFGADDR_OFS, | ||
59 | (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | | ||
60 | (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | | ||
61 | ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | | ||
62 | GT_PCI0_CFGADDR_CONFIGEN_BIT); | ||
63 | |||
64 | if (access_type == PCI_ACCESS_WRITE) { | ||
65 | if (busnum == 0 && PCI_SLOT(devfn) == 0) { | ||
66 | /* | ||
67 | * The Galileo system controller is acting | ||
68 | * differently than other devices. | ||
69 | */ | ||
70 | GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); | ||
71 | } else | ||
72 | __GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); | ||
73 | } else { | ||
74 | if (busnum == 0 && PCI_SLOT(devfn) == 0) { | ||
75 | /* | ||
76 | * The Galileo system controller is acting | ||
77 | * differently than other devices. | ||
78 | */ | ||
79 | *data = GT_READ(GT_PCI0_CFGDATA_OFS); | ||
80 | } else | ||
81 | *data = __GT_READ(GT_PCI0_CFGDATA_OFS); | ||
82 | } | ||
83 | |||
84 | /* Check for master or target abort */ | ||
85 | intr = GT_READ(GT_INTRCAUSE_OFS); | ||
86 | |||
87 | if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { | ||
88 | /* Error occurred */ | ||
89 | |||
90 | /* Clear bits */ | ||
91 | GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | | ||
92 | GT_INTRCAUSE_TARABORT0_BIT)); | ||
93 | |||
94 | return -1; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | /* | ||
102 | * We can't address 8 and 16 bit words directly. Instead we have to | ||
103 | * read/write a 32bit word and mask/modify the data we actually want. | ||
104 | */ | ||
105 | static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
106 | int where, int size, u32 * val) | ||
107 | { | ||
108 | u32 data = 0; | ||
109 | |||
110 | if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | ||
111 | &data)) | ||
112 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
113 | |||
114 | if (size == 1) | ||
115 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
116 | else if (size == 2) | ||
117 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
118 | else | ||
119 | *val = data; | ||
120 | |||
121 | return PCIBIOS_SUCCESSFUL; | ||
122 | } | ||
123 | |||
124 | static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
125 | int where, int size, u32 val) | ||
126 | { | ||
127 | u32 data = 0; | ||
128 | |||
129 | if (size == 4) | ||
130 | data = val; | ||
131 | else { | ||
132 | if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, | ||
133 | where, &data)) | ||
134 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
135 | |||
136 | if (size == 1) | ||
137 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
138 | (val << ((where & 3) << 3)); | ||
139 | else if (size == 2) | ||
140 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
141 | (val << ((where & 3) << 3)); | ||
142 | } | ||
143 | |||
144 | if (gt64120_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, | ||
145 | &data)) | ||
146 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
147 | |||
148 | return PCIBIOS_SUCCESSFUL; | ||
149 | } | ||
150 | |||
151 | struct pci_ops gt64120_pci_ops = { | ||
152 | .read = gt64120_pcibios_read, | ||
153 | .write = gt64120_pcibios_write | ||
154 | }; | ||
diff --git a/arch/mips/pci/ops-gt96100.c b/arch/mips/pci/ops-gt96100.c new file mode 100644 index 000000000000..9e4ea6627e21 --- /dev/null +++ b/arch/mips/pci/ops-gt96100.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * Galileo EV96100 board specific pci support. | ||
5 | * | ||
6 | * Copyright 2000 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ppopov@mvista.com or source@mvista.com | ||
9 | * | ||
10 | * This file was derived from Carsten Langgaard's | ||
11 | * arch/mips/mips-boards/generic/pci.c | ||
12 | * | ||
13 | * Carsten Langgaard, carstenl@mips.com | ||
14 | * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify it | ||
17 | * under the terms of the GNU General Public License as published by the | ||
18 | * Free Software Foundation; either version 2 of the License, or (at your | ||
19 | * option) any later version. | ||
20 | * | ||
21 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
23 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
24 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
27 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
28 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License along | ||
33 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
34 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
35 | */ | ||
36 | #include <linux/types.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/init.h> | ||
40 | |||
41 | #include <asm/delay.h> | ||
42 | #include <asm/gt64120.h> | ||
43 | #include <asm/galileo-boards/ev96100.h> | ||
44 | |||
45 | #define PCI_ACCESS_READ 0 | ||
46 | #define PCI_ACCESS_WRITE 1 | ||
47 | |||
48 | static int static gt96100_config_access(unsigned char access_type, | ||
49 | struct pci_bus *bus, unsigned int devfn, int where, u32 * data) | ||
50 | { | ||
51 | unsigned char bus = bus->number; | ||
52 | u32 intr; | ||
53 | |||
54 | /* | ||
55 | * Because of a bug in the galileo (for slot 31). | ||
56 | */ | ||
57 | if (bus == 0 && devfn >= PCI_DEVFN(31, 0)) | ||
58 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
59 | |||
60 | /* Clear cause register bits */ | ||
61 | GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | | ||
62 | GT_INTRCAUSE_TARABORT0_BIT)); | ||
63 | |||
64 | /* Setup address */ | ||
65 | GT_WRITE(GT_PCI0_CFGADDR_OFS, | ||
66 | (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | | ||
67 | (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | | ||
68 | ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | | ||
69 | GT_PCI0_CFGADDR_CONFIGEN_BIT); | ||
70 | udelay(2); | ||
71 | |||
72 | |||
73 | if (access_type == PCI_ACCESS_WRITE) { | ||
74 | if (devfn != 0) | ||
75 | *data = le32_to_cpu(*data); | ||
76 | GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); | ||
77 | } else { | ||
78 | *data = GT_READ(GT_PCI0_CFGDATA_OFS); | ||
79 | if (devfn != 0) | ||
80 | *data = le32_to_cpu(*data); | ||
81 | } | ||
82 | |||
83 | udelay(2); | ||
84 | |||
85 | /* Check for master or target abort */ | ||
86 | intr = GT_READ(GT_INTRCAUSE_OFS); | ||
87 | |||
88 | if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { | ||
89 | /* Error occured */ | ||
90 | |||
91 | /* Clear bits */ | ||
92 | GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | | ||
93 | GT_INTRCAUSE_TARABORT0_BIT)); | ||
94 | return -1; | ||
95 | } | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * We can't address 8 and 16 bit words directly. Instead we have to | ||
101 | * read/write a 32bit word and mask/modify the data we actually want. | ||
102 | */ | ||
103 | static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
104 | int where, int size, u32 * val) | ||
105 | { | ||
106 | u32 data = 0; | ||
107 | |||
108 | if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) | ||
109 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
110 | |||
111 | switch (size) { | ||
112 | case 1: | ||
113 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
114 | break; | ||
115 | |||
116 | case 2: | ||
117 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
118 | break; | ||
119 | |||
120 | case 4: | ||
121 | *val = data; | ||
122 | break; | ||
123 | } | ||
124 | return PCIBIOS_SUCCESSFUL; | ||
125 | } | ||
126 | |||
127 | static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
128 | int where, int size, u32 val) | ||
129 | { | ||
130 | u32 data = 0; | ||
131 | |||
132 | switch (size) { | ||
133 | case 1: | ||
134 | if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) | ||
135 | return -1; | ||
136 | |||
137 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
138 | (val << ((where & 3) << 3)); | ||
139 | |||
140 | if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) | ||
141 | return -1; | ||
142 | |||
143 | return PCIBIOS_SUCCESSFUL; | ||
144 | |||
145 | case 2: | ||
146 | if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) | ||
147 | return -1; | ||
148 | |||
149 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
150 | (val << ((where & 3) << 3)); | ||
151 | |||
152 | if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data)) | ||
153 | return -1; | ||
154 | |||
155 | |||
156 | return PCIBIOS_SUCCESSFUL; | ||
157 | |||
158 | case 4: | ||
159 | if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val)) | ||
160 | return -1; | ||
161 | |||
162 | return PCIBIOS_SUCCESSFUL; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | struct pci_ops gt96100_pci_ops = { | ||
167 | .read = gt96100_pcibios_read, | ||
168 | .write = gt96100_pcibios_write | ||
169 | }; | ||
diff --git a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c new file mode 100644 index 000000000000..b7a8b9a6f9db --- /dev/null +++ b/arch/mips/pci/ops-it8172.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * | ||
3 | * BRIEF MODULE DESCRIPTION | ||
4 | * IT8172 system controller specific pci support. | ||
5 | * | ||
6 | * Copyright 2000 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ppopov@mvista.com or source@mvista.com | ||
9 | * | ||
10 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
20 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
23 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License along | ||
29 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
30 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
31 | */ | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/init.h> | ||
36 | |||
37 | #include <asm/it8172/it8172.h> | ||
38 | #include <asm/it8172/it8172_pci.h> | ||
39 | |||
40 | #define PCI_ACCESS_READ 0 | ||
41 | #define PCI_ACCESS_WRITE 1 | ||
42 | |||
43 | #undef DEBUG | ||
44 | #ifdef DEBUG | ||
45 | #define DBG(x...) printk(x) | ||
46 | #else | ||
47 | #define DBG(x...) | ||
48 | #endif | ||
49 | |||
50 | static struct resource pci_mem_resource_1; | ||
51 | |||
52 | static struct resource pci_io_resource = { | ||
53 | "io pci IO space", | ||
54 | 0x14018000, | ||
55 | 0x17FFFFFF, | ||
56 | IORESOURCE_IO | ||
57 | }; | ||
58 | |||
59 | static struct resource pci_mem_resource_0 = { | ||
60 | "ext pci memory space 0/1", | ||
61 | 0x10101000, | ||
62 | 0x13FFFFFF, | ||
63 | IORESOURCE_MEM, | ||
64 | &pci_mem_resource_0, | ||
65 | NULL, | ||
66 | &pci_mem_resource_1 | ||
67 | }; | ||
68 | |||
69 | static struct resource pci_mem_resource_1 = { | ||
70 | "ext pci memory space 2/3", | ||
71 | 0x1A000000, | ||
72 | 0x1FBFFFFF, | ||
73 | IORESOURCE_MEM, | ||
74 | &pci_mem_resource_0, | ||
75 | NULL, | ||
76 | NULL | ||
77 | }; | ||
78 | |||
79 | extern struct pci_ops it8172_pci_ops; | ||
80 | |||
81 | struct pci_controller it8172_controller = { | ||
82 | .pci_ops = &it8172_pci_ops, | ||
83 | .io_resource = &pci_io_resource, | ||
84 | .mem_resource = &pci_mem_resource_0, | ||
85 | }; | ||
86 | |||
87 | static int it8172_pcibios_config_access(unsigned char access_type, | ||
88 | struct pci_bus *bus, | ||
89 | unsigned int devfn, int where, | ||
90 | u32 * data) | ||
91 | { | ||
92 | /* | ||
93 | * config cycles are on 4 byte boundary only | ||
94 | */ | ||
95 | |||
96 | /* Setup address */ | ||
97 | IT_WRITE(IT_CONFADDR, (bus->number << IT_BUSNUM_SHF) | | ||
98 | (devfn << IT_FUNCNUM_SHF) | (where & ~0x3)); | ||
99 | |||
100 | if (access_type == PCI_ACCESS_WRITE) { | ||
101 | IT_WRITE(IT_CONFDATA, *data); | ||
102 | } else { | ||
103 | IT_READ(IT_CONFDATA, *data); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Revisit: check for master or target abort. | ||
108 | */ | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | |||
113 | /* | ||
114 | * We can't address 8 and 16 bit words directly. Instead we have to | ||
115 | * read/write a 32bit word and mask/modify the data we actually want. | ||
116 | */ | ||
117 | static write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
118 | int size, u32 val) | ||
119 | { | ||
120 | u32 data = 0; | ||
121 | |||
122 | switch (size) { | ||
123 | case 1: | ||
124 | if (it8172_pcibios_config_access | ||
125 | (PCI_ACCESS_READ, dev, where, &data)) | ||
126 | return -1; | ||
127 | |||
128 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
129 | |||
130 | return PCIBIOS_SUCCESSFUL; | ||
131 | |||
132 | case 2: | ||
133 | |||
134 | if (where & 1) | ||
135 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
136 | |||
137 | if (it8172_pcibios_config_access | ||
138 | (PCI_ACCESS_READ, dev, where, &data)) | ||
139 | return -1; | ||
140 | |||
141 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
142 | DBG("cfg read word: bus %d dev_fn %x where %x: val %x\n", | ||
143 | dev->bus->number, dev->devfn, where, *val); | ||
144 | |||
145 | return PCIBIOS_SUCCESSFUL; | ||
146 | |||
147 | case 4: | ||
148 | |||
149 | if (where & 3) | ||
150 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
151 | |||
152 | if (it8172_pcibios_config_access | ||
153 | (PCI_ACCESS_READ, dev, where, &data)) | ||
154 | return -1; | ||
155 | |||
156 | *val = data; | ||
157 | |||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | |||
163 | static write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
164 | int size, u32 val) | ||
165 | { | ||
166 | u32 data = 0; | ||
167 | |||
168 | switch (size) { | ||
169 | case 1: | ||
170 | if (it8172_pcibios_config_access | ||
171 | (PCI_ACCESS_READ, dev, where, &data)) | ||
172 | return -1; | ||
173 | |||
174 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
175 | (val << ((where & 3) << 3)); | ||
176 | |||
177 | if (it8172_pcibios_config_access | ||
178 | (PCI_ACCESS_WRITE, dev, where, &data)) | ||
179 | return -1; | ||
180 | |||
181 | return PCIBIOS_SUCCESSFUL; | ||
182 | |||
183 | case 2: | ||
184 | if (where & 1) | ||
185 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
186 | |||
187 | if (it8172_pcibios_config_access | ||
188 | (PCI_ACCESS_READ, dev, where, &data)) | ||
189 | eturn - 1; | ||
190 | |||
191 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
192 | (val << ((where & 3) << 3)); | ||
193 | |||
194 | if (it8172_pcibios_config_access | ||
195 | (PCI_ACCESS_WRITE, dev, where, &data)) | ||
196 | return -1; | ||
197 | |||
198 | return PCIBIOS_SUCCESSFUL; | ||
199 | |||
200 | case 4: | ||
201 | if (where & 3) | ||
202 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
203 | |||
204 | if (it8172_pcibios_config_access | ||
205 | (PCI_ACCESS_WRITE, dev, where, &val)) | ||
206 | return -1; | ||
207 | |||
208 | return PCIBIOS_SUCCESSFUL; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | struct pci_ops it8172_pci_ops = { | ||
213 | .read = read_config, | ||
214 | .write = write_config, | ||
215 | }; | ||
diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c new file mode 100644 index 000000000000..8008e31c5e81 --- /dev/null +++ b/arch/mips/pci/ops-mace.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 Keith M Wesolowski | ||
7 | */ | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <asm/pci.h> | ||
13 | #include <asm/ip32/mace.h> | ||
14 | |||
15 | #if 0 | ||
16 | # define DPRINTK(args...) printk(args); | ||
17 | #else | ||
18 | # define DPRINTK(args...) | ||
19 | #endif | ||
20 | |||
21 | /* | ||
22 | * O2 has up to 5 PCI devices connected into the MACE bridge. The device | ||
23 | * map looks like this: | ||
24 | * | ||
25 | * 0 aic7xxx 0 | ||
26 | * 1 aic7xxx 1 | ||
27 | * 2 expansion slot | ||
28 | * 3 N/C | ||
29 | * 4 N/C | ||
30 | */ | ||
31 | |||
32 | #define chkslot(_bus,_devfn) \ | ||
33 | do { \ | ||
34 | if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \ | ||
35 | || PCI_SLOT (_devfn) > 3) \ | ||
36 | return PCIBIOS_DEVICE_NOT_FOUND; \ | ||
37 | } while (0) | ||
38 | |||
39 | #define mkaddr(_devfn, _reg) \ | ||
40 | ((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL)) | ||
41 | |||
42 | static int | ||
43 | mace_pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
44 | int reg, int size, u32 *val) | ||
45 | { | ||
46 | chkslot(bus, devfn); | ||
47 | mace->pci.config_addr = mkaddr(devfn, reg); | ||
48 | switch (size) { | ||
49 | case 1: | ||
50 | *val = mace->pci.config_data.b[(reg & 3) ^ 3]; | ||
51 | break; | ||
52 | case 2: | ||
53 | *val = mace->pci.config_data.w[((reg >> 1) & 1) ^ 1]; | ||
54 | break; | ||
55 | case 4: | ||
56 | *val = mace->pci.config_data.l; | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | DPRINTK("read%d: reg=%08x,val=%02x\n", size * 8, reg, *val); | ||
61 | |||
62 | return PCIBIOS_SUCCESSFUL; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | mace_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
67 | int reg, int size, u32 val) | ||
68 | { | ||
69 | chkslot(bus, devfn); | ||
70 | mace->pci.config_addr = mkaddr(devfn, reg); | ||
71 | switch (size) { | ||
72 | case 1: | ||
73 | mace->pci.config_data.b[(reg & 3) ^ 3] = val; | ||
74 | break; | ||
75 | case 2: | ||
76 | mace->pci.config_data.w[((reg >> 1) & 1) ^ 1] = val; | ||
77 | break; | ||
78 | case 4: | ||
79 | mace->pci.config_data.l = val; | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | DPRINTK("write%d: reg=%08x,val=%02x\n", size * 8, reg, val); | ||
84 | |||
85 | return PCIBIOS_SUCCESSFUL; | ||
86 | } | ||
87 | |||
88 | struct pci_ops mace_pci_ops = { | ||
89 | .read = mace_pci_read_config, | ||
90 | .write = mace_pci_write_config, | ||
91 | }; | ||
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c new file mode 100644 index 000000000000..1ac5c59199d1 --- /dev/null +++ b/arch/mips/pci/ops-marvell.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) | ||
7 | */ | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/types.h> | ||
10 | #include <linux/pci.h> | ||
11 | |||
12 | #include <asm/marvell.h> | ||
13 | |||
14 | static int mv_read_config(struct pci_bus *bus, unsigned int devfn, | ||
15 | int where, int size, u32 * val) | ||
16 | { | ||
17 | struct mv_pci_controller *mvbc = bus->sysdata; | ||
18 | unsigned long address_reg, data_reg; | ||
19 | u32 address; | ||
20 | |||
21 | address_reg = mvbc->config_addr; | ||
22 | data_reg = mvbc->config_vreg; | ||
23 | |||
24 | /* Accessing device 31 crashes those Marvells. Since years. | ||
25 | Will they ever make sane controllers ... */ | ||
26 | if (PCI_SLOT(devfn) == 31) | ||
27 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
28 | |||
29 | address = (bus->number << 16) | (devfn << 8) | | ||
30 | (where & 0xfc) | 0x80000000; | ||
31 | |||
32 | /* start the configuration cycle */ | ||
33 | MV_WRITE(address_reg, address); | ||
34 | |||
35 | switch (size) { | ||
36 | case 1: | ||
37 | *val = MV_READ_8(data_reg + (where & 0x3)); | ||
38 | break; | ||
39 | |||
40 | case 2: | ||
41 | *val = MV_READ_16(data_reg + (where & 0x3)); | ||
42 | break; | ||
43 | |||
44 | case 4: | ||
45 | *val = MV_READ(data_reg); | ||
46 | break; | ||
47 | } | ||
48 | |||
49 | return PCIBIOS_SUCCESSFUL; | ||
50 | } | ||
51 | |||
52 | static int mv_write_config(struct pci_bus *bus, unsigned int devfn, | ||
53 | int where, int size, u32 val) | ||
54 | { | ||
55 | struct mv_pci_controller *mvbc = bus->sysdata; | ||
56 | unsigned long address_reg, data_reg; | ||
57 | u32 address; | ||
58 | |||
59 | address_reg = mvbc->config_addr; | ||
60 | data_reg = mvbc->config_vreg; | ||
61 | |||
62 | /* Accessing device 31 crashes those Marvells. Since years. | ||
63 | Will they ever make sane controllers ... */ | ||
64 | if (PCI_SLOT(devfn) == 31) | ||
65 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
66 | |||
67 | address = (bus->number << 16) | (devfn << 8) | | ||
68 | (where & 0xfc) | 0x80000000; | ||
69 | |||
70 | /* start the configuration cycle */ | ||
71 | MV_WRITE(address_reg, address); | ||
72 | |||
73 | switch (size) { | ||
74 | case 1: | ||
75 | MV_WRITE_8(data_reg + (where & 0x3), val); | ||
76 | break; | ||
77 | |||
78 | case 2: | ||
79 | MV_WRITE_16(data_reg + (where & 0x3), val); | ||
80 | break; | ||
81 | |||
82 | case 4: | ||
83 | MV_WRITE(data_reg, val); | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | return PCIBIOS_SUCCESSFUL; | ||
88 | } | ||
89 | |||
90 | struct pci_ops mv_pci_ops = { | ||
91 | .read = mv_read_config, | ||
92 | .write = mv_write_config | ||
93 | }; | ||
diff --git a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c new file mode 100644 index 000000000000..7bc099643a9d --- /dev/null +++ b/arch/mips/pci/ops-msc.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc. | ||
3 | * All rights reserved. | ||
4 | * Authors: Carsten Langgaard <carstenl@mips.com> | ||
5 | * Maciej W. Rozycki <macro@mips.com> | ||
6 | * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) | ||
7 | * | ||
8 | * This program is free software; you can distribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License (Version 2) as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
15 | * for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
20 | * | ||
21 | * MIPS boards specific PCI support. | ||
22 | * | ||
23 | */ | ||
24 | #include <linux/config.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | |||
30 | #include <asm/mips-boards/msc01_pci.h> | ||
31 | |||
32 | #define PCI_ACCESS_READ 0 | ||
33 | #define PCI_ACCESS_WRITE 1 | ||
34 | |||
35 | /* | ||
36 | * PCI configuration cycle AD bus definition | ||
37 | */ | ||
38 | /* Type 0 */ | ||
39 | #define PCI_CFG_TYPE0_REG_SHF 0 | ||
40 | #define PCI_CFG_TYPE0_FUNC_SHF 8 | ||
41 | |||
42 | /* Type 1 */ | ||
43 | #define PCI_CFG_TYPE1_REG_SHF 0 | ||
44 | #define PCI_CFG_TYPE1_FUNC_SHF 8 | ||
45 | #define PCI_CFG_TYPE1_DEV_SHF 11 | ||
46 | #define PCI_CFG_TYPE1_BUS_SHF 16 | ||
47 | |||
48 | static int msc_pcibios_config_access(unsigned char access_type, | ||
49 | struct pci_bus *bus, unsigned int devfn, int where, u32 * data) | ||
50 | { | ||
51 | unsigned char busnum = bus->number; | ||
52 | unsigned char type; | ||
53 | u32 intr; | ||
54 | |||
55 | #ifdef CONFIG_MIPS_BOARDS_GEN | ||
56 | if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) { | ||
57 | /* MIPS Core boards have SOCit connected as device 17 */ | ||
58 | return -1; | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | /* Clear status register bits. */ | ||
63 | MSC_WRITE(MSC01_PCI_INTSTAT, | ||
64 | (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)); | ||
65 | |||
66 | /* Setup address */ | ||
67 | if (busnum == 0) | ||
68 | type = 0; /* Type 0 */ | ||
69 | else | ||
70 | type = 1; /* Type 1 */ | ||
71 | |||
72 | MSC_WRITE(MSC01_PCI_CFGADDR, | ||
73 | ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) | | ||
74 | (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) | ||
75 | | (PCI_FUNC(devfn) << | ||
76 | MSC01_PCI_CFGADDR_FNUM_SHF) | ((where / | ||
77 | 4) << | ||
78 | MSC01_PCI_CFGADDR_RNUM_SHF) | ||
79 | | (type))); | ||
80 | |||
81 | /* Perform access */ | ||
82 | if (access_type == PCI_ACCESS_WRITE) | ||
83 | MSC_WRITE(MSC01_PCI_CFGDATA, *data); | ||
84 | else | ||
85 | MSC_READ(MSC01_PCI_CFGDATA, *data); | ||
86 | |||
87 | /* Detect Master/Target abort */ | ||
88 | MSC_READ(MSC01_PCI_INTSTAT, intr); | ||
89 | if (intr & (MSC01_PCI_INTCFG_MA_BIT | | ||
90 | MSC01_PCI_INTCFG_TA_BIT)) { | ||
91 | /* Error occurred */ | ||
92 | |||
93 | /* Clear bits */ | ||
94 | MSC_READ(MSC01_PCI_INTSTAT, intr); | ||
95 | MSC_WRITE(MSC01_PCI_INTSTAT, | ||
96 | (MSC01_PCI_INTCFG_MA_BIT | | ||
97 | MSC01_PCI_INTCFG_TA_BIT)); | ||
98 | |||
99 | return -1; | ||
100 | } | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | |||
106 | /* | ||
107 | * We can't address 8 and 16 bit words directly. Instead we have to | ||
108 | * read/write a 32bit word and mask/modify the data we actually want. | ||
109 | */ | ||
110 | static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
111 | int where, int size, u32 * val) | ||
112 | { | ||
113 | u32 data = 0; | ||
114 | |||
115 | if ((size == 2) && (where & 1)) | ||
116 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
117 | else if ((size == 4) && (where & 3)) | ||
118 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
119 | |||
120 | if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | ||
121 | &data)) | ||
122 | return -1; | ||
123 | |||
124 | if (size == 1) | ||
125 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
126 | else if (size == 2) | ||
127 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
128 | else | ||
129 | *val = data; | ||
130 | |||
131 | return PCIBIOS_SUCCESSFUL; | ||
132 | } | ||
133 | |||
134 | static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
135 | int where, int size, u32 val) | ||
136 | { | ||
137 | u32 data = 0; | ||
138 | |||
139 | if ((size == 2) && (where & 1)) | ||
140 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
141 | else if ((size == 4) && (where & 3)) | ||
142 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
143 | |||
144 | if (size == 4) | ||
145 | data = val; | ||
146 | else { | ||
147 | if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, | ||
148 | where, &data)) | ||
149 | return -1; | ||
150 | |||
151 | if (size == 1) | ||
152 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
153 | (val << ((where & 3) << 3)); | ||
154 | else if (size == 2) | ||
155 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
156 | (val << ((where & 3) << 3)); | ||
157 | } | ||
158 | |||
159 | if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, | ||
160 | &data)) | ||
161 | return -1; | ||
162 | |||
163 | return PCIBIOS_SUCCESSFUL; | ||
164 | } | ||
165 | |||
166 | struct pci_ops msc_pci_ops = { | ||
167 | .read = msc_pcibios_read, | ||
168 | .write = msc_pcibios_write | ||
169 | }; | ||
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c new file mode 100644 index 000000000000..a7169928b351 --- /dev/null +++ b/arch/mips/pci/ops-nile4.c | |||
@@ -0,0 +1,147 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/pci.h> | ||
4 | #include <asm/bootinfo.h> | ||
5 | |||
6 | #include <asm/lasat/lasat.h> | ||
7 | #include <asm/gt64120.h> | ||
8 | #include <asm/nile4.h> | ||
9 | |||
10 | #define PCI_ACCESS_READ 0 | ||
11 | #define PCI_ACCESS_WRITE 1 | ||
12 | |||
13 | #define LO(reg) (reg / 4) | ||
14 | #define HI(reg) (reg / 4 + 1) | ||
15 | |||
16 | volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; | ||
17 | |||
18 | static spinlock_t nile4_pci_lock; | ||
19 | |||
20 | static int nile4_pcibios_config_access(unsigned char access_type, | ||
21 | struct pci_bus *bus, unsigned int devfn, int where, u32 * val) | ||
22 | { | ||
23 | unsigned char busnum = bus->number; | ||
24 | u32 adr, mask, err; | ||
25 | |||
26 | if ((busnum == 0) && (PCI_SLOT(devfn) > 8)) | ||
27 | /* The addressing scheme chosen leaves room for just | ||
28 | * 8 devices on the first busnum (besides the PCI | ||
29 | * controller itself) */ | ||
30 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
31 | |||
32 | if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) { | ||
33 | /* Access controller registers directly */ | ||
34 | if (access_type == PCI_ACCESS_WRITE) { | ||
35 | vrc_pciregs[(0x200 + where) >> 2] = *val; | ||
36 | } else { | ||
37 | *val = vrc_pciregs[(0x200 + where) >> 2]; | ||
38 | } | ||
39 | return PCIBIOS_SUCCESSFUL; | ||
40 | } | ||
41 | |||
42 | /* Temporarily map PCI Window 1 to config space */ | ||
43 | mask = vrc_pciregs[LO(NILE4_PCIINIT1)]; | ||
44 | vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0); | ||
45 | |||
46 | /* Clear PCI Error register. This also clears the Error Type | ||
47 | * bits in the Control register */ | ||
48 | vrc_pciregs[LO(NILE4_PCIERR)] = 0; | ||
49 | vrc_pciregs[HI(NILE4_PCIERR)] = 0; | ||
50 | |||
51 | /* Setup address */ | ||
52 | if (busnum == 0) | ||
53 | adr = | ||
54 | KSEG1ADDR(PCI_WINDOW1) + | ||
55 | ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8) | ||
56 | | (where & ~3)); | ||
57 | else | ||
58 | adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) | | ||
59 | (where & ~3); | ||
60 | |||
61 | if (access_type == PCI_ACCESS_WRITE) | ||
62 | *(u32 *) adr = *val; | ||
63 | else | ||
64 | *val = *(u32 *) adr; | ||
65 | |||
66 | /* Check for master or target abort */ | ||
67 | err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7; | ||
68 | |||
69 | /* Restore PCI Window 1 */ | ||
70 | vrc_pciregs[LO(NILE4_PCIINIT1)] = mask; | ||
71 | |||
72 | if (err) | ||
73 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
74 | |||
75 | return PCIBIOS_SUCCESSFUL; | ||
76 | } | ||
77 | |||
78 | static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
79 | int where, int size, u32 * val) | ||
80 | { | ||
81 | unsigned long flags; | ||
82 | u32 data = 0; | ||
83 | int err; | ||
84 | |||
85 | if ((size == 2) && (where & 1)) | ||
86 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
87 | else if ((size == 4) && (where & 3)) | ||
88 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
89 | |||
90 | spin_lock_irqsave(&nile4_pci_lock, flags); | ||
91 | err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | ||
92 | &data); | ||
93 | spin_unlock_irqrestore(&nile4_pci_lock, flags); | ||
94 | |||
95 | if (err) | ||
96 | return err; | ||
97 | |||
98 | if (size == 1) | ||
99 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
100 | else if (size == 2) | ||
101 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
102 | else | ||
103 | *val = data; | ||
104 | |||
105 | return PCIBIOS_SUCCESSFUL; | ||
106 | } | ||
107 | |||
108 | static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
109 | int where, int size, u32 val) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | u32 data = 0; | ||
113 | int err; | ||
114 | |||
115 | if ((size == 2) && (where & 1)) | ||
116 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
117 | else if ((size == 4) && (where & 3)) | ||
118 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
119 | |||
120 | spin_lock_irqsave(&nile4_pci_lock, flags); | ||
121 | err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | ||
122 | &data); | ||
123 | spin_unlock_irqrestore(&nile4_pci_lock, flags); | ||
124 | |||
125 | if (err) | ||
126 | return err; | ||
127 | |||
128 | if (size == 1) | ||
129 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
130 | (val << ((where & 3) << 3)); | ||
131 | else if (size == 2) | ||
132 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
133 | (val << ((where & 3) << 3)); | ||
134 | else | ||
135 | data = val; | ||
136 | |||
137 | if (nile4_pcibios_config_access | ||
138 | (PCI_ACCESS_WRITE, bus, devfn, where, &data)) | ||
139 | return -1; | ||
140 | |||
141 | return PCIBIOS_SUCCESSFUL; | ||
142 | } | ||
143 | |||
144 | struct pci_ops nile4_pci_ops = { | ||
145 | .read = nile4_pcibios_read, | ||
146 | .write = nile4_pcibios_write, | ||
147 | }; | ||
diff --git a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c new file mode 100644 index 000000000000..62bdd19c7f8e --- /dev/null +++ b/arch/mips/pci/ops-sni.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * SNI specific PCI support for RM200/RM300. | ||
7 | * | ||
8 | * Copyright (C) 1997 - 2000, 2003 Ralf Baechle <ralf@linux-mips.org> | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <asm/sni.h> | ||
14 | |||
15 | /* | ||
16 | * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device | ||
17 | * address are decoded. We therefore manually have to reject attempts at | ||
18 | * reading outside this range. Being on the paranoid side we only do this | ||
19 | * test for bus 0 and hope forwarding and decoding work properly for any | ||
20 | * subordinated busses. | ||
21 | * | ||
22 | * ASIC PCI only supports type 1 config cycles. | ||
23 | */ | ||
24 | static int set_config_address(unsigned int busno, unsigned int devfn, int reg) | ||
25 | { | ||
26 | if ((devfn > 255) || (reg > 255)) | ||
27 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
28 | |||
29 | if (busno == 0 && devfn >= PCI_DEVFN(8, 0)) | ||
30 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
31 | |||
32 | *(volatile u32 *)PCIMT_CONFIG_ADDRESS = | ||
33 | ((busno & 0xff) << 16) | | ||
34 | ((devfn & 0xff) << 8) | | ||
35 | (reg & 0xfc); | ||
36 | |||
37 | return PCIBIOS_SUCCESSFUL; | ||
38 | } | ||
39 | |||
40 | static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg, | ||
41 | int size, u32 * val) | ||
42 | { | ||
43 | int res; | ||
44 | |||
45 | if ((res = set_config_address(bus->number, devfn, reg))) | ||
46 | return res; | ||
47 | |||
48 | switch (size) { | ||
49 | case 1: | ||
50 | *val = *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)); | ||
51 | break; | ||
52 | case 2: | ||
53 | *val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)); | ||
54 | break; | ||
55 | case 4: | ||
56 | *val = *(volatile u32 *) PCIMT_CONFIG_DATA; | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg, | ||
64 | int size, u32 val) | ||
65 | { | ||
66 | int res; | ||
67 | |||
68 | if ((res = set_config_address(bus->number, devfn, reg))) | ||
69 | return res; | ||
70 | |||
71 | switch (size) { | ||
72 | case 1: | ||
73 | *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val; | ||
74 | break; | ||
75 | case 2: | ||
76 | *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val; | ||
77 | break; | ||
78 | case 4: | ||
79 | *(volatile u32 *) PCIMT_CONFIG_DATA = val; | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | struct pci_ops sni_pci_ops = { | ||
87 | .read = pcimt_read, | ||
88 | .write = pcimt_write, | ||
89 | }; | ||
diff --git a/arch/mips/pci/ops-titan-ht.c b/arch/mips/pci/ops-titan-ht.c new file mode 100644 index 000000000000..46c636c27e06 --- /dev/null +++ b/arch/mips/pci/ops-titan-ht.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PMC-Sierra | ||
3 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
11 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
13 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
14 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
15 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
16 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
17 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
19 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <asm/io.h> | ||
32 | |||
33 | #include <asm/titan_dep.h> | ||
34 | |||
35 | static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn, | ||
36 | int offset, u32 * val) | ||
37 | { | ||
38 | volatile uint32_t address; | ||
39 | int busno; | ||
40 | |||
41 | busno = bus->number; | ||
42 | |||
43 | address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000; | ||
44 | if (busno != 0) | ||
45 | address |= 1; | ||
46 | |||
47 | /* | ||
48 | * RM9000 HT Errata: Issue back to back HT config | ||
49 | * transcations. Issue a BIU sync before and | ||
50 | * after the HT cycle | ||
51 | */ | ||
52 | |||
53 | *(volatile int32_t *) 0xfb0000f0 |= 0x2; | ||
54 | |||
55 | udelay(30); | ||
56 | |||
57 | *(volatile int32_t *) 0xfb0006f8 = address; | ||
58 | *(val) = *(volatile int32_t *) 0xfb0006fc; | ||
59 | |||
60 | udelay(30); | ||
61 | |||
62 | * (volatile int32_t *) 0xfb0000f0 |= 0x2; | ||
63 | |||
64 | return PCIBIOS_SUCCESSFUL; | ||
65 | } | ||
66 | |||
67 | static int titan_ht_config_read(struct pci_bus *bus, unsigned int devfn, | ||
68 | int offset, int size, u32 * val) | ||
69 | { | ||
70 | uint32_t dword; | ||
71 | |||
72 | titan_ht_config_read_dword(bus, devfn, offset, &dword); | ||
73 | |||
74 | dword >>= ((offset & 3) << 3); | ||
75 | dword &= (0xffffffffU >> ((4 - size) << 8)); | ||
76 | |||
77 | return PCIBIOS_SUCCESSFUL; | ||
78 | } | ||
79 | |||
80 | static inline int titan_ht_config_write_dword(struct pci_bus *bus, | ||
81 | unsigned int devfn, int offset, u32 val) | ||
82 | { | ||
83 | volatile uint32_t address; | ||
84 | int busno; | ||
85 | |||
86 | busno = bus->number; | ||
87 | |||
88 | address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000; | ||
89 | if (busno != 0) | ||
90 | address |= 1; | ||
91 | |||
92 | *(volatile int32_t *) 0xfb0000f0 |= 0x2; | ||
93 | |||
94 | udelay(30); | ||
95 | |||
96 | *(volatile int32_t *) 0xfb0006f8 = address; | ||
97 | *(volatile int32_t *) 0xfb0006fc = val; | ||
98 | |||
99 | udelay(30); | ||
100 | |||
101 | *(volatile int32_t *) 0xfb0000f0 |= 0x2; | ||
102 | |||
103 | return PCIBIOS_SUCCESSFUL; | ||
104 | } | ||
105 | |||
106 | static int titan_ht_config_write(struct pci_bus *bus, unsigned int devfn, | ||
107 | int offset, int size, u32 val) | ||
108 | { | ||
109 | uint32_t val1, val2, mask; | ||
110 | |||
111 | titan_ht_config_read_dword(bus, devfn, offset, &val2); | ||
112 | |||
113 | val1 = val << ((offset & 3) << 3); | ||
114 | mask = ~(0xffffffffU >> ((4 - size) << 8)); | ||
115 | val2 &= ~(mask << ((offset & 3) << 8)); | ||
116 | |||
117 | titan_ht_config_write_dword(bus, devfn, offset, val1 | val2); | ||
118 | |||
119 | return PCIBIOS_SUCCESSFUL; | ||
120 | } | ||
121 | |||
122 | struct pci_ops titan_ht_pci_ops = { | ||
123 | .read = titan_ht_config_read, | ||
124 | .write = titan_ht_config_write, | ||
125 | }; | ||
diff --git a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c new file mode 100644 index 000000000000..233ec6f2054d --- /dev/null +++ b/arch/mips/pci/ops-titan.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PMC-Sierra | ||
3 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
11 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
13 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
14 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
15 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
16 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
17 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
19 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/kernel.h> | ||
28 | |||
29 | #include <asm/titan_dep.h> | ||
30 | |||
31 | static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg, | ||
32 | int size, u32 * val) | ||
33 | { | ||
34 | uint32_t address, tmp; | ||
35 | int dev, busno, func; | ||
36 | |||
37 | busno = bus->number; | ||
38 | dev = PCI_SLOT(devfn); | ||
39 | func = PCI_FUNC(devfn); | ||
40 | |||
41 | address = (busno << 16) | (dev << 11) | (func << 8) | | ||
42 | (reg & 0xfc) | 0x80000000; | ||
43 | |||
44 | |||
45 | /* start the configuration cycle */ | ||
46 | TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address); | ||
47 | tmp = TITAN_READ(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3); | ||
48 | |||
49 | switch (size) { | ||
50 | case 1: | ||
51 | tmp &= 0xff; | ||
52 | case 2: | ||
53 | tmp &= 0xffff; | ||
54 | } | ||
55 | *val = tmp; | ||
56 | |||
57 | return PCIBIOS_SUCCESSFUL; | ||
58 | } | ||
59 | |||
60 | static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg, | ||
61 | int size, u32 val) | ||
62 | { | ||
63 | uint32_t address; | ||
64 | int dev, busno, func; | ||
65 | |||
66 | busno = bus->number; | ||
67 | dev = PCI_SLOT(devfn); | ||
68 | func = PCI_FUNC(devfn); | ||
69 | |||
70 | address = (busno << 16) | (dev << 11) | (func << 8) | | ||
71 | (reg & 0xfc) | 0x80000000; | ||
72 | |||
73 | /* start the configuration cycle */ | ||
74 | TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address); | ||
75 | |||
76 | /* write the data */ | ||
77 | switch (size) { | ||
78 | case 1: | ||
79 | TITAN_WRITE_8(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3), val); | ||
80 | break; | ||
81 | |||
82 | case 2: | ||
83 | TITAN_WRITE_16(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2), val); | ||
84 | break; | ||
85 | |||
86 | case 4: | ||
87 | TITAN_WRITE(TITAN_PCI_0_CONFIG_DATA, val); | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | return PCIBIOS_SUCCESSFUL; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Titan PCI structure | ||
96 | */ | ||
97 | struct pci_ops titan_pci_ops = { | ||
98 | titan_read_config, | ||
99 | titan_write_config, | ||
100 | }; | ||
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c new file mode 100644 index 000000000000..0e0daadc303d --- /dev/null +++ b/arch/mips/pci/ops-tx3927.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: MontaVista Software, Inc. | ||
4 | * ahennessy@mvista.com | ||
5 | * | ||
6 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
7 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | ||
9 | * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c | ||
10 | * | ||
11 | * Define the pci_ops for JMR3927. | ||
12 | * | ||
13 | * Much of the code is derived from the original DDB5074 port by | ||
14 | * Geert Uytterhoeven <geert@sonycom.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify it | ||
17 | * under the terms of the GNU General Public License as published by the | ||
18 | * Free Software Foundation; either version 2 of the License, or (at your | ||
19 | * option) any later version. | ||
20 | * | ||
21 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
23 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
24 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
27 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
28 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License along | ||
33 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
34 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
35 | */ | ||
36 | #include <linux/types.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/init.h> | ||
40 | |||
41 | #include <asm/addrspace.h> | ||
42 | #include <asm/jmr3927/jmr3927.h> | ||
43 | #include <asm/debug.h> | ||
44 | |||
45 | static inline int mkaddr(unsigned char bus, unsigned char dev_fn, | ||
46 | unsigned char where) | ||
47 | { | ||
48 | if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0)) | ||
49 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
50 | |||
51 | tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) | | ||
52 | ((dev_fn & 0xff) << 0x08) | | ||
53 | (where & 0xfc); | ||
54 | |||
55 | /* clear M_ABORT and Disable M_ABORT Int. */ | ||
56 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; | ||
57 | tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT; | ||
58 | |||
59 | return PCIBIOS_SUCCESSFUL; | ||
60 | } | ||
61 | |||
62 | static inline int check_abort(void) | ||
63 | { | ||
64 | if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) | ||
65 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; | ||
66 | tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; | ||
67 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
68 | |||
69 | return PCIBIOS_SUCCESSFUL; | ||
70 | } | ||
71 | |||
72 | static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
73 | int where, int size, u32 * val) | ||
74 | { | ||
75 | int ret, busno; | ||
76 | |||
77 | /* check if the bus is top-level */ | ||
78 | if (bus->parent != NULL) | ||
79 | busno = bus->number; | ||
80 | |||
81 | ret = mkaddr(busno, devfn, where); | ||
82 | if (ret) | ||
83 | return ret; | ||
84 | |||
85 | switch (size) { | ||
86 | case 1: | ||
87 | *val = *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)); | ||
88 | break; | ||
89 | |||
90 | case 2: | ||
91 | *val = le16_to_cpu(*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3))); | ||
92 | break; | ||
93 | |||
94 | case 4: | ||
95 | *val = le32_to_cpu(tx3927_pcicptr->icd); | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | return check_abort(); | ||
100 | } | ||
101 | |||
102 | static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
103 | int where, int size, u32 val) | ||
104 | { | ||
105 | int ret, busno; | ||
106 | |||
107 | /* check if the bus is top-level */ | ||
108 | if (bus->parent != NULL) | ||
109 | bus = bus->number; | ||
110 | else | ||
111 | bus = 0; | ||
112 | |||
113 | ret = mkaddr(busno, devfn, where); | ||
114 | if (ret) | ||
115 | return ret; | ||
116 | |||
117 | switch (size) { | ||
118 | case 1: | ||
119 | *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)) = val; | ||
120 | break; | ||
121 | |||
122 | case 2: | ||
123 | *(volatile u16 *) (unsigned longulong) & tx3927_pcicptr->icd | (where & 2)) = | ||
124 | cpu_to_le16(val); | ||
125 | break; | ||
126 | |||
127 | case 4: | ||
128 | tx3927_pcicptr->icd = cpu_to_le32(val); | ||
129 | } | ||
130 | |||
131 | if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) | ||
132 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; | ||
133 | tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; | ||
134 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
135 | |||
136 | return check_abort(); | ||
137 | } | ||
138 | |||
139 | struct pci_ops jmr3927_pci_ops = { | ||
140 | jmr3927_pcibios_read_config, | ||
141 | jmr3927_pcibios_write_config, | ||
142 | }; | ||
143 | |||
144 | |||
145 | #ifndef JMR3927_INIT_INDIRECT_PCI | ||
146 | |||
147 | inline unsigned long tc_readl(volatile __u32 * addr) | ||
148 | { | ||
149 | return readl(addr); | ||
150 | } | ||
151 | |||
152 | inline void tc_writel(unsigned long data, volatile __u32 * addr) | ||
153 | { | ||
154 | writel(data, addr); | ||
155 | } | ||
156 | #else | ||
157 | |||
158 | unsigned long tc_readl(volatile __u32 * addr) | ||
159 | { | ||
160 | unsigned long val; | ||
161 | |||
162 | addr = PHYSADDR(addr); | ||
163 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
164 | (unsigned long) addr; | ||
165 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
166 | (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) | | ||
167 | PCI_IPCIBE_IBE_LONG; | ||
168 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
169 | val = | ||
170 | le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> | ||
171 | ipcidata); | ||
172 | /* clear by setting */ | ||
173 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
174 | return val; | ||
175 | } | ||
176 | |||
177 | void tc_writel(unsigned long data, volatile __u32 * addr) | ||
178 | { | ||
179 | addr = PHYSADDR(addr); | ||
180 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = | ||
181 | cpu_to_le32(data); | ||
182 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
183 | (unsigned long) addr; | ||
184 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
185 | (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) | | ||
186 | PCI_IPCIBE_IBE_LONG; | ||
187 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
188 | /* clear by setting */ | ||
189 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
190 | } | ||
191 | |||
192 | unsigned char tx_ioinb(unsigned char *addr) | ||
193 | { | ||
194 | unsigned long val; | ||
195 | __u32 ioaddr; | ||
196 | int offset; | ||
197 | int byte; | ||
198 | |||
199 | ioaddr = (unsigned long) addr; | ||
200 | offset = ioaddr & 0x3; | ||
201 | if (offset == 0) | ||
202 | byte = 0x7; | ||
203 | else if (offset == 1) | ||
204 | byte = 0xb; | ||
205 | else if (offset == 2) | ||
206 | byte = 0xd; | ||
207 | else if (offset == 3) | ||
208 | byte = 0xe; | ||
209 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
210 | (unsigned long) ioaddr; | ||
211 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
212 | (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; | ||
213 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
214 | val = | ||
215 | le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> | ||
216 | ipcidata); | ||
217 | val = val & 0xff; | ||
218 | /* clear by setting */ | ||
219 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
220 | return val; | ||
221 | } | ||
222 | |||
223 | void tx_iooutb(unsigned long data, unsigned char *addr) | ||
224 | { | ||
225 | __u32 ioaddr; | ||
226 | int offset; | ||
227 | int byte; | ||
228 | |||
229 | data = data | (data << 8) | (data << 16) | (data << 24); | ||
230 | ioaddr = (unsigned long) addr; | ||
231 | offset = ioaddr & 0x3; | ||
232 | if (offset == 0) | ||
233 | byte = 0x7; | ||
234 | else if (offset == 1) | ||
235 | byte = 0xb; | ||
236 | else if (offset == 2) | ||
237 | byte = 0xd; | ||
238 | else if (offset == 3) | ||
239 | byte = 0xe; | ||
240 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; | ||
241 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
242 | (unsigned long) ioaddr; | ||
243 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
244 | (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; | ||
245 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
246 | /* clear by setting */ | ||
247 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
248 | } | ||
249 | |||
250 | unsigned short tx_ioinw(unsigned short *addr) | ||
251 | { | ||
252 | unsigned long val; | ||
253 | __u32 ioaddr; | ||
254 | int offset; | ||
255 | int byte; | ||
256 | |||
257 | ioaddr = (unsigned long) addr; | ||
258 | offset = ioaddr & 0x3; | ||
259 | if (offset == 0) | ||
260 | byte = 0x3; | ||
261 | else if (offset == 2) | ||
262 | byte = 0xc; | ||
263 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
264 | (unsigned long) ioaddr; | ||
265 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
266 | (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; | ||
267 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
268 | val = | ||
269 | le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> | ||
270 | ipcidata); | ||
271 | val = val & 0xffff; | ||
272 | /* clear by setting */ | ||
273 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
274 | return val; | ||
275 | |||
276 | } | ||
277 | |||
278 | void tx_iooutw(unsigned long data, unsigned short *addr) | ||
279 | { | ||
280 | __u32 ioaddr; | ||
281 | int offset; | ||
282 | int byte; | ||
283 | |||
284 | data = data | (data << 16); | ||
285 | ioaddr = (unsigned long) addr; | ||
286 | offset = ioaddr & 0x3; | ||
287 | if (offset == 0) | ||
288 | byte = 0x3; | ||
289 | else if (offset == 2) | ||
290 | byte = 0xc; | ||
291 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; | ||
292 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
293 | (unsigned long) ioaddr; | ||
294 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
295 | (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; | ||
296 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
297 | /* clear by setting */ | ||
298 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
299 | } | ||
300 | |||
301 | unsigned long tx_ioinl(unsigned int *addr) | ||
302 | { | ||
303 | unsigned long val; | ||
304 | __u32 ioaddr; | ||
305 | |||
306 | ioaddr = (unsigned long) addr; | ||
307 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
308 | (unsigned long) ioaddr; | ||
309 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
310 | (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | | ||
311 | PCI_IPCIBE_IBE_LONG; | ||
312 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
313 | val = | ||
314 | le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> | ||
315 | ipcidata); | ||
316 | /* clear by setting */ | ||
317 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
318 | return val; | ||
319 | } | ||
320 | |||
321 | void tx_iooutl(unsigned long data, unsigned int *addr) | ||
322 | { | ||
323 | __u32 ioaddr; | ||
324 | |||
325 | ioaddr = (unsigned long) addr; | ||
326 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = | ||
327 | cpu_to_le32(data); | ||
328 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = | ||
329 | (unsigned long) ioaddr; | ||
330 | *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = | ||
331 | (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | | ||
332 | PCI_IPCIBE_IBE_LONG; | ||
333 | while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); | ||
334 | /* clear by setting */ | ||
335 | tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; | ||
336 | } | ||
337 | |||
338 | void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count) | ||
339 | { | ||
340 | unsigned char *ptr = (unsigned char *) buffer; | ||
341 | |||
342 | while (count--) { | ||
343 | *ptr++ = tx_ioinb(addr); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | void tx_insword(unsigned short *addr, void *buffer, unsigned int count) | ||
348 | { | ||
349 | unsigned short *ptr = (unsigned short *) buffer; | ||
350 | |||
351 | while (count--) { | ||
352 | *ptr++ = tx_ioinw(addr); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | void tx_inslong(unsigned int *addr, void *buffer, unsigned int count) | ||
357 | { | ||
358 | unsigned long *ptr = (unsigned long *) buffer; | ||
359 | |||
360 | while (count--) { | ||
361 | *ptr++ = tx_ioinl(addr); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count) | ||
366 | { | ||
367 | unsigned char *ptr = (unsigned char *) buffer; | ||
368 | |||
369 | while (count--) { | ||
370 | tx_iooutb(*ptr++, addr); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | void tx_outsword(unsigned short *addr, void *buffer, unsigned int count) | ||
375 | { | ||
376 | unsigned short *ptr = (unsigned short *) buffer; | ||
377 | |||
378 | while (count--) { | ||
379 | tx_iooutw(*ptr++, addr); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | void tx_outslong(unsigned int *addr, void *buffer, unsigned int count) | ||
384 | { | ||
385 | unsigned long *ptr = (unsigned long *) buffer; | ||
386 | |||
387 | while (count--) { | ||
388 | tx_iooutl(*ptr++, addr); | ||
389 | } | ||
390 | } | ||
391 | #endif | ||
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c new file mode 100644 index 000000000000..2a9d7227fe87 --- /dev/null +++ b/arch/mips/pci/ops-tx4927.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: MontaVista Software, Inc. | ||
4 | * ahennessy@mvista.com | ||
5 | * | ||
6 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
7 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | ||
9 | * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c | ||
10 | * | ||
11 | * Define the pci_ops for the Toshiba rbtx4927 | ||
12 | * | ||
13 | * Much of the code is derived from the original DDB5074 port by | ||
14 | * Geert Uytterhoeven <geert@sonycom.com> | ||
15 | * | ||
16 | * Copyright 2004 MontaVista Software Inc. | ||
17 | * Author: Manish Lachwani (mlachwani@mvista.com) | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | ||
20 | * under the terms of the GNU General Public License as published by the | ||
21 | * Free Software Foundation; either version 2 of the License, or (at your | ||
22 | * option) any later version. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
25 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
26 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
27 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
30 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
31 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
34 | * | ||
35 | * You should have received a copy of the GNU General Public License along | ||
36 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
37 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
38 | */ | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/kernel.h> | ||
42 | #include <linux/init.h> | ||
43 | |||
44 | #include <asm/addrspace.h> | ||
45 | #include <asm/byteorder.h> | ||
46 | #include <asm/tx4927/tx4927_pci.h> | ||
47 | |||
48 | /* initialize in setup */ | ||
49 | struct resource pci_io_resource = { | ||
50 | .name = "TX4927 PCI IO SPACE", | ||
51 | .start = 0x1000, | ||
52 | .end = (0x1000 + (TX4927_PCIIO_SIZE)) - 1, | ||
53 | .flags = IORESOURCE_IO | ||
54 | }; | ||
55 | |||
56 | /* initialize in setup */ | ||
57 | struct resource pci_mem_resource = { | ||
58 | .name = "TX4927 PCI MEM SPACE", | ||
59 | .start = TX4927_PCIMEM, | ||
60 | .end = TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1, | ||
61 | .flags = IORESOURCE_MEM | ||
62 | }; | ||
63 | |||
64 | static int mkaddr(int bus, int dev_fn, int where, int *flagsp) | ||
65 | { | ||
66 | if (bus > 0) { | ||
67 | /* Type 1 configuration */ | ||
68 | tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | | ||
69 | ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1; | ||
70 | } else { | ||
71 | if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0)) | ||
72 | return -1; | ||
73 | |||
74 | /* Type 0 configuration */ | ||
75 | tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | | ||
76 | ((dev_fn & 0xff) << 0x08) | (where & 0xfc); | ||
77 | } | ||
78 | /* clear M_ABORT and Disable M_ABORT Int. */ | ||
79 | tx4927_pcicptr->pcistatus = | ||
80 | (tx4927_pcicptr->pcistatus & 0x0000ffff) | | ||
81 | (PCI_STATUS_REC_MASTER_ABORT << 16); | ||
82 | tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT; | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int check_abort(int flags) | ||
87 | { | ||
88 | int code = PCIBIOS_SUCCESSFUL; | ||
89 | if (tx4927_pcicptr-> | ||
90 | pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) { | ||
91 | tx4927_pcicptr->pcistatus = | ||
92 | (tx4927_pcicptr-> | ||
93 | pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT | ||
94 | << 16); | ||
95 | tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT; | ||
96 | code = PCIBIOS_DEVICE_NOT_FOUND; | ||
97 | } | ||
98 | return code; | ||
99 | } | ||
100 | |||
101 | static int tx4927_pcibios_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
102 | int size, u32 * val) | ||
103 | { | ||
104 | int flags, retval, dev, busno, func; | ||
105 | |||
106 | busno = bus->number; | ||
107 | dev = PCI_SLOT(devfn); | ||
108 | func = PCI_FUNC(devfn); | ||
109 | |||
110 | /* check if the bus is top-level */ | ||
111 | if (bus->parent != NULL) { | ||
112 | busno = bus->number; | ||
113 | } else { | ||
114 | busno = 0; | ||
115 | } | ||
116 | |||
117 | if (mkaddr(busno, devfn, where, &flags)) | ||
118 | return -1; | ||
119 | |||
120 | switch (size) { | ||
121 | case 1: | ||
122 | *val = *(volatile u8 *) ((ulong) & tx4927_pcicptr-> | ||
123 | g2pcfgdata | | ||
124 | #ifdef __LITTLE_ENDIAN | ||
125 | (where & 3)); | ||
126 | #else | ||
127 | ((where & 0x3) ^ 0x3)); | ||
128 | #endif | ||
129 | break; | ||
130 | case 2: | ||
131 | *val = *(volatile u16 *) ((ulong) & tx4927_pcicptr-> | ||
132 | g2pcfgdata | | ||
133 | #ifdef __LITTLE_ENDIAN | ||
134 | (where & 3)); | ||
135 | #else | ||
136 | ((where & 0x3) ^ 0x2)); | ||
137 | #endif | ||
138 | break; | ||
139 | case 4: | ||
140 | *val = tx4927_pcicptr->g2pcfgdata; | ||
141 | break; | ||
142 | } | ||
143 | |||
144 | retval = check_abort(flags); | ||
145 | if (retval == PCIBIOS_DEVICE_NOT_FOUND) | ||
146 | *val = 0xffffffff; | ||
147 | |||
148 | return retval; | ||
149 | } | ||
150 | |||
151 | static int tx4927_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
152 | int size, u32 val) | ||
153 | { | ||
154 | int flags, dev, busno, func; | ||
155 | busno = bus->number; | ||
156 | dev = PCI_SLOT(devfn); | ||
157 | func = PCI_FUNC(devfn); | ||
158 | |||
159 | /* check if the bus is top-level */ | ||
160 | if (bus->parent != NULL) { | ||
161 | busno = bus->number; | ||
162 | } else { | ||
163 | busno = 0; | ||
164 | } | ||
165 | |||
166 | if (mkaddr(busno, devfn, where, &flags)) | ||
167 | return -1; | ||
168 | |||
169 | switch (size) { | ||
170 | case 1: | ||
171 | *(volatile u8 *) ((ulong) & tx4927_pcicptr-> | ||
172 | g2pcfgdata | | ||
173 | #ifdef __LITTLE_ENDIAN | ||
174 | (where & 3)) = val; | ||
175 | #else | ||
176 | ((where & 0x3) ^ 0x3)) = val; | ||
177 | #endif | ||
178 | break; | ||
179 | |||
180 | case 2: | ||
181 | *(volatile u16 *) ((ulong) & tx4927_pcicptr-> | ||
182 | g2pcfgdata | | ||
183 | #ifdef __LITTLE_ENDIAN | ||
184 | (where & 3)) = val; | ||
185 | #else | ||
186 | ((where & 0x3) ^ 0x2)) = val; | ||
187 | #endif | ||
188 | break; | ||
189 | case 4: | ||
190 | tx4927_pcicptr->g2pcfgdata = val; | ||
191 | break; | ||
192 | } | ||
193 | |||
194 | return check_abort(flags); | ||
195 | } | ||
196 | |||
197 | struct pci_ops tx4927_pci_ops = { | ||
198 | tx4927_pcibios_read_config, | ||
199 | tx4927_pcibios_write_config | ||
200 | }; | ||
201 | |||
202 | /* | ||
203 | * h/w only supports devices 0x00 to 0x14 | ||
204 | */ | ||
205 | struct pci_controller tx4927_controller = { | ||
206 | .pci_ops = &tx4927_pci_ops, | ||
207 | .io_resource = &pci_io_resource, | ||
208 | .mem_resource = &pci_mem_resource, | ||
209 | }; | ||
diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c new file mode 100644 index 000000000000..44654605e461 --- /dev/null +++ b/arch/mips/pci/ops-vr41xx.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series. | ||
3 | * | ||
4 | * Copyright (C) 2001-2003 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | ||
6 | * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | /* | ||
23 | * Changes: | ||
24 | * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> | ||
25 | * - New creation, NEC VR4122 and VR4131 are supported. | ||
26 | */ | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/types.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | |||
32 | #define PCICONFDREG KSEG1ADDR(0x0f000c14) | ||
33 | #define PCICONFAREG KSEG1ADDR(0x0f000c18) | ||
34 | |||
35 | static inline int set_pci_configuration_address(unsigned char number, | ||
36 | unsigned int devfn, int where) | ||
37 | { | ||
38 | if (number == 0) { | ||
39 | /* | ||
40 | * Type 0 configuration | ||
41 | */ | ||
42 | if (PCI_SLOT(devfn) < 11 || where > 0xff) | ||
43 | return -EINVAL; | ||
44 | |||
45 | writel((1U << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) | | ||
46 | (where & 0xfc), PCICONFAREG); | ||
47 | } else { | ||
48 | /* | ||
49 | * Type 1 configuration | ||
50 | */ | ||
51 | if (where > 0xff) | ||
52 | return -EINVAL; | ||
53 | |||
54 | writel(((uint32_t)number << 16) | ((devfn & 0xff) << 8) | | ||
55 | (where & 0xfc) | 1U, PCICONFAREG); | ||
56 | } | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, | ||
62 | int size, uint32_t *val) | ||
63 | { | ||
64 | uint32_t data; | ||
65 | |||
66 | *val = 0xffffffffU; | ||
67 | if (set_pci_configuration_address(bus->number, devfn, where) < 0) | ||
68 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
69 | |||
70 | data = readl(PCICONFDREG); | ||
71 | |||
72 | switch (size) { | ||
73 | case 1: | ||
74 | *val = (data >> ((where & 3) << 3)) & 0xffU; | ||
75 | break; | ||
76 | case 2: | ||
77 | *val = (data >> ((where & 2) << 3)) & 0xffffU; | ||
78 | break; | ||
79 | case 4: | ||
80 | *val = data; | ||
81 | break; | ||
82 | default: | ||
83 | return PCIBIOS_FUNC_NOT_SUPPORTED; | ||
84 | } | ||
85 | |||
86 | return PCIBIOS_SUCCESSFUL; | ||
87 | } | ||
88 | |||
89 | static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, | ||
90 | int size, uint32_t val) | ||
91 | { | ||
92 | uint32_t data; | ||
93 | int shift; | ||
94 | |||
95 | if (set_pci_configuration_address(bus->number, devfn, where) < 0) | ||
96 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
97 | |||
98 | data = readl(PCICONFDREG); | ||
99 | |||
100 | switch (size) { | ||
101 | case 1: | ||
102 | shift = (where & 3) << 3; | ||
103 | data &= ~(0xffU << shift); | ||
104 | data |= ((val & 0xffU) << shift); | ||
105 | break; | ||
106 | case 2: | ||
107 | shift = (where & 2) << 3; | ||
108 | data &= ~(0xffffU << shift); | ||
109 | data |= ((val & 0xffffU) << shift); | ||
110 | break; | ||
111 | case 4: | ||
112 | data = val; | ||
113 | break; | ||
114 | default: | ||
115 | return PCIBIOS_FUNC_NOT_SUPPORTED; | ||
116 | } | ||
117 | |||
118 | writel(data, PCICONFDREG); | ||
119 | |||
120 | return PCIBIOS_SUCCESSFUL; | ||
121 | } | ||
122 | |||
123 | struct pci_ops vr41xx_pci_ops = { | ||
124 | .read = pci_config_read, | ||
125 | .write = pci_config_write, | ||
126 | }; | ||
diff --git a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c new file mode 100644 index 000000000000..73f9ceeb2f55 --- /dev/null +++ b/arch/mips/pci/pci-ddb5074.c | |||
@@ -0,0 +1,79 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/types.h> | ||
4 | #include <linux/pci.h> | ||
5 | |||
6 | #include <asm/debug.h> | ||
7 | |||
8 | #include <asm/ddb5xxx/ddb5xxx.h> | ||
9 | |||
10 | static struct resource extpci_io_resource = { | ||
11 | "pci IO space", | ||
12 | 0x1000, /* leave some room for ISA bus */ | ||
13 | DDB_PCI_IO_SIZE - 1, | ||
14 | IORESOURCE_IO | ||
15 | }; | ||
16 | |||
17 | static struct resource extpci_mem_resource = { | ||
18 | "pci memory space", | ||
19 | DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */ | ||
20 | DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1, | ||
21 | IORESOURCE_MEM | ||
22 | }; | ||
23 | |||
24 | extern struct pci_ops ddb5476_ext_pci_ops; | ||
25 | |||
26 | struct pci_controller ddb5476_controller = { | ||
27 | .pci_ops = &ddb5476_ext_pci_ops, | ||
28 | .io_resource = &extpci_io_resource, | ||
29 | .mem_resource = &extpci_mem_resource, | ||
30 | }; | ||
31 | |||
32 | #define PCI_EXT_INTA 8 | ||
33 | #define PCI_EXT_INTB 9 | ||
34 | #define PCI_EXT_INTC 10 | ||
35 | #define PCI_EXT_INTD 11 | ||
36 | #define PCI_EXT_INTE 12 | ||
37 | |||
38 | #define MAX_SLOT_NUM 14 | ||
39 | |||
40 | static unsigned char irq_map[MAX_SLOT_NUM] = { | ||
41 | [ 0] = nile4_to_irq(PCI_EXT_INTE), | ||
42 | [ 1] = nile4_to_irq(PCI_EXT_INTA), | ||
43 | [ 2] = nile4_to_irq(PCI_EXT_INTA), | ||
44 | [ 3] = nile4_to_irq(PCI_EXT_INTB), | ||
45 | [ 4] = nile4_to_irq(PCI_EXT_INTC), | ||
46 | [ 5] = nile4_to_irq(NILE4_INT_UART), | ||
47 | [10] = nile4_to_irq(PCI_EXT_INTE), | ||
48 | [13] = nile4_to_irq(PCI_EXT_INTE), | ||
49 | }; | ||
50 | |||
51 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
52 | { | ||
53 | return irq_map[slot]; | ||
54 | } | ||
55 | |||
56 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
57 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | void __init ddb_pci_reset_bus(void) | ||
63 | { | ||
64 | u32 temp; | ||
65 | |||
66 | /* | ||
67 | * I am not sure about the "official" procedure, the following | ||
68 | * steps work as far as I know: | ||
69 | * We first set PCI cold reset bit (bit 31) in PCICTRL-H. | ||
70 | * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. | ||
71 | * The same is true for both PCI channels. | ||
72 | */ | ||
73 | temp = ddb_in32(DDB_PCICTRL + 4); | ||
74 | temp |= 0x80000000; | ||
75 | ddb_out32(DDB_PCICTRL + 4, temp); | ||
76 | temp &= ~0xc0000000; | ||
77 | ddb_out32(DDB_PCICTRL + 4, temp); | ||
78 | |||
79 | } | ||
diff --git a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c new file mode 100644 index 000000000000..90dd49509800 --- /dev/null +++ b/arch/mips/pci/pci-ddb5476.c | |||
@@ -0,0 +1,93 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/types.h> | ||
4 | #include <linux/pci.h> | ||
5 | |||
6 | #include <asm/debug.h> | ||
7 | |||
8 | #include <asm/ddb5xxx/ddb5xxx.h> | ||
9 | |||
10 | static struct resource extpci_io_resource = { | ||
11 | "pci IO space", | ||
12 | 0x1000, /* leave some room for ISA bus */ | ||
13 | DDB_PCI_IO_SIZE - 1, | ||
14 | IORESOURCE_IO | ||
15 | }; | ||
16 | |||
17 | static struct resource extpci_mem_resource = { | ||
18 | "pci memory space", | ||
19 | DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */ | ||
20 | DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1, | ||
21 | IORESOURCE_MEM | ||
22 | }; | ||
23 | |||
24 | extern struct pci_ops ddb5476_ext_pci_ops; | ||
25 | |||
26 | struct pci_controller ddb5476_controller = { | ||
27 | .pci_ops = &ddb5476_ext_pci_ops, | ||
28 | .io_resource = &extpci_io_resource, | ||
29 | .mem_resource = &extpci_mem_resource | ||
30 | }; | ||
31 | |||
32 | |||
33 | /* | ||
34 | * we fix up irqs based on the slot number. | ||
35 | * The first entry is at AD:11. | ||
36 | * | ||
37 | * This does not work for devices on sub-buses yet. | ||
38 | */ | ||
39 | |||
40 | /* | ||
41 | * temporary | ||
42 | */ | ||
43 | |||
44 | #define PCI_EXT_INTA 8 | ||
45 | #define PCI_EXT_INTB 9 | ||
46 | #define PCI_EXT_INTC 10 | ||
47 | #define PCI_EXT_INTD 11 | ||
48 | #define PCI_EXT_INTE 12 | ||
49 | |||
50 | /* | ||
51 | * based on ddb5477 manual page 11 | ||
52 | */ | ||
53 | #define MAX_SLOT_NUM 21 | ||
54 | static unsigned char irq_map[MAX_SLOT_NUM] = { | ||
55 | [ 2] = 9, /* AD:13 USB */ | ||
56 | [ 3] = 10, /* AD:14 PMU */ | ||
57 | [ 5] = 0, /* AD:16 P2P bridge */ | ||
58 | [ 6] = nile4_to_irq(PCI_EXT_INTB), /* AD:17 */ | ||
59 | [ 7] = nile4_to_irq(PCI_EXT_INTC), /* AD:18 */ | ||
60 | [ 8] = nile4_to_irq(PCI_EXT_INTD), /* AD:19 */ | ||
61 | [ 9] = nile4_to_irq(PCI_EXT_INTA), /* AD:20 */ | ||
62 | [13] = 14, /* AD:24 HD controller, M5229 */ | ||
63 | }; | ||
64 | |||
65 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
66 | { | ||
67 | return irq_map[slot]; | ||
68 | } | ||
69 | |||
70 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
71 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
72 | { | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | void __init ddb_pci_reset_bus(void) | ||
77 | { | ||
78 | u32 temp; | ||
79 | |||
80 | /* | ||
81 | * I am not sure about the "official" procedure, the following | ||
82 | * steps work as far as I know: | ||
83 | * We first set PCI cold reset bit (bit 31) in PCICTRL-H. | ||
84 | * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. | ||
85 | * The same is true for both PCI channels. | ||
86 | */ | ||
87 | temp = ddb_in32(DDB_PCICTRL + 4); | ||
88 | temp |= 0x80000000; | ||
89 | ddb_out32(DDB_PCICTRL + 4, temp); | ||
90 | temp &= ~0xc0000000; | ||
91 | ddb_out32(DDB_PCICTRL + 4, temp); | ||
92 | |||
93 | } | ||
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c new file mode 100644 index 000000000000..4ddd53eaf656 --- /dev/null +++ b/arch/mips/pci/pci-ddb5477.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * PCI code for DDB5477. | ||
3 | * | ||
4 | * Copyright (C) 2001 MontaVista Software Inc. | ||
5 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
6 | * | ||
7 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/pci.h> | ||
18 | |||
19 | #include <asm/bootinfo.h> | ||
20 | #include <asm/debug.h> | ||
21 | |||
22 | #include <asm/ddb5xxx/ddb5xxx.h> | ||
23 | |||
24 | static struct resource extpci_io_resource = { | ||
25 | "ext pci IO space", | ||
26 | DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000, | ||
27 | DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1, | ||
28 | IORESOURCE_IO | ||
29 | }; | ||
30 | |||
31 | static struct resource extpci_mem_resource = { | ||
32 | "ext pci memory space", | ||
33 | DDB_PCI0_MEM_BASE + 0x100000, | ||
34 | DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1, | ||
35 | IORESOURCE_MEM | ||
36 | }; | ||
37 | |||
38 | static struct resource iopci_io_resource = { | ||
39 | "io pci IO space", | ||
40 | DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE, | ||
41 | DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1, | ||
42 | IORESOURCE_IO | ||
43 | }; | ||
44 | |||
45 | static struct resource iopci_mem_resource = { | ||
46 | "ext pci memory space", | ||
47 | DDB_PCI1_MEM_BASE, | ||
48 | DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1, | ||
49 | IORESOURCE_MEM | ||
50 | }; | ||
51 | |||
52 | extern struct pci_ops ddb5477_ext_pci_ops; | ||
53 | extern struct pci_ops ddb5477_io_pci_ops; | ||
54 | |||
55 | struct pci_controller ddb5477_ext_controller = { | ||
56 | .pci_ops = &ddb5477_ext_pci_ops, | ||
57 | .io_resource = &extpci_io_resource, | ||
58 | .mem_resource = &extpci_mem_resource | ||
59 | }; | ||
60 | |||
61 | struct pci_controller ddb5477_io_controller = { | ||
62 | .pci_ops = &ddb5477_io_pci_ops, | ||
63 | .io_resource = &iopci_io_resource, | ||
64 | .mem_resource = &iopci_mem_resource | ||
65 | }; | ||
66 | |||
67 | |||
68 | |||
69 | /* | ||
70 | * we fix up irqs based on the slot number. | ||
71 | * The first entry is at AD:11. | ||
72 | * Fortunately this works because, although we have two pci buses, | ||
73 | * they all have different slot numbers (except for rockhopper slot 20 | ||
74 | * which is handled below). | ||
75 | * | ||
76 | */ | ||
77 | |||
78 | /* | ||
79 | * irq mapping : device -> pci int # -> vrc4377 irq# , | ||
80 | * ddb5477 board manual page 4 and vrc5477 manual page 46 | ||
81 | */ | ||
82 | |||
83 | /* | ||
84 | * based on ddb5477 manual page 11 | ||
85 | */ | ||
86 | #define MAX_SLOT_NUM 21 | ||
87 | static unsigned char irq_map[MAX_SLOT_NUM] = { | ||
88 | /* SLOT: 0, AD:11 */ 0xff, | ||
89 | /* SLOT: 1, AD:12 */ 0xff, | ||
90 | /* SLOT: 2, AD:13 */ 0xff, | ||
91 | /* SLOT: 3, AD:14 */ 0xff, | ||
92 | /* SLOT: 4, AD:15 */ VRC5477_IRQ_INTA, /* onboard tulip */ | ||
93 | /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTB, /* slot 1 */ | ||
94 | /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTC, /* slot 2 */ | ||
95 | /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, /* slot 3 */ | ||
96 | /* SLOT: 8, AD:19 */ VRC5477_IRQ_INTE, /* slot 4 */ | ||
97 | /* SLOT: 9, AD:20 */ 0xff, | ||
98 | /* SLOT: 10, AD:21 */ 0xff, | ||
99 | /* SLOT: 11, AD:22 */ 0xff, | ||
100 | /* SLOT: 12, AD:23 */ 0xff, | ||
101 | /* SLOT: 13, AD:24 */ 0xff, | ||
102 | /* SLOT: 14, AD:25 */ 0xff, | ||
103 | /* SLOT: 15, AD:26 */ 0xff, | ||
104 | /* SLOT: 16, AD:27 */ 0xff, | ||
105 | /* SLOT: 17, AD:28 */ 0xff, | ||
106 | /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */ | ||
107 | /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */ | ||
108 | /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */ | ||
109 | }; | ||
110 | static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = { | ||
111 | /* SLOT: 0, AD:11 */ 0xff, | ||
112 | /* SLOT: 1, AD:12 */ VRC5477_IRQ_INTB, /* onboard AMD PCNET */ | ||
113 | /* SLOT: 2, AD:13 */ 0xff, | ||
114 | /* SLOT: 3, AD:14 */ 0xff, | ||
115 | /* SLOT: 4, AD:15 */ 14, /* M5229 ide ISA irq */ | ||
116 | /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTD, /* slot 3 */ | ||
117 | /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTA, /* slot 4 */ | ||
118 | /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, /* slot 5 */ | ||
119 | /* SLOT: 8, AD:19 */ 0, /* M5457 modem nop */ | ||
120 | /* SLOT: 9, AD:20 */ VRC5477_IRQ_INTA, /* slot 2 */ | ||
121 | /* SLOT: 10, AD:21 */ 0xff, | ||
122 | /* SLOT: 11, AD:22 */ 0xff, | ||
123 | /* SLOT: 12, AD:23 */ 0xff, | ||
124 | /* SLOT: 13, AD:24 */ 0xff, | ||
125 | /* SLOT: 14, AD:25 */ 0xff, | ||
126 | /* SLOT: 15, AD:26 */ 0xff, | ||
127 | /* SLOT: 16, AD:27 */ 0xff, | ||
128 | /* SLOT: 17, AD:28 */ 0, /* M7101 PMU nop */ | ||
129 | /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */ | ||
130 | /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */ | ||
131 | /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */ | ||
132 | }; | ||
133 | |||
134 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
135 | { | ||
136 | int slot_num; | ||
137 | unsigned char *slot_irq_map; | ||
138 | unsigned char irq; | ||
139 | |||
140 | /* | ||
141 | * We ignore the swizzled slot and pin values. The original | ||
142 | * pci_fixup_irq() codes largely base irq number on the dev slot | ||
143 | * numbers because except for one case they are unique even | ||
144 | * though there are multiple pci buses. | ||
145 | */ | ||
146 | |||
147 | if (mips_machtype == MACH_NEC_ROCKHOPPERII) | ||
148 | slot_irq_map = rockhopperII_irq_map; | ||
149 | else | ||
150 | slot_irq_map = irq_map; | ||
151 | |||
152 | slot_num = PCI_SLOT(dev->devfn); | ||
153 | irq = slot_irq_map[slot_num]; | ||
154 | |||
155 | db_assert(slot_num < MAX_SLOT_NUM); | ||
156 | |||
157 | db_assert(irq != 0xff); | ||
158 | |||
159 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
160 | |||
161 | if (mips_machtype == MACH_NEC_ROCKHOPPERII) { | ||
162 | /* hack to distinquish overlapping slot 20s, one | ||
163 | * on bus 0 (ALI USB on the M1535 on the backplane), | ||
164 | * and one on bus 2 (NEC USB controller on the CPU board) | ||
165 | * Make the M1535 USB - ISA IRQ number 9. | ||
166 | */ | ||
167 | if (slot_num == 20 && dev->bus->number == 0) { | ||
168 | pci_write_config_byte(dev, | ||
169 | PCI_INTERRUPT_LINE, | ||
170 | 9); | ||
171 | irq = 9; | ||
172 | } | ||
173 | |||
174 | } | ||
175 | |||
176 | return irq; | ||
177 | } | ||
178 | |||
179 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
180 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
181 | { | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | void ddb_pci_reset_bus(void) | ||
186 | { | ||
187 | u32 temp; | ||
188 | |||
189 | /* | ||
190 | * I am not sure about the "official" procedure, the following | ||
191 | * steps work as far as I know: | ||
192 | * We first set PCI cold reset bit (bit 31) in PCICTRL-H. | ||
193 | * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. | ||
194 | * The same is true for both PCI channels. | ||
195 | */ | ||
196 | temp = ddb_in32(DDB_PCICTL0_H); | ||
197 | temp |= 0x80000000; | ||
198 | ddb_out32(DDB_PCICTL0_H, temp); | ||
199 | temp &= ~0xc0000000; | ||
200 | ddb_out32(DDB_PCICTL0_H, temp); | ||
201 | |||
202 | temp = ddb_in32(DDB_PCICTL1_H); | ||
203 | temp |= 0x80000000; | ||
204 | ddb_out32(DDB_PCICTL1_H, temp); | ||
205 | temp &= ~0xc0000000; | ||
206 | ddb_out32(DDB_PCICTL1_H, temp); | ||
207 | } | ||
diff --git a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c new file mode 100644 index 000000000000..f9457ea00def --- /dev/null +++ b/arch/mips/pci/pci-ev96100.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright 2000 MontaVista Software Inc. | ||
3 | * Author: MontaVista Software, Inc. | ||
4 | * ppopov@mvista.com or source@mvista.com | ||
5 | * | ||
6 | * Carsten Langgaard, carstenl@mips.com | ||
7 | * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
8 | * | ||
9 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
19 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License along | ||
28 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | */ | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/init.h> | ||
35 | |||
36 | static struct resource pci_io_resource = { | ||
37 | .name = "io pci IO space", | ||
38 | .start = 0x10000000, | ||
39 | .end = 0x11ffffff, | ||
40 | .flags = IORESOURCE_IO | ||
41 | }; | ||
42 | |||
43 | static struct resource pci_mem_resource = { | ||
44 | .name = "ext pci memory space", | ||
45 | .start = 0x12000000, | ||
46 | .end = 0x13ffffff, | ||
47 | .flags = IORESOURCE_MEM | ||
48 | }; | ||
49 | |||
50 | extern struct pci_ops gt96100_pci_ops; | ||
51 | |||
52 | struct pci_controller ev96100_controller = { | ||
53 | .pci_ops = >96100_pci_ops, | ||
54 | .io_resource = &pci_io_resource, | ||
55 | .mem_resource = &pci_mem_resource, | ||
56 | }; | ||
57 | |||
58 | static void ev96100_pci_init(void) | ||
59 | { | ||
60 | register_pci_controller(&ev96100_controller); | ||
61 | } | ||
62 | |||
63 | arch_initcall(ev96100_pci_init); | ||
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c new file mode 100644 index 000000000000..068e0e508e15 --- /dev/null +++ b/arch/mips/pci/pci-ip27.c | |||
@@ -0,0 +1,489 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) | ||
7 | * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) | ||
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
9 | */ | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/pci.h> | ||
13 | #include <asm/sn/arch.h> | ||
14 | #include <asm/pci/bridge.h> | ||
15 | #include <asm/paccess.h> | ||
16 | #include <asm/sn/intr.h> | ||
17 | #include <asm/sn/sn0/hub.h> | ||
18 | |||
19 | extern unsigned int allocate_irqno(void); | ||
20 | |||
21 | /* | ||
22 | * Max #PCI busses we can handle; ie, max #PCI bridges. | ||
23 | */ | ||
24 | #define MAX_PCI_BUSSES 40 | ||
25 | |||
26 | /* | ||
27 | * Max #PCI devices (like scsi controllers) we handle on a bus. | ||
28 | */ | ||
29 | #define MAX_DEVICES_PER_PCIBUS 8 | ||
30 | |||
31 | /* | ||
32 | * XXX: No kmalloc available when we do our crosstalk scan, | ||
33 | * we should try to move it later in the boot process. | ||
34 | */ | ||
35 | static struct bridge_controller bridges[MAX_PCI_BUSSES]; | ||
36 | |||
37 | /* | ||
38 | * Translate from irq to software PCI bus number and PCI slot. | ||
39 | */ | ||
40 | struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | ||
41 | int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | ||
42 | |||
43 | /* | ||
44 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
45 | * not really documented, so right now I can't write code which uses it. | ||
46 | * Therefore we use type 0 accesses for now even though they won't work | ||
47 | * correcly for PCI-to-PCI bridges. | ||
48 | * | ||
49 | * The function is complicated by the ultimate brokeness of the IOC3 chip | ||
50 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
51 | * accesses and does only decode parts of it's address space. | ||
52 | */ | ||
53 | |||
54 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
55 | int where, int size, u32 * value) | ||
56 | { | ||
57 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
58 | bridge_t *bridge = bc->base; | ||
59 | int slot = PCI_SLOT(devfn); | ||
60 | int fn = PCI_FUNC(devfn); | ||
61 | volatile void *addr; | ||
62 | u32 cf, shift, mask; | ||
63 | int res; | ||
64 | |||
65 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
66 | if (get_dbe(cf, (u32 *) addr)) | ||
67 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
68 | |||
69 | /* | ||
70 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
71 | * generic PCI code a chance to look at it for real ... | ||
72 | */ | ||
73 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
74 | goto oh_my_gawd; | ||
75 | |||
76 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
77 | |||
78 | if (size == 1) | ||
79 | res = get_dbe(*value, (u8 *) addr); | ||
80 | else if (size == 2) | ||
81 | res = get_dbe(*value, (u16 *) addr); | ||
82 | else | ||
83 | res = get_dbe(*value, (u32 *) addr); | ||
84 | |||
85 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
86 | |||
87 | oh_my_gawd: | ||
88 | |||
89 | /* | ||
90 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
91 | * generic PCI code a chance to look at the wrong register. | ||
92 | */ | ||
93 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
94 | *value = 0; | ||
95 | return PCIBIOS_SUCCESSFUL; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
100 | * anything but 32-bit words ... | ||
101 | */ | ||
102 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
103 | |||
104 | if (get_dbe(cf, (u32 *) addr)) | ||
105 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
106 | |||
107 | shift = ((where & 3) << 3); | ||
108 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
109 | *value = (cf >> shift) & mask; | ||
110 | |||
111 | return PCIBIOS_SUCCESSFUL; | ||
112 | } | ||
113 | |||
114 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
115 | int where, int size, u32 * value) | ||
116 | { | ||
117 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
118 | bridge_t *bridge = bc->base; | ||
119 | int busno = bus->number; | ||
120 | int slot = PCI_SLOT(devfn); | ||
121 | int fn = PCI_FUNC(devfn); | ||
122 | volatile void *addr; | ||
123 | u32 cf, shift, mask; | ||
124 | int res; | ||
125 | |||
126 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
127 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
128 | if (get_dbe(cf, (u32 *) addr)) | ||
129 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
130 | |||
131 | /* | ||
132 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
133 | * generic PCI code a chance to look at it for real ... | ||
134 | */ | ||
135 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
136 | goto oh_my_gawd; | ||
137 | |||
138 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
139 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
140 | |||
141 | if (size == 1) | ||
142 | res = get_dbe(*value, (u8 *) addr); | ||
143 | else if (size == 2) | ||
144 | res = get_dbe(*value, (u16 *) addr); | ||
145 | else | ||
146 | res = get_dbe(*value, (u32 *) addr); | ||
147 | |||
148 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
149 | |||
150 | oh_my_gawd: | ||
151 | |||
152 | /* | ||
153 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
154 | * generic PCI code a chance to look at the wrong register. | ||
155 | */ | ||
156 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
157 | *value = 0; | ||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
163 | * anything but 32-bit words ... | ||
164 | */ | ||
165 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
166 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
167 | |||
168 | if (get_dbe(cf, (u32 *) addr)) | ||
169 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
170 | |||
171 | shift = ((where & 3) << 3); | ||
172 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
173 | *value = (cf >> shift) & mask; | ||
174 | |||
175 | return PCIBIOS_SUCCESSFUL; | ||
176 | } | ||
177 | |||
178 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
179 | int where, int size, u32 * value) | ||
180 | { | ||
181 | if (bus->number > 0) | ||
182 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
183 | |||
184 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
185 | } | ||
186 | |||
187 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
188 | int where, int size, u32 value) | ||
189 | { | ||
190 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
191 | bridge_t *bridge = bc->base; | ||
192 | int slot = PCI_SLOT(devfn); | ||
193 | int fn = PCI_FUNC(devfn); | ||
194 | volatile void *addr; | ||
195 | u32 cf, shift, mask, smask; | ||
196 | int res; | ||
197 | |||
198 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
199 | if (get_dbe(cf, (u32 *) addr)) | ||
200 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
201 | |||
202 | /* | ||
203 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
204 | * generic PCI code a chance to look at it for real ... | ||
205 | */ | ||
206 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
207 | goto oh_my_gawd; | ||
208 | |||
209 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
210 | |||
211 | if (size == 1) { | ||
212 | res = put_dbe(value, (u8 *) addr); | ||
213 | } else if (size == 2) { | ||
214 | res = put_dbe(value, (u16 *) addr); | ||
215 | } else { | ||
216 | res = put_dbe(value, (u32 *) addr); | ||
217 | } | ||
218 | |||
219 | if (res) | ||
220 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
221 | |||
222 | return PCIBIOS_SUCCESSFUL; | ||
223 | |||
224 | oh_my_gawd: | ||
225 | |||
226 | /* | ||
227 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
228 | * generic PCI code a chance to touch the wrong register. | ||
229 | */ | ||
230 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
231 | return PCIBIOS_SUCCESSFUL; | ||
232 | |||
233 | /* | ||
234 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
235 | * anything but 32-bit words ... | ||
236 | */ | ||
237 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
238 | |||
239 | if (get_dbe(cf, (u32 *) addr)) | ||
240 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
241 | |||
242 | shift = ((where & 3) << 3); | ||
243 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
244 | smask = mask << shift; | ||
245 | |||
246 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
247 | if (put_dbe(cf, (u32 *) addr)) | ||
248 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
249 | |||
250 | return PCIBIOS_SUCCESSFUL; | ||
251 | } | ||
252 | |||
253 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
254 | int where, int size, u32 value) | ||
255 | { | ||
256 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
257 | bridge_t *bridge = bc->base; | ||
258 | int slot = PCI_SLOT(devfn); | ||
259 | int fn = PCI_FUNC(devfn); | ||
260 | int busno = bus->number; | ||
261 | volatile void *addr; | ||
262 | u32 cf, shift, mask, smask; | ||
263 | int res; | ||
264 | |||
265 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
266 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
267 | if (get_dbe(cf, (u32 *) addr)) | ||
268 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
269 | |||
270 | /* | ||
271 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
272 | * generic PCI code a chance to look at it for real ... | ||
273 | */ | ||
274 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
275 | goto oh_my_gawd; | ||
276 | |||
277 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
278 | |||
279 | if (size == 1) { | ||
280 | res = put_dbe(value, (u8 *) addr); | ||
281 | } else if (size == 2) { | ||
282 | res = put_dbe(value, (u16 *) addr); | ||
283 | } else { | ||
284 | res = put_dbe(value, (u32 *) addr); | ||
285 | } | ||
286 | |||
287 | if (res) | ||
288 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
289 | |||
290 | return PCIBIOS_SUCCESSFUL; | ||
291 | |||
292 | oh_my_gawd: | ||
293 | |||
294 | /* | ||
295 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
296 | * generic PCI code a chance to touch the wrong register. | ||
297 | */ | ||
298 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
299 | return PCIBIOS_SUCCESSFUL; | ||
300 | |||
301 | /* | ||
302 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
303 | * anything but 32-bit words ... | ||
304 | */ | ||
305 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
306 | |||
307 | if (get_dbe(cf, (u32 *) addr)) | ||
308 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
309 | |||
310 | shift = ((where & 3) << 3); | ||
311 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
312 | smask = mask << shift; | ||
313 | |||
314 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
315 | if (put_dbe(cf, (u32 *) addr)) | ||
316 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
317 | |||
318 | return PCIBIOS_SUCCESSFUL; | ||
319 | } | ||
320 | |||
321 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
322 | int where, int size, u32 value) | ||
323 | { | ||
324 | if (bus->number > 0) | ||
325 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
326 | |||
327 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
328 | } | ||
329 | |||
330 | static struct pci_ops bridge_pci_ops = { | ||
331 | .read = pci_read_config, | ||
332 | .write = pci_write_config, | ||
333 | }; | ||
334 | |||
335 | int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) | ||
336 | { | ||
337 | unsigned long offset = NODE_OFFSET(nasid); | ||
338 | struct bridge_controller *bc; | ||
339 | static int num_bridges = 0; | ||
340 | bridge_t *bridge; | ||
341 | int slot; | ||
342 | |||
343 | printk("a bridge\n"); | ||
344 | |||
345 | /* XXX: kludge alert.. */ | ||
346 | if (!num_bridges) | ||
347 | ioport_resource.end = ~0UL; | ||
348 | |||
349 | bc = &bridges[num_bridges]; | ||
350 | |||
351 | bc->pc.pci_ops = &bridge_pci_ops; | ||
352 | bc->pc.mem_resource = &bc->mem; | ||
353 | bc->pc.io_resource = &bc->io; | ||
354 | |||
355 | bc->pc.index = num_bridges; | ||
356 | |||
357 | bc->mem.name = "Bridge PCI MEM"; | ||
358 | bc->pc.mem_offset = offset; | ||
359 | bc->mem.start = 0; | ||
360 | bc->mem.end = ~0UL; | ||
361 | bc->mem.flags = IORESOURCE_MEM; | ||
362 | |||
363 | bc->io.name = "Bridge IO MEM"; | ||
364 | bc->pc.io_offset = offset; | ||
365 | bc->io.start = 0UL; | ||
366 | bc->io.end = ~0UL; | ||
367 | bc->io.flags = IORESOURCE_IO; | ||
368 | |||
369 | bc->irq_cpu = smp_processor_id(); | ||
370 | bc->widget_id = widget_id; | ||
371 | bc->nasid = nasid; | ||
372 | |||
373 | bc->baddr = (u64)masterwid << 60; | ||
374 | bc->baddr |= (1UL << 56); /* Barrier set */ | ||
375 | |||
376 | /* | ||
377 | * point to this bridge | ||
378 | */ | ||
379 | bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); | ||
380 | |||
381 | /* | ||
382 | * Clear all pending interrupts. | ||
383 | */ | ||
384 | bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; | ||
385 | |||
386 | /* | ||
387 | * Until otherwise set up, assume all interrupts are from slot 0 | ||
388 | */ | ||
389 | bridge->b_int_device = 0x0; | ||
390 | |||
391 | /* | ||
392 | * swap pio's to pci mem and io space (big windows) | ||
393 | */ | ||
394 | bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | | ||
395 | BRIDGE_CTRL_MEM_SWAP; | ||
396 | |||
397 | /* | ||
398 | * Hmm... IRIX sets additional bits in the address which | ||
399 | * are documented as reserved in the bridge docs. | ||
400 | */ | ||
401 | bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); | ||
402 | bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ | ||
403 | bridge->b_dir_map = (masterwid << 20); /* DMA */ | ||
404 | bridge->b_int_enable = 0; | ||
405 | |||
406 | for (slot = 0; slot < 8; slot ++) { | ||
407 | bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; | ||
408 | bc->pci_int[slot] = -1; | ||
409 | } | ||
410 | bridge->b_wid_tflush; /* wait until Bridge PIO complete */ | ||
411 | |||
412 | bc->base = bridge; | ||
413 | |||
414 | register_pci_controller(&bc->pc); | ||
415 | |||
416 | num_bridges++; | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * All observed requests have pin == 1. We could have a global here, that | ||
423 | * gets incremented and returned every time - unfortunately, pci_map_irq | ||
424 | * may be called on the same device over and over, and need to return the | ||
425 | * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. | ||
426 | * | ||
427 | * A given PCI device, in general, should be able to intr any of the cpus | ||
428 | * on any one of the hubs connected to its xbow. | ||
429 | */ | ||
430 | int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
431 | { | ||
432 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
433 | int irq = bc->pci_int[slot]; | ||
434 | |||
435 | if (irq == -1) { | ||
436 | irq = bc->pci_int[slot] = request_bridge_irq(bc); | ||
437 | if (irq < 0) | ||
438 | panic("Can't allocate interrupt for PCI device %s\n", | ||
439 | pci_name(dev)); | ||
440 | } | ||
441 | |||
442 | irq_to_bridge[irq] = bc; | ||
443 | irq_to_slot[irq] = slot; | ||
444 | |||
445 | return irq; | ||
446 | } | ||
447 | |||
448 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
449 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
450 | { | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses | ||
456 | * to find the slot number in sense of the bridge device register. | ||
457 | * XXX This also means multiple devices might rely on conflicting bridge | ||
458 | * settings. | ||
459 | */ | ||
460 | |||
461 | static inline void pci_disable_swapping(struct pci_dev *dev) | ||
462 | { | ||
463 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
464 | bridge_t *bridge = bc->base; | ||
465 | int slot = PCI_SLOT(dev->devfn); | ||
466 | |||
467 | /* Turn off byte swapping */ | ||
468 | bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; | ||
469 | bridge->b_widget.w_tflush; /* Flush */ | ||
470 | } | ||
471 | |||
472 | static inline void pci_enable_swapping(struct pci_dev *dev) | ||
473 | { | ||
474 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
475 | bridge_t *bridge = bc->base; | ||
476 | int slot = PCI_SLOT(dev->devfn); | ||
477 | |||
478 | /* Turn on byte swapping */ | ||
479 | bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; | ||
480 | bridge->b_widget.w_tflush; /* Flush */ | ||
481 | } | ||
482 | |||
483 | static void __init pci_fixup_ioc3(struct pci_dev *d) | ||
484 | { | ||
485 | pci_disable_swapping(d); | ||
486 | } | ||
487 | |||
488 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, | ||
489 | pci_fixup_ioc3); | ||
diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c new file mode 100644 index 000000000000..1faeb034f06e --- /dev/null +++ b/arch/mips/pci/pci-ip32.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 Keith M Wesolowski | ||
7 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
8 | */ | ||
9 | #include <linux/config.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <asm/ip32/mace.h> | ||
16 | #include <asm/ip32/ip32_ints.h> | ||
17 | |||
18 | #undef DEBUG_MACE_PCI | ||
19 | |||
20 | /* | ||
21 | * Handle errors from the bridge. This includes master and target aborts, | ||
22 | * various command and address errors, and the interrupt test. This gets | ||
23 | * registered on the bridge error irq. It's conceivable that some of these | ||
24 | * conditions warrant a panic. Anybody care to say which ones? | ||
25 | */ | ||
26 | static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs) | ||
27 | { | ||
28 | char s; | ||
29 | unsigned int flags = mace->pci.error; | ||
30 | unsigned int addr = mace->pci.error_addr; | ||
31 | |||
32 | if (flags & MACEPCI_ERROR_MEMORY_ADDR) | ||
33 | s = 'M'; | ||
34 | else if (flags & MACEPCI_ERROR_CONFIG_ADDR) | ||
35 | s = 'C'; | ||
36 | else | ||
37 | s = 'X'; | ||
38 | |||
39 | if (flags & MACEPCI_ERROR_MASTER_ABORT) { | ||
40 | printk("MACEPCI: Master abort at 0x%08x (%c)\n", addr, s); | ||
41 | flags &= ~MACEPCI_ERROR_MASTER_ABORT; | ||
42 | } | ||
43 | if (flags & MACEPCI_ERROR_TARGET_ABORT) { | ||
44 | printk("MACEPCI: Target abort at 0x%08x (%c)\n", addr, s); | ||
45 | flags &= ~MACEPCI_ERROR_TARGET_ABORT; | ||
46 | } | ||
47 | if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) { | ||
48 | printk("MACEPCI: Data parity error at 0x%08x (%c)\n", addr, s); | ||
49 | flags &= ~MACEPCI_ERROR_DATA_PARITY_ERR; | ||
50 | } | ||
51 | if (flags & MACEPCI_ERROR_RETRY_ERR) { | ||
52 | printk("MACEPCI: Retry error at 0x%08x (%c)\n", addr, s); | ||
53 | flags &= ~MACEPCI_ERROR_RETRY_ERR; | ||
54 | } | ||
55 | if (flags & MACEPCI_ERROR_ILLEGAL_CMD) { | ||
56 | printk("MACEPCI: Illegal command at 0x%08x (%c)\n", addr, s); | ||
57 | flags &= ~MACEPCI_ERROR_ILLEGAL_CMD; | ||
58 | } | ||
59 | if (flags & MACEPCI_ERROR_SYSTEM_ERR) { | ||
60 | printk("MACEPCI: System error at 0x%08x (%c)\n", addr, s); | ||
61 | flags &= ~MACEPCI_ERROR_SYSTEM_ERR; | ||
62 | } | ||
63 | if (flags & MACEPCI_ERROR_PARITY_ERR) { | ||
64 | printk("MACEPCI: Parity error at 0x%08x (%c)\n", addr, s); | ||
65 | flags &= ~MACEPCI_ERROR_PARITY_ERR; | ||
66 | } | ||
67 | if (flags & MACEPCI_ERROR_OVERRUN) { | ||
68 | printk("MACEPCI: Overrun error at 0x%08x (%c)\n", addr, s); | ||
69 | flags &= ~MACEPCI_ERROR_OVERRUN; | ||
70 | } | ||
71 | if (flags & MACEPCI_ERROR_SIG_TABORT) { | ||
72 | printk("MACEPCI: Signaled target abort (clearing)\n"); | ||
73 | flags &= ~MACEPCI_ERROR_SIG_TABORT; | ||
74 | } | ||
75 | if (flags & MACEPCI_ERROR_INTERRUPT_TEST) { | ||
76 | printk("MACEPCI: Interrupt test triggered (clearing)\n"); | ||
77 | flags &= ~MACEPCI_ERROR_INTERRUPT_TEST; | ||
78 | } | ||
79 | |||
80 | mace->pci.error = flags; | ||
81 | |||
82 | return IRQ_HANDLED; | ||
83 | } | ||
84 | |||
85 | |||
86 | extern struct pci_ops mace_pci_ops; | ||
87 | #ifdef CONFIG_MIPS64 | ||
88 | static struct resource mace_pci_mem_resource = { | ||
89 | .name = "SGI O2 PCI MEM", | ||
90 | .start = MACEPCI_HI_MEMORY, | ||
91 | .end = 0x2FFFFFFFFUL, | ||
92 | .flags = IORESOURCE_MEM, | ||
93 | }; | ||
94 | static struct resource mace_pci_io_resource = { | ||
95 | .name = "SGI O2 PCI IO", | ||
96 | .start = 0x00000000UL, | ||
97 | .end = 0xffffffffUL, | ||
98 | .flags = IORESOURCE_IO, | ||
99 | }; | ||
100 | #define MACE_PCI_MEM_OFFSET 0x200000000 | ||
101 | #else | ||
102 | static struct resource mace_pci_mem_resource = { | ||
103 | .name = "SGI O2 PCI MEM", | ||
104 | .start = MACEPCI_LOW_MEMORY, | ||
105 | .end = MACEPCI_LOW_MEMORY + 0x2000000 - 1, | ||
106 | .flags = IORESOURCE_MEM, | ||
107 | }; | ||
108 | static struct resource mace_pci_io_resource = { | ||
109 | .name = "SGI O2 PCI IO", | ||
110 | .start = 0x00000000, | ||
111 | .end = 0xFFFFFFFF, | ||
112 | .flags = IORESOURCE_IO, | ||
113 | }; | ||
114 | #define MACE_PCI_MEM_OFFSET (MACEPCI_LOW_MEMORY - 0x80000000) | ||
115 | #endif | ||
116 | static struct pci_controller mace_pci_controller = { | ||
117 | .pci_ops = &mace_pci_ops, | ||
118 | .mem_resource = &mace_pci_mem_resource, | ||
119 | .io_resource = &mace_pci_io_resource, | ||
120 | .iommu = 0, | ||
121 | .mem_offset = MACE_PCI_MEM_OFFSET, | ||
122 | .io_offset = 0, | ||
123 | }; | ||
124 | |||
125 | static int __init mace_init(void) | ||
126 | { | ||
127 | PCIBIOS_MIN_IO = 0x1000; | ||
128 | |||
129 | /* Clear any outstanding errors and enable interrupts */ | ||
130 | mace->pci.error_addr = 0; | ||
131 | mace->pci.error = 0; | ||
132 | mace->pci.control = 0xff008500; | ||
133 | |||
134 | printk("MACE PCI rev %d\n", mace->pci.rev); | ||
135 | |||
136 | BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0, | ||
137 | "MACE PCI error", NULL)); | ||
138 | |||
139 | ioport_resource.end = mace_pci_io_resource.end; | ||
140 | register_pci_controller(&mace_pci_controller); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | arch_initcall(mace_init); | ||
diff --git a/arch/mips/pci/pci-jmr3927.c b/arch/mips/pci/pci-jmr3927.c new file mode 100644 index 000000000000..95a028769e56 --- /dev/null +++ b/arch/mips/pci/pci-jmr3927.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: MontaVista Software, Inc. | ||
4 | * ahennessy@mvista.com | ||
5 | * | ||
6 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
7 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
17 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
20 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/init.h> | ||
33 | |||
34 | #include <asm/jmr3927/jmr3927.h> | ||
35 | #include <asm/debug.h> | ||
36 | |||
37 | struct resource pci_io_resource = { | ||
38 | "IO MEM", | ||
39 | 0x1000, /* reserve regacy I/O space */ | ||
40 | 0x1000 + JMR3927_PCIIO_SIZE - 1, | ||
41 | IORESOURCE_IO | ||
42 | }; | ||
43 | |||
44 | struct resource pci_mem_resource = { | ||
45 | "PCI MEM", | ||
46 | JMR3927_PCIMEM, | ||
47 | JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1, | ||
48 | IORESOURCE_MEM | ||
49 | }; | ||
50 | |||
51 | extern struct pci_ops jmr3927_pci_ops; | ||
52 | |||
53 | struct pci_controller jmr3927_controller = { | ||
54 | .pci_ops = &jmr3927_pci_ops, | ||
55 | .io_resource = &pci_io_resource, | ||
56 | .mem_resource = &pci_mem_resource, | ||
57 | .mem_offset = JMR3927_PCIMEM; | ||
58 | }; | ||
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c new file mode 100644 index 000000000000..ae3cc4b254b5 --- /dev/null +++ b/arch/mips/pci/pci-lasat.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001, 04 Keith M Wesolowski | ||
7 | */ | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <asm/bootinfo.h> | ||
17 | |||
18 | extern struct pci_ops nile4_pci_ops; | ||
19 | extern struct pci_ops gt64120_pci_ops; | ||
20 | static struct resource lasat_pci_mem_resource = { | ||
21 | .name = "LASAT PCI MEM", | ||
22 | .start = 0x18000000, | ||
23 | .end = 0x19FFFFFF, | ||
24 | .flags = IORESOURCE_MEM, | ||
25 | }; | ||
26 | |||
27 | static struct resource lasat_pci_io_resource = { | ||
28 | .name = "LASAT PCI IO", | ||
29 | .start = 0x1a000000, | ||
30 | .end = 0x1bFFFFFF, | ||
31 | .flags = IORESOURCE_IO, | ||
32 | }; | ||
33 | |||
34 | static struct pci_controller lasat_pci_controller = { | ||
35 | .mem_resource = &lasat_pci_mem_resource, | ||
36 | .io_resource = &lasat_pci_io_resource, | ||
37 | }; | ||
38 | |||
39 | static int __init lasat_pci_setup(void) | ||
40 | { | ||
41 | printk("PCI: starting\n"); | ||
42 | |||
43 | switch (mips_machtype) { | ||
44 | case MACH_LASAT_100: | ||
45 | lasat_pci_controller.pci_ops = >64120_pci_ops; | ||
46 | break; | ||
47 | case MACH_LASAT_200: | ||
48 | lasat_pci_controller.pci_ops = &nile4_pci_ops; | ||
49 | break; | ||
50 | default: | ||
51 | panic("pcibios_init: mips_machtype incorrect"); | ||
52 | } | ||
53 | |||
54 | register_pci_controller(&lasat_pci_controller); | ||
55 | return 0; | ||
56 | } | ||
57 | early_initcall(lasat_pci_setup); | ||
58 | |||
59 | #define LASATINT_ETH1 0 | ||
60 | #define LASATINT_ETH0 1 | ||
61 | #define LASATINT_HDC 2 | ||
62 | #define LASATINT_COMP 3 | ||
63 | #define LASATINT_HDLC 4 | ||
64 | #define LASATINT_PCIA 5 | ||
65 | #define LASATINT_PCIB 6 | ||
66 | #define LASATINT_PCIC 7 | ||
67 | #define LASATINT_PCID 8 | ||
68 | |||
69 | int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
70 | { | ||
71 | switch (slot) { | ||
72 | case 1: | ||
73 | return LASATINT_PCIA; /* Expansion Module 0 */ | ||
74 | case 2: | ||
75 | return LASATINT_PCIB; /* Expansion Module 1 */ | ||
76 | case 3: | ||
77 | return LASATINT_PCIC; /* Expansion Module 2 */ | ||
78 | case 4: | ||
79 | return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */ | ||
80 | case 5: | ||
81 | return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */ | ||
82 | case 6: | ||
83 | return LASATINT_HDC; /* IDE controller */ | ||
84 | default: | ||
85 | return 0xff; /* Illegal */ | ||
86 | } | ||
87 | |||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
92 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c new file mode 100644 index 000000000000..1d84d36e034d --- /dev/null +++ b/arch/mips/pci/pci-ocelot-c.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
7 | */ | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <asm/mv64340.h> | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | |||
15 | /* | ||
16 | * We assume the address ranges have already been setup appropriately by | ||
17 | * the firmware. PMON in case of the Ocelot C does that. | ||
18 | */ | ||
19 | static struct resource mv_pci_io_mem0_resource = { | ||
20 | .name = "MV64340 PCI0 IO MEM", | ||
21 | .flags = IORESOURCE_IO | ||
22 | }; | ||
23 | |||
24 | static struct resource mv_pci_mem0_resource = { | ||
25 | .name = "MV64340 PCI0 MEM", | ||
26 | .flags = IORESOURCE_MEM | ||
27 | }; | ||
28 | |||
29 | static struct mv_pci_controller mv_bus0_controller = { | ||
30 | .pcic = { | ||
31 | .pci_ops = &mv_pci_ops, | ||
32 | .mem_resource = &mv_pci_mem0_resource, | ||
33 | .io_resource = &mv_pci_io_mem0_resource, | ||
34 | }, | ||
35 | .config_addr = MV64340_PCI_0_CONFIG_ADDR, | ||
36 | .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG, | ||
37 | }; | ||
38 | |||
39 | static uint32_t mv_io_base, mv_io_size; | ||
40 | |||
41 | static void mv64340_pci0_init(void) | ||
42 | { | ||
43 | uint32_t mem0_base, mem0_size; | ||
44 | uint32_t io_base, io_size; | ||
45 | |||
46 | io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16; | ||
47 | io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16; | ||
48 | mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16; | ||
49 | mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16; | ||
50 | |||
51 | mv_pci_io_mem0_resource.start = 0; | ||
52 | mv_pci_io_mem0_resource.end = io_size - 1; | ||
53 | mv_pci_mem0_resource.start = mem0_base; | ||
54 | mv_pci_mem0_resource.end = mem0_base + mem0_size - 1; | ||
55 | mv_bus0_controller.pcic.mem_offset = mem0_base; | ||
56 | mv_bus0_controller.pcic.io_offset = 0; | ||
57 | |||
58 | ioport_resource.end = io_size - 1; | ||
59 | |||
60 | register_pci_controller(&mv_bus0_controller.pcic); | ||
61 | |||
62 | mv_io_base = io_base; | ||
63 | mv_io_size = io_size; | ||
64 | } | ||
65 | |||
66 | static struct resource mv_pci_io_mem1_resource = { | ||
67 | .name = "MV64340 PCI1 IO MEM", | ||
68 | .flags = IORESOURCE_IO | ||
69 | }; | ||
70 | |||
71 | static struct resource mv_pci_mem1_resource = { | ||
72 | .name = "MV64340 PCI1 MEM", | ||
73 | .flags = IORESOURCE_MEM | ||
74 | }; | ||
75 | |||
76 | static struct mv_pci_controller mv_bus1_controller = { | ||
77 | .pcic = { | ||
78 | .pci_ops = &mv_pci_ops, | ||
79 | .mem_resource = &mv_pci_mem1_resource, | ||
80 | .io_resource = &mv_pci_io_mem1_resource, | ||
81 | }, | ||
82 | .config_addr = MV64340_PCI_1_CONFIG_ADDR, | ||
83 | .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG, | ||
84 | }; | ||
85 | |||
86 | static __init void mv64340_pci1_init(void) | ||
87 | { | ||
88 | uint32_t mem0_base, mem0_size; | ||
89 | uint32_t io_base, io_size; | ||
90 | |||
91 | io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16; | ||
92 | io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16; | ||
93 | mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16; | ||
94 | mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16; | ||
95 | |||
96 | /* | ||
97 | * Here we assume the I/O window of second bus to be contiguous with | ||
98 | * the first. A gap is no problem but would waste address space for | ||
99 | * remapping the port space. | ||
100 | */ | ||
101 | mv_pci_io_mem1_resource.start = mv_io_size; | ||
102 | mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1; | ||
103 | mv_pci_mem1_resource.start = mem0_base; | ||
104 | mv_pci_mem1_resource.end = mem0_base + mem0_size - 1; | ||
105 | mv_bus1_controller.pcic.mem_offset = mem0_base; | ||
106 | mv_bus1_controller.pcic.io_offset = 0; | ||
107 | |||
108 | ioport_resource.end = io_base + io_size -mv_io_base - 1; | ||
109 | |||
110 | register_pci_controller(&mv_bus1_controller.pcic); | ||
111 | |||
112 | mv_io_size = io_base + io_size - mv_io_base; | ||
113 | } | ||
114 | |||
115 | static __init int __init ocelot_c_pci_init(void) | ||
116 | { | ||
117 | unsigned long io_v_base; | ||
118 | uint32_t enable; | ||
119 | |||
120 | enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE); | ||
121 | |||
122 | /* | ||
123 | * We require at least one enabled I/O or PCI memory window or we | ||
124 | * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3. | ||
125 | */ | ||
126 | if (enable & (0x01 << 9) || enable & (0x01 << 10)) | ||
127 | mv64340_pci0_init(); | ||
128 | |||
129 | if (enable & (0x01 << 14) || enable & (0x01 << 15)) | ||
130 | mv64340_pci1_init(); | ||
131 | |||
132 | if (mv_io_size) { | ||
133 | io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size); | ||
134 | if (!io_v_base) | ||
135 | panic("Could not ioremap I/O port range"); | ||
136 | |||
137 | set_io_port_base(io_v_base); | ||
138 | } | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | arch_initcall(ocelot_c_pci_init); | ||
diff --git a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c new file mode 100644 index 000000000000..1e3430154fa0 --- /dev/null +++ b/arch/mips/pci/pci-ocelot-g.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
7 | * | ||
8 | * This doesn't really fly - but I don't have a GT64240 system for testing. | ||
9 | */ | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <asm/gt64240.h> | ||
15 | |||
16 | /* | ||
17 | * We assume these address ranges have been programmed into the GT-64240 by | ||
18 | * the firmware. PMON in case of the Ocelot G does that. Note the size of | ||
19 | * the I/O range is completly stupid; I/O mappings are limited to at most | ||
20 | * 256 bytes by the PCI spec and deprecated; and just to make things worse | ||
21 | * apparently many devices don't decode more than 64k of I/O space. | ||
22 | */ | ||
23 | |||
24 | #define gt_io_size 0x20000000UL | ||
25 | #define gt_io_base 0xe0000000UL | ||
26 | |||
27 | static struct resource gt_pci_mem0_resource = { | ||
28 | .name = "MV64240 PCI0 MEM", | ||
29 | .start = 0xc0000000UL, | ||
30 | .end = 0xcfffffffUL, | ||
31 | .flags = IORESOURCE_MEM | ||
32 | }; | ||
33 | |||
34 | static struct resource gt_pci_io_mem0_resource = { | ||
35 | .name = "MV64240 PCI0 IO MEM", | ||
36 | .start = 0xe0000000UL, | ||
37 | .end = 0xefffffffUL, | ||
38 | .flags = IORESOURCE_IO | ||
39 | }; | ||
40 | |||
41 | static struct mv_pci_controller gt_bus0_controller = { | ||
42 | .pcic = { | ||
43 | .pci_ops = &mv_pci_ops, | ||
44 | .mem_resource = >_pci_mem0_resource, | ||
45 | .mem_offset = 0xc0000000UL, | ||
46 | .io_resource = >_pci_io_mem0_resource, | ||
47 | .io_offset = 0x00000000UL | ||
48 | }, | ||
49 | .config_addr = PCI_0CONFIGURATION_ADDRESS, | ||
50 | .config_vreg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, | ||
51 | }; | ||
52 | |||
53 | static struct resource gt_pci_mem1_resource = { | ||
54 | .name = "MV64240 PCI1 MEM", | ||
55 | .start = 0xd0000000UL, | ||
56 | .end = 0xdfffffffUL, | ||
57 | .flags = IORESOURCE_MEM | ||
58 | }; | ||
59 | |||
60 | static struct resource gt_pci_io_mem1_resource = { | ||
61 | .name = "MV64240 PCI1 IO MEM", | ||
62 | .start = 0xf0000000UL, | ||
63 | .end = 0xffffffffUL, | ||
64 | .flags = IORESOURCE_IO | ||
65 | }; | ||
66 | |||
67 | static struct mv_pci_controller gt_bus1_controller = { | ||
68 | .pcic = { | ||
69 | .pci_ops = &mv_pci_ops, | ||
70 | .mem_resource = >_pci_mem1_resource, | ||
71 | .mem_offset = 0xd0000000UL, | ||
72 | .io_resource = >_pci_io_mem1_resource, | ||
73 | .io_offset = 0x10000000UL | ||
74 | }, | ||
75 | .config_addr = PCI_1CONFIGURATION_ADDRESS, | ||
76 | .config_vreg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER, | ||
77 | }; | ||
78 | |||
79 | static __init int __init ocelot_g_pci_init(void) | ||
80 | { | ||
81 | unsigned long io_v_base; | ||
82 | |||
83 | if (gt_io_size) { | ||
84 | io_v_base = (unsigned long) ioremap(gt_io_base, gt_io_size); | ||
85 | if (!io_v_base) | ||
86 | panic("Could not ioremap I/O port range"); | ||
87 | |||
88 | set_io_port_base(io_v_base); | ||
89 | } | ||
90 | |||
91 | register_pci_controller(>_bus0_controller.pcic); | ||
92 | register_pci_controller(>_bus1_controller.pcic); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | arch_initcall(ocelot_g_pci_init); | ||
diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c new file mode 100644 index 000000000000..3da8a4ee6baa --- /dev/null +++ b/arch/mips/pci/pci-ocelot.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * BRIEF MODULE DESCRIPTION | ||
3 | * Galileo Evaluation Boards PCI support. | ||
4 | * | ||
5 | * The general-purpose functions to read/write and configure the GT64120A's | ||
6 | * PCI registers (function names start with pci0 or pci1) are either direct | ||
7 | * copies of functions written by Galileo Technology, or are modifications | ||
8 | * of their functions to work with Linux 2.4 vs Linux 2.2. These functions | ||
9 | * are Copyright - Galileo Technology. | ||
10 | * | ||
11 | * Other functions are derived from other MIPS PCI implementations, or were | ||
12 | * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. | ||
13 | * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com | ||
14 | * | ||
15 | * Copyright 2001 MontaVista Software Inc. | ||
16 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify it | ||
19 | * under the terms of the GNU General Public License as published by the | ||
20 | * Free Software Foundation; either version 2 of the License, or (at your | ||
21 | * option) any later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
24 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
26 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
29 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
30 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * You should have received a copy of the GNU General Public License along | ||
35 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
36 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
37 | */ | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/kernel.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/cache.h> | ||
44 | #include <asm/pci.h> | ||
45 | #include <asm/io.h> | ||
46 | #include <asm/gt64120.h> | ||
47 | |||
48 | static inline unsigned int pci0ReadConfigReg(unsigned int offset) | ||
49 | { | ||
50 | unsigned int DataForRegCf8; | ||
51 | unsigned int data; | ||
52 | |||
53 | DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | | ||
54 | (PCI_FUNC(device->devfn) << 8) | | ||
55 | (offset & ~0x3)) | 0x80000000; | ||
56 | GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); | ||
57 | GT_READ(GT_PCI0_CFGDATA_OFS, &data); | ||
58 | |||
59 | return data; | ||
60 | } | ||
61 | |||
62 | static inline void pci0WriteConfigReg(unsigned int offset, unsigned int data) | ||
63 | { | ||
64 | unsigned int DataForRegCf8; | ||
65 | |||
66 | DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | | ||
67 | (PCI_FUNC(device->devfn) << 8) | | ||
68 | (offset & ~0x3)) | 0x80000000; | ||
69 | GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); | ||
70 | GT_WRITE(GT_PCI0_CFGDATA_OFS, data); | ||
71 | } | ||
72 | |||
73 | static struct resource ocelot_mem_resource = { | ||
74 | iomem_resource.start = GT_PCI_MEM_BASE; | ||
75 | iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; | ||
76 | }; | ||
77 | |||
78 | static struct resource ocelot_io_resource = { | ||
79 | ioport_resource.start = GT_PCI_IO_BASE; | ||
80 | ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; | ||
81 | }; | ||
82 | |||
83 | static struct pci_controller ocelot_pci_controller = { | ||
84 | .pci_ops = gt64120_pci_ops; | ||
85 | .mem_resource = &ocelot_mem_resource; | ||
86 | .io_resource = &ocelot_io_resource; | ||
87 | }; | ||
88 | |||
89 | static int __init ocelot_pcibios_init(void) | ||
90 | { | ||
91 | u32 tmp; | ||
92 | |||
93 | GT_READ(GT_PCI0_CMD_OFS, &tmp); | ||
94 | GT_READ(GT_PCI0_BARE_OFS, &tmp); | ||
95 | |||
96 | /* | ||
97 | * You have to enable bus mastering to configure any other | ||
98 | * card on the bus. | ||
99 | */ | ||
100 | tmp = pci0ReadConfigReg(PCI_COMMAND); | ||
101 | tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; | ||
102 | pci0WriteConfigReg(PCI_COMMAND, tmp); | ||
103 | |||
104 | register_pci_controller(&ocelot_pci_controller); | ||
105 | } | ||
106 | |||
107 | arch_initcall(ocelot_pcibios_init); | ||
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c new file mode 100644 index 000000000000..7cca3bde59b2 --- /dev/null +++ b/arch/mips/pci/pci-sb1250.c | |||
@@ -0,0 +1,292 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001,2002,2003 Broadcom Corporation | ||
3 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * BCM1250-specific PCI support | ||
22 | * | ||
23 | * This module provides the glue between Linux's PCI subsystem | ||
24 | * and the hardware. We basically provide glue for accessing | ||
25 | * configuration space, and set up the translation for I/O | ||
26 | * space accesses. | ||
27 | * | ||
28 | * To access configuration space, we use ioremap. In the 32-bit | ||
29 | * kernel, this consumes either 4 or 8 page table pages, and 16MB of | ||
30 | * kernel mapped memory. Hopefully neither of these should be a huge | ||
31 | * problem. | ||
32 | */ | ||
33 | #include <linux/config.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/pci.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/mm.h> | ||
39 | #include <linux/console.h> | ||
40 | #include <linux/tty.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | |||
44 | #include <asm/sibyte/sb1250_defs.h> | ||
45 | #include <asm/sibyte/sb1250_regs.h> | ||
46 | #include <asm/sibyte/sb1250_scd.h> | ||
47 | #include <asm/sibyte/board.h> | ||
48 | |||
49 | /* | ||
50 | * Macros for calculating offsets into config space given a device | ||
51 | * structure or dev/fun/reg | ||
52 | */ | ||
53 | #define CFGOFFSET(bus,devfn,where) (((bus)<<16) + ((devfn)<<8) + (where)) | ||
54 | #define CFGADDR(bus,devfn,where) CFGOFFSET((bus)->number,(devfn),where) | ||
55 | |||
56 | static void *cfg_space; | ||
57 | |||
58 | #define PCI_BUS_ENABLED 1 | ||
59 | #define LDT_BUS_ENABLED 2 | ||
60 | #define PCI_DEVICE_MODE 4 | ||
61 | |||
62 | static int sb1250_bus_status = 0; | ||
63 | |||
64 | #define PCI_BRIDGE_DEVICE 0 | ||
65 | #define LDT_BRIDGE_DEVICE 1 | ||
66 | |||
67 | #ifdef CONFIG_SIBYTE_HAS_LDT | ||
68 | /* | ||
69 | * HT's level-sensitive interrupts require EOI, which is generated | ||
70 | * through a 4MB memory-mapped region | ||
71 | */ | ||
72 | unsigned long ldt_eoi_space; | ||
73 | #endif | ||
74 | |||
75 | /* | ||
76 | * Read/write 32-bit values in config space. | ||
77 | */ | ||
78 | static inline u32 READCFG32(u32 addr) | ||
79 | { | ||
80 | return *(u32 *) (cfg_space + (addr & ~3)); | ||
81 | } | ||
82 | |||
83 | static inline void WRITECFG32(u32 addr, u32 data) | ||
84 | { | ||
85 | *(u32 *) (cfg_space + (addr & ~3)) = data; | ||
86 | } | ||
87 | |||
88 | int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
89 | { | ||
90 | return dev->irq; | ||
91 | } | ||
92 | |||
93 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
94 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Some checks before doing config cycles: | ||
101 | * In PCI Device Mode, hide everything on bus 0 except the LDT host | ||
102 | * bridge. Otherwise, access is controlled by bridge MasterEn bits. | ||
103 | */ | ||
104 | static int sb1250_pci_can_access(struct pci_bus *bus, int devfn) | ||
105 | { | ||
106 | u32 devno; | ||
107 | |||
108 | if (!(sb1250_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE))) | ||
109 | return 0; | ||
110 | |||
111 | if (bus->number == 0) { | ||
112 | devno = PCI_SLOT(devfn); | ||
113 | if (devno == LDT_BRIDGE_DEVICE) | ||
114 | return (sb1250_bus_status & LDT_BUS_ENABLED) != 0; | ||
115 | else if (sb1250_bus_status & PCI_DEVICE_MODE) | ||
116 | return 0; | ||
117 | else | ||
118 | return 1; | ||
119 | } else | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Read/write access functions for various sizes of values | ||
125 | * in config space. Return all 1's for disallowed accesses | ||
126 | * for a kludgy but adequate simulation of master aborts. | ||
127 | */ | ||
128 | |||
129 | static int sb1250_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
130 | int where, int size, u32 * val) | ||
131 | { | ||
132 | u32 data = 0; | ||
133 | |||
134 | if ((size == 2) && (where & 1)) | ||
135 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
136 | else if ((size == 4) && (where & 3)) | ||
137 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
138 | |||
139 | if (sb1250_pci_can_access(bus, devfn)) | ||
140 | data = READCFG32(CFGADDR(bus, devfn, where)); | ||
141 | else | ||
142 | data = 0xFFFFFFFF; | ||
143 | |||
144 | if (size == 1) | ||
145 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
146 | else if (size == 2) | ||
147 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
148 | else | ||
149 | *val = data; | ||
150 | |||
151 | return PCIBIOS_SUCCESSFUL; | ||
152 | } | ||
153 | |||
154 | static int sb1250_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
155 | int where, int size, u32 val) | ||
156 | { | ||
157 | u32 cfgaddr = CFGADDR(bus, devfn, where); | ||
158 | u32 data = 0; | ||
159 | |||
160 | if ((size == 2) && (where & 1)) | ||
161 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
162 | else if ((size == 4) && (where & 3)) | ||
163 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
164 | |||
165 | if (!sb1250_pci_can_access(bus, devfn)) | ||
166 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
167 | |||
168 | data = READCFG32(cfgaddr); | ||
169 | |||
170 | if (size == 1) | ||
171 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
172 | (val << ((where & 3) << 3)); | ||
173 | else if (size == 2) | ||
174 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
175 | (val << ((where & 3) << 3)); | ||
176 | else | ||
177 | data = val; | ||
178 | |||
179 | WRITECFG32(cfgaddr, data); | ||
180 | |||
181 | return PCIBIOS_SUCCESSFUL; | ||
182 | } | ||
183 | |||
184 | struct pci_ops sb1250_pci_ops = { | ||
185 | .read = sb1250_pcibios_read, | ||
186 | .write = sb1250_pcibios_write, | ||
187 | }; | ||
188 | |||
189 | static struct resource sb1250_mem_resource = { | ||
190 | .name = "SB1250 PCI MEM", | ||
191 | .start = 0x40000000UL, | ||
192 | .end = 0x5fffffffUL, | ||
193 | .flags = IORESOURCE_MEM, | ||
194 | }; | ||
195 | |||
196 | static struct resource sb1250_io_resource = { | ||
197 | .name = "SB1250 PCI I/O", | ||
198 | .start = 0x00000000UL, | ||
199 | .end = 0x01ffffffUL, | ||
200 | .flags = IORESOURCE_IO, | ||
201 | }; | ||
202 | |||
203 | struct pci_controller sb1250_controller = { | ||
204 | .pci_ops = &sb1250_pci_ops, | ||
205 | .mem_resource = &sb1250_mem_resource, | ||
206 | .io_resource = &sb1250_io_resource, | ||
207 | }; | ||
208 | |||
209 | static int __init sb1250_pcibios_init(void) | ||
210 | { | ||
211 | uint32_t cmdreg; | ||
212 | uint64_t reg; | ||
213 | extern int pci_probe_only; | ||
214 | |||
215 | /* CFE will assign PCI resources */ | ||
216 | pci_probe_only = 1; | ||
217 | |||
218 | /* Avoid ISA compat ranges. */ | ||
219 | PCIBIOS_MIN_IO = 0x00008000UL; | ||
220 | PCIBIOS_MIN_MEM = 0x01000000UL; | ||
221 | |||
222 | /* Set I/O resource limits. */ | ||
223 | ioport_resource.end = 0x01ffffffUL; /* 32MB accessible by sb1250 */ | ||
224 | iomem_resource.end = 0xffffffffUL; /* no HT support yet */ | ||
225 | |||
226 | cfg_space = | ||
227 | ioremap(A_PHYS_LDTPCI_CFG_MATCH_BITS, 16 * 1024 * 1024); | ||
228 | |||
229 | /* | ||
230 | * See if the PCI bus has been configured by the firmware. | ||
231 | */ | ||
232 | reg = *((volatile uint64_t *) IOADDR(A_SCD_SYSTEM_CFG)); | ||
233 | if (!(reg & M_SYS_PCI_HOST)) { | ||
234 | sb1250_bus_status |= PCI_DEVICE_MODE; | ||
235 | } else { | ||
236 | cmdreg = | ||
237 | READCFG32(CFGOFFSET | ||
238 | (0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), | ||
239 | PCI_COMMAND)); | ||
240 | if (!(cmdreg & PCI_COMMAND_MASTER)) { | ||
241 | printk | ||
242 | ("PCI: Skipping PCI probe. Bus is not initialized.\n"); | ||
243 | iounmap(cfg_space); | ||
244 | return 0; | ||
245 | } | ||
246 | sb1250_bus_status |= PCI_BUS_ENABLED; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Establish mappings in KSEG2 (kernel virtual) to PCI I/O | ||
251 | * space. Use "match bytes" policy to make everything look | ||
252 | * little-endian. So, you need to also set | ||
253 | * CONFIG_SWAP_IO_SPACE, but this is the combination that | ||
254 | * works correctly with most of Linux's drivers. | ||
255 | * XXX ehs: Should this happen in PCI Device mode? | ||
256 | */ | ||
257 | |||
258 | set_io_port_base((unsigned long) | ||
259 | ioremap(A_PHYS_LDTPCI_IO_MATCH_BYTES, 65536)); | ||
260 | isa_slot_offset = (unsigned long) | ||
261 | ioremap(A_PHYS_LDTPCI_IO_MATCH_BYTES_32, 1024 * 1024); | ||
262 | |||
263 | #ifdef CONFIG_SIBYTE_HAS_LDT | ||
264 | /* | ||
265 | * Also check the LDT bridge's enable, just in case we didn't | ||
266 | * initialize that one. | ||
267 | */ | ||
268 | |||
269 | cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(LDT_BRIDGE_DEVICE, 0), | ||
270 | PCI_COMMAND)); | ||
271 | if (cmdreg & PCI_COMMAND_MASTER) { | ||
272 | sb1250_bus_status |= LDT_BUS_ENABLED; | ||
273 | |||
274 | /* | ||
275 | * Need bits 23:16 to convey vector number. Note that | ||
276 | * this consumes 4MB of kernel-mapped memory | ||
277 | * (Kseg2/Kseg3) for 32-bit kernel. | ||
278 | */ | ||
279 | ldt_eoi_space = (unsigned long) | ||
280 | ioremap(A_PHYS_LDT_SPECIAL_MATCH_BYTES, | ||
281 | 4 * 1024 * 1024); | ||
282 | } | ||
283 | #endif | ||
284 | |||
285 | register_pci_controller(&sb1250_controller); | ||
286 | |||
287 | #ifdef CONFIG_VGA_CONSOLE | ||
288 | take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); | ||
289 | #endif | ||
290 | return 0; | ||
291 | } | ||
292 | arch_initcall(sb1250_pcibios_init); | ||
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c new file mode 100644 index 000000000000..f3ccbf7fada4 --- /dev/null +++ b/arch/mips/pci/pci-vr41xx.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series. | ||
3 | * | ||
4 | * Copyright (C) 2001-2003 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | ||
6 | * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
7 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | /* | ||
24 | * Changes: | ||
25 | * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> | ||
26 | * - New creation, NEC VR4122 and VR4131 are supported. | ||
27 | */ | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/types.h> | ||
31 | |||
32 | #include <asm/cpu.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/vr41xx/vr41xx.h> | ||
35 | |||
36 | #include "pci-vr41xx.h" | ||
37 | |||
38 | extern struct pci_ops vr41xx_pci_ops; | ||
39 | |||
40 | static struct pci_master_address_conversion pci_master_memory1 = { | ||
41 | .bus_base_address = PCI_MASTER_MEM1_BUS_BASE_ADDRESS, | ||
42 | .address_mask = PCI_MASTER_MEM1_ADDRESS_MASK, | ||
43 | .pci_base_address = PCI_MASTER_MEM1_PCI_BASE_ADDRESS, | ||
44 | }; | ||
45 | |||
46 | static struct pci_target_address_conversion pci_target_memory1 = { | ||
47 | .address_mask = PCI_TARGET_MEM1_ADDRESS_MASK, | ||
48 | .bus_base_address = PCI_TARGET_MEM1_BUS_BASE_ADDRESS, | ||
49 | }; | ||
50 | |||
51 | static struct pci_master_address_conversion pci_master_io = { | ||
52 | .bus_base_address = PCI_MASTER_IO_BUS_BASE_ADDRESS, | ||
53 | .address_mask = PCI_MASTER_IO_ADDRESS_MASK, | ||
54 | .pci_base_address = PCI_MASTER_IO_PCI_BASE_ADDRESS, | ||
55 | }; | ||
56 | |||
57 | static struct pci_mailbox_address pci_mailbox = { | ||
58 | .base_address = PCI_MAILBOX_BASE_ADDRESS, | ||
59 | }; | ||
60 | |||
61 | static struct pci_target_address_window pci_target_window1 = { | ||
62 | .base_address = PCI_TARGET_WINDOW1_BASE_ADDRESS, | ||
63 | }; | ||
64 | |||
65 | static struct resource pci_mem_resource = { | ||
66 | .name = "PCI Memory resources", | ||
67 | .start = PCI_MEM_RESOURCE_START, | ||
68 | .end = PCI_MEM_RESOURCE_END, | ||
69 | .flags = IORESOURCE_MEM, | ||
70 | }; | ||
71 | |||
72 | static struct resource pci_io_resource = { | ||
73 | .name = "PCI I/O resources", | ||
74 | .start = PCI_IO_RESOURCE_START, | ||
75 | .end = PCI_IO_RESOURCE_END, | ||
76 | .flags = IORESOURCE_IO, | ||
77 | }; | ||
78 | |||
79 | static struct pci_controller_unit_setup vr41xx_pci_controller_unit_setup = { | ||
80 | .master_memory1 = &pci_master_memory1, | ||
81 | .target_memory1 = &pci_target_memory1, | ||
82 | .master_io = &pci_master_io, | ||
83 | .exclusive_access = CANNOT_LOCK_FROM_DEVICE, | ||
84 | .wait_time_limit_from_irdy_to_trdy = 0, | ||
85 | .mailbox = &pci_mailbox, | ||
86 | .target_window1 = &pci_target_window1, | ||
87 | .master_latency_timer = 0x80, | ||
88 | .retry_limit = 0, | ||
89 | .arbiter_priority_control = PCI_ARBITRATION_MODE_FAIR, | ||
90 | .take_away_gnt_mode = PCI_TAKE_AWAY_GNT_DISABLE, | ||
91 | }; | ||
92 | |||
93 | static struct pci_controller vr41xx_pci_controller = { | ||
94 | .pci_ops = &vr41xx_pci_ops, | ||
95 | .mem_resource = &pci_mem_resource, | ||
96 | .io_resource = &pci_io_resource, | ||
97 | }; | ||
98 | |||
99 | void __init vr41xx_pciu_setup(struct pci_controller_unit_setup *setup) | ||
100 | { | ||
101 | vr41xx_pci_controller_unit_setup = *setup; | ||
102 | } | ||
103 | |||
104 | static int __init vr41xx_pciu_init(void) | ||
105 | { | ||
106 | struct pci_controller_unit_setup *setup; | ||
107 | struct pci_master_address_conversion *master; | ||
108 | struct pci_target_address_conversion *target; | ||
109 | struct pci_mailbox_address *mailbox; | ||
110 | struct pci_target_address_window *window; | ||
111 | unsigned long vtclock, pci_clock_max; | ||
112 | uint32_t val; | ||
113 | |||
114 | setup = &vr41xx_pci_controller_unit_setup; | ||
115 | |||
116 | /* Disable PCI interrupt */ | ||
117 | vr41xx_disable_pciint(); | ||
118 | |||
119 | /* Supply VTClock to PCIU */ | ||
120 | vr41xx_supply_clock(PCIU_CLOCK); | ||
121 | |||
122 | /* Dummy write, waiting for supply of VTClock. */ | ||
123 | vr41xx_disable_pciint(); | ||
124 | |||
125 | /* Select PCI clock */ | ||
126 | if (setup->pci_clock_max != 0) | ||
127 | pci_clock_max = setup->pci_clock_max; | ||
128 | else | ||
129 | pci_clock_max = PCI_CLOCK_MAX; | ||
130 | vtclock = vr41xx_get_vtclock_frequency(); | ||
131 | if (vtclock < pci_clock_max) | ||
132 | writel(EQUAL_VTCLOCK, PCICLKSELREG); | ||
133 | else if ((vtclock / 2) < pci_clock_max) | ||
134 | writel(HALF_VTCLOCK, PCICLKSELREG); | ||
135 | else if (current_cpu_data.processor_id >= PRID_VR4131_REV2_1 && | ||
136 | (vtclock / 3) < pci_clock_max) | ||
137 | writel(ONE_THIRD_VTCLOCK, PCICLKSELREG); | ||
138 | else if ((vtclock / 4) < pci_clock_max) | ||
139 | writel(QUARTER_VTCLOCK, PCICLKSELREG); | ||
140 | else { | ||
141 | printk(KERN_ERR "PCI Clock is over 33MHz.\n"); | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | |||
145 | /* Supply PCI clock by PCI bus */ | ||
146 | vr41xx_supply_clock(PCI_CLOCK); | ||
147 | |||
148 | if (setup->master_memory1 != NULL) { | ||
149 | master = setup->master_memory1; | ||
150 | val = IBA(master->bus_base_address) | | ||
151 | MASTER_MSK(master->address_mask) | | ||
152 | WINEN | | ||
153 | PCIA(master->pci_base_address); | ||
154 | writel(val, PCIMMAW1REG); | ||
155 | } else { | ||
156 | val = readl(PCIMMAW1REG); | ||
157 | val &= ~WINEN; | ||
158 | writel(val, PCIMMAW1REG); | ||
159 | } | ||
160 | |||
161 | if (setup->master_memory2 != NULL) { | ||
162 | master = setup->master_memory2; | ||
163 | val = IBA(master->bus_base_address) | | ||
164 | MASTER_MSK(master->address_mask) | | ||
165 | WINEN | | ||
166 | PCIA(master->pci_base_address); | ||
167 | writel(val, PCIMMAW2REG); | ||
168 | } else { | ||
169 | val = readl(PCIMMAW2REG); | ||
170 | val &= ~WINEN; | ||
171 | writel(val, PCIMMAW2REG); | ||
172 | } | ||
173 | |||
174 | if (setup->target_memory1 != NULL) { | ||
175 | target = setup->target_memory1; | ||
176 | val = TARGET_MSK(target->address_mask) | | ||
177 | WINEN | | ||
178 | ITA(target->bus_base_address); | ||
179 | writel(val, PCITAW1REG); | ||
180 | } else { | ||
181 | val = readl(PCITAW1REG); | ||
182 | val &= ~WINEN; | ||
183 | writel(val, PCITAW1REG); | ||
184 | } | ||
185 | |||
186 | if (setup->target_memory2 != NULL) { | ||
187 | target = setup->target_memory2; | ||
188 | val = TARGET_MSK(target->address_mask) | | ||
189 | WINEN | | ||
190 | ITA(target->bus_base_address); | ||
191 | writel(val, PCITAW2REG); | ||
192 | } else { | ||
193 | val = readl(PCITAW2REG); | ||
194 | val &= ~WINEN; | ||
195 | writel(val, PCITAW2REG); | ||
196 | } | ||
197 | |||
198 | if (setup->master_io != NULL) { | ||
199 | master = setup->master_io; | ||
200 | val = IBA(master->bus_base_address) | | ||
201 | MASTER_MSK(master->address_mask) | | ||
202 | WINEN | | ||
203 | PCIIA(master->pci_base_address); | ||
204 | writel(val, PCIMIOAWREG); | ||
205 | } else { | ||
206 | val = readl(PCIMIOAWREG); | ||
207 | val &= ~WINEN; | ||
208 | writel(val, PCIMIOAWREG); | ||
209 | } | ||
210 | |||
211 | if (setup->exclusive_access == CANNOT_LOCK_FROM_DEVICE) | ||
212 | writel(UNLOCK, PCIEXACCREG); | ||
213 | else | ||
214 | writel(0, PCIEXACCREG); | ||
215 | |||
216 | if (current_cpu_data.cputype == CPU_VR4122) | ||
217 | writel(TRDYV(setup->wait_time_limit_from_irdy_to_trdy), PCITRDYVREG); | ||
218 | |||
219 | writel(MLTIM(setup->master_latency_timer), LATTIMEREG); | ||
220 | |||
221 | if (setup->mailbox != NULL) { | ||
222 | mailbox = setup->mailbox; | ||
223 | val = MBADD(mailbox->base_address) | TYPE_32BITSPACE | | ||
224 | MSI_MEMORY | PREF_APPROVAL; | ||
225 | writel(val, MAILBAREG); | ||
226 | } | ||
227 | |||
228 | if (setup->target_window1) { | ||
229 | window = setup->target_window1; | ||
230 | val = PMBA(window->base_address) | TYPE_32BITSPACE | | ||
231 | MSI_MEMORY | PREF_APPROVAL; | ||
232 | writel(val, PCIMBA1REG); | ||
233 | } | ||
234 | |||
235 | if (setup->target_window2) { | ||
236 | window = setup->target_window2; | ||
237 | val = PMBA(window->base_address) | TYPE_32BITSPACE | | ||
238 | MSI_MEMORY | PREF_APPROVAL; | ||
239 | writel(val, PCIMBA2REG); | ||
240 | } | ||
241 | |||
242 | val = readl(RETVALREG); | ||
243 | val &= ~RTYVAL_MASK; | ||
244 | val |= RTYVAL(setup->retry_limit); | ||
245 | writel(val, RETVALREG); | ||
246 | |||
247 | val = readl(PCIAPCNTREG); | ||
248 | val &= ~(TKYGNT | PAPC); | ||
249 | |||
250 | switch (setup->arbiter_priority_control) { | ||
251 | case PCI_ARBITRATION_MODE_ALTERNATE_0: | ||
252 | val |= PAPC_ALTERNATE_0; | ||
253 | break; | ||
254 | case PCI_ARBITRATION_MODE_ALTERNATE_B: | ||
255 | val |= PAPC_ALTERNATE_B; | ||
256 | break; | ||
257 | default: | ||
258 | val |= PAPC_FAIR; | ||
259 | break; | ||
260 | } | ||
261 | |||
262 | if (setup->take_away_gnt_mode == PCI_TAKE_AWAY_GNT_ENABLE) | ||
263 | val |= TKYGNT_ENABLE; | ||
264 | |||
265 | writel(val, PCIAPCNTREG); | ||
266 | |||
267 | writel(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | ||
268 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR, COMMANDREG); | ||
269 | |||
270 | /* Clear bus error */ | ||
271 | readl(BUSERRADREG); | ||
272 | |||
273 | writel(BLOODY_CONFIG_DONE, PCIENREG); | ||
274 | |||
275 | if (setup->mem_resource != NULL) | ||
276 | vr41xx_pci_controller.mem_resource = setup->mem_resource; | ||
277 | |||
278 | if (setup->io_resource != NULL) { | ||
279 | vr41xx_pci_controller.io_resource = setup->io_resource; | ||
280 | } else { | ||
281 | set_io_port_base(IO_PORT_BASE); | ||
282 | ioport_resource.start = IO_PORT_RESOURCE_START; | ||
283 | ioport_resource.end = IO_PORT_RESOURCE_END; | ||
284 | } | ||
285 | |||
286 | register_pci_controller(&vr41xx_pci_controller); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | arch_initcall(vr41xx_pciu_init); | ||
diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h new file mode 100644 index 000000000000..23815c8b903c --- /dev/null +++ b/arch/mips/pci/pci-vr41xx.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series. | ||
3 | * | ||
4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | ||
6 | * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #ifndef __PCI_VR41XX_H | ||
23 | #define __PCI_VR41XX_H | ||
24 | |||
25 | #define PCIMMAW1REG KSEG1ADDR(0x0f000c00) | ||
26 | #define PCIMMAW2REG KSEG1ADDR(0x0f000c04) | ||
27 | #define PCITAW1REG KSEG1ADDR(0x0f000c08) | ||
28 | #define PCITAW2REG KSEG1ADDR(0x0f000c0c) | ||
29 | #define PCIMIOAWREG KSEG1ADDR(0x0f000c10) | ||
30 | #define IBA(addr) ((addr) & 0xff000000U) | ||
31 | #define MASTER_MSK(mask) (((mask) >> 11) & 0x000fe000U) | ||
32 | #define PCIA(addr) (((addr) >> 24) & 0x000000ffU) | ||
33 | #define TARGET_MSK(mask) (((mask) >> 8) & 0x000fe000U) | ||
34 | #define ITA(addr) (((addr) >> 24) & 0x000000ffU) | ||
35 | #define PCIIA(addr) (((addr) >> 24) & 0x000000ffU) | ||
36 | #define WINEN 0x1000U | ||
37 | #define PCICONFDREG KSEG1ADDR(0x0f000c14) | ||
38 | #define PCICONFAREG KSEG1ADDR(0x0f000c18) | ||
39 | #define PCIMAILREG KSEG1ADDR(0x0f000c1c) | ||
40 | #define BUSERRADREG KSEG1ADDR(0x0f000c24) | ||
41 | #define EA(reg) ((reg) &0xfffffffc) | ||
42 | |||
43 | #define INTCNTSTAREG KSEG1ADDR(0x0f000c28) | ||
44 | #define MABTCLR 0x80000000U | ||
45 | #define TRDYCLR 0x40000000U | ||
46 | #define PARCLR 0x20000000U | ||
47 | #define MBCLR 0x10000000U | ||
48 | #define SERRCLR 0x08000000U | ||
49 | #define RTYCLR 0x04000000U | ||
50 | #define MABCLR 0x02000000U | ||
51 | #define TABCLR 0x01000000U | ||
52 | /* RFU */ | ||
53 | #define MABTMSK 0x00008000U | ||
54 | #define TRDYMSK 0x00004000U | ||
55 | #define PARMSK 0x00002000U | ||
56 | #define MBMSK 0x00001000U | ||
57 | #define SERRMSK 0x00000800U | ||
58 | #define RTYMSK 0x00000400U | ||
59 | #define MABMSK 0x00000200U | ||
60 | #define TABMSK 0x00000100U | ||
61 | #define IBAMABT 0x00000080U | ||
62 | #define TRDYRCH 0x00000040U | ||
63 | #define PAR 0x00000020U | ||
64 | #define MB 0x00000010U | ||
65 | #define PCISERR 0x00000008U | ||
66 | #define RTYRCH 0x00000004U | ||
67 | #define MABORT 0x00000002U | ||
68 | #define TABORT 0x00000001U | ||
69 | |||
70 | #define PCIEXACCREG KSEG1ADDR(0x0f000c2c) | ||
71 | #define UNLOCK 0x2U | ||
72 | #define EAREQ 0x1U | ||
73 | #define PCIRECONTREG KSEG1ADDR(0x0f000c30) | ||
74 | #define RTRYCNT(reg) ((reg) & 0x000000ffU) | ||
75 | #define PCIENREG KSEG1ADDR(0x0f000c34) | ||
76 | #define BLOODY_CONFIG_DONE 0x4U | ||
77 | #define PCICLKSELREG KSEG1ADDR(0x0f000c38) | ||
78 | #define EQUAL_VTCLOCK 0x2U | ||
79 | #define HALF_VTCLOCK 0x0U | ||
80 | #define ONE_THIRD_VTCLOCK 0x3U | ||
81 | #define QUARTER_VTCLOCK 0x1U | ||
82 | #define PCITRDYVREG KSEG1ADDR(0x0f000c3c) | ||
83 | #define TRDYV(val) ((uint32_t)(val) & 0xffU) | ||
84 | #define PCICLKRUNREG KSEG1ADDR(0x0f000c60) | ||
85 | |||
86 | #define VENDORIDREG KSEG1ADDR(0x0f000d00) | ||
87 | #define DEVICEIDREG KSEG1ADDR(0x0f000d00) | ||
88 | #define COMMANDREG KSEG1ADDR(0x0f000d04) | ||
89 | #define STATUSREG KSEG1ADDR(0x0f000d04) | ||
90 | #define REVIDREG KSEG1ADDR(0x0f000d08) | ||
91 | #define CLASSREG KSEG1ADDR(0x0f000d08) | ||
92 | #define CACHELSREG KSEG1ADDR(0x0f000d0c) | ||
93 | #define LATTIMEREG KSEG1ADDR(0x0f000d0c) | ||
94 | #define MLTIM(val) (((uint32_t)(val) << 7) & 0xff00U) | ||
95 | #define MAILBAREG KSEG1ADDR(0x0f000d10) | ||
96 | #define PCIMBA1REG KSEG1ADDR(0x0f000d14) | ||
97 | #define PCIMBA2REG KSEG1ADDR(0x0f000d18) | ||
98 | #define MBADD(base) ((base) & 0xfffff800U) | ||
99 | #define PMBA(base) ((base) & 0xffe00000U) | ||
100 | #define PREF 0x8U | ||
101 | #define PREF_APPROVAL 0x8U | ||
102 | #define PREF_DISAPPROVAL 0x0U | ||
103 | #define TYPE 0x6U | ||
104 | #define TYPE_32BITSPACE 0x0U | ||
105 | #define MSI 0x1U | ||
106 | #define MSI_MEMORY 0x0U | ||
107 | #define INTLINEREG KSEG1ADDR(0x0f000d3c) | ||
108 | #define INTPINREG KSEG1ADDR(0x0f000d3c) | ||
109 | #define RETVALREG KSEG1ADDR(0x0f000d40) | ||
110 | #define PCIAPCNTREG KSEG1ADDR(0x0f000d40) | ||
111 | #define TKYGNT 0x04000000U | ||
112 | #define TKYGNT_ENABLE 0x04000000U | ||
113 | #define TKYGNT_DISABLE 0x00000000U | ||
114 | #define PAPC 0x03000000U | ||
115 | #define PAPC_ALTERNATE_B 0x02000000U | ||
116 | #define PAPC_ALTERNATE_0 0x01000000U | ||
117 | #define PAPC_FAIR 0x00000000U | ||
118 | #define RTYVAL(val) (((uint32_t)(val) << 7) & 0xff00U) | ||
119 | #define RTYVAL_MASK 0xff00U | ||
120 | |||
121 | #define PCI_CLOCK_MAX 33333333U | ||
122 | |||
123 | /* | ||
124 | * Default setup | ||
125 | */ | ||
126 | #define PCI_MASTER_MEM1_BUS_BASE_ADDRESS 0x10000000U | ||
127 | #define PCI_MASTER_MEM1_ADDRESS_MASK 0x7c000000U | ||
128 | #define PCI_MASTER_MEM1_PCI_BASE_ADDRESS 0x10000000U | ||
129 | |||
130 | #define PCI_TARGET_MEM1_ADDRESS_MASK 0x08000000U | ||
131 | #define PCI_TARGET_MEM1_BUS_BASE_ADDRESS 0x00000000U | ||
132 | |||
133 | #define PCI_MASTER_IO_BUS_BASE_ADDRESS 0x16000000U | ||
134 | #define PCI_MASTER_IO_ADDRESS_MASK 0x7e000000U | ||
135 | #define PCI_MASTER_IO_PCI_BASE_ADDRESS 0x00000000U | ||
136 | |||
137 | #define PCI_MAILBOX_BASE_ADDRESS 0x00000000U | ||
138 | |||
139 | #define PCI_TARGET_WINDOW1_BASE_ADDRESS 0x00000000U | ||
140 | |||
141 | #define IO_PORT_BASE KSEG1ADDR(PCI_MASTER_IO_BUS_BASE_ADDRESS) | ||
142 | #define IO_PORT_RESOURCE_START PCI_MASTER_IO_PCI_BASE_ADDRESS | ||
143 | #define IO_PORT_RESOURCE_END (~PCI_MASTER_IO_ADDRESS_MASK & PCI_MASTER_ADDRESS_MASK) | ||
144 | |||
145 | #define PCI_IO_RESOURCE_START 0x01000000UL | ||
146 | #define PCI_IO_RESOURCE_END 0x01ffffffUL | ||
147 | |||
148 | #define PCI_MEM_RESOURCE_START 0x11000000UL | ||
149 | #define PCI_MEM_RESOURCE_END 0x13ffffffUL | ||
150 | |||
151 | #endif /* __PCI_VR41XX_H */ | ||
diff --git a/arch/mips/pci/pci-yosemite.c b/arch/mips/pci/pci-yosemite.c new file mode 100644 index 000000000000..dac9ed4b0ccf --- /dev/null +++ b/arch/mips/pci/pci-yosemite.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
7 | */ | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <asm/titan_dep.h> | ||
13 | |||
14 | extern struct pci_ops titan_pci_ops; | ||
15 | |||
16 | static struct resource py_mem_resource = { | ||
17 | "Titan PCI MEM", 0xe0000000UL, 0xe3ffffffUL, IORESOURCE_MEM | ||
18 | }; | ||
19 | |||
20 | /* | ||
21 | * PMON really reserves 16MB of I/O port space but that's stupid, nothing | ||
22 | * needs that much since allocations are limited to 256 bytes per device | ||
23 | * anyway. So we just claim 64kB here. | ||
24 | */ | ||
25 | #define TITAN_IO_SIZE 0x0000ffffUL | ||
26 | #define TITAN_IO_BASE 0xe8000000UL | ||
27 | |||
28 | static struct resource py_io_resource = { | ||
29 | "Titan IO MEM", 0x00001000UL, TITAN_IO_SIZE - 1, IORESOURCE_IO, | ||
30 | }; | ||
31 | |||
32 | static struct pci_controller py_controller = { | ||
33 | .pci_ops = &titan_pci_ops, | ||
34 | .mem_resource = &py_mem_resource, | ||
35 | .mem_offset = 0x00000000UL, | ||
36 | .io_resource = &py_io_resource, | ||
37 | .io_offset = 0x00000000UL | ||
38 | }; | ||
39 | |||
40 | static char ioremap_failed[] __initdata = "Could not ioremap I/O port range"; | ||
41 | |||
42 | static int __init pmc_yosemite_setup(void) | ||
43 | { | ||
44 | unsigned long io_v_base; | ||
45 | |||
46 | io_v_base = (unsigned long) ioremap(TITAN_IO_BASE, TITAN_IO_SIZE); | ||
47 | if (!io_v_base) | ||
48 | panic(ioremap_failed); | ||
49 | |||
50 | set_io_port_base(io_v_base); | ||
51 | TITAN_WRITE(RM9000x2_OCD_LKM7, TITAN_READ(RM9000x2_OCD_LKM7) | 1); | ||
52 | |||
53 | ioport_resource.end = TITAN_IO_SIZE - 1; | ||
54 | |||
55 | register_pci_controller(&py_controller); | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | arch_initcall(pmc_yosemite_setup); | ||
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c new file mode 100644 index 000000000000..8141dffac241 --- /dev/null +++ b/arch/mips/pci/pci.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2 of the License, or (at your | ||
5 | * option) any later version. | ||
6 | * | ||
7 | * Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org) | ||
8 | */ | ||
9 | #include <linux/config.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/bootmem.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/pci.h> | ||
16 | |||
17 | /* | ||
18 | * Indicate whether we respect the PCI setup left by the firmware. | ||
19 | * | ||
20 | * Make this long-lived so that we know when shutting down | ||
21 | * whether we probed only or not. | ||
22 | */ | ||
23 | int pci_probe_only; | ||
24 | |||
25 | #define PCI_ASSIGN_ALL_BUSSES 1 | ||
26 | |||
27 | unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES; | ||
28 | |||
29 | /* | ||
30 | * The PCI controller list. | ||
31 | */ | ||
32 | |||
33 | struct pci_controller *hose_head, **hose_tail = &hose_head; | ||
34 | struct pci_controller *pci_isa_hose; | ||
35 | |||
36 | unsigned long PCIBIOS_MIN_IO = 0x0000; | ||
37 | unsigned long PCIBIOS_MIN_MEM = 0; | ||
38 | |||
39 | /* | ||
40 | * We need to avoid collisions with `mirrored' VGA ports | ||
41 | * and other strange ISA hardware, so we always want the | ||
42 | * addresses to be allocated in the 0x000-0x0ff region | ||
43 | * modulo 0x400. | ||
44 | * | ||
45 | * Why? Because some silly external IO cards only decode | ||
46 | * the low 10 bits of the IO address. The 0x00-0xff region | ||
47 | * is reserved for motherboard devices that decode all 16 | ||
48 | * bits, so it's ok to allocate at, say, 0x2800-0x28ff, | ||
49 | * but we want to try to avoid allocating at 0x2900-0x2bff | ||
50 | * which might have be mirrored at 0x0100-0x03ff.. | ||
51 | */ | ||
52 | void | ||
53 | pcibios_align_resource(void *data, struct resource *res, | ||
54 | unsigned long size, unsigned long align) | ||
55 | { | ||
56 | struct pci_dev *dev = data; | ||
57 | struct pci_controller *hose = dev->sysdata; | ||
58 | unsigned long start = res->start; | ||
59 | |||
60 | if (res->flags & IORESOURCE_IO) { | ||
61 | /* Make sure we start at our min on all hoses */ | ||
62 | if (start < PCIBIOS_MIN_IO + hose->io_resource->start) | ||
63 | start = PCIBIOS_MIN_IO + hose->io_resource->start; | ||
64 | |||
65 | /* | ||
66 | * Put everything into 0x00-0xff region modulo 0x400 | ||
67 | */ | ||
68 | if (start & 0x300) | ||
69 | start = (start + 0x3ff) & ~0x3ff; | ||
70 | } else if (res->flags & IORESOURCE_MEM) { | ||
71 | /* Make sure we start at our min on all hoses */ | ||
72 | if (start < PCIBIOS_MIN_MEM + hose->mem_resource->start) | ||
73 | start = PCIBIOS_MIN_MEM + hose->mem_resource->start; | ||
74 | } | ||
75 | |||
76 | res->start = start; | ||
77 | } | ||
78 | |||
79 | struct pci_controller * __init alloc_pci_controller(void) | ||
80 | { | ||
81 | return alloc_bootmem(sizeof(struct pci_controller)); | ||
82 | } | ||
83 | |||
84 | void __init register_pci_controller(struct pci_controller *hose) | ||
85 | { | ||
86 | *hose_tail = hose; | ||
87 | hose_tail = &hose->next; | ||
88 | } | ||
89 | |||
90 | /* Most MIPS systems have straight-forward swizzling needs. */ | ||
91 | |||
92 | static inline u8 bridge_swizzle(u8 pin, u8 slot) | ||
93 | { | ||
94 | return (((pin - 1) + slot) % 4) + 1; | ||
95 | } | ||
96 | |||
97 | static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp) | ||
98 | { | ||
99 | u8 pin = *pinp; | ||
100 | |||
101 | while (dev->bus->parent) { | ||
102 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); | ||
103 | /* Move up the chain of bridges. */ | ||
104 | dev = dev->bus->self; | ||
105 | } | ||
106 | *pinp = pin; | ||
107 | |||
108 | /* The slot is the slot of the last bridge. */ | ||
109 | return PCI_SLOT(dev->devfn); | ||
110 | } | ||
111 | |||
112 | static int __init pcibios_init(void) | ||
113 | { | ||
114 | struct pci_controller *hose; | ||
115 | struct pci_bus *bus; | ||
116 | int next_busno; | ||
117 | int need_domain_info = 0; | ||
118 | |||
119 | /* Scan all of the recorded PCI controllers. */ | ||
120 | for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { | ||
121 | |||
122 | if (request_resource(&iomem_resource, hose->mem_resource) < 0) | ||
123 | goto out; | ||
124 | if (request_resource(&ioport_resource, hose->io_resource) < 0) | ||
125 | goto out_free_mem_resource; | ||
126 | |||
127 | if (!hose->iommu) | ||
128 | PCI_DMA_BUS_IS_PHYS = 1; | ||
129 | |||
130 | bus = pci_scan_bus(next_busno, hose->pci_ops, hose); | ||
131 | hose->bus = bus; | ||
132 | hose->need_domain_info = need_domain_info; | ||
133 | next_busno = bus->subordinate + 1; | ||
134 | /* Don't allow 8-bit bus number overflow inside the hose - | ||
135 | reserve some space for bridges. */ | ||
136 | if (next_busno > 224) { | ||
137 | next_busno = 0; | ||
138 | need_domain_info = 1; | ||
139 | } | ||
140 | continue; | ||
141 | |||
142 | out_free_mem_resource: | ||
143 | release_resource(hose->mem_resource); | ||
144 | |||
145 | out: | ||
146 | printk(KERN_WARNING | ||
147 | "Skipping PCI bus scan due to resource conflict\n"); | ||
148 | } | ||
149 | |||
150 | if (!pci_probe_only) | ||
151 | pci_assign_unassigned_resources(); | ||
152 | pci_fixup_irqs(common_swizzle, pcibios_map_irq); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | subsys_initcall(pcibios_init); | ||
158 | |||
159 | static int pcibios_enable_resources(struct pci_dev *dev, int mask) | ||
160 | { | ||
161 | u16 cmd, old_cmd; | ||
162 | int idx; | ||
163 | struct resource *r; | ||
164 | |||
165 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
166 | old_cmd = cmd; | ||
167 | for(idx=0; idx<6; idx++) { | ||
168 | /* Only set up the requested stuff */ | ||
169 | if (!(mask & (1<<idx))) | ||
170 | continue; | ||
171 | |||
172 | r = &dev->resource[idx]; | ||
173 | if (!r->start && r->end) { | ||
174 | printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | if (r->flags & IORESOURCE_IO) | ||
178 | cmd |= PCI_COMMAND_IO; | ||
179 | if (r->flags & IORESOURCE_MEM) | ||
180 | cmd |= PCI_COMMAND_MEMORY; | ||
181 | } | ||
182 | if (dev->resource[PCI_ROM_RESOURCE].start) | ||
183 | cmd |= PCI_COMMAND_MEMORY; | ||
184 | if (cmd != old_cmd) { | ||
185 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | ||
186 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
187 | } | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * If we set up a device for bus mastering, we need to check the latency | ||
193 | * timer as certain crappy BIOSes forget to set it properly. | ||
194 | */ | ||
195 | unsigned int pcibios_max_latency = 255; | ||
196 | |||
197 | void pcibios_set_master(struct pci_dev *dev) | ||
198 | { | ||
199 | u8 lat; | ||
200 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | ||
201 | if (lat < 16) | ||
202 | lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; | ||
203 | else if (lat > pcibios_max_latency) | ||
204 | lat = pcibios_max_latency; | ||
205 | else | ||
206 | return; | ||
207 | printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", | ||
208 | pci_name(dev), lat); | ||
209 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | ||
210 | } | ||
211 | |||
212 | unsigned int pcibios_assign_all_busses(void) | ||
213 | { | ||
214 | return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; | ||
215 | } | ||
216 | |||
217 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
218 | { | ||
219 | int err; | ||
220 | |||
221 | if ((err = pcibios_enable_resources(dev, mask)) < 0) | ||
222 | return err; | ||
223 | |||
224 | return pcibios_plat_dev_init(dev); | ||
225 | } | ||
226 | |||
227 | static void __init pcibios_fixup_device_resources(struct pci_dev *dev, | ||
228 | struct pci_bus *bus) | ||
229 | { | ||
230 | /* Update device resources. */ | ||
231 | struct pci_controller *hose = (struct pci_controller *)bus->sysdata; | ||
232 | unsigned long offset = 0; | ||
233 | int i; | ||
234 | |||
235 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
236 | if (!dev->resource[i].start) | ||
237 | continue; | ||
238 | if (dev->resource[i].flags & IORESOURCE_IO) | ||
239 | offset = hose->io_offset; | ||
240 | else if (dev->resource[i].flags & IORESOURCE_MEM) | ||
241 | offset = hose->mem_offset; | ||
242 | |||
243 | dev->resource[i].start += offset; | ||
244 | dev->resource[i].end += offset; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||
249 | { | ||
250 | /* Propagate hose info into the subordinate devices. */ | ||
251 | |||
252 | struct pci_controller *hose = bus->sysdata; | ||
253 | struct list_head *ln; | ||
254 | struct pci_dev *dev = bus->self; | ||
255 | |||
256 | if (!dev) { | ||
257 | bus->resource[0] = hose->io_resource; | ||
258 | bus->resource[1] = hose->mem_resource; | ||
259 | } else if (pci_probe_only && | ||
260 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
261 | pci_read_bridge_bases(bus); | ||
262 | pcibios_fixup_device_resources(dev, bus); | ||
263 | } | ||
264 | |||
265 | for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { | ||
266 | struct pci_dev *dev = pci_dev_b(ln); | ||
267 | |||
268 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
269 | pcibios_fixup_device_resources(dev, bus); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | void __init | ||
274 | pcibios_update_irq(struct pci_dev *dev, int irq) | ||
275 | { | ||
276 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
277 | } | ||
278 | |||
279 | void __devinit | ||
280 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
281 | struct resource *res) | ||
282 | { | ||
283 | struct pci_controller *hose = (struct pci_controller *)dev->sysdata; | ||
284 | unsigned long offset = 0; | ||
285 | |||
286 | if (res->flags & IORESOURCE_IO) | ||
287 | offset = hose->io_offset; | ||
288 | else if (res->flags & IORESOURCE_MEM) | ||
289 | offset = hose->mem_offset; | ||
290 | |||
291 | region->start = res->start - offset; | ||
292 | region->end = res->end - offset; | ||
293 | } | ||
294 | |||
295 | #ifdef CONFIG_HOTPLUG | ||
296 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
297 | EXPORT_SYMBOL(PCIBIOS_MIN_IO); | ||
298 | EXPORT_SYMBOL(PCIBIOS_MIN_MEM); | ||
299 | #endif | ||
300 | |||
301 | char *pcibios_setup(char *str) | ||
302 | { | ||
303 | return str; | ||
304 | } | ||