gonzui


Format: Advanced Search

tkernel_2/lib/libtk/src/sysdepend/tef_em1d/ptimer.cbare sourcepermlink (0.05 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 2014/07/14.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:  *      ptimer.c
   18:  *
   19:  *      Physical timer
   20:  */
   21: 
   22: #include <basic.h>
   23: #include <tk/tkernel.h>
   24: #include <tk/ptimer.h>
   25: 
   26: /*
   27:  * List of timers
   28:  */
   29: LOCAL struct timerlist {
   30:         INT    base;              /* base address of timer registers  */
   31:         INTVEC irq;            /* interrupt number */
   32:         UINT   mode;             /* operation mode */
   33:         FP     hdr;                /* user-defined interrupt handler */
   34:         void*  exinf;           /* user-defined exntended information */
   35: } TimerList[] = {
   36:         { 0xc0000100,  IV_IRQ(55) },    /* TI1 */
   37:         { 0xc0000200,  IV_IRQ(56) },    /* TI2 */
   38:         { 0xc0000300,  IV_IRQ(57) },    /* TI3 */
   39:         { 0xc0002000,  IV_IRQ(34) },    /* TG0 */
   40:         { 0xc0002100,  IV_IRQ(35) },    /* TG1 */
   41:         { 0xc0002200,  IV_IRQ(36) },    /* TG2 */
   42:         { 0xc0002300,  IV_IRQ(44) },    /* TG3 */
   43:         { 0xc0002400,  IV_IRQ(45) },    /* TG4 */
   44:         { 0xc0002500,  IV_IRQ(46) },    /* TG5 */
   45:         { 0xc0001000,  IV_IRQ(58) },    /* TW0 */
   46:         { 0xc0001100,  IV_IRQ(59) },    /* TW1 */
   47:         { 0xc0001200,  IV_IRQ(60) },    /* TW2 */
   48:         { 0xc0001300,  IV_IRQ(61) }     /* TW3 */
   49: };
   50: 
   51: #define N_TIMER         ( sizeof(TimerList) / sizeof(TimerList[0]) )
   52: 
   53: /*
   54:  * Timer
   55:  *      register size W
   56:  */
   57: #define TI(pn, ofs)     ( TimerList[pn].base + (ofs) )
   58: 
   59: #define TI_OP(pn)       TI(pn, 0x00)  /* RW timer operation */
   60: #define TI_CLR(pn)      TI(pn, 0x04) /* -W clear timer */
   61: #define TI_SET(pn)      TI(pn, 0x08) /* RW set timer value */
   62: #define TI_RCR(pn)      TI(pn, 0x0c) /* R- current counter */
   63: #define TI_SCLR(pn)     TI(pn, 0x14)        /* RW watch out for setting timer value */
   64: 
   65: #define TO_EN           0x0004           /* enable TOUT */
   66: #define TSTART          0x0002          /* start counting */
   67: #define TM_EN           0x0001           /* enable timer */
   68: 
   69: #define TCR_CLR         0x0002         /* clear counter */
   70: 
   71: #define TM_SCLR         0x0001         /* warch out for setting timer value */
   72: 
   73: /*
   74:  * Supply clock
   75:  *      register size W
   76:  */
   77: #define ASMU(n)         ( 0xc0110000 + (n) )
   78: 
   79: #define TI0TIN_SEL      ASMU(0x0138) /* set TI0/TW0 TIN */
   80: #define TI1TIN_SEL      ASMU(0x013c) /* set TI1/TW1 TIN */
   81: #define TI2TIN_SEL      ASMU(0x0140) /* set TI2/TW2 TIN */
   82: #define TI3TIN_SEL      ASMU(0x0144) /* set TI3/TW3 TIN */
   83: #define TGnTIN_SEL      ASMU(0x0148) /* set TG0-5   TIN */
   84: 
   85: #define DIVTIMTIN       ASMU(0x014c)  /* set timer clock divisor */
   86: #define GCLKCTRL3       ASMU(0x01cc)  /* set clock gate */
   87: #define GCLKCTRL3ENA    ASMU(0x01d0)       /* enable write */
   88: 
   89: #define TITIN_PLL3      0            /* PLL3 divided by DIVTIMTIN */
   90: #define TITIN_32768     1           /* 32.768 KHz */
   91: #define TITIN_32K       2             /* 32 KHz */
   92: 
   93: #define TIN_GCK(pn)     ( 2 << (pn) )       /* TIN gate */
   94: 
   95: /*
   96:  * Input clock
   97:  *      PLL3 divided by DIVTIMTIN
   98:  */
   99: #define PLL3_CLK        229376000      /* Hz */
  100: 
  101: #define D0(d)           ( (d) & 0x7 )            /* DIV0TIMTIN */
  102: #define D1(d)           ( ((d) >> 4) & 0xf )     /* DIV1TIMTIN */
  103: 
  104: #define TIN_CLK(d)      ( PLL3_CLK / ((1 << D0(d)) * (D1(d) + 1)) )
  105: 
  106: /* ------------------------------------------------------------------------ */
  107: 
  108: /*
  109:  * Initialize timer
  110:  */
  111: LOCAL void initialize_timer( void )
  112: {
  113:         UW     m;
  114: 
  115:         /* select clock */
  116:         out_w(TI0TIN_SEL, in_w(TI0TIN_SEL) & ~0x00030000);
  117:         out_w(TI1TIN_SEL, 0);
  118:         out_w(TI2TIN_SEL, 0);
  119:         out_w(TI3TIN_SEL, 0);
  120:         out_w(TGnTIN_SEL, 0);
  121: 
  122:         /* close clock gate */
  123:         m = 0x00003ffe;
  124:         out_w(GCLKCTRL3ENA, in_w(GCLKCTRL3ENA) | m);
  125:         out_w(GCLKCTRL3, in_w(GCLKCTRL3) & ~m);
  126: }
  127: 
  128: /*
  129:  * Check the physical timer number
  130:  */
  131: LOCAL INT CHK_PTMRNO( UINT ptmrno )
  132: {
  133:         static BOOL    init = FALSE;
  134:         UINT   imask;
  135: 
  136:         if ( (ptmrno < 1) || (ptmrno > N_TIMER) ) return E_PAR;
  137: 
  138:         if ( !init ) {
  139:                 DI(imask);
  140: 
  141:                 /* Initialize the timer on the first visit */
  142:                 if ( !init ) initialize_timer();
  143:                 init = TRUE;
  144: 
  145:                 EI(imask);
  146:         }
  147: 
  148:         return ptmrno - 1;
  149: }
  150: 
  151: /* ------------------------------------------------------------------------ */
  152: 
  153: /*
  154:  * Timer interrupt handler
  155:  */
  156: LOCAL void timer_inthdr( UINT dintno, void *sp )
  157: {
  158:         struct timerlist *tp;
  159:         INT    pn;
  160: 
  161:         for ( pn = 0; pn < N_TIMER; ++pn ) {
  162:                 tp = &TimerList[pn];
  163:                 if ( DINTNO(tp->irq) == dintno ) break;
  164:         }
  165:         if ( pn >= N_TIMER ) return;
  166: 
  167:         ClearInt(tp->irq);
  168: 
  169:         if ( tp->mode == TA_ALM_PTMR ) {
  170:                 /* stop counting */
  171:                 out_w(TI_OP(pn), 0);
  172: 
  173:                 /* stop clock */
  174:                 out_w(GCLKCTRL3, in_w(GCLKCTRL3) & ~TIN_GCK(pn));
  175:         }
  176: 
  177:         if ( tp->hdr != NULL ) {
  178:                 /* call user-defined interrupt handler */
  179:                 (*tp->hdr)(tp->exinf);
  180:         }
  181: }
  182: 
  183: /*
  184:  * Start physical timer
  185:  */
  186: EXPORT ER StartPhysicalTimer( UINT ptmrno, UW limit, UINT mode )
  187: {
  188:         INT    pn;
  189:         UINT   imask;
  190:         T_DINT dint;
  191:         ER     err;
  192: 
  193:         if ( (mode != TA_ALM_PTMR) && (mode != TA_CYC_PTMR) ) return E_PAR;
  194: 
  195:         /* setting below 2 is impossible ??? */
  196:         if ( limit <= 2 ) return E_PAR;
  197: 
  198:         pn = CHK_PTMRNO(ptmrno);
  199:         if ( pn < E_OK ) return pn;
  200: 
  201:         /* stop timer */
  202:         out_w(TI_OP(pn), 0);
  203: 
  204:         TimerList[pn].mode = mode;
  205: 
  206:         /* set up timer interrupt handler */
  207:         dint.intatr = TA_HLNG;
  208:         dint.inthdr = timer_inthdr;
  209:         err = tk_def_int(DINTNO(TimerList[pn].irq), &dint);
  210:         if ( err < E_OK ) return err;
  211: 
  212:         SetIntMode(TimerList[pn].irq, IM_ENA);
  213:         ClearInt(TimerList[pn].irq);
  214: 
  215:         DI(imask);
  216: 
  217:         /* start feeding clock */
  218:         out_w(GCLKCTRL3, in_w(GCLKCTRL3) | TIN_GCK(pn));
  219: 
  220:         /* enable timer */
  221:         out_w(TI_OP(pn), TM_EN);
  222:         while ( (in_w(TI_SCLR(pn)) & TM_SCLR) != 0 );
  223:         WaitUsec(1);
  224: 
  225:         /* set counter */
  226:         out_w(TI_SET(pn), limit);
  227: 
  228:         /* start counting */
  229:         out_w(TI_OP(pn), TO_EN|TSTART|TM_EN);
  230: 
  231:         EI(imask);
  232: 
  233:         /* enable timer interrupt */
  234:         EnableInt(TimerList[pn].irq);
  235: 
  236:         return E_OK;
  237: }
  238: 
  239: /*
  240:  * Stop physical timer
  241:  */
  242: EXPORT ER StopPhysicalTimer( UINT ptmrno )
  243: {
  244:         INT    pn;
  245:         UINT   imask;
  246: 
  247:         pn = CHK_PTMRNO(ptmrno);
  248:         if ( pn < E_OK ) return pn;
  249: 
  250:         /* Stop timer interrupt */
  251:         DisableInt(TimerList[pn].irq);
  252: 
  253:         DI(imask);
  254: 
  255:         /* Stop counting */
  256:         out_w(TI_OP(pn), in_w(TI_OP(pn)) & TM_EN);
  257: 
  258:         /* Stop clock */
  259:         out_w(GCLKCTRL3, in_w(GCLKCTRL3) & ~TIN_GCK(pn));
  260: 
  261:         EI(imask);
  262: 
  263:         return E_OK;
  264: }
  265: 
  266: /*
  267:  * Obtain the count of the physical timer
  268:  */
  269: EXPORT ER GetPhysicalTimerCount( UINT ptmrno, UW *p_count )
  270: {
  271:         INT    pn;
  272: 
  273:         pn = CHK_PTMRNO(ptmrno);
  274:         if ( pn < E_OK ) return pn;
  275: 
  276:         if ( (in_w(TI_OP(pn)) & TM_EN) == 0 ) {
  277:                 *p_count = 0;
  278:         } else {
  279:                 *p_count = in_w(TI_RCR(pn));
  280:         }
  281: 
  282:         return E_OK;
  283: }
  284: 
  285: /*
  286:  * Definition of physical timer handler
  287:  */
  288: EXPORT ER DefinePhysicalTimerHandler( UINT ptmrno, CONST T_DPTMR *pk_dptmr )
  289: {
  290:         INT    pn;
  291:         UINT   imask;
  292: 
  293:         pn = CHK_PTMRNO(ptmrno);
  294:         if ( pn < E_OK ) return pn;
  295: 
  296:         if ( pk_dptmr != NULL ) {
  297:                 if ( (pk_dptmr->ptmratr & ~(TA_ASM|TA_HLNG)) != 0 )
  298:                                                 return E_PAR;
  299: 
  300:                 DI(imask);
  301:                 TimerList[pn].exinf = pk_dptmr->exinf;
  302:                 TimerList[pn].hdr   = pk_dptmr->ptmrhdr;
  303:                 EI(imask);
  304:         } else {
  305:                 TimerList[pn].hdr   = NULL;
  306:         }
  307: 
  308:         return E_OK;
  309: }
  310: 
  311: /*
  312:  * Obtain the configuration information of physical timer
  313:  */
  314: EXPORT ER GetPhysicalTimerConfig( UINT ptmrno, T_RPTMR *pk_rptmr )
  315: {
  316:         INT    pn;
  317:         UW     d;
  318: 
  319:         pn = CHK_PTMRNO(ptmrno);
  320:         if ( pn < E_OK ) return pn;
  321: 
  322:         d = in_w(DIVTIMTIN);
  323: 
  324:         pk_rptmr->ptmrclk  = TIN_CLK(d);
  325:         pk_rptmr->maxcount = 0xffffffff;
  326:         pk_rptmr->defhdr   = TRUE;
  327: 
  328:         return E_OK;
  329: }