File indexing completed on 2025-05-11 08:24:11
0001
0002
0003
0004
0005
0006
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 }