Changeset 007d4e12 in rtems


Ignore:
Timestamp:
Feb 25, 2019, 6:07:19 AM (8 weeks ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
5f813694
Parents:
9e48958
git-author:
Sebastian Huber <sebastian.huber@…> (02/25/19 06:07:19)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/15/19 15:02:22)
Message:

bsp/lpc24xx: Convert I2C driver to Linux API

Change license to BSD-2-Clause.

Close #3725.

Files:
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • bsps/arm/lpc24xx/i2c/i2c.c

    r9e48958 r007d4e12  
    22 * @file
    33 *
    4  * @ingroup RTEMSBSPsARMLPC24XX_libi2c
     4 * @ingroup RTEMSBSPsARMLPC24XXI2C
     5 */
     6
     7/*
     8 * SPDX-License-Identifier: BSD-2-Clause
    59 *
    6  * @brief LibI2C bus driver for the I2C modules.
     10 * Copyright (C) 2009, 2019 embedded brains GmbH
     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.
    732 */
    833
    9 /*
    10  * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
    11  *
    12  *  embedded brains GmbH
    13  *  Obere Lagerstr. 30
    14  *  82178 Puchheim
    15  *  Germany
    16  *  <rtems@embedded-brains.de>
    17  *
    18  * The license and distribution terms for this file may be
    19  * found in the file LICENSE in this distribution or at
    20  * http://www.rtems.org/license/LICENSE.
    21  */
    22 
     34#include <bsp/i2c.h>
    2335#include <bsp.h>
    24 #include <bsp/i2c.h>
     36#include <bsp/io.h>
    2537#include <bsp/irq.h>
    2638#include <bsp/irq-generic.h>
    27 #include <bsp/system-clocks.h>
    28 
    29 #define RTEMS_STATUS_CHECKS_USE_PRINTK
    30 
    31 #include <rtems/status-checks.h>
    32 
    33 static void lpc24xx_i2c_handler(void *arg)
    34 {
    35   lpc24xx_i2c_bus_entry *e = arg;
    36   volatile lpc24xx_i2c *regs = e->regs;
    37   unsigned state = regs->stat;
    38   uint8_t *data = e->data;
    39   uint8_t *end = e->end;
    40   bool notify = true;
    41 
    42   switch (state) {
    43     case 0x28U:
    44       /* Data has been transmitted successfully */
    45       if (data != end) {
    46         regs->dat = *data;
    47         ++data;
     39
     40#include <rtems/score/assert.h>
     41
     42#include <dev/i2c/i2c.h>
     43
     44RTEMS_STATIC_ASSERT(I2C_M_RD == 1, lpc24xx_i2c_read_flag);
     45
     46typedef struct {
     47  i2c_bus base;
     48  volatile lpc24xx_i2c *regs;
     49  uint8_t *buf;
     50  const uint8_t *buf_end;
     51  size_t todo;
     52  const i2c_msg *msg;
     53  const i2c_msg *msg_end;
     54  int error;
     55  rtems_binary_semaphore sem;
     56  lpc24xx_module module;
     57  rtems_vector_number irq;
     58} lpc24xx_i2c_bus;
     59
     60typedef struct {
     61  volatile lpc24xx_i2c *regs;
     62  lpc24xx_module module;
     63  rtems_vector_number irq;
     64} lpc24xx_i2c_config;
     65
     66static const i2c_msg *lpc24xx_i2c_msg_inc(lpc24xx_i2c_bus *bus)
     67{
     68  const i2c_msg *msg;
     69
     70  msg = bus->msg + 1;
     71  bus->msg = msg;
     72  return msg;
     73}
     74
     75static void lpc24xx_i2c_msg_inc_and_set_buf(lpc24xx_i2c_bus *bus)
     76{
     77  const i2c_msg *msg;
     78
     79  msg = lpc24xx_i2c_msg_inc(bus);
     80  bus->buf = msg->buf;
     81  bus->buf_end = bus->buf + msg->len;
     82}
     83
     84static void lpc24xx_i2c_buf_inc(lpc24xx_i2c_bus *bus)
     85{
     86  ++bus->buf;
     87  --bus->todo;
     88}
     89
     90static void lpc24xx_i2c_buf_push(lpc24xx_i2c_bus *bus, uint8_t c)
     91{
     92  while (true) {
     93    if (bus->buf != bus->buf_end) {
     94      bus->buf[0] = c;
     95      lpc24xx_i2c_buf_inc(bus);
     96      break;
     97    }
     98
     99    lpc24xx_i2c_msg_inc_and_set_buf(bus);
     100  }
     101}
     102
     103static uint8_t lpc24xx_i2c_buf_pop(lpc24xx_i2c_bus *bus)
     104{
     105  while (true) {
     106    if (bus->buf != bus->buf_end) {
     107      uint8_t c;
     108
     109      c = bus->buf[0];
     110      lpc24xx_i2c_buf_inc(bus);
     111      return c;
     112    }
     113
     114    lpc24xx_i2c_msg_inc_and_set_buf(bus);
     115  }
     116}
     117
     118static void lpc24xx_i2c_setup_msg(lpc24xx_i2c_bus *bus, const i2c_msg *msg)
     119{
     120  int can_continue;
     121  size_t todo;
     122
     123  bus->msg = msg;
     124  bus->buf = msg->buf;
     125  todo = msg->len;
     126  bus->buf_end = bus->buf + todo;
     127
     128  can_continue = (msg->flags & I2C_M_RD) | I2C_M_NOSTART;
     129  ++msg;
     130
     131  while (msg != bus->msg_end) {
     132    if ((msg->flags & (I2C_M_RD | I2C_M_NOSTART)) != can_continue) {
     133      break;
     134    }
     135
     136    todo += msg->len;
     137    ++msg;
     138  }
     139
     140  bus->todo = todo;
     141}
     142
     143static int lpc24xx_i2c_next_msg(
     144  lpc24xx_i2c_bus *bus,
     145  volatile lpc24xx_i2c *regs
     146)
     147{
     148  const i2c_msg *msg;
     149  int error;
     150
     151  msg = bus->msg + 1;
     152  error = 1;
     153
     154  if (msg != bus->msg_end) {
     155    lpc24xx_i2c_setup_msg(bus, msg);
     156
     157    if ((msg->flags & I2C_M_NOSTART) == 0) {
     158      regs->conset = LPC24XX_I2C_STA;
     159      regs->conclr = LPC24XX_I2C_SI;
     160    } else {
     161      regs->conset = LPC24XX_I2C_STO;
     162      regs->conclr = LPC24XX_I2C_SI;
     163      error = -EINVAL;
     164    }
     165  } else {
     166    regs->conset = LPC24XX_I2C_STO;
     167    regs->conclr = LPC24XX_I2C_SI;
     168    error = 0;
     169  }
     170
     171  return error;
     172}
     173
     174static void lpc24xx_i2c_interrupt(void *arg)
     175{
     176  lpc24xx_i2c_bus *bus;
     177  volatile lpc24xx_i2c *regs;
     178  const i2c_msg *msg;
     179  int error;
     180
     181  bus = arg;
     182  regs = bus->regs;
     183  error = 1;
     184
     185  switch (regs->stat) {
     186    case 0x00:
     187      /* Bus error */
     188    case 0x20:
     189      /* Slave address plus write sent, NACK received */
     190    case 0x48:
     191      /* Slave address plus read sent, NACK received */
     192      regs->conset = LPC24XX_I2C_STO | LPC24XX_I2C_AA;
     193      regs->conclr = LPC24XX_I2C_SI;
     194      error = -EIO;
     195      break;
     196    case 0x08:
     197      /* Start sent */
     198    case 0x10:
     199      /* Repeated start sent */
     200      msg = bus->msg;
     201      regs->dat = (uint8_t) ((msg->addr << 1) | (msg->flags & I2C_M_RD));
     202      regs->conset = LPC24XX_I2C_AA;
     203      regs->conclr = LPC24XX_I2C_STA | LPC24XX_I2C_SI;
     204      break;
     205    case 0x18:
     206      /* Slave address plus write sent, ACK received */
     207    case 0x28:
     208      /* Data sent, ACK received */
     209      if (bus->todo > 0) {
     210        regs->dat = lpc24xx_i2c_buf_pop(bus);
    48211        regs->conset = LPC24XX_I2C_AA;
    49212        regs->conclr = LPC24XX_I2C_SI;
    50         notify = false;
    51         e->data = data;
     213      } else {
     214        error = lpc24xx_i2c_next_msg(bus, regs);
    52215      }
    53216      break;
    54     case 0x50U:
    55       /* Data has been received */
    56       if (data != end) {
    57         *data = (uint8_t) regs->dat;
    58         ++data;
    59         if (data != end) {
    60           if (data + 1 != end) {
    61             regs->conset = LPC24XX_I2C_AA;
    62           } else {
    63             regs->conclr = LPC24XX_I2C_AA;
    64           }
    65           regs->conclr = LPC24XX_I2C_SI;
    66           notify = false;
    67           e->data = data;
    68         } else {
    69           /* This is an error and should never happen */
    70         }
     217    case 0x30:
     218      /* Data sent, NACK received */
     219      if (bus->todo == 0) {
     220        error = lpc24xx_i2c_next_msg(bus, regs);
     221      } else {
     222        regs->conset = LPC24XX_I2C_STO;
     223        regs->conclr = LPC24XX_I2C_SI;
     224        error = -EIO;
    71225      }
    72226      break;
    73     case 0x58U:
    74       /* Last data has been received */
    75       if (data != end) {
    76         *data = (uint8_t) regs->dat;
     227    case 0x40:
     228      /* Slave address plus read sent, ACK received */
     229      if (bus->todo > 1) {
     230        regs->conset = LPC24XX_I2C_AA;
     231        regs->conclr = LPC24XX_I2C_SI;
     232      } else {
     233        regs->conclr = LPC24XX_I2C_SI | LPC24XX_I2C_AA;
    77234      }
    78235      break;
     236    case 0x50:
     237      /* Data received, ACK returned */
     238    case 0x58:
     239      /* Data received, NACK returned */
     240      lpc24xx_i2c_buf_push(bus, regs->dat);
     241
     242      if (bus->todo > 1) {
     243        regs->conset = LPC24XX_I2C_AA;
     244        regs->conclr = LPC24XX_I2C_SI;
     245      } else if (bus->todo == 1) {
     246        regs->conclr = LPC24XX_I2C_SI | LPC24XX_I2C_AA;
     247      } else {
     248        error = lpc24xx_i2c_next_msg(bus, regs);
     249      }
     250      break;
     251    case 0xF8:
     252      /* Do nothing */
     253      break;
    79254    default:
    80       /* Do nothing */
    81       break;
    82   }
    83 
    84   /* Notify task if necessary */
    85   if (notify) {
    86     bsp_interrupt_vector_disable(e->vector);
    87 
    88     rtems_semaphore_release(e->state_update);
    89   }
    90 }
    91 
    92 static rtems_status_code lpc24xx_i2c_wait(lpc24xx_i2c_bus_entry *e)
    93 {
    94   bsp_interrupt_vector_enable(e->vector);
    95 
    96   return rtems_semaphore_obtain(e->state_update, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    97 }
    98 
    99 static rtems_status_code lpc24xx_i2c_init(rtems_libi2c_bus_t *bus)
    100 {
    101   rtems_status_code sc = RTEMS_SUCCESSFUL;
    102   lpc24xx_i2c_bus_entry *e = (lpc24xx_i2c_bus_entry *) bus;
    103   volatile lpc24xx_i2c *regs = e->regs;
    104   unsigned cycles = LPC24XX_CCLK / (8U * 100000U * 2U);
    105 
    106   /* Create semaphore */
    107   sc = rtems_semaphore_create (
    108     rtems_build_name ('I', '2', 'C', '0' + e->index),
    109     0,
    110     RTEMS_SIMPLE_BINARY_SEMAPHORE,
    111     0,
    112     &e->state_update
     255      error = -EIO;
     256      break;
     257  }
     258
     259  if (error <= 0) {
     260    bus->error = error;
     261    bsp_interrupt_vector_disable(bus->irq);
     262    rtems_binary_semaphore_post(&bus->sem);
     263  }
     264}
     265
     266static int
     267lpc24xx_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
     268{
     269  lpc24xx_i2c_bus *bus;
     270  volatile lpc24xx_i2c *regs;
     271  uint16_t supported;
     272  uint32_t i;
     273  int eno;
     274
     275  if (msg_count == 0){
     276    return 0;
     277  }
     278
     279  supported = I2C_M_RD;
     280
     281  for (i = 0; i < msg_count; ++i) {
     282    if ((msgs[i].flags & ~supported) != 0) {
     283      return -EINVAL;
     284    }
     285
     286    supported |= I2C_M_NOSTART;
     287  }
     288
     289  bus = (lpc24xx_i2c_bus *) base;
     290  bus->msg_end = msgs + msg_count;
     291  lpc24xx_i2c_setup_msg(bus, msgs);
     292
     293  regs = bus->regs;
     294
     295  /* Start */
     296  regs->conset = LPC24XX_I2C_STA;
     297
     298  bsp_interrupt_vector_enable(bus->irq);
     299  eno = rtems_binary_semaphore_wait_timed_ticks(
     300    &bus->sem,
     301    bus->base.timeout
    113302  );
    114   RTEMS_CHECK_SC(sc, "create status update semaphore");
    115 
    116   /* Enable module power */
    117   sc = lpc24xx_module_enable(LPC24XX_MODULE_I2C_0 + e->index, LPC24XX_MODULE_CCLK_8);
    118   RTEMS_CHECK_SC(sc, "enable module");
    119 
    120   /* Pin configuration */
    121   sc = lpc24xx_pin_config(e->pins, LPC24XX_PIN_SET_FUNCTION);
    122   RTEMS_CHECK_SC(sc, "pin configuration");
    123 
    124   /* Clock high and low duty cycles */
    125   regs->sclh = cycles;
    126   regs->scll = cycles;
    127 
    128   /* Disable module */
    129   regs->conclr = LPC24XX_I2C_EN;
    130 
    131   /* Install interrupt handler and disable this vector */
     303  if (eno != 0) {
     304    regs->conclr = LPC24XX_I2C_EN;
     305    regs->conset = LPC24XX_I2C_EN;
     306    rtems_binary_semaphore_try_wait(&bus->sem);
     307    return -ETIMEDOUT;
     308  }
     309
     310  return bus->error;
     311}
     312
     313/* I2C-Bus Specification and User Manual, Table 10 */
     314static const uint16_t lpc24xx_i2c_t_low_high[3][2] = {
     315  { 4700, 4000 },
     316  { 1300,  600 },
     317  {  500,  260 }
     318};
     319
     320static uint32_t lpc24xx_i2c_cycle_count(uint32_t scl, uint32_t x, uint32_t t)
     321{
     322  scl = (scl * x + t - 1) / t;
     323
     324  if (scl <= 4) {
     325    scl = 4;
     326  } else if (scl >= 0xffff) {
     327    scl = 0xffff;
     328  }
     329
     330  return scl;
     331}
     332
     333static int lpc24xx_i2c_set_clock(i2c_bus *base, unsigned long clock)
     334{
     335  lpc24xx_i2c_bus *bus;
     336  volatile lpc24xx_i2c *regs;
     337  size_t i;
     338  uint32_t low;
     339  uint32_t high;
     340  uint32_t t;
     341  uint32_t scl;
     342
     343  if (clock <= 100000) {
     344    i = 0;
     345  } else if (clock <= 400000) {
     346    i = 1;
     347  } else {
     348    i = 2;
     349  }
     350
     351  low = lpc24xx_i2c_t_low_high[i][0];
     352  high = lpc24xx_i2c_t_low_high[i][1];
     353  t = low + high;
     354  scl = (LPC24XX_PCLK + clock - 1) / clock;
     355
     356  bus = (lpc24xx_i2c_bus *) base;
     357  regs = bus->regs;
     358
     359  regs->scll = lpc24xx_i2c_cycle_count(scl, low, t);
     360  regs->sclh = lpc24xx_i2c_cycle_count(scl, high, t);
     361
     362  return 0;
     363}
     364
     365static void
     366lpc24xx_i2c_destroy(i2c_bus *base)
     367{
     368  lpc24xx_i2c_bus *bus;
     369  rtems_status_code sc;
     370
     371  bus = (lpc24xx_i2c_bus *) base;
     372
     373  sc = rtems_interrupt_handler_remove(bus->irq, lpc24xx_i2c_interrupt, bus);
     374  _Assert(sc == RTEMS_SUCCESSFUL);
     375  (void) sc;
     376
     377  /* Disable I2C module */
     378  bus->regs->conclr = LPC24XX_I2C_EN;
     379
     380  sc = lpc24xx_module_disable(bus->module);
     381  _Assert(sc == RTEMS_SUCCESSFUL);
     382  (void) sc;
     383
     384  rtems_binary_semaphore_destroy(&bus->sem);
     385  i2c_bus_destroy_and_free(&bus->base);
     386}
     387
     388static int lpc24xx_i2c_init(lpc24xx_i2c_bus *bus)
     389{
     390  rtems_status_code sc;
     391
     392  sc = lpc24xx_module_enable(bus->module, LPC24XX_MODULE_PCLK_DEFAULT);
     393  _Assert(sc == RTEMS_SUCCESSFUL);
     394  (void) sc;
     395
     396  /* Disable I2C module */
     397  bus->regs->conclr = LPC24XX_I2C_EN;
     398
    132399  sc = rtems_interrupt_handler_install(
    133     e->vector,
     400    bus->irq,
    134401    "I2C",
    135402    RTEMS_INTERRUPT_UNIQUE,
    136     lpc24xx_i2c_handler,
    137     e
     403    lpc24xx_i2c_interrupt,
     404    bus
    138405  );
    139   RTEMS_CHECK_SC(sc, "install interrupt handler");
    140   bsp_interrupt_vector_disable(e->vector);
    141 
    142   /* Enable module in master mode */
    143   regs->conset = LPC24XX_I2C_EN;
    144 
    145   /* Set self address */
    146   regs->adr = 0;
    147 
    148   return RTEMS_SUCCESSFUL;
    149 }
    150 
    151 static rtems_status_code lpc24xx_i2c_send_start(rtems_libi2c_bus_t *bus)
    152 {
    153   rtems_status_code sc = RTEMS_SUCCESSFUL;
    154   lpc24xx_i2c_bus_entry *e = (lpc24xx_i2c_bus_entry *) bus;
    155   volatile lpc24xx_i2c *regs = e->regs;
    156 
    157   /* Start */
    158   regs->conclr = LPC24XX_I2C_STA | LPC24XX_I2C_AA | LPC24XX_I2C_SI;
    159   regs->conset = LPC24XX_I2C_STA;
    160 
    161   /* Wait */
    162   sc = lpc24xx_i2c_wait(e);
    163   RTEMS_CHECK_SC(sc, "wait for state update");
    164 
    165   return RTEMS_SUCCESSFUL;
    166 }
    167 
    168 static rtems_status_code lpc24xx_i2c_send_stop(rtems_libi2c_bus_t *bus)
    169 {
    170   lpc24xx_i2c_bus_entry *e = (lpc24xx_i2c_bus_entry *) bus;
    171   volatile lpc24xx_i2c *regs = e->regs;
    172 
    173   /* Stop */
    174   regs->conset = LPC24XX_I2C_STO | LPC24XX_I2C_AA;
    175   regs->conclr = LPC24XX_I2C_STA | LPC24XX_I2C_SI;
    176 
    177   return RTEMS_SUCCESSFUL;
    178 }
    179 
    180 static rtems_status_code lpc24xx_i2c_send_addr(
    181   rtems_libi2c_bus_t *bus,
    182   uint32_t addr,
    183   int rw
     406  if (sc != RTEMS_SUCCESSFUL) {
     407    return EAGAIN;
     408  }
     409
     410  rtems_binary_semaphore_init(&bus->sem, "I2C");
     411
     412  lpc24xx_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT);
     413
     414  /* Initialize I2C module */
     415  bus->regs->conset = LPC24XX_I2C_EN;
     416
     417  return 0;
     418}
     419
     420static int i2c_bus_register_lpc24xx(
     421  const char *bus_path,
     422  const lpc24xx_i2c_config *config
    184423)
    185424{
    186   rtems_status_code sc = RTEMS_SUCCESSFUL;
    187   lpc24xx_i2c_bus_entry *e = (lpc24xx_i2c_bus_entry *) bus;
    188   volatile lpc24xx_i2c *regs = e->regs;
    189   unsigned state = regs->stat;
    190 
    191   /* Check state */
    192   if (state != 0x8U && state != 0x10U) {
    193     return -RTEMS_IO_ERROR;
    194   }
    195 
    196   /* Send address */
    197   regs->dat = (uint8_t) ((addr << 1U) | ((rw != 0) ? 1U : 0U));
    198   regs->conset = LPC24XX_I2C_AA;
    199   regs->conclr = LPC24XX_I2C_STA | LPC24XX_I2C_SI;
    200 
    201   /* Wait */
    202   sc = lpc24xx_i2c_wait(e);
    203   RTEMS_CHECK_SC_RV(sc, "wait for state update");
    204 
    205   /* Check state */
    206   state = regs->stat;
    207   if (state != 0x18U && state != 0x40U) {
    208     return -RTEMS_IO_ERROR;
    209   }
    210 
    211   return RTEMS_SUCCESSFUL;
    212 }
    213 
    214 static int lpc24xx_i2c_read(rtems_libi2c_bus_t *bus, unsigned char *in, int n)
    215 {
    216   rtems_status_code sc = RTEMS_SUCCESSFUL;
    217   lpc24xx_i2c_bus_entry *e = (lpc24xx_i2c_bus_entry *) bus;
    218   volatile lpc24xx_i2c *regs = e->regs;
    219   unsigned state = regs->stat;
    220   uint8_t *data = in;
    221   uint8_t *end = in + n;
    222 
    223   if (n <= 0) {
    224     return n;
    225   } else if (state != 0x40U) {
    226     return -RTEMS_IO_ERROR;
    227   }
    228 
    229   /* Setup receive buffer */
    230   e->data = data;
    231   e->end = end;
    232 
    233   /* Ready to receive data */
    234   if (data + 1 != end) {
    235     regs->conset = LPC24XX_I2C_AA;
    236   } else {
    237     regs->conclr = LPC24XX_I2C_AA;
    238   }
    239   regs->conclr = LPC24XX_I2C_SI;
    240 
    241   /* Wait */
    242   sc = lpc24xx_i2c_wait(e);
    243   RTEMS_CHECK_SC_RV(sc, "wait for state update");
    244 
    245   /* Check state */
    246   state = regs->stat;
    247   if (state != 0x58U) {
    248     return -RTEMS_IO_ERROR;
    249   }
    250 
    251   return n;
    252 }
    253 
    254 static int lpc24xx_i2c_write(
    255   rtems_libi2c_bus_t *bus,
    256   unsigned char *out,
    257   int n
    258 )
    259 {
    260   rtems_status_code sc = RTEMS_SUCCESSFUL;
    261   lpc24xx_i2c_bus_entry *e = (lpc24xx_i2c_bus_entry *) bus;
    262   volatile lpc24xx_i2c *regs = e->regs;
    263   unsigned state = 0;
    264 
    265   if (n <= 0) {
    266     return n;
    267   }
    268 
    269   /* Setup transmit buffer */
    270   e->data = out + 1;
    271   e->end = out + n;
    272 
    273   /* Transmit first byte */
    274   regs->dat = *out;
    275   regs->conset = LPC24XX_I2C_AA;
    276   regs->conclr = LPC24XX_I2C_SI;
    277 
    278   /* Wait */
    279   sc = lpc24xx_i2c_wait(e);
    280   RTEMS_CHECK_SC_RV(sc, "wait for state update");
    281 
    282   /* Check state */
    283   state = regs->stat;
    284   if (state != 0x28U) {
    285     return -RTEMS_IO_ERROR;
    286   }
    287 
    288   return n;
    289 }
    290 
    291 static int lpc24xx_i2c_set_transfer_mode(
    292   rtems_libi2c_bus_t *bus,
    293   const rtems_libi2c_tfr_mode_t *mode
    294 )
    295 {
    296   return -RTEMS_NOT_IMPLEMENTED;
    297 }
    298 
    299 static int lpc24xx_i2c_ioctl(rtems_libi2c_bus_t *bus, int cmd, void *arg)
    300 {
    301   int rv = -1;
    302   const rtems_libi2c_tfr_mode_t *tm = (const rtems_libi2c_tfr_mode_t *) arg;
    303 
    304   switch (cmd) {
    305     case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
    306       rv = lpc24xx_i2c_set_transfer_mode(bus, tm);
    307       break;
    308     default:
    309       rv = -RTEMS_NOT_DEFINED;
    310       break;
    311   }
    312 
    313   return rv;
    314 }
    315 
    316 const rtems_libi2c_bus_ops_t lpc24xx_i2c_ops = {
    317   .init = lpc24xx_i2c_init,
    318   .send_start = lpc24xx_i2c_send_start,
    319   .send_stop = lpc24xx_i2c_send_stop,
    320   .send_addr = lpc24xx_i2c_send_addr,
    321   .read_bytes = lpc24xx_i2c_read,
    322   .write_bytes = lpc24xx_i2c_write,
    323   .ioctl = lpc24xx_i2c_ioctl
    324 };
     425  lpc24xx_i2c_bus *bus;
     426  int eno;
     427
     428  bus = (lpc24xx_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus));
     429  if (bus == NULL){
     430    return -1;
     431  }
     432
     433  bus->regs = config->regs;
     434  bus->module = config->module;
     435  bus->irq = config->irq;
     436
     437  eno = lpc24xx_i2c_init(bus);
     438  if (eno != 0) {
     439    (*bus->base.destroy)(&bus->base);
     440    rtems_set_errno_and_return_minus_one(eno);
     441  }
     442
     443  bus->base.transfer = lpc24xx_i2c_transfer;
     444  bus->base.set_clock = lpc24xx_i2c_set_clock;
     445  bus->base.destroy = lpc24xx_i2c_destroy;
     446
     447  return i2c_bus_register(&bus->base, bus_path);
     448}
     449
     450int lpc24xx_register_i2c_0(void)
     451{
     452  static const lpc24xx_i2c_config config = {
     453    .regs = (volatile lpc24xx_i2c *) I2C0_BASE_ADDR,
     454    .module = LPC24XX_MODULE_I2C_0,
     455    .irq = LPC24XX_IRQ_I2C_0
     456  };
     457
     458  return i2c_bus_register_lpc24xx(
     459    LPC24XX_I2C_0_BUS_PATH,
     460    &config
     461  );
     462}
     463
     464int lpc24xx_register_i2c_1(void)
     465{
     466  static const lpc24xx_i2c_config config = {
     467    .regs = (volatile lpc24xx_i2c *) I2C1_BASE_ADDR,
     468    .module = LPC24XX_MODULE_I2C_1,
     469    .irq = LPC24XX_IRQ_I2C_1
     470  };
     471
     472  return i2c_bus_register_lpc24xx(
     473    LPC24XX_I2C_2_BUS_PATH,
     474    &config
     475  );
     476}
     477
     478int lpc24xx_register_i2c_2(void)
     479{
     480  static const lpc24xx_i2c_config config = {
     481    .regs = (volatile lpc24xx_i2c *) I2C2_BASE_ADDR,
     482    .module = LPC24XX_MODULE_I2C_2,
     483    .irq = LPC24XX_IRQ_I2C_2
     484  };
     485
     486  return i2c_bus_register_lpc24xx(
     487    LPC24XX_I2C_2_BUS_PATH,
     488    &config
     489  );
     490}
  • bsps/arm/lpc24xx/include/bsp/i2c.h

    r9e48958 r007d4e12  
    22 * @file
    33 *
    4  * @ingroup RTEMSBSPsARMLPC24XX_libi2c
    5  *
    6  * @brief LibI2C bus driver for the I2C modules.
     4 * @ingroup RTEMSBSPsARMLPC24XXI2C
    75 */
    86
    97/*
    10  * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
     8 * SPDX-License-Identifier: BSD-2-Clause
    119 *
    12  *  embedded brains GmbH
    13  *  Obere Lagerstr. 30
    14  *  82178 Puchheim
    15  *  Germany
    16  *  <rtems@embedded-brains.de>
     10 * Copyright (C) 2009, 2019 embedded brains GmbH
    1711 *
    18  * The license and distribution terms for this file may be
    19  * found in the file LICENSE in this distribution or at
    20  * http://www.rtems.org/license/LICENSE.
     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.
    2132 */
    2233
    2334#ifndef LIBBSP_ARM_LPC24XX_I2C_H
    2435#define LIBBSP_ARM_LPC24XX_I2C_H
    25 
    26 #include <rtems.h>
    27 #include <rtems/libi2c.h>
    28 
    29 #include <bsp/io.h>
    30 #include <bsp/lpc24xx.h>
    3136
    3237#ifdef __cplusplus
     
    3540
    3641/**
    37  * @defgroup lpc24xx_libi2c LPC24XX Bus Drivers
     42 * @defgroup RTEMSBSPsARMLPC24XXI2C I2C Driver
    3843 *
    3944 * @ingroup RTEMSBSPsARMLPC24XX
    40  *
    41  * @brief LibI2C bus drivers for LPC24XX.
    4245 *
    4346 * @{
    4447 */
    4548
    46 typedef struct {
    47   rtems_libi2c_bus_t bus;
    48   volatile lpc24xx_i2c *regs;
    49   size_t index;
    50   const lpc24xx_pin_range *pins;
    51   rtems_vector_number vector;
    52   rtems_id state_update;
    53   uint8_t *volatile data;
    54   uint8_t *volatile end;
    55 } lpc24xx_i2c_bus_entry;
     49#define LPC24XX_I2C_0_BUS_PATH "/dev/i2c-0"
    5650
    57 extern const rtems_libi2c_bus_ops_t lpc24xx_i2c_ops;
     51#define LPC24XX_I2C_1_BUS_PATH "/dev/i2c-1"
    5852
    59 extern rtems_libi2c_bus_t *const lpc24xx_i2c_0;
     53#define LPC24XX_I2C_2_BUS_PATH "/dev/i2c-2"
    6054
    61 extern rtems_libi2c_bus_t *const lpc24xx_i2c_1;
     55int lpc24xx_register_i2c_0(void);
    6256
    63 extern rtems_libi2c_bus_t *const lpc24xx_i2c_2;
     57int lpc24xx_register_i2c_1(void);
     58
     59int lpc24xx_register_i2c_2(void);
    6460
    6561/** @} */
  • c/src/lib/libbsp/arm/lpc24xx/Makefile.am

    r9e48958 r007d4e12  
    101101# I2C
    102102librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc24xx/i2c/i2c.c
    103 librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc24xx/i2c/i2c-config.c
    104103
    105104# Framebuffer
Note: See TracChangeset for help on using the changeset viewer.