Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:34

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2016 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <dev/spi/spi.h>
0033 
0034 #include <sys/ioctl.h>
0035 #include <sys/stat.h>
0036 #include <errno.h>
0037 #include <fcntl.h>
0038 #include <math.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 #include <unistd.h>
0042 
0043 #include <rtems/libcsupport.h>
0044 
0045 #include "tmacros.h"
0046 
0047 static uint8_t mode_8 = 0xA5;
0048 static uint32_t mode_32 = 0x5A5A5A5A;
0049 static uint32_t speed = 12345678;
0050 static uint8_t bits_per_word = 12;
0051 static uint8_t lsb_first = 1;
0052 
0053 const char rtems_test_name[] = "SPI 1";
0054 
0055 static const char bus_path[] = "/dev/spi-0";
0056 
0057 typedef struct test_device test_device;
0058 
0059 struct test_device {
0060   int (*transfer)(
0061     spi_bus *bus,
0062     const spi_ioc_transfer *msgs,
0063     uint32_t msg_count,
0064     test_device *dev
0065   );
0066 };
0067 
0068 typedef struct {
0069   test_device base;
0070   char buf[3];
0071 } test_device_simple_read_write;
0072 
0073 typedef struct {
0074   spi_bus base;
0075   unsigned long clock;
0076   test_device *device;
0077   uint32_t msg_count;
0078   uint32_t max_speed_hz;
0079   test_device_simple_read_write simple_read_write;
0080 } test_bus;
0081 
0082 static int test_simple_read_write_transfer(
0083   spi_bus *bus,
0084   const spi_ioc_transfer *msgs,
0085   uint32_t msg_count,
0086   test_device *base
0087 )
0088 {
0089   (void)bus;
0090 
0091   test_device_simple_read_write *dev = (test_device_simple_read_write *) base;
0092 
0093   if (msg_count == 1 && msgs[0].len == sizeof(dev->buf)) {
0094     if (msgs[0].rx_buf == 0){
0095         memcpy(&dev->buf[0], msgs[0].tx_buf, sizeof(dev->buf));
0096     } else if (msgs[0].tx_buf == 0){
0097         memcpy(msgs[0].rx_buf, &dev->buf[0], sizeof(dev->buf));
0098     } else {
0099         return -EIO;
0100     }
0101   } else {
0102     return -EIO;
0103   }
0104   return 0;
0105 }
0106 
0107 static int test_transfer(
0108   spi_bus *base,
0109   const spi_ioc_transfer *msgs,
0110   uint32_t msg_count
0111 )
0112 {
0113   test_bus *bus = (test_bus *) base;
0114   test_device *dev;
0115 
0116   dev = bus->device;
0117   bus->msg_count = msg_count;
0118 
0119   return (*dev->transfer)(&bus->base, msgs, msg_count, dev);
0120 }
0121 
0122 static int test_setup(spi_bus *base)
0123 {
0124   test_bus *bus = (test_bus *) base;
0125 
0126   if ((base->speed_hz > bus->max_speed_hz) ||
0127     ((base->bits_per_word < 8) || (base->bits_per_word > 16))) {
0128     return 1;
0129   }
0130 
0131   return 0;
0132 }
0133 
0134 static void test_destroy(spi_bus *base)
0135 {
0136   spi_bus_destroy_and_free(base);
0137 }
0138 
0139 static void test_simple_read_write(test_bus *bus, int fd)
0140 {
0141   static const char zero[] = { 0, 0, 0 };
0142   static const char abc[] = { 'a', 'b', 'c' };
0143 
0144   int rv;
0145   char buf[3];
0146   ssize_t n;
0147 
0148   errno = 0;
0149   rv = ioctl(fd, 0xb00b);
0150   rtems_test_assert(rv == -1);
0151   rtems_test_assert(errno == EINVAL);
0152 
0153   errno = 0;
0154   n = write(fd, &buf[0], 1000);
0155   rtems_test_assert(n == -1);
0156   rtems_test_assert(errno == EIO);
0157 
0158   errno = 0;
0159   n = read(fd, &buf[0], 1000);
0160   rtems_test_assert(n == -1);
0161   rtems_test_assert(errno == EIO);
0162 
0163   rtems_test_assert(
0164     memcmp(&bus->simple_read_write.buf[0], &zero[0], sizeof(buf)) == 0
0165   );
0166 
0167   n = write(fd, &abc[0], sizeof(buf));
0168   rtems_test_assert(n == (ssize_t) sizeof(buf));
0169 
0170   rtems_test_assert(
0171     memcmp(&bus->simple_read_write.buf[0], &abc[0], sizeof(buf)) == 0
0172   );
0173 
0174   n = read(fd, &buf[0], sizeof(buf));
0175   rtems_test_assert(n == (ssize_t) sizeof(buf));
0176 
0177   rtems_test_assert(memcmp(&buf[0], &abc[0], sizeof(buf)) == 0);
0178 }
0179 
0180 static void test(void)
0181 {
0182   rtems_resource_snapshot snapshot;
0183   test_bus *bus;
0184   int rv;
0185   int fd;
0186   uint8_t read_mode_8;
0187   uint32_t read_mode_32;
0188   uint32_t read_speed;
0189   uint8_t read_bits_per_word;
0190   uint8_t read_lsb_first;
0191   spi_ioc_transfer msg;
0192 
0193   rtems_resource_snapshot_take(&snapshot);
0194 
0195   bus = (test_bus *) spi_bus_alloc_and_init(sizeof(*bus));
0196   rtems_test_assert(bus != NULL);
0197 
0198   bus->base.transfer = test_transfer;
0199   bus->base.destroy = test_destroy;
0200   bus->base.setup = test_setup;
0201 
0202   bus->simple_read_write.base.transfer = test_simple_read_write_transfer;
0203   bus->device = &bus->simple_read_write.base;
0204 
0205   bus->max_speed_hz = 50000000;
0206 
0207   rv = spi_bus_register(&bus->base, &bus_path[0]);
0208   rtems_test_assert(rv == 0);
0209 
0210   fd = open(&bus_path[0], O_RDWR);
0211   rtems_test_assert(fd >= 0);
0212 
0213   rv = ioctl(fd, SPI_BUS_OBTAIN);
0214   rtems_test_assert(rv == 0);
0215 
0216   rv = ioctl(fd, SPI_BUS_RELEASE);
0217   rtems_test_assert(rv == 0);
0218 
0219   rv = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
0220   rtems_test_assert(rv == 0);
0221   rv = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &read_speed);
0222   rtems_test_assert(rv == 0);
0223   rtems_test_assert(read_speed == speed);
0224 
0225   speed = 60000000;
0226   rv = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
0227   rtems_test_assert(rv == -1);
0228 
0229   rv = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_first);
0230   rtems_test_assert(rv == 0);
0231   rv = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &read_lsb_first);
0232   rtems_test_assert(rv == 0);
0233   rtems_test_assert(read_lsb_first == lsb_first);
0234 
0235   rv = ioctl(fd, SPI_IOC_WR_MODE, &mode_8);
0236   rtems_test_assert(rv == 0);
0237   rv = ioctl(fd, SPI_IOC_RD_MODE, &read_mode_8);
0238   rtems_test_assert(rv == 0);
0239   rtems_test_assert(read_mode_8 == mode_8);
0240 
0241   rv = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word);
0242   rtems_test_assert(rv == 0);
0243   rv = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &read_bits_per_word);
0244   rtems_test_assert(rv == 0);
0245   rtems_test_assert(read_bits_per_word == bits_per_word);
0246 
0247   bits_per_word = 7;
0248   rv = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word);
0249   rtems_test_assert(rv == -1);
0250 
0251   rv = ioctl(fd, SPI_IOC_WR_MODE32, &mode_32);
0252   rtems_test_assert(rv == 0);
0253   rv = ioctl(fd, SPI_IOC_RD_MODE32, &read_mode_32);
0254   rtems_test_assert(rv == 0);
0255   rtems_test_assert(read_mode_32 == mode_32);
0256 
0257   bus->msg_count = 1;
0258   ioctl(fd, SPI_IOC_MESSAGE(8192), &msg);
0259   rtems_test_assert(bus->msg_count == 0);
0260 
0261   test_simple_read_write(bus, fd);
0262 
0263   rv = close(fd);
0264   rtems_test_assert(rv == 0);
0265 
0266   rv = unlink(&bus_path[0]);
0267   rtems_test_assert(rv == 0);
0268 
0269   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0270 }
0271 
0272 static void Init(rtems_task_argument arg)
0273 {
0274   (void)arg;
0275 
0276   TEST_BEGIN();
0277 
0278   test();
0279 
0280   TEST_END();
0281   rtems_test_exit(0);
0282 }
0283 
0284 #define CONFIGURE_MICROSECONDS_PER_TICK 2000
0285 
0286 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0287 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0288 
0289 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 7
0290 
0291 #define CONFIGURE_MAXIMUM_TASKS 1
0292 
0293 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0294 
0295 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0296 
0297 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0298 
0299 #define CONFIGURE_INIT
0300 
0301 #include <rtems/confdefs.h>