xref: /optee_os/core/drivers/ls_dspi.c (revision f354a5d8f98eb3bc8f3360eccd7405144266b5b4)
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 /* SPI mode flags */
973513f269SManish Tomar #define SPI_CPHA      BIT(0) /* clock phase */
983513f269SManish Tomar #define SPI_CPOL      BIT(1) /* clock polarity */
993513f269SManish Tomar #define SPI_CS_HIGH   BIT(2) /* CS active high */
1003513f269SManish Tomar #define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */
1013513f269SManish Tomar #define SPI_CONT      BIT(4) /* Continuous CS mode */
1023513f269SManish Tomar 
1033513f269SManish Tomar /* default SCK frequency, unit: HZ */
1043513f269SManish Tomar #define PLATFORM_CLK          650000000
1053513f269SManish Tomar #define DSPI_DEFAULT_SCK_FREQ 10000000
1063513f269SManish Tomar #define DSPI_CLK_DIV          4 /* prescaler divisor */
1073513f269SManish Tomar #define DSPI_CLK              (PLATFORM_CLK / DSPI_CLK_DIV) /* DSPI clock */
1083513f269SManish Tomar #define CS_SPEED_MAX_HZ       1000000   /* Slave max speed */
1093513f269SManish Tomar 
1103513f269SManish Tomar /*
1113513f269SManish Tomar  * Calculate the divide scaler value between expected SCK frequency
1123513f269SManish Tomar  * and input clk frequency
1133513f269SManish Tomar  * req_pbr:	pre-scaler value of baud rate for slave
1143513f269SManish Tomar  * req_br:	scaler value of baud rate for slave
1153513f269SManish Tomar  * speed_hz:	speed value of slave
1163513f269SManish Tomar  * clkrate:	clock value of slave
1173513f269SManish Tomar  */
1183513f269SManish Tomar static TEE_Result dspi_convert_hz_to_baud(unsigned int *req_pbr,
1193513f269SManish Tomar 					  unsigned int *req_br,
1203513f269SManish Tomar 					  unsigned int speed_hz,
1213513f269SManish Tomar 					  unsigned int clkrate)
1223513f269SManish Tomar {
1233513f269SManish Tomar 	/* Valid pre-scaler values for baud rate*/
1243513f269SManish Tomar 	static const unsigned int pbr_val[4] = { 2, 3, 5, 7 };
1253513f269SManish Tomar 	/* Valid baud rate scaler values*/
1263513f269SManish Tomar 	static const unsigned int brs_val[16] = { 2, 4, 6, 8,
1273513f269SManish Tomar 						16, 32, 64, 128,
1283513f269SManish Tomar 						256, 512, 1024, 2048,
1293513f269SManish Tomar 						4096, 8192, 16384, 32768 };
1303513f269SManish Tomar 	unsigned int tmp_val = 0;
1313513f269SManish Tomar 	unsigned int curr_val = 0;
1323513f269SManish Tomar 	unsigned int i = 0;
1333513f269SManish Tomar 	unsigned int j = 0;
1343513f269SManish Tomar 
1353513f269SManish Tomar 	tmp_val = clkrate / speed_hz;
1363513f269SManish Tomar 
1373513f269SManish Tomar 	for (i = 0; i < ARRAY_SIZE(pbr_val); i++) {
1383513f269SManish Tomar 		for (j = 0; j < ARRAY_SIZE(brs_val); j++) {
1393513f269SManish Tomar 			curr_val = pbr_val[i] * brs_val[j];
1403513f269SManish Tomar 			if (curr_val >= tmp_val) {
1413513f269SManish Tomar 				*req_pbr = i;
1423513f269SManish Tomar 				*req_br = j;
1433513f269SManish Tomar 				return TEE_SUCCESS;
1443513f269SManish Tomar 			}
1453513f269SManish Tomar 		}
1463513f269SManish Tomar 	}
1473513f269SManish Tomar 
1483513f269SManish Tomar 	EMSG("Can not find valid baud rate, speed_hz is %d, ", speed_hz);
1493513f269SManish Tomar 	EMSG("clkrate is %d, using max prescaler value", clkrate);
1503513f269SManish Tomar 
1513513f269SManish Tomar 	return TEE_ERROR_ITEM_NOT_FOUND;
1523513f269SManish Tomar }
1533513f269SManish Tomar 
1543513f269SManish Tomar /*
1553513f269SManish Tomar  * Configure speed of slave
1563513f269SManish Tomar  * dspi_data:	DSPI controller chip instance
1573513f269SManish Tomar  * speed:	speed of slave
1583513f269SManish Tomar  */
1593513f269SManish Tomar static void dspi_setup_speed(struct ls_dspi_data *dspi_data,
1603513f269SManish Tomar 			     unsigned int speed)
1613513f269SManish Tomar {
1623513f269SManish Tomar 	TEE_Result status = TEE_ERROR_GENERIC;
1633513f269SManish Tomar 	unsigned int bus_setup = 0;
1643513f269SManish Tomar 	unsigned int bus_clock = 0;
1653513f269SManish Tomar 	unsigned int req_i = 0;
1663513f269SManish Tomar 	unsigned int req_j = 0;
1673513f269SManish Tomar 
1683513f269SManish Tomar 	bus_clock = dspi_data->bus_clk_hz;
1693513f269SManish Tomar 
1703513f269SManish Tomar 	DMSG("DSPI set_speed: expected SCK speed %u, bus_clk %u", speed,
1713513f269SManish Tomar 	     bus_clock);
1723513f269SManish Tomar 
1733513f269SManish Tomar 	bus_setup = io_read32(dspi_data->base + DSPI_CTAR0);
1743513f269SManish Tomar 	bus_setup &= ~(DSPI_CTAR_BRD | DSPI_CTAR_BRP(0x3) | DSPI_CTAR_BR(0xf));
1753513f269SManish Tomar 
1763513f269SManish Tomar 	status = dspi_convert_hz_to_baud(&req_i, &req_j, speed, bus_clock);
1773513f269SManish Tomar 
1783513f269SManish Tomar 	/* In case of failure scenario with max speed, setting default speed */
1793513f269SManish Tomar 	if (status == TEE_ERROR_ITEM_NOT_FOUND) {
1803513f269SManish Tomar 		speed = dspi_data->speed_hz;
1813513f269SManish Tomar 		status = dspi_convert_hz_to_baud(&req_i, &req_j,
1823513f269SManish Tomar 						 speed, bus_clock);
1833513f269SManish Tomar 	}
1843513f269SManish Tomar 
1853513f269SManish Tomar 	if (status == TEE_SUCCESS) {
1863513f269SManish Tomar 		bus_setup |= (DSPI_CTAR_BRP(req_i) | DSPI_CTAR_BR(req_j));
1873513f269SManish Tomar 		io_write32(dspi_data->base + DSPI_CTAR0, bus_setup);
1883513f269SManish Tomar 		dspi_data->speed_hz = speed;
1893513f269SManish Tomar 	} else {
1903513f269SManish Tomar 		EMSG("Unable to set speed");
1913513f269SManish Tomar 	}
1923513f269SManish Tomar }
1933513f269SManish Tomar 
1943513f269SManish Tomar /*
1953513f269SManish Tomar  * Transferred data to TX FIFO
1963513f269SManish Tomar  * dspi_data:	DSPI controller chip instance
1973513f269SManish Tomar  */
1983513f269SManish Tomar static void dspi_tx(struct ls_dspi_data *dspi_data, uint32_t ctrl,
1993513f269SManish Tomar 		    uint16_t data)
2003513f269SManish Tomar {
2013513f269SManish Tomar 	int timeout = DSPI_TXRX_WAIT_TIMEOUT;
2023513f269SManish Tomar 	uint32_t dspi_val_addr = dspi_data->base + DSPI_PUSHR;
2033513f269SManish Tomar 	uint32_t dspi_val = ctrl | data;
2043513f269SManish Tomar 
2053513f269SManish Tomar 	/* wait for empty entries in TXFIFO or timeout */
2063513f269SManish Tomar 	while (DSPI_SR_TXCTR(io_read32(dspi_data->base + DSPI_SR)) >= 4 &&
2073513f269SManish Tomar 	       timeout--)
2083513f269SManish Tomar 		udelay(1);
2093513f269SManish Tomar 
2103513f269SManish Tomar 	if (timeout >= 0)
2113513f269SManish Tomar 		io_write32(dspi_val_addr, dspi_val);
2123513f269SManish Tomar 	else
2133513f269SManish Tomar 		EMSG("waiting timeout!");
2143513f269SManish Tomar }
2153513f269SManish Tomar 
2163513f269SManish Tomar /*
2173513f269SManish Tomar  * Read data from RX FIFO
2183513f269SManish Tomar  * dspi_data:	DSPI controller chip instance
2193513f269SManish Tomar  */
2203513f269SManish Tomar static uint16_t dspi_rx(struct ls_dspi_data *dspi_data)
2213513f269SManish Tomar {
2223513f269SManish Tomar 	int timeout = DSPI_TXRX_WAIT_TIMEOUT;
2233513f269SManish Tomar 	uint32_t dspi_val_addr = dspi_data->base + DSPI_POPR;
2243513f269SManish Tomar 
2253513f269SManish Tomar 	/* wait for valid entries in RXFIFO or timeout */
2263513f269SManish Tomar 	while (DSPI_SR_RXCTR(io_read32(dspi_data->base + DSPI_SR)) == 0 &&
2273513f269SManish Tomar 	       timeout--)
2283513f269SManish Tomar 		udelay(1);
2293513f269SManish Tomar 
2303513f269SManish Tomar 	if (timeout >= 0)
2313513f269SManish Tomar 		return (uint16_t)DSPI_RFR_RXDATA(io_read32(dspi_val_addr));
2323513f269SManish Tomar 
2333513f269SManish Tomar 	EMSG("waiting timeout!");
2343513f269SManish Tomar 
2353513f269SManish Tomar 	return 0xFFFF;
2363513f269SManish Tomar }
2373513f269SManish Tomar 
2383513f269SManish Tomar /*
2393513f269SManish Tomar  * Transfer and Receive 8-bit data
2403513f269SManish Tomar  * chip:	spi_chip instance
2413513f269SManish Tomar  * wdata:	TX data queue
2423513f269SManish Tomar  * rdata:	RX data queue
2433513f269SManish Tomar  * num_pkts:	number of data packets
2443513f269SManish Tomar  */
2453513f269SManish Tomar static enum spi_result ls_dspi_txrx8(struct spi_chip *chip, uint8_t *wdata,
2463513f269SManish Tomar 				     uint8_t *rdata, size_t num_pkts)
2473513f269SManish Tomar {
2483513f269SManish Tomar 	uint8_t *spi_rd = NULL;
2493513f269SManish Tomar 	uint8_t *spi_wr = NULL;
2503513f269SManish Tomar 	uint32_t ctrl = 0;
2513513f269SManish Tomar 	struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
2523513f269SManish Tomar 						  chip);
2533513f269SManish Tomar 	unsigned int cs = data->slave_cs;
2543513f269SManish Tomar 
2553513f269SManish Tomar 	spi_wr = wdata;
2563513f269SManish Tomar 	spi_rd = rdata;
2573513f269SManish Tomar 
2583513f269SManish Tomar 	/*
2593513f269SManish Tomar 	 * Assert PCSn signals between transfers
2603513f269SManish Tomar 	 * select which CTAR register and slave to be used for TX
2613513f269SManish Tomar 	 * CTAS selects which CTAR to be used, here we are using CTAR0
2623513f269SManish Tomar 	 * PCS (peripheral chip select) is selecting the slave.
2633513f269SManish Tomar 	 */
2643513f269SManish Tomar 	ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs);
2653513f269SManish Tomar 	if (data->slave_mode & SPI_CONT)
2663513f269SManish Tomar 		ctrl |= DSPI_TFR_CONT;
2673513f269SManish Tomar 
2683513f269SManish Tomar 	if (data->slave_data_size_bits != 8) {
2693513f269SManish Tomar 		EMSG("data_size_bits should be 8, not %u",
2703513f269SManish Tomar 		     data->slave_data_size_bits);
2713513f269SManish Tomar 		return SPI_ERR_CFG;
2723513f269SManish Tomar 	}
2733513f269SManish Tomar 
2743513f269SManish Tomar 	while (num_pkts) {
2753513f269SManish Tomar 		if (wdata && rdata) {
2763513f269SManish Tomar 			dspi_tx(data, ctrl, *spi_wr++);
2773513f269SManish Tomar 			*spi_rd++ = dspi_rx(data);
2783513f269SManish Tomar 		} else if (wdata) {
2793513f269SManish Tomar 			dspi_tx(data, ctrl, *spi_wr++);
2803513f269SManish Tomar 			dspi_rx(data);
2813513f269SManish Tomar 		} else if (rdata) {
2823513f269SManish Tomar 			dspi_tx(data, ctrl, DSPI_IDLE_DATA);
2833513f269SManish Tomar 			*spi_rd++ = dspi_rx(data);
2843513f269SManish Tomar 		}
2853513f269SManish Tomar 		num_pkts = num_pkts - 1;
2863513f269SManish Tomar 	}
2873513f269SManish Tomar 
2883513f269SManish Tomar 	return SPI_OK;
2893513f269SManish Tomar }
2903513f269SManish Tomar 
2913513f269SManish Tomar /*
2923513f269SManish Tomar  * Transfer and Receive 16-bit data
2933513f269SManish Tomar  * chip:        spi_chip instance
2943513f269SManish Tomar  * wdata:	TX data queue
2953513f269SManish Tomar  * rdata:	RX data queue
2963513f269SManish Tomar  * num_pkts:	number of data packets
2973513f269SManish Tomar  */
2983513f269SManish Tomar static enum spi_result ls_dspi_txrx16(struct spi_chip *chip, uint16_t *wdata,
2993513f269SManish Tomar 				      uint16_t *rdata, size_t num_pkts)
3003513f269SManish Tomar {
3013513f269SManish Tomar 	uint32_t ctrl = 0;
3023513f269SManish Tomar 	uint16_t *spi_rd = NULL;
3033513f269SManish Tomar 	uint16_t *spi_wr = NULL;
3043513f269SManish Tomar 	struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
3053513f269SManish Tomar 						  chip);
3063513f269SManish Tomar 	unsigned int cs = data->slave_cs;
3073513f269SManish Tomar 
3083513f269SManish Tomar 	spi_wr = wdata;
3093513f269SManish Tomar 	spi_rd = rdata;
3103513f269SManish Tomar 
3113513f269SManish Tomar 	/*
3123513f269SManish Tomar 	 * Assert PCSn signals between transfers
3133513f269SManish Tomar 	 * select which CTAR register and slave to be used for TX
3143513f269SManish Tomar 	 * CTAS selects which CTAR to be used, here we are using CTAR0
3153513f269SManish Tomar 	 * PCS (peripheral chip select) is selecting the slave.
3163513f269SManish Tomar 	 */
3173513f269SManish Tomar 	ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs);
3183513f269SManish Tomar 	if (data->slave_mode & SPI_CONT)
3193513f269SManish Tomar 		ctrl |= DSPI_TFR_CONT;
3203513f269SManish Tomar 
3213513f269SManish Tomar 	if (data->slave_data_size_bits != 16) {
3223513f269SManish Tomar 		EMSG("data_size_bits should be 16, not %u",
3233513f269SManish Tomar 		     data->slave_data_size_bits);
3243513f269SManish Tomar 		return SPI_ERR_CFG;
3253513f269SManish Tomar 	}
3263513f269SManish Tomar 
3273513f269SManish Tomar 	while (num_pkts) {
3283513f269SManish Tomar 		if (wdata && rdata) {
3293513f269SManish Tomar 			dspi_tx(data, ctrl, *spi_wr++);
3303513f269SManish Tomar 			*spi_rd++ = dspi_rx(data);
3313513f269SManish Tomar 		} else if (wdata) {
3323513f269SManish Tomar 			dspi_tx(data, ctrl, *spi_wr++);
3333513f269SManish Tomar 			dspi_rx(data);
3343513f269SManish Tomar 		} else if (rdata) {
3353513f269SManish Tomar 			dspi_tx(data, ctrl, DSPI_IDLE_DATA);
3363513f269SManish Tomar 			*spi_rd++ = dspi_rx(data);
3373513f269SManish Tomar 		}
3383513f269SManish Tomar 		num_pkts = num_pkts - 1;
3393513f269SManish Tomar 	}
3403513f269SManish Tomar 
3413513f269SManish Tomar 	return SPI_OK;
3423513f269SManish Tomar }
3433513f269SManish Tomar 
3443513f269SManish Tomar /*
3453513f269SManish Tomar  * Statrt DSPI module
3463513f269SManish Tomar  * chip:	spi_chip instance
3473513f269SManish Tomar  */
3483513f269SManish Tomar static void ls_dspi_start(struct spi_chip *chip)
3493513f269SManish Tomar {
3503513f269SManish Tomar 	struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
3513513f269SManish Tomar 						  chip);
3523513f269SManish Tomar 
3533513f269SManish Tomar 	DMSG("Start DSPI Module");
3543513f269SManish Tomar 	io_clrbits32(data->base + DSPI_MCR, DSPI_MCR_HALT);
3553513f269SManish Tomar }
3563513f269SManish Tomar 
3573513f269SManish Tomar /*
3583513f269SManish Tomar  * Stop DSPI module
3593513f269SManish Tomar  * chip:	spi_chip instance
3603513f269SManish Tomar  */
3613513f269SManish Tomar static void ls_dspi_end(struct spi_chip *chip)
3623513f269SManish Tomar {
3633513f269SManish Tomar 	struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
3643513f269SManish Tomar 						  chip);
3653513f269SManish Tomar 
3663513f269SManish Tomar 	/* De-assert PCSn if in CONT mode */
3673513f269SManish Tomar 	if (data->slave_mode & SPI_CONT) {
3683513f269SManish Tomar 		unsigned int cs = data->slave_cs;
3693513f269SManish Tomar 		unsigned int ctrl = DSPI_TFR_CTAS(data->ctar_sel) |
3703513f269SManish Tomar 				    DSPI_TFR_PCS(cs);
3713513f269SManish Tomar 
3723513f269SManish Tomar 		/* Dummy read to deassert */
3733513f269SManish Tomar 		dspi_tx(data, ctrl, DSPI_IDLE_DATA);
3743513f269SManish Tomar 		dspi_rx(data);
3753513f269SManish Tomar 	}
3763513f269SManish Tomar 
3773513f269SManish Tomar 	DMSG("Stop DSPI Module");
3783513f269SManish Tomar 	io_setbits32(data->base + DSPI_MCR, DSPI_MCR_HALT);
3793513f269SManish Tomar }
3803513f269SManish Tomar 
3813513f269SManish Tomar /*
3823513f269SManish Tomar  * Clear RX and TX FIFO
3833513f269SManish Tomar  * dspi_data:   DSPI controller chip instance
3843513f269SManish Tomar  */
3853513f269SManish Tomar void dspi_flush_fifo(struct ls_dspi_data *dspi_data)
3863513f269SManish Tomar {
3873513f269SManish Tomar 	unsigned int mcr_val = 0;
3883513f269SManish Tomar 
3893513f269SManish Tomar 	mcr_val = io_read32(dspi_data->base + DSPI_MCR);
3903513f269SManish Tomar 	/* flush RX and TX FIFO */
3913513f269SManish Tomar 	mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF);
3923513f269SManish Tomar 
3933513f269SManish Tomar 	io_write32(dspi_data->base + DSPI_MCR, mcr_val);
3943513f269SManish Tomar }
3953513f269SManish Tomar 
3963513f269SManish Tomar /*
3973513f269SManish Tomar  * Configure active state of slave
3983513f269SManish Tomar  * dspi_data:   DSPI controller chip instance
3993513f269SManish Tomar  * cs:		chip select value of slave
4003513f269SManish Tomar  * state:	slave mode
4013513f269SManish Tomar  */
4023513f269SManish Tomar static void dspi_set_cs_active_state(struct ls_dspi_data *dspi_data,
4033513f269SManish Tomar 				     unsigned int cs, unsigned int state)
4043513f269SManish Tomar {
4053513f269SManish Tomar 	DMSG("Set CS active state cs=%d state=%d", cs, state);
4063513f269SManish Tomar 
4073513f269SManish Tomar 	if (state & SPI_CS_HIGH)
4083513f269SManish Tomar 		/* CSx inactive state is low */
4093513f269SManish Tomar 		io_clrbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs));
4103513f269SManish Tomar 	else
4113513f269SManish Tomar 		/* CSx inactive state is high */
4123513f269SManish Tomar 		io_setbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs));
4133513f269SManish Tomar }
4143513f269SManish Tomar 
4153513f269SManish Tomar /*
4163513f269SManish Tomar  * Configure transfer state of slave
4173513f269SManish Tomar  * dspi_data:   DSPI controller chip instance
4183513f269SManish Tomar  * state:	slave mode
4193513f269SManish Tomar  */
4203513f269SManish Tomar static void dspi_set_transfer_state(struct ls_dspi_data *dspi_data,
4213513f269SManish Tomar 				    unsigned int state)
4223513f269SManish Tomar {
4233513f269SManish Tomar 	unsigned int bus_setup = 0;
4243513f269SManish Tomar 
4253513f269SManish Tomar 	DMSG("Set transfer state=%d bits=%d", state,
4263513f269SManish Tomar 	     dspi_data->slave_data_size_bits);
4273513f269SManish Tomar 
4283513f269SManish Tomar 	bus_setup = io_read32(dspi_data->base + DSPI_CTAR0);
4293513f269SManish Tomar 	bus_setup &= ~DSPI_CTAR_SET_MODE_MASK;
4303513f269SManish Tomar 	bus_setup |= dspi_data->ctar_val;
4313513f269SManish Tomar 	bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE);
4323513f269SManish Tomar 
4333513f269SManish Tomar 	if (state & SPI_CPOL)
4343513f269SManish Tomar 		bus_setup |= DSPI_CTAR_CPOL;
4353513f269SManish Tomar 	if (state & SPI_CPHA)
4363513f269SManish Tomar 		bus_setup |= DSPI_CTAR_CPHA;
4373513f269SManish Tomar 	if (state & SPI_LSB_FIRST)
4383513f269SManish Tomar 		bus_setup |= DSPI_CTAR_LSBFE;
4393513f269SManish Tomar 
4403513f269SManish Tomar 	if (dspi_data->slave_data_size_bits == 8)
4413513f269SManish Tomar 		bus_setup |= DSPI_CTAR_FMSZ(7);
4423513f269SManish Tomar 	else if (dspi_data->slave_data_size_bits == 16)
4433513f269SManish Tomar 		bus_setup |= DSPI_CTAR_FMSZ(15);
4443513f269SManish Tomar 
4453513f269SManish Tomar 	if (dspi_data->ctar_sel == 0)
4463513f269SManish Tomar 		io_write32(dspi_data->base + DSPI_CTAR0, bus_setup);
4473513f269SManish Tomar 	else
4483513f269SManish Tomar 		io_write32(dspi_data->base + DSPI_CTAR1, bus_setup);
4493513f269SManish Tomar }
4503513f269SManish Tomar 
4513513f269SManish Tomar /*
4523513f269SManish Tomar  * Configure speed of slave
4533513f269SManish Tomar  * dspi_data:   DSPI controller chip instance
4543513f269SManish Tomar  * speed_max_hz:        maximum speed for slave
4553513f269SManish Tomar  */
4563513f269SManish Tomar static void dspi_set_speed(struct ls_dspi_data *dspi_data,
4573513f269SManish Tomar 			   unsigned int speed_max_hz)
4583513f269SManish Tomar {
4593513f269SManish Tomar 	dspi_setup_speed(dspi_data, speed_max_hz);
4603513f269SManish Tomar }
4613513f269SManish Tomar 
4623513f269SManish Tomar /*
4633513f269SManish Tomar  * Configure slave for DSPI controller
4643513f269SManish Tomar  * dspi_data:		DSPI controller chip instance
4653513f269SManish Tomar  * cs:			chip select value of slave
4663513f269SManish Tomar  * speed_max_hz:	maximum speed of slave
4673513f269SManish Tomar  * state:		slave mode
4683513f269SManish Tomar  */
4693513f269SManish Tomar static void dspi_config_slave_state(struct ls_dspi_data *dspi_data,
4703513f269SManish Tomar 				    unsigned int cs, unsigned int speed_max_hz,
4713513f269SManish Tomar 				    unsigned int state)
4723513f269SManish Tomar {
4733513f269SManish Tomar 	unsigned int sr_val = 0;
4743513f269SManish Tomar 
4753513f269SManish Tomar 	/* configure speed */
4763513f269SManish Tomar 	dspi_set_speed(dspi_data, speed_max_hz);
4773513f269SManish Tomar 
4783513f269SManish Tomar 	/* configure transfer state */
4793513f269SManish Tomar 	dspi_set_transfer_state(dspi_data, state);
4803513f269SManish Tomar 
4813513f269SManish Tomar 	/* configure active state of CSX */
4823513f269SManish Tomar 	dspi_set_cs_active_state(dspi_data, cs, state);
4833513f269SManish Tomar 
4843513f269SManish Tomar 	/* clear FIFO */
4853513f269SManish Tomar 	dspi_flush_fifo(dspi_data);
4863513f269SManish Tomar 
4873513f269SManish Tomar 	/* check module TX and RX status */
4883513f269SManish Tomar 	sr_val = io_read32(dspi_data->base + DSPI_SR);
4893513f269SManish Tomar 	if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS)
4903513f269SManish Tomar 		EMSG("DSPI RX/TX not ready");
4913513f269SManish Tomar }
4923513f269SManish Tomar 
4933513f269SManish Tomar /*
4943513f269SManish Tomar  * Configure master for DSPI controller
4953513f269SManish Tomar  * dspi_data: DSPI controller chip instance
4963513f269SManish Tomar  * mcr_val: value of master configuration register
4973513f269SManish Tomar  */
4983513f269SManish Tomar static void dspi_set_master_state(struct ls_dspi_data *dspi_data,
4993513f269SManish Tomar 				  unsigned int mcr_val)
5003513f269SManish Tomar {
5013513f269SManish Tomar 	DMSG("Set master state val=0x%x", mcr_val);
5023513f269SManish Tomar 	io_write32(dspi_data->base + DSPI_MCR, mcr_val);
5033513f269SManish Tomar }
5043513f269SManish Tomar 
5053513f269SManish Tomar /*
5063513f269SManish Tomar  * Configure DSPI controller
5073513f269SManish Tomar  * chip: spi_chip instance
5083513f269SManish Tomar  */
5093513f269SManish Tomar static void ls_dspi_configure(struct spi_chip *chip)
5103513f269SManish Tomar {
5113513f269SManish Tomar 	struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data,
5123513f269SManish Tomar 						  chip);
5133513f269SManish Tomar 	unsigned int mcr_cfg_val = 0;
5143513f269SManish Tomar 
5153513f269SManish Tomar 	mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK | DSPI_MCR_CRXF |
5163513f269SManish Tomar 		      DSPI_MCR_CTXF;
5173513f269SManish Tomar 
5183513f269SManish Tomar 	/* Configure Master */
5193513f269SManish Tomar 	dspi_set_master_state(data, mcr_cfg_val);
5203513f269SManish Tomar 
5213513f269SManish Tomar 	/* Configure DSPI slave */
5223513f269SManish Tomar 	dspi_config_slave_state(data, data->slave_cs, data->slave_speed_max_hz,
5233513f269SManish Tomar 				data->slave_mode);
5243513f269SManish Tomar }
5253513f269SManish Tomar 
5263513f269SManish Tomar /*
5273513f269SManish Tomar  * Extract information for DSPI Controller from the DTB
5283513f269SManish Tomar  * dspi_data: DSPI controller chip instance
5293513f269SManish Tomar  */
5303513f269SManish Tomar static TEE_Result get_info_from_device_tree(struct ls_dspi_data *dspi_data)
5313513f269SManish Tomar {
5323513f269SManish Tomar 	const fdt32_t *bus_num = NULL;
5333513f269SManish Tomar 	const fdt32_t *chip_select_num = NULL;
5343513f269SManish Tomar 	size_t size = 0;
5353513f269SManish Tomar 	int node = 0;
5363513f269SManish Tomar 	vaddr_t ctrl_base = 0;
5373513f269SManish Tomar 	void *fdt = NULL;
5383513f269SManish Tomar 
5393513f269SManish Tomar 	/*
5403513f269SManish Tomar 	 * First get the DSPI Controller base address from the DTB
5413513f269SManish Tomar 	 * if DTB present and if the DSPI Controller defined in it.
5423513f269SManish Tomar 	 */
5433513f269SManish Tomar 	fdt = get_dt();
5443513f269SManish Tomar 	if (!fdt) {
5453513f269SManish Tomar 		EMSG("Unable to get DTB, DSPI init failed\n");
5463513f269SManish Tomar 		return TEE_ERROR_ITEM_NOT_FOUND;
5473513f269SManish Tomar 	}
5483513f269SManish Tomar 
5493513f269SManish Tomar 	node = 0;
5503513f269SManish Tomar 	while (node != -FDT_ERR_NOTFOUND) {
5513513f269SManish Tomar 		node = fdt_node_offset_by_compatible(fdt, node,
5523513f269SManish Tomar 						     "fsl,lx2160a-dspi");
553*f354a5d8SGatien Chevallier 		if (!(fdt_get_status(fdt, node) & DT_STATUS_OK_SEC))
5543513f269SManish Tomar 			continue;
5553513f269SManish Tomar 
5563513f269SManish Tomar 		bus_num = fdt_getprop(fdt, node, "bus-num", NULL);
5573513f269SManish Tomar 		if (bus_num && dspi_data->slave_bus ==
5583513f269SManish Tomar 			(unsigned int)fdt32_to_cpu(*bus_num)) {
559a5d5bbc8SVesa Jääskeläinen 			if (dt_map_dev(fdt, node, &ctrl_base, &size,
560a5d5bbc8SVesa Jääskeläinen 				       DT_MAP_AUTO) < 0) {
5613513f269SManish Tomar 				EMSG("Unable to get virtual address");
5623513f269SManish Tomar 				return TEE_ERROR_GENERIC;
5633513f269SManish Tomar 			}
5643513f269SManish Tomar 			break;
5653513f269SManish Tomar 		}
5663513f269SManish Tomar 	}
5673513f269SManish Tomar 
5683513f269SManish Tomar 	dspi_data->base = ctrl_base;
5693513f269SManish Tomar 	dspi_data->bus_clk_hz = DSPI_CLK;
5703513f269SManish Tomar 
5713513f269SManish Tomar 	chip_select_num = fdt_getprop(fdt, node, "spi-num-chipselects", NULL);
5723513f269SManish Tomar 	if (chip_select_num)
5733513f269SManish Tomar 		dspi_data->num_chipselect = (int)fdt32_to_cpu(*chip_select_num);
5743513f269SManish Tomar 	else
5753513f269SManish Tomar 		return TEE_ERROR_ITEM_NOT_FOUND;
5763513f269SManish Tomar 
5773513f269SManish Tomar 	dspi_data->speed_hz = DSPI_DEFAULT_SCK_FREQ;
5783513f269SManish Tomar 
5793513f269SManish Tomar 	return TEE_SUCCESS;
5803513f269SManish Tomar }
5813513f269SManish Tomar 
5823513f269SManish Tomar static const struct spi_ops ls_dspi_ops = {
5833513f269SManish Tomar 	.configure = ls_dspi_configure,
5843513f269SManish Tomar 	.start = ls_dspi_start,
5853513f269SManish Tomar 	.txrx8 = ls_dspi_txrx8,
5863513f269SManish Tomar 	.txrx16 = ls_dspi_txrx16,
5873513f269SManish Tomar 	.end = ls_dspi_end,
5883513f269SManish Tomar };
5893513f269SManish Tomar DECLARE_KEEP_PAGER(ls_dspi_ops);
5903513f269SManish Tomar 
5913513f269SManish Tomar TEE_Result ls_dspi_init(struct ls_dspi_data *dspi_data)
5923513f269SManish Tomar {
5933513f269SManish Tomar 	TEE_Result status = TEE_ERROR_GENERIC;
5943513f269SManish Tomar 
5953513f269SManish Tomar 	/*
5963513f269SManish Tomar 	 * First get the DSPI Controller base address from the DTB,
5973513f269SManish Tomar 	 * if DTB present and if the DSPI Controller defined in it.
5983513f269SManish Tomar 	 */
5993513f269SManish Tomar 	if (dspi_data)
6003513f269SManish Tomar 		status = get_info_from_device_tree(dspi_data);
6013513f269SManish Tomar 	if (status == TEE_SUCCESS)
6023513f269SManish Tomar 		/* generic DSPI chip handle */
6033513f269SManish Tomar 		dspi_data->chip.ops = &ls_dspi_ops;
6043513f269SManish Tomar 	else
6053513f269SManish Tomar 		EMSG("Unable to get info from device tree");
6063513f269SManish Tomar 
6073513f269SManish Tomar 	return status;
6083513f269SManish Tomar }
609