source: rtems/c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c @ db01d0c

4.115
Last change on this file since db01d0c was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 25.9 KB
Line 
1/*===============================================================*\
2| Project: RTEMS support for MPC83xx                              |
3+-----------------------------------------------------------------+
4|                    Copyright (c) 2007                           |
5|                    Embedded Brains GmbH                         |
6|                    Obere Lagerstr. 30                           |
7|                    D-82178 Puchheim                             |
8|                    Germany                                      |
9|                    rtems@embedded-brains.de                     |
10+-----------------------------------------------------------------+
11| The license and distribution terms for this file may be         |
12| found in the file LICENSE in this distribution or at            |
13|                                                                 |
14| http://www.rtems.org/license/LICENSE.                           |
15|                                                                 |
16+-----------------------------------------------------------------+
17| this file contains the MPC83xx I2C driver                       |
18\*===============================================================*/
19#include <stdlib.h>
20#include <bsp.h>
21#include <bsp/irq.h>
22#if defined(__GEN83xx_BSP_h)
23  #include <mpc83xx/mpc83xx_i2cdrv.h>
24#elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
25  #include <bsp/mpc83xx_i2cdrv.h>
26#endif
27#include <rtems/error.h>
28#include <rtems/bspIo.h>
29#include <errno.h>
30#include <rtems/libi2c.h>
31
32#undef DEBUG
33
34#if defined(__GEN83xx_BSP_h)
35  #define I2CCR_MEN  (1 << 7)   /* module enable */
36#elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
37  #define I2CCR_MDIS (1 << 7)   /* module disable */
38#endif
39#define I2CCR_MIEN (1 << 6)     /* module interrupt enable */
40#define I2CCR_MSTA (1 << 5)     /* 0->1 generates a start condiiton, 1->0 a stop */
41#define I2CCR_MTX  (1 << 4)     /* 0 = receive mode, 1 = transmit mode           */
42#define I2CCR_TXAK (1 << 3)     /* 0 = send ack 1 = send nak during receive      */
43#define I2CCR_RSTA (1 << 2)     /* 1 = send repeated start condition             */
44#define I2CCR_BCST (1 << 0)     /* 0 = disable 1 = enable broadcast accept       */
45
46#define I2CSR_MCF  (1 << 7)     /* data transfer (0=transfer in progres) */
47#define I2CSR_MAAS (1 << 6)     /* addessed as slave   */
48#define I2CSR_MBB  (1 << 5)     /* bus busy            */
49#define I2CSR_MAL  (1 << 4)     /* arbitration lost    */
50#define I2CSR_BCSTM (1 << 3)    /* broadcast match     */
51#define I2CSR_SRW  (1 << 2)     /* slave read/write    */
52#define I2CSR_MIF  (1 << 1)     /* module interrupt    */
53#define I2CSR_RXAK (1 << 0)     /* receive acknowledge */
54
55/*=========================================================================*\
56| Function:                                                                 |
57\*-------------------------------------------------------------------------*/
58static rtems_status_code mpc83xx_i2c_find_clock_divider
59(
60/*-------------------------------------------------------------------------*\
61| Purpose:                                                                  |
62|   determine proper divider value                                          |
63+---------------------------------------------------------------------------+
64| Input Parameters:                                                         |
65\*-------------------------------------------------------------------------*/
66 uint8_t *result,                        /* result value                   */
67 int divider                             /* requested divider              */
68)
69/*-------------------------------------------------------------------------*\
70| Return Value:                                                             |
71|    o = ok or error code                                                   |
72\*=========================================================================*/
73{
74  int i;
75  int fdr_val;
76  rtems_status_code sc = RTEMS_SUCCESSFUL;
77  struct {
78    int divider;
79    int fdr_val;
80  } dividers[] ={
81#if defined(__GEN83xx_BSP_h)
82    {  256,0x20 }, {  288,0x21 }, {  320,0x22 }, {  352,0x23 },
83    {  384,0x00 }, {  416,0x01 }, {  448,0x25 }, {  480,0x02 },
84    {  512,0x26 }, {  576,0x03 }, {  640,0x04 }, {  704,0x05 },
85    {  768,0x29 }, {  832,0x06 }, {  896,0x2a }, { 1024,0x07 },
86    { 1152,0x08 }, { 1280,0x09 }, { 1536,0x0A }, { 1792,0x2E },
87    { 1920,0x0B }, { 2048,0x2F }, { 2304,0x0C }, { 2560,0x0D },
88    { 3072,0x0E }, { 3584,0x32 }, { 3840,0x0F }, { 4096,0x33 },
89    { 4608,0x10 }, { 5120,0x11 }, { 6144,0x12 }, { 7168,0x36 },
90    { 7680,0x13 }, { 8192,0x37 }, { 9216,0x14 }, {10240,0x15 },
91    {12288,0x16 }, {14336,0x3A }, {15360,0x17 }, {16384,0x3B },
92    {18432,0x18 }, {20480,0x19 }, {24576,0x1A }, {28672,0x3E },
93    {30720,0x1B }, {32768,0x3F }, {36864,0x1C }, {40960,0x1D },
94    {49152,0x1E }, {61440,0x1F }
95#elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
96    { 768, 0x31 }
97#endif
98  };
99
100  if (divider <= 0) {
101    sc = RTEMS_INVALID_NUMBER;
102  }
103
104  if (sc == RTEMS_SUCCESSFUL) {
105    sc = RTEMS_INVALID_NUMBER;
106    for (i = 0, fdr_val = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++) {
107      fdr_val = dividers[i].fdr_val;
108      if (dividers[i].divider >= divider)
109        {
110          sc = RTEMS_SUCCESSFUL;
111          *result = fdr_val;
112          break;
113        }
114    }
115  }
116  return sc;
117}
118
119/*=========================================================================*\
120| Function:                                                                 |
121\*-------------------------------------------------------------------------*/
122static int mpc83xx_i2c_wait
123(
124/*-------------------------------------------------------------------------*\
125| Purpose:                                                                  |
126|   wait for i2c to become idle                                             |
127+---------------------------------------------------------------------------+
128| Input Parameters:                                                         |
129\*-------------------------------------------------------------------------*/
130 mpc83xx_i2c_softc_t *softc_ptr,          /* handle              */
131 uint8_t              desired_status,     /* desired status word */
132 uint8_t              status_mask         /* status word mask    */
133)
134/*-------------------------------------------------------------------------*\
135| Return Value:                                                             |
136|    o = ok or error code                                                   |
137\*=========================================================================*/
138{
139  uint8_t act_status;
140  rtems_status_code rc;
141  uint32_t tout;
142
143#if defined(DEBUG)
144  printk("mpc83xx_i2c_wait called... ");
145#endif
146
147  if (softc_ptr->initialized) {
148    /*
149     * enable interrupt mask
150     */
151    softc_ptr->reg_ptr->i2ccr |= I2CCR_MIEN;
152    rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,RTEMS_WAIT,100);
153    if (rc != RTEMS_SUCCESSFUL) {
154      return rc;
155    }
156  }
157  else {
158    tout = 0;
159    do {
160      if (tout++ > 1000000) {
161#if defined(DEBUG)
162        printk("... exit with RTEMS_TIMEOUT\r\n");
163#endif
164        return RTEMS_TIMEOUT;
165      }
166    } while (!(softc_ptr->reg_ptr->i2csr & I2CSR_MIF));
167  }
168  softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MIEN;
169
170  act_status = softc_ptr->reg_ptr->i2csr;
171  if ((act_status  & status_mask) != desired_status) {
172#if defined(DEBUG)
173    printk("... exit with RTEMS_IO_ERROR\r\n");
174#endif
175    return RTEMS_IO_ERROR;
176  }
177#if defined(DEBUG)
178        printk("... exit OK\r\n");
179#endif
180  return RTEMS_SUCCESSFUL;
181}
182
183/*=========================================================================*\
184| Function:                                                                 |
185\*-------------------------------------------------------------------------*/
186static void mpc83xx_i2c_irq_handler
187(
188/*-------------------------------------------------------------------------*\
189| Purpose:                                                                  |
190|   handle interrupts                                                       |
191+---------------------------------------------------------------------------+
192| Input Parameters:                                                         |
193\*-------------------------------------------------------------------------*/
194 rtems_irq_hdl_param handle     /* handle, is softc_ptr structure          */
195)
196/*-------------------------------------------------------------------------*\
197| Return Value:                                                             |
198|    <none>                                                                 |
199\*=========================================================================*/
200{
201  mpc83xx_i2c_softc_t *softc_ptr = (mpc83xx_i2c_softc_t *)handle;
202
203  /*
204   * clear IRQ flag
205   */
206  #if defined(__GEN83xx_BSP_h)
207    softc_ptr->reg_ptr->i2csr &= ~I2CSR_MIF;
208  #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
209    softc_ptr->reg_ptr->i2csr = I2CSR_MIF;
210  #endif
211
212  /*
213   * disable interrupt mask
214   */
215  softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MIEN;
216  if (softc_ptr->initialized) {
217    rtems_semaphore_release(softc_ptr->irq_sema_id);
218  }
219}
220
221/*=========================================================================*\
222| Function:                                                                 |
223\*-------------------------------------------------------------------------*/
224static void mpc83xx_i2c_irq_on_off
225(
226/*-------------------------------------------------------------------------*\
227| Purpose:                                                                  |
228|   enable/disable interrupts (void, handled at different position)         |
229+---------------------------------------------------------------------------+
230| Input Parameters:                                                         |
231\*-------------------------------------------------------------------------*/
232 const
233 rtems_irq_connect_data *irq_conn_data   /* irq connect data                */
234)
235/*-------------------------------------------------------------------------*\
236| Return Value:                                                             |
237|    <none>                                                                 |
238\*=========================================================================*/
239{
240}
241
242
243/*=========================================================================*\
244| Function:                                                                 |
245\*-------------------------------------------------------------------------*/
246static int mpc83xx_i2c_irq_isOn
247(
248/*-------------------------------------------------------------------------*\
249| Purpose:                                                                  |
250|   check state of interrupts, void, done differently                       |
251+---------------------------------------------------------------------------+
252| Input Parameters:                                                         |
253\*-------------------------------------------------------------------------*/
254 const
255 rtems_irq_connect_data *irq_conn_data  /* irq connect data                */
256)
257/*-------------------------------------------------------------------------*\
258| Return Value:                                                             |
259|    TRUE, if enabled                                                       |
260\*=========================================================================*/
261{
262  return (TRUE);
263}
264
265/*=========================================================================*\
266| Function:                                                                 |
267\*-------------------------------------------------------------------------*/
268static void mpc83xx_i2c_install_irq_handler
269(
270/*-------------------------------------------------------------------------*\
271| Purpose:                                                                  |
272|   (un-)install the interrupt handler                                      |
273+---------------------------------------------------------------------------+
274| Input Parameters:                                                         |
275\*-------------------------------------------------------------------------*/
276 mpc83xx_i2c_softc_t *softc_ptr,        /* ptr to control structure        */
277 int install                            /* TRUE: install, FALSE: remove    */
278)
279/*-------------------------------------------------------------------------*\
280| Return Value:                                                             |
281|    <none>                                                                 |
282\*=========================================================================*/
283{
284  rtems_status_code rc = RTEMS_SUCCESSFUL;
285
286  rtems_irq_connect_data irq_conn_data = {
287    softc_ptr->irq_number,
288    mpc83xx_i2c_irq_handler,           /* rtems_irq_hdl           */
289    (rtems_irq_hdl_param)softc_ptr,    /* (rtems_irq_hdl_param)   */
290    mpc83xx_i2c_irq_on_off,            /* (rtems_irq_enable)      */
291    mpc83xx_i2c_irq_on_off,            /* (rtems_irq_disable)     */
292    mpc83xx_i2c_irq_isOn               /* (rtems_irq_is_enabled)  */
293  };
294
295  /*
296   * (un-)install handler for I2C device
297   */
298  if (install) {
299    /*
300     * create semaphore for IRQ synchronization
301     */
302    rc = rtems_semaphore_create(rtems_build_name('i','2','c','s'),
303                                0,
304                                RTEMS_FIFO
305                                | RTEMS_SIMPLE_BINARY_SEMAPHORE,
306                                0,
307                                &softc_ptr->irq_sema_id);
308    if (rc != RTEMS_SUCCESSFUL) {
309      rtems_panic("I2C: cannot create semaphore");
310    }
311    if (!BSP_install_rtems_irq_handler (&irq_conn_data)) {
312      rtems_panic("I2C: cannot install IRQ handler");
313    }
314  }
315  else {
316    if (!BSP_remove_rtems_irq_handler (&irq_conn_data)) {
317      rtems_panic("I2C: cannot uninstall IRQ handler");
318    }
319    /*
320     * delete sync semaphore
321     */
322    if (softc_ptr->irq_sema_id != 0) {
323      rc = rtems_semaphore_delete(softc_ptr->irq_sema_id);
324      if (rc != RTEMS_SUCCESSFUL) {
325        rtems_panic("I2C: cannot delete semaphore");
326      }
327    }
328  }
329}
330
331/*=========================================================================*\
332| Function:                                                                 |
333\*-------------------------------------------------------------------------*/
334static rtems_status_code mpc83xx_i2c_init
335(
336/*-------------------------------------------------------------------------*\
337| Purpose:                                                                  |
338|   initialize the driver                                                   |
339+---------------------------------------------------------------------------+
340| Input Parameters:                                                         |
341\*-------------------------------------------------------------------------*/
342 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
343)
344/*-------------------------------------------------------------------------*\
345| Return Value:                                                             |
346|    o = ok or error code                                                   |
347\*=========================================================================*/
348{
349  mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
350  uint8_t fdr_val;
351  int errval;
352#if defined(DEBUG)
353  printk("mpc83xx_i2c_init called... ");
354#endif
355  /*
356   * init HW registers
357   */
358  /*
359   * init frequency divider to 100kHz
360   */
361  errval = mpc83xx_i2c_find_clock_divider(&fdr_val,
362                                          softc_ptr->base_frq/100000);
363  if (errval != 0) {
364    return errval;
365  }
366  softc_ptr->reg_ptr->i2cfdr = fdr_val;
367  /*
368   * init digital filter sampling rate
369   */
370  softc_ptr->reg_ptr->i2cdfsrr = 0x10 ; /* no special filtering needed */
371  /*
372   * set own slave address to broadcast (0x00)
373   */
374  softc_ptr->reg_ptr->i2cadr = 0x00 ;
375
376  /*
377   * set control register to module enable
378   */
379  #if defined(__GEN83xx_BSP_h)
380    softc_ptr->reg_ptr->i2ccr = I2CCR_MEN;
381  #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H)
382    softc_ptr->reg_ptr->i2ccr = 0;
383  #endif
384
385  /*
386   * init interrupt stuff
387   */
388  mpc83xx_i2c_install_irq_handler(softc_ptr,TRUE);
389
390  /*
391   * mark, that we have initialized
392   */
393  softc_ptr->initialized = TRUE;
394#if defined(DEBUG)
395  printk("... exit OK\r\n");
396#endif
397  return RTEMS_SUCCESSFUL;
398}
399
400/*=========================================================================*\
401| Function:                                                                 |
402\*-------------------------------------------------------------------------*/
403static rtems_status_code mpc83xx_i2c_send_start
404(
405/*-------------------------------------------------------------------------*\
406| Purpose:                                                                  |
407|   send a start condition to bus                                           |
408+---------------------------------------------------------------------------+
409| Input Parameters:                                                         |
410\*-------------------------------------------------------------------------*/
411 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
412)
413/*-------------------------------------------------------------------------*\
414| Return Value:                                                             |
415|    o = ok or error code                                                   |
416\*=========================================================================*/
417{
418  mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
419
420#if defined(DEBUG)
421  printk("mpc83xx_i2c_send_start called... ");
422#endif
423  if (0 != (softc_ptr->reg_ptr->i2ccr & I2CCR_MSTA)) {
424    /*
425     * already started, so send a "repeated start"
426     */
427    softc_ptr->reg_ptr->i2ccr |= I2CCR_RSTA;
428  }
429  else {
430    softc_ptr->reg_ptr->i2ccr |= I2CCR_MSTA;
431  }
432
433#if defined(DEBUG)
434  printk("... exit OK\r\n");
435#endif
436  return 0;
437}
438
439/*=========================================================================*\
440| Function:                                                                 |
441\*-------------------------------------------------------------------------*/
442static rtems_status_code mpc83xx_i2c_send_stop
443(
444/*-------------------------------------------------------------------------*\
445| Purpose:                                                                  |
446|   send a stop condition to bus                                            |
447+---------------------------------------------------------------------------+
448| Input Parameters:                                                         |
449\*-------------------------------------------------------------------------*/
450 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
451)
452/*-------------------------------------------------------------------------*\
453| Return Value:                                                             |
454|    o = ok or error code                                                   |
455\*=========================================================================*/
456{
457  mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
458
459#if defined(DEBUG)
460  printk("mpc83xx_i2c_send_stop called... ");
461#endif
462  softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MSTA;
463  /*
464   * wait, 'til stop has been executed
465   */
466  while (0 != (softc_ptr->reg_ptr->i2csr & I2CSR_MBB)) {
467    rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
468  }
469#if defined(DEBUG)
470  printk("... exit OK\r\n");
471#endif
472  return 0;
473}
474
475/*=========================================================================*\
476| Function:                                                                 |
477\*-------------------------------------------------------------------------*/
478static rtems_status_code mpc83xx_i2c_send_addr
479(
480/*-------------------------------------------------------------------------*\
481| Purpose:                                                                  |
482|   address a slave device on the bus                                       |
483+---------------------------------------------------------------------------+
484| Input Parameters:                                                         |
485\*-------------------------------------------------------------------------*/
486 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
487 uint32_t addr,                          /* address to send on bus         */
488 int rw                                  /* 0=write,1=read                 */
489)
490/*-------------------------------------------------------------------------*\
491| Return Value:                                                             |
492|    o = ok or error code                                                   |
493\*=========================================================================*/
494{
495  mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
496  uint8_t addr_byte;
497  rtems_status_code rc;
498
499#if defined(DEBUG)
500  printk("mpc83xx_i2c_send_addr called... ");
501#endif
502  softc_ptr->reg_ptr->i2ccr |= I2CCR_MTX;
503  /*
504   * determine, whether short or long address is needed, determine rd/wr
505   */
506  if (addr > 0x7f) {
507    addr_byte = (0xf0
508                 | ((addr >> 7) & 0x06)
509                 | ((rw) ? 1 : 0));
510    /*
511     * send first byte
512     */
513    softc_ptr->reg_ptr->i2cdr = addr_byte;
514    /*
515     * wait for successful transfer
516     */
517    rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | I2CSR_RXAK);
518    if (rc != RTEMS_SUCCESSFUL) {
519#if defined(DEBUG)
520      printk("... exit rc=%d\r\n",rc);
521#endif
522      return rc;
523    }
524  }
525  /*
526   * send (final) byte
527   */
528  addr_byte = ((addr << 1)
529               | ((rw) ? 1 : 0));
530
531  softc_ptr->reg_ptr->i2cdr = addr_byte;
532  /*
533   * wait for successful transfer
534   */
535  rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | I2CSR_RXAK);
536
537#if defined(DEBUG)
538  printk("... exit rc=%d\r\n",rc);
539#endif
540  return rc;
541}
542
543/*=========================================================================*\
544| Function:                                                                 |
545\*-------------------------------------------------------------------------*/
546static int mpc83xx_i2c_read_bytes
547(
548/*-------------------------------------------------------------------------*\
549| Purpose:                                                                  |
550|   receive some bytes from I2C device                                      |
551+---------------------------------------------------------------------------+
552| Input Parameters:                                                         |
553\*-------------------------------------------------------------------------*/
554 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
555 unsigned char *buf,                     /* buffer to store bytes          */
556 int len                                 /* number of bytes to receive     */
557)
558/*-------------------------------------------------------------------------*\
559| Return Value:                                                             |
560|    number of bytes received or (negative) error code                      |
561\*=========================================================================*/
562{
563  mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
564  rtems_status_code rc;
565  unsigned char *p = buf;
566
567#if defined(DEBUG)
568  printk("mpc83xx_i2c_read_bytes called... ");
569#endif
570  softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MTX;
571  softc_ptr->reg_ptr->i2ccr &= ~I2CCR_TXAK;
572  /*
573   * FIXME: do we need to deactivate TXAK from the start,
574   * when only one byte is to be received?
575   */
576  /*
577   * we need a dummy transfer here to start the first read
578   */
579  softc_ptr->reg_ptr->i2cdr;
580
581  while (len-- > 0) {
582    if (len == 0) {
583      /*
584       * last byte is not acknowledged
585       */
586      softc_ptr->reg_ptr->i2ccr |= I2CCR_TXAK;
587    }
588    /*
589     * wait 'til end of transfer
590     */
591    rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF);
592    if (rc != RTEMS_SUCCESSFUL) {
593#if defined(DEBUG)
594      printk("... exit rc=%d\r\n",-rc);
595#endif
596      return -rc;
597    }
598    *p++ = softc_ptr->reg_ptr->i2cdr;
599
600  }
601
602 /*
603  * wait 'til end of last transfer
604  */
605  rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF);
606
607#if defined(DEBUG)
608  printk("... exit OK, rc=%d\r\n",p-buf);
609#endif
610  return p - buf;
611}
612
613/*=========================================================================*\
614| Function:                                                                 |
615\*-------------------------------------------------------------------------*/
616static int mpc83xx_i2c_write_bytes
617(
618/*-------------------------------------------------------------------------*\
619| Purpose:                                                                  |
620|   send some bytes to I2C device                                           |
621+---------------------------------------------------------------------------+
622| Input Parameters:                                                         |
623\*-------------------------------------------------------------------------*/
624 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
625 unsigned char *buf,                     /* buffer to send                 */
626 int len                                 /* number of bytes to send        */
627
628)
629/*-------------------------------------------------------------------------*\
630| Return Value:                                                             |
631|    number of bytes sent or (negative) error code                          |
632\*=========================================================================*/
633{
634  mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc);
635  rtems_status_code rc;
636  unsigned char *p = buf;
637
638#if defined(DEBUG)
639  printk("mpc83xx_i2c_write_bytes called... ");
640#endif
641  softc_ptr->reg_ptr->i2ccr =
642    (softc_ptr->reg_ptr->i2ccr & ~I2CCR_TXAK) | I2CCR_MTX;
643  while (len-- > 0) {
644    int rxack = len != 0 ? I2CSR_RXAK : 0;
645
646    softc_ptr->reg_ptr->i2cdr = *p++;
647    /*
648     * wait 'til end of transfer
649     */
650    rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | rxack);
651    if (rc != RTEMS_SUCCESSFUL) {
652#if defined(DEBUG)
653      printk("... exit rc=%d\r\n",-rc);
654#endif
655      return -rc;
656    }
657  }
658#if defined(DEBUG)
659  printk("... exit OK, rc=%d\r\n",p-buf);
660#endif
661  return p - buf;
662}
663
664rtems_libi2c_bus_ops_t mpc83xx_i2c_ops = {
665  .init = mpc83xx_i2c_init,
666  .send_start = mpc83xx_i2c_send_start,
667  .send_stop = mpc83xx_i2c_send_stop,
668  .send_addr = mpc83xx_i2c_send_addr,
669  .read_bytes = mpc83xx_i2c_read_bytes,
670  .write_bytes = mpc83xx_i2c_write_bytes,
671};
672
Note: See TracBrowser for help on using the repository browser.