summaryrefslogtreecommitdiffstats
path: root/bsps
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2019-03-06 11:48:00 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2019-03-06 13:07:16 +0100
commit923a033f57385f4308bc914681d14c2b884db65b (patch)
treeba43b4b07e9d11cde971152bed4b51daaa50a665 /bsps
parentbsp/atsam: Make SPI CS delays configurable (diff)
downloadrtems-923a033f57385f4308bc914681d14c2b884db65b.tar.bz2
bsp/atsam: Change CS delay after transfer
Diffstat (limited to 'bsps')
-rw-r--r--bsps/arm/atsam/spi/atsam_spi_bus.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/bsps/arm/atsam/spi/atsam_spi_bus.c b/bsps/arm/atsam/spi/atsam_spi_bus.c
index 635bcebc20..20cba79050 100644
--- a/bsps/arm/atsam/spi/atsam_spi_bus.c
+++ b/bsps/arm/atsam/spi/atsam_spi_bus.c
@@ -71,6 +71,8 @@ typedef struct {
bool chip_select_active;
bool chip_select_decode;
uint8_t spi_id;
+ uint32_t peripheral_clk_per_us;
+ uint32_t spi_mr;
uint32_t spi_csr[4];
} atsam_spi_bus;
@@ -79,11 +81,15 @@ static void atsam_spi_wakeup_task(atsam_spi_bus *bus)
rtems_binary_semaphore_post(&bus->sem);
}
-static uint8_t atsam_calculate_dlybcs(uint16_t delay_in_us)
+static uint8_t atsam_calculate_dlybcs(const atsam_spi_bus *bus)
{
- return (
- (BOARD_MCK / delay_in_us) < 0xFF) ?
- (BOARD_MCK / delay_in_us) : 0xFF;
+ uint32_t dlybcs = bus->base.delay_usecs * bus->peripheral_clk_per_us;
+
+ if (dlybcs > 0xff) {
+ dlybcs = 0xff;
+ }
+
+ return dlybcs;
}
static uint32_t atsam_calculate_scbr(uint32_t speed_hz)
@@ -126,27 +132,24 @@ static void atsam_set_phase_and_polarity(uint32_t mode, uint32_t *csr)
static void atsam_configure_spi(atsam_spi_bus *bus)
{
- uint8_t delay_cs;
uint32_t scbr;
uint32_t csr = 0;
- uint32_t mode = 0;
+ uint32_t mr;
uint32_t cs = bus->base.cs;
- delay_cs = atsam_calculate_dlybcs(bus->base.delay_usecs);
scbr = atsam_calculate_scbr(bus->base.speed_hz);
- mode |= SPI_MR_DLYBCS(delay_cs);
- mode |= SPI_MR_MSTR;
- mode |= SPI_MR_MODFDIS;
+ mr = bus->spi_mr;
+
if (bus->chip_select_decode) {
- mode |= SPI_MR_PCS(bus->base.cs);
- mode |= SPI_MR_PCSDEC;
+ mr |= SPI_MR_PCS(bus->base.cs);
+ mr |= SPI_MR_PCSDEC;
cs /= 4;
} else {
- mode |= SPI_PCS(bus->base.cs);
+ mr |= SPI_PCS(bus->base.cs);
}
- bus->spi_regs->SPI_MR = mode;
+ bus->spi_regs->SPI_MR = mr;
csr = bus->spi_csr[cs]
| SPI_CSR_SCBR(scbr)
@@ -345,7 +348,6 @@ static int atsam_check_configure_spi(atsam_spi_bus *bus, const spi_ioc_transfer
|| msg->speed_hz != bus->base.speed_hz
|| msg->bits_per_word != bus->base.bits_per_word
|| msg->cs != bus->base.cs
- || msg->delay_usecs != bus->base.delay_usecs
) {
if (
msg->bits_per_word < 8
@@ -360,7 +362,6 @@ static int atsam_check_configure_spi(atsam_spi_bus *bus, const spi_ioc_transfer
bus->base.speed_hz = msg->speed_hz;
bus->base.bits_per_word = msg->bits_per_word;
bus->base.cs = msg->cs;
- bus->base.delay_usecs = msg->delay_usecs;
atsam_configure_spi(bus);
}
@@ -407,6 +408,22 @@ static void atsam_spi_dma_callback(uint32_t channel, void *arg)
--bus->transfer_in_progress;
if (bus->transfer_in_progress == 0) {
+ const spi_ioc_transfer *msg = bus->msg_current;
+
+ if (msg->delay_usecs != bus->base.delay_usecs) {
+ uint32_t mr;
+ uint32_t mr_dlybcs;
+
+ bus->base.delay_usecs = msg->delay_usecs;
+ mr_dlybcs = SPI_MR_DLYBCS(atsam_calculate_dlybcs(bus));
+ bus->spi_mr = mr_dlybcs | SPI_MR_MSTR | SPI_MR_MODFDIS;
+
+ mr = bus->spi_regs->SPI_MR;
+ mr &= ~SPI_MR_DLYBCS_Msk;
+ mr |= mr_dlybcs;
+ bus->spi_regs->SPI_MR = mr;
+ }
+
atsam_spi_copy_back_rx_after_dma_transfer(bus);
atsam_spi_setup_transfer(bus);
}
@@ -617,11 +634,12 @@ int spi_bus_register_atsam(
bus->base.max_speed_hz = MAX_SPI_FREQUENCY;
bus->base.bits_per_word = 8;
bus->base.speed_hz = bus->base.max_speed_hz;
- bus->base.delay_usecs = 1;
bus->base.cs = 1;
bus->spi_id = config->spi_peripheral_id;
bus->spi_regs = config->spi_regs;
bus->chip_select_decode = config->chip_select_decode;
+ bus->peripheral_clk_per_us = BOARD_MCK / 1000000;
+ bus->spi_mr = SPI_MR_MSTR | SPI_MR_MODFDIS;
for (i = 0; i < RTEMS_ARRAY_SIZE(bus->spi_csr); ++i) {
if (config->dlybs_in_ns[i] != 0) {