]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /************************************************************* |
2 | * | |
3 | * Copyright @ Motorola, 1999 | |
4 | * | |
5 | ************************************************************/ | |
6 | #include <common.h> | |
7 | ||
8 | #ifdef CONFIG_HARD_I2C | |
9 | #include <i2c.h> | |
10 | #include "i2c_export.h" | |
11 | #include "i2c.h" | |
12 | ||
13 | #undef I2CDBG0 | |
14 | #undef DEBUG | |
15 | ||
16 | /* Define a macro to use an optional application-layer print function, if | |
17 | * one was passed to the I2C library during initialization. If there was | |
18 | * no function pointer passed, this protects against calling it. Also define | |
19 | * the global variable that holds the passed pointer. | |
20 | */ | |
21 | #define TIMEOUT (CFG_HZ/4) | |
22 | #define PRINT if ( app_print ) app_print | |
23 | static int (*app_print) (char *, ...); | |
24 | ||
25 | /******************* Internal to I2C Driver *****************/ | |
26 | static unsigned int ByteToXmit = 0; | |
27 | static unsigned int XmitByte = 0; | |
28 | static unsigned char *XmitBuf = 0; | |
29 | static unsigned int XmitBufEmptyStop = 0; | |
30 | static unsigned int ByteToRcv = 0; | |
31 | static unsigned int RcvByte = 0; | |
32 | static unsigned char *RcvBuf = 0; | |
33 | static unsigned int RcvBufFulStop = 0; | |
34 | static unsigned int MasterRcvAddress = 0; | |
35 | ||
36 | /* Set by call to get_eumbbar during I2C_Initialize. | |
37 | * This could be globally available to the I2C library, but there is | |
38 | * an advantage to passing it as a parameter: it is already in a register | |
39 | * and doesn't have to be loaded from memory. Also, that is the way the | |
40 | * I2C library was already implemented and I don't want to change it without | |
41 | * a more detailed analysis. | |
42 | * It is being set as a global variable in I2C_Initialize to hide it from | |
43 | * the DINK application layer, because it is Kahlua-specific. I think that | |
44 | * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in | |
45 | * a Kahlua-specific library dealing with the embedded utilities memory block. | |
46 | * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are | |
47 | * defined in dink32/drivers/i2c/i2c2.s. | |
48 | */ | |
49 | static unsigned int Global_eumbbar = 0; | |
50 | ||
51 | extern unsigned int load_runtime_reg (unsigned int eumbbar, | |
52 | unsigned int reg); | |
53 | ||
54 | extern unsigned int store_runtime_reg (unsigned int eumbbar, | |
55 | unsigned int reg, unsigned int val); | |
56 | ||
57 | /************************** API *****************/ | |
58 | ||
59 | /* Application Program Interface (API) are the calls provided by the I2C | |
60 | * library to upper layer applications (i.e., DINK) to access the Kahlua | |
61 | * I2C bus interface. The functions and values that are part of this API | |
62 | * are declared in i2c_export.h. | |
63 | */ | |
64 | ||
65 | /* Initialize I2C unit with the following: | |
66 | * driver's slave address | |
67 | * interrupt enabled | |
68 | * optional pointer to application layer print function | |
69 | * | |
70 | * These parameters may be added: | |
71 | * desired clock rate | |
72 | * digital filter frequency sampling rate | |
73 | * | |
74 | * This function must be called before I2C unit can be used. | |
75 | */ | |
76 | I2C_Status I2C_Initialize (unsigned char addr, | |
77 | I2C_INTERRUPT_MODE en_int, | |
78 | int (*p) (char *, ...)) | |
79 | { | |
80 | I2CStatus status; | |
81 | ||
82 | /* establish the pointer, if there is one, to the application's "printf" */ | |
83 | app_print = p; | |
84 | ||
85 | /* If this is the first call, get the embedded utilities memory block | |
86 | * base address. I'm not sure what to do about error handling here: | |
87 | * if a non-zero value is returned, accept it. | |
88 | */ | |
89 | if (Global_eumbbar == 0) | |
90 | Global_eumbbar = get_eumbbar (); | |
91 | if (Global_eumbbar == 0) { | |
92 | PRINT ("I2C_Initialize: can't find EUMBBAR\n"); | |
93 | return I2C_ERROR; | |
94 | } | |
95 | ||
96 | /* validate the I2C address */ | |
97 | if (addr & 0x80) { | |
98 | PRINT ("I2C_Initialize, I2C address invalid: %d 0x%x\n", | |
99 | (unsigned int) addr, (unsigned int) addr); | |
100 | return I2C_ERROR; | |
101 | } | |
102 | ||
103 | /* Call the internal I2C library function to perform work. | |
104 | * Accept the default frequency sampling rate (no way to set it currently, | |
105 | * via I2C_Init) and set the clock frequency to something reasonable. | |
106 | */ | |
107 | status = I2C_Init (Global_eumbbar, (unsigned char) 0x31, addr, en_int); | |
108 | if (status != I2CSUCCESS) { | |
109 | PRINT ("I2C_Initialize: error in initiation\n"); | |
110 | return I2C_ERROR; | |
111 | } | |
112 | ||
113 | /* all is well */ | |
114 | return I2C_SUCCESS; | |
115 | } | |
116 | ||
117 | ||
118 | /* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV | |
119 | * are implemented. Both are only in polling mode. | |
120 | * | |
121 | * en_int controls interrupt/polling mode | |
122 | * act is the type of transaction | |
123 | * i2c_addr is the I2C address of the slave device | |
124 | * data_addr is the address of the data on the slave device | |
125 | * len is the length of data to send or receive | |
126 | * buffer is the address of the data buffer | |
127 | * stop = I2C_NO_STOP, don't signal STOP at end of transaction | |
3595ac49 | 128 | * I2C_STOP, signal STOP at end of transaction |
c609719b WD |
129 | * retry is the timeout retry value, currently ignored |
130 | * rsta = I2C_NO_RESTART, this is not continuation of existing transaction | |
3595ac49 | 131 | * I2C_RESTART, this is a continuation of existing transaction |
c609719b WD |
132 | */ |
133 | I2C_Status I2C_do_transaction ( I2C_INTERRUPT_MODE en_int, | |
134 | I2C_TRANSACTION_MODE act, | |
135 | unsigned char i2c_addr, | |
136 | unsigned char data_addr, | |
137 | int len, | |
138 | char *buffer, | |
139 | I2C_STOP_MODE stop, | |
140 | int retry, I2C_RESTART_MODE rsta) | |
141 | { | |
142 | I2C_Status status; | |
143 | unsigned char data_addr_buffer[1]; | |
144 | ||
145 | #if 1 | |
146 | /* This is a temporary work-around. The I2C library breaks the protocol | |
147 | * if it attempts to handle a data transmission in more than one | |
148 | * transaction, so the data address and the actual data bytes are put | |
149 | * into a single buffer before sending it to the library internal functions. | |
150 | * The problem is related to being able to restart a transaction without | |
151 | * sending the I2C device address or repeating the data address. It may take | |
152 | * a day or two to sort it all out, so I'll have to get back to it later. | |
153 | * Look at I2C_Start to see about using some status flags (I'm not sure that | |
154 | * "stop" and "rsta" are enough to reflect the states, maybe so; but the logic | |
155 | * in the library is insufficient) to control correct handling of the protocol. | |
156 | */ | |
157 | unsigned char dummy_buffer[257]; | |
158 | ||
159 | if (act == I2C_MASTER_XMIT) { | |
160 | int i; | |
161 | ||
162 | if (len > 256) | |
163 | return I2C_ERROR; | |
164 | for (i = 1; i <= len; i++) | |
165 | dummy_buffer[i] = buffer[i - 1]; | |
166 | dummy_buffer[0] = data_addr; | |
167 | status = I2C_do_buffer (en_int, act, i2c_addr, 1 + len, | |
168 | dummy_buffer, stop, retry, rsta); | |
169 | if (status != I2C_SUCCESS) { | |
170 | PRINT ("I2C_do_transaction: can't perform data transfer\n"); | |
171 | return I2C_ERROR; | |
172 | } | |
173 | return I2C_SUCCESS; | |
174 | } | |
175 | #endif /* end of temp work-around */ | |
176 | ||
177 | /* validate requested transaction type */ | |
178 | if ((act != I2C_MASTER_XMIT) && (act != I2C_MASTER_RCV)) { | |
179 | PRINT ("I2C_do_transaction, invalid transaction request: %d\n", | |
180 | act); | |
181 | return I2C_ERROR; | |
182 | } | |
183 | ||
184 | /* range check the I2C address */ | |
185 | if (i2c_addr & 0x80) { | |
186 | PRINT ("I2C_do_transaction, I2C address out of range: %d 0x%x\n", | |
187 | (unsigned int) i2c_addr, (unsigned int) i2c_addr); | |
188 | return I2C_ERROR; | |
189 | } else { | |
190 | data_addr_buffer[0] = data_addr; | |
191 | } | |
192 | ||
193 | /* | |
3595ac49 WD |
194 | * We first have to contact the slave device and transmit the |
195 | * data address. Be careful about the STOP and restart stuff. | |
196 | * We don't want to signal STOP after sending the data | |
197 | * address, but this could be a continuation if the | |
198 | * application didn't release the bus after the previous | |
199 | * transaction, by not sending a STOP after it. | |
c609719b WD |
200 | */ |
201 | status = I2C_do_buffer (en_int, I2C_MASTER_XMIT, i2c_addr, 1, | |
202 | data_addr_buffer, I2C_NO_STOP, retry, rsta); | |
203 | if (status != I2C_SUCCESS) { | |
204 | PRINT ("I2C_do_transaction: can't send data address for read\n"); | |
205 | return I2C_ERROR; | |
206 | } | |
207 | ||
208 | /* The data transfer will be a continuation. */ | |
209 | rsta = I2C_RESTART; | |
210 | ||
211 | /* now handle the user data */ | |
212 | status = I2C_do_buffer (en_int, act, i2c_addr, len, | |
213 | buffer, stop, retry, rsta); | |
214 | if (status != I2C_SUCCESS) { | |
215 | PRINT ("I2C_do_transaction: can't perform data transfer\n"); | |
216 | return I2C_ERROR; | |
217 | } | |
218 | ||
219 | /* all is well */ | |
220 | return I2C_SUCCESS; | |
221 | } | |
222 | ||
223 | /* This function performs the work for I2C_do_transaction. The work is | |
224 | * split into this function to enable I2C_do_transaction to first transmit | |
225 | * the data address to the I2C slave device without putting the data address | |
226 | * into the first byte of the buffer. | |
227 | * | |
228 | * en_int controls interrupt/polling mode | |
229 | * act is the type of transaction | |
230 | * i2c_addr is the I2C address of the slave device | |
231 | * len is the length of data to send or receive | |
232 | * buffer is the address of the data buffer | |
233 | * stop = I2C_NO_STOP, don't signal STOP at end of transaction | |
3595ac49 | 234 | * I2C_STOP, signal STOP at end of transaction |
c609719b WD |
235 | * retry is the timeout retry value, currently ignored |
236 | * rsta = I2C_NO_RESTART, this is not continuation of existing transaction | |
3595ac49 | 237 | * I2C_RESTART, this is a continuation of existing transaction |
c609719b WD |
238 | */ |
239 | static I2C_Status I2C_do_buffer (I2C_INTERRUPT_MODE en_int, | |
240 | I2C_TRANSACTION_MODE act, | |
241 | unsigned char i2c_addr, | |
242 | int len, | |
243 | unsigned char *buffer, | |
244 | I2C_STOP_MODE stop, | |
245 | int retry, I2C_RESTART_MODE rsta) | |
246 | { | |
247 | I2CStatus rval; | |
248 | unsigned int dev_stat; | |
249 | ||
250 | if (act == I2C_MASTER_RCV) { | |
251 | /* set up for master-receive transaction */ | |
252 | rval = I2C_get (Global_eumbbar, i2c_addr, buffer, len, stop, rsta); | |
253 | } else { | |
254 | /* set up for master-transmit transaction */ | |
255 | rval = I2C_put (Global_eumbbar, i2c_addr, buffer, len, stop, rsta); | |
256 | } | |
257 | ||
258 | /* validate the setup */ | |
259 | if (rval != I2CSUCCESS) { | |
260 | dev_stat = load_runtime_reg (Global_eumbbar, I2CSR); | |
261 | PRINT ("Error(I2C_do_buffer): control phase, code(0x%08x), status(0x%08x)\n", rval, dev_stat); | |
262 | I2C_Stop (Global_eumbbar); | |
263 | return I2C_ERROR; | |
264 | } | |
265 | ||
266 | if (en_int == 1) { | |
267 | /* this should not happen, no interrupt handling yet */ | |
268 | return I2C_SUCCESS; | |
269 | } | |
270 | ||
271 | /* this performs the polling action, when the transfer is completed, | |
272 | * the status returned from I2C_Timer_Event will be I2CBUFFFULL or | |
273 | * I2CBUFFEMPTY (rcv or xmit), I2CSUCCESS or I2CADDRESS indicates the | |
274 | * transaction is not yet complete, anything else is an error. | |
275 | */ | |
276 | while (rval == I2CSUCCESS || rval == I2CADDRESS) { | |
277 | int timeval = get_timer (0); | |
278 | ||
279 | /* poll the device until something happens */ | |
280 | do { | |
281 | rval = I2C_Timer_Event (Global_eumbbar, 0); | |
282 | } | |
283 | while (rval == I2CNOEVENT && get_timer (timeval) < TIMEOUT); | |
284 | ||
285 | /* check for error condition */ | |
286 | if (rval == I2CSUCCESS || | |
287 | rval == I2CBUFFFULL || | |
288 | rval == I2CBUFFEMPTY || | |
289 | rval == I2CADDRESS) { | |
290 | ; /* do nothing */ | |
291 | } else { | |
292 | /* report the error condition */ | |
293 | dev_stat = load_runtime_reg (Global_eumbbar, I2CSR); | |
294 | PRINT ("Error(I2C_do_buffer): code(0x%08x), status(0x%08x)\n", | |
295 | rval, dev_stat); | |
296 | return I2C_ERROR; | |
297 | } | |
298 | } | |
299 | ||
300 | /* all is well */ | |
301 | return I2C_SUCCESS; | |
302 | } | |
303 | ||
304 | /** | |
305 | * Note: | |
306 | * | |
307 | * In all following functions, | |
308 | * the caller shall pass the configured embedded utility memory | |
309 | * block base, EUMBBAR. | |
310 | **/ | |
311 | ||
312 | /*********************************************************** | |
313 | * function: I2C_put | |
314 | * | |
315 | * description: | |
316 | Send a buffer of data to the intended rcv_addr. | |
317 | * If stop_flag is set, after the whole buffer | |
318 | * is sent, generate a STOP signal provided that the | |
319 | * receiver doesn't signal the STOP in the middle. | |
320 | * I2C is the master performing transmitting. If | |
321 | * no STOP signal is generated at the end of current | |
322 | * transaction, the master can generate a START signal | |
323 | * to another slave addr. | |
324 | * | |
325 | * note: this is master xmit API | |
326 | *********************************************************/ | |
327 | static I2CStatus I2C_put (unsigned int eumbbar, unsigned char rcv_addr, /* receiver's address */ | |
328 | unsigned char *buffer_ptr, /* pointer of data to be sent */ | |
329 | unsigned int length, /* number of byte of in the buffer */ | |
330 | unsigned int stop_flag, /* 1 - signal STOP when buffer is empty | |
331 | * 0 - no STOP signal when buffer is empty | |
332 | */ | |
333 | unsigned int is_cnt) | |
334 | { /* 1 - this is a restart, don't check MBB | |
335 | * 0 - this is a new start, check MBB | |
336 | */ | |
337 | if (buffer_ptr == 0 || length == 0) { | |
338 | return I2CERROR; | |
339 | } | |
340 | #ifdef I2CDBG0 | |
341 | PRINT ("%s(%d): I2C_put\n", __FILE__, __LINE__); | |
342 | #endif | |
343 | ||
344 | XmitByte = 0; | |
345 | ByteToXmit = length; | |
346 | XmitBuf = buffer_ptr; | |
347 | XmitBufEmptyStop = stop_flag; | |
348 | ||
349 | RcvByte = 0; | |
350 | ByteToRcv = 0; | |
351 | RcvBuf = 0; | |
352 | ||
353 | /* we are the master, start transaction */ | |
354 | return I2C_Start (eumbbar, rcv_addr, XMIT, is_cnt); | |
355 | } | |
356 | ||
357 | /*********************************************************** | |
358 | * function: I2C_get | |
359 | * | |
360 | * description: | |
361 | * Receive a buffer of data from the desired sender_addr | |
362 | * If stop_flag is set, when the buffer is full and the | |
363 | * sender does not signal STOP, generate a STOP signal. | |
364 | * I2C is the master performing receiving. If no STOP signal | |
365 | * is generated, the master can generate a START signal | |
366 | * to another slave addr. | |
367 | * | |
368 | * note: this is master receive API | |
369 | **********************************************************/ | |
370 | static I2CStatus I2C_get (unsigned int eumbbar, unsigned char rcv_from, /* sender's address */ | |
371 | unsigned char *buffer_ptr, /* pointer of receiving buffer */ | |
372 | unsigned int length, /* length of the receiving buffer */ | |
373 | unsigned int stop_flag, /* 1 - signal STOP when buffer is full | |
374 | * 0 - no STOP signal when buffer is full | |
375 | */ | |
376 | unsigned int is_cnt) | |
377 | { /* 1 - this is a restart, don't check MBB | |
378 | * 0 - this is a new start, check MBB | |
379 | */ | |
380 | if (buffer_ptr == 0 || length == 0) { | |
381 | return I2CERROR; | |
382 | } | |
383 | #ifdef I2CDBG0 | |
384 | PRINT ("%s(%d): I2C_get\n", __FILE__, __LINE__); | |
385 | #endif | |
386 | ||
387 | RcvByte = 0; | |
388 | ByteToRcv = length; | |
389 | RcvBuf = buffer_ptr; | |
390 | RcvBufFulStop = stop_flag; | |
391 | ||
392 | XmitByte = 0; | |
393 | ByteToXmit = 0; | |
394 | XmitBuf = 0; | |
395 | ||
396 | /* we are the master, start the transaction */ | |
397 | return I2C_Start (eumbbar, rcv_from, RCV, is_cnt); | |
398 | ||
399 | } | |
400 | ||
401 | #if 0 /* turn off dead code */ | |
402 | /********************************************************* | |
403 | * function: I2C_write | |
404 | * | |
405 | * description: | |
406 | * Send a buffer of data to the requiring master. | |
407 | * If stop_flag is set, after the whole buffer is sent, | |
408 | * generate a STOP signal provided that the requiring | |
409 | * receiver doesn't signal the STOP in the middle. | |
410 | * I2C is the slave performing transmitting. | |
411 | * | |
412 | * Note: this is slave xmit API. | |
413 | * | |
414 | * due to the current Kahlua design, slave transmitter | |
415 | * shall not signal STOP since there is no way | |
416 | * for master to detect it, causing I2C bus hung. | |
417 | * | |
418 | * For the above reason, the stop_flag is always | |
419 | * set, i.e., 0. | |
420 | * | |
421 | * programmer shall use the timer on Kahlua to | |
422 | * control the interval of data byte at the | |
423 | * master side. | |
424 | *******************************************************/ | |
425 | static I2CStatus I2C_write (unsigned int eumbbar, unsigned char *buffer_ptr, /* pointer of data to be sent */ | |
426 | unsigned int length, /* number of byte of in the buffer */ | |
427 | unsigned int stop_flag) | |
428 | { /* 1 - signal STOP when buffer is empty | |
429 | * 0 - no STOP signal when buffer is empty | |
430 | */ | |
431 | if (buffer_ptr == 0 || length == 0) { | |
432 | return I2CERROR; | |
433 | } | |
434 | ||
435 | XmitByte = 0; | |
436 | ByteToXmit = length; | |
437 | XmitBuf = buffer_ptr; | |
438 | XmitBufEmptyStop = 0; /* in order to avoid bus hung, ignored the user's stop_flag */ | |
439 | ||
440 | RcvByte = 0; | |
441 | ByteToRcv = 0; | |
442 | RcvBuf = 0; | |
443 | ||
444 | /* we are the slave, just wait for being called, or pull */ | |
445 | /* I2C_Timer_Event( eumbbar ); */ | |
446 | } | |
447 | ||
448 | /****************************************************** | |
449 | * function: I2C_read | |
450 | * | |
451 | * description: | |
452 | * Receive a buffer of data from the sending master. | |
453 | * If stop_flag is set, when the buffer is full and the | |
454 | * sender does not signal STOP, generate a STOP signal. | |
455 | * I2C is the slave performing receiving. | |
456 | * | |
457 | * note: this is slave receive API | |
458 | ****************************************************/ | |
459 | static I2CStatus I2C_read (unsigned int eumbbar, unsigned char *buffer_ptr, /* pointer of receiving buffer */ | |
460 | unsigned int length, /* length of the receiving buffer */ | |
461 | unsigned int stop_flag) | |
462 | { /* 1 - signal STOP when buffer is full | |
463 | * 0 - no STOP signal when buffer is full | |
464 | */ | |
465 | if (buffer_ptr == 0 || length == 0) { | |
466 | return I2CERROR; | |
467 | } | |
468 | ||
469 | RcvByte = 0; | |
470 | ByteToRcv = length; | |
471 | RcvBuf = buffer_ptr; | |
472 | RcvBufFulStop = stop_flag; | |
473 | ||
474 | XmitByte = 0; | |
475 | ByteToXmit = 0; | |
476 | XmitBuf = 0; | |
477 | ||
478 | /* wait for master to call us, or poll */ | |
479 | /* I2C_Timer_Event( eumbbar ); */ | |
480 | } | |
481 | #endif /* turn off dead code */ | |
482 | ||
483 | /********************************************************* | |
484 | * function: I2c_Timer_Event | |
485 | * | |
486 | * description: | |
487 | * if interrupt is not used, this is the timer event handler. | |
488 | * After each fixed time interval, this function can be called | |
489 | * to check the I2C status and call appropriate function to | |
490 | * handle the status event. | |
491 | ********************************************************/ | |
492 | static I2CStatus I2C_Timer_Event (unsigned int eumbbar, | |
493 | I2CStatus (*handler) (unsigned int)) | |
494 | { | |
495 | I2C_STAT stat; | |
496 | ||
497 | #ifdef I2CDBG0 | |
498 | PRINT ("%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__); | |
499 | #endif | |
500 | ||
501 | stat = I2C_Get_Stat (eumbbar); | |
502 | ||
503 | if (stat.mif == 1) { | |
504 | if (handler == 0) { | |
505 | return I2C_ISR (eumbbar); | |
506 | } else { | |
507 | return (*handler) (eumbbar); | |
508 | } | |
509 | } | |
510 | ||
511 | return I2CNOEVENT; | |
512 | } | |
513 | ||
514 | ||
515 | /****************** Device I/O function *****************/ | |
516 | ||
517 | /****************************************************** | |
518 | * function: I2C_Start | |
519 | * | |
520 | * description: Generate a START signal in the desired mode. | |
3595ac49 | 521 | * I2C is the master. |
c609719b | 522 | * |
3595ac49 | 523 | * Return I2CSUCCESS if no error. |
c609719b WD |
524 | * |
525 | * note: | |
526 | ****************************************************/ | |
527 | static I2CStatus I2C_Start (unsigned int eumbbar, unsigned char slave_addr, /* address of the receiver */ | |
528 | I2C_MODE mode, /* XMIT(1) - put (write) | |
529 | * RCV(0) - get (read) | |
530 | */ | |
531 | unsigned int is_cnt) | |
532 | { /* 1 - this is a restart, don't check MBB | |
533 | * 0 - this is a new start | |
534 | */ | |
535 | unsigned int tmp = 0; | |
536 | I2C_STAT stat; | |
537 | I2C_CTRL ctrl; | |
538 | ||
539 | #ifdef I2CDBG0 | |
540 | PRINT ("%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__, | |
541 | __LINE__, slave_addr, mode, is_cnt); | |
542 | #endif | |
543 | ||
544 | ctrl = I2C_Get_Ctrl (eumbbar); | |
545 | ||
546 | /* first make sure I2C has been initialized */ | |
547 | if (ctrl.men == 0) { | |
548 | return I2CERROR; | |
549 | } | |
550 | ||
551 | /* next make sure bus is idle */ | |
552 | stat = I2C_Get_Stat (eumbbar); | |
553 | ||
554 | if (is_cnt == 0 && stat.mbb == 1) { | |
555 | /* sorry, we lost */ | |
556 | return I2CBUSBUSY; | |
557 | } else if (is_cnt == 1 && stat.mif == 1 && stat.mal == 0) { | |
558 | /* sorry, we lost the bus */ | |
559 | return I2CALOSS; | |
560 | } | |
561 | ||
562 | ||
563 | /* OK, I2C is enabled and we have the bus */ | |
564 | ||
565 | /* prepare to write the slave address */ | |
566 | ctrl.msta = 1; | |
567 | ctrl.mtx = 1; | |
568 | ctrl.txak = 0; | |
569 | ctrl.rsta = is_cnt; /* set the repeat start bit */ | |
570 | I2C_Set_Ctrl (eumbbar, ctrl); | |
571 | ||
572 | /* write the slave address and xmit/rcv mode bit */ | |
573 | tmp = load_runtime_reg (eumbbar, I2CDR); | |
574 | tmp = (tmp & 0xffffff00) | | |
575 | ((slave_addr & 0x007f) << 1) | | |
576 | (mode == XMIT ? 0x0 : 0x1); | |
577 | store_runtime_reg (eumbbar, I2CDR, tmp); | |
578 | ||
579 | if (mode == RCV) { | |
580 | MasterRcvAddress = 1; | |
581 | } else { | |
582 | MasterRcvAddress = 0; | |
583 | } | |
584 | ||
585 | #ifdef I2CDBG0 | |
586 | PRINT ("%s(%d): I2C_Start exit\n", __FILE__, __LINE__); | |
587 | #endif | |
588 | ||
589 | /* wait for the interrupt or poll */ | |
590 | return I2CSUCCESS; | |
591 | } | |
592 | ||
593 | /*********************************************************** | |
594 | * function: I2c_Stop | |
595 | * | |
596 | * description: Generate a STOP signal to terminate the master | |
3595ac49 WD |
597 | * transaction. |
598 | * return I2CSUCCESS | |
c609719b WD |
599 | * |
600 | **********************************************************/ | |
601 | static I2CStatus I2C_Stop (unsigned int eumbbar) | |
602 | { | |
603 | I2C_CTRL ctrl; | |
604 | ||
605 | #ifdef I2CDBG0 | |
606 | PRINT ("%s(%d): I2C_Stop enter\n", __FILE__, __LINE__); | |
607 | #endif | |
608 | ||
609 | ctrl = I2C_Get_Ctrl (eumbbar); | |
610 | ctrl.msta = 0; | |
611 | I2C_Set_Ctrl (eumbbar, ctrl); | |
612 | ||
613 | #ifdef I2CDBG0 | |
614 | PRINT ("%s(%d): I2C_Stop exit\n", __FILE__, __LINE__); | |
615 | #endif | |
616 | ||
617 | return I2CSUCCESS; | |
618 | } | |
619 | ||
620 | /**************************************************** | |
621 | * function: I2C_Master_Xmit | |
622 | * | |
623 | * description: Master sends one byte of data to | |
3595ac49 | 624 | * slave target |
c609719b | 625 | * |
3595ac49 WD |
626 | * return I2CSUCCESS if the byte transmitted. |
627 | * Otherwise no-zero | |
c609719b WD |
628 | * |
629 | * Note: condition must meet when this function is called: | |
630 | * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) == 0 | |
631 | * I2CCR(MSTA) == 1 && I2CCR(MTX) == 1 | |
632 | * | |
633 | ***************************************************/ | |
634 | static I2CStatus I2C_Master_Xmit (unsigned int eumbbar) | |
635 | { | |
636 | unsigned int val; | |
637 | ||
638 | if (ByteToXmit > 0) { | |
639 | ||
640 | if (ByteToXmit == XmitByte) { | |
641 | /* all xmitted */ | |
642 | ByteToXmit = 0; | |
643 | ||
644 | if (XmitBufEmptyStop == 1) { | |
645 | I2C_Stop (eumbbar); | |
646 | } | |
647 | ||
648 | return I2CBUFFEMPTY; | |
649 | ||
650 | } | |
651 | #ifdef I2CDBG0 | |
652 | PRINT ("%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, | |
653 | *(XmitBuf + XmitByte)); | |
654 | #endif | |
655 | ||
656 | val = *(XmitBuf + XmitByte); | |
657 | val &= 0x000000ff; | |
658 | store_runtime_reg (eumbbar, I2CDR, val); | |
659 | XmitByte++; | |
660 | ||
661 | return I2CSUCCESS; | |
662 | ||
663 | } | |
664 | ||
665 | return I2CBUFFEMPTY; | |
666 | } | |
667 | ||
668 | /*********************************************** | |
669 | * function: I2C_Master_Rcv | |
670 | * | |
671 | * description: master reads one byte data | |
3595ac49 | 672 | * from slave source |
c609719b | 673 | * |
3595ac49 | 674 | * return I2CSUCCESS if no error |
c609719b WD |
675 | * |
676 | * Note: condition must meet when this function is called: | |
677 | * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && | |
678 | * I2CCR(MSTA) == 1 && I2CCR(MTX) == 0 | |
679 | * | |
680 | ***********************************************/ | |
681 | static I2CStatus I2C_Master_Rcv (unsigned int eumbbar) | |
682 | { | |
683 | I2C_CTRL ctrl; | |
684 | unsigned int val; | |
685 | ||
686 | if (ByteToRcv > 0) { | |
687 | ||
688 | if (ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1) { | |
689 | /* master requests more than or equal to 2 bytes | |
690 | * we are reading 2nd to last byte | |
691 | */ | |
692 | ||
693 | /* we need to set I2CCR(TXAK) to generate a STOP */ | |
694 | ctrl = I2C_Get_Ctrl (eumbbar); | |
695 | ctrl.txak = 1; | |
696 | I2C_Set_Ctrl (eumbbar, ctrl); | |
697 | ||
698 | /* Kahlua will automatically generate a STOP | |
699 | * next time a transaction happens | |
700 | */ | |
701 | ||
702 | /* note: the case of master requesting one byte is | |
703 | * handled in I2C_ISR | |
704 | */ | |
705 | } | |
706 | ||
707 | /* generat a STOP before reading the last byte */ | |
708 | if (RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1) { | |
709 | I2C_Stop (eumbbar); | |
710 | } | |
711 | ||
712 | val = load_runtime_reg (eumbbar, I2CDR); | |
713 | *(RcvBuf + RcvByte) = val & 0xFF; | |
714 | ||
715 | #ifdef I2CDBG0 | |
716 | PRINT ("%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, | |
717 | *(RcvBuf + RcvByte)); | |
718 | #endif | |
719 | ||
720 | RcvByte++; | |
721 | ||
722 | if (ByteToRcv == RcvByte) { | |
723 | ByteToRcv = 0; | |
724 | ||
725 | return I2CBUFFFULL; | |
726 | } | |
727 | ||
728 | return I2CSUCCESS; | |
729 | } | |
730 | ||
731 | return I2CBUFFFULL; | |
732 | ||
733 | } | |
734 | ||
735 | /**************************************************** | |
736 | * function: I2C_Slave_Xmit | |
737 | * | |
738 | * description: Slave sends one byte of data to | |
3595ac49 | 739 | * requesting destination |
c609719b | 740 | * |
3595ac49 WD |
741 | * return SUCCESS if the byte transmitted. Otherwise |
742 | * No-zero | |
c609719b WD |
743 | * |
744 | * Note: condition must meet when this function is called: | |
745 | * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) = 0 | |
746 | * I2CCR(MSTA) == 0 && I2CCR(MTX) == 1 | |
747 | * | |
748 | ***************************************************/ | |
749 | static I2CStatus I2C_Slave_Xmit (unsigned int eumbbar) | |
750 | { | |
751 | unsigned int val; | |
752 | ||
753 | if (ByteToXmit > 0) { | |
754 | ||
755 | if (ByteToXmit == XmitByte) { | |
756 | /* no more data to send */ | |
757 | ByteToXmit = 0; | |
758 | ||
759 | /* | |
3595ac49 WD |
760 | * do not toggle I2CCR(MTX). Doing so will |
761 | * cause bus-hung since current Kahlua design | |
762 | * does not give master a way to detect slave | |
763 | * stop. It is always a good idea for master | |
764 | * to use timer to prevent the long long | |
765 | * delays | |
c609719b WD |
766 | */ |
767 | ||
768 | return I2CBUFFEMPTY; | |
769 | } | |
770 | #ifdef I2CDBG | |
771 | PRINT ("%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, | |
772 | *(XmitBuf + XmitByte)); | |
773 | #endif | |
774 | ||
775 | val = *(XmitBuf + XmitByte); | |
776 | val &= 0x000000ff; | |
777 | store_runtime_reg (eumbbar, I2CDR, val); | |
778 | XmitByte++; | |
779 | ||
780 | return I2CSUCCESS; | |
781 | } | |
782 | ||
783 | return I2CBUFFEMPTY; | |
784 | } | |
785 | ||
786 | /*********************************************** | |
787 | * function: I2C_Slave_Rcv | |
788 | * | |
789 | * description: slave reads one byte data | |
3595ac49 | 790 | * from master source |
c609719b | 791 | * |
3595ac49 | 792 | * return I2CSUCCESS if no error otherwise non-zero |
c609719b WD |
793 | * |
794 | * Note: condition must meet when this function is called: | |
795 | * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && | |
796 | * I2CCR(MSTA) == 0 && I2CCR(MTX) = 0 | |
797 | * | |
798 | ***********************************************/ | |
799 | static I2CStatus I2C_Slave_Rcv (unsigned int eumbbar) | |
800 | { | |
801 | unsigned int val; | |
802 | I2C_CTRL ctrl; | |
803 | ||
804 | if (ByteToRcv > 0) { | |
805 | val = load_runtime_reg (eumbbar, I2CDR); | |
806 | *(RcvBuf + RcvByte) = val & 0xff; | |
807 | #ifdef I2CDBG | |
808 | PRINT ("%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, | |
809 | *(RcvBuf + RcvByte)); | |
810 | #endif | |
811 | RcvByte++; | |
812 | ||
813 | if (ByteToRcv == RcvByte) { | |
814 | if (RcvBufFulStop == 1) { | |
815 | /* all done */ | |
816 | ctrl = I2C_Get_Ctrl (eumbbar); | |
817 | ctrl.txak = 1; | |
818 | I2C_Set_Ctrl (eumbbar, ctrl); | |
819 | } | |
820 | ||
821 | ByteToRcv = 0; | |
822 | return I2CBUFFFULL; | |
823 | } | |
824 | ||
825 | return I2CSUCCESS; | |
826 | } | |
827 | ||
828 | return I2CBUFFFULL; | |
829 | } | |
830 | ||
831 | /****************** Device Control Function *************/ | |
832 | ||
833 | /********************************************************* | |
834 | * function: I2C_Init | |
835 | * | |
836 | * description: Initialize I2C unit with desired frequency divider, | |
3595ac49 WD |
837 | * master's listening address, with interrupt enabled |
838 | * or disabled. | |
c609719b WD |
839 | * |
840 | * note: | |
841 | ********************************************************/ | |
842 | static I2CStatus I2C_Init (unsigned int eumbbar, unsigned char fdr, /* frequency divider */ | |
843 | unsigned char slave_addr, /* driver's address used for receiving */ | |
844 | unsigned int en_int) | |
845 | { /* 1 - enable I2C interrupt | |
846 | * 0 - disable I2C interrup | |
847 | */ | |
848 | I2C_CTRL ctrl; | |
849 | unsigned int tmp; | |
850 | ||
851 | #ifdef I2CDBG0 | |
852 | PRINT ("%s(%d): I2C_Init enter\n", __FILE__, __LINE__); | |
853 | #endif | |
854 | ||
855 | ctrl = I2C_Get_Ctrl (eumbbar); | |
856 | /* disable the I2C module before we change everything */ | |
857 | ctrl.men = 0; | |
858 | I2C_Set_Ctrl (eumbbar, ctrl); | |
859 | ||
860 | /* set the frequency diver */ | |
861 | tmp = load_runtime_reg (eumbbar, I2CFDR); | |
862 | tmp = (tmp & 0xffffffc0) | (fdr & 0x3f); | |
863 | store_runtime_reg (eumbbar, I2CFDR, tmp); | |
864 | ||
865 | /* Set our listening (slave) address */ | |
866 | tmp = load_runtime_reg (eumbbar, I2CADR); | |
867 | tmp = (tmp & 0xffffff01) | ((slave_addr & 0x7f) << 1); | |
868 | store_runtime_reg (eumbbar, I2CADR, tmp); | |
869 | ||
870 | /* enable I2C with desired interrupt setting */ | |
871 | ctrl.men = 1; | |
872 | ctrl.mien = en_int & 0x1; | |
873 | I2C_Set_Ctrl (eumbbar, ctrl); | |
874 | #ifdef I2CDBG0 | |
875 | PRINT ("%s(%d): I2C_Init exit\n", __FILE__, __LINE__); | |
876 | #endif | |
877 | ||
878 | return I2CSUCCESS; | |
879 | ||
880 | } | |
881 | ||
882 | /***************************************** | |
883 | * function I2c_Get_Stat | |
884 | * | |
885 | * description: Query I2C Status, i.e., read I2CSR | |
886 | * | |
887 | ****************************************/ | |
888 | static I2C_STAT I2C_Get_Stat (unsigned int eumbbar) | |
889 | { | |
890 | unsigned int temp; | |
891 | I2C_STAT stat; | |
892 | ||
893 | temp = load_runtime_reg (eumbbar, I2CSR); | |
894 | ||
895 | #ifdef I2CDBG0 | |
896 | PRINT ("%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp); | |
897 | #endif | |
898 | ||
899 | stat.rsrv0 = (temp & 0xffffff00) >> 8; | |
900 | stat.mcf = (temp & 0x00000080) >> 7; | |
901 | stat.maas = (temp & 0x00000040) >> 6; | |
902 | stat.mbb = (temp & 0x00000020) >> 5; | |
903 | stat.mal = (temp & 0x00000010) >> 4; | |
904 | stat.rsrv1 = (temp & 0x00000008) >> 3; | |
905 | stat.srw = (temp & 0x00000004) >> 2; | |
906 | stat.mif = (temp & 0x00000002) >> 1; | |
907 | stat.rxak = (temp & 0x00000001); | |
908 | return stat; | |
909 | } | |
910 | ||
911 | /********************************************* | |
912 | * function: I2c_Set_Ctrl | |
913 | * | |
914 | * description: Change I2C Control bits, | |
3595ac49 | 915 | * i.e., write to I2CCR |
c609719b WD |
916 | * |
917 | ********************************************/ | |
918 | static void I2C_Set_Ctrl (unsigned int eumbbar, I2C_CTRL ctrl) | |
919 | { /* new control value */ | |
920 | unsigned int temp = load_runtime_reg (eumbbar, I2CCR); | |
921 | ||
922 | temp &= 0xffffff03; | |
923 | temp |= ((ctrl.men & 0x1) << 7); | |
924 | temp |= ((ctrl.mien & 0x1) << 6); | |
925 | temp |= ((ctrl.msta & 0x1) << 5); | |
926 | temp |= ((ctrl.mtx & 0x1) << 4); | |
927 | temp |= ((ctrl.txak & 0x1) << 3); | |
928 | temp |= ((ctrl.rsta & 0x1) << 2); | |
929 | #ifdef I2CDBG0 | |
930 | PRINT ("%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp); | |
931 | #endif | |
932 | store_runtime_reg (eumbbar, I2CCR, temp); | |
933 | ||
934 | } | |
935 | ||
936 | /***************************************** | |
937 | * function: I2C_Get_Ctrl | |
938 | * | |
939 | * description: Query I2C Control bits, | |
3595ac49 | 940 | * i.e., read I2CCR |
c609719b WD |
941 | *****************************************/ |
942 | static I2C_CTRL I2C_Get_Ctrl (unsigned int eumbbar) | |
943 | { | |
944 | union { | |
945 | I2C_CTRL ctrl; | |
946 | unsigned int temp; | |
947 | } s; | |
948 | ||
949 | s.temp = load_runtime_reg (eumbbar, I2CCR); | |
950 | #ifdef I2CDBG0 | |
951 | PRINT ("%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp); | |
952 | #endif | |
953 | ||
954 | return s.ctrl; | |
955 | } | |
956 | ||
957 | ||
958 | /**************************************** | |
959 | * function: I2C_Slave_Addr | |
960 | * | |
961 | * description: Process slave address phase. | |
3595ac49 | 962 | * return I2CSUCCESS if no error |
c609719b WD |
963 | * |
964 | * note: Precondition for calling this function: | |
965 | * I2CSR(MIF) == 1 && | |
966 | * I2CSR(MAAS) == 1 | |
967 | ****************************************/ | |
968 | static I2CStatus I2C_Slave_Addr (unsigned int eumbbar) | |
969 | { | |
970 | I2C_STAT stat = I2C_Get_Stat (eumbbar); | |
971 | I2C_CTRL ctrl = I2C_Get_Ctrl (eumbbar); | |
972 | ||
973 | if (stat.srw == 1) { | |
974 | /* we are asked to xmit */ | |
975 | ctrl.mtx = 1; | |
976 | I2C_Set_Ctrl (eumbbar, ctrl); /* set MTX */ | |
977 | return I2C_Slave_Xmit (eumbbar); | |
978 | } | |
979 | ||
980 | /* we are asked to receive data */ | |
981 | ctrl.mtx = 0; | |
982 | I2C_Set_Ctrl (eumbbar, ctrl); | |
983 | (void) load_runtime_reg (eumbbar, I2CDR); /* do a fake read to start */ | |
984 | ||
985 | return I2CADDRESS; | |
986 | } | |
987 | ||
988 | /*********************************************** | |
989 | * function: I2C_ISR | |
990 | * | |
991 | * description: I2C Interrupt service routine | |
992 | * | |
993 | * note: Precondition: | |
994 | * I2CSR(MIF) == 1 | |
995 | **********************************************/ | |
996 | static I2CStatus I2C_ISR (unsigned int eumbbar) | |
997 | { | |
998 | I2C_STAT stat; | |
999 | I2C_CTRL ctrl; | |
1000 | ||
1001 | #ifdef I2CDBG0 | |
1002 | PRINT ("%s(%d): I2C_ISR\n", __FILE__, __LINE__); | |
1003 | #endif | |
1004 | ||
1005 | stat = I2C_Get_Stat (eumbbar); | |
1006 | ctrl = I2C_Get_Ctrl (eumbbar); | |
1007 | ||
1008 | /* clear MIF */ | |
1009 | stat.mif = 0; | |
1010 | ||
1011 | /* Now let see what kind of event this is */ | |
1012 | if (stat.mcf == 1) { | |
1013 | /* transfer compete */ | |
1014 | ||
1015 | /* clear the MIF bit */ | |
1016 | I2C_Set_Stat (eumbbar, stat); | |
1017 | ||
1018 | if (ctrl.msta == 1) { | |
1019 | /* master */ | |
1020 | if (ctrl.mtx == 1) { | |
1021 | /* check if this is the address phase for master receive */ | |
1022 | if (MasterRcvAddress == 1) { | |
1023 | /* Yes, it is the address phase of master receive */ | |
1024 | ctrl.mtx = 0; | |
1025 | /* now check how much we want to receive */ | |
1026 | if (ByteToRcv == 1 && RcvBufFulStop == 1) { | |
1027 | ctrl.txak = 1; | |
1028 | } | |
1029 | ||
1030 | I2C_Set_Ctrl (eumbbar, ctrl); | |
1031 | (void) load_runtime_reg (eumbbar, I2CDR); /* fake read first */ | |
1032 | ||
1033 | MasterRcvAddress = 0; | |
1034 | return I2CADDRESS; | |
1035 | ||
1036 | } | |
1037 | ||
1038 | /* master xmit */ | |
1039 | if (stat.rxak == 0) { | |
1040 | /* slave has acknowledged */ | |
1041 | return I2C_Master_Xmit (eumbbar); | |
1042 | } | |
1043 | ||
1044 | /* slave has not acknowledged yet, generate a STOP */ | |
1045 | if (XmitBufEmptyStop == 1) { | |
1046 | ctrl.msta = 0; | |
1047 | I2C_Set_Ctrl (eumbbar, ctrl); | |
1048 | } | |
1049 | ||
1050 | return I2CSUCCESS; | |
1051 | } | |
1052 | ||
1053 | /* master receive */ | |
1054 | return I2C_Master_Rcv (eumbbar); | |
1055 | } | |
1056 | ||
1057 | /* slave */ | |
1058 | if (ctrl.mtx == 1) { | |
1059 | /* slave xmit */ | |
1060 | if (stat.rxak == 0) { | |
1061 | /* master has acknowledged */ | |
1062 | return I2C_Slave_Xmit (eumbbar); | |
1063 | } | |
1064 | ||
1065 | /* master has not acknowledged, wait for STOP */ | |
1066 | /* do nothing for preventing bus from hung */ | |
1067 | return I2CSUCCESS; | |
1068 | } | |
1069 | ||
1070 | /* slave rcv */ | |
1071 | return I2C_Slave_Rcv (eumbbar); | |
1072 | ||
1073 | } else if (stat.maas == 1) { | |
1074 | /* received a call from master */ | |
1075 | ||
1076 | /* clear the MIF bit */ | |
1077 | I2C_Set_Stat (eumbbar, stat); | |
1078 | ||
1079 | /* master is calling us, process the address phase */ | |
1080 | return I2C_Slave_Addr (eumbbar); | |
1081 | } else { | |
1082 | /* has to be arbitration lost */ | |
1083 | stat.mal = 0; | |
1084 | I2C_Set_Stat (eumbbar, stat); | |
1085 | ||
1086 | ctrl.msta = 0; /* return to receive mode */ | |
1087 | I2C_Set_Ctrl (eumbbar, ctrl); | |
1088 | } | |
1089 | ||
1090 | return I2CSUCCESS; | |
1091 | ||
1092 | } | |
1093 | ||
1094 | /****************************************************** | |
1095 | * function: I2C_Set_Stat | |
1096 | * | |
1097 | * description: modify the I2CSR | |
1098 | * | |
1099 | *****************************************************/ | |
1100 | static void I2C_Set_Stat (unsigned int eumbbar, I2C_STAT stat) | |
1101 | { | |
1102 | union { | |
1103 | unsigned int val; | |
1104 | I2C_STAT stat; | |
1105 | } s_tmp; | |
1106 | union { | |
1107 | unsigned int val; | |
1108 | I2C_STAT stat; | |
1109 | } s; | |
1110 | ||
1111 | s.val = load_runtime_reg (eumbbar, I2CSR); | |
1112 | s.val &= 0xffffff08; | |
1113 | s_tmp.stat = stat; | |
1114 | s.val |= (s_tmp.val & 0xf7); | |
1115 | ||
1116 | #ifdef I2CDBG0 | |
1117 | PRINT ("%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val); | |
1118 | #endif | |
1119 | ||
1120 | store_runtime_reg (eumbbar, I2CSR, s.val); | |
1121 | ||
1122 | } | |
1123 | ||
1124 | /****************************************************** | |
1125 | * The following are routines to glue the rest of | |
1126 | * U-Boot to the Sandpoint I2C driver. | |
1127 | *****************************************************/ | |
1128 | ||
1129 | void i2c_init (int speed, int slaveadd) | |
1130 | { | |
47cd00fa WD |
1131 | #ifdef CFG_I2C_INIT_BOARD |
1132 | /* | |
1133 | * call board specific i2c bus reset routine before accessing the | |
1134 | * environment, which might be in a chip on that bus. For details | |
1135 | * about this problem see doc/I2C_Edge_Conditions. | |
1136 | */ | |
1137 | i2c_init_board(); | |
1138 | #endif | |
1139 | ||
c609719b WD |
1140 | #ifdef DEBUG |
1141 | I2C_Initialize (0x7f, 0, (void *) printf); | |
1142 | #else | |
1143 | I2C_Initialize (0x7f, 0, 0); | |
1144 | #endif | |
1145 | } | |
1146 | ||
1147 | int i2c_probe (uchar chip) | |
1148 | { | |
1149 | int tmp; | |
1150 | ||
1151 | /* | |
1152 | * Try to read the first location of the chip. The underlying | |
1153 | * driver doesn't appear to support sending just the chip address | |
1154 | * and looking for an <ACK> back. | |
1155 | */ | |
1156 | udelay(10000); | |
1157 | return i2c_read (chip, 0, 1, (char *)&tmp, 1); | |
1158 | } | |
1159 | ||
1160 | int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) | |
1161 | { | |
1162 | I2CStatus status; | |
1163 | uchar xaddr[4]; | |
1164 | ||
1165 | if (alen > 0) { | |
1166 | xaddr[0] = (addr >> 24) & 0xFF; | |
1167 | xaddr[1] = (addr >> 16) & 0xFF; | |
1168 | xaddr[2] = (addr >> 8) & 0xFF; | |
1169 | xaddr[3] = addr & 0xFF; | |
1170 | ||
1171 | status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen, | |
1172 | &xaddr[4 - alen], I2C_NO_STOP, 1, | |
1173 | I2C_NO_RESTART); | |
1174 | if (status != I2C_SUCCESS) { | |
1175 | PRINT ("i2c_read: can't send data address for read\n"); | |
1176 | return 1; | |
1177 | } | |
1178 | } | |
1179 | ||
1180 | /* The data transfer will be a continuation. */ | |
1181 | status = I2C_do_buffer (0, I2C_MASTER_RCV, chip, len, | |
1182 | buffer, I2C_STOP, 1, (alen > 0 ? I2C_RESTART : | |
1183 | I2C_NO_RESTART)); | |
1184 | ||
1185 | if (status != I2C_SUCCESS) { | |
1186 | PRINT ("i2c_read: can't perform data transfer\n"); | |
1187 | return 1; | |
1188 | } | |
1189 | ||
1190 | return 0; | |
1191 | } | |
1192 | ||
1193 | int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) | |
1194 | { | |
1195 | I2CStatus status; | |
3595ac49 WD |
1196 | uchar dummy_buffer[I2C_RXTX_LEN + 2]; |
1197 | uchar *p; | |
c609719b WD |
1198 | int i; |
1199 | ||
3595ac49 | 1200 | /* fill in address in big endian order */ |
27b207fd WD |
1201 | for (i=alen-1; i>=0; --i) { |
1202 | buffer[i] = addr & 0xFF; | |
1203 | addr >>= 8; | |
1204 | } | |
3595ac49 | 1205 | /* fill in data */ |
27b207fd WD |
1206 | p = dummy_buffer + alen; |
1207 | ||
3595ac49 | 1208 | for (i=0; i<len; ++i) |
27b207fd | 1209 | *p++ = *buffer++; |
c609719b WD |
1210 | |
1211 | status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen + len, | |
1212 | dummy_buffer, I2C_STOP, 1, I2C_NO_RESTART); | |
1213 | ||
1214 | #ifdef CFG_EEPROM_PAGE_WRITE_DELAY_MS | |
1215 | udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000); | |
1216 | #endif | |
1217 | if (status != I2C_SUCCESS) { | |
1218 | PRINT ("i2c_write: can't perform data transfer\n"); | |
1219 | return 1; | |
1220 | } | |
1221 | ||
1222 | return 0; | |
1223 | } | |
1224 | ||
1225 | uchar i2c_reg_read (uchar i2c_addr, uchar reg) | |
1226 | { | |
1227 | char buf[1]; | |
1228 | ||
1229 | i2c_init (0, 0); | |
1230 | ||
1231 | i2c_read (i2c_addr, reg, 1, buf, 1); | |
1232 | ||
1233 | return (buf[0]); | |
1234 | } | |
1235 | ||
1236 | void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val) | |
1237 | { | |
1238 | i2c_init (0, 0); | |
1239 | ||
1240 | i2c_write (i2c_addr, reg, 1, &val, 1); | |
1241 | } | |
1242 | ||
1243 | #endif /* CONFIG_HARD_I2C */ |