blob: ae6642e952bf35f5a3506eae6c446baee44f6341 [file] [log] [blame]
wdenke69b4b82002-09-17 21:26:59 +00001/*
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/* includes */
25#include <common.h>
26#include "srom.h"
27
28/* locals */
29static unsigned long mpc107_eumb_addr = 0;
30
31/*----------------------------------------------------------------------------*/
32
33/*
34 * calculate checksum for ELTEC revision srom
35 */
36unsigned long el_srom_checksum (ptr, size)
37register unsigned char *ptr;
38unsigned long size;
39{
40 u_long f, accu = 0;
41 u_int i;
42 u_char byte;
43
44 for (; size; size--)
45 {
wdenk8bde7f72003-06-27 21:31:46 +000046 byte = *ptr++;
47 for (i = 8; i; i--)
48 {
49 f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
50 accu >>= 1; accu ^= f;
51 byte >>= 1;
52 }
wdenke69b4b82002-09-17 21:26:59 +000053 }
54 return(accu);
55}
56
57/*----------------------------------------------------------------------------*/
58
59static int mpc107_i2c_wait ( unsigned long timeout )
60{
61 unsigned long x;
62
63 while (((x = in32r(MPC107_I2CSR)) & 0x82) != 0x82)
64 {
wdenk8bde7f72003-06-27 21:31:46 +000065 if (!timeout--)
66 return -1;
wdenke69b4b82002-09-17 21:26:59 +000067 }
68
69 if (x & 0x10)
70 {
wdenk8bde7f72003-06-27 21:31:46 +000071 return -1;
wdenke69b4b82002-09-17 21:26:59 +000072 }
73 out32r(MPC107_I2CSR, 0);
74
75 return 0;
76}
77
78/*----------------------------------------------------------------------------*/
79
80static int mpc107_i2c_wait_idle ( unsigned long timeout )
81{
82 while (in32r(MPC107_I2CSR) & 0x20)
83 {
wdenk8bde7f72003-06-27 21:31:46 +000084 if (!timeout--)
85 return -1;
wdenke69b4b82002-09-17 21:26:59 +000086 }
87 return 0;
88}
89
90
91/*----------------------------------------------------------------------------*/
92
93int mpc107_i2c_read_byte (
94 unsigned char device,
95 unsigned char block,
96 unsigned char offset )
97{
98 unsigned long timeout = MPC107_I2C_TIMEOUT;
99 int data;
100
101 if (!mpc107_eumb_addr)
wdenk8bde7f72003-06-27 21:31:46 +0000102 return -6;
wdenke69b4b82002-09-17 21:26:59 +0000103
104 mpc107_i2c_wait_idle (timeout);
105
106 /* Start with MEN */
107 out32r(MPC107_I2CCR, 0x80);
108
109 /* Start as master */
110 out32r(MPC107_I2CCR, 0xB0);
111 out32r(MPC107_I2CDR, (0xA0 | device | block));
112
113 if (mpc107_i2c_wait(timeout) < 0)
114 {
wdenk8bde7f72003-06-27 21:31:46 +0000115 printf("mpc107_i2c_read Error 1\n");
116 return -2;
wdenke69b4b82002-09-17 21:26:59 +0000117 }
118
119 if (in32r(MPC107_I2CSR)&0x1)
120 {
wdenk8bde7f72003-06-27 21:31:46 +0000121 /* Generate STOP condition; device busy or not existing */
122 out32r(MPC107_I2CCR, 0x80);
123 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000124 }
125
126 /* Data address */
127 out32r(MPC107_I2CDR, offset);
128
129 if (mpc107_i2c_wait(timeout) < 0)
130 {
wdenk8bde7f72003-06-27 21:31:46 +0000131 printf("mpc107_i2c_read Error 2\n");
132 return -3;
wdenke69b4b82002-09-17 21:26:59 +0000133 }
134
135 /* Switch to read - restart */
136 out32r(MPC107_I2CCR, 0xB4);
137 out32r(MPC107_I2CDR, (0xA1 | device | block));
138
139 if (mpc107_i2c_wait(timeout) < 0)
140 {
wdenk8bde7f72003-06-27 21:31:46 +0000141 printf("mpc107_i2c_read Error 3\n");
142 return -4;
wdenke69b4b82002-09-17 21:26:59 +0000143 }
144
145 out32r(MPC107_I2CCR, 0xA8); /* no ACK */
146 in32r(MPC107_I2CDR);
147
148 if (mpc107_i2c_wait(timeout) < 0)
149 {
wdenk8bde7f72003-06-27 21:31:46 +0000150 printf("mpc107_i2c_read Error 4\n");
151 return -5;
wdenke69b4b82002-09-17 21:26:59 +0000152 }
153 /* Generate STOP condition */
154 out32r(MPC107_I2CCR, 0x88);
155
156 /* read */
157 data = in32r(MPC107_I2CDR);
158
159 return (data);
160}
161
162/*----------------------------------------------------------------------------*/
163
164int mpc107_i2c_write_byte (
165 unsigned char device,
166 unsigned char block,
167 unsigned char offset,
168 unsigned char val )
169{
170
171 unsigned long timeout = MPC107_I2C_TIMEOUT;
172
173 if (!mpc107_eumb_addr)
wdenk8bde7f72003-06-27 21:31:46 +0000174 return -6;
wdenke69b4b82002-09-17 21:26:59 +0000175
176 mpc107_i2c_wait_idle(timeout);
177
178 /* Start with MEN */
179 out32r(MPC107_I2CCR, 0x80);
180
181 /* Start as master */
182 out32r(MPC107_I2CCR, 0xB0);
183 out32r(MPC107_I2CDR, (0xA0 | device | block));
184
185 if (mpc107_i2c_wait(timeout) < 0)
186 {
wdenk8bde7f72003-06-27 21:31:46 +0000187 printf("mpc107_i2c_write Error 1\n");
188 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000189 }
190
191 /* Data address */
192 out32r(MPC107_I2CDR, offset);
193
194 if (mpc107_i2c_wait(timeout) < 0)
195 {
wdenk8bde7f72003-06-27 21:31:46 +0000196 printf("mpc107_i2c_write Error 2\n");
197 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000198 }
199
200 /* Write */
201 out32r(MPC107_I2CDR, val);
202 if (mpc107_i2c_wait(timeout) < 0)
203 {
wdenk8bde7f72003-06-27 21:31:46 +0000204 printf("mpc107_i2c_write Error 3\n");
205 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000206 }
207
208 /* Generate Stop Condition */
209 out32r(MPC107_I2CCR, 0x80);
210
211 /* Return ACK or no ACK */
212 return (in32r(MPC107_I2CSR) & 0x01);
213}
214
215/*----------------------------------------------------------------------------*/
216
217int mpc107_srom_load (
218 unsigned char addr,
219 unsigned char *pBuf,
220 int cnt,
221 unsigned char device,
222 unsigned char block )
223{
224 register int i;
225 int val;
226 int timeout;
227
228 for (i = 0; i < cnt; i++)
229 {
wdenk8bde7f72003-06-27 21:31:46 +0000230 timeout=100;
231 do
232 {
233 val = mpc107_i2c_read_byte (device, block, addr);
234 if (val < -1)
235 {
236 printf("i2c_read_error %d at dev %x block %x addr %x\n",
237 val, device, block, addr);
238 return -1;
239 }
240 else if (timeout==0)
241 {
242 printf ("i2c_read_error: timeout at dev %x block %x addr %x\n",
243 device, block, addr);
244 return -1;
245 }
246 timeout--;
247 } while (val == -1); /* if no ack: try again! */
wdenke69b4b82002-09-17 21:26:59 +0000248
wdenk8bde7f72003-06-27 21:31:46 +0000249 *pBuf++ = (unsigned char)val;
250 addr++;
wdenke69b4b82002-09-17 21:26:59 +0000251
wdenk8bde7f72003-06-27 21:31:46 +0000252 if ((addr == 0) && (i != cnt-1)) /* is it the same block ? */
253 {
254 if (block == FIRST_BLOCK)
255 block = SECOND_BLOCK;
256 else
257 {
258 printf ("ic2_read_error: read beyond 2. block !\n");
259 return -1;
260 }
261 }
wdenke69b4b82002-09-17 21:26:59 +0000262 }
263 udelay(100000);
264 return (cnt);
265}
266
267/*----------------------------------------------------------------------------*/
268
269int mpc107_srom_store (
270 unsigned char addr,
271 unsigned char *pBuf,
272 int cnt,
273 unsigned char device,
274 unsigned char block )
275{
276 register int i;
277
278 for (i = 0; i < cnt; i++)
279 {
wdenk8bde7f72003-06-27 21:31:46 +0000280 while (mpc107_i2c_write_byte (device,block,addr,*pBuf) == 1);
281 addr++;
282 pBuf++;
wdenke69b4b82002-09-17 21:26:59 +0000283
wdenk8bde7f72003-06-27 21:31:46 +0000284 if ((addr == 0) && (i != cnt-1)) /* is it the same block ? */
285 {
286 if (block == FIRST_BLOCK)
287 block = SECOND_BLOCK;
288 else
289 {
290 printf ("ic2_write_error: write beyond 2. block !\n");
291 return -1;
292 }
293 }
wdenke69b4b82002-09-17 21:26:59 +0000294 }
295 udelay(100000);
296 return(cnt);
297}
298
299/*----------------------------------------------------------------------------*/
300
301int mpc107_i2c_init ( unsigned long eumb_addr, unsigned long divider )
302{
303 unsigned long x;
304
305 if (eumb_addr)
wdenk8bde7f72003-06-27 21:31:46 +0000306 mpc107_eumb_addr = eumb_addr;
wdenke69b4b82002-09-17 21:26:59 +0000307 else
wdenk8bde7f72003-06-27 21:31:46 +0000308 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000309
310 /* Set I2C clock */
311 x = in32r(MPC107_I2CFDR) & 0xffffff00;
312 out32r(MPC107_I2CFDR, (x | divider));
313
314 /* Clear arbitration */
315 out32r(MPC107_I2CSR, 0);
316
317 return mpc107_eumb_addr;
318}
319
320/*----------------------------------------------------------------------------*/