gonzui


Format: Advanced Search

mtkernel_3/device/ser/sysdepend/rza2m/ser_rza2m.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) 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_RZA2M
   16: 
   17: #include <tk/tkernel.h>
   18: #include <tm/tmonitor.h>
   19: #include "../../ser.h"
   20: #include "../../../include/dev_def.h"
   21: #if DEV_SER_ENABLE
   22: 
   23: /*
   24:  *      ser_rza2m.c
   25:  *      Serial communication device driver
   26:  *      System dependent processing for RZ/A2M
   27:  */
   28: 
   29: /*----------------------------------------------------------------------
   30:  * Device register base address
   31:  */
   32: const LOCAL UW ba[DEV_SER_UNITNM] = 
   33:         { SCI0_BASE, SCI1_BASE, SCI2_BASE, SCI3_BASE, SCI4_BASE};
   34: 
   35: /*----------------------------------------------------------------------
   36:  * Interrupt number Table
   37:  */
   38: const LOCAL UINT inotbl[DEV_SER_UNITNM] = 
   39:         { INTNO_SCI0_ERI, INTNO_SCI1_ERI, INTNO_SCI2_ERI, INTNO_SCI3_ERI, INTNO_SCI4_ERI};
   40: #define INTNO_BRI(n)    (inotbl[n])
   41: #define INTNO_ERI(n)    (inotbl[n])
   42: #define INTNO_RXI(n)    (inotbl[n]+1)
   43: #define INTNO_TXI(n)    (inotbl[n]+2)
   44: #define INTNO_TEI(n)    (inotbl[n]+3)
   45: #define INTNO_DRI(n)    (inotbl[n]+3)
   46: 
   47: /*----------------------------------------------------------------------
   48:  * Device control data
   49: */
   50: typedef struct {
   51:         UW     mode;               // Serial mode
   52:         UW     speed;              // Spped (bit rate)
   53: } T_DEV_SER_LLDEVCB;
   54: 
   55: LOCAL T_DEV_SER_LLDEVCB         ll_devcb[DEV_SER_UNITNM];
   56: 
   57: /*----------------------------------------------------------------------
   58:  * Interrupt handler
   59:  */
   60: 
   61: /*
   62:  * TXI: Transmit data empty interrupt
   63:  */
   64: void sci_txi_inthdr( UINT intno)
   65: {
   66:         UW     unit, data;
   67:         UH     reg;
   68:         UINT   inttxi = INTNO_SCI0_TXI;
   69: 
   70:         ClearInt(intno);
   71: 
   72:         for(unit = 0; unit < DEV_SER_UNITNM; unit++, inttxi+=6) {
   73:                 if(intno == inttxi) break;
   74:         }
   75: 
   76:         if(unit < DEV_SER_UNITNM ) {
   77:                 if( dev_ser_get_snddat(unit, &data)) {
   78:                         out_b(ba[unit] + SCI_FTDR, (UB)data);
   79:                 } else {
   80:                         reg = in_h(ba[unit] + SCI_SCR);
   81:                         out_h(ba[unit] + SCI_SCR, reg & ~SCI_SCR_TIE);
   82:                 }
   83:         }
   84: 
   85:         EndOfInt(intno);
   86: }
   87: 
   88: /*
   89:  * RXI: Receive data full interrupt
   90:  */
   91: void sci_rxi_inthdr( UINT intno)
   92: {
   93:         UW     unit, data;
   94:         UH     reg;
   95:         UINT   intrxi = INTNO_SCI0_RXI;
   96: 
   97:         ClearInt(intno);
   98: 
   99:         for(unit = 0; unit < DEV_SER_UNITNM; unit++, intrxi+=6) {
  100:                 if(intno == intrxi) break;
  101:         }
  102: 
  103:         if(unit < DEV_SER_UNITNM ) {
  104:                 data = in_b(ba[unit] + SCI_FRDR);
  105: 
  106:                 /* Clear DR & RDF bit */
  107:                 reg = in_h(ba[unit] + SCI_FSR);
  108:                 out_h(ba[unit] + SCI_FSR, reg & ~(SCI_FSR_DR|SCI_FSR_RDF));
  109: 
  110:                 dev_ser_notify_rcv(unit, data);       /* Notify the main process of data reception. */      
  111:         }
  112: 
  113:         EndOfInt(intno);
  114: }
  115: 
  116: /*
  117:  * ERI: Receive error interrupt
  118:  */
  119: void sci_eri_inthdr( UINT intno)
  120: {
  121:         UW     unit, err;
  122:         UH     reg;
  123:         UINT   interi = INTNO_SCI0_ERI;
  124: 
  125:         ClearInt(intno);
  126: 
  127:         for(unit = 0; unit < DEV_SER_UNITNM; unit++, interi+=6) {
  128:                 if(intno == interi) break;
  129:         }
  130: 
  131:         if(unit < DEV_SER_UNITNM ) {
  132:                 reg = in_h(ba[unit] + SCI_FSR);
  133:                 out_h(ba[unit] + SCI_FSR, reg & ~SCI_FSR_ER); /* Clear receive error */
  134:                 err = (UW)(reg & (DEV_SER_ERR_PE | DEV_SER_ERR_FE));
  135: 
  136:                 reg = in_h(ba[unit] + SCI_LSR);
  137:                 out_h(ba[unit] + SCI_FSR, reg & ~SCI_LSR_ORER);       /* Clear receive error */
  138:                 err |= (UW)(reg & DEV_SER_ERR_OE);
  139: 
  140:                 dev_ser_notify_err(unit, err);        /* Notify error to main process */
  141:         }
  142: 
  143:         EndOfInt(intno);
  144: }
  145: 
  146: 
  147: /*----------------------------------------------------------------------
  148:  * Set mode & Start communication
  149:  */
  150: LOCAL void start_com(UW unit, UW mode, UW speed)
  151: {
  152:         UH     reg;
  153: 
  154:         /* Set communication mode & Speed */
  155:         out_h( ba[unit] + SCI_SMR, (UH)((mode & 0x00000078)|(speed>>8 & 0x00000003)));
  156: 
  157:         reg = in_h( ba[unit] + SCI_SEMR);
  158:         out_h( ba[unit] + SCI_SEMR, (UH)((reg & ~SCI_SEMR_ABCS)|(speed & SCI_SEMR_ABCS)));
  159: 
  160:         out_b( ba[unit] + SCI_BRR, (UB)(speed >>16));
  161: 
  162:         /* Clear DR & RDF bit */
  163:         reg = in_h(ba[unit] + SCI_FSR);
  164:         out_h(ba[unit] + SCI_FSR, reg & ~(SCI_FSR_DR|SCI_FSR_RDF));
  165: 
  166:         /* SCR.TE,RE,TIE,RIE,REIE<- 1 */
  167:         out_h( ba[unit] + SCI_SCR, 
  168:                 (SCI_SCR_RE | SCI_SCR_TE | SCI_SCR_RIE | SCI_SCR_REIE));
  169: }
  170: 
  171: /*----------------------------------------------------------------------
  172:  * Stop communication
  173:  */
  174: LOCAL void stop_com(UW unit)
  175: {
  176:         if(unit != DEVCNF_SER_DBGUN) {
  177:                 out_h(ba[unit] + SCI_SCR, SCI_SCR_INI);
  178:         } else {       /* Used by T-Monitor */
  179:                 out_h(ba[unit] + SCI_SCR, SCI_SCR_DEBUG);
  180:         }
  181: }
  182: 
  183: /*----------------------------------------------------------------------
  184:  * Calculate baud rate
  185:  */
  186: typedef struct {
  187:         UW     baud;       // baud tate
  188:         UW     val;        // set value
  189: } T_BPS_VAL;
  190: 
  191: LOCAL const T_BPS_VAL   bps_tbl[] = {
  192:         /* Val : brr<<16 | cks << 8 | abcs */
  193:         /* P1 clock=66.67MHz */
  194:         { 500000,      (  3<<16) + (0<<8) + 0 },
  195:         { 230400,      (  8<<16) + (0<<8) + 0 },
  196:         { 115200,      ( 17<<16) + (0<<8) + 0 },
  197:         {  38400,      ( 53<<16) + (0<<8) + 0 },
  198:         {  31250,      ( 65<<16) + (0<<8) + 0 },
  199:         {  28800,      ( 71<<16) + (0<<8) + 0 },
  200:         {  19200,      (106<<16) + (0<<8) + 0 },
  201:         {  14400,      (142<<16) + (0<<8) + 0 },
  202:         {   9600,      (214<<16) + (0<<8) + 0 },
  203:         {   4800,      (106<<16) + (1<<8) + 0 },
  204:         {   2400,      (214<<16) + (1<<8) + 0 },
  205:         {   1200,      (106<<16) + (2<<8) + 0 },
  206:         {    600,      (214<<16) + (2<<8) + 0 },
  207:         {    300,      (106<<16) + (3<<8) + 0 },
  208:         {    150,      (214<<16) + (3<<8) + 0 },
  209:         {      0,      0 }
  210: };
  211: 
  212: LOCAL UW calc_brr(UW baud)
  213: {
  214:         const T_BPS_VAL                *p_tbl;
  215: 
  216:         for(p_tbl = bps_tbl; p_tbl->baud != 0; p_tbl++) {
  217:                 if(p_tbl->baud == baud) break;
  218:         }
  219: 
  220:         return (p_tbl->baud != 0)? p_tbl->val: 0;
  221: }
  222: 
  223: /*----------------------------------------------------------------------
  224:  * Low level device control
  225:  */
  226: EXPORT ER dev_ser_llctl( UW unit, INT cmd, UW parm)
  227: {
  228:         UW     data;
  229:         UH     reg;
  230:         ER     err = E_OK;
  231: 
  232:         switch(cmd) {
  233:         case LLD_SER_MODE:     /* Set Communication mode */
  234:                 ll_devcb[unit].mode = parm;
  235:                 break;
  236:         
  237:         case LLD_SER_SPEED:    /* Set Communication Speed */
  238:                 data = calc_brr(parm);
  239:                 if(data != 0) {
  240:                         ll_devcb[unit].speed = data;
  241:                 } else {
  242:                         err = E_PAR;
  243:                 }
  244:                 break;
  245:         
  246:         case LLD_SER_START:    /* Start communication */
  247:                 /* FIFO initialize */
  248:                 out_h(ba[unit] + SCI_FCR, SCI_FCR_RFRST | SCI_FCR_TFRST);     /* FIFO Reset */
  249:                 out_h(ba[unit] + SCI_FCR, SCI_FCR_INI);                               /* Set RSTRG */
  250:                 out_h(ba[unit] + SCI_FTCR, SCI_FTCR_INI);                     /* Set FIFO trigger */
  251: 
  252:                 /* Initialize status & Clear Error bits */
  253:                 reg = in_h(ba[unit] + SCI_FSR);
  254:                 out_h(ba[unit] + SCI_FSR, 0);                 /* Initialize FSR */
  255:                 reg = in_h(ba[unit] + SCI_LSR);
  256:                 out_h(ba[unit] + SCI_LSR, 0);                 /* Initialize LSR */
  257: 
  258:                 /* Clear Interrupt */
  259:                 ClearInt( INTNO_ERI(unit));
  260:                 ClearInt( INTNO_RXI(unit));
  261:                 ClearInt( INTNO_TXI(unit));
  262: 
  263:                 /* Enable Interrupt */
  264:                 EnableInt( INTNO_ERI(unit), DEVCNF_SER_INTPRI);
  265:                 EnableInt( INTNO_RXI(unit), DEVCNF_SER_INTPRI);
  266:                 EnableInt( INTNO_TXI(unit), DEVCNF_SER_INTPRI);
  267:         
  268:                 /* Set mode & Start communication */
  269:                 start_com( unit, ll_devcb[unit].mode, ll_devcb[unit].speed);
  270:                 break;
  271:         
  272:         case LLD_SER_STOP:
  273:                 /* Disable Interrupt */
  274:                 DisableInt( INTNO_ERI(unit));
  275:                 DisableInt( INTNO_RXI(unit));
  276:                 DisableInt( INTNO_TXI(unit));
  277:                 stop_com(unit);                       // Stop communication
  278:                 break;
  279: 
  280:         case LLD_SER_SEND:
  281:                 reg = in_h( ba[unit] + SCI_FDR);
  282:                 if((reg>>8) < 0x0010) {
  283:                         out_b(ba[unit] + SCI_FTDR, (UB)parm);
  284:                         reg = in_h(ba[unit] + SCI_SCR);
  285:                         out_h(ba[unit] + SCI_SCR, reg | SCI_SCR_TIE);
  286:                         err = E_OK;
  287:                 } else {
  288:                         err = E_BUSY;
  289:                 }
  290:                 break;
  291: 
  292:         case LLD_SER_BREAK:    /* Send Break */
  293:                 err = E_NOSPT;
  294:                 break;
  295:         }
  296: 
  297:         return err;
  298: }
  299: 
  300: /*----------------------------------------------------------------------
  301:  * Device initialization
  302:  */
  303: EXPORT ER dev_ser_llinit( T_SER_DCB *p_dcb)
  304: {
  305:         T_DINT         dint;
  306:         UW             unit;
  307:         ER             err;
  308: 
  309:         unit = p_dcb->unit;
  310: 
  311: #if DEVCONF_SER_INIT_MSTP               // Initialize module stop
  312:         UB     stbc;
  313: 
  314:         stbc = in_b(CPG_STBCR1);
  315:         out_b(CPG_STBCR1, stbc & ~(1<<(7-unit)));
  316:         stbc = in_b(CPG_STBCR1);       // dummy read
  317:         
  318: #endif          /* DEVCONF_SER_INIT_MSTP */
  319: 
  320:         stop_com(unit);                                        /* Stop communication */
  321:         out_h(ba[unit] + SCI_SPTR, SCI_SPTR_INI);      /* Serial port setting */
  322:         out_h( ba[unit] + SCI_SEMR, 0);
  323: 
  324: 
  325:         /* Device Control block Initizlize */
  326:         p_dcb->intno_rcv = INTNO_RXI(unit);
  327:         p_dcb->intno_snd = INTNO_TXI(unit);
  328: 
  329:         /* Interrupt handler definition */
  330:         dint.intatr    = TA_HLNG;
  331:         dint.inthdr    = sci_eri_inthdr;
  332:         err = tk_def_int(INTNO_ERI(unit), &dint);
  333:         dint.inthdr    = sci_rxi_inthdr;
  334:         err = tk_def_int(INTNO_RXI(unit), &dint);      
  335:         dint.inthdr    = sci_txi_inthdr;
  336:         err = tk_def_int(INTNO_TXI(unit), &dint);
  337: 
  338:         return err;
  339: }
  340: 
  341: #endif          /* DEV_SER_ENABLE */
  342: #endif          /* CPU_RZA2M */