gonzui


Format: Advanced Search

mtkernel_3/device/i2c/sysdepend/tx03_m367/i2c_m367.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    Device Driver for micro T-Kernel for μT-Kernel 3.0
    4:  *
    5:  *    Copyright (C) 2020-2021 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2021/08.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: #include <sys/machine.h>
   15: #ifdef CPU_TMPM367FDFG
   16: 
   17: #include <tk/tkernel.h>
   18: #include "../../i2c.h"
   19: #include "../../../include/dev_def.h"
   20: #if DEV_IIC_ENABLE
   21: /*
   22:  *      i2c_m367.c
   23:   *     I2C device driver
   24:  *      System-dependent definition for TX03_M367
   25:  */
   26: 
   27: /*----------------------------------------------------------------------
   28:  * Device register base address
   29: */
   30: const LOCAL UW ba[DEV_I2C_UNITNM] = { I2C0_BASE, I2C1_BASE, I2C2_BASE };
   31: 
   32: /*----------------------------------------------------------------------
   33:  * Device initialization value
   34: */
   35: const LOCAL struct {
   36:         TMO    timout;            // I2C timeout time
   37:         PRI    intpri;            // Interrupt priority
   38:         UW     sck;                // Frequency selection
   39: } ll_devinit[DEV_I2C_UNITNM] = {
   40:         {      /* SBI0 */
   41:                 .timout               = DEVCNF_I2C0_TMO,
   42:                 .intpri               = DEVCNF_I2C0_INTPRI,
   43:                 .sck          = DEVCNF_I2C0_SCK,
   44:         },
   45:         {      /* SBI1 */
   46:                 .timout               = DEVCNF_I2C1_TMO,
   47:                 .intpri               = DEVCNF_I2C1_INTPRI,
   48:                 .sck          = DEVCNF_I2C1_SCK,
   49:         },
   50:         {      /* SBI2 */
   51:                 .timout               = DEVCNF_I2C2_TMO,
   52:                 .intpri               = DEVCNF_I2C2_INTPRI,
   53:                 .sck          = DEVCNF_I2C2_SCK,
   54:         },
   55: };
   56: 
   57: /*----------------------------------------------------------------------
   58:  * Device control data
   59: */
   60: typedef struct {
   61:         ID     wait_tskid; /* Wait Task ID */
   62:         UW     state;              /* Operating state */
   63:         UW     sadr;               /* Slave address */
   64:         ER     ioerr;              /* Communication error */
   65:         UW     sdat_num;   /* Number of send data */
   66:         UW     rdat_num;   /* Number of receive data */
   67:         UB     *sbuf;              /* Send buffer */
   68:         UB     *rbuf;              /* Receive buffer */
   69: } T_I2C_LLDCB;
   70: LOCAL T_I2C_LLDCB       ll_devcb[DEV_I2C_UNITNM];
   71: 
   72: 
   73: /*-------------------------------------------------------
   74:  * Interrupt handler
   75:  *-------------------------------------------------------
   76:  */
   77: LOCAL void i2c_inthdr( UINT intno )
   78: {
   79:         T_I2C_LLDCB    *p_cb;
   80:         UW             sbisr;
   81:         INT            unit;
   82: 
   83:         for ( unit = 0; unit < DEV_I2C_UNITNM; unit++ ) {
   84:                 if ( INTNO_INTSBI(unit) == intno ) {
   85:                         p_cb = &ll_devcb[unit];
   86:                         break;
   87:                 }
   88:         }
   89:         if(unit >= DEV_I2C_UNITNM) return;
   90: 
   91:         sbisr = in_w(ba[unit] + I2C_SBIxSR);
   92:         if ( (sbisr & I2C_SBIxSR_AL) != 0 ) {
   93:                 /* Communication error */
   94:                 p_cb->ioerr = E_IO;
   95:                 goto stop;
   96:         }
   97: 
   98:         switch( p_cb->state ) {
   99:         case I2C_STS_RECV | I2C_STS_TOP:
  100:                 if(p_cb->rdat_num == 1) {
  101:                         out_w(ba[unit] + I2C_SBIxCR1, 
  102:                                         I2C_SBIxCR1_INIT & ~I2C_SBIxCR1_ACK);
  103:                 }
  104:                 in_w(ba[unit] + I2C_SBIxDBR);
  105:                 p_cb->state = I2C_STS_RECV;
  106:                 break;
  107: 
  108:         case I2C_STS_RECV:
  109:                 if(p_cb->rdat_num == 1) {
  110:                         out_w(ba[unit] + I2C_SBIxCR1, 
  111:                                         I2C_SBIxCR1_INIT & ~I2C_SBIxCR1_ACK);
  112:                 }
  113:                 *(p_cb->rbuf++) = (UB)(in_w(ba[unit] + I2C_SBIxDBR) & 0xff);
  114:                 if(--(p_cb->rdat_num) <= 0) {
  115:                         p_cb->state = I2C_STS_STOP;
  116:                 }
  117:                 break;
  118:         
  119:         case I2C_STS_SEND:
  120:                 if ( (sbisr & I2C_SBIxSR_LRB) != 0 ) {
  121:                         p_cb->ioerr = 1; /* Interruption by NAK */
  122:                         goto stop;
  123:                 }
  124: 
  125:                 out_w(ba[unit] + I2C_SBIxDBR, *p_cb->sbuf++);
  126:                 if(--(p_cb->sdat_num) <= 0) {
  127:                         if(p_cb->rdat_num == 0) {
  128:                                 p_cb->state = I2C_STS_STOP;
  129:                         } else {
  130:                                 p_cb->state = I2C_STS_RESTART;
  131:                         }
  132:                 }
  133:                 break;
  134:         
  135:         case I2C_STS_RESTART:
  136:                 out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_RESTART);
  137:                 if(p_cb->wait_tskid) {
  138:                         tk_wup_tsk(p_cb->wait_tskid);
  139:                         p_cb->wait_tskid = 0;
  140:                 }
  141:                 break;
  142: 
  143:         case I2C_STS_STOP:
  144:         stop:
  145:                 out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_STOP);
  146:                 if(p_cb->wait_tskid) {
  147:                         tk_wup_tsk(p_cb->wait_tskid);
  148:                         p_cb->wait_tskid = 0;
  149:                 }
  150:                 break;
  151:         }
  152: }
  153: 
  154: /*----------------------------------------------------------------------
  155:  * Waiting for status change
  156:  */
  157: LOCAL void i2c_wait_status( T_I2C_LLDCB *p_cb, INT unit, UW mask, UW value )
  158: {
  159:         _UW    t = CLOCK_fc;      /* Timeout value */
  160: 
  161:         while ( p_cb->ioerr == E_OK ) {
  162:                 if ( (in_w(ba[unit] + I2C_SBIxSR) & mask) == value ) break;
  163:                 if ( --t == 0 ) p_cb->ioerr = E_TMOUT;
  164:         }
  165:         return;
  166: }
  167: 
  168: /*----------------------------------------------------------------------
  169:  * Execution of communication
  170:  */
  171: LOCAL ER i2c_trans(INT unit, T_I2C_LLDCB *p_cb)
  172: {
  173:         UINT           imask;
  174:         ER             err;
  175: 
  176:         p_cb->ioerr            = E_OK;
  177:         p_cb->wait_tskid       = 0;
  178: 
  179:         while ((err = p_cb->ioerr) == E_OK ) {
  180: 
  181:                 switch ( p_cb->state ) {
  182:                   case I2C_STS_RESTART:
  183:                         i2c_wait_status(p_cb, unit, I2C_SBIxSR_BB, 0);
  184:                         i2c_wait_status(p_cb, unit, I2C_SBIxSR_LRB, I2C_SBIxSR_LRB);
  185:                         WaitUsec(5);
  186:                         /* no break */
  187: 
  188:                   case I2C_STS_START:
  189:                         DI(imask);
  190:                         out_w(ba[unit] + I2C_SBIxCR1, I2C_SBIxCR1_INIT);
  191:                         if(p_cb->sdat_num > 0 ) {    /* Send */
  192:                                 out_w(ba[unit] + I2C_SBIxDBR, p_cb->sadr);
  193:                                 p_cb->state = I2C_STS_SEND;
  194:                         } else {                     /* Receive */
  195:                                 out_w(ba[unit] + I2C_SBIxDBR, (p_cb->sadr|1));
  196:                                 p_cb->state = I2C_STS_RECV | I2C_STS_TOP;
  197:                         }
  198:                         out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_START);
  199:                         EI(imask);
  200:                         break;
  201: 
  202:                   case I2C_STS_STOP:
  203:                         i2c_wait_status(p_cb, unit, I2C_SBIxSR_BB, 0);
  204:                         break;
  205:                 }
  206:                 if ( (err = p_cb->ioerr) != E_OK || p_cb->state == I2C_STS_STOP ) break;
  207: 
  208:                 p_cb->wait_tskid = tk_get_tid();
  209:                 err = tk_slp_tsk(ll_devinit[unit].timout);
  210:                 if ( err < E_OK ) break;
  211:         }
  212: 
  213:         /* Communication stop */
  214:         DI(imask);
  215:         out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_STOP);
  216:         EI(imask);
  217: 
  218:         return err;
  219: }
  220: 
  221: /*----------------------------------------------------------------------
  222:  * Set communication parameters
  223:  */
  224: Inline void set_com_start(UW unit, UW sadr, UW sdat_num, UW rdat_num, UB *sbuf, UB *rbuf)
  225: {
  226:         ll_devcb[unit].state   = I2C_STS_START;
  227:         ll_devcb[unit].sadr    = sadr<<1; /* Slave address */
  228:         ll_devcb[unit].sdat_num        = sdat_num;    /* Number of send data */
  229:         ll_devcb[unit].rdat_num        = rdat_num;    /* Number of receive data */
  230:         ll_devcb[unit].sbuf    = sbuf;            /* Send buffer */
  231:         ll_devcb[unit].rbuf    = rbuf;            /* Receive buffer */
  232: }
  233: 
  234: 
  235: /*----------------------------------------------------------------------
  236:  * Low level device control
  237:  */
  238: EXPORT W dev_i2c_llctl( UW unit, INT cmd, UW p1, UW p2, UW *pp)
  239: {
  240:         T_I2C_EXEC     *p_ex;
  241:         ER             err        = E_OK;
  242: 
  243:         switch(cmd) {
  244:         case LLD_I2C_OPEN:
  245:                 /* I2C Device reset */
  246:                 out_w(ba[unit] + I2C_SBIxCR0, I2C_SBIxCR0_SBIEN);
  247:                 out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_SBIM_I2C | I2C_SBIxCR2_SWRST(2));
  248:                 out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_SBIM_I2C | I2C_SBIxCR2_SWRST(1));
  249:                 while ( (in_w(ba[unit] + I2C_SBIxCR1) & I2C_SBIxCR1_SWRMON) == 0 );
  250: 
  251:                 /* I2C Initial setting */
  252:                 out_w(ba[unit] + I2C_SBIxCR1, I2C_SBIxCR1_INIT | ll_devinit[unit].sck);
  253:                 out_w(ba[unit] + I2C_SBIxCR2, I2C_SBIxCR2_STOP);
  254:                 out_w(ba[unit] + I2C_SBIxBR0, 0);
  255: 
  256:                 EnableInt(INTNO_INTSBI(unit), ll_devinit[unit].intpri);
  257:                 break;
  258: 
  259:         case LLD_I2C_CLOSE:
  260:                 /* Disable I2C interrupt */
  261:                 DisableInt(INTNO_INTSBI(unit));
  262:                 break;
  263: 
  264:         case LLD_I2C_READ:
  265:                 set_com_start( unit, p1, 0, p2, NULL, (UB*)pp);
  266:                 err = i2c_trans(unit, &ll_devcb[unit]);
  267:                 if(err >= E_OK) err = p1 - ll_devcb[unit].sdat_num;
  268:                 break;
  269: 
  270:         case LLD_I2C_WRITE:
  271:                 set_com_start( unit, p1, p2, 0, (UB*)pp, NULL);
  272:                 err = i2c_trans(unit, &ll_devcb[unit]);
  273:                 if(err >= E_OK) err = p1 - ll_devcb[unit].sdat_num;
  274:                 break;
  275: 
  276:         case LLD_I2C_EXEC:
  277:                 p_ex = (T_I2C_EXEC*)pp;
  278:                 set_com_start( unit, p_ex->sadr, p_ex->snd_size, p_ex->rcv_size, p_ex->snd_data, p_ex->rcv_data);
  279:                 err = i2c_trans(unit, &ll_devcb[unit]);
  280:                 if(err >= E_OK) err = p_ex->snd_size + p_ex->rcv_size;
  281:                 break;
  282:         }
  283:         
  284:         return (W)err;
  285: }
  286: 
  287: /*----------------------------------------------------------------------
  288:  * Device initialization
  289:  */
  290: EXPORT ER dev_i2c_llinit( T_I2C_DCB *p_dcb)
  291: {
  292:         const T_DINT   dint = {
  293:                 .intatr       = TA_HLNG,
  294:                 .inthdr       = i2c_inthdr,
  295:         };
  296:         ER     err;
  297: 
  298:         /* Interrupt handler definition */
  299:         err = tk_def_int(INTNO_INTSBI(p_dcb->unit), &dint);
  300: 
  301:         return err;
  302: }
  303: 
  304: #endif          /* DEV_IIC_ENABLE */
  305: #endif          /* CPU_TMPM367FDFG */