]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/eltec/bab7xx/dc_srom.c
Initial revision
[karo-tx-uboot.git] / board / eltec / bab7xx / dc_srom.c
1 /*
2  * (C) Copyright 2002 ELTEC Elektronik AG
3  * Frank Gottschling <fgottschling@eltec.de>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * SRom I/O routines.
26  */
27
28 #include <common.h>
29 #include <pci.h>
30 #include "srom.h"
31
32 #define SROM_RD         0x00004000    /* Read from Boot ROM */
33 #define SROM_WR         0x00002000    /* Write to Boot ROM */
34 #define SROM_SR         0x00000800    /* Select Serial ROM when set */
35
36 #define DT_IN           0x00000004    /* Serial Data In */
37 #define DT_CLK          0x00000002    /* Serial ROM Clock */
38 #define DT_CS           0x00000001    /* Serial ROM Chip Select */
39
40 static u_int         dc_srom_iobase;
41
42 /*----------------------------------------------------------------------------*/
43
44 static int inl(u_long addr)
45 {
46     return le32_to_cpu(*(volatile u_long *)(addr));
47 }
48
49 /*----------------------------------------------------------------------------*/
50
51 static void outl (int command, u_long addr)
52 {
53     *(volatile u_long *)(addr) = cpu_to_le32(command);
54 }
55
56 /*----------------------------------------------------------------------------*/
57
58 static void sendto_srom(u_int command, u_long addr)
59 {
60     outl(command, addr);
61     udelay(1);
62
63     return;
64 }
65
66 /*----------------------------------------------------------------------------*/
67
68 static int getfrom_srom(u_long addr)
69 {
70     s32 tmp;
71
72     tmp = inl(addr);
73     udelay(1);
74
75     return tmp;
76 }
77
78 /*----------------------------------------------------------------------------*/
79
80 static void srom_latch (u_int command, u_long addr)
81 {
82     sendto_srom (command, addr);
83     sendto_srom (command | DT_CLK, addr);
84     sendto_srom (command, addr);
85
86     return;
87 }
88
89 /*----------------------------------------------------------------------------*/
90
91 static void srom_command_rd (u_int command, u_long addr)
92 {
93     srom_latch (command, addr);
94     srom_latch (command, addr);
95     srom_latch ((command & 0x0000ff00) | DT_CS, addr);
96
97     return;
98 }
99
100 /*----------------------------------------------------------------------------*/
101
102 static void srom_command_wr (u_int command, u_long addr)
103 {
104     srom_latch (command, addr);
105     srom_latch ((command & 0x0000ff00) | DT_CS, addr);
106     srom_latch (command, addr);
107
108     return;
109 }
110
111 /*----------------------------------------------------------------------------*/
112
113 static void srom_address(u_int command, u_long addr, u_char offset)
114 {
115     int i;
116     signed char a;
117
118     a = (char)(offset << 2);
119     for (i=0; i<6; i++, a <<= 1)
120     {
121         srom_latch(command | ((a < 0) ? DT_IN : 0), addr);
122     }
123     udelay(1);
124
125     i = (getfrom_srom(addr) >> 3) & 0x01;
126
127     return;
128 }
129 /*----------------------------------------------------------------------------*/
130
131 static short srom_data_rd (u_int command, u_long addr)
132 {
133     int i;
134     short word = 0;
135     s32 tmp;
136
137     for (i=0; i<16; i++)
138     {
139         sendto_srom(command  | DT_CLK, addr);
140         tmp = getfrom_srom(addr);
141         sendto_srom(command, addr);
142
143         word = (word << 1) | ((tmp >> 3) & 0x01);
144     }
145
146     sendto_srom(command & 0x0000ff00, addr);
147
148     return word;
149 }
150
151 /*----------------------------------------------------------------------------*/
152
153 static int srom_data_wr (u_int command, u_long addr, short val)
154 {
155     int i;
156     u_long longVal;
157     s32 tmp;
158
159     longVal = (u_long)(le16_to_cpu(val));
160
161     for (i=0; i<16; i++)
162     {
163         tmp = (longVal & 0x8000)>>13;
164
165         sendto_srom (tmp | command, addr);
166         sendto_srom (tmp | command  | DT_CLK, addr);
167         sendto_srom (tmp | command, addr);
168
169         longVal = longVal<<1;
170     }
171
172     sendto_srom(command & 0x0000ff00, addr);
173     sendto_srom(command, addr);
174
175     tmp = 100;
176     do
177     {
178         if ((getfrom_srom(dc_srom_iobase) & 0x8) == 0x8)
179             break;
180         udelay(1000);
181     } while (--tmp);
182
183     if (tmp == 0)
184     {
185         printf("Write DEC21143 SRom timed out !\n");
186         return (-1);
187     }
188
189     return 0;
190 }
191
192
193 /*----------------------------------------------------------------------------*/
194 static short srom_rd (u_long addr, u_char offset)
195 {
196     sendto_srom (SROM_RD | SROM_SR, addr);
197     srom_latch (SROM_RD | SROM_SR | DT_CS, addr);
198
199     srom_command_rd (SROM_RD | SROM_SR | DT_IN | DT_CS, addr);
200
201     srom_address (SROM_RD | SROM_SR | DT_CS, addr, offset);
202
203     return srom_data_rd (SROM_RD | SROM_SR | DT_CS, addr);
204 }
205
206 /*----------------------------------------------------------------------------*/
207
208 static void srom_wr_enable (u_long addr)
209 {
210     int i;
211
212     sendto_srom (SROM_WR | SROM_SR, addr);
213     srom_latch (SROM_WR | SROM_SR | DT_CS, addr);
214
215     srom_latch (SROM_WR | SROM_SR | DT_IN | DT_CS, addr);
216     srom_latch (SROM_WR | SROM_SR | DT_CS, addr);
217     srom_latch (SROM_WR | SROM_SR | DT_CS, addr);
218
219     for (i=0; i<6; i++)
220     {
221         srom_latch (SROM_WR | SROM_SR | DT_IN | DT_CS, addr);
222     }
223 }
224
225 /*----------------------------------------------------------------------------*/
226
227 static int srom_wr (u_long addr, u_char offset, short val)
228 {
229     srom_wr_enable (addr);
230
231     sendto_srom (SROM_WR | SROM_SR, addr);
232     srom_latch (SROM_WR | SROM_SR | DT_CS, addr);
233
234     srom_command_wr (SROM_WR | SROM_SR | DT_IN | DT_CS, addr);
235
236     srom_address (SROM_WR | SROM_SR | DT_CS, addr, offset);
237
238     return srom_data_wr (SROM_WR | SROM_SR | DT_CS, addr, val);
239 }
240
241 /*----------------------------------------------------------------------------*/
242 /*
243  * load data from the srom
244  */
245 int dc_srom_load (u_short *dest)
246 {
247     int offset;
248     short tmp;
249
250     /* get srom iobase from local network controller */
251     pci_read_config_dword(PCI_BDF(0,14,0), PCI_BASE_ADDRESS_1, &dc_srom_iobase);
252     dc_srom_iobase &= PCI_BASE_ADDRESS_MEM_MASK;
253     dc_srom_iobase  = pci_mem_to_phys(PCI_BDF(0,14,0), dc_srom_iobase);
254     dc_srom_iobase += 0x48;            /* io offset for srom access */
255
256     memset (dest, 0, 128);
257     for (offset=0; offset<64; offset++)
258     {
259         tmp = srom_rd (dc_srom_iobase, offset);
260         *dest++ = le16_to_cpu(tmp);
261     }
262
263     return (0);
264 }
265
266 /*----------------------------------------------------------------------------*/
267
268 /*
269  * store data into the srom
270  */
271 int dc_srom_store (u_short *src)
272 {
273     int offset;
274
275     /* get srom iobase from local network controller */
276     pci_read_config_dword(PCI_BDF(0,14,0), PCI_BASE_ADDRESS_1, &dc_srom_iobase);
277     dc_srom_iobase &= PCI_BASE_ADDRESS_MEM_MASK;
278     dc_srom_iobase  = pci_mem_to_phys(PCI_BDF(0,14,0), dc_srom_iobase);
279     dc_srom_iobase += 0x48;            /* io offset for srom access */
280
281     for (offset=0; offset<64; offset++)
282     {
283         if (srom_wr (dc_srom_iobase, offset, *src) == -1)
284                 return (-1);
285         src++;
286     }
287
288     return (0);
289 }
290
291 /*----------------------------------------------------------------------------*/