gonzui


Format: Advanced Search

tkernel_2/driver/tef_em1d/clk/src/em1d512_spi.cbare sourcepermlink (0.03 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2011/09/08.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:         em1d512_spi.c  SPI access (EM1-D512)
   18:  *
   19:  */
   20: 
   21: #include "clkdrv.h"
   22: #include <tk/util.h>
   23: 
   24: #ifdef  DEBUG
   25: #define DP(x)   printf x
   26: #else
   27: #define DP(x)   /* do nothing */
   28: #endif
   29: 
   30: #define SPIMAX          3
   31: LOCAL   FastLock  SPILock[SPIMAX];
   32: LOCAL   ID                SPITskID[SPIMAX];
   33: LOCAL   const UW  SPIBase[SPIMAX] = {0xc0120000, 0xc0130000, 0x40130000};
   34: LOCAL   const UW  SPIVec[SPIMAX] = {IV_IRQ(24), IV_IRQ(25), IV_IRQ(42)};
   35: LOCAL   const UW  SPIPol[SPIMAX] = {0x009a, 0x0000, 0x0003};
   36: LOCAL   const UW  SPIMode[SPIMAX] = {0x2700, 0x0700, 0x2700};
   37: 
   38: #define SPn_MODE(n)             (SPIBase[n] + 0x0000)
   39: #define SPn_POL(n)              (SPIBase[n] + 0x0004)
   40: #define SPn_CONTROL(n)          (SPIBase[n] + 0x0008)
   41: #define SPn_TX_DATA(n)          (SPIBase[n] + 0x0010)
   42: #define SPn_RX_DATA(n)          (SPIBase[n] + 0x0014)
   43: #define SPn_STATUS(n)           (SPIBase[n] + 0x0018)
   44: #define SPn_RAW_STATUS(n)       (SPIBase[n] + 0x001c)
   45: #define SPn_ENSET(n)            (SPIBase[n] + 0x0020)
   46: #define SPn_ENCLR(n)            (SPIBase[n] + 0x0024)
   47: #define SPn_FFCLR(n)            (SPIBase[n] + 0x0028)
   48: #define SPn_CONTROL2(n)         (SPIBase[n] + 0x0034)
   49: #define SPn_TIECS(n)            (SPIBase[n] + 0x0038)
   50: 
   51: #define TIMEOUT                 10    // msec
   52: 
   53: /* interrupt handler */
   54: LOCAL   void      spi_inthdr(INTVEC vec)
   55: {
   56:         W      i;
   57: 
   58:         for (i = 0; i < SPIMAX; i++) {
   59:                 if (vec == SPIVec[i]) {
   60:                         out_w(SPn_FFCLR(i), ~0);
   61:                         tk_wup_tsk(SPITskID[i]);
   62:                         break;
   63:                 }
   64:         }
   65: 
   66:         return;
   67: }
   68: 
   69: /* wait for interrupt */
   70: LOCAL   ER        wait_int(void)
   71: {
   72:         return tk_slp_tsk(TIMEOUT);
   73: }
   74: 
   75: /* SPI initialization */
   76: LOCAL   void      spi_init(W ch)
   77: {
   78:         out_w(SPn_MODE(ch), SPIMode[ch]);
   79:         out_w(SPn_TIECS(ch), 0x000f);          // CS: control by SPn_POL
   80:         out_w(SPn_POL(ch), SPIPol[ch]);
   81:         out_w(SPn_ENCLR(ch), ~0);              // interrupt disable
   82: 
   83:         out_w(SPn_CONTROL(ch), 0x0100);                // starting reset
   84:         WaitUsec(10);
   85:         out_w(SPn_CONTROL(ch), 0x0000);                // releasing reset
   86:         out_w(SPn_CONTROL2(ch), 0x0000);
   87: 
   88:         out_w(SPn_FFCLR(ch), ~0);
   89:         out_w(SPn_ENSET(ch), 0x0004);          // interrupt enable
   90: 
   91:         return;
   92: }
   93: 
   94: /* control CS line */
   95: LOCAL   void      spi_cs(W ch, W cs, BOOL enable)
   96: {
   97:         WaitNsec(200);
   98:         out_w(SPn_POL(ch), SPIPol[ch] ^ (enable ? (1 << (cs * 3)) : 0));
   99:         WaitNsec(200);
  100: 
  101:         return;
  102: }
  103: 
  104: /* SPI send/receive */
  105: EXPORT  ER       SPIXfer(W ch_cs, UB *xmit, UB *recv, W len)
  106: {
  107:         ER     er;
  108:         W      i, ch, cs;
  109: 
  110:         /* parameter check */
  111:         ch = (ch_cs >> 8) & 0xff;
  112:         cs = (ch_cs >> 0) & 0xff;
  113:         if (ch > 2 || cs > 3) {
  114:                 er = E_PAR;
  115:                 goto fin0;
  116:         }
  117: 
  118:         Lock(&SPILock[ch]);
  119:         SPITskID[ch] = tk_get_tid();
  120:         tk_can_wup(TSK_SELF);
  121: 
  122:         spi_cs(ch, cs, TRUE);
  123: 
  124:         /* send / receive */
  125:         for (i = 0; i < len; i++) {
  126:                 if (xmit != NULL) {
  127:                         out_w(SPn_TX_DATA(ch), *xmit++);
  128:                 } else {
  129:                         out_w(SPn_TX_DATA(ch), ~0);
  130:                 }
  131: 
  132:                 out_w(SPn_CONTROL(ch), 0x000d);
  133:                 er = wait_int();
  134:                 if (er < E_OK) {
  135:                         DP(("spi_txrx: wait_int %d\n", er));
  136:                         spi_init(ch);
  137:                         goto fin1;
  138:                 }
  139: 
  140:                 if (recv != NULL) {
  141:                         *recv++ = in_w(SPn_RX_DATA(ch));
  142:                 } else {
  143:                         in_w(SPn_RX_DATA(ch));
  144:                 }
  145:         }
  146: 
  147:         er = E_OK;
  148: 
  149: fin1:
  150:         spi_cs(ch, cs, FALSE);
  151:         Unlock(&SPILock[ch]);
  152: fin0:
  153:         return er;
  154: }
  155: 
  156: /* SPI driver prolog ends */
  157: EXPORT  ER       SPIup(W ch, BOOL start)
  158: {
  159: #define SPITag  "SPI_"
  160: 
  161:         ER     er;
  162:         T_DINT dint;
  163: 
  164:         /* check channel number */
  165:         if (ch < 0 || ch > 2) {
  166:                 er = E_PAR;
  167:                 goto fin0;
  168:         }
  169: 
  170:         /* epilog processing */
  171:         if (!start) {
  172:                 er = E_OK;
  173:                 goto fin2;
  174:         }
  175: 
  176:         /* creating a lock for exclusive control */
  177:         er = CreateLock(&SPILock[ch], SPITag);
  178:         if (er < E_OK) {
  179:                 DP(("SPIup: CreateLock %d\n", er));
  180:                 goto fin0;
  181:         }
  182: 
  183:         /* register interrupt handler */
  184:         dint.intatr = TA_HLNG;
  185:         dint.inthdr = spi_inthdr;
  186:         er = tk_def_int(SPIVec[ch], &dint);
  187:         if (er < E_OK) {
  188:                 DP(("SPIup: tk_def_int %d\n", er));
  189:                 goto fin1;
  190:         }
  191: 
  192:         /* clear interrupt and permit it again */
  193:         spi_init(ch);
  194:         SetIntMode(SPIVec[ch], IM_ENA);
  195:         EnableInt(SPIVec[ch]);
  196: 
  197:         er = E_OK;
  198:         goto fin0;
  199: 
  200: fin2:
  201:         DisableInt(SPIVec[ch]);
  202:         SetIntMode(SPIVec[ch], IM_DIS);
  203:         tk_def_int(SPIVec[ch], NULL);
  204: fin1:
  205:         DeleteLock(&SPILock[ch]);
  206: fin0:
  207:         return er;
  208: }