source: rtems/bsps/arm/altera-cyclone-v/i2c/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: 5.9 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSBSPsARMCycVI2C
7 */
8
9/*
10 * Copyright (c) 2014 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 <bsp.h>
35#include <bsp/i2cdrv.h>
36#include <assert.h>
37#include <rtems/libio.h>
38#include "i2cdrv-config.h"
39
40typedef struct {
41  ALT_I2C_DEV_t i2c_dev;
42  rtems_id mutex;
43} i2cdrv_entry;
44
45i2cdrv_entry i2cdrv_table[CYCLONE_V_NO_I2C];
46
47static ALT_I2C_DEV_t *get_device(i2cdrv_entry *e)
48{
49  return &e->i2c_dev;
50}
51
52static rtems_status_code init_i2c_module(
53  i2cdrv_entry *e,
54  const i2cdrv_configuration *cfg
55)
56{
57  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
58  ALT_I2C_CTLR_t controller = cfg->controller;
59  ALT_I2C_DEV_t *dev = get_device(e);
60  ALT_I2C_MASTER_CONFIG_t i2c_cfg = {
61    .addr_mode = ALT_I2C_ADDR_MODE_7_BIT,
62    .restart_enable = false,
63  };
64
65  asc = alt_i2c_init(controller, dev);
66  if ( asc != ALT_E_SUCCESS ) {
67    return RTEMS_IO_ERROR;
68  }
69  asc = alt_i2c_op_mode_set(dev, ALT_I2C_MODE_MASTER);
70  if ( asc != ALT_E_SUCCESS ) {
71    return RTEMS_IO_ERROR;
72  }
73  asc = alt_i2c_master_config_speed_set(dev, &i2c_cfg, cfg->speed);
74  if ( asc != ALT_E_SUCCESS ) {
75    return RTEMS_IO_ERROR;
76  }
77  asc = alt_i2c_master_config_set(dev, &i2c_cfg);
78  if ( asc != ALT_E_SUCCESS ) {
79    return RTEMS_IO_ERROR;
80  }
81  asc = alt_i2c_enable(dev);
82  if ( asc != ALT_E_SUCCESS ) {
83    return RTEMS_IO_ERROR;
84  }
85
86  return RTEMS_SUCCESSFUL;
87}
88
89rtems_device_driver i2cdrv_initialize(
90  rtems_device_major_number major,
91  rtems_device_minor_number minor,
92  void *arg
93)
94{
95  rtems_status_code sc = RTEMS_SUCCESSFUL;
96
97  for ( size_t i = 0; i < CYCLONE_V_NO_I2C; ++i ) {
98    i2cdrv_entry *e = &i2cdrv_table[i];
99    const i2cdrv_configuration *cfg = &i2cdrv_config[i];
100
101    sc = rtems_io_register_name(cfg->device_name, major, i);
102    assert(sc == RTEMS_SUCCESSFUL);
103
104    sc = rtems_semaphore_create(
105      rtems_build_name ('I', '2', 'C', '0' + i),
106      0,
107      RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
108      0,
109      &e->mutex
110    );
111    assert(sc == RTEMS_SUCCESSFUL);
112
113    sc = init_i2c_module(e, cfg);
114    if ( sc != RTEMS_SUCCESSFUL ) {
115      /* I2C is not usable at this point. Releasing the mutex would allow the
116       * usage which could lead to undefined behaviour. */
117      return sc;
118    }
119
120    sc = rtems_semaphore_release(e->mutex);
121    assert(sc == RTEMS_SUCCESSFUL);
122  }
123
124  return sc;
125}
126
127rtems_device_driver i2cdrv_open(
128  rtems_device_major_number major,
129  rtems_device_major_number minor,
130  void *arg
131)
132{
133  rtems_status_code sc = RTEMS_SUCCESSFUL;
134  i2cdrv_entry *e = &i2cdrv_table[minor];
135
136  sc = rtems_semaphore_obtain(e->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
137  return sc;
138}
139
140rtems_device_driver i2cdrv_close(
141  rtems_device_major_number major,
142  rtems_device_major_number minor,
143  void *arg
144)
145{
146  rtems_status_code sc = RTEMS_SUCCESSFUL;
147  i2cdrv_entry *e = &i2cdrv_table[minor];
148
149  sc = rtems_semaphore_release(e->mutex);
150  return sc;
151}
152
153rtems_device_driver i2cdrv_read(
154  rtems_device_major_number major,
155  rtems_device_major_number minor,
156  void *arg
157)
158{
159  rtems_status_code sc = RTEMS_SUCCESSFUL;
160  i2cdrv_entry *e = &i2cdrv_table[minor];
161  rtems_libio_rw_args_t *rw  = arg;
162  ALT_I2C_DEV_t *dev = get_device(e);
163  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
164
165  asc = alt_i2c_master_receive(dev, rw->buffer, rw->count, true, true);
166  if ( asc == ALT_E_SUCCESS ) {
167    rw->bytes_moved = rw->count;
168  } else {
169    sc = RTEMS_IO_ERROR;
170  }
171
172  return sc;
173}
174
175rtems_device_driver i2cdrv_write(
176  rtems_device_major_number major,
177  rtems_device_minor_number minor,
178  void *arg
179)
180{
181  rtems_status_code sc = RTEMS_SUCCESSFUL;
182  i2cdrv_entry *e = &i2cdrv_table[minor];
183  rtems_libio_rw_args_t *rw  = arg;
184  ALT_I2C_DEV_t *dev = get_device(e);
185  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
186
187  asc = alt_i2c_master_transmit(dev, rw->buffer, rw->count, true, true);
188  if ( asc == ALT_E_SUCCESS ) {
189    rw->bytes_moved = rw->count;
190  } else {
191    sc = RTEMS_IO_ERROR;
192  }
193
194  return sc;
195}
196
197static rtems_status_code ioctl_set_slave_address(
198  i2cdrv_entry *e,
199  rtems_libio_ioctl_args_t *args
200)
201{
202  ALT_I2C_DEV_t *dev = get_device(e);
203  ALT_STATUS_CODE asc = ALT_E_SUCCESS;
204  uint32_t address = (uint32_t) args->buffer;
205
206  asc = alt_i2c_master_target_set(dev, address);
207  if ( asc != ALT_E_SUCCESS ) {
208    return RTEMS_IO_ERROR;
209  }
210
211  return RTEMS_SUCCESSFUL;
212}
213
214rtems_device_driver i2cdrv_ioctl(
215  rtems_device_major_number major,
216  rtems_device_minor_number minor,
217  void *arg
218)
219{
220  rtems_status_code sc = RTEMS_SUCCESSFUL;
221  i2cdrv_entry *e = &i2cdrv_table[minor];
222  rtems_libio_ioctl_args_t *args = arg;
223
224  switch (args->command) {
225    case I2C_IOC_SET_SLAVE_ADDRESS:
226      sc = ioctl_set_slave_address(e, args);
227      break;
228    default:
229      sc = RTEMS_INVALID_NUMBER;
230      break;
231  }
232
233  return sc;
234}
Note: See TracBrowser for help on using the repository browser.