From 276afd2b4812bef2476456476af7e5392102d8a6 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Apr 2018 09:48:52 +0200 Subject: bsps: Move SPI drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/arm/imx/Makefile.am | 2 +- c/src/lib/libbsp/arm/imx/spi/imx-ecspi.c | 449 ------------------------------- 2 files changed, 1 insertion(+), 450 deletions(-) delete mode 100644 c/src/lib/libbsp/arm/imx/spi/imx-ecspi.c (limited to 'c/src/lib/libbsp/arm/imx') diff --git a/c/src/lib/libbsp/arm/imx/Makefile.am b/c/src/lib/libbsp/arm/imx/Makefile.am index 3426433800..5d151d693f 100644 --- a/c/src/lib/libbsp/arm/imx/Makefile.am +++ b/c/src/lib/libbsp/arm/imx/Makefile.am @@ -69,7 +69,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/cache/cache-cp15.c librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/imx/i2c/imx-i2c.c # SPI -librtemsbsp_a_SOURCES += spi/imx-ecspi.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/imx/spi/imx-ecspi.c # Start hooks librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/imx/start/bspstarthooks.c diff --git a/c/src/lib/libbsp/arm/imx/spi/imx-ecspi.c b/c/src/lib/libbsp/arm/imx/spi/imx-ecspi.c deleted file mode 100644 index 9a232c53e9..0000000000 --- a/c/src/lib/libbsp/arm/imx/spi/imx-ecspi.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (c) 2017 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IMX_ECSPI_FIFO_SIZE 64 - -typedef struct imx_ecspi_bus imx_ecspi_bus; - -struct imx_ecspi_bus { - spi_bus base; - volatile imx_ecspi *regs; - uint32_t conreg; - uint32_t speed_hz; - uint32_t mode; - uint8_t bits_per_word; - uint8_t cs; - uint32_t msg_todo; - const spi_ioc_transfer *msg; - uint32_t todo; - uint32_t in_transfer; - uint8_t *rx_buf; - const uint8_t *tx_buf; - void (*push)(imx_ecspi_bus *, volatile imx_ecspi *); - void (*pop)(imx_ecspi_bus *, volatile imx_ecspi *); - rtems_id task_id; - rtems_vector_number irq; -}; - -static bool imx_ecspi_is_rx_fifo_not_empty(volatile imx_ecspi *regs) -{ - return (regs->statreg & IMX_ECSPI_RR) != 0; -} - -static void imx_ecspi_reset(volatile imx_ecspi *regs) -{ - while (imx_ecspi_is_rx_fifo_not_empty(regs)) { - regs->rxdata; - } -} - -static void imx_ecspi_done(imx_ecspi_bus *bus) -{ - rtems_event_transient_send(bus->task_id); -} - -#define IMC_ECSPI_PUSH(type) \ -static void imx_ecspi_push_##type(imx_ecspi_bus *bus, volatile imx_ecspi *regs) \ -{ \ - type val = 0; \ - if (bus->tx_buf != NULL) { \ - val = *(type *)bus->tx_buf; \ - bus->tx_buf += sizeof(type); \ - } \ - bus->todo -= sizeof(type); \ - regs->txdata = val; \ -} - -#define IMX_ECSPI_POP(type) \ -static void imx_ecspi_pop_##type(imx_ecspi_bus *bus, volatile imx_ecspi *regs) \ -{ \ - uint32_t val = regs->rxdata; \ - if (bus->rx_buf != NULL) { \ - *(type *)bus->rx_buf = val; \ - bus->rx_buf += sizeof(type); \ - } \ -} - -IMC_ECSPI_PUSH(uint8_t) -IMX_ECSPI_POP(uint8_t) -IMC_ECSPI_PUSH(uint16_t) -IMX_ECSPI_POP(uint16_t) -IMC_ECSPI_PUSH(uint32_t) -IMX_ECSPI_POP(uint32_t) - -static void imx_ecspi_push_uint32_t_swap( - imx_ecspi_bus *bus, - volatile imx_ecspi *regs -) -{ - uint32_t val = 0; - - if (bus->tx_buf != NULL) { - val = bswap32(*(uint32_t *)bus->tx_buf); - bus->tx_buf += sizeof(uint32_t); - } - - bus->todo -= sizeof(uint32_t); - regs->txdata = val; -} - -static void imx_ecspi_pop_uint32_t_swap( - imx_ecspi_bus *bus, - volatile imx_ecspi *regs -) -{ - uint32_t val = regs->rxdata; - - if (bus->rx_buf != NULL) { - *(uint32_t *)bus->rx_buf = bswap32(val); - bus->rx_buf += sizeof(uint32_t); - } -} - -static void imx_ecspi_push(imx_ecspi_bus *bus, volatile imx_ecspi *regs) -{ - while (bus->todo > 0 && bus->in_transfer < IMX_ECSPI_FIFO_SIZE) { - (*bus->push)(bus, regs); - ++bus->in_transfer; - } -} - -static uint32_t imx_ecspi_conreg_divider(imx_ecspi_bus *bus, uint32_t speed_hz) -{ - uint32_t post; - uint32_t pre; - uint32_t clk_in; - - clk_in = bus->base.max_speed_hz; - - if (clk_in > speed_hz) { - post = fls((int) clk_in) - fls((int) speed_hz); - - if (clk_in > (speed_hz << post)) { - ++post; - } - - /* We have 2^4 == 16, use the pre-divider for this factor */ - post = MAX(4, post) - 4; - - if (post <= 0xf) { - pre = howmany(clk_in, speed_hz << post) - 1; - } else { - post = 0xf; - pre = 0xf; - } - } else { - post = 0; - pre = 0; - } - - return IMX_ECSPI_CONREG_POST_DIVIDER(post) - | IMX_ECSPI_CONREG_PRE_DIVIDER(pre); -} - -static void imx_ecspi_config( - imx_ecspi_bus *bus, - volatile imx_ecspi *regs, - uint32_t speed_hz, - uint8_t bits_per_word, - uint32_t mode, - uint8_t cs -) -{ - uint32_t conreg; - uint32_t testreg; - uint32_t configreg; - uint32_t cs_bit; - - conreg = IMX_ECSPI_CONREG_CHANNEL_MODE(0xf) - | IMX_ECSPI_CONREG_SMC | IMX_ECSPI_CONREG_EN; - testreg = regs->testreg; - configreg = regs->configreg; - cs_bit = 1U << cs; - - conreg |= imx_ecspi_conreg_divider(bus, speed_hz); - conreg |= IMX_ECSPI_CONREG_CHANNEL_SELECT(cs); - - configreg |= IMX_ECSPI_CONFIGREG_SS_CTL(cs_bit); - - if ((mode & SPI_CPHA) != 0) { - configreg |= IMX_ECSPI_CONFIGREG_SCLK_PHA(cs_bit); - } else { - configreg &= ~IMX_ECSPI_CONFIGREG_SCLK_PHA(cs_bit); - } - - if ((mode & SPI_CPOL) != 0) { - configreg |= IMX_ECSPI_CONFIGREG_SCLK_POL(cs_bit); - configreg |= IMX_ECSPI_CONFIGREG_SCLK_CTL(cs_bit); - } else { - configreg &= ~IMX_ECSPI_CONFIGREG_SCLK_POL(cs_bit); - configreg &= ~IMX_ECSPI_CONFIGREG_SCLK_CTL(cs_bit); - } - - if ((mode & SPI_CS_HIGH) != 0) { - configreg |= IMX_ECSPI_CONFIGREG_SS_POL(cs_bit); - } else { - configreg &= ~IMX_ECSPI_CONFIGREG_SS_POL(cs_bit); - } - - if ((mode & SPI_LOOP) != 0) { - testreg |= IMX_ECSPI_TESTREG_LBC; - } else { - testreg &= ~IMX_ECSPI_TESTREG_LBC; - } - - regs->conreg = conreg; - regs->testreg = testreg; - regs->configreg = configreg; - - bus->conreg = conreg; - bus->speed_hz = speed_hz; - bus->bits_per_word = bits_per_word; - bus->mode = mode; - bus->cs = cs; - - /* FIXME: Clock change delay */ -} - -static void imx_ecspi_set_push_pop( - imx_ecspi_bus *bus, - uint32_t len, - uint8_t bits_per_word -) -{ - uint32_t conreg; - - conreg = bus->conreg; - - if (len % 4 == 0 && len <= IMX_ECSPI_FIFO_SIZE) { - conreg |= IMX_ECSPI_CONREG_BURST_LENGTH((len * 8) - 1); - - bus->push = imx_ecspi_push_uint32_t_swap; - bus->pop = imx_ecspi_pop_uint32_t_swap; - } else { - conreg |= IMX_ECSPI_CONREG_BURST_LENGTH(bits_per_word - 1); - - if (bits_per_word <= 8) { - bus->push = imx_ecspi_push_uint8_t; - bus->pop = imx_ecspi_pop_uint8_t; - } else if (bits_per_word <= 16) { - bus->push = imx_ecspi_push_uint16_t; - bus->pop = imx_ecspi_pop_uint16_t; - } else { - bus->push = imx_ecspi_push_uint32_t; - bus->pop = imx_ecspi_pop_uint32_t; - } - } - - bus->regs->conreg = conreg; -} - -static void imx_ecspi_next_msg(imx_ecspi_bus *bus, volatile imx_ecspi *regs) -{ - if (bus->msg_todo > 0) { - const spi_ioc_transfer *msg; - - msg = bus->msg; - - if ( - msg->speed_hz != bus->speed_hz - || msg->bits_per_word != bus->bits_per_word - || msg->mode != bus->mode - || msg->cs != bus->cs - ) { - imx_ecspi_config( - bus, - regs, - msg->speed_hz, - msg->bits_per_word, - msg->mode, - msg->cs - ); - } - - bus->todo = msg->len; - bus->rx_buf = msg->rx_buf; - bus->tx_buf = msg->tx_buf; - imx_ecspi_set_push_pop(bus, msg->len, msg->bits_per_word); - imx_ecspi_push(bus, regs); - regs->intreg = IMX_ECSPI_TE; - } else { - regs->intreg = 0; - imx_ecspi_done(bus); - } -} - -static void imx_ecspi_interrupt(void *arg) -{ - imx_ecspi_bus *bus; - volatile imx_ecspi *regs; - - bus = arg; - regs = bus->regs; - - while (imx_ecspi_is_rx_fifo_not_empty(regs)) { - (*bus->pop)(bus, regs); - --bus->in_transfer; - } - - if (bus->todo > 0) { - imx_ecspi_push(bus, regs); - } else if (bus->in_transfer > 0) { - regs->intreg = IMX_ECSPI_RR; - } else { - --bus->msg_todo; - ++bus->msg; - imx_ecspi_next_msg(bus, regs); - } -} - -static int imx_ecspi_transfer( - spi_bus *base, - const spi_ioc_transfer *msgs, - uint32_t n -) -{ - imx_ecspi_bus *bus; - - bus = (imx_ecspi_bus *) base; - - bus->msg_todo = n; - bus->msg = &msgs[0]; - bus->task_id = rtems_task_self(); - - imx_ecspi_next_msg(bus, bus->regs); - rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); - return 0; -} - -static void imx_ecspi_destroy(spi_bus *base) -{ - imx_ecspi_bus *bus; - - bus = (imx_ecspi_bus *) base; - rtems_interrupt_handler_remove(bus->irq, imx_ecspi_interrupt, bus); - spi_bus_destroy_and_free(&bus->base); -} - -static int imx_ecspi_init(imx_ecspi_bus *bus, const void *fdt, int node) -{ - rtems_status_code sc; - int len; - const uint32_t *val; - - imx_ecspi_config( - bus, - bus->regs, - bus->base.max_speed_hz, - 8, - 0, - 0 - ); - imx_ecspi_reset(bus->regs); - - sc = rtems_interrupt_handler_install( - bus->irq, - "ECSPI", - RTEMS_INTERRUPT_UNIQUE, - imx_ecspi_interrupt, - bus - ); - if (sc != RTEMS_SUCCESSFUL) { - return EAGAIN; - } - - val = fdt_getprop(fdt, node, "pinctrl-0", &len); - if (len == 4) { - imx_iomux_configure_pins(fdt, fdt32_to_cpu(val[0])); - } - - return 0; -} - -static int imx_ecspi_setup(spi_bus *base) -{ - imx_ecspi_bus *bus; - - bus = (imx_ecspi_bus *) base; - - if ( - bus->base.speed_hz > imx_ccm_ipg_hz() - || bus->base.bits_per_word > 32 - ) { - return -EINVAL; - } - - imx_ecspi_config( - bus, - bus->regs, - bus->base.speed_hz, - bus->base.bits_per_word, - bus->base.mode, - bus->base.cs - ); - return 0; -} - -int spi_bus_register_imx(const char *bus_path, const char *alias_or_path) -{ - const void *fdt; - const char *path; - int node; - imx_ecspi_bus *bus; - int eno; - - fdt = bsp_fdt_get(); - path = fdt_get_alias(fdt, alias_or_path); - - if (path == NULL) { - path = alias_or_path; - } - - node = fdt_path_offset(fdt, path); - if (node < 0) { - rtems_set_errno_and_return_minus_one(ENXIO); - } - - bus = (imx_ecspi_bus *) spi_bus_alloc_and_init(sizeof(*bus)); - if (bus == NULL){ - return -1; - } - - bus->base.max_speed_hz = imx_ccm_ipg_hz(); - bus->base.delay_usecs = 1; - bus->regs = imx_get_reg_of_node(fdt, node); - bus->irq = imx_get_irq_of_node(fdt, node, 0); - - eno = imx_ecspi_init(bus, fdt, node); - if (eno != 0) { - (*bus->base.destroy)(&bus->base); - rtems_set_errno_and_return_minus_one(eno); - } - - bus->base.transfer = imx_ecspi_transfer; - bus->base.destroy = imx_ecspi_destroy; - bus->base.setup = imx_ecspi_setup; - - return spi_bus_register(&bus->base, bus_path); -} -- cgit v1.2.3