uboot/drivers/spi/mxc_spi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <malloc.h>
   9#include <spi.h>
  10#include <asm/errno.h>
  11#include <asm/io.h>
  12#include <asm/gpio.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/clock.h>
  15
  16#ifdef CONFIG_MX27
  17/* i.MX27 has a completely wrong register layout and register definitions in the
  18 * datasheet, the correct one is in the Freescale's Linux driver */
  19
  20#error "i.MX27 CSPI not supported due to drastic differences in register definitions" \
  21"See linux mxc_spi driver from Freescale for details."
  22#endif
  23
  24static unsigned long spi_bases[] = {
  25        MXC_SPI_BASE_ADDRESSES
  26};
  27
  28#define OUT     MXC_GPIO_DIRECTION_OUT
  29
  30#define reg_read readl
  31#define reg_write(a, v) writel(v, a)
  32
  33struct mxc_spi_slave {
  34        struct spi_slave slave;
  35        unsigned long   base;
  36        u32             ctrl_reg;
  37#if defined(MXC_ECSPI)
  38        u32             cfg_reg;
  39#endif
  40        int             gpio;
  41        int             ss_pol;
  42};
  43
  44static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
  45{
  46        return container_of(slave, struct mxc_spi_slave, slave);
  47}
  48
  49void spi_cs_activate(struct spi_slave *slave)
  50{
  51        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
  52        if (mxcs->gpio > 0)
  53                gpio_set_value(mxcs->gpio, mxcs->ss_pol);
  54}
  55
  56void spi_cs_deactivate(struct spi_slave *slave)
  57{
  58        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
  59        if (mxcs->gpio > 0)
  60                gpio_set_value(mxcs->gpio,
  61                              !(mxcs->ss_pol));
  62}
  63
  64u32 get_cspi_div(u32 div)
  65{
  66        int i;
  67
  68        for (i = 0; i < 8; i++) {
  69                if (div <= (4 << i))
  70                        return i;
  71        }
  72        return i;
  73}
  74
  75#ifdef MXC_CSPI
  76static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
  77                unsigned int max_hz, unsigned int mode)
  78{
  79        unsigned int ctrl_reg;
  80        u32 clk_src;
  81        u32 div;
  82
  83        clk_src = mxc_get_clock(MXC_CSPI_CLK);
  84
  85        div = DIV_ROUND_UP(clk_src, max_hz);
  86        div = get_cspi_div(div);
  87
  88        debug("clk %d Hz, div %d, real clk %d Hz\n",
  89                max_hz, div, clk_src / (4 << div));
  90
  91        ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
  92                MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS) |
  93                MXC_CSPICTRL_DATARATE(div) |
  94                MXC_CSPICTRL_EN |
  95#ifdef CONFIG_MX35
  96                MXC_CSPICTRL_SSCTL |
  97#endif
  98                MXC_CSPICTRL_MODE;
  99
 100        if (mode & SPI_CPHA)
 101                ctrl_reg |= MXC_CSPICTRL_PHA;
 102        if (mode & SPI_CPOL)
 103                ctrl_reg |= MXC_CSPICTRL_POL;
 104        if (mode & SPI_CS_HIGH)
 105                ctrl_reg |= MXC_CSPICTRL_SSPOL;
 106        mxcs->ctrl_reg = ctrl_reg;
 107
 108        return 0;
 109}
 110#endif
 111
 112#ifdef MXC_ECSPI
 113static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
 114                unsigned int max_hz, unsigned int mode)
 115{
 116        u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
 117        s32 reg_ctrl, reg_config;
 118        u32 ss_pol = 0, sclkpol = 0, sclkpha = 0, pre_div = 0, post_div = 0;
 119        struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
 120
 121        if (max_hz == 0) {
 122                printf("Error: desired clock is 0\n");
 123                return -1;
 124        }
 125
 126        /*
 127         * Reset SPI and set all CSs to master mode, if toggling
 128         * between slave and master mode we might see a glitch
 129         * on the clock line
 130         */
 131        reg_ctrl = MXC_CSPICTRL_MODE_MASK;
 132        reg_write(&regs->ctrl, reg_ctrl);
 133        reg_ctrl |=  MXC_CSPICTRL_EN;
 134        reg_write(&regs->ctrl, reg_ctrl);
 135
 136        if (clk_src > max_hz) {
 137                pre_div = (clk_src - 1) / max_hz;
 138                /* fls(1) = 1, fls(0x80000000) = 32, fls(16) = 5 */
 139                post_div = fls(pre_div);
 140                if (post_div > 4) {
 141                        post_div -= 4;
 142                        if (post_div >= 16) {
 143                                printf("Error: no divider for the freq: %d\n",
 144                                        max_hz);
 145                                return -1;
 146                        }
 147                        pre_div >>= post_div;
 148                } else {
 149                        post_div = 0;
 150                }
 151        }
 152
 153        debug("pre_div = %d, post_div=%d\n", pre_div, post_div);
 154        reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_SELCHAN(3)) |
 155                MXC_CSPICTRL_SELCHAN(cs);
 156        reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_PREDIV(0x0F)) |
 157                MXC_CSPICTRL_PREDIV(pre_div);
 158        reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
 159                MXC_CSPICTRL_POSTDIV(post_div);
 160
 161        /* We need to disable SPI before changing registers */
 162        reg_ctrl &= ~MXC_CSPICTRL_EN;
 163
 164        if (mode & SPI_CS_HIGH)
 165                ss_pol = 1;
 166
 167        if (mode & SPI_CPOL)
 168                sclkpol = 1;
 169
 170        if (mode & SPI_CPHA)
 171                sclkpha = 1;
 172
 173        reg_config = reg_read(&regs->cfg);
 174
 175        /*
 176         * Configuration register setup
 177         * The MX51 supports different setup for each SS
 178         */
 179        reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_SSPOL))) |
 180                (ss_pol << (cs + MXC_CSPICON_SSPOL));
 181        reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_POL))) |
 182                (sclkpol << (cs + MXC_CSPICON_POL));
 183        reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_PHA))) |
 184                (sclkpha << (cs + MXC_CSPICON_PHA));
 185
 186        debug("reg_ctrl = 0x%x\n", reg_ctrl);
 187        reg_write(&regs->ctrl, reg_ctrl);
 188        debug("reg_config = 0x%x\n", reg_config);
 189        reg_write(&regs->cfg, reg_config);
 190
 191        /* save config register and control register */
 192        mxcs->ctrl_reg = reg_ctrl;
 193        mxcs->cfg_reg = reg_config;
 194
 195        /* clear interrupt reg */
 196        reg_write(&regs->intr, 0);
 197        reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 198
 199        return 0;
 200}
 201#endif
 202
 203int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
 204        const u8 *dout, u8 *din, unsigned long flags)
 205{
 206        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
 207        int nbytes = DIV_ROUND_UP(bitlen, 8);
 208        u32 data, cnt, i;
 209        struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
 210
 211        debug("%s: bitlen %d dout 0x%x din 0x%x\n",
 212                __func__, bitlen, (u32)dout, (u32)din);
 213
 214        mxcs->ctrl_reg = (mxcs->ctrl_reg &
 215                ~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
 216                MXC_CSPICTRL_BITCOUNT(bitlen - 1);
 217
 218        reg_write(&regs->ctrl, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
 219#ifdef MXC_ECSPI
 220        reg_write(&regs->cfg, mxcs->cfg_reg);
 221#endif
 222
 223        /* Clear interrupt register */
 224        reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 225
 226        /*
 227         * The SPI controller works only with words,
 228         * check if less than a word is sent.
 229         * Access to the FIFO is only 32 bit
 230         */
 231        if (bitlen % 32) {
 232                data = 0;
 233                cnt = (bitlen % 32) / 8;
 234                if (dout) {
 235                        for (i = 0; i < cnt; i++) {
 236                                data = (data << 8) | (*dout++ & 0xFF);
 237                        }
 238                }
 239                debug("Sending SPI 0x%x\n", data);
 240
 241                reg_write(&regs->txdata, data);
 242                nbytes -= cnt;
 243        }
 244
 245        data = 0;
 246
 247        while (nbytes > 0) {
 248                data = 0;
 249                if (dout) {
 250                        /* Buffer is not 32-bit aligned */
 251                        if ((unsigned long)dout & 0x03) {
 252                                data = 0;
 253                                for (i = 0; i < 4; i++)
 254                                        data = (data << 8) | (*dout++ & 0xFF);
 255                        } else {
 256                                data = *(u32 *)dout;
 257                                data = cpu_to_be32(data);
 258                                dout += 4;
 259                        }
 260                }
 261                debug("Sending SPI 0x%x\n", data);
 262                reg_write(&regs->txdata, data);
 263                nbytes -= 4;
 264        }
 265
 266        /* FIFO is written, now starts the transfer setting the XCH bit */
 267        reg_write(&regs->ctrl, mxcs->ctrl_reg |
 268                MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
 269
 270        /* Wait until the TC (Transfer completed) bit is set */
 271        while ((reg_read(&regs->stat) & MXC_CSPICTRL_TC) == 0)
 272                ;
 273
 274        /* Transfer completed, clear any pending request */
 275        reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 276
 277        nbytes = DIV_ROUND_UP(bitlen, 8);
 278
 279        cnt = nbytes % 32;
 280
 281        if (bitlen % 32) {
 282                data = reg_read(&regs->rxdata);
 283                cnt = (bitlen % 32) / 8;
 284                data = cpu_to_be32(data) >> ((sizeof(data) - cnt) * 8);
 285                debug("SPI Rx unaligned: 0x%x\n", data);
 286                if (din) {
 287                        memcpy(din, &data, cnt);
 288                        din += cnt;
 289                }
 290                nbytes -= cnt;
 291        }
 292
 293        while (nbytes > 0) {
 294                u32 tmp;
 295                tmp = reg_read(&regs->rxdata);
 296                data = cpu_to_be32(tmp);
 297                debug("SPI Rx: 0x%x 0x%x\n", tmp, data);
 298                cnt = min(nbytes, sizeof(data));
 299                if (din) {
 300                        memcpy(din, &data, cnt);
 301                        din += cnt;
 302                }
 303                nbytes -= cnt;
 304        }
 305
 306        return 0;
 307
 308}
 309
 310int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 311                void *din, unsigned long flags)
 312{
 313        int n_bytes = DIV_ROUND_UP(bitlen, 8);
 314        int n_bits;
 315        int ret;
 316        u32 blk_size;
 317        u8 *p_outbuf = (u8 *)dout;
 318        u8 *p_inbuf = (u8 *)din;
 319
 320        if (!slave)
 321                return -1;
 322
 323        if (flags & SPI_XFER_BEGIN)
 324                spi_cs_activate(slave);
 325
 326        while (n_bytes > 0) {
 327                if (n_bytes < MAX_SPI_BYTES)
 328                        blk_size = n_bytes;
 329                else
 330                        blk_size = MAX_SPI_BYTES;
 331
 332                n_bits = blk_size * 8;
 333
 334                ret = spi_xchg_single(slave, n_bits, p_outbuf, p_inbuf, 0);
 335
 336                if (ret)
 337                        return ret;
 338                if (dout)
 339                        p_outbuf += blk_size;
 340                if (din)
 341                        p_inbuf += blk_size;
 342                n_bytes -= blk_size;
 343        }
 344
 345        if (flags & SPI_XFER_END) {
 346                spi_cs_deactivate(slave);
 347        }
 348
 349        return 0;
 350}
 351
 352void spi_init(void)
 353{
 354}
 355
 356static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
 357{
 358        int ret;
 359
 360        /*
 361         * Some SPI devices require active chip-select over multiple
 362         * transactions, we achieve this using a GPIO. Still, the SPI
 363         * controller has to be configured to use one of its own chipselects.
 364         * To use this feature you have to call spi_setup_slave() with
 365         * cs = internal_cs | (gpio << 8), and you have to use some unused
 366         * on this SPI controller cs between 0 and 3.
 367         */
 368        if (cs > 3) {
 369                mxcs->gpio = cs >> 8;
 370                cs &= 3;
 371                ret = gpio_direction_output(mxcs->gpio, !(mxcs->ss_pol));
 372                if (ret) {
 373                        printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
 374                        return -EINVAL;
 375                }
 376        } else {
 377                mxcs->gpio = -1;
 378        }
 379
 380        return cs;
 381}
 382
 383struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 384                        unsigned int max_hz, unsigned int mode)
 385{
 386        struct mxc_spi_slave *mxcs;
 387        int ret;
 388
 389        if (bus >= ARRAY_SIZE(spi_bases))
 390                return NULL;
 391
 392        mxcs = spi_alloc_slave(struct mxc_spi_slave, bus, cs);
 393        if (!mxcs) {
 394                puts("mxc_spi: SPI Slave not allocated !\n");
 395                return NULL;
 396        }
 397
 398        mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
 399
 400        ret = decode_cs(mxcs, cs);
 401        if (ret < 0) {
 402                free(mxcs);
 403                return NULL;
 404        }
 405
 406        cs = ret;
 407
 408        mxcs->base = spi_bases[bus];
 409
 410        ret = spi_cfg_mxc(mxcs, cs, max_hz, mode);
 411        if (ret) {
 412                printf("mxc_spi: cannot setup SPI controller\n");
 413                free(mxcs);
 414                return NULL;
 415        }
 416        return &mxcs->slave;
 417}
 418
 419void spi_free_slave(struct spi_slave *slave)
 420{
 421        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
 422
 423        free(mxcs);
 424}
 425
 426int spi_claim_bus(struct spi_slave *slave)
 427{
 428        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
 429        struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
 430
 431        reg_write(&regs->rxdata, 1);
 432        udelay(1);
 433        reg_write(&regs->ctrl, mxcs->ctrl_reg);
 434        reg_write(&regs->period, MXC_CSPIPERIOD_32KHZ);
 435        reg_write(&regs->intr, 0);
 436
 437        return 0;
 438}
 439
 440void spi_release_bus(struct spi_slave *slave)
 441{
 442        /* TODO: Shut the controller down */
 443}
 444