source: rtems/bsps/powerpc/gen83xx/dev/mpc83xx_i2cdrv.c

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

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