uboot/drivers/spi/fsl_espi.c
<<
>>
Prefs
   1/*
   2 * eSPI controller driver.
   3 *
   4 * Copyright 2010-2011 Freescale Semiconductor, Inc.
   5 * Author: Mingkai Hu (Mingkai.hu@freescale.com)
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <common.h>
  11
  12#include <malloc.h>
  13#include <spi.h>
  14#include <asm/immap_85xx.h>
  15
  16struct fsl_spi_slave {
  17        struct spi_slave slave;
  18        ccsr_espi_t     *espi;
  19        unsigned int    div16;
  20        unsigned int    pm;
  21        int             tx_timeout;
  22        unsigned int    mode;
  23        size_t          cmd_len;
  24        u8              cmd_buf[16];
  25        size_t          data_len;
  26        unsigned int    max_transfer_length;
  27};
  28
  29#define to_fsl_spi_slave(s) container_of(s, struct fsl_spi_slave, slave)
  30#define US_PER_SECOND           1000000UL
  31
  32#define ESPI_MAX_CS_NUM         4
  33#define ESPI_FIFO_WIDTH_BIT     32
  34
  35#define ESPI_EV_RNE             BIT(9)
  36#define ESPI_EV_TNF             BIT(8)
  37#define ESPI_EV_DON             BIT(14)
  38#define ESPI_EV_TXE             BIT(15)
  39#define ESPI_EV_RFCNT_SHIFT     24
  40#define ESPI_EV_RFCNT_MASK      (0x3f << ESPI_EV_RFCNT_SHIFT)
  41
  42#define ESPI_MODE_EN            BIT(31) /* Enable interface */
  43#define ESPI_MODE_TXTHR(x)      ((x) << 8)      /* Tx FIFO threshold */
  44#define ESPI_MODE_RXTHR(x)      ((x) << 0)      /* Rx FIFO threshold */
  45
  46#define ESPI_COM_CS(x)          ((x) << 30)
  47#define ESPI_COM_TRANLEN(x)     ((x) << 0)
  48
  49#define ESPI_CSMODE_CI_INACTIVEHIGH     BIT(31)
  50#define ESPI_CSMODE_CP_BEGIN_EDGCLK     BIT(30)
  51#define ESPI_CSMODE_REV_MSB_FIRST       BIT(29)
  52#define ESPI_CSMODE_DIV16               BIT(28)
  53#define ESPI_CSMODE_PM(x)               ((x) << 24)
  54#define ESPI_CSMODE_POL_ASSERTED_LOW    BIT(20)
  55#define ESPI_CSMODE_LEN(x)              ((x) << 16)
  56#define ESPI_CSMODE_CSBEF(x)            ((x) << 12)
  57#define ESPI_CSMODE_CSAFT(x)            ((x) << 8)
  58#define ESPI_CSMODE_CSCG(x)             ((x) << 3)
  59
  60#define ESPI_CSMODE_INIT_VAL (ESPI_CSMODE_POL_ASSERTED_LOW | \
  61                ESPI_CSMODE_CSBEF(0) | ESPI_CSMODE_CSAFT(0) | \
  62                ESPI_CSMODE_CSCG(1))
  63
  64#define ESPI_MAX_DATA_TRANSFER_LEN 0xFFF0
  65
  66struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  67                unsigned int max_hz, unsigned int mode)
  68{
  69        struct fsl_spi_slave *fsl;
  70        sys_info_t sysinfo;
  71        unsigned long spibrg = 0;
  72        unsigned long spi_freq = 0;
  73        unsigned char pm = 0;
  74
  75        if (!spi_cs_is_valid(bus, cs))
  76                return NULL;
  77
  78        fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs);
  79        if (!fsl)
  80                return NULL;
  81
  82        fsl->espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR);
  83        fsl->mode = mode;
  84        fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN;
  85
  86        /* Set eSPI BRG clock source */
  87        get_sys_info(&sysinfo);
  88        spibrg = sysinfo.freq_systembus / 2;
  89        fsl->div16 = 0;
  90        if ((spibrg / max_hz) > 32) {
  91                fsl->div16 = ESPI_CSMODE_DIV16;
  92                pm = spibrg / (max_hz * 16 * 2);
  93                if (pm > 16) {
  94                        pm = 16;
  95                        debug("Requested speed is too low: %d Hz, %ld Hz "
  96                                "is used.\n", max_hz, spibrg / (32 * 16));
  97                }
  98        } else
  99                pm = spibrg / (max_hz * 2);
 100        if (pm)
 101                pm--;
 102        fsl->pm = pm;
 103
 104        if (fsl->div16)
 105                spi_freq = spibrg / ((pm + 1) * 2 * 16);
 106        else
 107                spi_freq = spibrg / ((pm + 1) * 2);
 108
 109        /* set tx_timeout to 10 times of one espi FIFO entry go out */
 110        fsl->tx_timeout = DIV_ROUND_UP((US_PER_SECOND * ESPI_FIFO_WIDTH_BIT
 111                                * 10), spi_freq);
 112
 113        return &fsl->slave;
 114}
 115
 116void spi_free_slave(struct spi_slave *slave)
 117{
 118        struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
 119        free(fsl);
 120}
 121
 122void spi_init(void)
 123{
 124
 125}
 126
 127int spi_claim_bus(struct spi_slave *slave)
 128{
 129        struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
 130        ccsr_espi_t *espi = fsl->espi;
 131        unsigned char pm = fsl->pm;
 132        unsigned int cs = slave->cs;
 133        unsigned int mode =  fsl->mode;
 134        unsigned int div16 = fsl->div16;
 135        int i;
 136
 137        debug("%s: bus:%i cs:%i\n", __func__, slave->bus, cs);
 138
 139        /* Enable eSPI interface */
 140        out_be32(&espi->mode, ESPI_MODE_RXTHR(3)
 141                        | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN);
 142
 143        out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */
 144        out_be32(&espi->mask, 0x00000000); /* Mask  all eSPI interrupts */
 145
 146        /* Init CS mode interface */
 147        for (i = 0; i < ESPI_MAX_CS_NUM; i++)
 148                out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL);
 149
 150        out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) &
 151                ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16
 152                | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK
 153                | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF)));
 154
 155        /* Set eSPI BRG clock source */
 156        out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
 157                | ESPI_CSMODE_PM(pm) | div16);
 158
 159        /* Set eSPI mode */
 160        if (mode & SPI_CPHA)
 161                out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
 162                        | ESPI_CSMODE_CP_BEGIN_EDGCLK);
 163        if (mode & SPI_CPOL)
 164                out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
 165                        | ESPI_CSMODE_CI_INACTIVEHIGH);
 166
 167        /* Character bit order: msb first */
 168        out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
 169                | ESPI_CSMODE_REV_MSB_FIRST);
 170
 171        /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */
 172        out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
 173                | ESPI_CSMODE_LEN(7));
 174
 175        return 0;
 176}
 177
 178void spi_release_bus(struct spi_slave *slave)
 179{
 180
 181}
 182
 183static void fsl_espi_tx(struct fsl_spi_slave *fsl, const void *dout)
 184{
 185        ccsr_espi_t *espi = fsl->espi;
 186        unsigned int tmpdout, event;
 187        int tmp_tx_timeout;
 188
 189        if (dout)
 190                tmpdout = *(u32 *)dout;
 191        else
 192                tmpdout = 0;
 193
 194        out_be32(&espi->tx, tmpdout);
 195        out_be32(&espi->event, ESPI_EV_TNF);
 196        debug("***spi_xfer:...%08x written\n", tmpdout);
 197
 198        tmp_tx_timeout = fsl->tx_timeout;
 199        /* Wait for eSPI transmit to go out */
 200        while (tmp_tx_timeout--) {
 201                event = in_be32(&espi->event);
 202                if (event & ESPI_EV_DON || event & ESPI_EV_TXE) {
 203                        out_be32(&espi->event, ESPI_EV_TXE);
 204                        break;
 205                }
 206                udelay(1);
 207        }
 208
 209        if (tmp_tx_timeout < 0)
 210                debug("***spi_xfer:...Tx timeout! event = %08x\n", event);
 211}
 212
 213static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, unsigned int bytes)
 214{
 215        ccsr_espi_t *espi = fsl->espi;
 216        unsigned int tmpdin, rx_times;
 217        unsigned char *buf, *p_cursor;
 218
 219        if (bytes <= 0)
 220                return 0;
 221
 222        rx_times = DIV_ROUND_UP(bytes, 4);
 223        buf = (unsigned char *)malloc(4 * rx_times);
 224        if (!buf) {
 225                debug("SF: Failed to malloc memory.\n");
 226                return -1;
 227        }
 228        p_cursor = buf;
 229        while (rx_times--) {
 230                tmpdin = in_be32(&espi->rx);
 231                debug("***spi_xfer:...%08x readed\n", tmpdin);
 232                *(u32 *)p_cursor = tmpdin;
 233                p_cursor += 4;
 234        }
 235
 236        if (din)
 237                memcpy(din, buf, bytes);
 238
 239        free(buf);
 240        out_be32(&espi->event, ESPI_EV_RNE);
 241
 242        return bytes;
 243}
 244
 245int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
 246                void *data_in, unsigned long flags)
 247{
 248        struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
 249        ccsr_espi_t *espi = fsl->espi;
 250        unsigned int event, rx_bytes;
 251        const void *dout = NULL;
 252        void *din = NULL;
 253        int len = 0;
 254        int num_blks, num_chunks, max_tran_len, tran_len;
 255        int num_bytes;
 256        unsigned char *buffer = NULL;
 257        size_t buf_len;
 258        u8 *cmd_buf = fsl->cmd_buf;
 259        size_t cmd_len = fsl->cmd_len;
 260        size_t data_len = bitlen / 8;
 261        size_t rx_offset = 0;
 262        int rf_cnt;
 263
 264        max_tran_len = fsl->max_transfer_length;
 265        switch (flags) {
 266        case SPI_XFER_BEGIN:
 267                cmd_len = fsl->cmd_len = data_len;
 268                memcpy(cmd_buf, data_out, cmd_len);
 269                return 0;
 270        case 0:
 271        case SPI_XFER_END:
 272                if (bitlen == 0) {
 273                        spi_cs_deactivate(slave);
 274                        return 0;
 275                }
 276                buf_len = 2 * cmd_len + min(data_len, (size_t)max_tran_len);
 277                len = cmd_len + data_len;
 278                rx_offset = cmd_len;
 279                buffer = (unsigned char *)malloc(buf_len);
 280                if (!buffer) {
 281                        debug("SF: Failed to malloc memory.\n");
 282                        return 1;
 283                }
 284                memcpy(buffer, cmd_buf, cmd_len);
 285                if (data_in == NULL)
 286                        memcpy(buffer + cmd_len, data_out, data_len);
 287                break;
 288        case SPI_XFER_BEGIN | SPI_XFER_END:
 289                len = data_len;
 290                buffer = (unsigned char *)malloc(len * 2);
 291                if (!buffer) {
 292                        debug("SF: Failed to malloc memory.\n");
 293                        return 1;
 294                }
 295                memcpy(buffer, data_out, len);
 296                rx_offset = len;
 297                cmd_len = 0;
 298                break;
 299        }
 300
 301        debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) len %u\n",
 302              *(uint *)data_out, data_out, *(uint *)data_in, data_in, len);
 303
 304        num_chunks = DIV_ROUND_UP(data_len, max_tran_len);
 305        while (num_chunks--) {
 306                if (data_in)
 307                        din = buffer + rx_offset;
 308                dout = buffer;
 309                tran_len = min(data_len, (size_t)max_tran_len);
 310                num_blks = DIV_ROUND_UP(tran_len + cmd_len, 4);
 311                num_bytes = (tran_len + cmd_len) % 4;
 312                fsl->data_len = tran_len + cmd_len;
 313                spi_cs_activate(slave);
 314
 315                /* Clear all eSPI events */
 316                out_be32(&espi->event , 0xffffffff);
 317                /* handle data in 32-bit chunks */
 318                while (num_blks) {
 319                        event = in_be32(&espi->event);
 320                        if (event & ESPI_EV_TNF) {
 321                                fsl_espi_tx(fsl, dout);
 322                                /* Set up the next iteration */
 323                                if (len > 4) {
 324                                        len -= 4;
 325                                        dout += 4;
 326                                }
 327                        }
 328
 329                        event = in_be32(&espi->event);
 330                        if (event & ESPI_EV_RNE) {
 331                                rf_cnt = ((event & ESPI_EV_RFCNT_MASK)
 332                                                >> ESPI_EV_RFCNT_SHIFT);
 333                                if (rf_cnt >= 4)
 334                                        rx_bytes = 4;
 335                                else if (num_blks == 1 && rf_cnt == num_bytes)
 336                                        rx_bytes = num_bytes;
 337                                else
 338                                        continue;
 339                                if (fsl_espi_rx(fsl, din, rx_bytes)
 340                                                == rx_bytes) {
 341                                        num_blks--;
 342                                        if (din)
 343                                                din = (unsigned char *)din
 344                                                        + rx_bytes;
 345                                }
 346                        }
 347                }
 348                if (data_in) {
 349                        memcpy(data_in, buffer + 2 * cmd_len, tran_len);
 350                        if (*buffer == 0x0b) {
 351                                data_in += tran_len;
 352                                data_len -= tran_len;
 353                                *(int *)buffer += tran_len;
 354                        }
 355                }
 356                spi_cs_deactivate(slave);
 357        }
 358
 359        free(buffer);
 360        return 0;
 361}
 362
 363int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 364{
 365        return bus == 0 && cs < ESPI_MAX_CS_NUM;
 366}
 367
 368void spi_cs_activate(struct spi_slave *slave)
 369{
 370        struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
 371        ccsr_espi_t *espi = fsl->espi;
 372        unsigned int com = 0;
 373        size_t data_len = fsl->data_len;
 374
 375        com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF));
 376        com |= ESPI_COM_CS(slave->cs);
 377        com |= ESPI_COM_TRANLEN(data_len - 1);
 378        out_be32(&espi->com, com);
 379}
 380
 381void spi_cs_deactivate(struct spi_slave *slave)
 382{
 383        struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
 384        ccsr_espi_t *espi = fsl->espi;
 385
 386        /* clear the RXCNT and TXCNT */
 387        out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN));
 388        out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN);
 389}
 390