]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * (C) Copyright 2002 Wolfgang Grandegger <wg@denx.de> | |
3 | * | |
4 | * See file CREDITS for list of people who contributed to this | |
5 | * project. | |
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 as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (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, | |
20 | * MA 02111-1307 USA | |
21 | */ | |
22 | ||
23 | #include <common.h> | |
24 | #include <mpc824x.h> | |
25 | #include <asm/io.h> | |
26 | #include <pci.h> | |
27 | ||
28 | #include "pn62.h" | |
29 | ||
30 | typedef struct { | |
31 | pci_dev_t devno; | |
32 | volatile u32 *csr; | |
33 | ||
34 | } i2155x_t; | |
35 | ||
36 | static i2155x_t i2155x = { 0, NULL }; | |
37 | ||
38 | static struct pci_device_id i2155x_ids[] = { | |
39 | { 0x1011, 0x0046 }, /* i21554 */ | |
40 | { 0x8086, 0xb555 } /* i21555 */ | |
41 | }; | |
42 | ||
43 | int i2155x_init(void) | |
44 | { | |
45 | pci_dev_t devno; | |
46 | u32 val; | |
47 | int i; | |
48 | ||
49 | /* | |
50 | * Find the Intel bridge. | |
51 | */ | |
52 | if ((devno = pci_find_devices(i2155x_ids, 0)) < 0) { | |
53 | printf("Error: Intel bridge 2155x not found!\n"); | |
54 | return -1; | |
55 | } | |
56 | i2155x.devno = devno; | |
57 | ||
58 | /* | |
59 | * Get auto-configured base address for CSR access. | |
60 | */ | |
61 | pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &val); | |
62 | if (val & PCI_BASE_ADDRESS_SPACE_IO) { | |
63 | val &= PCI_BASE_ADDRESS_IO_MASK; | |
64 | i2155x.csr = (volatile u32 *)(_IO_BASE + val); | |
65 | } else { | |
66 | val &= PCI_BASE_ADDRESS_MEM_MASK; | |
67 | i2155x.csr = (volatile u32 *)val; | |
68 | } | |
69 | ||
70 | /* | |
71 | * Translate downstream memory 2 (bar3) to base of shared memory. | |
72 | */ | |
73 | i2155x_set_bar_base(3, PN62_SMEM_DEFAULT); | |
74 | ||
75 | /* | |
76 | * Enable memory space, I/O space and bus master bits | |
77 | * in both Primary and Secondary command registers. | |
78 | */ | |
79 | val = PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER|PCI_COMMAND_IO; | |
80 | pci_write_config_word(devno, 0x44, val); | |
81 | pci_write_config_word(devno, 0x04, val); | |
82 | ||
83 | /* | |
84 | * Clear scratchpad registers. | |
85 | */ | |
86 | for (i = 0; i < (I2155X_SCRAPAD_MAX - 1); i++) { | |
87 | i2155x_write_scrapad(i, 0x0); | |
88 | } | |
89 | ||
90 | /* | |
91 | * Set interrupt line for Linux. | |
92 | */ | |
93 | pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 3); | |
94 | ||
95 | return 0; | |
96 | } | |
97 | ||
98 | /* | |
99 | * Access the Scratchpad registers 0..7 of the Intel bridge. | |
100 | */ | |
101 | void i2155x_write_scrapad(int idx, u32 val) | |
102 | { | |
103 | if (idx >= 0 && idx < I2155X_SCRAPAD_MAX) | |
104 | out_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx, val); | |
105 | else | |
106 | printf("i2155x_write_scrapad: invalid index\n"); | |
107 | } | |
108 | ||
109 | u32 i2155x_read_scrapad(int idx) | |
110 | { | |
111 | if (idx >= 0 && idx < I2155X_SCRAPAD_MAX) | |
112 | return in_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx); | |
113 | else | |
114 | printf("i2155x_read_scrapad: invalid index\n"); | |
115 | return -1; | |
116 | } | |
117 | ||
118 | void i2155x_set_bar_base(int bar, u32 base) | |
119 | { | |
120 | if (bar >= 2 && bar <= 4) { | |
121 | pci_write_config_dword(i2155x.devno, | |
122 | I2155X_BAR2_BASE + (bar - 2) * 4, | |
123 | base); | |
124 | } | |
125 | } | |
126 | ||
127 | /* | |
128 | * Read Vital Product Data (VPD) from the Serial EPROM attached | |
129 | * to the Intel bridge. | |
130 | */ | |
131 | int i2155x_read_vpd(int offset, int size, unsigned char *data) | |
132 | { | |
133 | int i, n; | |
134 | u16 val16; | |
135 | ||
136 | for (i = 0; i < size; i++) { | |
137 | pci_write_config_word(i2155x.devno, I2155X_VPD_ADDR, | |
138 | offset + i - I2155X_VPD_START); | |
139 | for (n = 10000; n > 0; n--) { | |
140 | pci_read_config_word(i2155x.devno, I2155X_VPD_ADDR, &val16); | |
141 | if ((val16 & 0x8000) != 0) /* wait for completion */ | |
142 | break; | |
143 | udelay(100); | |
144 | } | |
145 | if (n == 0) { | |
146 | printf("i2155x_read_vpd: TIMEOUT\n"); | |
147 | return -1; | |
148 | } | |
149 | ||
150 | pci_read_config_byte(i2155x.devno, I2155X_VPD_DATA, &data[i]); | |
151 | } | |
152 | ||
153 | return i; | |
154 | } | |
155 | ||
156 | static struct pci_device_id am79c95x_ids [] = { | |
8bde7f77 WD |
157 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, |
158 | { } | |
c609719b WD |
159 | }; |
160 | ||
161 | ||
162 | /* | |
163 | * Initialize the AMD ethernet controllers. | |
164 | */ | |
165 | int am79c95x_init(void) | |
166 | { | |
167 | pci_dev_t devno; | |
168 | int i; | |
169 | ||
170 | /* | |
171 | * Set interrupt line for Linux. | |
172 | */ | |
173 | for (i = 0; i < 2; i++) { | |
174 | if ((devno = pci_find_devices(am79c95x_ids, i)) < 0) | |
175 | break; | |
176 | pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 2+i); | |
177 | } | |
178 | if (i < 2) | |
179 | printf("Error: Only %d AMD Ethernet Controller found!\n", i); | |
180 | ||
181 | return 0; | |
182 | } | |
183 | ||
184 | ||
185 | void set_led(unsigned int number, unsigned int function) | |
186 | { | |
187 | volatile u8 *addr; | |
188 | ||
189 | if ((number >= 0) && (number < PN62_LED_MAX) && | |
190 | (function >= 0) && (function <= LED_LAST_FUNCTION)) { | |
191 | addr = (volatile u8 *)(PN62_LED_BASE + number * 8); | |
192 | out_8(addr, function&0xff); | |
193 | } | |
194 | } | |
195 | ||
196 | /* | |
197 | * Show fatal error indicated by Kinght Rider(tm) effect | |
198 | * in LEDS 0-7. LEDS 8-11 contain 4 bit error code. | |
199 | * Note: this function will not terminate. | |
200 | */ | |
201 | void fatal_error(unsigned int error_code) | |
202 | { | |
203 | int i, d; | |
204 | ||
205 | for (i = 0; i < 12; i++) { | |
206 | set_led(i, LED_0); | |
207 | } | |
208 | ||
209 | /* | |
210 | * Write error code. | |
211 | */ | |
212 | set_led(8, (error_code & 0x01) ? LED_1 : LED_0); | |
213 | set_led(9, (error_code & 0x02) ? LED_1 : LED_0); | |
214 | set_led(10, (error_code & 0x04) ? LED_1 : LED_0); | |
215 | set_led(11, (error_code & 0x08) ? LED_1 : LED_0); | |
216 | ||
217 | /* | |
218 | * Yay - Knight Rider effect! | |
219 | */ | |
220 | while(1) { | |
221 | unsigned int delay = 2000; | |
222 | ||
223 | for (i = 0; i < 8; i++) { | |
224 | set_led(i, LED_1); | |
225 | for (d = 0; d < delay; d++); | |
226 | set_led(i, LED_0); | |
227 | } | |
228 | ||
229 | for (i = 7; i > 0; i--) { | |
230 | set_led(i, LED_1); | |
231 | for (d = 0; d < delay; d++); | |
232 | set_led(i, LED_0); | |
233 | } | |
234 | } | |
235 | } |