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