gonzui


Format: Advanced Search

tkernel_2/lib/libtk/src/sysdepend/tef_em1d/int.cbare sourcepermlink (0.04 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 TRON Forum(http://www.tron.org/) at 2015/06/01.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: 
   15: /*
   16:  *      int_em1d512.c
   17:  *
   18:  *      EM1-D512 interrupt controller management
   19:  *
   20:  *      intvec passed to the functions for interrupt controller must
   21:  *      be within the valid ranges of IRQ and GPIO interrupt.
   22:  *      If a value outside the valid range is passed, the subsequent
   23:  *      correct behavior of the system is not guaranteed.
   24:  */
   25: 
   26: #include <basic.h>
   27: #include <tk/syslib.h>
   28: #include <tk/sysdef.h>
   29: 
   30: /*
   31:  * Interrupt controller
   32:  *      register size W
   33:  */
   34: #define AINT(n)         ( 0xc0020000 + (n) )   /* ACPU Interrupt */
   35: #define SINT(n)         ( 0xcc010000 + (n) )   /* ACPU Secure Interrupt */
   36: 
   37: #define IT0_IEN0        AINT(0x0000)   /* RW ACPU enable interrupt 0 */
   38: #define IT0_IEN1        AINT(0x0004)   /* RW ACPU enable interrupt 1 */
   39: #define IT0_IEN2        AINT(0x0100)   /* RW ACPU enable interrupt 2 */
   40: #define IT0_IDS0        AINT(0x0008)   /* -W ACPU disable interrupt 0 */
   41: #define IT0_IDS1        AINT(0x000C)   /* -W ACPU disable interrupt 1 */
   42: #define IT0_IDS2        AINT(0x0104)   /* -W ACPU disable interrupt 2 */
   43: #define IT0_RAW0        AINT(0x0010)   /* R- ACPU interrupt Raw status 0 */
   44: #define IT0_RAW1        AINT(0x0014)   /* R- ACPU interrupt Raw status 1 */
   45: #define IT0_RAW2        AINT(0x0108)   /* R- ACPU interrupt Raw status 2 */
   46: #define IT0_MST0        AINT(0x0018)   /* R- ACPU interrupt mask / status 0 */
   47: #define IT0_MST1        AINT(0x001C)   /* R- ACPU interrupt mask / status 1 */
   48: #define IT0_MST2        AINT(0x010C)   /* R- ACPU interrupt mask / status 2 */
   49: #define IT0_IIR         AINT(0x0024)   /* -W ACPU interrupt status / reset */
   50: #define IT0_FIE         AINT(0x0080)   /* RW ACPU FIQ enable interrupt */
   51: #define IT0_FID         AINT(0x0084)   /* -W ACPU FIQ disable interrupt */
   52: #define IT_PINV_SET0    AINT(0x0300)       /* RW enable inverted logic for interrupt input 0 */
   53: #define IT_PINV_SET1    AINT(0x0304)       /* RW enable inverted logic for interrupt input 1 */
   54: #define IT_PINV_SET2    AINT(0x0308)       /* RW enable inverted logic for interrupt input 2 */
   55: #define IT_PINV_CLR0    AINT(0x0310)       /* -W disable inverted logic for interrupt input 0 */
   56: #define IT_PINV_CLR1    AINT(0x0314)       /* -W disable inverted logic for interrupt input 1 */
   57: #define IT_PINV_CLR2    AINT(0x0318)       /* -W disable inverted logic for interrupt input 2 */
   58: #define IT_LIIS         AINT(0x0320)   /* -W internal interrupt status set */
   59: #define IT_LIIR         AINT(0x0324)   /* -W internal interrupt status reset */
   60: 
   61: #define IT0_IENS0       SINT(0xE200)  /* RW ACPU Secure enable interrupt 0 */
   62: #define IT0_IENS1       SINT(0xE204)  /* RW ACPU Secure enable interrupt 1 */
   63: #define IT0_IENS2       SINT(0xE208)  /* RW ACPU Secure enable interrupt 2 */
   64: #define IT0_IDSS0       SINT(0xE20C)  /* -W ACPU Secure disable interrupt 0 */
   65: #define IT0_IDSS1       SINT(0xE210)  /* -W ACPU Secure disable interrupt 1 */
   66: #define IT0_IDSS2       SINT(0xE214)  /* -W ACPU Secure disable interrupt 2 */
   67: 
   68: LOCAL const struct aint_reg {
   69:         UINT   IT0_IEN;  /* RW ACPU enable interrupt state */
   70:         UINT   IT0_IDS;  /* -W ACPU disable interrupt */
   71:         UINT   IT0_RAW;  /* R- ACPU interrupt Raw status */
   72:         UINT   IT0_MST;  /* R- ACPU interrupt mask / status */
   73:         UINT   IT_PINV_SET;      /* RW enable inverted logic for interrupt input */
   74:         UINT   IT_PINV_CLR;      /* -W disable inverted logic for interrupt input */
   75:         UINT   IT0_IENS; /* RW ACPU Secure enable interrupt state */
   76:         UINT   IT0_IDSS; /* -W ACPU Secure disable interrupt */
   77: } AINT[3] = {
   78:         { IT0_IEN0, IT0_IDS0, IT0_RAW0, IT0_MST0, IT_PINV_SET0, IT_PINV_CLR0,
   79:           IT0_IENS0, IT0_IDSS0 },
   80:         { IT0_IEN1, IT0_IDS1, IT0_RAW1, IT0_MST1, IT_PINV_SET1, IT_PINV_CLR1,
   81:           IT0_IENS1, IT0_IDSS1 },
   82:         { IT0_IEN2, IT0_IDS2, IT0_RAW2, IT0_MST2, IT_PINV_SET2, IT_PINV_CLR2,
   83:           IT0_IENS2, IT0_IDSS2 }
   84: };
   85: 
   86: /*
   87:  * GIO Interrupt
   88:  *      register size W
   89:  */
   90: #define GIO(b, n)       ( (b) + (n) )         /* General I/O */
   91: #define _L              ( 0xc0050000 + 0x000 )
   92: #define _H              ( 0xc0050000 + 0x040 )
   93: #define _HH             ( 0xc0050000 + 0x080 )
   94: #define _HHH            ( 0xc0050000 + 0x200 )
   95: 
   96: #define GIO_IIA(b)      GIO(b,0x0014)        /* RW enable interrupt status */
   97: #define GIO_IEN(b)      GIO(b,0x0018)        /* -W enable interrupt */
   98: #define GIO_IDS(b)      GIO(b,0x001C)        /* -W disable interrupt */
   99: #define GIO_IIM(b)      GIO(b,0x001C)        /* R- enable interrupt state */
  100: #define GIO_RAW(b)      GIO(b,0x0020)        /* R- interrupt Raw status */
  101: #define GIO_MST(b)      GIO(b,0x0024)        /* R- interrupt mask / status */
  102: #define GIO_IIR(b)      GIO(b,0x0028)        /* -W reset the cause of interrupt */
  103: #define GIO_GSW(b)      GIO(b,0x003C)        /* RW connected to GIO_INT_FIQ pin */
  104: #define GIO_IDT(n,b)    GIO(b,0x0100+(n)*4) /* RW interrupt detection method 0-3 */
  105: #define GIO_RAWBL(b)    GIO(b,0x0110)      /* R- edge-triggered interrupt status L */
  106: #define GIO_RAWBH(b)    GIO(b,0x0114)      /* R- edge-triggered interrupt status H */
  107: #define GIO_IRBL(b)     GIO(b,0x0118)       /* -W clear the cause of edge-triggered interrupt L */
  108: #define GIO_IRBH(b)     GIO(b,0x011C)       /* -W clear the cause of edge-triggered interrupt H */
  109: 
  110: LOCAL const UINT        GIOB[4] = { _L, _H, _HH, _HHH };
  111: 
  112: #define AINTNO(intvec)  ( ((intvec) - IV_IRQ(0)) / 32 )          /* AINT number */
  113: #define GIONO(intvec)   ( ((intvec) - IV_GPIO(0)) / 32 )  /* GIO number */
  114: #define BITNO(intvec)   ( ((intvec) - IV_IRQ(0)) % 32 )           /* bit number */
  115: 
  116: /* ------------------------------------------------------------------------ */
  117: 
  118: /*
  119:  * Disable / Enable interrupt
  120:  */
  121: Inline UW _disint( void )
  122: {
  123:         UW     imask;
  124:         Asm("  mrs      %0, cpsr     \n"
  125:         "      orr  ip, %0, %1       \n"
  126:         "      msr  cpsr_xc, ip      "
  127:                 : "=r"(imask)
  128:                 : "i"(PSR_DI)
  129:                 : "ip" );
  130:         return imask;
  131: }
  132: Inline void _enaint( UW imask )
  133: {
  134:         Asm("msr cpsr_xc, %0":: "r"(imask));
  135: }
  136: #define _DI(imask)      ( imask = _disint() )
  137: #define _EI(imask)      ( _enaint(imask) )
  138: 
  139: /*
  140:  * Set interrupt mode.
  141:  *      Set the interrupt mode specified by `intvec' to the mode given
  142:  *      by `mode'. If an illegal mode is given, subsequent correct behavior
  143:  *      of the system is not guaranteed.
  144:  *
  145:  *      The case of IRQ
  146:  *      mode := IM_ENA | IM_INV
  147:  *      or   IM_DIS
  148:  *
  149:  *      The case of GPIO
  150:  *      mode := IM_ENA | IM_LEVEL | (IM_HI || IM_LOW) | IM_ASYN
  151:  *       or IM_ENA | IM_EDGE | (IM_HI || IM_LOW || IM_BOTH) | IM_ASYN
  152:  *       or IM_DIS
  153:  *
  154:  *      If IM_ENA is specified, the mode setting is done, and
  155:  *      interrupt is disabled (DisableInt) and the interrupt pin is
  156:  *      asserted.
  157:  *      If IM_DIS is specified, interrupt pin is disasserted.
  158:  *      disasserted interrupt pin doesn't generate interrupt even if
  159:  *      it is enabled (EnabledInt).
  160:  *      In the initial state, pins are dis-asserted (IM_DIS).
  161:  *
  162:  *      The initial status of the following interrupt controllers
  163:  *      that manage GPIO interrupt is such that
  164:  *      as if IM_ENA had been specified and interrupts are enabled
  165:  *      (EnableInt).
  166:  *
  167:  *              IRQ26       GIO6 Interrupt (GPIO port  96--111)
  168:  *              IRQ27       GIO7 Interrupt (GPIO port 112--127)
  169:  *              IRQ50       GIO0 Interrupt (GPIO port   0-- 15)
  170:  *              IRQ51       GIO1 Interrupt (GPIO port  16-- 31)
  171:  *              IRQ52       GIO2 Interrupt (GPIO port  32-- 47)
  172:  *              IRQ53       GIO3 Interrupt (GPIO port  48-- 63)
  173:  *              IRQ79       GIO4 Interrupt (GPIO port  64-- 79)
  174:  *              IRQ80       GIO5 Interrupt (GPIO port  80-- 95)
  175:  */
  176: EXPORT void SetIntMode( INTVEC intvec, UINT mode )
  177: {
  178:         UW     m = 1 << BITNO(intvec);
  179:         UINT   imask;
  180: 
  181:         if ( intvec < IV_GPIO(0) ) {
  182:                 /* IRQ */
  183:                 const struct aint_reg *r = AINT + AINTNO(intvec);
  184: 
  185:                 out_w(r->IT0_IDS,  m);        /* disable interrupt */
  186:                 out_w(r->IT0_IDSS, m);        /* disassert interrupt pin */
  187:                 if ( (mode & IM_ENA) == 0 ) return;
  188: 
  189:                 if ( (mode & IM_INV) == 0 ) out_w(r->IT_PINV_CLR, m);
  190:                 else                      out_w(r->IT_PINV_SET, m);
  191: 
  192:                 out_w(r->IT0_IENS, m);        /* assert interrupt pin */
  193:         } else {
  194:                 /* GPIO */
  195:                 UINT  gb = GIOB[GIONO(intvec)];
  196:                 UINT  n;
  197:                 UW    mm, mv;
  198: 
  199:                 _DI(imask);
  200:                 out_w(GIO_IDS(gb), m);                            /* disable interrupt */
  201:                 out_w(GIO_IIA(gb), in_w(GIO_IIA(gb)) & ~m); /* disassert interrupt pin */
  202:                 _EI(imask);
  203:                 if ( (mode & IM_ENA) == 0 ) return;
  204: 
  205:                 n = (intvec - IV_GPIO(0)) % 8 * 4;
  206:                 mm = 0xf << n;
  207:                 mv = ((mode >> 8) & 0xf) << n;
  208:                 n = (intvec - IV_GPIO(0)) % 32 / 8;
  209:                 _DI(imask);
  210:                 out_w(GIO_IDT(n, gb), (in_w(GIO_IDT(n, gb)) & ~mm) | mv);
  211:                 out_w(GIO_IIA(gb), in_w(GIO_IIA(gb)) | m); /* assert interrupt pin */
  212:                 _EI(imask);
  213:         }
  214: }
  215: 
  216: /*
  217:  * Enable interrupt
  218:  *      enable interrupt specified by `intvec'
  219:  */
  220: EXPORT void EnableInt( INTVEC intvec )
  221: {
  222:         UW     m = 1 << BITNO(intvec);
  223: 
  224:         if ( intvec < IV_GPIO(0) ) {
  225:                 /* IRQ */
  226:                 const struct aint_reg *r = AINT + AINTNO(intvec);
  227:                 out_w(r->IT0_IEN, m);
  228:         } else {
  229:                 /* GPIO */
  230:                 UINT  gb = GIOB[GIONO(intvec)];
  231:                 out_w(GIO_IEN(gb), m);
  232:         }
  233: }
  234: 
  235: /*
  236:  * Disable interrupt
  237:  *      disable interrupt specified by `intvec'
  238:  */
  239: EXPORT void DisableInt( INTVEC intvec )
  240: {
  241:         UW     m = 1 << BITNO(intvec);
  242: 
  243:         if ( intvec < IV_GPIO(0) ) {
  244:                 /* IRQ */
  245:                 const struct aint_reg *r = AINT + AINTNO(intvec);
  246:                 out_w(r->IT0_IDS, m);
  247:         } else {
  248:                 /* GPIO */
  249:                 UINT  gb = GIOB[GIONO(intvec)];
  250:                 out_w(GIO_IDS(gb), m);
  251:         }
  252: }
  253: 
  254: /*
  255:  * Clear the request for interrupt
  256:  *      clear the request of interrupt specified by `intvec'.
  257:  *      We need to clear the requests only in the case of edge-trigger interrupts.
  258:  */
  259: EXPORT void ClearInt( INTVEC intvec )
  260: {
  261:         UW     m = 1 << BITNO(intvec);
  262: 
  263:         if ( intvec < IV_IRQ(32 ) ) {
  264:                 /* IRQ 0-31  no relevant targets */
  265: 
  266:         } else if ( intvec < IV_IRQ(64) ) {
  267:                 /* IRQ 32--63 */
  268:                 out_w(IT0_IIR, m);
  269: 
  270:         } else if ( intvec < IV_GPIO(0) ) {
  271:                 /* IRQ 64-95 no relevant targets */
  272: 
  273:         } else {
  274:                 /* GPIO */
  275:                 UINT  gb = GIOB[GIONO(intvec)];
  276:                 out_w(GIO_IIR(gb), m);
  277:         }
  278: }
  279: 
  280: /*
  281:  * Check the existence of interrupt request
  282:  *      check the existence of request for interrupt specified by intvec
  283:  *      If there is, TRUE (non-zero value) is returned
  284:  *
  285:  *      The existence of the request of interrupt is checked by
  286:  *      'raw' status register.
  287:  */
  288: EXPORT BOOL CheckInt( INTVEC intvec )
  289: {
  290:         UW     sts;
  291: 
  292:         if ( intvec < IV_GPIO(0) ) {
  293:                 /* IRQ */
  294:                 const struct aint_reg *r = AINT + AINTNO(intvec);
  295:                 sts = in_w(r->IT0_RAW);
  296:         } else {
  297:                 /* GPIO */
  298:                 UINT  gb = GIOB[GIONO(intvec)];
  299:                 sts = in_w(GIO_RAW(gb));
  300:         }
  301: 
  302:         return (sts >> BITNO(intvec)) & 1;
  303: }