]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/pn62/misc.c
Initial revision
[karo-tx-uboot.git] / board / pn62 / misc.c
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 [] = {
157         { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE },
158         { }
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 }