From 4a8b96ebfd8aa6f74c4d8094e993938a3e4fbf14 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Thu, 19 May 2016 15:32:03 +0200 Subject: [PATCH 01/14] spi: spilib: first draft Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/README.md | 86 ++++++++++++++ src/spi/driver/spilib/spi-epiphany.h | 8 ++ src/spi/driver/spilib/spi-generic.h | 44 +++++++ src/spi/driver/spilib/spi-simple.h | 29 +++++ src/spi/driver/spilib/spi-uio.h | 51 ++++++++ src/spi/driver/spilib/spi.h | 167 +++++++++++++++++++++++++++ src/spi/driver/spilib/uio-test.c | 82 +++++++++++++ 7 files changed, 467 insertions(+) create mode 100644 src/spi/driver/spilib/README.md create mode 100644 src/spi/driver/spilib/spi-epiphany.h create mode 100644 src/spi/driver/spilib/spi-generic.h create mode 100644 src/spi/driver/spilib/spi-simple.h create mode 100644 src/spi/driver/spilib/spi-uio.h create mode 100644 src/spi/driver/spilib/spi.h create mode 100644 src/spi/driver/spilib/uio-test.c diff --git a/src/spi/driver/spilib/README.md b/src/spi/driver/spilib/README.md new file mode 100644 index 00000000..63f6c06e --- /dev/null +++ b/src/spi/driver/spilib/README.md @@ -0,0 +1,86 @@ +# Driver layer for SPI + +## User API + +```c + +union spi_config { + uint8_t reg; + struct { + unsigned disable:1; + unsigned irq_enable:1; + unsigned cpol:1; + unsigned cpha:1; + unsigned lsb_first:1; + unsigned user_regs_enable:1; /* slave only */ + } __packed; +} __packed; + +union spi_status { + uint8_t reg; + struct { + unsigned split_transaction_data_ready:1; + unsigned transfer_active:1; /* master only */ + unsigned tx_fifo_half_full:1; /* master only */ + } __packed; +} __packed; + +/** + * spi_init - SPI init + * + * @param dev uninitialized device structure + * @param arg target argument (depends on target) + * + * @return 0 on success. Negative on error + */ +int spi_init(spi_dev_t *dev, void *arg); + +/** + * spi_set_config - Set configuration for SPI device + * + * @param dev device structure + * @param config spi configuration + * + */ +void spi_set_config(spi_dev_t *dev, union spi_config *config); + +/** + * spi_get_config - Get configuration for SPI device + * + * @param dev device structure + * @param config spi configuration + * + */ +void spi_get_config(spi_dev_t *dev, union spi_config *config); + +/** + * spi_get_status - Get status for SPI device + * + * @param dev device structure + * @param status spi status + * + */ +void spi_get_status(spi_dev_t *dev, union spi_status *status); + +/** + * spi_read - Read bytes + * + * @param dev device structure + * @param dest destination buffer + * @param count number of bytes + * + */ +void spi_read(spi_dev_t *dev, uint8_t *dest, unsigned count); + +/** + * spi_write - Write bytes + * + * @param dev device structure + * @param src source buffer + * @param count number of bytes + * + */ +void spi_write(spi_dev_t *dev, uint8_t *src, unsigned count); + + +``` diff --git a/src/spi/driver/spilib/spi-epiphany.h b/src/spi/driver/spilib/spi-epiphany.h new file mode 100644 index 00000000..294939d3 --- /dev/null +++ b/src/spi/driver/spilib/spi-epiphany.h @@ -0,0 +1,8 @@ +#pragma once +#ifndef _SPI_INTERNAL +# error "Don't include this file directly" +#endif + +#include "spi-generic.h" + +#error "Epiphany target not implemented" diff --git a/src/spi/driver/spilib/spi-generic.h b/src/spi/driver/spilib/spi-generic.h new file mode 100644 index 00000000..b2cdad20 --- /dev/null +++ b/src/spi/driver/spilib/spi-generic.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef _SPI_INTERNAL +# error "Don't include this file directly" +#endif + +#include + +struct spi_generic_dev { + volatile uint8_t *regs; +}; + +___unused +static void _spi_reg_write(struct spi_generic_dev *dev, unsigned reg, + uint8_t val) +{ + dev->regs[reg] = val; +} + +___unused +static uint8_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) +{ + return dev->regs[reg]; +} + +___unused +static void _spi_read(struct spi_generic_dev *dev, uint8_t *dest, + unsigned count) +{ + while (count--) + *dest++ = dev->regs[SPI_RX]; +} + +___unused +static void _spi_write(struct spi_generic_dev *dev, const uint8_t *src, + unsigned count) +{ + while (count--) { + /* ??? Do we need this (and why isn't there a FULL flag)? */ + while (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_TX_FIFO_HALF_FULL) + ; + + dev->regs[SPI_TX] = *src++; + } +} diff --git a/src/spi/driver/spilib/spi-simple.h b/src/spi/driver/spilib/spi-simple.h new file mode 100644 index 00000000..9f3630e9 --- /dev/null +++ b/src/spi/driver/spilib/spi-simple.h @@ -0,0 +1,29 @@ +#pragma once +#ifndef _SPI_INTERNAL +# error "Don't include this file directly" +#endif + +#include "spi-generic.h" + +typedef struct spi_generic_dev spi_dev_t; + +__unused +static int spi_init(spi_dev_t *dev, void *arg) +{ + if (!arg) +#ifdef SPI_SIMPLE_DEFAULT_ADDR + arg = (void *) SPI_SIMPLE_DEFAULT_ADDR; +#else + return -EINVAL; +#endif + + dev->regs = (struct spi_registers *) arg; + + return 0; +} + +#define spi_fini(dev) /* nop */ +#define spi_reg_write _spi_reg_write +#define spi_reg_read _spi_reg_read +#define spi_write _spi_write +#define spi_read _spi_read diff --git a/src/spi/driver/spilib/spi-uio.h b/src/spi/driver/spilib/spi-uio.h new file mode 100644 index 00000000..72b37e67 --- /dev/null +++ b/src/spi/driver/spilib/spi-uio.h @@ -0,0 +1,51 @@ +#pragma once +#ifndef _SPI_INTERNAL +# error "Don't include this file directly" +#endif + +#include "spi-generic.h" + +#include +#include +#include +#include +#include +#include +#include + +struct spi_uio_dev { + int fd; + struct spi_generic_dev generic; +}; + +typedef struct spi_uio_dev spi_dev_t; + +___unused +static int spi_init(spi_dev_t *dev, void *arg) +{ + char *path = arg; + + dev->fd = open(path, O_RDWR); + if (dev->fd < 0) + return -errno; + + dev->generic.regs = mmap(NULL, 0x1000, PROT_WRITE | PROT_READ, + MAP_SHARED, dev->fd, 0); + if (dev->generic.regs == MAP_FAILED) + return -errno; + + return 0; +} + +___unused +static void spi_fini(spi_dev_t *dev) +{ + munmap((void *) dev->generic.regs, 0x1000); + close(dev->fd); +} + +#define spi_to_generic(dev) (&(dev)->generic) +#define spi_reg_write(dev, reg, val) _spi_reg_write(spi_to_generic((dev)), (reg), (val)) +#define spi_reg_read(dev, reg) _spi_reg_read(spi_to_generic((dev)), (reg)) +#define spi_write(dev, src, count) _spi_write(spi_to_generic((dev)), (src), (count)) +#define spi_read(dev, dest, count) _spi_read(spi_to_generic((dev)), (dest), (count)) diff --git a/src/spi/driver/spilib/spi.h b/src/spi/driver/spilib/spi.h new file mode 100644 index 00000000..ffd6f8b5 --- /dev/null +++ b/src/spi/driver/spilib/spi.h @@ -0,0 +1,167 @@ +#pragma once +#include +#include +#include + +/*** API */ + +/** + * spi_init - SPI init + * + * @param dev uninitialized device structure + * @param arg target argument (depends on target) + * + * @return 0 on success. Negative on error + */ +//int spi_init(spi_dev_t *dev, void *arg); + +/** + * spi_init - SPI finalize + * + * @param dev uninitialized device structure + */ +//void spi_init(spi_dev_t *dev); + + +/** + * spi_set_config - Set configuration for SPI device + * + * @param dev device structure + * @param config spi configuration + * + */ +//void spi_set_config(spi_dev_t *dev, uint8_t config); +#define spi_set_config(dev, config) spi_reg_write((dev), SPI_CONFIG, (config)) + +/** + * spi_get_config - Get configuration for SPI device + * + * @param dev device structure + * + * @return spi config register + */ +//uint8_t spi_get_config(spi_dev_t *dev); +#define spi_get_config(dev) spi_reg_read((dev), SPI_CONFIG) + +/** + * spi_get_status - Get status for SPI device + * + * @param dev device structure + * + */ +//uint8_t spi_get_status(spi_dev_t *dev); +#define spi_get_status(dev) spi_reg_read((dev), SPI_STATUS) + +/** + * spi_read - Read bytes + * + * @param dev device structure + * @param dest destination buffer + * @param count number of bytes + * + */ +//void spi_read(spi_dev_t *dev, uint8_t *dest, unsigned count); + +/** + * spi_write - Write bytes + * + * @param dev device structure + * @param src source buffer + * @param count number of bytes + * + */ +//void spi_write(spi_dev_t *dev, const uint8_t *src, unsigned count); + + +/*** Raw register access API */ + +#define SPI_CONFIG 0x00 +#define SPI_STATUS 0x01 +#define SPI_CLKDIV 0x02 +#define SPI_TX 0x08 /* master only */ +#define SPI_RX 0x10 +#define SPI_USER0 0x20 /* slave only, first user register */ + +#define SPI_CONFIG_DISABLE (1 << 0) +#define SPI_CONFIG_IRQ_ENABLE (1 << 1) +#define SPI_CONFIG_CPOL (1 << 2) +#define SPI_CONFIG_CPHA (1 << 3) +#define SPI_CONFIG_LSB (1 << 4) +#define SPI_CONFIG_USER_REGS (1 << 5)/* slave only */ + +#define SPI_STATUS_SPLIT (1 << 0) +#define SPI_STATUS_TRANSFER_ACTIVE (1 << 1) /* master only */ +#define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 2) /* master only */ + +/** + * spi_reg_write - Set SPI device register + * + * @param dev device structure + * @param reg register + * @param val value + * + */ +//void spi_reg_write(spi_dev_t *dev, unsigned reg, uint8_t val); + +/** + * spi_reg_read - Get SPI device register + * + * @param dev device structure + * @param reg register + * + * @return register value + */ +//uint8_t spi_reg_write(spi_dev_t *dev, unsigned reg); + +#ifndef ___unused +# if defined(__GNUC__) || defined(__clang__) +# define ___unused __attribute__((unused)) +# else +# define ___unused +# endif +#endif + +#ifndef __packed +# if defined(__GNUC__) || defined(__clang__) +# define __packed __attribute__((packed)) +# else +# define __packed +# endif +#endif + +#ifndef __aligned +# if defined(__GNUC__) || defined(__clang__) +# define __aligned(X) __attribute__((aligned(X))) +# else +# define __aligned(X) +# endif +#endif + +/* Targets */ +#define SPI_TARGET_SIMPLE 0 +#define SPI_TARGET_EPIPHANY 1 +#define SPI_TARGET_UIO 2 + +/* Autodetect target */ +#ifndef SPI_TARGET +# if defined(__epiphany__) +# define SPI_TARGET SPI_TARGET_EPIPHANY +# elif defined(__linux__) +# define SPI_TARGET SPI_TARGET_UIO +#else +# define SPI_TARGET SPI_TARGET_SIMPLE +# endif +#endif + + +#define _SPI_INTERNAL +#if SPI_TARGET == SPI_TARGET_SIMPLE +# include "spi-simple.h" +#elif SPI_TARGET == SPI_TARGET_EPIPHANY +# include "spi-epiphany.h" +#elif SPI_TARGET == SPI_TARGET_UIO +# include "spi-uio.h" +#else +# error "Invalid SPI_TARGET" +#endif +#undef _SPI_INTERNAL diff --git a/src/spi/driver/spilib/uio-test.c b/src/spi/driver/spilib/uio-test.c new file mode 100644 index 00000000..5afc5a4c --- /dev/null +++ b/src/spi/driver/spilib/uio-test.c @@ -0,0 +1,82 @@ +#include "spi.h" +#define SPI_TARGET SPI_TARGET_UIO +#include + +/* Assume master/slave pins are connected in loop-back */ + +/* TODO: Add burst */ + +/* OH SPI slave specifics */ +struct oh_spi_mosi_pkt { + struct { + unsigned addr:6; + unsigned mode:2; + } __attribute__((packed)); + uint8_t data; +} __attribute__((packed)); + +struct oh_spi_miso_pkt { + unsigned:8; + uint8_t data; +} __attribute__((packed)); + + +#define SLAVE_WRITE 0x00 +#define SLAVE_READ 0x02 +#define SLAVE_FETCH 0x03 + +uint8_t slave_access(spi_dev_t *dev, unsigned mode, unsigned addr, uint8_t data) +{ + struct oh_spi_miso_pkt miso; + struct oh_spi_mosi_pkt mosi = { + .addr = addr, + .mode = mode, + .data = data, + }; + spi_write(dev, (uint8_t *) &mosi, sizeof(mosi)); + spi_read(dev, (uint8_t *) &miso, sizeof(miso)); + + return miso.data; +} + +void slave_write(spi_dev_t *dev, unsigned addr, uint8_t data) +{ + slave_access(dev, SLAVE_WRITE, addr, data); +} + +uint8_t slave_read(spi_dev_t *dev, unsigned addr) +{ + return slave_access(dev, SLAVE_READ, addr, 0); +} + +int main() +{ + int i; + spi_dev_t master; + uint8_t slave_regs[13]; + bool fail = false; + + if (spi_init(&master, (void *) "/dev/uio0")) { + perror("spi_init"); + return 1; + } + + for (i = 0; i < 13; i++) + slave_write(&master, SPI_USER0 + i, i); + + for (i = 0; i < 13; i++) + slave_regs[i] = slave_read(&master, SPI_USER0 + i); + + printf("slave user regs: "); + for (i = 0; i < 13; i++) + printf("0x%2x ", (int) slave_regs[i]); + printf("\n"); + + for (i = 0; i < 13; i++) + if (slave_regs[i] != i) + fail = true; + + spi_fini(&master); + + return fail ? 1 : 0; +} From 62a3097bd978c4f695913c5cb9fd805d8893d678 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Thu, 19 May 2016 18:40:28 +0200 Subject: [PATCH 02/14] spi: spilib: No read/write functions, just transfer Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/README.md | 111 +++++++++++++++++++--------- src/spi/driver/spilib/spi-generic.h | 47 ++++++++---- src/spi/driver/spilib/spi-uio.h | 4 +- src/spi/driver/spilib/spi.h | 35 ++++++--- src/spi/driver/spilib/test.c | 27 +++++++ src/spi/driver/spilib/uio-test.c | 9 +-- 6 files changed, 167 insertions(+), 66 deletions(-) create mode 100644 src/spi/driver/spilib/test.c diff --git a/src/spi/driver/spilib/README.md b/src/spi/driver/spilib/README.md index 63f6c06e..f306c819 100644 --- a/src/spi/driver/spilib/README.md +++ b/src/spi/driver/spilib/README.md @@ -3,28 +3,6 @@ ## User API ```c - -union spi_config { - uint8_t reg; - struct { - unsigned disable:1; - unsigned irq_enable:1; - unsigned cpol:1; - unsigned cpha:1; - unsigned lsb_first:1; - unsigned user_regs_enable:1; /* slave only */ - } __packed; -} __packed; - -union spi_status { - uint8_t reg; - struct { - unsigned split_transaction_data_ready:1; - unsigned transfer_active:1; /* master only */ - unsigned tx_fifo_half_full:1; /* master only */ - } __packed; -} __packed; - /** * spi_init - SPI init * @@ -35,6 +13,14 @@ union spi_status { */ int spi_init(spi_dev_t *dev, void *arg); +/** + * spi_init - SPI finalize + * + * @param dev uninitialized device structure + */ +void spi_init(spi_dev_t *dev); + + /** * spi_set_config - Set configuration for SPI device * @@ -42,45 +28,102 @@ int spi_init(spi_dev_t *dev, void *arg); * @param config spi configuration * */ -void spi_set_config(spi_dev_t *dev, union spi_config *config); +void spi_set_config(spi_dev_t *dev, uint8_t config); +#define spi_set_config(dev, config) spi_reg_write((dev), SPI_CONFIG, (config)) /** * spi_get_config - Get configuration for SPI device * * @param dev device structure - * @param config spi configuration * + * @return spi config register */ -void spi_get_config(spi_dev_t *dev, union spi_config *config); +uint8_t spi_get_config(spi_dev_t *dev); +#define spi_get_config(dev) spi_reg_read((dev), SPI_CONFIG) /** * spi_get_status - Get status for SPI device * * @param dev device structure - * @param status spi status * */ -void spi_get_status(spi_dev_t *dev, union spi_status *status); +uint8_t spi_get_status(spi_dev_t *dev); +#define spi_get_status(dev) spi_reg_read((dev), SPI_STATUS) /** - * spi_read - Read bytes + * spi_set_clkdiv - Set master clock divider * * @param dev device structure - * @param dest destination buffer - * @param count number of bytes + * @param config spi configuration * */ -void spi_read(spi_dev_t *dev, uint8_t *dest, unsigned count); +void spi_set_clkdiv(spi_dev_t *dev, uint8_t clkdiv); +#define spi_set_clkdiv(dev, clkdiv) spi_reg_write((dev), SPI_CLKDIV, (clkdiv)) /** - * spi_write - Write bytes + * spi_get_clkdiv - Get master clock divider * * @param dev device structure - * @param src source buffer + * + * @return clock divider register + * + */ +uint8_t spi_get_clkdiv(spi_dev_t *dev); +#define spi_get_clkdiv(dev) spi_reg_read((dev), SPI_CLKDIV) + +/** + * spi_transter - Perform one SPI transfer + * + * @param dev device structure + * @param tx transmit data buffer + * @param rx receive data buffer * @param count number of bytes * */ -void spi_write(spi_dev_t *dev, uint8_t *src, unsigned count); +void spi_transfer(spi_dev_t *dev, uint8_t *tx, uint8_t *rx, unsigned count); + +/*** Raw register access API */ + +#define SPI_CONFIG 0x00 +#define SPI_STATUS 0x01 +#define SPI_CLKDIV 0x02 +#define SPI_TX 0x08 /* master only */ +#define SPI_RX 0x10 +#define SPI_USER0 0x20 /* slave only, first user register */ + +#define SPI_CONFIG_DISABLE (1 << 0) +#define SPI_CONFIG_IRQ_ENABLE (1 << 1) +#define SPI_CONFIG_CPOL (1 << 2) +#define SPI_CONFIG_CPHA (1 << 3) +#define SPI_CONFIG_LSB (1 << 4) +#define SPI_CONFIG_USER_REGS (1 << 5)/* slave only */ + +#define SPI_STATUS_SPLIT (1 << 0) +#define SPI_STATUS_STATE (3 << 1) /* master only */ +#define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 3) /* master only */ + +#define SPI_STATE_IDLE(status) ((status) & SPI_STATUS_STATE == 0) +#define SPI_STATE_SETUP(status) ((status) & SPI_STATUS_STATE == 1) +#define SPI_STATE_DATA(status) ((status) & SPI_STATUS_STATE == 2) +#define SPI_STATE_HOLD(status) ((status) & SPI_STATUS_STATE == 3) +/** + * spi_reg_write - Set SPI device register + * + * @param dev device structure + * @param reg register + * @param val value + * + */ +void spi_reg_write(spi_dev_t *dev, unsigned reg, uint8_t val); +/** + * spi_reg_read - Get SPI device register + * + * @param dev device structure + * @param reg register + * + * @return register value + */ +uint8_t spi_reg_write(spi_dev_t *dev, unsigned reg); ``` diff --git a/src/spi/driver/spilib/spi-generic.h b/src/spi/driver/spilib/spi-generic.h index b2cdad20..4a40ee4b 100644 --- a/src/spi/driver/spilib/spi-generic.h +++ b/src/spi/driver/spilib/spi-generic.h @@ -23,22 +23,41 @@ static uint8_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) } ___unused -static void _spi_read(struct spi_generic_dev *dev, uint8_t *dest, - unsigned count) +static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, + void *rx, unsigned count) { - while (count--) - *dest++ = dev->regs[SPI_RX]; -} + unsigned i; + uint8_t dummy_rx = 0; + const uint8_t *u8_tx = (const uint8_t *) tx; + uint8_t *u8_rx = (uint8_t *) rx; -___unused -static void _spi_write(struct spi_generic_dev *dev, const uint8_t *src, - unsigned count) -{ - while (count--) { - /* ??? Do we need this (and why isn't there a FULL flag)? */ - while (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_TX_FIFO_HALF_FULL) - ; + /* TODO: Flush queues */ + + /* TODO: Enable TX */ - dev->regs[SPI_TX] = *src++; + /* TODO: Tell master to hold SS */ + + while (count) { + /* TODO: Check RX FIFO full instead */ + for (i = 0; + ! (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_TX_FIFO_HALF_FULL); + i++, count--) { + if (tx) + dev->regs[SPI_TX] = *u8_tx++; + else + dev->regs[SPI_TX] = 0; + } + while (i--) { + if (rx) + *u8_rx++ = dev->regs[SPI_RX]; + else + dummy_rx = dev->regs[SPI_RX]; + } } + + (void) dummy_rx; + + /* TODO: Tell master to release SS */ + + /* TODO: Disable TX */ } diff --git a/src/spi/driver/spilib/spi-uio.h b/src/spi/driver/spilib/spi-uio.h index 72b37e67..ff59b7bb 100644 --- a/src/spi/driver/spilib/spi-uio.h +++ b/src/spi/driver/spilib/spi-uio.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -47,5 +48,4 @@ static void spi_fini(spi_dev_t *dev) #define spi_to_generic(dev) (&(dev)->generic) #define spi_reg_write(dev, reg, val) _spi_reg_write(spi_to_generic((dev)), (reg), (val)) #define spi_reg_read(dev, reg) _spi_reg_read(spi_to_generic((dev)), (reg)) -#define spi_write(dev, src, count) _spi_write(spi_to_generic((dev)), (src), (count)) -#define spi_read(dev, dest, count) _spi_read(spi_to_generic((dev)), (dest), (count)) +#define spi_transfer(dev, tx, rx, count) _spi_transfer(spi_to_generic((dev)), (tx), (rx), (count)) diff --git a/src/spi/driver/spilib/spi.h b/src/spi/driver/spilib/spi.h index ffd6f8b5..1859d396 100644 --- a/src/spi/driver/spilib/spi.h +++ b/src/spi/driver/spilib/spi.h @@ -53,25 +53,36 @@ #define spi_get_status(dev) spi_reg_read((dev), SPI_STATUS) /** - * spi_read - Read bytes + * spi_set_clkdiv - Set master clock divider * * @param dev device structure - * @param dest destination buffer - * @param count number of bytes + * @param config spi configuration * */ -//void spi_read(spi_dev_t *dev, uint8_t *dest, unsigned count); +//void spi_set_clkdiv(spi_dev_t *dev, uint8_t clkdiv); +#define spi_set_clkdiv(dev, clkdiv) spi_reg_write((dev), SPI_CLKDIV, (clkdiv)) /** - * spi_write - Write bytes + * spi_get_clkdiv - Get master clock divider * * @param dev device structure - * @param src source buffer - * @param count number of bytes + * + * @return clock divider register * */ -//void spi_write(spi_dev_t *dev, const uint8_t *src, unsigned count); +//uint8_t spi_get_clkdiv(spi_dev_t *dev); +#define spi_get_clkdiv(dev) spi_reg_read((dev), SPI_CLKDIV) +/** + * spi_transter - Perform one SPI transfer + * + * @param dev device structure + * @param tx transmit data buffer + * @param rx receive data buffer + * @param count number of bytes + * + */ +//void spi_transfer(spi_dev_t *dev, uint8_t *tx, uint8_t *rx, unsigned count); /*** Raw register access API */ @@ -90,9 +101,13 @@ #define SPI_CONFIG_USER_REGS (1 << 5)/* slave only */ #define SPI_STATUS_SPLIT (1 << 0) -#define SPI_STATUS_TRANSFER_ACTIVE (1 << 1) /* master only */ -#define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 2) /* master only */ +#define SPI_STATUS_STATE (3 << 1) /* master only */ +#define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 3) /* master only */ +#define SPI_STATE_IDLE(status) ((status) & SPI_STATUS_STATE == 0) +#define SPI_STATE_SETUP(status) ((status) & SPI_STATUS_STATE == 1) +#define SPI_STATE_DATA(status) ((status) & SPI_STATUS_STATE == 2) +#define SPI_STATE_HOLD(status) ((status) & SPI_STATUS_STATE == 3) /** * spi_reg_write - Set SPI device register * diff --git a/src/spi/driver/spilib/test.c b/src/spi/driver/spilib/test.c new file mode 100644 index 00000000..bf8b9f65 --- /dev/null +++ b/src/spi/driver/spilib/test.c @@ -0,0 +1,27 @@ +#define SPI_TARGET SPI_TARGET_SIMPLE +#define SPI_SIMPLE_DEFAULT_ADDR 0xdeadbee0 + +#include +#include "spi.h" + +int main() +{ + int val; + spi_dev_t dev; + + if (spi_init(&dev, NULL)) + exit(EXIT_FAILURE); + + spi_set_direction(&dev, 63, SPI_DIR_IN); + spi_set_direction(&dev, 0, SPI_DIR_OUT); + + val = 1; + spi_write(&dev, 0, val); + val = spi_read(&dev, 63); + spi_write(&dev, 0, ~val & 1); + val = spi_read(&dev, 63); + spi_toggle(&dev, 0); + val = spi_read(&dev, 63); + + return val; +} diff --git a/src/spi/driver/spilib/uio-test.c b/src/spi/driver/spilib/uio-test.c index 5afc5a4c..dd2c7061 100644 --- a/src/spi/driver/spilib/uio-test.c +++ b/src/spi/driver/spilib/uio-test.c @@ -8,10 +8,8 @@ /* OH SPI slave specifics */ struct oh_spi_mosi_pkt { - struct { - unsigned addr:6; - unsigned mode:2; - } __attribute__((packed)); + unsigned addr:6; + unsigned mode:2; uint8_t data; } __attribute__((packed)); @@ -33,8 +31,7 @@ uint8_t slave_access(spi_dev_t *dev, unsigned mode, unsigned addr, uint8_t data) .mode = mode, .data = data, }; - spi_write(dev, (uint8_t *) &mosi, sizeof(mosi)); - spi_read(dev, (uint8_t *) &miso, sizeof(miso)); + spi_transfer(dev, (uint8_t *) &mosi, &miso, sizeof(mosi)); return miso.data; } From 8eeb5a79c8849dae67b1c7bc597a488aa5d49e9f Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Thu, 19 May 2016 18:41:21 +0200 Subject: [PATCH 03/14] spi: parallella_spi: Fix pin directions Signed-off-by: Ola Jeppsson --- src/spi/hdl/parallella_spi.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spi/hdl/parallella_spi.v b/src/spi/hdl/parallella_spi.v index 46e14fc1..f884aad6 100644 --- a/src/spi/hdl/parallella_spi.v +++ b/src/spi/hdl/parallella_spi.v @@ -124,7 +124,7 @@ module parallella_spi(/*AUTOARG*/ assign spi_m_sclk = gpio_out[3]; /* NOTE: 0 = in, 1 = out */ - assign gpio_dir[NGPIO-1:0] = {{(NGPIO-8){1'b0}}, 8'b01001011}; + assign gpio_dir[NGPIO-1:0] = {{(NGPIO-11){1'b0}}, 8'b01001011, 3'b000}; assign constant_zero = 1'b0; assign constant_one = 1'b1; From cabc3593a3a541cbedf57e26d43d0c9b522bc7fd Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Thu, 19 May 2016 21:21:27 +0000 Subject: [PATCH 04/14] spi: spilib: working (w/ wrong register addresses) Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/spi-generic.h | 81 +++++++++++++++++++++++------ src/spi/driver/spilib/spi.h | 11 ++-- src/spi/driver/spilib/uio-test.c | 64 ++++++++++++++++++----- 3 files changed, 122 insertions(+), 34 deletions(-) diff --git a/src/spi/driver/spilib/spi-generic.h b/src/spi/driver/spilib/spi-generic.h index 4a40ee4b..e1ccffb3 100644 --- a/src/spi/driver/spilib/spi-generic.h +++ b/src/spi/driver/spilib/spi-generic.h @@ -6,7 +6,7 @@ #include struct spi_generic_dev { - volatile uint8_t *regs; + volatile uint32_t *regs; }; ___unused @@ -17,7 +17,7 @@ static void _spi_reg_write(struct spi_generic_dev *dev, unsigned reg, } ___unused -static uint8_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) +static uint32_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) { return dev->regs[reg]; } @@ -30,34 +30,83 @@ static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, uint8_t dummy_rx = 0; const uint8_t *u8_tx = (const uint8_t *) tx; uint8_t *u8_rx = (uint8_t *) rx; + uint8_t config; /* TODO: Flush queues */ /* TODO: Enable TX */ + /* TODO: Tell master to hold SS */ + config = _spi_reg_read(dev, SPI_CONFIG); + while (count) { + union buf { + uint32_t u32; + uint16_t u16[2]; + uint8_t u8[4]; + } ___packed; + union buf rx0 = { 0 }, rx1 = { 0 }, tx0 = { 0 }, tx1 = { 0 }; + union buf *dst = (union buf *) &dev->regs[SPI_TX]; + + if (tx) + memcpy(&tx0.u32, u8_tx, count > 4 ? 4 : count); + + /* Enable TX */ + config &= ~SPI_CONFIG_DISABLE; + _spi_reg_write(dev, SPI_CONFIG, config); + + /* Disable TX */ + //config |= SPI_CONFIG_DISABLE; + //_spi_reg_write(dev, SPI_CONFIG, config); + /* TODO: Check RX FIFO full instead */ - for (i = 0; - ! (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_TX_FIFO_HALF_FULL); - i++, count--) { - if (tx) - dev->regs[SPI_TX] = *u8_tx++; - else - dev->regs[SPI_TX] = 0; + for (i = 0; count && i < 4 /* TODO: 8 */ ;) { + /*! (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_TX_FIFO_HALF_FULL);) {*/ + switch (count) { + case 1: + dst->u8[0] = tx0.u8[0]; + count -= 1; i += 1; + break; + case 2: + dst->u16[0] = tx0.u16[0]; + count -= 2; i += 2; + break; + case 3: + dst->u16[0] = tx0.u16[0]; + dst->u8[0] = tx0.u8[3]; + count -= 3; i += 3; + break; + default: + dst->u32 = tx0.u32; + count -= 4; i += 4; + }; } - while (i--) { - if (rx) - *u8_rx++ = dev->regs[SPI_RX]; - else - dummy_rx = dev->regs[SPI_RX]; + ///* Enable TX */ + //config &= ~SPI_CONFIG_DISABLE; + //_spi_reg_write(dev, SPI_CONFIG, config); + + while (!SPI_STATE_IDLE(_spi_reg_read(dev, SPI_STATUS))) + ; + + rx0.u32 = dev->regs[SPI_RX0]; + rx1.u32 = dev->regs[SPI_RX1]; + + //printf("rx0: %08x\n", rx0.u32); + + int j; + //printf("i: %d\n", i); + if (rx) { + //printf("i: %d\n", i); + for (j = 0; i, j < 4; i--, j++) + *u8_rx++ = rx0.u8[j]; + for (j = 0; i, j < 4; i--, j++) + *u8_rx++ = rx1.u8[j]; } } (void) dummy_rx; /* TODO: Tell master to release SS */ - - /* TODO: Disable TX */ } diff --git a/src/spi/driver/spilib/spi.h b/src/spi/driver/spilib/spi.h index 1859d396..7632505a 100644 --- a/src/spi/driver/spilib/spi.h +++ b/src/spi/driver/spilib/spi.h @@ -90,7 +90,8 @@ #define SPI_STATUS 0x01 #define SPI_CLKDIV 0x02 #define SPI_TX 0x08 /* master only */ -#define SPI_RX 0x10 +#define SPI_RX0 0x10 +#define SPI_RX1 0x14 #define SPI_USER0 0x20 /* slave only, first user register */ #define SPI_CONFIG_DISABLE (1 << 0) @@ -104,10 +105,10 @@ #define SPI_STATUS_STATE (3 << 1) /* master only */ #define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 3) /* master only */ -#define SPI_STATE_IDLE(status) ((status) & SPI_STATUS_STATE == 0) -#define SPI_STATE_SETUP(status) ((status) & SPI_STATUS_STATE == 1) -#define SPI_STATE_DATA(status) ((status) & SPI_STATUS_STATE == 2) -#define SPI_STATE_HOLD(status) ((status) & SPI_STATUS_STATE == 3) +#define SPI_STATE_IDLE(status) (((status) & SPI_STATUS_STATE) >> 1 == 0) +#define SPI_STATE_SETUP(status) (((status) & SPI_STATUS_STATE) >> 1 == 1) +#define SPI_STATE_DATA(status) (((status) & SPI_STATUS_STATE) >> 1 == 2) +#define SPI_STATE_HOLD(status) (((status) & SPI_STATUS_STATE) >> 1 == 3) /** * spi_reg_write - Set SPI device register * diff --git a/src/spi/driver/spilib/uio-test.c b/src/spi/driver/spilib/uio-test.c index dd2c7061..9072341e 100644 --- a/src/spi/driver/spilib/uio-test.c +++ b/src/spi/driver/spilib/uio-test.c @@ -14,8 +14,8 @@ struct oh_spi_mosi_pkt { } __attribute__((packed)); struct oh_spi_miso_pkt { - unsigned:8; uint8_t data; + unsigned fook:8; } __attribute__((packed)); @@ -31,7 +31,7 @@ uint8_t slave_access(spi_dev_t *dev, unsigned mode, unsigned addr, uint8_t data) .mode = mode, .data = data, }; - spi_transfer(dev, (uint8_t *) &mosi, &miso, sizeof(mosi)); + spi_transfer(dev, &mosi, &miso, sizeof(mosi)); return miso.data; } @@ -58,20 +58,58 @@ int main() return 1; } - for (i = 0; i < 13; i++) - slave_write(&master, SPI_USER0 + i, i); + printf("status: %#x\n", spi_reg_read(&master, SPI_STATUS)); - for (i = 0; i < 13; i++) - slave_regs[i] = slave_read(&master, SPI_USER0 + i); + printf("clkdiv: %#x\n", spi_reg_read(&master, SPI_CLKDIV)); - printf("slave user regs: "); - for (i = 0; i < 13; i++) - printf("0x%2x ", (int) slave_regs[i]); - printf("\n"); + printf("config: %#x\n", spi_reg_read(&master, SPI_CONFIG)); - for (i = 0; i < 13; i++) - if (slave_regs[i] != i) - fail = true; + printf("spi_reg_read(0x31): %#x\n", spi_reg_read(&master, 31)); + spi_set_clkdiv(&master, 0x5); + + int j; + //for (j = 0; j < 100000; j++) { + for (j = 0; j < 1; j++) { + + for (i = 0; i < 13; i++) + slave_write(&master, SPI_USER0 + i, i * 2); + + for (i = 0; i < 13; i++) + slave_regs[i] = slave_read(&master, SPI_USER0 + i); + +#if 1 + printf("slave user regs: "); + for (i = 0; i < 13; i++) + printf("0x%02x ", (int) slave_regs[i]); + printf("\n"); +#endif + + for (i = 0; i < 13; i++) + if (slave_regs[i] != i * 2) + fail = true; + + for (i = 0; i < 13; i++) + slave_write(&master, SPI_USER0 + i, i); + + for (i = 0; i < 13; i++) + slave_regs[i] = slave_read(&master, SPI_USER0 + i); +#if 1 + printf("slave user regs: "); + for (i = 0; i < 13; i++) + printf("0x%02x ", (int) slave_regs[i]); + printf("\n"); +#endif + + for (i = 0; i < 13; i++) + if (slave_regs[i] != i) + fail = true; + + if (fail) + break; + +// if (!(j % 10000)) +// printf("j=%d\n", j); + } spi_fini(&master); From e3d7e9b706ad4e0e42b14fabc09a424725882c31 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Fri, 20 May 2016 15:14:37 +0000 Subject: [PATCH 05/14] spi: spilib: Go back to original register offsets Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/spi-generic.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/spi/driver/spilib/spi-generic.h b/src/spi/driver/spilib/spi-generic.h index e1ccffb3..5f369e8c 100644 --- a/src/spi/driver/spilib/spi-generic.h +++ b/src/spi/driver/spilib/spi-generic.h @@ -4,22 +4,29 @@ #endif #include +#include struct spi_generic_dev { - volatile uint32_t *regs; + volatile uint8_t *regs; }; ___unused static void _spi_reg_write(struct spi_generic_dev *dev, unsigned reg, - uint8_t val) + uint32_t val) { - dev->regs[reg] = val; + if (reg & 3) + dev->regs[reg] = (uint8_t) val; + else + *(uint32_t *) &dev->regs[reg] = val; } ___unused static uint32_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) { - return dev->regs[reg]; + if (reg & 3) + return (uint32_t) dev->regs[reg]; + else + return *(uint32_t *) &dev->regs[reg]; } ___unused @@ -90,8 +97,8 @@ static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, while (!SPI_STATE_IDLE(_spi_reg_read(dev, SPI_STATUS))) ; - rx0.u32 = dev->regs[SPI_RX0]; - rx1.u32 = dev->regs[SPI_RX1]; + rx0.u32 = *(uint32_t *) &dev->regs[SPI_RX0]; + rx1.u32 = *(uint32_t *) &dev->regs[SPI_RX1]; //printf("rx0: %08x\n", rx0.u32); From 697361e23d51d2d4748887ffef79a080cc4781d0 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Fri, 20 May 2016 15:53:41 +0000 Subject: [PATCH 06/14] spi: spilib: upate uio-test Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/uio-test.c | 37 +++++++++++++++++--------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/spi/driver/spilib/uio-test.c b/src/spi/driver/spilib/uio-test.c index 9072341e..9ad6ee01 100644 --- a/src/spi/driver/spilib/uio-test.c +++ b/src/spi/driver/spilib/uio-test.c @@ -64,12 +64,11 @@ int main() printf("config: %#x\n", spi_reg_read(&master, SPI_CONFIG)); - printf("spi_reg_read(0x31): %#x\n", spi_reg_read(&master, 31)); + printf("spi_reg_read(28): %#x\n", spi_reg_read(&master, 28)); spi_set_clkdiv(&master, 0x5); int j; - //for (j = 0; j < 100000; j++) { - for (j = 0; j < 1; j++) { + for (j = 0; j < 10000; j++) { for (i = 0; i < 13; i++) slave_write(&master, SPI_USER0 + i, i * 2); @@ -77,12 +76,12 @@ int main() for (i = 0; i < 13; i++) slave_regs[i] = slave_read(&master, SPI_USER0 + i); -#if 1 - printf("slave user regs: "); - for (i = 0; i < 13; i++) - printf("0x%02x ", (int) slave_regs[i]); - printf("\n"); -#endif + if (j == 0) { + printf("slave user regs: "); + for (i = 0; i < 13; i++) + printf("0x%02x ", (int) slave_regs[i]); + printf("\n"); + } for (i = 0; i < 13; i++) if (slave_regs[i] != i * 2) @@ -93,12 +92,13 @@ int main() for (i = 0; i < 13; i++) slave_regs[i] = slave_read(&master, SPI_USER0 + i); -#if 1 - printf("slave user regs: "); - for (i = 0; i < 13; i++) - printf("0x%02x ", (int) slave_regs[i]); - printf("\n"); -#endif + + if (j == 0) { + printf("slave user regs: "); + for (i = 0; i < 13; i++) + printf("0x%02x ", (int) slave_regs[i]); + printf("\n"); + } for (i = 0; i < 13; i++) if (slave_regs[i] != i) @@ -107,11 +107,14 @@ int main() if (fail) break; -// if (!(j % 10000)) -// printf("j=%d\n", j); } spi_fini(&master); + if (fail) + printf("FAIL\n"); + else + printf("PASS\n"); + return fail ? 1 : 0; } From c21d5b16a74dabf5b6e78e7392fc63df6f240178 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 24 May 2016 14:38:11 +0000 Subject: [PATCH 07/14] spi: spilib: Add __spi prefix to convenience macros Add __spi prefix to __unused / __packed / __aligned to avoid name clashes with system headers. Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/spi-generic.h | 8 ++++---- src/spi/driver/spilib/spi-simple.h | 2 +- src/spi/driver/spilib/spi-uio.h | 4 ++-- src/spi/driver/spilib/spi.h | 18 +++++++++--------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/spi/driver/spilib/spi-generic.h b/src/spi/driver/spilib/spi-generic.h index 5f369e8c..d04050bc 100644 --- a/src/spi/driver/spilib/spi-generic.h +++ b/src/spi/driver/spilib/spi-generic.h @@ -10,7 +10,7 @@ struct spi_generic_dev { volatile uint8_t *regs; }; -___unused +__spi_unused static void _spi_reg_write(struct spi_generic_dev *dev, unsigned reg, uint32_t val) { @@ -20,7 +20,7 @@ static void _spi_reg_write(struct spi_generic_dev *dev, unsigned reg, *(uint32_t *) &dev->regs[reg] = val; } -___unused +__spi_unused static uint32_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) { if (reg & 3) @@ -29,7 +29,7 @@ static uint32_t _spi_reg_read(struct spi_generic_dev *dev, unsigned reg) return *(uint32_t *) &dev->regs[reg]; } -___unused +__spi_unused static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, void *rx, unsigned count) { @@ -53,7 +53,7 @@ static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, uint32_t u32; uint16_t u16[2]; uint8_t u8[4]; - } ___packed; + } __spi_packed; union buf rx0 = { 0 }, rx1 = { 0 }, tx0 = { 0 }, tx1 = { 0 }; union buf *dst = (union buf *) &dev->regs[SPI_TX]; diff --git a/src/spi/driver/spilib/spi-simple.h b/src/spi/driver/spilib/spi-simple.h index 9f3630e9..fd0f1cde 100644 --- a/src/spi/driver/spilib/spi-simple.h +++ b/src/spi/driver/spilib/spi-simple.h @@ -7,7 +7,7 @@ typedef struct spi_generic_dev spi_dev_t; -__unused +__spi_unused static int spi_init(spi_dev_t *dev, void *arg) { if (!arg) diff --git a/src/spi/driver/spilib/spi-uio.h b/src/spi/driver/spilib/spi-uio.h index ff59b7bb..e0355eff 100644 --- a/src/spi/driver/spilib/spi-uio.h +++ b/src/spi/driver/spilib/spi-uio.h @@ -21,7 +21,7 @@ struct spi_uio_dev { typedef struct spi_uio_dev spi_dev_t; -___unused +__spi_unused static int spi_init(spi_dev_t *dev, void *arg) { char *path = arg; @@ -38,7 +38,7 @@ static int spi_init(spi_dev_t *dev, void *arg) return 0; } -___unused +__spi_unused static void spi_fini(spi_dev_t *dev) { munmap((void *) dev->generic.regs, 0x1000); diff --git a/src/spi/driver/spilib/spi.h b/src/spi/driver/spilib/spi.h index 7632505a..79254d33 100644 --- a/src/spi/driver/spilib/spi.h +++ b/src/spi/driver/spilib/spi.h @@ -129,27 +129,27 @@ */ //uint8_t spi_reg_write(spi_dev_t *dev, unsigned reg); -#ifndef ___unused +#ifndef __spi_unused # if defined(__GNUC__) || defined(__clang__) -# define ___unused __attribute__((unused)) +# define __spi_unused __attribute__((unused)) # else -# define ___unused +# define __spi_unused # endif #endif -#ifndef __packed +#ifndef __spi_packed # if defined(__GNUC__) || defined(__clang__) -# define __packed __attribute__((packed)) +# define __spi_packed __attribute__((packed)) # else -# define __packed +# define __spi_packed # endif #endif -#ifndef __aligned +#ifndef __spi_aligned # if defined(__GNUC__) || defined(__clang__) -# define __aligned(X) __attribute__((aligned(X))) +# define __spi_aligned(X) __attribute__((aligned(X))) # else -# define __aligned(X) +# define __spi_aligned(X) # endif #endif From 352573ba566bab5a9c43046cfb2485ea2e23703a Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 24 May 2016 14:42:35 +0000 Subject: [PATCH 08/14] spi: spilib: Update generic spi_transfer Support up to 8 byte transfers. Wait for RX to complete before reading from deserializer regs. Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/spi-generic.h | 134 +++++++++++++++++----------- src/spi/driver/spilib/spi.h | 10 +-- 2 files changed, 85 insertions(+), 59 deletions(-) diff --git a/src/spi/driver/spilib/spi-generic.h b/src/spi/driver/spilib/spi-generic.h index d04050bc..8887fe70 100644 --- a/src/spi/driver/spilib/spi-generic.h +++ b/src/spi/driver/spilib/spi-generic.h @@ -17,7 +17,8 @@ static void _spi_reg_write(struct spi_generic_dev *dev, unsigned reg, if (reg & 3) dev->regs[reg] = (uint8_t) val; else - *(uint32_t *) &dev->regs[reg] = val; + *(volatile uint32_t *) &dev->regs[reg] = val; + } __spi_unused @@ -33,8 +34,7 @@ __spi_unused static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, void *rx, unsigned count) { - unsigned i; - uint8_t dummy_rx = 0; + unsigned n; const uint8_t *u8_tx = (const uint8_t *) tx; uint8_t *u8_rx = (uint8_t *) rx; uint8_t config; @@ -43,77 +43,107 @@ static void _spi_transfer(struct spi_generic_dev *dev, const void *tx, /* TODO: Enable TX */ - - /* TODO: Tell master to hold SS */ + /* TODO: Tell master to hold SS? */ config = _spi_reg_read(dev, SPI_CONFIG); while (count) { - union buf { + union acme { uint32_t u32; uint16_t u16[2]; uint8_t u8[4]; } __spi_packed; - union buf rx0 = { 0 }, rx1 = { 0 }, tx0 = { 0 }, tx1 = { 0 }; - union buf *dst = (union buf *) &dev->regs[SPI_TX]; + union acme rx0, rx1, tx0, tx1; + volatile union acme *txfifo = (union acme *) &dev->regs[SPI_TX]; if (tx) memcpy(&tx0.u32, u8_tx, count > 4 ? 4 : count); + if (tx && count > 4) + memcpy(&tx1.u32, &u8_tx[4], count - 4 > 4 ? 4 : count - 4); + + /* Clear status register */ + _spi_reg_write(dev, SPI_STATUS, 0); + while (_spi_reg_read(dev, SPI_STATUS)) + ; /* Enable TX */ config &= ~SPI_CONFIG_DISABLE; _spi_reg_write(dev, SPI_CONFIG, config); - /* Disable TX */ - //config |= SPI_CONFIG_DISABLE; - //_spi_reg_write(dev, SPI_CONFIG, config); - - /* TODO: Check RX FIFO full instead */ - for (i = 0; count && i < 4 /* TODO: 8 */ ;) { - /*! (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_TX_FIFO_HALF_FULL);) {*/ - switch (count) { - case 1: - dst->u8[0] = tx0.u8[0]; - count -= 1; i += 1; - break; - case 2: - dst->u16[0] = tx0.u16[0]; - count -= 2; i += 2; - break; - case 3: - dst->u16[0] = tx0.u16[0]; - dst->u8[0] = tx0.u8[3]; - count -= 3; i += 3; - break; - default: - dst->u32 = tx0.u32; - count -= 4; i += 4; - }; - } - ///* Enable TX */ - //config &= ~SPI_CONFIG_DISABLE; - //_spi_reg_write(dev, SPI_CONFIG, config); - - while (!SPI_STATE_IDLE(_spi_reg_read(dev, SPI_STATUS))) + /* Write TX data to TX fifo */ + switch (count) { + case 1: + txfifo->u8[0] = tx0.u8[0]; + count -= 1; n = 1; + break; + case 2: + txfifo->u16[0] = tx0.u16[0]; + count -= 2; n = 2; + break; + case 3: + txfifo->u16[0] = tx0.u16[0]; + txfifo->u8[0] = tx0.u8[3]; + count -= 3; n = 3; + break; + case 4: + txfifo->u32 = tx0.u32; + count -= 4; n = 4; + break; + case 5: + txfifo->u32 = tx0.u32; + txfifo->u8[0] = tx1.u8[0]; + count -= 5; n = 5; + break; + case 6: + txfifo->u32 = tx0.u32; + txfifo->u32 = tx1.u16[0]; + count -= 6; n = 6; + break; + case 7: + txfifo->u32 = tx0.u32; + txfifo->u32 = tx1.u16[0]; + txfifo->u32 = tx1.u8[3]; + count -= 7; n = 7; + break; + default: + txfifo->u32 = tx0.u32; + txfifo->u32 = tx1.u32; + count -= 8; n = 8; + break; + }; + + /* Wait for transfer to complete */ + while (_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_ACTIVE) + ; + while (!(_spi_reg_read(dev, SPI_STATUS) & SPI_STATUS_SPLIT)) ; - rx0.u32 = *(uint32_t *) &dev->regs[SPI_RX0]; - rx1.u32 = *(uint32_t *) &dev->regs[SPI_RX1]; - - //printf("rx0: %08x\n", rx0.u32); - - int j; - //printf("i: %d\n", i); if (rx) { - //printf("i: %d\n", i); - for (j = 0; i, j < 4; i--, j++) - *u8_rx++ = rx0.u8[j]; - for (j = 0; i, j < 4; i--, j++) - *u8_rx++ = rx1.u8[j]; + uint8_t buf[8] = { 0 }; + unsigned i, j; + + /* Read deserializer */ + rx0.u32 = *(uint32_t *) &dev->regs[SPI_RX0]; + rx1.u32 = *(uint32_t *) &dev->regs[SPI_RX1]; + + memcpy(&buf[0], &rx0, 4); + memcpy(&buf[4], &rx1, 4); + + /* Reverse bytes in transfer */ + for (i = n - 1, j = 0; i > j; i--, j++) { + uint8_t tmp; + tmp = buf[i]; + buf[i] = buf[j]; + buf[j] = tmp; + } + + memcpy(u8_rx, buf, n); + u8_rx += n; } + } - (void) dummy_rx; + _spi_reg_write(dev, SPI_STATUS, 0); /* TODO: Tell master to release SS */ } diff --git a/src/spi/driver/spilib/spi.h b/src/spi/driver/spilib/spi.h index 79254d33..18462c34 100644 --- a/src/spi/driver/spilib/spi.h +++ b/src/spi/driver/spilib/spi.h @@ -98,17 +98,13 @@ #define SPI_CONFIG_IRQ_ENABLE (1 << 1) #define SPI_CONFIG_CPOL (1 << 2) #define SPI_CONFIG_CPHA (1 << 3) -#define SPI_CONFIG_LSB (1 << 4) +#define SPI_CONFIG_LSB_FIRST (1 << 4) #define SPI_CONFIG_USER_REGS (1 << 5)/* slave only */ #define SPI_STATUS_SPLIT (1 << 0) -#define SPI_STATUS_STATE (3 << 1) /* master only */ -#define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 3) /* master only */ +#define SPI_STATUS_ACTIVE (1 << 1) /* master only */ +#define SPI_STATUS_TX_FIFO_HALF_FULL (1 << 2) /* master only */ -#define SPI_STATE_IDLE(status) (((status) & SPI_STATUS_STATE) >> 1 == 0) -#define SPI_STATE_SETUP(status) (((status) & SPI_STATUS_STATE) >> 1 == 1) -#define SPI_STATE_DATA(status) (((status) & SPI_STATUS_STATE) >> 1 == 2) -#define SPI_STATE_HOLD(status) (((status) & SPI_STATUS_STATE) >> 1 == 3) /** * spi_reg_write - Set SPI device register * From cd9fe76ebe2b4575fb21d583a9330e7cfbffb083 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 24 May 2016 14:42:48 +0000 Subject: [PATCH 09/14] spi: spilib: Update uio-test - Add test for slave address auto-increment. - Add test for the 2 MSB in every byte. Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/uio-test.c | 125 +++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 33 deletions(-) diff --git a/src/spi/driver/spilib/uio-test.c b/src/spi/driver/spilib/uio-test.c index 9ad6ee01..e29e4b6f 100644 --- a/src/spi/driver/spilib/uio-test.c +++ b/src/spi/driver/spilib/uio-test.c @@ -4,18 +4,16 @@ /* Assume master/slave pins are connected in loop-back */ -/* TODO: Add burst */ - /* OH SPI slave specifics */ struct oh_spi_mosi_pkt { unsigned addr:6; unsigned mode:2; - uint8_t data; + uint8_t data[7]; } __attribute__((packed)); struct oh_spi_miso_pkt { - uint8_t data; - unsigned fook:8; + unsigned:8; + uint8_t data[7]; } __attribute__((packed)); @@ -23,32 +21,54 @@ struct oh_spi_miso_pkt { #define SLAVE_READ 0x02 #define SLAVE_FETCH 0x03 -uint8_t slave_access(spi_dev_t *dev, unsigned mode, unsigned addr, uint8_t data) +void slave_access(spi_dev_t *dev, unsigned mode, unsigned addr, uint8_t *txbuf, + uint8_t *rxbuf, unsigned count) { struct oh_spi_miso_pkt miso; struct oh_spi_mosi_pkt mosi = { .addr = addr, .mode = mode, - .data = data, + .data = { 0 }, }; - spi_transfer(dev, &mosi, &miso, sizeof(mosi)); + if (txbuf) + memcpy(mosi.data, txbuf, count); + + if (mode == SLAVE_WRITE) + spi_transfer(dev, &mosi, NULL, 1 + count); + else + spi_transfer(dev, &mosi, &miso, 1 + count); - return miso.data; + if (rxbuf) + memcpy(rxbuf, &miso.data[0], count); +} + +void slave_write_n(spi_dev_t *dev, unsigned addr, uint8_t *data, unsigned count) +{ + slave_access(dev, SLAVE_WRITE, addr, data, NULL, count); } void slave_write(spi_dev_t *dev, unsigned addr, uint8_t data) { - slave_access(dev, SLAVE_WRITE, addr, data); + slave_access(dev, SLAVE_WRITE, addr, &data, NULL, 1); } uint8_t slave_read(spi_dev_t *dev, unsigned addr) { - return slave_access(dev, SLAVE_READ, addr, 0); + uint8_t value; + slave_access(dev, SLAVE_READ, addr, NULL, &value, 1); + return value; +} + +void slave_read_n(spi_dev_t *dev, unsigned addr, uint8_t *readback, + unsigned count) +{ + slave_access(dev, SLAVE_READ, addr, NULL, readback, count); } + int main() { - int i; + int i, j; spi_dev_t master; uint8_t slave_regs[13]; bool fail = false; @@ -58,6 +78,11 @@ int main() return 1; } + spi_set_clkdiv(&master, 0xfe); + + slave_write(&master, SPI_CONFIG, 0); + spi_reg_write(&master, SPI_CONFIG, 0); + printf("status: %#x\n", spi_reg_read(&master, SPI_STATUS)); printf("clkdiv: %#x\n", spi_reg_read(&master, SPI_CLKDIV)); @@ -65,49 +90,83 @@ int main() printf("config: %#x\n", spi_reg_read(&master, SPI_CONFIG)); printf("spi_reg_read(28): %#x\n", spi_reg_read(&master, 28)); - spi_set_clkdiv(&master, 0x5); - int j; - for (j = 0; j < 10000; j++) { + printf("Testing write / read to slave regs loop\n"); +#if 1 + for (i = 0; i < 1000; i++) { - for (i = 0; i < 13; i++) - slave_write(&master, SPI_USER0 + i, i * 2); + for (j = 0; j < 13; j++) + slave_write(&master, SPI_USER0 + j, j * 2); - for (i = 0; i < 13; i++) - slave_regs[i] = slave_read(&master, SPI_USER0 + i); + for (j = 0; j < 13; j++) { + //printf("i: 0x%x\n", i); + slave_regs[j] = slave_read(&master, SPI_USER0 + j); + } - if (j == 0) { + if (i == 0) { printf("slave user regs: "); - for (i = 0; i < 13; i++) - printf("0x%02x ", (int) slave_regs[i]); + for (j = 0; j < 13; j++) + printf("0x%02x ", (int) slave_regs[j]); printf("\n"); } - for (i = 0; i < 13; i++) - if (slave_regs[i] != i * 2) + for (j = 0; j < 13; j++) + if (slave_regs[j] != j * 2) { + printf("fail\n"); fail = true; + } - for (i = 0; i < 13; i++) - slave_write(&master, SPI_USER0 + i, i); + for (j = 0; j < 13; j++) + slave_write(&master, SPI_USER0 + j, j); - for (i = 0; i < 13; i++) - slave_regs[i] = slave_read(&master, SPI_USER0 + i); + for (j = 0; j < 13; j++) + slave_regs[j] = slave_read(&master, SPI_USER0 + j); - if (j == 0) { + if (i == 0) { printf("slave user regs: "); - for (i = 0; i < 13; i++) - printf("0x%02x ", (int) slave_regs[i]); + for (j = 0; j < 13; j++) + printf("0x%02x ", (int) slave_regs[j]); printf("\n"); } - for (i = 0; i < 13; i++) - if (slave_regs[i] != i) + for (j = 0; j < 13; j++) + if (slave_regs[j] != j) { + printf("fail\n"); fail = true; + } if (fail) break; } +#endif + + printf(fail ? "FAIL\n" : "OK\n"); + + uint8_t written[7] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99}; + uint8_t readback[7] = { 0x0 }; + +#if 0 + printf("Testing high bits set and slave addr autoincrement\n"); + slave_write_n(&master, SPI_USER0, written, 7); + slave_read_n(&master, SPI_USER0, readback, 7); +#else + printf("Testing high bits set\n"); + for (i = 0; i < 7; i++) { + slave_write(&master, SPI_USER0 + i, written[i]); + readback[i] = slave_read(&master, SPI_USER0 + i); + } +#endif + + for (i = 0; i < 7; i++) { + printf("written[%d] = 0x%02x readback[%d] = 0x%02x\n", + i, (int) written[i], i, readback[i]); + if (readback[i] != written[i]) + fail = true; + } + + printf("rx0 = 0x%08x rx1 = 0x%08x\n", + spi_reg_read(&master, SPI_RX0), spi_reg_read(&master, SPI_RX1)); spi_fini(&master); From 987f8df03fe8a7604e5f932f727f3e1711f20a99 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 24 May 2016 17:01:21 +0200 Subject: [PATCH 10/14] spi: Connect nreset of oh_rise2pulse Solves issue with master STATUS[0] always high. Signed-off-by: Ola Jeppsson --- src/spi/hdl/spi_master_io.v | 5 +++-- src/spi/hdl/spi_slave_io.v | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/spi/hdl/spi_master_io.v b/src/spi/hdl/spi_master_io.v index 1dad7d6c..0daa1270 100644 --- a/src/spi/hdl/spi_master_io.v +++ b/src/spi/hdl/spi_master_io.v @@ -146,10 +146,11 @@ module spi_master_io //generate access pulse at rise of ss oh_rise2pulse - pulse (.out (rx_access), + pulse (.nreset(nreset), + .out (rx_access), .clk (clk), .in (ss)); - + oh_ser2par #(.PW(64), .SW(1)) ser2par (//output diff --git a/src/spi/hdl/spi_slave_io.v b/src/spi/hdl/spi_slave_io.v index a85876a7..7feb51b4 100644 --- a/src/spi/hdl/spi_slave_io.v +++ b/src/spi/hdl/spi_slave_io.v @@ -165,9 +165,10 @@ module spi_slave_io #( parameter PW = 104 // packet width .din (ss)); //create single cycle pulse - oh_rise2pulse r2p (.out (ss_pulse), - .clk (clk), - .in (ss_sync)); + oh_rise2pulse r2p (.nreset (nreset), + .out (ss_pulse), + .clk (clk), + .in (ss_sync)); assign spi_fetch = ss_pulse & (command_reg[7:6]==`SPI_FETCH); From 31c05935bafdaddc606efd7e09a09f5da72a814f Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 24 May 2016 17:05:28 +0200 Subject: [PATCH 11/14] spi: fpga: Add constraint for master slave clock out Signed-off-by: Ola Jeppsson --- src/spi/fpga/axi_spi_timing.xdc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spi/fpga/axi_spi_timing.xdc b/src/spi/fpga/axi_spi_timing.xdc index 90770f54..fce0ff68 100644 --- a/src/spi/fpga/axi_spi_timing.xdc +++ b/src/spi/fpga/axi_spi_timing.xdc @@ -1,3 +1,4 @@ # SPI slave clock create_clock -name spi_s_sclk -period 10 [get_ports spi_s_sclk] - +# SPI master clock +create_clock -name spi_m_sclk -period 10 [get_ports spi_m_sclk] From ff8ad4e976dd4d787548a9f0cfc3059187e043c8 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Fri, 27 May 2016 22:14:53 +0000 Subject: [PATCH 12/14] spi: spilib: Add slave address increment test to uio-test Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/uio-test.c | 54 +++++++++++++++----------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/spi/driver/spilib/uio-test.c b/src/spi/driver/spilib/uio-test.c index e29e4b6f..680d3dd6 100644 --- a/src/spi/driver/spilib/uio-test.c +++ b/src/spi/driver/spilib/uio-test.c @@ -42,9 +42,9 @@ void slave_access(spi_dev_t *dev, unsigned mode, unsigned addr, uint8_t *txbuf, memcpy(rxbuf, &miso.data[0], count); } -void slave_write_n(spi_dev_t *dev, unsigned addr, uint8_t *data, unsigned count) +void slave_write_n(spi_dev_t *dev, unsigned addr, uint8_t *tx, unsigned count) { - slave_access(dev, SLAVE_WRITE, addr, data, NULL, count); + slave_access(dev, SLAVE_WRITE, addr, tx, NULL, count); } void slave_write(spi_dev_t *dev, unsigned addr, uint8_t data) @@ -59,10 +59,10 @@ uint8_t slave_read(spi_dev_t *dev, unsigned addr) return value; } -void slave_read_n(spi_dev_t *dev, unsigned addr, uint8_t *readback, +void slave_read_n(spi_dev_t *dev, unsigned addr, uint8_t *rx, unsigned count) { - slave_access(dev, SLAVE_READ, addr, NULL, readback, count); + slave_access(dev, SLAVE_READ, addr, NULL, rx, count); } @@ -78,9 +78,9 @@ int main() return 1; } - spi_set_clkdiv(&master, 0xfe); + spi_set_clkdiv(&master, 5); - slave_write(&master, SPI_CONFIG, 0); +// slave_write(&master, SPI_CONFIG, 0); spi_reg_write(&master, SPI_CONFIG, 0); printf("status: %#x\n", spi_reg_read(&master, SPI_STATUS)); @@ -92,11 +92,11 @@ int main() printf("spi_reg_read(28): %#x\n", spi_reg_read(&master, 28)); printf("Testing write / read to slave regs loop\n"); -#if 1 - for (i = 0; i < 1000; i++) { + + for (i = 0; i < 10000; i++) { for (j = 0; j < 13; j++) - slave_write(&master, SPI_USER0 + j, j * 2); + slave_write(&master, SPI_USER0 + j, 0xff - j * 2); for (j = 0; j < 13; j++) { //printf("i: 0x%x\n", i); @@ -111,13 +111,13 @@ int main() } for (j = 0; j < 13; j++) - if (slave_regs[j] != j * 2) { + if (slave_regs[j] != 0xff - j * 2) { printf("fail\n"); fail = true; } for (j = 0; j < 13; j++) - slave_write(&master, SPI_USER0 + j, j); + slave_write(&master, SPI_USER0 + j, 0xff - j); for (j = 0; j < 13; j++) slave_regs[j] = slave_read(&master, SPI_USER0 + j); @@ -130,7 +130,7 @@ int main() } for (j = 0; j < 13; j++) - if (slave_regs[j] != j) { + if (slave_regs[j] != 0xff - j) { printf("fail\n"); fail = true; } @@ -139,29 +139,27 @@ int main() break; } -#endif printf(fail ? "FAIL\n" : "OK\n"); - uint8_t written[7] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99}; - uint8_t readback[7] = { 0x0 }; + uint8_t pat0[7] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32}; + uint8_t pat1[7] = { 0xfe ^ 0xff, 0xdc ^ 0xff, 0xba ^ 0xff, 0x98 ^ 0xff, + 0x76 ^ 0xff, 0x54 ^ 0xff, 0x32 ^ 0xff }; + uint8_t in0[7] = { 0x0 }; + uint8_t in1[7] = { 0x0 }; -#if 0 printf("Testing high bits set and slave addr autoincrement\n"); - slave_write_n(&master, SPI_USER0, written, 7); - slave_read_n(&master, SPI_USER0, readback, 7); -#else - printf("Testing high bits set\n"); - for (i = 0; i < 7; i++) { - slave_write(&master, SPI_USER0 + i, written[i]); - readback[i] = slave_read(&master, SPI_USER0 + i); - } -#endif + slave_write_n(&master, SPI_USER0, pat0, 7); + slave_read_n(&master, SPI_USER0, in0, 7); + slave_write_n(&master, SPI_USER0, pat1, 7); + slave_read_n(&master, SPI_USER0, in1, 7); for (i = 0; i < 7; i++) { - printf("written[%d] = 0x%02x readback[%d] = 0x%02x\n", - i, (int) written[i], i, readback[i]); - if (readback[i] != written[i]) + printf("pat0[%d] = 0x%02x in0[%d] = 0x%02x\n", + i, (int) pat0[i], i, in0[i]); + printf("pat1[%d] = 0x%02x in1[%d] = 0x%02x\n", + i, (int) pat1[i], i, in1[i]); + if (in0[i] != pat0[i] || in1[i] != pat1[i]) fail = true; } From 48f95ef007afee7954a32c9ef8d01099516b8e9a Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 31 May 2016 22:13:00 +0000 Subject: [PATCH 13/14] spi: spilib: Add Makefile Signed-off-by: Ola Jeppsson --- src/spi/driver/spilib/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/spi/driver/spilib/Makefile diff --git a/src/spi/driver/spilib/Makefile b/src/spi/driver/spilib/Makefile new file mode 100644 index 00000000..5e7c8730 --- /dev/null +++ b/src/spi/driver/spilib/Makefile @@ -0,0 +1,6 @@ +all: uio-test + +clean: + rm -f uio-test + +.PHONY: all clean From 4b9e555472eeac45e59b94990439b8a4b86423ac Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Tue, 31 May 2016 22:34:33 +0000 Subject: [PATCH 14/14] spi: linux-uio: Add files and instructions for uio Signed-off-by: Ola Jeppsson --- src/spi/driver/linux-uio/README.md | 16 ++++++ src/spi/driver/linux-uio/uio.ko | Bin 0 -> 16236 bytes src/spi/driver/linux-uio/uio_pdrv_genirq.ko | Bin 0 -> 7660 bytes .../linux-uio/zynq-parallella-oh-spi.dtb | Bin 0 -> 13240 bytes .../linux-uio/zynq-parallella-oh-spi.dts | 51 ++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 src/spi/driver/linux-uio/README.md create mode 100644 src/spi/driver/linux-uio/uio.ko create mode 100644 src/spi/driver/linux-uio/uio_pdrv_genirq.ko create mode 100644 src/spi/driver/linux-uio/zynq-parallella-oh-spi.dtb create mode 100644 src/spi/driver/linux-uio/zynq-parallella-oh-spi.dts diff --git a/src/spi/driver/linux-uio/README.md b/src/spi/driver/linux-uio/README.md new file mode 100644 index 00000000..27965ca1 --- /dev/null +++ b/src/spi/driver/linux-uio/README.md @@ -0,0 +1,16 @@ +# OH Linux generic UIO driver + +Modules and devicetree compiled for Pubuntu 2016.3.x + +1. Copy `zynq-parallella-oh-spi.dtb` to SD card boot partition, name it `devicetree.dtb`. +2. Reboot Parallella +3. (OPTIONAL) Load bitstream: `sudo dd if=parallella.bit.bin of=/dev/xdevcfg` +3. Load the required modules: +``` +sudo insmod uio.ko +sudo insmod uio_pdrv_genirq.ko of_id=oh,mio +sudo rmmod uio_pdrv_genirq.ko +sudo insmod uio_pdrv_genirq.ko of_id=oh,mio +chmod 777 /dev/uio0 +``` +4. You can now compile and run uio-test in oh.git/src/spi/driver/spilib diff --git a/src/spi/driver/linux-uio/uio.ko b/src/spi/driver/linux-uio/uio.ko new file mode 100644 index 0000000000000000000000000000000000000000..74020756edc2f84936deb5c8c96665ff608723a2 GIT binary patch literal 16236 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 LItD-&OZ5K$7yKsa literal 0 HcmV?d00001 diff --git a/src/spi/driver/linux-uio/uio_pdrv_genirq.ko b/src/spi/driver/linux-uio/uio_pdrv_genirq.ko new file mode 100644 index 0000000000000000000000000000000000000000..97ea822e1d49a51d9a5a2271443b6705a49ff539 GIT binary patch literal 7660 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 literal 0 HcmV?d00001 diff --git a/src/spi/driver/linux-uio/zynq-parallella-oh-spi.dtb b/src/spi/driver/linux-uio/zynq-parallella-oh-spi.dtb new file mode 100644 index 0000000000000000000000000000000000000000..176b83166853d4d376d7b45213170847a3466637 GIT binary patch literal 13240 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 Ai2wiq literal 0 HcmV?d00001 diff --git a/src/spi/driver/linux-uio/zynq-parallella-oh-spi.dts b/src/spi/driver/linux-uio/zynq-parallella-oh-spi.dts new file mode 100644 index 00000000..3e423b90 --- /dev/null +++ b/src/spi/driver/linux-uio/zynq-parallella-oh-spi.dts @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Parallella Foundation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +/dts-v1/; +#include "zynq-parallella1.dtsi" + +/ { + model = "Adapteva Parallella Board with OH SPI bitstream"; +}; + +&amba { + spi2: spi2@7fe00000 { + compatible = "oh,spi"; + reg = <0x7fe00000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <0 53 4>; + }; +}; + +&usb_phy0 { + status = "okay"; +}; + +&usb_phy1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&elink0 { + status = "disabled"; +}; + +&i2c0 { + status = "disabled"; +};