Back to home page

LXR

 
 

    


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

0001 /*
0002  * Copyright (c) 2016 embedded brains GmbH & Co. KG
0003  *
0004  * The license and distribution terms for this file may be
0005  * found in the file LICENSE in this distribution or at
0006  * http://www.rtems.org/license/LICENSE.
0007  */
0008 
0009 #include <dev/serial/sc16is752.h>
0010 
0011 #include <assert.h>
0012 #include <fcntl.h>
0013 #include <inttypes.h>
0014 #include <unistd.h>
0015 
0016 #include <dev/spi/spi.h>
0017 
0018 #include "sc16is752-regs.h"
0019 
0020 static void msg_init(
0021   struct spi_ioc_transfer *msg,
0022   uint8_t cs,
0023   uint32_t speed,
0024   size_t len,
0025   uint8_t *rx_buf,
0026   const uint8_t *tx_buf
0027 )
0028 {
0029   msg->rx_buf = rx_buf;
0030   msg->tx_buf = tx_buf;
0031   msg->len = len;
0032   msg->speed_hz = speed;
0033   msg->delay_usecs = 1;
0034   msg->bits_per_word = 8;
0035   msg->cs_change = 0;
0036   msg->rx_nbits = 0;
0037   msg->tx_nbits = 0;
0038   msg->mode = 0;
0039   msg->cs = cs;
0040 }
0041 
0042 static int sc16is752_spi_write_reg(
0043   sc16is752_context *base,
0044   uint8_t addr,
0045   const uint8_t *data,
0046   size_t len
0047 )
0048 {
0049   sc16is752_spi_context *ctx = (sc16is752_spi_context *) base;
0050   spi_ioc_transfer msg[2];
0051   uint8_t unused[SC16IS752_FIFO_DEPTH];
0052   uint8_t tx_cmd;
0053 
0054   _Assert(len < RTEMS_ARRAY_SIZE(unused));
0055 
0056   tx_cmd = addr << 3;
0057   msg_init(&msg[0], ctx->cs, ctx->speed_hz, 1, &unused[0], &tx_cmd);
0058   msg_init(&msg[1], ctx->cs, ctx->speed_hz, len, &unused[0], &data[0]);
0059   msg[1].cs_change = 1;
0060 
0061   return ioctl(ctx->fd, SPI_IOC_MESSAGE(2), &msg[0]);
0062 }
0063 
0064 static int sc16is752_spi_read_reg(
0065   sc16is752_context *base,
0066   uint8_t addr,
0067   uint8_t *data,
0068   size_t len
0069 )
0070 {
0071   sc16is752_spi_context *ctx = (sc16is752_spi_context *) base;
0072   spi_ioc_transfer msg[2];
0073   uint8_t unused;
0074   uint8_t tx_cmd;
0075   uint8_t tx_buf[SC16IS752_FIFO_DEPTH];
0076 
0077   _Assert(len < RTEMS_ARRAY_SIZE(tx_buf));
0078 
0079   tx_cmd = 0x80 | (addr << 3);
0080   msg_init(&msg[0], ctx->cs, ctx->speed_hz, 1, &unused, &tx_cmd);
0081   msg_init(&msg[1], ctx->cs, ctx->speed_hz, len, &data[0], &tx_buf[0]);
0082   msg[1].cs_change = 1;
0083 
0084   return ioctl(ctx->fd, SPI_IOC_MESSAGE(2), &msg[0]);
0085 }
0086 
0087 static int sc16is752_spi_read_2_reg(
0088   sc16is752_context *base,
0089   uint8_t addr_0,
0090   uint8_t addr_1,
0091   uint8_t data[2]
0092 )
0093 {
0094   sc16is752_spi_context *ctx = (sc16is752_spi_context *) base;
0095   spi_ioc_transfer msg[4];
0096   uint8_t unused;
0097   uint8_t tx_cmd_0;
0098   uint8_t tx_cmd_1;
0099 
0100   tx_cmd_0 = 0x80 | (addr_0 << 3);
0101   tx_cmd_1 = 0x80 | (addr_1 << 3);
0102   msg_init(&msg[0], ctx->cs, ctx->speed_hz, 1, &unused, &tx_cmd_0);
0103   msg_init(&msg[1], ctx->cs, ctx->speed_hz, 1, &data[0], &unused);
0104   msg_init(&msg[2], ctx->cs, ctx->speed_hz, 1, &unused, &tx_cmd_1);
0105   msg_init(&msg[3], ctx->cs, ctx->speed_hz, 1, &data[1], &unused);
0106   msg[1].cs_change = 1;
0107   msg[3].cs_change = 1;
0108 
0109   return ioctl(ctx->fd, SPI_IOC_MESSAGE(4), &msg[0]);
0110 }
0111 
0112 static bool sc16is752_spi_first_open(sc16is752_context *base)
0113 {
0114   sc16is752_spi_context *ctx = (sc16is752_spi_context *) base;
0115   ctx->fd = open(ctx->spi_path, O_RDWR);
0116   return ctx->fd >= 0;
0117 }
0118 
0119 static void sc16is752_spi_last_close(sc16is752_context *base)
0120 {
0121   sc16is752_spi_context *ctx = (sc16is752_spi_context *) base;
0122   close(ctx->fd);
0123 }
0124 
0125 rtems_status_code sc16is752_spi_create(
0126   sc16is752_spi_context *ctx,
0127   const char *device_path
0128 )
0129 {
0130   ctx->base.write_reg = sc16is752_spi_write_reg;
0131   ctx->base.read_reg = sc16is752_spi_read_reg;
0132   ctx->base.read_2_reg = sc16is752_spi_read_2_reg;
0133   ctx->base.first_open = sc16is752_spi_first_open;
0134   ctx->base.last_close = sc16is752_spi_last_close;
0135 
0136   return rtems_termios_device_install(
0137     device_path,
0138     &sc16is752_termios_handler,
0139     NULL,
0140     &ctx->base.base
0141   );
0142 }