source: rtems/bsps/arm/altera-cyclone-v/i2c/i2cdrv.c @ a2dad96

5
Last change on this file since a2dad96 was a2dad96, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 23, 2018 at 7:45:28 AM

bsps: Move I2C drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <info@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <bsp.h>
16#include <bsp/i2cdrv.h>
17#include <assert.h>
18#include <rtems/libio.h>
19#include "i2cdrv-config.h"
20
21typedef struct {
22  ALT_I2C_DEV_t i2c_dev;
23  rtems_id mutex;
24} i2cdrv_entry;
25
26i2cdrv_entry i2cdrv_table[CYCLONE_V_NO_I2C];
27
28static ALT_I2C_DEV_t *get_device(i2cdrv_entry *e)
29{
30  return &e->i2c_dev;
31}
32
33static rtems_status_code init_i2c_module(
34  i2cdrv_entry *e,
35  const i2cdrv_configuration *cfg
36)
37{
38  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
39  ALT_I2C_CTLR_t controller = cfg->controller;
40  ALT_I2C_DEV_t *dev = get_device(e);
41  ALT_I2C_MASTER_CONFIG_t i2c_cfg = {
42    .addr_mode = ALT_I2C_ADDR_MODE_7_BIT,
43    .restart_enable = false,
44  };
45
46  asc = alt_i2c_init(controller, dev);
47  if ( asc != ALT_E_SUCCESS ) {
48    return RTEMS_IO_ERROR;
49  }
50  asc = alt_i2c_op_mode_set(dev, ALT_I2C_MODE_MASTER);
51  if ( asc != ALT_E_SUCCESS ) {
52    return RTEMS_IO_ERROR;
53  }
54  asc = alt_i2c_master_config_speed_set(dev, &i2c_cfg, cfg->speed);
55  if ( asc != ALT_E_SUCCESS ) {
56    return RTEMS_IO_ERROR;
57  }
58  asc = alt_i2c_master_config_set(dev, &i2c_cfg);
59  if ( asc != ALT_E_SUCCESS ) {
60    return RTEMS_IO_ERROR;
61  }
62  asc = alt_i2c_enable(dev);
63  if ( asc != ALT_E_SUCCESS ) {
64    return RTEMS_IO_ERROR;
65  }
66
67  return RTEMS_SUCCESSFUL;
68}
69
70rtems_device_driver i2cdrv_initialize(
71  rtems_device_major_number major,
72  rtems_device_minor_number minor,
73  void *arg
74)
75{
76  rtems_status_code sc = RTEMS_SUCCESSFUL;
77
78  for ( size_t i = 0; i < CYCLONE_V_NO_I2C; ++i ) {
79    i2cdrv_entry *e = &i2cdrv_table[i];
80    const i2cdrv_configuration *cfg = &i2cdrv_config[i];
81
82    sc = rtems_io_register_name(cfg->device_name, major, i);
83    assert(sc == RTEMS_SUCCESSFUL);
84
85    sc = rtems_semaphore_create(
86      rtems_build_name ('I', '2', 'C', '0' + i),
87      0,
88      RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
89      0,
90      &e->mutex
91    );
92    assert(sc == RTEMS_SUCCESSFUL);
93
94    sc = init_i2c_module(e, cfg);
95    if ( sc != RTEMS_SUCCESSFUL ) {
96      /* I2C is not usable at this point. Releasing the mutex would allow the
97       * usage which could lead to undefined behaviour. */
98      return sc;
99    }
100
101    sc = rtems_semaphore_release(e->mutex);
102    assert(sc == RTEMS_SUCCESSFUL);
103  }
104
105  return sc;
106}
107
108rtems_device_driver i2cdrv_open(
109  rtems_device_major_number major,
110  rtems_device_major_number minor,
111  void *arg
112)
113{
114  rtems_status_code sc = RTEMS_SUCCESSFUL;
115  i2cdrv_entry *e = &i2cdrv_table[minor];
116
117  sc = rtems_semaphore_obtain(e->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
118  return sc;
119}
120
121rtems_device_driver i2cdrv_close(
122  rtems_device_major_number major,
123  rtems_device_major_number minor,
124  void *arg
125)
126{
127  rtems_status_code sc = RTEMS_SUCCESSFUL;
128  i2cdrv_entry *e = &i2cdrv_table[minor];
129
130  sc = rtems_semaphore_release(e->mutex);
131  return sc;
132}
133
134rtems_device_driver i2cdrv_read(
135  rtems_device_major_number major,
136  rtems_device_major_number minor,
137  void *arg
138)
139{
140  rtems_status_code sc = RTEMS_SUCCESSFUL;
141  i2cdrv_entry *e = &i2cdrv_table[minor];
142  rtems_libio_rw_args_t *rw  = arg;
143  ALT_I2C_DEV_t *dev = get_device(e);
144  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
145
146  asc = alt_i2c_master_receive(dev, rw->buffer, rw->count, true, true);
147  if ( asc == ALT_E_SUCCESS ) {
148    rw->bytes_moved = rw->count;
149  } else {
150    sc = RTEMS_IO_ERROR;
151  }
152
153  return sc;
154}
155
156rtems_device_driver i2cdrv_write(
157  rtems_device_major_number major,
158  rtems_device_minor_number minor,
159  void *arg
160)
161{
162  rtems_status_code sc = RTEMS_SUCCESSFUL;
163  i2cdrv_entry *e = &i2cdrv_table[minor];
164  rtems_libio_rw_args_t *rw  = arg;
165  ALT_I2C_DEV_t *dev = get_device(e);
166  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
167
168  asc = alt_i2c_master_transmit(dev, rw->buffer, rw->count, true, true);
169  if ( asc == ALT_E_SUCCESS ) {
170    rw->bytes_moved = rw->count;
171  } else {
172    sc = RTEMS_IO_ERROR;
173  }
174
175  return sc;
176}
177
178static rtems_status_code ioctl_set_slave_address(
179  i2cdrv_entry *e,
180  rtems_libio_ioctl_args_t *args
181)
182{
183  ALT_I2C_DEV_t *dev = get_device(e);
184  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
185  uint32_t address = (uint32_t) args->buffer;
186
187  asc = alt_i2c_master_target_set(dev, address);
188  if ( asc != ALT_E_SUCCESS ) {
189    return RTEMS_IO_ERROR;
190  }
191
192  return RTEMS_SUCCESSFUL;
193}
194
195rtems_device_driver i2cdrv_ioctl(
196  rtems_device_major_number major,
197  rtems_device_minor_number minor,
198  void *arg
199)
200{
201  rtems_status_code sc = RTEMS_SUCCESSFUL;
202  i2cdrv_entry *e = &i2cdrv_table[minor];
203  rtems_libio_ioctl_args_t *args = arg;
204
205  switch (args->command) {
206    case I2C_IOC_SET_SLAVE_ADDRESS:
207      sc = ioctl_set_slave_address(e, args);
208      break;
209    default:
210      sc = RTEMS_INVALID_NUMBER;
211      break;
212  }
213
214  return sc;
215}
Note: See TracBrowser for help on using the repository browser.