uboot/drivers/spi/bfin_spi.c
<<
>>
Prefs
   1/*
   2 * Driver for Blackfin On-Chip SPI device
   3 *
   4 * Copyright (c) 2005-2008 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9/*#define DEBUG*/
  10
  11#include <common.h>
  12#include <malloc.h>
  13#include <spi.h>
  14
  15#include <asm/blackfin.h>
  16#include <asm/mach-common/bits/spi.h>
  17
  18struct bfin_spi_slave {
  19        struct spi_slave slave;
  20        void *mmr_base;
  21        u16 ctl, baud, flg;
  22};
  23
  24#define MAKE_SPI_FUNC(mmr, off) \
  25static inline void write_##mmr(struct bfin_spi_slave *bss, u16 val) { bfin_write16(bss->mmr_base + off, val); } \
  26static inline u16 read_##mmr(struct bfin_spi_slave *bss) { return bfin_read16(bss->mmr_base + off); }
  27MAKE_SPI_FUNC(SPI_CTL,  0x00)
  28MAKE_SPI_FUNC(SPI_FLG,  0x04)
  29MAKE_SPI_FUNC(SPI_STAT, 0x08)
  30MAKE_SPI_FUNC(SPI_TDBR, 0x0c)
  31MAKE_SPI_FUNC(SPI_RDBR, 0x10)
  32MAKE_SPI_FUNC(SPI_BAUD, 0x14)
  33
  34#define to_bfin_spi_slave(s) container_of(s, struct bfin_spi_slave, slave)
  35
  36__attribute__((weak))
  37int spi_cs_is_valid(unsigned int bus, unsigned int cs)
  38{
  39#if defined(__ADSPBF538__) || defined(__ADSPBF539__)
  40        /* The SPI1/SPI2 buses are weird ... only 1 CS */
  41        if (bus > 0 && cs != 1)
  42                return 0;
  43#endif
  44        return (cs >= 1 && cs <= 7);
  45}
  46
  47__attribute__((weak))
  48void spi_cs_activate(struct spi_slave *slave)
  49{
  50        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
  51        write_SPI_FLG(bss,
  52                (read_SPI_FLG(bss) &
  53                ~((!bss->flg << 8) << slave->cs)) |
  54                (1 << slave->cs));
  55        SSYNC();
  56        debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));
  57}
  58
  59__attribute__((weak))
  60void spi_cs_deactivate(struct spi_slave *slave)
  61{
  62        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
  63        u16 flg;
  64
  65        /* make sure we force the cs to deassert rather than let the
  66         * pin float back up.  otherwise, exact timings may not be
  67         * met some of the time leading to random behavior (ugh).
  68         */
  69        flg = read_SPI_FLG(bss) | ((!bss->flg << 8) << slave->cs);
  70        write_SPI_FLG(bss, flg);
  71        SSYNC();
  72        debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));
  73
  74        flg &= ~(1 << slave->cs);
  75        write_SPI_FLG(bss, flg);
  76        SSYNC();
  77        debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));
  78}
  79
  80void spi_init()
  81{
  82}
  83
  84struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  85                unsigned int max_hz, unsigned int mode)
  86{
  87        struct bfin_spi_slave *bss;
  88        ulong sclk;
  89        u32 mmr_base;
  90        u32 baud;
  91
  92        if (!spi_cs_is_valid(bus, cs))
  93                return NULL;
  94
  95        switch (bus) {
  96#ifdef SPI_CTL
  97# define SPI0_CTL SPI_CTL
  98#endif
  99                case 0: mmr_base = SPI0_CTL; break;
 100#ifdef SPI1_CTL
 101                case 1: mmr_base = SPI1_CTL; break;
 102#endif
 103#ifdef SPI2_CTL
 104                case 2: mmr_base = SPI2_CTL; break;
 105#endif
 106                default: return NULL;
 107        }
 108
 109        sclk = get_sclk();
 110        baud = sclk / (2 * max_hz);
 111        /* baud should be rounded up */
 112        if (sclk % (2 * max_hz))
 113                baud += 1;
 114        if (baud < 2)
 115                baud = 2;
 116        else if (baud > (u16)-1)
 117                baud = -1;
 118
 119        bss = malloc(sizeof(*bss));
 120        if (!bss)
 121                return NULL;
 122
 123        bss->slave.bus = bus;
 124        bss->slave.cs = cs;
 125        bss->mmr_base = (void *)mmr_base;
 126        bss->ctl = SPE | MSTR | TDBR_CORE;
 127        if (mode & SPI_CPHA) bss->ctl |= CPHA;
 128        if (mode & SPI_CPOL) bss->ctl |= CPOL;
 129        if (mode & SPI_LSB_FIRST) bss->ctl |= LSBF;
 130        bss->baud = baud;
 131        bss->flg = mode & SPI_CS_HIGH ? 1 : 0;
 132
 133        debug("%s: bus:%i cs:%i mmr:%x ctl:%x baud:%i flg:%i\n", __func__,
 134                bus, cs, mmr_base, bss->ctl, baud, bss->flg);
 135
 136        return &bss->slave;
 137}
 138
 139void spi_free_slave(struct spi_slave *slave)
 140{
 141        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
 142        free(bss);
 143}
 144
 145static void spi_portmux(struct spi_slave *slave)
 146{
 147#if defined(__ADSPBF51x__)
 148#define SET_MUX(port, mux, func) port##_mux = ((port##_mux & ~PORT_x_MUX_##mux##_MASK) | PORT_x_MUX_##mux##_FUNC_##func)
 149        u16 f_mux = bfin_read_PORTF_MUX();
 150        u16 f_fer = bfin_read_PORTF_FER();
 151        u16 g_mux = bfin_read_PORTG_MUX();
 152        u16 g_fer = bfin_read_PORTG_FER();
 153        u16 h_mux = bfin_read_PORTH_MUX();
 154        u16 h_fer = bfin_read_PORTH_FER();
 155        switch (slave->bus) {
 156        case 0:
 157                /* set SCK/MISO/MOSI */
 158                SET_MUX(g, 7, 1);
 159                g_fer |= PG12 | PG13 | PG14;
 160                switch (slave->cs) {
 161                        case 1: SET_MUX(f, 2, 1); f_fer |= PF7;  break;
 162                        case 2: /* see G above */ g_fer |= PG15; break;
 163                        case 3: SET_MUX(h, 1, 3); f_fer |= PH4;  break;
 164                        case 4: /* no muxing */   h_fer |= PH8;  break;
 165                        case 5: SET_MUX(g, 1, 3); h_fer |= PG3;  break;
 166                        case 6: /* no muxing */                  break;
 167                        case 7: /* no muxing */                  break;
 168                }
 169        case 1:
 170                /* set SCK/MISO/MOSI */
 171                SET_MUX(h, 0, 2);
 172                h_fer |= PH1 | PH2 | PH3;
 173                switch (slave->cs) {
 174                        case 1: SET_MUX(h, 2, 3); h_fer |= PH6;  break;
 175                        case 2: SET_MUX(f, 0, 3); f_fer |= PF0;  break;
 176                        case 3: SET_MUX(g, 0, 3); g_fer |= PG0;  break;
 177                        case 4: SET_MUX(f, 3, 3); f_fer |= PF8;  break;
 178                        case 5: SET_MUX(g, 6, 3); h_fer |= PG11; break;
 179                        case 6: /* no muxing */                  break;
 180                        case 7: /* no muxing */                  break;
 181                }
 182        }
 183        bfin_write_PORTF_MUX(f_mux);
 184        bfin_write_PORTF_FER(f_fer);
 185        bfin_write_PORTG_MUX(g_mux);
 186        bfin_write_PORTG_FER(g_fer);
 187        bfin_write_PORTH_MUX(h_mux);
 188        bfin_write_PORTH_FER(h_fer);
 189#elif defined(__ADSPBF52x__)
 190#define SET_MUX(port, mux, func) port##_mux = ((port##_mux & ~PORT_x_MUX_##mux##_MASK) | PORT_x_MUX_##mux##_FUNC_##func)
 191        u16 f_mux = bfin_read_PORTF_MUX();
 192        u16 f_fer = bfin_read_PORTF_FER();
 193        u16 g_mux = bfin_read_PORTG_MUX();
 194        u16 g_fer = bfin_read_PORTG_FER();
 195        u16 h_mux = bfin_read_PORTH_MUX();
 196        u16 h_fer = bfin_read_PORTH_FER();
 197        /* set SCK/MISO/MOSI */
 198        SET_MUX(g, 0, 3);
 199        g_fer |= PG2 | PG3 | PG4;
 200        switch (slave->cs) {
 201                case 1: /* see G above */ g_fer |= PG1;  break;
 202                case 2: SET_MUX(f, 4, 3); f_fer |= PF12; break;
 203                case 3: SET_MUX(f, 4, 3); f_fer |= PF13; break;
 204                case 4: SET_MUX(h, 1, 1); h_fer |= PH8;  break;
 205                case 5: SET_MUX(h, 2, 1); h_fer |= PH9;  break;
 206                case 6: SET_MUX(f, 1, 3); f_fer |= PF9;  break;
 207                case 7: SET_MUX(f, 2, 3); f_fer |= PF10; break;
 208        }
 209        bfin_write_PORTF_MUX(f_mux);
 210        bfin_write_PORTF_FER(f_fer);
 211        bfin_write_PORTG_MUX(g_mux);
 212        bfin_write_PORTG_FER(g_fer);
 213        bfin_write_PORTH_MUX(h_mux);
 214        bfin_write_PORTH_FER(h_fer);
 215#elif defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__)
 216        u16 mux = bfin_read_PORT_MUX();
 217        u16 f_fer = bfin_read_PORTF_FER();
 218        /* set SCK/MISO/MOSI */
 219        f_fer |= PF11 | PF12 | PF13;
 220        switch (slave->cs) {
 221                case 1: f_fer |= PF10; break;
 222                case 2: mux |= PJSE; break;
 223                case 3: mux |= PJSE; break;
 224                case 4: mux |= PFS4E; f_fer |= PF6; break;
 225                case 5: mux |= PFS5E; f_fer |= PF5; break;
 226                case 6: mux |= PFS6E; f_fer |= PF4; break;
 227                case 7: mux |= PJCE_SPI; break;
 228        }
 229        bfin_write_PORT_MUX(mux);
 230        bfin_write_PORTF_FER(f_fer);
 231#elif defined(__ADSPBF538__) || defined(__ADSPBF539__)
 232        u16 fer, pins;
 233        if (slave->bus == 1)
 234                pins = PD0 | PD1 | PD2 | (slave->cs == 1 ? PD4 : 0);
 235        else if (slave->bus == 2)
 236                pins = PD5 | PD6 | PD7 | (slave->cs == 1 ? PD9 : 0);
 237        else
 238                pins = 0;
 239        if (pins) {
 240                fer = bfin_read_PORTDIO_FER();
 241                fer &= ~pins;
 242                bfin_write_PORTDIO_FER(fer);
 243        }
 244#elif defined(__ADSPBF54x__)
 245#define DO_MUX(port, pin) \
 246        mux = ((mux & ~PORT_x_MUX_##pin##_MASK) | PORT_x_MUX_##pin##_FUNC_1); \
 247        fer |= P##port##pin;
 248        u32 mux;
 249        u16 fer;
 250        switch (slave->bus) {
 251        case 0:
 252                mux = bfin_read_PORTE_MUX();
 253                fer = bfin_read_PORTE_FER();
 254                /* set SCK/MISO/MOSI */
 255                DO_MUX(E, 0);
 256                DO_MUX(E, 1);
 257                DO_MUX(E, 2);
 258                switch (slave->cs) {
 259                        case 1: DO_MUX(E, 4); break;
 260                        case 2: DO_MUX(E, 5); break;
 261                        case 3: DO_MUX(E, 6); break;
 262                }
 263                bfin_write_PORTE_MUX(mux);
 264                bfin_write_PORTE_FER(fer);
 265                break;
 266        case 1:
 267                mux = bfin_read_PORTG_MUX();
 268                fer = bfin_read_PORTG_FER();
 269                /* set SCK/MISO/MOSI */
 270                DO_MUX(G, 8);
 271                DO_MUX(G, 9);
 272                DO_MUX(G, 10);
 273                switch (slave->cs) {
 274                        case 1: DO_MUX(G, 5); break;
 275                        case 2: DO_MUX(G, 6); break;
 276                        case 3: DO_MUX(G, 7); break;
 277                }
 278                bfin_write_PORTG_MUX(mux);
 279                bfin_write_PORTG_FER(fer);
 280                break;
 281        case 2:
 282                mux = bfin_read_PORTB_MUX();
 283                fer = bfin_read_PORTB_FER();
 284                /* set SCK/MISO/MOSI */
 285                DO_MUX(B, 12);
 286                DO_MUX(B, 13);
 287                DO_MUX(B, 14);
 288                switch (slave->cs) {
 289                        case 1: DO_MUX(B, 9);  break;
 290                        case 2: DO_MUX(B, 10); break;
 291                        case 3: DO_MUX(B, 11); break;
 292                }
 293                bfin_write_PORTB_MUX(mux);
 294                bfin_write_PORTB_FER(fer);
 295                break;
 296        }
 297#endif
 298}
 299
 300int spi_claim_bus(struct spi_slave *slave)
 301{
 302        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
 303
 304        debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
 305
 306        spi_portmux(slave);
 307        write_SPI_CTL(bss, bss->ctl);
 308        write_SPI_BAUD(bss, bss->baud);
 309        SSYNC();
 310
 311        return 0;
 312}
 313
 314void spi_release_bus(struct spi_slave *slave)
 315{
 316        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
 317        debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
 318        write_SPI_CTL(bss, 0);
 319        SSYNC();
 320}
 321
 322#ifndef CONFIG_BFIN_SPI_IDLE_VAL
 323# define CONFIG_BFIN_SPI_IDLE_VAL 0xff
 324#endif
 325
 326int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 327                void *din, unsigned long flags)
 328{
 329        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
 330        const u8 *tx = dout;
 331        u8 *rx = din;
 332        uint bytes = bitlen / 8;
 333        int ret = 0;
 334
 335        debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
 336                slave->bus, slave->cs, bitlen, bytes, flags);
 337
 338        if (bitlen == 0)
 339                goto done;
 340
 341        /* we can only do 8 bit transfers */
 342        if (bitlen % 8) {
 343                flags |= SPI_XFER_END;
 344                goto done;
 345        }
 346
 347        if (flags & SPI_XFER_BEGIN)
 348                spi_cs_activate(slave);
 349
 350        /* todo: take advantage of hardware fifos and setup RX dma */
 351        while (bytes--) {
 352                u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL);
 353                debug("%s: tx:%x ", __func__, value);
 354                write_SPI_TDBR(bss, value);
 355                SSYNC();
 356                while ((read_SPI_STAT(bss) & TXS))
 357                        if (ctrlc()) {
 358                                ret = -1;
 359                                goto done;
 360                        }
 361                while (!(read_SPI_STAT(bss) & SPIF))
 362                        if (ctrlc()) {
 363                                ret = -1;
 364                                goto done;
 365                        }
 366                while (!(read_SPI_STAT(bss) & RXS))
 367                        if (ctrlc()) {
 368                                ret = -1;
 369                                goto done;
 370                        }
 371                value = read_SPI_RDBR(bss);
 372                if (rx)
 373                        *rx++ = value;
 374                debug("rx:%x\n", value);
 375        }
 376
 377 done:
 378        if (flags & SPI_XFER_END)
 379                spi_cs_deactivate(slave);
 380
 381        return ret;
 382}
 383