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"); 5533513f269SManish Tomar 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)) { 559*a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &ctrl_base, &size, 560*a5d5bbc8SVesa 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