source: rtems/testsuites/libtests/i2c01/init.c @ 67ac69fc

4.115
Last change on this file since 67ac69fc was 67ac69fc, checked in by Sebastian Huber <sebastian.huber@…>, on 11/07/14 at 12:50:01

Add NXP PCA9535 16-bit GPIO I2C driver

  • Property mode set to 100644
File size: 12.7 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 *  <rtems@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#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <dev/i2c/i2c.h>
20#include <dev/i2c/eeprom.h>
21#include <dev/i2c/gpio-nxp-pca9535.h>
22
23#include <sys/ioctl.h>
24#include <sys/stat.h>
25#include <errno.h>
26#include <fcntl.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31#include <rtems/libcsupport.h>
32
33#include "tmacros.h"
34
35const char rtems_test_name[] = "I2C 1";
36
37#define SPARE_ADDRESS_BITS 3
38
39#define DEVICE_SIMPLE_READ_WRITE (0UL << SPARE_ADDRESS_BITS)
40
41#define DEVICE_EEPROM (1UL << SPARE_ADDRESS_BITS)
42
43#define DEVICE_GPIO_NXP_PCA9535 (2UL << SPARE_ADDRESS_BITS)
44
45#define EEPROM_SIZE 512
46
47typedef struct test_device test_device;
48
49struct test_device {
50  int (*transfer)(
51    i2c_bus *bus,
52    i2c_msg *msgs,
53    uint32_t msg_count,
54    test_device *dev
55  );
56};
57
58typedef struct {
59  test_device base;
60  char buf[3];
61} test_device_simple_read_write;
62
63typedef struct {
64  test_device base;
65  unsigned current_reg;
66  uint8_t regs[8];
67} test_device_gpio_nxp_pca9535;
68
69typedef struct {
70  test_device base;
71  unsigned current_address;
72  uint8_t data[EEPROM_SIZE];
73} test_device_eeprom;
74
75typedef struct {
76  i2c_bus base;
77  unsigned long clock;
78  test_device *devices[3];
79  test_device_simple_read_write simple_read_write;
80  test_device_gpio_nxp_pca9535 gpio_nxp_pca9535;
81  test_device_eeprom eeprom;
82} test_bus;
83
84static const char bus_path[] = "/dev/i2c-0";
85
86static const char gpio_nxp_pca9535_path[] = "/dev/i2c-0.gpio-nxp-pc9535-0";
87
88static const char eeprom_path[] = "/dev/i2c-0.eeprom-0";
89
90static void cyclic_inc(unsigned *val, unsigned cycle)
91{
92  unsigned v = *val;
93  unsigned m = cycle - 1U;
94
95  *val = (v & ~m) + ((v + 1U) & m);
96}
97
98static int test_simple_read_write_transfer(
99  i2c_bus *bus,
100  i2c_msg *msgs,
101  uint32_t msg_count,
102  test_device *base
103)
104{
105  test_device_simple_read_write *dev = (test_device_simple_read_write *) base;
106
107  if (msg_count == 1 && msgs[0].len == sizeof(dev->buf)) {
108    if ((msgs[0].flags & I2C_M_RD) != 0) {
109      memcpy(msgs[0].buf, &dev->buf[0], sizeof(dev->buf));
110    } else {
111      memcpy(&dev->buf[0], msgs[0].buf, sizeof(dev->buf));
112    }
113
114    return 0;
115  } else {
116    return -EIO;
117  }
118}
119
120static int test_gpio_nxp_pca9535_transfer(
121  i2c_bus *bus,
122  i2c_msg *msgs,
123  uint32_t msg_count,
124  test_device *base
125)
126{
127  test_device_gpio_nxp_pca9535 *dev = (test_device_gpio_nxp_pca9535 *) base;
128  i2c_msg *first = &msgs[0];
129  i2c_msg *second = &msgs[1];
130  int i;
131
132  /* Get command byte */
133  if (
134    msg_count < 1
135      || (first->flags & I2C_M_RD) != 0
136      || first->len < 1
137  ) {
138    return -EIO;
139  }
140
141  dev->current_reg = first->buf[0];
142
143  if (first->len > 1) {
144    /* Write */
145
146    if (msg_count != 1) {
147      return -EIO;
148    }
149
150    for (i = 1; i < first->len; ++i) {
151      dev->regs[dev->current_reg] = first->buf[i];
152
153      /* Output is input */
154      if (dev->current_reg == 2) {
155        dev->regs[0] = first->buf[i];
156      } else if (dev->current_reg == 3) {
157        dev->regs[1] = first->buf[i];
158      }
159
160      cyclic_inc(&dev->current_reg, 2);
161    }
162  } else {
163    /* Read */
164
165    if (msg_count != 2) {
166      return -EIO;
167    }
168
169    for (i = 0; i < second->len; ++i) {
170      second->buf[i] = dev->regs[dev->current_reg];
171      cyclic_inc(&dev->current_reg, 2);
172    }
173  }
174
175  return 0;
176}
177
178static int test_eeprom_transfer(
179  i2c_bus *bus,
180  i2c_msg *msgs,
181  uint32_t msg_count,
182  test_device *base
183)
184{
185  test_device_eeprom *dev = (test_device_eeprom *) base;
186  i2c_msg *msg = &msgs[0];
187  uint32_t i;
188
189  if (msg_count > 0 && (msg->flags & I2C_M_RD) == 0) {
190    if (msg->len < 1) {
191      return -EIO;
192    }
193
194    dev->current_address = msg->buf[0] | ((msg->addr & 0x1) << 8);
195    --msg->len;
196    ++msg->buf;
197  }
198
199  for (i = 0; i < msg_count; ++i) {
200    int j;
201
202    msg = &msgs[i];
203
204    if ((msg->flags & I2C_M_RD) != 0) {
205      for (j = 0; j < msg->len; ++j) {
206        msg->buf[j] = dev->data[dev->current_address];
207        cyclic_inc(&dev->current_address, sizeof(dev->data));
208      }
209    } else {
210      for (j = 0; j < msg->len; ++j) {
211        dev->data[dev->current_address] = msg->buf[j];
212        cyclic_inc(&dev->current_address, 8);
213      }
214    }
215  }
216
217  return 0;
218}
219
220static int test_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
221{
222  test_bus *bus = (test_bus *) base;
223  uint16_t addr;
224  test_device *dev;
225
226  addr = msgs[0].addr >> SPARE_ADDRESS_BITS;
227  if (addr >= RTEMS_ARRAY_SIZE(bus->devices)) {
228    return -EIO;
229  }
230
231  dev = bus->devices[addr];
232
233  return (*dev->transfer)(&bus->base, msgs, msg_count, dev);
234}
235
236static int test_set_clock(i2c_bus *base, unsigned long clock)
237{
238  test_bus *bus = (test_bus *) base;
239
240  bus->clock = clock;
241
242  return 0;
243}
244
245static void test_destroy(i2c_bus *base)
246{
247  i2c_bus_destroy_and_free(base);
248}
249
250static void test_simple_read_write(test_bus *bus, int fd)
251{
252  static const char zero[] = { 0, 0, 0 };
253  static const char abc[] = { 'a', 'b', 'c' };
254
255  int rv;
256  char buf[3];
257  ssize_t n;
258
259  rv = ioctl(fd, I2C_SLAVE, DEVICE_SIMPLE_READ_WRITE);
260  rtems_test_assert(rv == 0);
261
262  errno = 0;
263  rv = ioctl(fd, 0xb00b);
264  rtems_test_assert(rv == -1);
265  rtems_test_assert(errno == ENOTTY);
266
267  errno = 0;
268  n = write(fd, &buf[0], 1000);
269  rtems_test_assert(n == -1);
270  rtems_test_assert(errno == EIO);
271
272  errno = 0;
273  n = read(fd, &buf[0], 1000);
274  rtems_test_assert(n == -1);
275  rtems_test_assert(errno == EIO);
276
277  rtems_test_assert(
278    memcmp(&bus->simple_read_write.buf[0], &zero[0], sizeof(buf)) == 0
279  );
280
281  n = write(fd, &abc[0], sizeof(buf));
282  rtems_test_assert(n == (ssize_t) sizeof(buf));
283
284  rtems_test_assert(
285    memcmp(&bus->simple_read_write.buf[0], &abc[0], sizeof(buf)) == 0
286  );
287
288  n = read(fd, &buf[0], sizeof(buf));
289  rtems_test_assert(n == (ssize_t) sizeof(buf));
290
291  rtems_test_assert(memcmp(&buf[0], &abc[0], sizeof(buf)) == 0);
292}
293
294static void test_gpio_nxp_pca9535(void)
295{
296  int rv;
297  int fd;
298  uint16_t val;
299
300  rv = i2c_dev_register_gpio_nxp_pca9535(
301    &bus_path[0],
302    &gpio_nxp_pca9535_path[0],
303    DEVICE_GPIO_NXP_PCA9535
304  );
305  rtems_test_assert(rv == 0);
306
307  fd = open(&gpio_nxp_pca9535_path[0], O_RDWR);
308  rtems_test_assert(fd >= 0);
309
310  rv = gpio_nxp_pca9535_get_input(fd, &val);
311  rtems_test_assert(rv == 0);
312  rtems_test_assert(val == 0);
313
314  rv = gpio_nxp_pca9535_get_output(fd, &val);
315  rtems_test_assert(rv == 0);
316  rtems_test_assert(val == 0);
317
318  rv = gpio_nxp_pca9535_set_output(fd, 0xa5ef);
319  rtems_test_assert(rv == 0);
320
321  rv = gpio_nxp_pca9535_get_input(fd, &val);
322  rtems_test_assert(rv == 0);
323  rtems_test_assert(val == 0xa5ef);
324
325  rv = gpio_nxp_pca9535_get_output(fd, &val);
326  rtems_test_assert(rv == 0);
327  rtems_test_assert(val == 0xa5ef);
328
329  rv = gpio_nxp_pca9535_clear_and_set_output(fd, 0x0ff0, 0x0170);
330  rtems_test_assert(rv == 0);
331
332  rv = gpio_nxp_pca9535_get_polarity_inversion(fd, &val);
333  rtems_test_assert(rv == 0);
334  rtems_test_assert(val == 0);
335
336  rv = gpio_nxp_pca9535_set_polarity_inversion(fd, 0x5afe);
337  rtems_test_assert(rv == 0);
338
339  rv = gpio_nxp_pca9535_get_config(fd, &val);
340  rtems_test_assert(rv == 0);
341  rtems_test_assert(val == 0);
342
343  rv = gpio_nxp_pca9535_set_config(fd, 0x2bcd);
344  rtems_test_assert(rv == 0);
345
346  rv = gpio_nxp_pca9535_get_input(fd, &val);
347  rtems_test_assert(rv == 0);
348  rtems_test_assert(val == 0xa17f);
349
350  rv = gpio_nxp_pca9535_get_output(fd, &val);
351  rtems_test_assert(rv == 0);
352  rtems_test_assert(val == 0xa17f);
353
354  rv = gpio_nxp_pca9535_get_polarity_inversion(fd, &val);
355  rtems_test_assert(rv == 0);
356  rtems_test_assert(val == 0x5afe);
357
358  rv = gpio_nxp_pca9535_get_config(fd, &val);
359  rtems_test_assert(rv == 0);
360  rtems_test_assert(val == 0x2bcd);
361
362  rv = close(fd);
363  rtems_test_assert(rv == 0);
364
365  rv = unlink(&gpio_nxp_pca9535_path[0]);
366  rtems_test_assert(rv == 0);
367}
368
369static void test_eeprom(void)
370{
371  int rv;
372  int fd_in;
373  int fd_out;
374  struct stat st;
375  uint8_t in[EEPROM_SIZE];
376  uint8_t out[EEPROM_SIZE];
377  ssize_t n;
378  off_t off;
379  size_t i;
380
381  rv = i2c_dev_register_eeprom(
382    &bus_path[0],
383    &eeprom_path[0],
384    DEVICE_EEPROM,
385    1,
386    8,
387    sizeof(out),
388    0
389  );
390  rtems_test_assert(rv == 0);
391
392  fd_in = open(&eeprom_path[0], O_RDWR);
393  rtems_test_assert(fd_in >= 0);
394
395  fd_out = open(&eeprom_path[0], O_RDWR);
396  rtems_test_assert(fd_out >= 0);
397
398  rv = fstat(fd_in, &st);
399  rtems_test_assert(rv == 0);
400  rtems_test_assert(st.st_blksize == 8);
401  rtems_test_assert(st.st_size == sizeof(out));
402
403  memset(&out[0], 0, sizeof(out));
404
405  n = read(fd_in, &in[0], sizeof(in) + 1);
406  rtems_test_assert(n == (ssize_t) sizeof(in));
407
408  rtems_test_assert(memcmp(&in[0], &out[0], sizeof(in)) == 0);
409
410  off = lseek(fd_in, 0, SEEK_CUR);
411  rtems_test_assert(off == sizeof(out));
412
413  for (i = 0; i < sizeof(out); ++i) {
414    off = lseek(fd_out, 0, SEEK_CUR);
415    rtems_test_assert(off == i);
416
417    out[i] = (uint8_t) i;
418
419    n = write(fd_out, &out[i], sizeof(out[i]));
420    rtems_test_assert(n == (ssize_t) sizeof(out[i]));
421
422    off = lseek(fd_in, 0, SEEK_SET);
423    rtems_test_assert(off == 0);
424
425    n = read(fd_in, &in[0], sizeof(in));
426    rtems_test_assert(n == (ssize_t) sizeof(in));
427
428    rtems_test_assert(memcmp(&in[0], &out[0], sizeof(in)) == 0);
429  }
430
431  rv = close(fd_in);
432  rtems_test_assert(rv == 0);
433
434  rv = close(fd_out);
435  rtems_test_assert(rv == 0);
436
437  rv = unlink(&eeprom_path[0]);
438  rtems_test_assert(rv == 0);
439}
440
441static void test(void)
442{
443  rtems_resource_snapshot snapshot;
444  test_bus *bus;
445  int rv;
446  int fd;
447
448  rtems_resource_snapshot_take(&snapshot);
449
450  bus = (test_bus *) i2c_bus_alloc_and_init(sizeof(*bus));
451  rtems_test_assert(bus != NULL);
452
453  bus->base.transfer = test_transfer;
454  bus->base.set_clock = test_set_clock;
455  bus->base.destroy = test_destroy;
456  bus->base.functionality = I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING
457    | I2C_FUNC_NOSTART;
458
459  bus->simple_read_write.base.transfer = test_simple_read_write_transfer;
460  bus->devices[0] = &bus->simple_read_write.base;
461
462  bus->eeprom.base.transfer = test_eeprom_transfer;
463  bus->devices[1] = &bus->eeprom.base;
464
465  bus->gpio_nxp_pca9535.base.transfer = test_gpio_nxp_pca9535_transfer;
466  bus->devices[2] = &bus->gpio_nxp_pca9535.base;
467
468  rv = i2c_bus_register(&bus->base, &bus_path[0]);
469  rtems_test_assert(rv == 0);
470
471  fd = open(&bus_path[0], O_RDWR);
472  rtems_test_assert(fd >= 0);
473
474  rtems_test_assert(bus->clock == 0);
475  rv = ioctl(fd, I2C_BUS_SET_CLOCK, 0xdeadbeefUL);
476  rtems_test_assert(rv == 0);
477  rtems_test_assert(bus->clock == 0xdeadbeef);
478
479  rv = ioctl(fd, I2C_BUS_OBTAIN);
480  rtems_test_assert(rv == 0);
481
482  rv = ioctl(fd, I2C_BUS_RELEASE);
483  rtems_test_assert(rv == 0);
484
485  rtems_test_assert(!bus->base.ten_bit_address);
486
487  rv = ioctl(fd, I2C_TENBIT, 1UL);
488  rtems_test_assert(rv == 0);
489  rtems_test_assert(bus->base.ten_bit_address);
490
491  rv = ioctl(fd, I2C_TENBIT, 0UL);
492  rtems_test_assert(rv == 0);
493  rtems_test_assert(!bus->base.ten_bit_address);
494
495  rtems_test_assert(!bus->base.use_pec);
496
497  rv = ioctl(fd, I2C_PEC, 1UL);
498  rtems_test_assert(rv == 0);
499  rtems_test_assert(bus->base.use_pec);
500
501  rv = ioctl(fd, I2C_PEC, 0UL);
502  rtems_test_assert(rv == 0);
503  rtems_test_assert(!bus->base.use_pec);
504
505  rv = ioctl(fd, I2C_SLAVE, 123UL);
506  rtems_test_assert(rv == 0);
507  rtems_test_assert(bus->base.default_address == 123);
508
509  rv = ioctl(fd, I2C_SLAVE_FORCE, 456UL);
510  rtems_test_assert(rv == 0);
511  rtems_test_assert(bus->base.default_address == 456);
512
513  rtems_test_assert(bus->base.retries == 0);
514
515  rv = ioctl(fd, I2C_RETRIES, 1UL);
516  rtems_test_assert(rv == 0);
517  rtems_test_assert(bus->base.retries == 1);
518
519  rv = ioctl(fd, I2C_RETRIES, 0UL);
520  rtems_test_assert(rv == 0);
521  rtems_test_assert(bus->base.retries == 0);
522
523  rtems_test_assert(bus->base.timeout == 0);
524
525  rv = ioctl(fd, I2C_TIMEOUT, 1UL);
526  rtems_test_assert(rv == 0);
527  rtems_test_assert(bus->base.timeout == 5);
528
529  rv = ioctl(fd, I2C_TIMEOUT, 0UL);
530  rtems_test_assert(rv == 0);
531  rtems_test_assert(bus->base.timeout == 0);
532
533  test_simple_read_write(bus, fd);
534  test_eeprom();
535  test_gpio_nxp_pca9535();
536
537  rv = close(fd);
538  rtems_test_assert(rv == 0);
539
540  rv = unlink(&bus_path[0]);
541  rtems_test_assert(rv == 0);
542
543  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
544}
545
546static void Init(rtems_task_argument arg)
547{
548  TEST_BEGIN();
549
550  test();
551
552  TEST_END();
553  rtems_test_exit(0);
554}
555
556#define CONFIGURE_MICROSECONDS_PER_TICK 2000
557
558#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
559#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
560
561#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
562
563#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 7
564
565#define CONFIGURE_MAXIMUM_TASKS 1
566
567#define CONFIGURE_MAXIMUM_SEMAPHORES 1
568
569#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
570
571#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
572
573#define CONFIGURE_INIT
574
575#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.