1273feafeSMingkai Hu /* 2273feafeSMingkai Hu * eSPI controller driver. 3273feafeSMingkai Hu * 4273feafeSMingkai Hu * Copyright 2010-2011 Freescale Semiconductor, Inc. 5273feafeSMingkai Hu * Author: Mingkai Hu (Mingkai.hu@freescale.com) 6273feafeSMingkai Hu * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 8273feafeSMingkai Hu */ 9273feafeSMingkai Hu 10273feafeSMingkai Hu #include <common.h> 11273feafeSMingkai Hu 12273feafeSMingkai Hu #include <malloc.h> 13273feafeSMingkai Hu #include <spi.h> 14273feafeSMingkai Hu #include <asm/immap_85xx.h> 15273feafeSMingkai Hu 16273feafeSMingkai Hu struct fsl_spi_slave { 17273feafeSMingkai Hu struct spi_slave slave; 18afb90706SHou Zhiqiang ccsr_espi_t *espi; 19273feafeSMingkai Hu unsigned int div16; 20273feafeSMingkai Hu unsigned int pm; 21afb90706SHou Zhiqiang int tx_timeout; 22273feafeSMingkai Hu unsigned int mode; 23273feafeSMingkai Hu size_t cmd_len; 24273feafeSMingkai Hu u8 cmd_buf[16]; 25273feafeSMingkai Hu size_t data_len; 26273feafeSMingkai Hu unsigned int max_transfer_length; 27273feafeSMingkai Hu }; 28273feafeSMingkai Hu 29273feafeSMingkai Hu #define to_fsl_spi_slave(s) container_of(s, struct fsl_spi_slave, slave) 30afb90706SHou Zhiqiang #define US_PER_SECOND 1000000UL 31273feafeSMingkai Hu 32273feafeSMingkai Hu #define ESPI_MAX_CS_NUM 4 33afb90706SHou Zhiqiang #define ESPI_FIFO_WIDTH_BIT 32 34273feafeSMingkai Hu 35*29e6abd9SJagan Teki #define ESPI_EV_RNE BIT(9) 36*29e6abd9SJagan Teki #define ESPI_EV_TNF BIT(8) 37*29e6abd9SJagan Teki #define ESPI_EV_DON BIT(14) 38*29e6abd9SJagan Teki #define ESPI_EV_TXE BIT(15) 39afb90706SHou Zhiqiang #define ESPI_EV_RFCNT_SHIFT 24 40afb90706SHou Zhiqiang #define ESPI_EV_RFCNT_MASK (0x3f << ESPI_EV_RFCNT_SHIFT) 41273feafeSMingkai Hu 42*29e6abd9SJagan Teki #define ESPI_MODE_EN BIT(31) /* Enable interface */ 43273feafeSMingkai Hu #define ESPI_MODE_TXTHR(x) ((x) << 8) /* Tx FIFO threshold */ 44273feafeSMingkai Hu #define ESPI_MODE_RXTHR(x) ((x) << 0) /* Rx FIFO threshold */ 45273feafeSMingkai Hu 46273feafeSMingkai Hu #define ESPI_COM_CS(x) ((x) << 30) 47273feafeSMingkai Hu #define ESPI_COM_TRANLEN(x) ((x) << 0) 48273feafeSMingkai Hu 49*29e6abd9SJagan Teki #define ESPI_CSMODE_CI_INACTIVEHIGH BIT(31) 50*29e6abd9SJagan Teki #define ESPI_CSMODE_CP_BEGIN_EDGCLK BIT(30) 51*29e6abd9SJagan Teki #define ESPI_CSMODE_REV_MSB_FIRST BIT(29) 52*29e6abd9SJagan Teki #define ESPI_CSMODE_DIV16 BIT(28) 53273feafeSMingkai Hu #define ESPI_CSMODE_PM(x) ((x) << 24) 54*29e6abd9SJagan Teki #define ESPI_CSMODE_POL_ASSERTED_LOW BIT(20) 55273feafeSMingkai Hu #define ESPI_CSMODE_LEN(x) ((x) << 16) 56273feafeSMingkai Hu #define ESPI_CSMODE_CSBEF(x) ((x) << 12) 57273feafeSMingkai Hu #define ESPI_CSMODE_CSAFT(x) ((x) << 8) 58273feafeSMingkai Hu #define ESPI_CSMODE_CSCG(x) ((x) << 3) 59273feafeSMingkai Hu 60273feafeSMingkai Hu #define ESPI_CSMODE_INIT_VAL (ESPI_CSMODE_POL_ASSERTED_LOW | \ 61273feafeSMingkai Hu ESPI_CSMODE_CSBEF(0) | ESPI_CSMODE_CSAFT(0) | \ 62273feafeSMingkai Hu ESPI_CSMODE_CSCG(1)) 63273feafeSMingkai Hu 64273feafeSMingkai Hu #define ESPI_MAX_DATA_TRANSFER_LEN 0xFFF0 65273feafeSMingkai Hu 66273feafeSMingkai Hu struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 67273feafeSMingkai Hu unsigned int max_hz, unsigned int mode) 68273feafeSMingkai Hu { 69273feafeSMingkai Hu struct fsl_spi_slave *fsl; 70273feafeSMingkai Hu sys_info_t sysinfo; 71273feafeSMingkai Hu unsigned long spibrg = 0; 72afb90706SHou Zhiqiang unsigned long spi_freq = 0; 73273feafeSMingkai Hu unsigned char pm = 0; 74273feafeSMingkai Hu 75273feafeSMingkai Hu if (!spi_cs_is_valid(bus, cs)) 76273feafeSMingkai Hu return NULL; 77273feafeSMingkai Hu 78d3504feeSSimon Glass fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs); 79273feafeSMingkai Hu if (!fsl) 80273feafeSMingkai Hu return NULL; 81273feafeSMingkai Hu 82afb90706SHou Zhiqiang fsl->espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR); 83273feafeSMingkai Hu fsl->mode = mode; 84273feafeSMingkai Hu fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; 85273feafeSMingkai Hu 86273feafeSMingkai Hu /* Set eSPI BRG clock source */ 87273feafeSMingkai Hu get_sys_info(&sysinfo); 88997399faSPrabhakar Kushwaha spibrg = sysinfo.freq_systembus / 2; 89273feafeSMingkai Hu fsl->div16 = 0; 90273feafeSMingkai Hu if ((spibrg / max_hz) > 32) { 91273feafeSMingkai Hu fsl->div16 = ESPI_CSMODE_DIV16; 92273feafeSMingkai Hu pm = spibrg / (max_hz * 16 * 2); 93273feafeSMingkai Hu if (pm > 16) { 94273feafeSMingkai Hu pm = 16; 955cc08a17SMarek Vasut debug("Requested speed is too low: %d Hz, %ld Hz " 965cc08a17SMarek Vasut "is used.\n", max_hz, spibrg / (32 * 16)); 97273feafeSMingkai Hu } 98273feafeSMingkai Hu } else 99273feafeSMingkai Hu pm = spibrg / (max_hz * 2); 100273feafeSMingkai Hu if (pm) 101273feafeSMingkai Hu pm--; 102273feafeSMingkai Hu fsl->pm = pm; 103273feafeSMingkai Hu 104afb90706SHou Zhiqiang if (fsl->div16) 105afb90706SHou Zhiqiang spi_freq = spibrg / ((pm + 1) * 2 * 16); 106afb90706SHou Zhiqiang else 107afb90706SHou Zhiqiang spi_freq = spibrg / ((pm + 1) * 2); 108afb90706SHou Zhiqiang 109afb90706SHou Zhiqiang /* set tx_timeout to 10 times of one espi FIFO entry go out */ 110afb90706SHou Zhiqiang fsl->tx_timeout = DIV_ROUND_UP((US_PER_SECOND * ESPI_FIFO_WIDTH_BIT 111afb90706SHou Zhiqiang * 10), spi_freq); 112afb90706SHou Zhiqiang 113273feafeSMingkai Hu return &fsl->slave; 114273feafeSMingkai Hu } 115273feafeSMingkai Hu 116273feafeSMingkai Hu void spi_free_slave(struct spi_slave *slave) 117273feafeSMingkai Hu { 118273feafeSMingkai Hu struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); 119273feafeSMingkai Hu free(fsl); 120273feafeSMingkai Hu } 121273feafeSMingkai Hu 122273feafeSMingkai Hu void spi_init(void) 123273feafeSMingkai Hu { 124273feafeSMingkai Hu 125273feafeSMingkai Hu } 126273feafeSMingkai Hu 127273feafeSMingkai Hu int spi_claim_bus(struct spi_slave *slave) 128273feafeSMingkai Hu { 129273feafeSMingkai Hu struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); 130afb90706SHou Zhiqiang ccsr_espi_t *espi = fsl->espi; 131273feafeSMingkai Hu unsigned char pm = fsl->pm; 132273feafeSMingkai Hu unsigned int cs = slave->cs; 133273feafeSMingkai Hu unsigned int mode = fsl->mode; 134273feafeSMingkai Hu unsigned int div16 = fsl->div16; 135273feafeSMingkai Hu int i; 136273feafeSMingkai Hu 137273feafeSMingkai Hu debug("%s: bus:%i cs:%i\n", __func__, slave->bus, cs); 138273feafeSMingkai Hu 139273feafeSMingkai Hu /* Enable eSPI interface */ 140273feafeSMingkai Hu out_be32(&espi->mode, ESPI_MODE_RXTHR(3) 141273feafeSMingkai Hu | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN); 142273feafeSMingkai Hu 143273feafeSMingkai Hu out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */ 144273feafeSMingkai Hu out_be32(&espi->mask, 0x00000000); /* Mask all eSPI interrupts */ 145273feafeSMingkai Hu 146273feafeSMingkai Hu /* Init CS mode interface */ 147273feafeSMingkai Hu for (i = 0; i < ESPI_MAX_CS_NUM; i++) 148273feafeSMingkai Hu out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL); 149273feafeSMingkai Hu 150273feafeSMingkai Hu out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) & 151273feafeSMingkai Hu ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16 152273feafeSMingkai Hu | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK 153273feafeSMingkai Hu | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF))); 154273feafeSMingkai Hu 155273feafeSMingkai Hu /* Set eSPI BRG clock source */ 156273feafeSMingkai Hu out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) 157273feafeSMingkai Hu | ESPI_CSMODE_PM(pm) | div16); 158273feafeSMingkai Hu 159273feafeSMingkai Hu /* Set eSPI mode */ 160273feafeSMingkai Hu if (mode & SPI_CPHA) 161273feafeSMingkai Hu out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) 162273feafeSMingkai Hu | ESPI_CSMODE_CP_BEGIN_EDGCLK); 163273feafeSMingkai Hu if (mode & SPI_CPOL) 164273feafeSMingkai Hu out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) 165273feafeSMingkai Hu | ESPI_CSMODE_CI_INACTIVEHIGH); 166273feafeSMingkai Hu 167273feafeSMingkai Hu /* Character bit order: msb first */ 168273feafeSMingkai Hu out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) 169273feafeSMingkai Hu | ESPI_CSMODE_REV_MSB_FIRST); 170273feafeSMingkai Hu 171273feafeSMingkai Hu /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */ 172273feafeSMingkai Hu out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) 173273feafeSMingkai Hu | ESPI_CSMODE_LEN(7)); 174273feafeSMingkai Hu 175273feafeSMingkai Hu return 0; 176273feafeSMingkai Hu } 177273feafeSMingkai Hu 178273feafeSMingkai Hu void spi_release_bus(struct spi_slave *slave) 179273feafeSMingkai Hu { 180273feafeSMingkai Hu 181273feafeSMingkai Hu } 182273feafeSMingkai Hu 183afb90706SHou Zhiqiang static void fsl_espi_tx(struct fsl_spi_slave *fsl, const void *dout) 184afb90706SHou Zhiqiang { 185afb90706SHou Zhiqiang ccsr_espi_t *espi = fsl->espi; 186afb90706SHou Zhiqiang unsigned int tmpdout, event; 187afb90706SHou Zhiqiang int tmp_tx_timeout; 188afb90706SHou Zhiqiang 189afb90706SHou Zhiqiang if (dout) 190afb90706SHou Zhiqiang tmpdout = *(u32 *)dout; 191afb90706SHou Zhiqiang else 192afb90706SHou Zhiqiang tmpdout = 0; 193afb90706SHou Zhiqiang 194afb90706SHou Zhiqiang out_be32(&espi->tx, tmpdout); 195afb90706SHou Zhiqiang out_be32(&espi->event, ESPI_EV_TNF); 196afb90706SHou Zhiqiang debug("***spi_xfer:...%08x written\n", tmpdout); 197afb90706SHou Zhiqiang 198afb90706SHou Zhiqiang tmp_tx_timeout = fsl->tx_timeout; 199afb90706SHou Zhiqiang /* Wait for eSPI transmit to go out */ 200afb90706SHou Zhiqiang while (tmp_tx_timeout--) { 201afb90706SHou Zhiqiang event = in_be32(&espi->event); 202afb90706SHou Zhiqiang if (event & ESPI_EV_DON || event & ESPI_EV_TXE) { 203afb90706SHou Zhiqiang out_be32(&espi->event, ESPI_EV_TXE); 204afb90706SHou Zhiqiang break; 205afb90706SHou Zhiqiang } 206afb90706SHou Zhiqiang udelay(1); 207afb90706SHou Zhiqiang } 208afb90706SHou Zhiqiang 209afb90706SHou Zhiqiang if (tmp_tx_timeout < 0) 210afb90706SHou Zhiqiang debug("***spi_xfer:...Tx timeout! event = %08x\n", event); 211afb90706SHou Zhiqiang } 212afb90706SHou Zhiqiang 213afb90706SHou Zhiqiang static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, unsigned int bytes) 214afb90706SHou Zhiqiang { 215afb90706SHou Zhiqiang ccsr_espi_t *espi = fsl->espi; 216afb90706SHou Zhiqiang unsigned int tmpdin, rx_times; 217afb90706SHou Zhiqiang unsigned char *buf, *p_cursor; 218afb90706SHou Zhiqiang 219afb90706SHou Zhiqiang if (bytes <= 0) 220afb90706SHou Zhiqiang return 0; 221afb90706SHou Zhiqiang 222afb90706SHou Zhiqiang rx_times = DIV_ROUND_UP(bytes, 4); 223afb90706SHou Zhiqiang buf = (unsigned char *)malloc(4 * rx_times); 224afb90706SHou Zhiqiang if (!buf) { 225afb90706SHou Zhiqiang debug("SF: Failed to malloc memory.\n"); 226afb90706SHou Zhiqiang return -1; 227afb90706SHou Zhiqiang } 228afb90706SHou Zhiqiang p_cursor = buf; 229afb90706SHou Zhiqiang while (rx_times--) { 230afb90706SHou Zhiqiang tmpdin = in_be32(&espi->rx); 231afb90706SHou Zhiqiang debug("***spi_xfer:...%08x readed\n", tmpdin); 232afb90706SHou Zhiqiang *(u32 *)p_cursor = tmpdin; 233afb90706SHou Zhiqiang p_cursor += 4; 234afb90706SHou Zhiqiang } 235afb90706SHou Zhiqiang 236afb90706SHou Zhiqiang if (din) 237afb90706SHou Zhiqiang memcpy(din, buf, bytes); 238afb90706SHou Zhiqiang 239afb90706SHou Zhiqiang free(buf); 240afb90706SHou Zhiqiang out_be32(&espi->event, ESPI_EV_RNE); 241afb90706SHou Zhiqiang 242afb90706SHou Zhiqiang return bytes; 243afb90706SHou Zhiqiang } 244afb90706SHou Zhiqiang 245273feafeSMingkai Hu int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, 246273feafeSMingkai Hu void *data_in, unsigned long flags) 247273feafeSMingkai Hu { 248273feafeSMingkai Hu struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); 249afb90706SHou Zhiqiang ccsr_espi_t *espi = fsl->espi; 250afb90706SHou Zhiqiang unsigned int event, rx_bytes; 251273feafeSMingkai Hu const void *dout = NULL; 252273feafeSMingkai Hu void *din = NULL; 253273feafeSMingkai Hu int len = 0; 254273feafeSMingkai Hu int num_blks, num_chunks, max_tran_len, tran_len; 255273feafeSMingkai Hu int num_bytes; 256273feafeSMingkai Hu unsigned char *buffer = NULL; 257273feafeSMingkai Hu size_t buf_len; 258273feafeSMingkai Hu u8 *cmd_buf = fsl->cmd_buf; 259273feafeSMingkai Hu size_t cmd_len = fsl->cmd_len; 260273feafeSMingkai Hu size_t data_len = bitlen / 8; 261273feafeSMingkai Hu size_t rx_offset = 0; 262afb90706SHou Zhiqiang int rf_cnt; 263273feafeSMingkai Hu 264273feafeSMingkai Hu max_tran_len = fsl->max_transfer_length; 265273feafeSMingkai Hu switch (flags) { 266273feafeSMingkai Hu case SPI_XFER_BEGIN: 267273feafeSMingkai Hu cmd_len = fsl->cmd_len = data_len; 268273feafeSMingkai Hu memcpy(cmd_buf, data_out, cmd_len); 269273feafeSMingkai Hu return 0; 270273feafeSMingkai Hu case 0: 271273feafeSMingkai Hu case SPI_XFER_END: 272273feafeSMingkai Hu if (bitlen == 0) { 273273feafeSMingkai Hu spi_cs_deactivate(slave); 274273feafeSMingkai Hu return 0; 275273feafeSMingkai Hu } 276b4141195SMasahiro Yamada buf_len = 2 * cmd_len + min(data_len, (size_t)max_tran_len); 277273feafeSMingkai Hu len = cmd_len + data_len; 278273feafeSMingkai Hu rx_offset = cmd_len; 279273feafeSMingkai Hu buffer = (unsigned char *)malloc(buf_len); 280273feafeSMingkai Hu if (!buffer) { 281273feafeSMingkai Hu debug("SF: Failed to malloc memory.\n"); 282273feafeSMingkai Hu return 1; 283273feafeSMingkai Hu } 284273feafeSMingkai Hu memcpy(buffer, cmd_buf, cmd_len); 285273feafeSMingkai Hu if (data_in == NULL) 286273feafeSMingkai Hu memcpy(buffer + cmd_len, data_out, data_len); 287273feafeSMingkai Hu break; 288273feafeSMingkai Hu case SPI_XFER_BEGIN | SPI_XFER_END: 289273feafeSMingkai Hu len = data_len; 290273feafeSMingkai Hu buffer = (unsigned char *)malloc(len * 2); 291273feafeSMingkai Hu if (!buffer) { 292273feafeSMingkai Hu debug("SF: Failed to malloc memory.\n"); 293273feafeSMingkai Hu return 1; 294273feafeSMingkai Hu } 295273feafeSMingkai Hu memcpy(buffer, data_out, len); 296273feafeSMingkai Hu rx_offset = len; 297273feafeSMingkai Hu cmd_len = 0; 298273feafeSMingkai Hu break; 299273feafeSMingkai Hu } 300273feafeSMingkai Hu 301afb90706SHou Zhiqiang debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) len %u\n", 302afb90706SHou Zhiqiang *(uint *)data_out, data_out, *(uint *)data_in, data_in, len); 303273feafeSMingkai Hu 304a444aa7aSAxel Lin num_chunks = DIV_ROUND_UP(data_len, max_tran_len); 305273feafeSMingkai Hu while (num_chunks--) { 306273feafeSMingkai Hu if (data_in) 307273feafeSMingkai Hu din = buffer + rx_offset; 308273feafeSMingkai Hu dout = buffer; 309b4141195SMasahiro Yamada tran_len = min(data_len, (size_t)max_tran_len); 310a444aa7aSAxel Lin num_blks = DIV_ROUND_UP(tran_len + cmd_len, 4); 311273feafeSMingkai Hu num_bytes = (tran_len + cmd_len) % 4; 312273feafeSMingkai Hu fsl->data_len = tran_len + cmd_len; 313273feafeSMingkai Hu spi_cs_activate(slave); 314273feafeSMingkai Hu 315273feafeSMingkai Hu /* Clear all eSPI events */ 316273feafeSMingkai Hu out_be32(&espi->event , 0xffffffff); 317273feafeSMingkai Hu /* handle data in 32-bit chunks */ 318afb90706SHou Zhiqiang while (num_blks) { 319273feafeSMingkai Hu event = in_be32(&espi->event); 320273feafeSMingkai Hu if (event & ESPI_EV_TNF) { 321afb90706SHou Zhiqiang fsl_espi_tx(fsl, dout); 322273feafeSMingkai Hu /* Set up the next iteration */ 323273feafeSMingkai Hu if (len > 4) { 324273feafeSMingkai Hu len -= 4; 325273feafeSMingkai Hu dout += 4; 326273feafeSMingkai Hu } 327273feafeSMingkai Hu } 328273feafeSMingkai Hu 329273feafeSMingkai Hu event = in_be32(&espi->event); 330273feafeSMingkai Hu if (event & ESPI_EV_RNE) { 331afb90706SHou Zhiqiang rf_cnt = ((event & ESPI_EV_RFCNT_MASK) 332afb90706SHou Zhiqiang >> ESPI_EV_RFCNT_SHIFT); 333afb90706SHou Zhiqiang if (rf_cnt >= 4) 334afb90706SHou Zhiqiang rx_bytes = 4; 335afb90706SHou Zhiqiang else if (num_blks == 1 && rf_cnt == num_bytes) 336afb90706SHou Zhiqiang rx_bytes = num_bytes; 337afb90706SHou Zhiqiang else 338afb90706SHou Zhiqiang continue; 339afb90706SHou Zhiqiang if (fsl_espi_rx(fsl, din, rx_bytes) 340afb90706SHou Zhiqiang == rx_bytes) { 341afb90706SHou Zhiqiang num_blks--; 342afb90706SHou Zhiqiang if (din) 343afb90706SHou Zhiqiang din = (unsigned char *)din 344afb90706SHou Zhiqiang + rx_bytes; 345273feafeSMingkai Hu } 346273feafeSMingkai Hu } 347273feafeSMingkai Hu } 348273feafeSMingkai Hu if (data_in) { 349273feafeSMingkai Hu memcpy(data_in, buffer + 2 * cmd_len, tran_len); 350273feafeSMingkai Hu if (*buffer == 0x0b) { 351273feafeSMingkai Hu data_in += tran_len; 352273feafeSMingkai Hu data_len -= tran_len; 353273feafeSMingkai Hu *(int *)buffer += tran_len; 354273feafeSMingkai Hu } 355273feafeSMingkai Hu } 356273feafeSMingkai Hu spi_cs_deactivate(slave); 357273feafeSMingkai Hu } 358273feafeSMingkai Hu 359273feafeSMingkai Hu free(buffer); 360273feafeSMingkai Hu return 0; 361273feafeSMingkai Hu } 362273feafeSMingkai Hu 363273feafeSMingkai Hu int spi_cs_is_valid(unsigned int bus, unsigned int cs) 364273feafeSMingkai Hu { 365273feafeSMingkai Hu return bus == 0 && cs < ESPI_MAX_CS_NUM; 366273feafeSMingkai Hu } 367273feafeSMingkai Hu 368273feafeSMingkai Hu void spi_cs_activate(struct spi_slave *slave) 369273feafeSMingkai Hu { 370273feafeSMingkai Hu struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); 371afb90706SHou Zhiqiang ccsr_espi_t *espi = fsl->espi; 372273feafeSMingkai Hu unsigned int com = 0; 373273feafeSMingkai Hu size_t data_len = fsl->data_len; 374273feafeSMingkai Hu 375273feafeSMingkai Hu com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF)); 376273feafeSMingkai Hu com |= ESPI_COM_CS(slave->cs); 377273feafeSMingkai Hu com |= ESPI_COM_TRANLEN(data_len - 1); 378273feafeSMingkai Hu out_be32(&espi->com, com); 379273feafeSMingkai Hu } 380273feafeSMingkai Hu 381273feafeSMingkai Hu void spi_cs_deactivate(struct spi_slave *slave) 382273feafeSMingkai Hu { 383afb90706SHou Zhiqiang struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); 384afb90706SHou Zhiqiang ccsr_espi_t *espi = fsl->espi; 385273feafeSMingkai Hu 386273feafeSMingkai Hu /* clear the RXCNT and TXCNT */ 387273feafeSMingkai Hu out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN)); 388273feafeSMingkai Hu out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN); 389273feafeSMingkai Hu } 390