diff options
Diffstat (limited to 'arch/mips/pci/ops-gt64111.c')
-rw-r--r-- | arch/mips/pci/ops-gt64111.c | 100 |
1 files changed, 100 insertions, 0 deletions
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 | }; | ||