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 #include <linux/init.h>
22
23 #include <asm/mips-boards/msc01_pci.h>
24
25 #define PCI_ACCESS_READ 0
26 #define PCI_ACCESS_WRITE 1
27
28 /*
29 * PCI configuration cycle AD bus definition
30 */
31 /* Type 0 */
32 #define PCI_CFG_TYPE0_REG_SHF 0
33 #define PCI_CFG_TYPE0_FUNC_SHF 8
34
35 /* Type 1 */
36 #define PCI_CFG_TYPE1_REG_SHF 0
37 #define PCI_CFG_TYPE1_FUNC_SHF 8
38 #define PCI_CFG_TYPE1_DEV_SHF 11
39 #define PCI_CFG_TYPE1_BUS_SHF 16
40
msc_config_access(unsigned char access_type,struct pci_dev * dev,unsigned char where,u32 * data)41 static int msc_config_access(unsigned char access_type,
42 struct pci_dev *dev, unsigned char where, u32 *data)
43 {
44 unsigned char bus = dev->bus->number;
45 unsigned char dev_fn = dev->devfn;
46 unsigned char type;
47 u32 intr, dummy;
48 u64 pci_addr;
49
50 if ((bus == 0) && (PCI_SLOT(dev_fn) == 0))
51 return -1;
52
53 /* Clear status register bits. */
54 MSC_WRITE(MSC01_PCI_INTSTAT,
55 (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
56
57 /* Setup address */
58 if (bus == 0)
59 type = 0; /* Type 0 */
60 else
61 type = 1; /* Type 1 */
62
63 MSC_WRITE(MSC01_PCI_CFGADDR,
64 ((bus << MSC01_PCI_CFGADDR_BNUM_SHF) |
65 (PCI_SLOT(dev_fn) << MSC01_PCI_CFGADDR_DNUM_SHF) |
66 (PCI_FUNC(dev_fn) << MSC01_PCI_CFGADDR_FNUM_SHF) |
67 ((where /4 ) << MSC01_PCI_CFGADDR_RNUM_SHF) |
68 (type)));
69
70 /* Perform access */
71 if (access_type == PCI_ACCESS_WRITE) {
72 MSC_WRITE(MSC01_PCI_CFGDATA, *data);
73 } else {
74 MSC_READ(MSC01_PCI_CFGDATA, *data);
75 }
76
77 /* Detect Master/Target abort */
78 MSC_READ(MSC01_PCI_INTSTAT, intr);
79 if (intr & (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)) {
80 /* Error occurred */
81
82 /* Clear bits */
83 MSC_READ(MSC01_PCI_INTSTAT, intr);
84 MSC_WRITE(MSC01_PCI_INTSTAT,
85 (MSC01_PCI_INTCFG_MA_BIT |
86 MSC01_PCI_INTCFG_TA_BIT));
87
88 return -1;
89 }
90
91 return 0;
92 }
93
94
95 /*
96 * We can't address 8 and 16 bit words directly. Instead we have to
97 * read/write a 32bit word and mask/modify the data we actually want.
98 */
msc_read_config_byte(struct pci_dev * dev,int where,u8 * val)99 static int msc_read_config_byte (struct pci_dev *dev, int where,
100 u8 *val)
101 {
102 u32 data = 0;
103
104 if (msc_config_access(PCI_ACCESS_READ, dev, where, &data))
105 return -1;
106
107 *val = (data >> ((where & 3) << 3)) & 0xff;
108
109 return PCIBIOS_SUCCESSFUL;
110 }
111
msc_read_config_word(struct pci_dev * dev,int where,u16 * val)112 static int msc_read_config_word (struct pci_dev *dev, int where,
113 u16 *val)
114 {
115 u32 data = 0;
116
117 if (where & 1)
118 return PCIBIOS_BAD_REGISTER_NUMBER;
119
120 if (msc_config_access(PCI_ACCESS_READ, dev, where, &data))
121 return -1;
122
123 *val = (data >> ((where & 3) << 3)) & 0xffff;
124
125 return PCIBIOS_SUCCESSFUL;
126 }
127
msc_read_config_dword(struct pci_dev * dev,int where,u32 * val)128 static int msc_read_config_dword (struct pci_dev *dev, int where,
129 u32 *val)
130 {
131 u32 data = 0;
132
133 if (where & 3)
134 return PCIBIOS_BAD_REGISTER_NUMBER;
135
136 if (msc_config_access(PCI_ACCESS_READ, dev, where, &data))
137 return -1;
138
139 *val = data;
140
141 return PCIBIOS_SUCCESSFUL;
142 }
143
msc_write_config_byte(struct pci_dev * dev,int where,u8 val)144 static int msc_write_config_byte (struct pci_dev *dev, int where,
145 u8 val)
146 {
147 u32 data = 0;
148
149 if (msc_config_access(PCI_ACCESS_READ, dev, where, &data))
150 return -1;
151
152 data = (data & ~(0xff << ((where & 3) << 3))) |
153 (val << ((where & 3) << 3));
154
155 if (msc_config_access(PCI_ACCESS_WRITE, dev, where, &data))
156 return -1;
157
158 return PCIBIOS_SUCCESSFUL;
159 }
160
msc_write_config_word(struct pci_dev * dev,int where,u16 val)161 static int msc_write_config_word (struct pci_dev *dev, int where,
162 u16 val)
163 {
164 u32 data = 0;
165
166 if (where & 1)
167 return PCIBIOS_BAD_REGISTER_NUMBER;
168
169 if (msc_config_access(PCI_ACCESS_READ, dev, where, &data))
170 return -1;
171
172 data = (data & ~(0xffff << ((where & 3) << 3))) |
173 (val << ((where & 3) << 3));
174
175 if (msc_config_access(PCI_ACCESS_WRITE, dev, where, &data))
176 return -1;
177
178
179 return PCIBIOS_SUCCESSFUL;
180 }
181
msc_write_config_dword(struct pci_dev * dev,int where,u32 val)182 static int msc_write_config_dword(struct pci_dev *dev, int where,
183 u32 val)
184 {
185 if (where & 3)
186 return PCIBIOS_BAD_REGISTER_NUMBER;
187
188 if (msc_config_access(PCI_ACCESS_WRITE, dev, where, &val))
189 return -1;
190
191 return PCIBIOS_SUCCESSFUL;
192 }
193
194 struct pci_ops msc_pci_ops = {
195 msc_read_config_byte,
196 msc_read_config_word,
197 msc_read_config_dword,
198 msc_write_config_byte,
199 msc_write_config_word,
200 msc_write_config_dword
201 };
202