uboot/arch/powerpc/cpu/mpc5xx/spi.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2001 Navin Boppuri / Prashant Patel
   3 *      <nboppuri@trinetcommunication.com>,
   4 *      <pmpatel@trinetcommunication.com>
   5 * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
   6 * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11/*
  12 * MPC5xx CPM SPI interface.
  13 *
  14 * Parts of this code are probably not portable and/or specific to
  15 * the board which I used for the tests. Please send fixes/complaints
  16 * to wd@denx.de
  17 *
  18 * Ported to MPC5xx
  19 * Copyright (c) 2003 Denis Peter, MPL AG Switzerland, d.petr@mpl.ch.
  20 */
  21
  22#include <common.h>
  23#include <mpc5xx.h>
  24#include <asm/5xx_immap.h>
  25#include <linux/ctype.h>
  26#include <malloc.h>
  27#include <post.h>
  28#include <net.h>
  29
  30#if defined(CONFIG_SPI)
  31
  32#undef  DEBUG
  33
  34#define SPI_EEPROM_WREN         0x06
  35#define SPI_EEPROM_RDSR         0x05
  36#define SPI_EEPROM_READ         0x03
  37#define SPI_EEPROM_WRITE        0x02
  38
  39
  40#ifdef  DEBUG
  41
  42#define DPRINT(a)       printf a;
  43/* -----------------------------------------------
  44 * Helper functions to peek into tx and rx buffers
  45 * ----------------------------------------------- */
  46static const char * const hex_digit = "0123456789ABCDEF";
  47
  48static char quickhex (int i)
  49{
  50        return hex_digit[i];
  51}
  52
  53static void memdump (void *pv, int num)
  54{
  55        int i;
  56        unsigned char *pc = (unsigned char *) pv;
  57
  58        for (i = 0; i < num; i++)
  59                printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
  60        printf ("\t");
  61        for (i = 0; i < num; i++)
  62                printf ("%c", isprint (pc[i]) ? pc[i] : '.');
  63        printf ("\n");
  64}
  65#else   /* !DEBUG */
  66
  67#define DPRINT(a)
  68
  69#endif  /* DEBUG */
  70
  71/* -------------------
  72 * Function prototypes
  73 * ------------------- */
  74void spi_init (void);
  75
  76ssize_t spi_read (uchar *, int, uchar *, int);
  77ssize_t spi_write (uchar *, int, uchar *, int);
  78ssize_t spi_xfer (size_t);
  79
  80
  81/* **************************************************************************
  82 *
  83 *  Function:    spi_init_f
  84 *
  85 *  Description: Init SPI-Controller (ROM part)
  86 *
  87 *  return:      ---
  88 *
  89 * *********************************************************************** */
  90
  91void spi_init_f (void)
  92{
  93        int i;
  94
  95        volatile immap_t *immr;
  96        volatile qsmcm5xx_t *qsmcm;
  97
  98        immr = (immap_t *)  CONFIG_SYS_IMMR;
  99        qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
 100
 101        qsmcm->qsmcm_qsmcr = 0; /* all accesses enabled */
 102        qsmcm->qsmcm_qspi_il = 0; /* lowest IRQ */
 103
 104        /* --------------------------------------------
 105         * GPIO or per. Function
 106         * PQSPAR[00] = 0 reserved
 107         * PQSPAR[01] = 1 [0x4000] -> PERI: (SPICS3)
 108         * PQSPAR[02] = 0 [0x0000] -> GPIO
 109         * PQSPAR[03] = 0 [0x0000] -> GPIO
 110         * PQSPAR[04] = 1 [0x0800] -> PERI: (SPICS0)
 111         * PQSPAR[05] = 0 reseved
 112         * PQSPAR[06] = 1 [0x0200] -> PERI: (SPIMOSI)
 113         * PQSPAR[07] = 1 [0x0100] -> PERI: (SPIMISO)
 114         * -------------------------------------------- */
 115        qsmcm->qsmcm_pqspar =  0x3 | (CONFIG_SYS_SPI_CS_USED << 3);
 116
 117         /* --------------------------------------------
 118         * DDRQS[00] = 0 reserved
 119         * DDRQS[01] = 1 [0x0040] -> SPICS3 Output
 120         * DDRQS[02] = 0 [0x0000] -> GPIO Output
 121         * DDRQS[03] = 0 [0x0000] -> GPIO Output
 122         * DDRQS[04] = 1 [0x0008] -> SPICS0 Output
 123         * DDRQS[05] = 1 [0x0004] -> SPICLK Output
 124         * DDRQS[06] = 1 [0x0002] -> SPIMOSI Output
 125         * DDRQS[07] = 0 [0x0001] -> SPIMISO Input
 126         * -------------------------------------------- */
 127        qsmcm->qsmcm_ddrqs = 0x7E;
 128         /* --------------------------------------------
 129         * Base state for used SPI CS pins, if base = 0 active must be 1
 130         * PORTQS[00] = 0 reserved
 131         * PORTQS[01] = 0 reserved
 132         * PORTQS[02] = 0 reserved
 133         * PORTQS[03] = 0 reserved
 134         * PORTQS[04] = 0 [0x0000] RxD2
 135         * PORTQS[05] = 1 [0x0400] TxD2
 136         * PORTQS[06] = 0 [0x0000] RxD1
 137         * PORTQS[07] = 1 [0x0100] TxD1
 138         * PORTQS[08] = 0 reserved
 139         * PORTQS[09] = 0 [0x0000] -> SPICS3 Base Output
 140         * PORTQS[10] = 0 [0x0000] -> SPICS2 Base Output
 141         * PORTQS[11] = 0 [0x0000] -> SPICS1 Base Output
 142         * PORTQS[12] = 0 [0x0000] -> SPICS0 Base Output
 143         * PORTQS[13] = 0 [0x0004] -> SPICLK Output
 144         * PORTQS[14] = 0 [0x0002] -> SPIMOSI Output
 145         * PORTQS[15] = 0 [0x0001] -> SPIMISO Input
 146         * -------------------------------------------- */
 147        qsmcm->qsmcm_portqs |= (CONFIG_SYS_SPI_CS_BASE << 3);
 148        /* --------------------------------------------
 149         * Controll Register 0
 150         * SPCR0[00] = 1 (0x8000) Master
 151         * SPCR0[01] = 0 (0x0000) Wired-Or
 152         * SPCR0[2..5] = (0x2000) Bits per transfer (default 8)
 153         * SPCR0[06] = 0 (0x0000) Normal polarity
 154         * SPCR0[07] = 0 (0x0000) Normal Clock Phase
 155         * SPCR0[08..15] = 14 1.4MHz
 156         */
 157        qsmcm->qsmcm_spcr0=0xA00E;
 158        /* --------------------------------------------
 159         * Controll Register 1
 160         * SPCR1[00] = 0 (0x0000) QSPI enabled
 161         * SPCR1[1..7] =  (0x7F00) Delay before Transfer
 162         * SPCR1[8..15] = (0x0000) Delay After transfer (204.8usec@40MHz)
 163         */
 164        qsmcm->qsmcm_spcr1=0x7F00;
 165        /* --------------------------------------------
 166         * Controll Register 2
 167         * SPCR2[00] = 0 (0x0000) SPI IRQs Disabeld
 168         * SPCR2[01] = 0 (0x0000) No Wrap around
 169         * SPCR2[02] = 0 (0x0000) Wrap to 0
 170         * SPCR2[3..7] = (0x0000) End Queue pointer = 0
 171         * SPCR2[8..10] = 0 (0x0000) reserved
 172         * SPCR2[11..15] = 0 (0x0000) NewQueue Address = 0
 173         */
 174        qsmcm->qsmcm_spcr2=0x0000;
 175        /* --------------------------------------------
 176         * Controll Register 3
 177         * SPCR3[00..04] = 0 (0x0000) reserved
 178         * SPCR3[05] = 0 (0x0000) Feedback disabled
 179         * SPCR3[06] = 0 (0x0000) IRQ on HALTA & MODF disabled
 180         * SPCR3[07] = 0 (0x0000) Not halted
 181         */
 182        qsmcm->qsmcm_spcr3=0x00;
 183        /* --------------------------------------------
 184         * SPSR (Controll Register 3) Read only/ reset Flags 08,09,10
 185         * SPCR3[08] = 1 (0x80) QSPI finished
 186         * SPCR3[09] = 1 (0x40) Mode Fault Flag
 187         * SPCR3[10] = 1 (0x20) HALTA
 188         * SPCR3[11..15] = 0 (0x0000) Last executed command
 189         */
 190        qsmcm->qsmcm_spsr=0xE0;
 191        /*-------------------------------------------
 192         * Setup RAM
 193         */
 194        for(i=0;i<32;i++) {
 195                 qsmcm->qsmcm_recram[i]=0x0000;
 196                 qsmcm->qsmcm_tranram[i]=0x0000;
 197                 qsmcm->qsmcm_comdram[i]=0x00;
 198        }
 199        return;
 200}
 201
 202/* **************************************************************************
 203 *
 204 *  Function:    spi_init_r
 205 *  Dummy, all initializations have been done in spi_init_r
 206 * *********************************************************************** */
 207void spi_init_r (void)
 208{
 209        return;
 210
 211}
 212
 213/****************************************************************************
 214 *  Function:    spi_write
 215 **************************************************************************** */
 216ssize_t short_spi_write (uchar *addr, int alen, uchar *buffer, int len)
 217{
 218        int i,dlen;
 219        volatile immap_t *immr;
 220        volatile qsmcm5xx_t *qsmcm;
 221
 222        immr = (immap_t *)  CONFIG_SYS_IMMR;
 223        qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
 224        for(i=0;i<32;i++) {
 225                 qsmcm->qsmcm_recram[i]=0x0000;
 226                 qsmcm->qsmcm_tranram[i]=0x0000;
 227                 qsmcm->qsmcm_comdram[i]=0x00;
 228        }
 229        qsmcm->qsmcm_tranram[0] =  SPI_EEPROM_WREN; /* write enable */
 230        spi_xfer(1);
 231        i=0;
 232        qsmcm->qsmcm_tranram[i++] =  SPI_EEPROM_WRITE; /* WRITE memory array */
 233        qsmcm->qsmcm_tranram[i++] =  addr[0];
 234        qsmcm->qsmcm_tranram[i++] =  addr[1];
 235
 236        for(dlen=0;dlen<len;dlen++) {
 237                qsmcm->qsmcm_tranram[i+dlen] = buffer[dlen]; /* WRITE memory array */
 238        }
 239        /* transmit it */
 240        spi_xfer(i+dlen);
 241        /* ignore received data */
 242        for (i = 0; i < 1000; i++) {
 243                qsmcm->qsmcm_tranram[0] =  SPI_EEPROM_RDSR; /* read status */
 244                qsmcm->qsmcm_tranram[1] = 0;
 245                spi_xfer(2);
 246                if (!(qsmcm->qsmcm_recram[1] & 1)) {
 247                        break;
 248                }
 249                udelay(1000);
 250        }
 251        if (i >= 1000) {
 252                printf ("*** spi_write: Time out while writing!\n");
 253        }
 254        return len;
 255}
 256
 257#define TRANSFER_LEN 16
 258
 259ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
 260{
 261        int index,i,newlen;
 262        uchar newaddr[2];
 263        int curraddr;
 264
 265        curraddr=(addr[alen-2]<<8)+addr[alen-1];
 266        i=len;
 267        index=0;
 268        do {
 269                newaddr[1]=(curraddr & 0xff);
 270                newaddr[0]=((curraddr>>8) & 0xff);
 271                if(i>TRANSFER_LEN) {
 272                        newlen=TRANSFER_LEN;
 273                        i-=TRANSFER_LEN;
 274                }
 275                else {
 276                        newlen=i;
 277                        i=0;
 278                }
 279                short_spi_write (newaddr, 2, &buffer[index], newlen);
 280                index+=newlen;
 281                curraddr+=newlen;
 282        }while(i);
 283        return (len);
 284}
 285
 286/****************************************************************************
 287 *  Function:    spi_read
 288 **************************************************************************** */
 289ssize_t short_spi_read (uchar *addr, int alen, uchar *buffer, int len)
 290{
 291        int i;
 292        volatile immap_t *immr;
 293        volatile qsmcm5xx_t *qsmcm;
 294
 295        immr = (immap_t *)  CONFIG_SYS_IMMR;
 296        qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
 297
 298        for(i=0;i<32;i++) {
 299                 qsmcm->qsmcm_recram[i]=0x0000;
 300                 qsmcm->qsmcm_tranram[i]=0x0000;
 301                 qsmcm->qsmcm_comdram[i]=0x00;
 302        }
 303        i=0;
 304        qsmcm->qsmcm_tranram[i++] = (SPI_EEPROM_READ); /* READ memory array */
 305        qsmcm->qsmcm_tranram[i++] = addr[0] & 0xff;
 306        qsmcm->qsmcm_tranram[i++] = addr[1] & 0xff;
 307        spi_xfer(3 + len);
 308        for(i=0;i<len;i++) {
 309                *buffer++=(char)qsmcm->qsmcm_recram[i+3];
 310        }
 311        return len;
 312}
 313
 314ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
 315{
 316        int index,i,newlen;
 317        uchar newaddr[2];
 318        int curraddr;
 319
 320        curraddr=(addr[alen-2]<<8)+addr[alen-1];
 321        i=len;
 322        index=0;
 323        do {
 324                newaddr[1]=(curraddr & 0xff);
 325                newaddr[0]=((curraddr>>8) & 0xff);
 326                if(i>TRANSFER_LEN) {
 327                        newlen=TRANSFER_LEN;
 328                        i-=TRANSFER_LEN;
 329                }
 330                else {
 331                        newlen=i;
 332                        i=0;
 333                }
 334                short_spi_read (newaddr, 2, &buffer[index], newlen);
 335                index+=newlen;
 336                curraddr+=newlen;
 337        }while(i);
 338        return (len);
 339}
 340
 341/****************************************************************************
 342 *  Function:    spi_xfer
 343 **************************************************************************** */
 344ssize_t spi_xfer (size_t count)
 345{
 346        volatile immap_t *immr;
 347        volatile qsmcm5xx_t *qsmcm;
 348        int i;
 349        int tm;
 350        ushort status;
 351        immr = (immap_t *)  CONFIG_SYS_IMMR;
 352        qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
 353        DPRINT (("*** spi_xfer entered count %d***\n",count));
 354
 355        /* Set CS for device */
 356        for(i=0;i<(count-1);i++)
 357                qsmcm->qsmcm_comdram[i] = 0x80 | CONFIG_SYS_SPI_CS_ACT;  /* CS3 is connected to the SPI EEPROM */
 358
 359        qsmcm->qsmcm_comdram[i] = CONFIG_SYS_SPI_CS_ACT; /* CS3 is connected to the SPI EEPROM */
 360        qsmcm->qsmcm_spcr2=((count-1)&0x1F)<<8;
 361
 362        DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n", count));
 363
 364        qsmcm->qsmcm_spsr=0xE0; /* clear all flags */
 365
 366        /* start spi transfer */
 367        DPRINT (("*** spi_xfer: Performing transfer ...\n"));
 368        qsmcm->qsmcm_spcr1 |= 0x8000;           /* Start transmit */
 369
 370        /* --------------------------------
 371         * Wait for SPI transmit to get out
 372         * or time out (1 second = 1000 ms)
 373         * -------------------------------- */
 374        for (tm=0; tm<1000; ++tm) {
 375                status=qsmcm->qsmcm_spcr1;
 376                if((status & 0x8000)==0)
 377                        break;
 378                udelay (1000);
 379        }
 380        if (tm >= 1000) {
 381                printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
 382        }
 383#ifdef  DEBUG
 384        printf ("\nspi_xfer: txbuf after xfer\n");
 385        memdump ((void *) qsmcm->qsmcm_tranram, 32);    /* dump of txbuf before transmit */
 386        printf ("spi_xfer: rxbuf after xfer\n");
 387        memdump ((void *) qsmcm->qsmcm_recram, 32);     /* dump of rxbuf after transmit */
 388        printf ("\nspi_xfer: commbuf after xfer\n");
 389        memdump ((void *) qsmcm->qsmcm_comdram, 32);    /* dump of txbuf before transmit */
 390        printf ("\n");
 391#endif
 392
 393        return count;
 394}
 395
 396#endif  /* CONFIG_SPI  */
 397