blob: 4f95703e143144df57dea69fc4cf99024cf4f7f2 [file] [log] [blame]
wdenke69b4b82002-09-17 21:26:59 +00001/*
2 * (C) Copyright 2002 ELTEC Elektronik AG
3 * Frank Gottschling <fgottschling@eltec.de>
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenke69b4b82002-09-17 21:26:59 +00006 */
7
8/* includes */
9#include <common.h>
10#include "srom.h"
11
12/* locals */
13static unsigned long mpc107_eumb_addr = 0;
14
15/*----------------------------------------------------------------------------*/
16
17/*
18 * calculate checksum for ELTEC revision srom
19 */
20unsigned long el_srom_checksum (ptr, size)
21register unsigned char *ptr;
22unsigned long size;
23{
24 u_long f, accu = 0;
25 u_int i;
26 u_char byte;
27
28 for (; size; size--)
29 {
wdenk8bde7f72003-06-27 21:31:46 +000030 byte = *ptr++;
31 for (i = 8; i; i--)
32 {
33 f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
34 accu >>= 1; accu ^= f;
35 byte >>= 1;
36 }
wdenke69b4b82002-09-17 21:26:59 +000037 }
38 return(accu);
39}
40
41/*----------------------------------------------------------------------------*/
42
43static int mpc107_i2c_wait ( unsigned long timeout )
44{
45 unsigned long x;
46
47 while (((x = in32r(MPC107_I2CSR)) & 0x82) != 0x82)
48 {
wdenk8bde7f72003-06-27 21:31:46 +000049 if (!timeout--)
50 return -1;
wdenke69b4b82002-09-17 21:26:59 +000051 }
52
53 if (x & 0x10)
54 {
wdenk8bde7f72003-06-27 21:31:46 +000055 return -1;
wdenke69b4b82002-09-17 21:26:59 +000056 }
57 out32r(MPC107_I2CSR, 0);
58
59 return 0;
60}
61
62/*----------------------------------------------------------------------------*/
63
64static int mpc107_i2c_wait_idle ( unsigned long timeout )
65{
66 while (in32r(MPC107_I2CSR) & 0x20)
67 {
wdenk8bde7f72003-06-27 21:31:46 +000068 if (!timeout--)
69 return -1;
wdenke69b4b82002-09-17 21:26:59 +000070 }
71 return 0;
72}
73
74
75/*----------------------------------------------------------------------------*/
76
77int mpc107_i2c_read_byte (
78 unsigned char device,
79 unsigned char block,
80 unsigned char offset )
81{
82 unsigned long timeout = MPC107_I2C_TIMEOUT;
83 int data;
84
85 if (!mpc107_eumb_addr)
wdenk8bde7f72003-06-27 21:31:46 +000086 return -6;
wdenke69b4b82002-09-17 21:26:59 +000087
88 mpc107_i2c_wait_idle (timeout);
89
90 /* Start with MEN */
91 out32r(MPC107_I2CCR, 0x80);
92
93 /* Start as master */
94 out32r(MPC107_I2CCR, 0xB0);
95 out32r(MPC107_I2CDR, (0xA0 | device | block));
96
97 if (mpc107_i2c_wait(timeout) < 0)
98 {
wdenk8bde7f72003-06-27 21:31:46 +000099 printf("mpc107_i2c_read Error 1\n");
100 return -2;
wdenke69b4b82002-09-17 21:26:59 +0000101 }
102
103 if (in32r(MPC107_I2CSR)&0x1)
104 {
wdenk8bde7f72003-06-27 21:31:46 +0000105 /* Generate STOP condition; device busy or not existing */
106 out32r(MPC107_I2CCR, 0x80);
107 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000108 }
109
110 /* Data address */
111 out32r(MPC107_I2CDR, offset);
112
113 if (mpc107_i2c_wait(timeout) < 0)
114 {
wdenk8bde7f72003-06-27 21:31:46 +0000115 printf("mpc107_i2c_read Error 2\n");
116 return -3;
wdenke69b4b82002-09-17 21:26:59 +0000117 }
118
119 /* Switch to read - restart */
120 out32r(MPC107_I2CCR, 0xB4);
121 out32r(MPC107_I2CDR, (0xA1 | device | block));
122
123 if (mpc107_i2c_wait(timeout) < 0)
124 {
wdenk8bde7f72003-06-27 21:31:46 +0000125 printf("mpc107_i2c_read Error 3\n");
126 return -4;
wdenke69b4b82002-09-17 21:26:59 +0000127 }
128
129 out32r(MPC107_I2CCR, 0xA8); /* no ACK */
130 in32r(MPC107_I2CDR);
131
132 if (mpc107_i2c_wait(timeout) < 0)
133 {
wdenk8bde7f72003-06-27 21:31:46 +0000134 printf("mpc107_i2c_read Error 4\n");
135 return -5;
wdenke69b4b82002-09-17 21:26:59 +0000136 }
137 /* Generate STOP condition */
138 out32r(MPC107_I2CCR, 0x88);
139
140 /* read */
141 data = in32r(MPC107_I2CDR);
142
143 return (data);
144}
145
146/*----------------------------------------------------------------------------*/
147
148int mpc107_i2c_write_byte (
149 unsigned char device,
150 unsigned char block,
151 unsigned char offset,
152 unsigned char val )
153{
154
155 unsigned long timeout = MPC107_I2C_TIMEOUT;
156
157 if (!mpc107_eumb_addr)
wdenk8bde7f72003-06-27 21:31:46 +0000158 return -6;
wdenke69b4b82002-09-17 21:26:59 +0000159
160 mpc107_i2c_wait_idle(timeout);
161
162 /* Start with MEN */
163 out32r(MPC107_I2CCR, 0x80);
164
165 /* Start as master */
166 out32r(MPC107_I2CCR, 0xB0);
167 out32r(MPC107_I2CDR, (0xA0 | device | block));
168
169 if (mpc107_i2c_wait(timeout) < 0)
170 {
wdenk8bde7f72003-06-27 21:31:46 +0000171 printf("mpc107_i2c_write Error 1\n");
172 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000173 }
174
175 /* Data address */
176 out32r(MPC107_I2CDR, offset);
177
178 if (mpc107_i2c_wait(timeout) < 0)
179 {
wdenk8bde7f72003-06-27 21:31:46 +0000180 printf("mpc107_i2c_write Error 2\n");
181 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000182 }
183
184 /* Write */
185 out32r(MPC107_I2CDR, val);
186 if (mpc107_i2c_wait(timeout) < 0)
187 {
wdenk8bde7f72003-06-27 21:31:46 +0000188 printf("mpc107_i2c_write Error 3\n");
189 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000190 }
191
192 /* Generate Stop Condition */
193 out32r(MPC107_I2CCR, 0x80);
194
195 /* Return ACK or no ACK */
196 return (in32r(MPC107_I2CSR) & 0x01);
197}
198
199/*----------------------------------------------------------------------------*/
200
201int mpc107_srom_load (
202 unsigned char addr,
203 unsigned char *pBuf,
204 int cnt,
205 unsigned char device,
206 unsigned char block )
207{
208 register int i;
209 int val;
210 int timeout;
211
212 for (i = 0; i < cnt; i++)
213 {
wdenk8bde7f72003-06-27 21:31:46 +0000214 timeout=100;
215 do
216 {
217 val = mpc107_i2c_read_byte (device, block, addr);
218 if (val < -1)
219 {
220 printf("i2c_read_error %d at dev %x block %x addr %x\n",
221 val, device, block, addr);
222 return -1;
223 }
224 else if (timeout==0)
225 {
226 printf ("i2c_read_error: timeout at dev %x block %x addr %x\n",
227 device, block, addr);
228 return -1;
229 }
230 timeout--;
231 } while (val == -1); /* if no ack: try again! */
wdenke69b4b82002-09-17 21:26:59 +0000232
wdenk8bde7f72003-06-27 21:31:46 +0000233 *pBuf++ = (unsigned char)val;
234 addr++;
wdenke69b4b82002-09-17 21:26:59 +0000235
wdenk8bde7f72003-06-27 21:31:46 +0000236 if ((addr == 0) && (i != cnt-1)) /* is it the same block ? */
237 {
238 if (block == FIRST_BLOCK)
239 block = SECOND_BLOCK;
240 else
241 {
242 printf ("ic2_read_error: read beyond 2. block !\n");
243 return -1;
244 }
245 }
wdenke69b4b82002-09-17 21:26:59 +0000246 }
247 udelay(100000);
248 return (cnt);
249}
250
251/*----------------------------------------------------------------------------*/
252
253int mpc107_srom_store (
254 unsigned char addr,
255 unsigned char *pBuf,
256 int cnt,
257 unsigned char device,
258 unsigned char block )
259{
260 register int i;
261
262 for (i = 0; i < cnt; i++)
263 {
wdenk8bde7f72003-06-27 21:31:46 +0000264 while (mpc107_i2c_write_byte (device,block,addr,*pBuf) == 1);
265 addr++;
266 pBuf++;
wdenke69b4b82002-09-17 21:26:59 +0000267
wdenk8bde7f72003-06-27 21:31:46 +0000268 if ((addr == 0) && (i != cnt-1)) /* is it the same block ? */
269 {
270 if (block == FIRST_BLOCK)
271 block = SECOND_BLOCK;
272 else
273 {
274 printf ("ic2_write_error: write beyond 2. block !\n");
275 return -1;
276 }
277 }
wdenke69b4b82002-09-17 21:26:59 +0000278 }
279 udelay(100000);
280 return(cnt);
281}
282
283/*----------------------------------------------------------------------------*/
284
285int mpc107_i2c_init ( unsigned long eumb_addr, unsigned long divider )
286{
287 unsigned long x;
288
289 if (eumb_addr)
wdenk8bde7f72003-06-27 21:31:46 +0000290 mpc107_eumb_addr = eumb_addr;
wdenke69b4b82002-09-17 21:26:59 +0000291 else
wdenk8bde7f72003-06-27 21:31:46 +0000292 return -1;
wdenke69b4b82002-09-17 21:26:59 +0000293
294 /* Set I2C clock */
295 x = in32r(MPC107_I2CFDR) & 0xffffff00;
296 out32r(MPC107_I2CFDR, (x | divider));
297
298 /* Clear arbitration */
299 out32r(MPC107_I2CSR, 0);
300
301 return mpc107_eumb_addr;
302}
303
304/*----------------------------------------------------------------------------*/