]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * | |
3 | * (C) Copyright 2000 | |
4 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
5 | * | |
6 | * (C) Copyright 2001 | |
7 | * James Dougherty (jfd@cs.stanford.edu) | |
8 | * | |
9 | * See file CREDITS for list of people who contributed to this | |
10 | * project. | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of | |
15 | * the License, or (at your option) any later version. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; if not, write to the Free Software | |
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
25 | * MA 02111-1307 USA | |
26 | */ | |
27 | ||
28 | /* | |
29 | * PCI Configuration space access support for MPC824x/MPC107 PCI Bridge | |
30 | */ | |
31 | #include <common.h> | |
32 | #include <mpc824x.h> | |
33 | #include <pci.h> | |
34 | ||
35 | #include "mousse.h" | |
36 | ||
37 | /* | |
38 | * Promise ATA/66 support. | |
39 | */ | |
40 | #define XFER_PIO_4 0x0C /* 0000|1100 */ | |
41 | #define XFER_PIO_3 0x0B /* 0000|1011 */ | |
42 | #define XFER_PIO_2 0x0A /* 0000|1010 */ | |
43 | #define XFER_PIO_1 0x09 /* 0000|1001 */ | |
44 | #define XFER_PIO_0 0x08 /* 0000|1000 */ | |
45 | #define XFER_PIO_SLOW 0x00 /* 0000|0000 */ | |
46 | ||
47 | /* Promise Regs */ | |
48 | #define REG_A 0x01 | |
49 | #define REG_B 0x02 | |
50 | #define REG_C 0x04 | |
51 | #define REG_D 0x08 | |
52 | ||
53 | void | |
54 | pdc202xx_decode_registers (unsigned char registers, unsigned char value) | |
55 | { | |
56 | unsigned char bit = 0, bit1 = 0, bit2 = 0; | |
57 | switch(registers) { | |
58 | case REG_A: | |
59 | bit2 = 0; | |
60 | printf(" A Register "); | |
61 | if (value & 0x80) printf("SYNC_IN "); | |
62 | if (value & 0x40) printf("ERRDY_EN "); | |
63 | if (value & 0x20) printf("IORDY_EN "); | |
64 | if (value & 0x10) printf("PREFETCH_EN "); | |
65 | if (value & 0x08) { printf("PA3 ");bit2 |= 0x08; } | |
66 | if (value & 0x04) { printf("PA2 ");bit2 |= 0x04; } | |
67 | if (value & 0x02) { printf("PA1 ");bit2 |= 0x02; } | |
68 | if (value & 0x01) { printf("PA0 ");bit2 |= 0x01; } | |
69 | printf("PIO(A) = %d ", bit2); | |
70 | break; | |
71 | case REG_B: | |
72 | bit1 = 0;bit2 = 0; | |
73 | printf(" B Register "); | |
74 | if (value & 0x80) { printf("MB2 ");bit1 |= 0x80; } | |
75 | if (value & 0x40) { printf("MB1 ");bit1 |= 0x40; } | |
76 | if (value & 0x20) { printf("MB0 ");bit1 |= 0x20; } | |
77 | printf("DMA(B) = %d ", bit1 >> 5); | |
78 | if (value & 0x10) printf("PIO_FORCED/PB4 "); | |
79 | if (value & 0x08) { printf("PB3 ");bit2 |= 0x08; } | |
80 | if (value & 0x04) { printf("PB2 ");bit2 |= 0x04; } | |
81 | if (value & 0x02) { printf("PB1 ");bit2 |= 0x02; } | |
82 | if (value & 0x01) { printf("PB0 ");bit2 |= 0x01; } | |
83 | printf("PIO(B) = %d ", bit2); | |
84 | break; | |
85 | case REG_C: | |
86 | bit2 = 0; | |
87 | printf(" C Register "); | |
88 | if (value & 0x80) printf("DMARQp "); | |
89 | if (value & 0x40) printf("IORDYp "); | |
90 | if (value & 0x20) printf("DMAR_EN "); | |
91 | if (value & 0x10) printf("DMAW_EN "); | |
92 | ||
93 | if (value & 0x08) { printf("MC3 ");bit2 |= 0x08; } | |
94 | if (value & 0x04) { printf("MC2 ");bit2 |= 0x04; } | |
95 | if (value & 0x02) { printf("MC1 ");bit2 |= 0x02; } | |
96 | if (value & 0x01) { printf("MC0 ");bit2 |= 0x01; } | |
97 | printf("DMA(C) = %d ", bit2); | |
98 | break; | |
99 | case REG_D: | |
100 | printf(" D Register "); | |
101 | break; | |
102 | default: | |
103 | return; | |
104 | } | |
105 | printf("\n %s ", (registers & REG_D) ? "DP" : | |
106 | (registers & REG_C) ? "CP" : | |
107 | (registers & REG_B) ? "BP" : | |
108 | (registers & REG_A) ? "AP" : "ERROR"); | |
109 | for (bit=128;bit>0;bit/=2) | |
110 | printf("%s", (value & bit) ? "1" : "0"); | |
111 | printf("\n"); | |
112 | } | |
113 | ||
114 | /* | |
115 | * Promise ATA/66 Support: configure Promise ATA66 card in specified mode. | |
116 | */ | |
117 | int | |
118 | pdc202xx_tune_chipset (pci_dev_t dev, int drive, unsigned char speed) | |
119 | { | |
120 | unsigned short drive_conf; | |
121 | int err = 0; | |
122 | unsigned char drive_pci, AP, BP, CP, DP; | |
123 | unsigned char TA = 0, TB = 0; | |
124 | ||
125 | switch (drive) { | |
126 | case 0: drive_pci = 0x60; break; | |
127 | case 1: drive_pci = 0x64; break; | |
128 | case 2: drive_pci = 0x68; break; | |
129 | case 3: drive_pci = 0x6c; break; | |
130 | default: return -1; | |
131 | } | |
132 | ||
133 | pci_read_config_word(dev, drive_pci, &drive_conf); | |
134 | pci_read_config_byte(dev, (drive_pci), &AP); | |
135 | pci_read_config_byte(dev, (drive_pci)|0x01, &BP); | |
136 | pci_read_config_byte(dev, (drive_pci)|0x02, &CP); | |
137 | pci_read_config_byte(dev, (drive_pci)|0x03, &DP); | |
138 | ||
139 | if ((AP & 0x0F) || (BP & 0x07)) { | |
140 | /* clear PIO modes of lower 8421 bits of A Register */ | |
141 | pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); | |
142 | pci_read_config_byte(dev, (drive_pci), &AP); | |
143 | ||
144 | /* clear PIO modes of lower 421 bits of B Register */ | |
145 | pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); | |
146 | pci_read_config_byte(dev, (drive_pci)|0x01, &BP); | |
147 | ||
148 | pci_read_config_byte(dev, (drive_pci), &AP); | |
149 | pci_read_config_byte(dev, (drive_pci)|0x01, &BP); | |
150 | } | |
151 | ||
152 | pci_read_config_byte(dev, (drive_pci), &AP); | |
153 | pci_read_config_byte(dev, (drive_pci)|0x01, &BP); | |
154 | pci_read_config_byte(dev, (drive_pci)|0x02, &CP); | |
155 | ||
156 | switch(speed) { | |
157 | case XFER_PIO_4: TA = 0x01; TB = 0x04; break; | |
158 | case XFER_PIO_3: TA = 0x02; TB = 0x06; break; | |
159 | case XFER_PIO_2: TA = 0x03; TB = 0x08; break; | |
160 | case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; | |
161 | case XFER_PIO_0: | |
162 | default: TA = 0x09; TB = 0x13; break; | |
163 | } | |
164 | ||
165 | pci_write_config_byte(dev, (drive_pci), AP|TA); | |
166 | pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); | |
167 | ||
168 | pci_read_config_byte(dev, (drive_pci), &AP); | |
169 | pci_read_config_byte(dev, (drive_pci)|0x01, &BP); | |
170 | pci_read_config_byte(dev, (drive_pci)|0x02, &CP); | |
171 | pci_read_config_byte(dev, (drive_pci)|0x03, &DP); | |
172 | ||
173 | ||
174 | #ifdef PDC202XX_DEBUG | |
175 | pdc202xx_decode_registers(REG_A, AP); | |
176 | pdc202xx_decode_registers(REG_B, BP); | |
177 | pdc202xx_decode_registers(REG_C, CP); | |
178 | pdc202xx_decode_registers(REG_D, DP); | |
179 | #endif | |
180 | return err; | |
181 | } | |
182 | /* | |
183 | * Show/Init PCI devices on the specified bus number. | |
184 | */ | |
185 | ||
186 | void pci_mousse_fixup_irq(struct pci_controller *hose, pci_dev_t dev) | |
187 | { | |
188 | unsigned int line; | |
189 | ||
190 | switch(PCI_DEV(dev)) { | |
191 | case 0x0d: | |
192 | line = 0x00000101; | |
193 | break; | |
194 | ||
195 | case 0x0e: | |
196 | default: | |
197 | line = 0x00000303; | |
198 | break; | |
199 | } | |
200 | ||
201 | pci_write_config_dword(dev, PCI_INTERRUPT_LINE, line); | |
202 | } | |
203 | ||
204 | void pci_mousse_setup_pdc202xx(struct pci_controller *hose, pci_dev_t dev, | |
205 | struct pci_config_table *_) | |
206 | { | |
207 | unsigned short vendorId; | |
208 | unsigned int mbar0, cmd; | |
209 | int bar, a; | |
210 | ||
211 | pci_read_config_word(dev, PCI_VENDOR_ID, &vendorId); | |
212 | ||
213 | if(vendorId == PCI_VENDOR_ID_PROMISE || vendorId == PCI_VENDOR_ID_CMD){ | |
214 | /* PDC 202xx card is handled differently, it is a bootable | |
215 | * device and needs all 5 MBAR's configured | |
216 | */ | |
217 | for(bar = 0; bar < 5; bar++){ | |
218 | pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0); | |
219 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, ~0); | |
220 | pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0); | |
221 | #ifdef DEBUG | |
222 | printf(" ATA_bar[%d] = %dbytes\n", bar, | |
223 | ~(mbar0 & PCI_BASE_ADDRESS_MEM_MASK) + 1); | |
224 | #endif | |
225 | } | |
226 | ||
227 | /* Program all BAR's */ | |
228 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PROMISE_MBAR0); | |
229 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, PROMISE_MBAR1); | |
230 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, PROMISE_MBAR2); | |
231 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, PROMISE_MBAR3); | |
232 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, PROMISE_MBAR4); | |
233 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_5, PROMISE_MBAR5); | |
234 | ||
235 | for(bar = 0; bar < 5; bar++){ | |
236 | pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0); | |
237 | #ifdef DEBUG | |
238 | printf(" ATA_bar[%d]@0x%x\n", bar, mbar0); | |
239 | #endif | |
240 | } | |
241 | ||
242 | /* Enable ROM Expansion base */ | |
243 | pci_write_config_dword(dev, PCI_ROM_ADDRESS, PROMISE_MBAR5|1); | |
244 | ||
245 | /* Io enable, Memory enable, master enable */ | |
246 | pci_read_config_dword(dev, PCI_COMMAND, &cmd); | |
247 | cmd &= ~0xffff0000; | |
248 | cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; | |
249 | pci_write_config_dword(dev, PCI_COMMAND, cmd); | |
250 | ||
251 | /* Breath some life into the controller */ | |
252 | for( a = 0; a < 4; a++) | |
253 | pdc202xx_tune_chipset(dev, a, XFER_PIO_0); | |
254 | } | |
255 | } | |
256 | ||
257 | static struct pci_config_table pci_sandpoint_config_table[] = { | |
258 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 0x0e, 0x00, | |
259 | pci_mousse_setup_pdc202xx }, | |
260 | #ifndef CONFIG_PCI_PNP | |
261 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 0x0d, 0x00, | |
262 | pci_cfgfunc_config_device, {PCI_ENET_IOADDR, | |
263 | PCI_ENET_MEMADDR, | |
264 | PCI_COMMAND_MEMORY | | |
265 | PCI_COMMAND_MASTER}}, | |
266 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | |
267 | pci_cfgfunc_config_device, {PCI_SLOT_IOADDR, | |
268 | PCI_SLOT_MEMADDR, | |
269 | PCI_COMMAND_MEMORY | | |
270 | PCI_COMMAND_MASTER}}, | |
271 | #endif | |
272 | { } | |
273 | }; | |
274 | ||
275 | struct pci_controller hose = { | |
276 | config_table: pci_sandpoint_config_table, | |
277 | fixup_irq: pci_mousse_fixup_irq, | |
278 | }; | |
279 | ||
ad10dd9a | 280 | void pci_init_board(void) |
c609719b WD |
281 | { |
282 | pci_mpc824x_init(&hose); | |
283 | } |