13513f269SManish Tomar // SPDX-License-Identifier: BSD-2-Clause
23513f269SManish Tomar /*
33513f269SManish Tomar * Copyright 2021 NXP
43513f269SManish Tomar *
53513f269SManish Tomar * Driver for DSPI Controller
63513f269SManish Tomar *
73513f269SManish Tomar */
83513f269SManish Tomar
93513f269SManish Tomar #include <assert.h>
103513f269SManish Tomar #include <drivers/ls_dspi.h>
113513f269SManish Tomar #include <io.h>
123513f269SManish Tomar #include <kernel/boot.h>
133513f269SManish Tomar #include <kernel/delay.h>
143513f269SManish Tomar #include <kernel/dt.h>
153513f269SManish Tomar #include <libfdt.h>
163513f269SManish Tomar #include <mm/core_memprot.h>
173513f269SManish Tomar #include <platform_config.h>
183513f269SManish Tomar #include <util.h>
193513f269SManish Tomar
203513f269SManish Tomar /* SPI register offset */
213513f269SManish Tomar #define DSPI_MCR 0x0 /* Module Configuration Register */
223513f269SManish Tomar #define DSPI_TCR 0x8 /* Transfer Count Register */
233513f269SManish Tomar #define DSPI_CTAR0 \
243513f269SManish Tomar 0xC /* Clock and Transfer Attributes Register (in Master mode) */
253513f269SManish Tomar #define DSPI_CTAR1 \
263513f269SManish Tomar 0x10 /* Clock and Transfer Attributes Register (in Master mode) */
273513f269SManish Tomar #define DSPI_SR 0x2C /* Status Register */
283513f269SManish Tomar #define DSPI_RSER 0x30 /* DMA/Interrupt Request Select and Enable Register */
293513f269SManish Tomar #define DSPI_PUSHR 0x34 /* PUSH TX FIFO Register In Master Mode */
303513f269SManish Tomar #define DSPI_POPR 0x38 /* POP RX FIFO Register */
313513f269SManish Tomar #define DSPI_TXFR0 0x3C /* Transmit FIFO Registers */
323513f269SManish Tomar #define DSPI_TXFR1 0x40 /* Transmit FIFO Registers */
333513f269SManish Tomar #define DSPI_TXFR2 0x44 /* Transmit FIFO Registers */
343513f269SManish Tomar #define DSPI_TXFR3 0x48 /* Transmit FIFO Registers */
353513f269SManish Tomar #define DSPI_RXFR0 0x7C /* Receive FIFO Registers */
363513f269SManish Tomar #define DSPI_RXFR1 0x80 /* Receive FIFO Registers */
373513f269SManish Tomar #define DSPI_RXFR2 0x84 /* Receive FIFO Registers */
383513f269SManish Tomar #define DSPI_RXFR3 0x88 /* Receive FIFO Registers */
393513f269SManish Tomar #define DSPI_CTARE0 0x11C /* Clock and Transfer Attributes Register Extended */
403513f269SManish Tomar #define DSPI_CTARE1 0x120 /* Clock and Transfer Attributes Register Extended */
413513f269SManish Tomar #define DSPI_SREX 0x13C /* Status Register Extended */
423513f269SManish Tomar
433513f269SManish Tomar /* Module configuration */
443513f269SManish Tomar #define DSPI_MCR_MSTR 0x80000000 /* Master/Slave Mode Select [0] */
453513f269SManish Tomar #define DSPI_MCR_CSCK 0x40000000 /* Continuous SCK Enable [1] */
463513f269SManish Tomar #define DSPI_MCR_DCONF(x) (((x) & 0x03) << 28) /* SPI Configuration [2-3] */
473513f269SManish Tomar #define DSPI_MCR_ROOE \
483513f269SManish Tomar 0x01000000 /* Receive FIFO Overflow Overwrite Enable[7] */
493513f269SManish Tomar #define DSPI_MCR_PCSIS(x) \
503513f269SManish Tomar (1 << (16 + (x))) /* Peripheral Chip Select x Inactive State [12-15] */
513513f269SManish Tomar #define DSPI_MCR_PCSIS_MASK (0xff << 16)
523513f269SManish Tomar #define DSPI_MCR_MDIS 0x00004000 /* Module Disable [17] */
533513f269SManish Tomar #define DSPI_MCR_DTXF 0x00002000 /* Disable Transmit FIFO [18] */
543513f269SManish Tomar #define DSPI_MCR_DRXF 0x00001000 /* Disable Receive FIFO [19] */
553513f269SManish Tomar #define DSPI_MCR_CTXF 0x00000800 /* Clear TX FIFO [20] */
563513f269SManish Tomar #define DSPI_MCR_CRXF 0x00000400 /* Clear RX FIFO [21] */
573513f269SManish Tomar #define DPSI_XSPI 0x00000008 /* Extended SPI Mode [28] */
583513f269SManish Tomar #define DSPI_MCR_PES 0x00000002 /* Parity Error Stop [30] */
593513f269SManish Tomar #define DSPI_MCR_HALT 0x00000001 /* Halt [31] */
603513f269SManish Tomar #define DPSI_ENABLE 0x0
613513f269SManish Tomar #define DSPI_DISABLE 0x1
623513f269SManish Tomar
633513f269SManish Tomar /* Transfer count */
643513f269SManish Tomar #define DSPI_TCR_SPI_TCNT(x) (((x) & 0x0000FFFF) << 16)
653513f269SManish Tomar
663513f269SManish Tomar /* Status */
673513f269SManish Tomar #define DSPI_SR_TXRXS 0x40000000 /* TX and RX Status [1] */
683513f269SManish Tomar #define DSPI_SR_TXCTR(x) \
693513f269SManish Tomar (((x) & 0x0000F000) >> 12) /* TX FIFO Counter [16-19] */
703513f269SManish Tomar #define DSPI_SR_RXCTR(x) \
713513f269SManish Tomar (((x) & 0x000000F0) >> 4) /* RX FIFO Counter [24-27] */
723513f269SManish Tomar
733513f269SManish Tomar #define DSPI_DATA_8BIT SHIFT_U32(8, 0)
743513f269SManish Tomar #define DSPI_DATA_16BIT SHIFT_U32(0xF, 0)
753513f269SManish Tomar
763513f269SManish Tomar #define DSPI_TFR_CONT (0x80000000)
773513f269SManish Tomar #define DSPI_TFR_CTAS(x) (((x) & 0x07) << 12)
783513f269SManish Tomar #define DSPI_TFR_PCS(x) (((1 << (x)) & 0x0000003f) << 16)
793513f269SManish Tomar #define DSPI_IDLE_DATA 0x0
803513f269SManish Tomar
813513f269SManish Tomar /* tx/rx data wait timeout value, unit: us */
823513f269SManish Tomar #define DSPI_TXRX_WAIT_TIMEOUT 1000000
833513f269SManish Tomar
843513f269SManish Tomar /* Transfer Fifo */
853513f269SManish Tomar #define DSPI_TFR_TXDATA(x) (((x) & 0x0000FFFF))
863513f269SManish Tomar
873513f269SManish Tomar /* Bit definitions and macros for DRFR */
883513f269SManish Tomar #define DSPI_RFR_RXDATA(x) (((x) & 0x0000FFFF))
893513f269SManish Tomar
903513f269SManish Tomar /* CTAR register pre-configure mask */
913513f269SManish Tomar #define DSPI_CTAR_SET_MODE_MASK \
923513f269SManish Tomar (DSPI_CTAR_FMSZ(15) | DSPI_CTAR_PCS_SCK(3) | DSPI_CTAR_PA_SCK(3) | \
933513f269SManish Tomar DSPI_CTAR_P_DT(3) | DSPI_CTAR_CS_SCK(15) | DSPI_CTAR_A_SCK(15) | \
943513f269SManish Tomar DSPI_CTAR_A_DT(15))
953513f269SManish Tomar
963513f269SManish Tomar /* default SCK frequency, unit: HZ */
973513f269SManish Tomar #define PLATFORM_CLK 650000000
983513f269SManish Tomar #define DSPI_DEFAULT_SCK_FREQ 10000000
993513f269SManish Tomar #define DSPI_CLK_DIV 4 /* prescaler divisor */
1003513f269SManish Tomar #define DSPI_CLK (PLATFORM_CLK / DSPI_CLK_DIV) /* DSPI clock */
1013513f269SManish Tomar #define CS_SPEED_MAX_HZ 1000000 /* Slave max speed */
1023513f269SManish Tomar
1033513f269SManish Tomar /*
1043513f269SManish Tomar * Calculate the divide scaler value between expected SCK frequency
1053513f269SManish Tomar * and input clk frequency
1063513f269SManish Tomar * req_pbr: pre-scaler value of baud rate for slave
1073513f269SManish Tomar * req_br: scaler value of baud rate for slave
1083513f269SManish Tomar * speed_hz: speed value of slave
1093513f269SManish Tomar * clkrate: clock value of slave
1103513f269SManish Tomar */
dspi_convert_hz_to_baud(unsigned int * req_pbr,unsigned int * req_br,unsigned int speed_hz,unsigned int clkrate)1113513f269SManish Tomar static TEE_Result dspi_convert_hz_to_baud(unsigned int *req_pbr,
1123513f269SManish Tomar unsigned int *req_br,
1133513f269SManish Tomar unsigned int speed_hz,
1143513f269SManish Tomar unsigned int clkrate)
1153513f269SManish Tomar {
1163513f269SManish Tomar /* Valid pre-scaler values for baud rate*/
1173513f269SManish Tomar static const unsigned int pbr_val[4] = { 2, 3, 5, 7 };
1183513f269SManish Tomar /* Valid baud rate scaler values*/
1193513f269SManish Tomar static const unsigned int brs_val[16] = { 2, 4, 6, 8,
1203513f269SManish Tomar 16, 32, 64, 128,
1213513f269SManish Tomar 256, 512, 1024, 2048,
1223513f269SManish Tomar 4096, 8192, 16384, 32768 };
1233513f269SManish Tomar unsigned int tmp_val = 0;
1243513f269SManish Tomar unsigned int curr_val = 0;
1253513f269SManish Tomar unsigned int i = 0;
1263513f269SManish Tomar unsigned int j = 0;
1273513f269SManish Tomar
1283513f269SManish Tomar tmp_val = clkrate / speed_hz;
1293513f269SManish Tomar
1303513f269SManish Tomar for (i = 0; i < ARRAY_SIZE(pbr_val); i++) {
1313513f269SManish Tomar for (j = 0; j < ARRAY_SIZE(brs_val); j++) {
1323513f269SManish Tomar curr_val = pbr_val[i] * brs_val[j];
1333513f269SManish Tomar if (curr_val >= tmp_val) {
1343513f269SManish Tomar *req_pbr = i;
1353513f269SManish Tomar *req_br = j;
1363513f269SManish Tomar return TEE_SUCCESS;
1373513f269SManish Tomar }
1383513f269SManish Tomar }
1393513f269SManish Tomar }
1403513f269SManish Tomar
1413513f269SManish Tomar EMSG("Can not find valid baud rate, speed_hz is %d, ", speed_hz);
1423513f269SManish Tomar EMSG("clkrate is %d, using max prescaler value", clkrate);
1433513f269SManish Tomar
1443513f269SManish Tomar return TEE_ERROR_ITEM_NOT_FOUND;
1453513f269SManish Tomar }
1463513f269SManish Tomar
1473513f269SManish Tomar /*
1483513f269SManish Tomar * Configure speed of slave
1493513f269SManish Tomar * dspi_data: DSPI controller chip instance
1503513f269SManish Tomar * speed: speed of slave
1513513f269SManish Tomar */
dspi_setup_speed(struct ls_dspi_data * dspi_data,unsigned int speed)1523513f269SManish Tomar static void dspi_setup_speed(struct ls_dspi_data *dspi_data,
1533513f269SManish Tomar unsigned int speed)
1543513f269SManish Tomar {
1553513f269SManish Tomar TEE_Result status = TEE_ERROR_GENERIC;
1563513f269SManish Tomar unsigned int bus_setup = 0;
1573513f269SManish Tomar unsigned int bus_clock = 0;
1583513f269SManish Tomar unsigned int req_i = 0;
1593513f269SManish Tomar unsigned int req_j = 0;
1603513f269SManish Tomar
1613513f269SManish Tomar bus_clock = dspi_data->bus_clk_hz;
1623513f269SManish Tomar
1633513f269SManish Tomar DMSG("DSPI set_speed: expected SCK speed %u, bus_clk %u", speed,
1643513f269SManish Tomar bus_clock);
1653513f269SManish Tomar
1663513f269SManish Tomar bus_setup = io_read32(dspi_data->base + DSPI_CTAR0);
1673513f269SManish Tomar bus_setup &= ~(DSPI_CTAR_BRD | DSPI_CTAR_BRP(0x3) | DSPI_CTAR_BR(0xf));
1683513f269SManish Tomar
1693513f269SManish Tomar status = dspi_convert_hz_to_baud(&req_i, &req_j, speed, bus_clock);
1703513f269SManish Tomar
1713513f269SManish Tomar /* In case of failure scenario with max speed, setting default speed */
1723513f269SManish Tomar if (status == TEE_ERROR_ITEM_NOT_FOUND) {
1733513f269SManish Tomar speed = dspi_data->speed_hz;
1743513f269SManish Tomar status = dspi_convert_hz_to_baud(&req_i, &req_j,
1753513f269SManish Tomar speed, bus_clock);
1763513f269SManish Tomar }
1773513f269SManish Tomar
1783513f269SManish Tomar if (status == TEE_SUCCESS) {
1793513f269SManish Tomar bus_setup |= (DSPI_CTAR_BRP(req_i) | DSPI_CTAR_BR(req_j));
1803513f269SManish Tomar io_write32(dspi_data->base + DSPI_CTAR0, bus_setup);
1813513f269SManish Tomar dspi_data->speed_hz = speed;
1823513f269SManish Tomar } else {
1833513f269SManish Tomar EMSG("Unable to set speed");
1843513f269SManish Tomar }
1853513f269SManish Tomar }
1863513f269SManish Tomar
1873513f269SManish Tomar /*
1883513f269SManish Tomar * Transferred data to TX FIFO
1893513f269SManish Tomar * dspi_data: DSPI controller chip instance
1903513f269SManish Tomar */
dspi_tx(struct ls_dspi_data * dspi_data,uint32_t ctrl,uint16_t data)1913513f269SManish Tomar static void dspi_tx(struct ls_dspi_data *dspi_data, uint32_t ctrl,
1923513f269SManish Tomar uint16_t data)
1933513f269SManish Tomar {
1943513f269SManish Tomar int timeout = DSPI_TXRX_WAIT_TIMEOUT;
1953513f269SManish Tomar uint32_t dspi_val_addr = dspi_data->base + DSPI_PUSHR;
1963513f269SManish Tomar uint32_t dspi_val = ctrl | data;
1973513f269SManish Tomar
1983513f269SManish Tomar /* wait for empty entries in TXFIFO or timeout */
1993513f269SManish Tomar while (DSPI_SR_TXCTR(io_read32(dspi_data->base + DSPI_SR)) >= 4 &&
2003513f269SManish Tomar timeout--)
2013513f269SManish Tomar udelay(1);
2023513f269SManish Tomar
2033513f269SManish Tomar if (timeout >= 0)
2043513f269SManish Tomar io_write32(dspi_val_addr, dspi_val);
2053513f269SManish Tomar else
2063513f269SManish Tomar EMSG("waiting timeout!");
2073513f269SManish Tomar }
2083513f269SManish Tomar
2093513f269SManish Tomar /*
2103513f269SManish Tomar * Read data from RX FIFO
2113513f269SManish Tomar * dspi_data: DSPI controller chip instance
2123513f269SManish Tomar */
dspi_rx(struct ls_dspi_data * dspi_data)2133513f269SManish Tomar static uint16_t dspi_rx(struct ls_dspi_data *dspi_data)
2143513f269SManish Tomar {
2153513f269SManish Tomar int timeout = DSPI_TXRX_WAIT_TIMEOUT;
2163513f269SManish Tomar uint32_t dspi_val_addr = dspi_data->base + DSPI_POPR;
2173513f269SManish Tomar
2183513f269SManish Tomar /* wait for valid entries in RXFIFO or timeout */
2193513f269SManish Tomar while (DSPI_SR_RXCTR(io_read32(dspi_data->base + DSPI_SR)) == 0 &&
2203513f269SManish Tomar timeout--)
2213513f269SManish Tomar udelay(1);
2223513f269SManish Tomar
2233513f269SManish Tomar if (timeout >= 0)
2243513f269SManish Tomar return (uint16_t)DSPI_RFR_RXDATA(io_read32(dspi_val_addr));
2253513f269SManish Tomar
2263513f269SManish Tomar EMSG("waiting timeout!");
2273513f269SManish Tomar
2283513f269SManish Tomar return 0xFFFF;
2293513f269SManish Tomar }
2303513f269SManish Tomar
2313513f269SManish Tomar /*
2323513f269SManish Tomar * Transfer and Receive 8-bit data
2333513f269SManish Tomar * chip: spi_chip instance
2343513f269SManish Tomar * wdata: TX data queue
2353513f269SManish Tomar * rdata: RX data queue
2363513f269SManish Tomar * num_pkts: number of data packets
2373513f269SManish Tomar */
ls_dspi_txrx8(struct spi_chip * chip,uint8_t * wdata,uint8_t * rdata,size_t num_pkts)2383513f269SManish Tomar static enum spi_result ls_dspi_txrx8(struct spi_chip *chip, uint8_t *wdata,
2393513f269SManish Tomar uint8_t *rdata, size_t num_pkts)
2403513f269SManish Tomar {
2413513f269SManish Tomar uint8_t *spi_rd = NULL;
2423513f269SManish Tomar uint8_t *spi_wr = NULL;
2433513f269SManish Tomar uint32_t ctrl = 0;
2443513f269SManish Tomar struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
2453513f269SManish Tomar chip);
2463513f269SManish Tomar unsigned int cs = data->slave_cs;
2473513f269SManish Tomar
2483513f269SManish Tomar spi_wr = wdata;
2493513f269SManish Tomar spi_rd = rdata;
2503513f269SManish Tomar
2513513f269SManish Tomar /*
2523513f269SManish Tomar * Assert PCSn signals between transfers
2533513f269SManish Tomar * select which CTAR register and slave to be used for TX
2543513f269SManish Tomar * CTAS selects which CTAR to be used, here we are using CTAR0
2553513f269SManish Tomar * PCS (peripheral chip select) is selecting the slave.
2563513f269SManish Tomar */
2573513f269SManish Tomar ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs);
2583513f269SManish Tomar if (data->slave_mode & SPI_CONT)
2593513f269SManish Tomar ctrl |= DSPI_TFR_CONT;
2603513f269SManish Tomar
2613513f269SManish Tomar if (data->slave_data_size_bits != 8) {
2623513f269SManish Tomar EMSG("data_size_bits should be 8, not %u",
2633513f269SManish Tomar data->slave_data_size_bits);
2643513f269SManish Tomar return SPI_ERR_CFG;
2653513f269SManish Tomar }
2663513f269SManish Tomar
2673513f269SManish Tomar while (num_pkts) {
2683513f269SManish Tomar if (wdata && rdata) {
2693513f269SManish Tomar dspi_tx(data, ctrl, *spi_wr++);
2703513f269SManish Tomar *spi_rd++ = dspi_rx(data);
2713513f269SManish Tomar } else if (wdata) {
2723513f269SManish Tomar dspi_tx(data, ctrl, *spi_wr++);
2733513f269SManish Tomar dspi_rx(data);
2743513f269SManish Tomar } else if (rdata) {
2753513f269SManish Tomar dspi_tx(data, ctrl, DSPI_IDLE_DATA);
2763513f269SManish Tomar *spi_rd++ = dspi_rx(data);
2773513f269SManish Tomar }
2783513f269SManish Tomar num_pkts = num_pkts - 1;
2793513f269SManish Tomar }
2803513f269SManish Tomar
2813513f269SManish Tomar return SPI_OK;
2823513f269SManish Tomar }
2833513f269SManish Tomar
2843513f269SManish Tomar /*
2853513f269SManish Tomar * Transfer and Receive 16-bit data
2863513f269SManish Tomar * chip: spi_chip instance
2873513f269SManish Tomar * wdata: TX data queue
2883513f269SManish Tomar * rdata: RX data queue
2893513f269SManish Tomar * num_pkts: number of data packets
2903513f269SManish Tomar */
ls_dspi_txrx16(struct spi_chip * chip,uint16_t * wdata,uint16_t * rdata,size_t num_pkts)2913513f269SManish Tomar static enum spi_result ls_dspi_txrx16(struct spi_chip *chip, uint16_t *wdata,
2923513f269SManish Tomar uint16_t *rdata, size_t num_pkts)
2933513f269SManish Tomar {
2943513f269SManish Tomar uint32_t ctrl = 0;
2953513f269SManish Tomar uint16_t *spi_rd = NULL;
2963513f269SManish Tomar uint16_t *spi_wr = NULL;
2973513f269SManish Tomar struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
2983513f269SManish Tomar chip);
2993513f269SManish Tomar unsigned int cs = data->slave_cs;
3003513f269SManish Tomar
3013513f269SManish Tomar spi_wr = wdata;
3023513f269SManish Tomar spi_rd = rdata;
3033513f269SManish Tomar
3043513f269SManish Tomar /*
3053513f269SManish Tomar * Assert PCSn signals between transfers
3063513f269SManish Tomar * select which CTAR register and slave to be used for TX
3073513f269SManish Tomar * CTAS selects which CTAR to be used, here we are using CTAR0
3083513f269SManish Tomar * PCS (peripheral chip select) is selecting the slave.
3093513f269SManish Tomar */
3103513f269SManish Tomar ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs);
3113513f269SManish Tomar if (data->slave_mode & SPI_CONT)
3123513f269SManish Tomar ctrl |= DSPI_TFR_CONT;
3133513f269SManish Tomar
3143513f269SManish Tomar if (data->slave_data_size_bits != 16) {
3153513f269SManish Tomar EMSG("data_size_bits should be 16, not %u",
3163513f269SManish Tomar data->slave_data_size_bits);
3173513f269SManish Tomar return SPI_ERR_CFG;
3183513f269SManish Tomar }
3193513f269SManish Tomar
3203513f269SManish Tomar while (num_pkts) {
3213513f269SManish Tomar if (wdata && rdata) {
3223513f269SManish Tomar dspi_tx(data, ctrl, *spi_wr++);
3233513f269SManish Tomar *spi_rd++ = dspi_rx(data);
3243513f269SManish Tomar } else if (wdata) {
3253513f269SManish Tomar dspi_tx(data, ctrl, *spi_wr++);
3263513f269SManish Tomar dspi_rx(data);
3273513f269SManish Tomar } else if (rdata) {
3283513f269SManish Tomar dspi_tx(data, ctrl, DSPI_IDLE_DATA);
3293513f269SManish Tomar *spi_rd++ = dspi_rx(data);
3303513f269SManish Tomar }
3313513f269SManish Tomar num_pkts = num_pkts - 1;
3323513f269SManish Tomar }
3333513f269SManish Tomar
3343513f269SManish Tomar return SPI_OK;
3353513f269SManish Tomar }
3363513f269SManish Tomar
3373513f269SManish Tomar /*
3383513f269SManish Tomar * Statrt DSPI module
3393513f269SManish Tomar * chip: spi_chip instance
3403513f269SManish Tomar */
ls_dspi_start(struct spi_chip * chip)3413513f269SManish Tomar static void ls_dspi_start(struct spi_chip *chip)
3423513f269SManish Tomar {
3433513f269SManish Tomar struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
3443513f269SManish Tomar chip);
3453513f269SManish Tomar
3463513f269SManish Tomar DMSG("Start DSPI Module");
3473513f269SManish Tomar io_clrbits32(data->base + DSPI_MCR, DSPI_MCR_HALT);
3483513f269SManish Tomar }
3493513f269SManish Tomar
3503513f269SManish Tomar /*
3513513f269SManish Tomar * Stop DSPI module
3523513f269SManish Tomar * chip: spi_chip instance
3533513f269SManish Tomar */
ls_dspi_end(struct spi_chip * chip)3543513f269SManish Tomar static void ls_dspi_end(struct spi_chip *chip)
3553513f269SManish Tomar {
3563513f269SManish Tomar struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
3573513f269SManish Tomar chip);
3583513f269SManish Tomar
3593513f269SManish Tomar /* De-assert PCSn if in CONT mode */
3603513f269SManish Tomar if (data->slave_mode & SPI_CONT) {
3613513f269SManish Tomar unsigned int cs = data->slave_cs;
3623513f269SManish Tomar unsigned int ctrl = DSPI_TFR_CTAS(data->ctar_sel) |
3633513f269SManish Tomar DSPI_TFR_PCS(cs);
3643513f269SManish Tomar
3653513f269SManish Tomar /* Dummy read to deassert */
3663513f269SManish Tomar dspi_tx(data, ctrl, DSPI_IDLE_DATA);
3673513f269SManish Tomar dspi_rx(data);
3683513f269SManish Tomar }
3693513f269SManish Tomar
3703513f269SManish Tomar DMSG("Stop DSPI Module");
3713513f269SManish Tomar io_setbits32(data->base + DSPI_MCR, DSPI_MCR_HALT);
3723513f269SManish Tomar }
3733513f269SManish Tomar
3743513f269SManish Tomar /*
3753513f269SManish Tomar * Clear RX and TX FIFO
3763513f269SManish Tomar * dspi_data: DSPI controller chip instance
3773513f269SManish Tomar */
dspi_flush_fifo(struct ls_dspi_data * dspi_data)37816c55971SSriram Sriram static void dspi_flush_fifo(struct ls_dspi_data *dspi_data)
3793513f269SManish Tomar {
3803513f269SManish Tomar unsigned int mcr_val = 0;
3813513f269SManish Tomar
3823513f269SManish Tomar mcr_val = io_read32(dspi_data->base + DSPI_MCR);
3833513f269SManish Tomar /* flush RX and TX FIFO */
3843513f269SManish Tomar mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
3853513f269SManish Tomar
3863513f269SManish Tomar io_write32(dspi_data->base + DSPI_MCR, mcr_val);
3873513f269SManish Tomar }
3883513f269SManish Tomar
3893513f269SManish Tomar /*
3906b48e94fSCarl Lamb * Flush DSPI module
3916b48e94fSCarl Lamb * chip: spi_chip instance
3926b48e94fSCarl Lamb */
ls_dspi_flush(struct spi_chip * chip)3936b48e94fSCarl Lamb static void ls_dspi_flush(struct spi_chip *chip)
3946b48e94fSCarl Lamb {
3956b48e94fSCarl Lamb struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
3966b48e94fSCarl Lamb chip);
3976b48e94fSCarl Lamb
3986b48e94fSCarl Lamb dspi_flush_fifo(data);
3996b48e94fSCarl Lamb }
4006b48e94fSCarl Lamb
4016b48e94fSCarl Lamb /*
4023513f269SManish Tomar * Configure active state of slave
4033513f269SManish Tomar * dspi_data: DSPI controller chip instance
4043513f269SManish Tomar * cs: chip select value of slave
4053513f269SManish Tomar * state: slave mode
4063513f269SManish Tomar */
dspi_set_cs_active_state(struct ls_dspi_data * dspi_data,unsigned int cs,unsigned int state)4073513f269SManish Tomar static void dspi_set_cs_active_state(struct ls_dspi_data *dspi_data,
4083513f269SManish Tomar unsigned int cs, unsigned int state)
4093513f269SManish Tomar {
4103513f269SManish Tomar DMSG("Set CS active state cs=%d state=%d", cs, state);
4113513f269SManish Tomar
4123513f269SManish Tomar if (state & SPI_CS_HIGH)
4133513f269SManish Tomar /* CSx inactive state is low */
4143513f269SManish Tomar io_clrbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs));
4153513f269SManish Tomar else
4163513f269SManish Tomar /* CSx inactive state is high */
4173513f269SManish Tomar io_setbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs));
4183513f269SManish Tomar }
4193513f269SManish Tomar
4203513f269SManish Tomar /*
4213513f269SManish Tomar * Configure transfer state of slave
4223513f269SManish Tomar * dspi_data: DSPI controller chip instance
4233513f269SManish Tomar * state: slave mode
4243513f269SManish Tomar */
dspi_set_transfer_state(struct ls_dspi_data * dspi_data,unsigned int state)4253513f269SManish Tomar static void dspi_set_transfer_state(struct ls_dspi_data *dspi_data,
4263513f269SManish Tomar unsigned int state)
4273513f269SManish Tomar {
4283513f269SManish Tomar unsigned int bus_setup = 0;
4293513f269SManish Tomar
4303513f269SManish Tomar DMSG("Set transfer state=%d bits=%d", state,
4313513f269SManish Tomar dspi_data->slave_data_size_bits);
4323513f269SManish Tomar
4333513f269SManish Tomar bus_setup = io_read32(dspi_data->base + DSPI_CTAR0);
4343513f269SManish Tomar bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
4353513f269SManish Tomar bus_setup |= dspi_data->ctar_val;
4363513f269SManish Tomar bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE);
4373513f269SManish Tomar
4383513f269SManish Tomar if (state & SPI_CPOL)
4393513f269SManish Tomar bus_setup |= DSPI_CTAR_CPOL;
4403513f269SManish Tomar if (state & SPI_CPHA)
4413513f269SManish Tomar bus_setup |= DSPI_CTAR_CPHA;
4423513f269SManish Tomar if (state & SPI_LSB_FIRST)
4433513f269SManish Tomar bus_setup |= DSPI_CTAR_LSBFE;
4443513f269SManish Tomar
4453513f269SManish Tomar if (dspi_data->slave_data_size_bits == 8)
4463513f269SManish Tomar bus_setup |= DSPI_CTAR_FMSZ(7);
4473513f269SManish Tomar else if (dspi_data->slave_data_size_bits == 16)
4483513f269SManish Tomar bus_setup |= DSPI_CTAR_FMSZ(15);
4493513f269SManish Tomar
4503513f269SManish Tomar if (dspi_data->ctar_sel == 0)
4513513f269SManish Tomar io_write32(dspi_data->base + DSPI_CTAR0, bus_setup);
4523513f269SManish Tomar else
4533513f269SManish Tomar io_write32(dspi_data->base + DSPI_CTAR1, bus_setup);
4543513f269SManish Tomar }
4553513f269SManish Tomar
4563513f269SManish Tomar /*
4573513f269SManish Tomar * Configure speed of slave
4583513f269SManish Tomar * dspi_data: DSPI controller chip instance
4593513f269SManish Tomar * speed_max_hz: maximum speed for slave
4603513f269SManish Tomar */
dspi_set_speed(struct ls_dspi_data * dspi_data,unsigned int speed_max_hz)4613513f269SManish Tomar static void dspi_set_speed(struct ls_dspi_data *dspi_data,
4623513f269SManish Tomar unsigned int speed_max_hz)
4633513f269SManish Tomar {
4643513f269SManish Tomar dspi_setup_speed(dspi_data, speed_max_hz);
4653513f269SManish Tomar }
4663513f269SManish Tomar
4673513f269SManish Tomar /*
4683513f269SManish Tomar * Configure slave for DSPI controller
4693513f269SManish Tomar * dspi_data: DSPI controller chip instance
4703513f269SManish Tomar * cs: chip select value of slave
4713513f269SManish Tomar * speed_max_hz: maximum speed of slave
4723513f269SManish Tomar * state: slave mode
4733513f269SManish Tomar */
dspi_config_slave_state(struct ls_dspi_data * dspi_data,unsigned int cs,unsigned int speed_max_hz,unsigned int state)4743513f269SManish Tomar static void dspi_config_slave_state(struct ls_dspi_data *dspi_data,
4753513f269SManish Tomar unsigned int cs, unsigned int speed_max_hz,
4763513f269SManish Tomar unsigned int state)
4773513f269SManish Tomar {
4783513f269SManish Tomar unsigned int sr_val = 0;
4793513f269SManish Tomar
4803513f269SManish Tomar /* configure speed */
4813513f269SManish Tomar dspi_set_speed(dspi_data, speed_max_hz);
4823513f269SManish Tomar
4833513f269SManish Tomar /* configure transfer state */
4843513f269SManish Tomar dspi_set_transfer_state(dspi_data, state);
4853513f269SManish Tomar
4863513f269SManish Tomar /* configure active state of CSX */
4873513f269SManish Tomar dspi_set_cs_active_state(dspi_data, cs, state);
4883513f269SManish Tomar
4893513f269SManish Tomar /* clear FIFO */
4903513f269SManish Tomar dspi_flush_fifo(dspi_data);
4913513f269SManish Tomar
4923513f269SManish Tomar /* check module TX and RX status */
4933513f269SManish Tomar sr_val = io_read32(dspi_data->base + DSPI_SR);
4943513f269SManish Tomar if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS)
4953513f269SManish Tomar EMSG("DSPI RX/TX not ready");
4963513f269SManish Tomar }
4973513f269SManish Tomar
4983513f269SManish Tomar /*
4993513f269SManish Tomar * Configure master for DSPI controller
5003513f269SManish Tomar * dspi_data: DSPI controller chip instance
5013513f269SManish Tomar * mcr_val: value of master configuration register
5023513f269SManish Tomar */
dspi_set_master_state(struct ls_dspi_data * dspi_data,unsigned int mcr_val)5033513f269SManish Tomar static void dspi_set_master_state(struct ls_dspi_data *dspi_data,
5043513f269SManish Tomar unsigned int mcr_val)
5053513f269SManish Tomar {
5063513f269SManish Tomar DMSG("Set master state val=0x%x", mcr_val);
5073513f269SManish Tomar io_write32(dspi_data->base + DSPI_MCR, mcr_val);
5083513f269SManish Tomar }
5093513f269SManish Tomar
5103513f269SManish Tomar /*
5113513f269SManish Tomar * Configure DSPI controller
5123513f269SManish Tomar * chip: spi_chip instance
5133513f269SManish Tomar */
ls_dspi_configure(struct spi_chip * chip)5143513f269SManish Tomar static void ls_dspi_configure(struct spi_chip *chip)
5153513f269SManish Tomar {
5163513f269SManish Tomar struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
5173513f269SManish Tomar chip);
5183513f269SManish Tomar unsigned int mcr_cfg_val = 0;
5193513f269SManish Tomar
5203513f269SManish Tomar mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK | DSPI_MCR_CRXF |
5213513f269SManish Tomar DSPI_MCR_CTXF;
5223513f269SManish Tomar
5233513f269SManish Tomar /* Configure Master */
5243513f269SManish Tomar dspi_set_master_state(data, mcr_cfg_val);
5253513f269SManish Tomar
5263513f269SManish Tomar /* Configure DSPI slave */
5273513f269SManish Tomar dspi_config_slave_state(data, data->slave_cs, data->slave_speed_max_hz,
5283513f269SManish Tomar data->slave_mode);
5293513f269SManish Tomar }
5303513f269SManish Tomar
5313513f269SManish Tomar /*
5323513f269SManish Tomar * Extract information for DSPI Controller from the DTB
5333513f269SManish Tomar * dspi_data: DSPI controller chip instance
5343513f269SManish Tomar */
get_info_from_device_tree(struct ls_dspi_data * dspi_data)5353513f269SManish Tomar static TEE_Result get_info_from_device_tree(struct ls_dspi_data *dspi_data)
5363513f269SManish Tomar {
5373513f269SManish Tomar const fdt32_t *bus_num = NULL;
5383513f269SManish Tomar const fdt32_t *chip_select_num = NULL;
5393513f269SManish Tomar size_t size = 0;
5403513f269SManish Tomar int node = 0;
5413513f269SManish Tomar vaddr_t ctrl_base = 0;
5423513f269SManish Tomar void *fdt = NULL;
5433513f269SManish Tomar
5443513f269SManish Tomar /*
5453513f269SManish Tomar * First get the DSPI Controller base address from the DTB
5463513f269SManish Tomar * if DTB present and if the DSPI Controller defined in it.
5473513f269SManish Tomar */
5483513f269SManish Tomar fdt = get_dt();
5493513f269SManish Tomar if (!fdt) {
550*bce2f88aSVincent Mailhol EMSG("Unable to get DTB, DSPI init failed");
5513513f269SManish Tomar return TEE_ERROR_ITEM_NOT_FOUND;
5523513f269SManish Tomar }
5533513f269SManish Tomar
5543513f269SManish Tomar node = 0;
5553513f269SManish Tomar while (node != -FDT_ERR_NOTFOUND) {
5563513f269SManish Tomar node = fdt_node_offset_by_compatible(fdt, node,
5573513f269SManish Tomar "fsl,lx2160a-dspi");
558f354a5d8SGatien Chevallier if (!(fdt_get_status(fdt, node) & DT_STATUS_OK_SEC))
5593513f269SManish Tomar continue;
5603513f269SManish Tomar
5613513f269SManish Tomar bus_num = fdt_getprop(fdt, node, "bus-num", NULL);
5623513f269SManish Tomar if (bus_num && dspi_data->slave_bus ==
5633513f269SManish Tomar (unsigned int)fdt32_to_cpu(*bus_num)) {
564a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &ctrl_base, &size,
565a5d5bbc8SVesa Jääskeläinen DT_MAP_AUTO) < 0) {
5663513f269SManish Tomar EMSG("Unable to get virtual address");
5673513f269SManish Tomar return TEE_ERROR_GENERIC;
5683513f269SManish Tomar }
5693513f269SManish Tomar break;
5703513f269SManish Tomar }
5713513f269SManish Tomar }
5723513f269SManish Tomar
5733513f269SManish Tomar dspi_data->base = ctrl_base;
5743513f269SManish Tomar dspi_data->bus_clk_hz = DSPI_CLK;
5753513f269SManish Tomar
5763513f269SManish Tomar chip_select_num = fdt_getprop(fdt, node, "spi-num-chipselects", NULL);
5773513f269SManish Tomar if (chip_select_num)
5783513f269SManish Tomar dspi_data->num_chipselect = (int)fdt32_to_cpu(*chip_select_num);
5793513f269SManish Tomar else
5803513f269SManish Tomar return TEE_ERROR_ITEM_NOT_FOUND;
5813513f269SManish Tomar
5823513f269SManish Tomar dspi_data->speed_hz = DSPI_DEFAULT_SCK_FREQ;
5833513f269SManish Tomar
5843513f269SManish Tomar return TEE_SUCCESS;
5853513f269SManish Tomar }
5863513f269SManish Tomar
5873513f269SManish Tomar static const struct spi_ops ls_dspi_ops = {
5883513f269SManish Tomar .configure = ls_dspi_configure,
5893513f269SManish Tomar .start = ls_dspi_start,
5903513f269SManish Tomar .txrx8 = ls_dspi_txrx8,
5913513f269SManish Tomar .txrx16 = ls_dspi_txrx16,
5923513f269SManish Tomar .end = ls_dspi_end,
5936b48e94fSCarl Lamb .flushfifo = ls_dspi_flush,
5943513f269SManish Tomar };
5953513f269SManish Tomar DECLARE_KEEP_PAGER(ls_dspi_ops);
5963513f269SManish Tomar
ls_dspi_init(struct ls_dspi_data * dspi_data)5973513f269SManish Tomar TEE_Result ls_dspi_init(struct ls_dspi_data *dspi_data)
5983513f269SManish Tomar {
5993513f269SManish Tomar TEE_Result status = TEE_ERROR_GENERIC;
6003513f269SManish Tomar
6013513f269SManish Tomar /*
6023513f269SManish Tomar * First get the DSPI Controller base address from the DTB,
6033513f269SManish Tomar * if DTB present and if the DSPI Controller defined in it.
6043513f269SManish Tomar */
6053513f269SManish Tomar if (dspi_data)
6063513f269SManish Tomar status = get_info_from_device_tree(dspi_data);
6073513f269SManish Tomar if (status == TEE_SUCCESS)
6083513f269SManish Tomar /* generic DSPI chip handle */
6093513f269SManish Tomar dspi_data->chip.ops = &ls_dspi_ops;
6103513f269SManish Tomar else
6113513f269SManish Tomar EMSG("Unable to get info from device tree");
6123513f269SManish Tomar
6133513f269SManish Tomar return status;
6143513f269SManish Tomar }
615