RZG2L SCIg Channel Smart Card Interface

Hi,

RZG2L has Smart Card interface on SCIg channel.

I connected Smart Card IC NCN8026A to RZG2L over SCIg channel.

I not getting any document for the SCIg channel in Renesas BSP documents.

How we proceed to do this. Is there any support is available in Renesas Linux BSP V1.3 update2??

Thanks 

Pravin Raut

Top Replies

  • Support for the SCIg peripherals are not included in the current Linux BSP.

    It might be possible to use the SCIg with the current driver in the kernel (drivers/tty/serial/sh-sci.c), but some development work might be needed.

    However, this is only for the standard UART functionality of SCIg. None of the Smart Card functionality (registers) exists in the driver. If you would like to use SCIg with a Smart Card, you will need to create a custom driver for your application.

  • Hi Chris,

    I added Smart Card mode in sh-sci.c and sh-sci.h.

    Please find attached files.

    Can you give suggestion on that ??

    Thanks

    Pravin Rautsh-sci_c.txt

    sh-sci_h.txt
    /* SPDX-License-Identifier: GPL-2.0 */
    #include <linux/bitops.h>
    #include <linux/serial_core.h>
    #include <linux/io.h>
    #include <linux/gpio.h>
    
    #define SCI_MAJOR		204
    #define SCI_MINOR_START		8
    
    
    /*
     * SCI register subset common for all port types.
     * Not all registers will exist on all parts.
     */
    enum {
    	SCSMR,				/* Serial Mode Register */
    	SCBRR,				/* Bit Rate Register */
    	SCSCR,				/* Serial Control Register */
    	SCxSR,				/* Serial Status Register */
    	SCFCR,				/* FIFO Control Register */
    	SCFDR,				/* FIFO Data Count Register */
    	SCxTDR,				/* Transmit (FIFO) Data Register */
    	SCxRDR,				/* Receive (FIFO) Data Register */
    	SCLSR,				/* Line Status Register */
    	SCTFDR,				/* Transmit FIFO Data Count Register */
    	SCRFDR,				/* Receive FIFO Data Count Register */
    	SCSPTR,				/* Serial Port Register */
    	HSSRR,				/* Sampling Rate Register */
    	SCPCR,				/* Serial Port Control Register */
    	SCPDR,				/* Serial Port Data Register */
    	SCDL,				/* BRG Frequency Division Register */
    	SCCKS,				/* BRG Clock Select Register */
    	HSRTRGR,			/* Rx FIFO Data Count Trigger Register */
    	HSTTRGR,			/* Tx FIFO Data Count Trigger Register */
    	SCSEMR,				/* Serial extended mode register */
    	
    	SCMR,				/* Smart Card Mode register */ 
    
    	SCIx_NR_REGS,
    };
    
    
    /* SCSMR (Serial Mode Register) */
    #define SCSMR_C_A	BIT(7)	/* Communication Mode */
    #define SCSMR_CSYNC	BIT(7)	/*   - Clocked synchronous mode */
    #define SCSMR_ASYNC	0	/*   - Asynchronous mode */
    #define SCSMR_CHR	BIT(6)	/* 7-bit Character Length */
    #define SCSMR_PE	BIT(5)	/* Parity Enable */
    #define SCSMR_ODD	BIT(4)	/* Odd Parity */
    #define SCSMR_STOP	BIT(3)	/* Stop Bit Length */
    #define SCSMR_CKS	0x0003	/* Clock Select */
    
    /* Serial Mode Register, SCIFA/SCIFB only bits */
    #define SCSMR_CKEDG	BIT(12)	/* Transmit/Receive Clock Edge Select */
    #define SCSMR_SRC_MASK	0x0700	/* Sampling Control */
    #define SCSMR_SRC_16	0x0000	/* Sampling rate 1/16 */
    #define SCSMR_SRC_5	0x0100	/* Sampling rate 1/5 */
    #define SCSMR_SRC_7	0x0200	/* Sampling rate 1/7 */
    #define SCSMR_SRC_11	0x0300	/* Sampling rate 1/11 */
    #define SCSMR_SRC_13	0x0400	/* Sampling rate 1/13 */
    #define SCSMR_SRC_17	0x0500	/* Sampling rate 1/17 */
    #define SCSMR_SRC_19	0x0600	/* Sampling rate 1/19 */
    #define SCSMR_SRC_27	0x0700	/* Sampling rate 1/27 */
    
    /* Serial Control Register, SCIFA/SCIFB only bits */
    #define SCSCR_TDRQE	BIT(15)	/* Tx Data Transfer Request Enable */
    #define SCSCR_RDRQE	BIT(14)	/* Rx Data Transfer Request Enable */
    
    /* Serial Control Register, HSCIF-only bits */
    #define HSSCR_TOT_SHIFT	14
    
    /* SCxSR (Serial Status Register) on SCI */
    #define SCI_TDRE	BIT(7)	/* Transmit Data Register Empty */
    #define SCI_RDRF	BIT(6)	/* Receive Data Register Full */
    #define SCI_ORER	BIT(5)	/* Overrun Error */
    #define SCI_FER		BIT(4)	/* Framing Error */
    #define SCI_PER		BIT(3)	/* Parity Error */
    #define SCI_TEND	BIT(2)	/* Transmit End */
    #define SCI_RESERVED	0x03	/* All reserved bits */
    
    #define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
    
    #define SCI_RDxF_CLEAR	(u32)(~(SCI_RESERVED | SCI_RDRF))
    #define SCI_ERROR_CLEAR	(u32)(~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER))
    #define SCI_TDxE_CLEAR	(u32)(~(SCI_RESERVED | SCI_TEND | SCI_TDRE))
    #define SCI_BREAK_CLEAR	(u32)(~(SCI_RESERVED | SCI_PER | SCI_FER | SCI_ORER))
    
    /* SCxSR (Serial Status Register) on SCIF, SCIFA, SCIFB, HSCIF */
    #define SCIF_ER		BIT(7)	/* Receive Error */
    #define SCIF_TEND	BIT(6)	/* Transmission End */
    #define SCIF_TDFE	BIT(5)	/* Transmit FIFO Data Empty */
    #define SCIF_BRK	BIT(4)	/* Break Detect */
    #define SCIF_FER	BIT(3)	/* Framing Error */
    #define SCIF_PER	BIT(2)	/* Parity Error */
    #define SCIF_RDF	BIT(1)	/* Receive FIFO Data Full */
    #define SCIF_DR		BIT(0)	/* Receive Data Ready */
    /* SCIF only (optional) */
    #define SCIF_PERC	0xf000	/* Number of Parity Errors */
    #define SCIF_FERC	0x0f00	/* Number of Framing Errors */
    /*SCIFA/SCIFB and SCIF on SH7705/SH7720/SH7721 only */
    #define SCIFA_ORER	BIT(9)	/* Overrun Error */
    
    #define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_BRK | SCIF_ER)
    
    #define SCIF_RDxF_CLEAR		(u32)(~(SCIF_DR | SCIF_RDF))
    #define SCIF_ERROR_CLEAR	(u32)(~(SCIF_PER | SCIF_FER | SCIF_ER))
    #define SCIF_TDxE_CLEAR		(u32)(~(SCIF_TDFE))
    #define SCIF_BREAK_CLEAR	(u32)(~(SCIF_PER | SCIF_FER | SCIF_BRK))
    
    /* SCFCR (FIFO Control Register) */
    #define SCFCR_RTRG1	BIT(7)	/* Receive FIFO Data Count Trigger */
    #define SCFCR_RTRG0	BIT(6)
    #define SCFCR_TTRG1	BIT(5)	/* Transmit FIFO Data Count Trigger */
    #define SCFCR_TTRG0	BIT(4)
    #define SCFCR_MCE	BIT(3)	/* Modem Control Enable */
    #define SCFCR_TFRST	BIT(2)	/* Transmit FIFO Data Register Reset */
    #define SCFCR_RFRST	BIT(1)	/* Receive FIFO Data Register Reset */
    #define SCFCR_LOOP	BIT(0)	/* Loopback Test */
    
    /* SCLSR (Line Status Register) on (H)SCIF */
    #define SCLSR_TO	BIT(2)	/* Timeout */
    #define SCLSR_ORER	BIT(0)	/* Overrun Error */
    
    /* SCSPTR (Serial Port Register), optional */
    #define SCSPTR_RTSIO	BIT(7)	/* Serial Port RTS# Pin Input/Output */
    #define SCSPTR_RTSDT	BIT(6)	/* Serial Port RTS# Pin Data */
    #define SCSPTR_CTSIO	BIT(5)	/* Serial Port CTS# Pin Input/Output */
    #define SCSPTR_CTSDT	BIT(4)	/* Serial Port CTS# Pin Data */
    #define SCSPTR_SCKIO	BIT(3)	/* Serial Port Clock Pin Input/Output */
    #define SCSPTR_SCKDT	BIT(2)	/* Serial Port Clock Pin Data */
    #define SCSPTR_SPB2IO	BIT(1)	/* Serial Port Break Input/Output */
    #define SCSPTR_SPB2DT	BIT(0)	/* Serial Port Break Data */
    
    /* HSSRR HSCIF */
    #define HSCIF_SRE	BIT(15)	/* Sampling Rate Register Enable */
    #define HSCIF_SRDE	BIT(14) /* Sampling Point Register Enable */
    
    #define HSCIF_SRHP_SHIFT	8
    #define HSCIF_SRHP_MASK		0x0f00
    
    /* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */
    #define SCPCR_RTSC	BIT(4)	/* Serial Port RTS# Pin / Output Pin */
    #define SCPCR_CTSC	BIT(3)	/* Serial Port CTS# Pin / Input Pin */
    #define SCPCR_SCKC	BIT(2)	/* Serial Port SCK Pin / Output Pin */
    #define SCPCR_RXDC	BIT(1)	/* Serial Port RXD Pin / Input Pin */
    #define SCPCR_TXDC	BIT(0)	/* Serial Port TXD Pin / Output Pin */
    
    /* SCPDR (Serial Port Data Register), SCIFA/SCIFB only */
    #define SCPDR_RTSD	BIT(4)	/* Serial Port RTS# Output Pin Data */
    #define SCPDR_CTSD	BIT(3)	/* Serial Port CTS# Input Pin Data */
    #define SCPDR_SCKD	BIT(2)	/* Serial Port SCK Output Pin Data */
    #define SCPDR_RXDD	BIT(1)	/* Serial Port RXD Input Pin Data */
    #define SCPDR_TXDD	BIT(0)	/* Serial Port TXD Output Pin Data */
    
    /*
     * BRG Clock Select Register (Some SCIF and HSCIF)
     * The Baud Rate Generator for external clock can provide a clock source for
     * the sampling clock. It outputs either its frequency divided clock, or the
     * (undivided) (H)SCK external clock.
     */
    #define SCCKS_CKS	BIT(15)	/* Select (H)SCK (1) or divided SC_CLK (0) */
    #define SCCKS_XIN	BIT(14)	/* SC_CLK uses bus clock (1) or SCIF_CLK (0) */
    
    #define SCxSR_TEND(port)	(((port)->type == PORT_SCI) ? SCI_TEND   : SCIF_TEND)
    #define SCxSR_RDxF(port)	(((port)->type == PORT_SCI) ? SCI_RDRF   : SCIF_DR | SCIF_RDF)
    #define SCxSR_TDxE(port)	(((port)->type == PORT_SCI) ? SCI_TDRE   : SCIF_TDFE)
    #define SCxSR_FER(port)		(((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
    #define SCxSR_PER(port)		(((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
    #define SCxSR_BRK(port)		(((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
    
    #define SCxSR_ERRORS(port)	(to_sci_port(port)->params->error_mask)
    
    #define SCxSR_RDxF_CLEAR(port) \
    	(((port)->type == PORT_SCI) ? SCI_RDxF_CLEAR : SCIF_RDxF_CLEAR)
    #define SCxSR_ERROR_CLEAR(port) \
    	(to_sci_port(port)->params->error_clear)
    #define SCxSR_TDxE_CLEAR(port) \
    	(((port)->type == PORT_SCI) ? SCI_TDxE_CLEAR : SCIF_TDxE_CLEAR)
    #define SCxSR_BREAK_CLEAR(port) \
    	(((port)->type == PORT_SCI) ? SCI_BREAK_CLEAR : SCIF_BREAK_CLEAR)
    

    static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
    struct ktermios *old)
    {
    unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i, bits;
    unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0;
    unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0;
    struct sci_port *s = to_sci_port(port);
    const struct plat_sci_reg *reg;
    int min_err = INT_MAX, err;
    unsigned long max_freq = 0;
    int best_clk = -1;
    unsigned long flags;
    u16 scr;

    if ((termios->c_cflag & CSIZE) == CS7)
    smr_val |= SCSMR_CHR;
    if (termios->c_cflag & PARENB)
    smr_val |= SCSMR_PE;
    if (termios->c_cflag & PARODD)
    smr_val |= SCSMR_PE | SCSMR_ODD;
    if (termios->c_cflag & CSTOPB)
    smr_val |= SCSMR_STOP;

    /*
    * earlyprintk comes here early on with port->uartclk set to zero.
    * the clock framework is not up and running at this point so here
    * we assume that 115200 is the maximum baud rate. please note that
    * the baud rate is not programmed during earlyprintk - it is assumed
    * that the previous boot loader has enabled required clocks and
    * setup the baud rate generator hardware for us already.
    */
    if (!port->uartclk) {
    baud = uart_get_baud_rate(port, termios, old, 0, 115200);
    goto done;
    }

    for (i = 0; i < SCI_NUM_CLKS; i++)
    max_freq = max(max_freq, s->clk_rates[i]);

    baud = uart_get_baud_rate(port, termios, old, 0, max_freq / min_sr(s));
    if (!baud)
    goto done;

    /*
    * There can be multiple sources for the sampling clock. Find the one
    * that gives us the smallest deviation from the desired baud rate.
    */

    /* Optional Undivided External Clock */
    if (s->clk_rates[SCI_SCK] && port->type != PORT_SCIFA &&
    port->type != PORT_SCIFB) {
    err = sci_sck_calc(s, baud, &srr1);
    if (abs(err) < abs(min_err)) {
    best_clk = SCI_SCK;
    scr_val = SCSCR_CKE1;
    sccks = SCCKS_CKS;
    min_err = err;
    srr = srr1;
    if (!err)
    goto done;
    }
    }

    /* Optional BRG Frequency Divided External Clock */
    if (s->clk_rates[SCI_SCIF_CLK] && sci_getreg(port, SCDL)->size) {
    err = sci_brg_calc(s, baud, s->clk_rates[SCI_SCIF_CLK], &dl1,
    &srr1);
    if (abs(err) < abs(min_err)) {
    best_clk = SCI_SCIF_CLK;
    scr_val = SCSCR_CKE1;
    sccks = 0;
    min_err = err;
    dl = dl1;
    srr = srr1;
    if (!err)
    goto done;
    }
    }

    /* Optional BRG Frequency Divided Internal Clock */
    if (s->clk_rates[SCI_BRG_INT] && sci_getreg(port, SCDL)->size) {
    err = sci_brg_calc(s, baud, s->clk_rates[SCI_BRG_INT], &dl1,
    &srr1);
    if (abs(err) < abs(min_err)) {
    best_clk = SCI_BRG_INT;
    scr_val = SCSCR_CKE1;
    sccks = SCCKS_XIN;
    min_err = err;
    dl = dl1;
    srr = srr1;
    if (!min_err)
    goto done;
    }
    }

    /* Divided Functional Clock using standard Bit Rate Register */
    err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1);
    if (abs(err) < abs(min_err)) {
    best_clk = SCI_FCK;
    scr_val = 0;
    min_err = err;
    brr = brr1;
    srr = srr1;
    cks = cks1;
    }

    done:
    if (best_clk >= 0)
    dev_dbg(port->dev, "Using clk %pC for %u%+d bps\n",
    s->clks[best_clk], baud, min_err);

    sci_port_enable(s);

    /*
    * Program the optional External Baud Rate Generator (BRG) first.
    * It controls the mux to select (H)SCK or frequency divided clock.
    */
    if (best_clk >= 0 && sci_getreg(port, SCCKS)->size) {
    serial_port_out(port, SCDL, dl);
    serial_port_out(port, SCCKS, sccks);
    }

    spin_lock_irqsave(&port->lock, flags);

    sci_reset(port);

    uart_update_timeout(port, termios->c_cflag, baud);

    /* byte size and parity */
    switch (termios->c_cflag & CSIZE) {
    case CS5:
    bits = 7;
    break;
    case CS6:
    bits = 8;
    break;
    case CS7:
    bits = 9;
    break;
    default:
    bits = 10;
    break;
    }

    if (termios->c_cflag & CSTOPB)
    bits++;
    if (termios->c_cflag & PARENB)
    bits++;

    if (best_clk >= 0) {
    if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
    switch (srr + 1) {
    case 5: smr_val |= SCSMR_SRC_5; break;
    case 7: smr_val |= SCSMR_SRC_7; break;
    case 11: smr_val |= SCSMR_SRC_11; break;
    case 13: smr_val |= SCSMR_SRC_13; break;
    case 16: smr_val |= SCSMR_SRC_16; break;
    case 17: smr_val |= SCSMR_SRC_17; break;
    case 19: smr_val |= SCSMR_SRC_19; break;
    case 27: smr_val |= SCSMR_SRC_27; break;
    }
    smr_val |= cks;
    /*we not support extended mode yet, make sure it is cleared*/
    if ((sci_getreg(port, SCSEMR)) && (sci_getreg(port, SCSEMR)->size))
    serial_port_out(port, SCSEMR, 0);
    serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
    serial_port_out(port, SCSMR, smr_val);
    serial_port_out(port, SCBRR, brr);
    if (sci_getreg(port, HSSRR)->size) {
    unsigned int hssrr = srr | HSCIF_SRE;
    /* Calculate deviation from intended rate at the
    * center of the last stop bit in sampling clocks.
    */
    int last_stop = bits * 2 - 1;
    int deviation = DIV_ROUND_CLOSEST(min_err * last_stop *
    (int)(srr + 1),
    2 * (int)baud);

    if (abs(deviation) >= 2) {
    /* At least two sampling clocks off at the
    * last stop bit; we can increase the error
    * margin by shifting the sampling point.
    */
    int shift = clamp(deviation / 2, -8, 7);

    hssrr |= (shift << HSCIF_SRHP_SHIFT) &
    HSCIF_SRHP_MASK;
    hssrr |= HSCIF_SRDE;
    }
    serial_port_out(port, HSSRR, hssrr);
    }

    /* Wait one bit interval */
    udelay((1000000 + (baud - 1)) / baud);
    } else {
    /* Don't touch the bit rate configuration */
    scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0);
    smr_val |= serial_port_in(port, SCSMR) &
    (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS);
    /*we not support extended mode yet, make sure it is cleared*/
    if (s->is_rzg2l)
    serial_port_out(port, SCSEMR, 0);
    serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
    serial_port_out(port, SCSMR, smr_val);
    }

    /*Added By Pravin Raut on 07-04-2022 for Smart Card mode*/
    serial_port_out(port, SCMR, 0xF3); //Smart Card mode selected.
    scr = serial_port_in(port, SCSCR); //Read the SCSCR register.
    serial_port_out(port, SCSCR, scr | 0x01); //Select SCK output clk for Smart Card.
    /*End of line for added code*/

    sci_init_pins(port, termios->c_cflag);

    port->status &= ~UPSTAT_AUTOCTS;
    s->autorts = false;
    reg = sci_getreg(port, SCFCR);
    if (reg->size) {
    unsigned short ctrl = serial_port_in(port, SCFCR);

    if ((port->flags & UPF_HARD_FLOW) &&
    (termios->c_cflag & CRTSCTS)) {
    /* There is no CTS interrupt to restart the hardware */
    port->status |= UPSTAT_AUTOCTS;
    /* MCE is enabled when RTS is raised */
    s->autorts = true;
    }

    /*
    * As we've done a sci_reset() above, ensure we don't
    * interfere with the FIFOs while toggling MCE. As the
    * reset values could still be set, simply mask them out.
    */
    ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);

    serial_port_out(port, SCFCR, ctrl);
    }
    if (port->flags & UPF_HARD_FLOW) {
    /* Refresh (Auto) RTS */
    sci_set_mctrl(port, port->mctrl);
    }

    scr_val |= SCSCR_RE | SCSCR_TE |
    (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
    serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
    if ((srr + 1 == 5) &&
    (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {
    /*
    * In asynchronous mode, when the sampling rate is 1/5, first
    * received data may become invalid on some SCIFA and SCIFB.
    * To avoid this problem wait more than 1 serial data time (1
    * bit time x serial data number) after setting SCSCR.RE = 1.
    */
    udelay(DIV_ROUND_UP(10 * 1000000, baud));
    }

    /*
    * Calculate delay for 2 DMA buffers (4 FIFO).
    * See serial_core.c::uart_update_timeout().
    * With 10 bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above
    * function calculates 1 jiffie for the data plus 5 jiffies for the
    * "slop(e)." Then below we calculate 5 jiffies (20ms) for 2 DMA
    * buffers (4 FIFO sizes), but when performing a faster transfer, the
    * value obtained by this formula is too small. Therefore, if the value
    * is smaller than 20ms, use 20ms as the timeout value for DMA.
    */
    s->rx_frame = (10000 * bits) / (baud / 100);
    #ifdef CONFIG_SERIAL_SH_SCI_DMA
    s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
    if (s->rx_timeout < 20)
    s->rx_timeout = 20;
    #endif

    if ((termios->c_cflag & CREAD) != 0)
    sci_start_rx(port);

    spin_unlock_irqrestore(&port->lock, flags);

    sci_port_disable(s);

    if (UART_ENABLE_MS(port, termios->c_cflag))
    sci_enable_ms(port);
    }

    Thanks

    Pravin Raut

  • Hi Chris,

    In SCIg channel, for Smart Card Interface, following are the register difference.

    SCIg in Smart Card mode configuration.

    1. SCMR – Smart Card Mode Register.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    BCP2

    --

    --

    CHR1

    SDIR

    SINV

    --

    SMIF

    1

    1

    1

    1

    0

    0

    1

    1

     

    For Smart Card Mode SCMR = 0xF3.

    • SMIF -> 1 to Select Smart Card Mode.
    • SINV -> 0 to Select Non-inverted Data.
    • SDIR -> 0 to LSB 1st.
    • CHR1 -> 1 to TX/RX 8-bit Data.
    • BCP2 -> 1 to Base Clock pulse default.

     

    1. SMR – Serial Mode Register.
    2. Non-Smart Card Communication.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    CM

    CHR

    PE

    PM

    STOP

    MP

    CKS [1:0]

    0

    0

    0

    0

    0

    0

    0

    0

     

    1. Smart Card Communication.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    GM

    BLK

    PE

    PM

    BCP [1:0]

    CKS [1:0]

    0

    0

    1

    0

    0

    0

    0

    0

     

    Bit

    Bit Value in Non-Smart Card

    Bit Value in Smart Card

    Description in Non-Smart Card

    Description in Smart Card

    CM/GM

    0

    0

    Asynchronous Mode

    Normal Mode Operation

    CHR/BLK

    0

    0

    8bit Length

    Normal Mode Operation

    PE/PE

    0

    1

    No Parity

    Parity Enable

    PM/PM

    0

    0

    Not Effective

    Even Parity

    STOP/BCP1

    0

    0

    1 Stop bit

    Kept Default

    MP/BCP0

    0

    0

    Multiprocessor Disable

    Kept Default

    CKS[1:0]

    0

    0

    P0 Source Clock used

    P0 Source Clock used

     

     

     

     

     

     

    1. SCR – Serial Control Register.
    2. Non-Smart Card Communication.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    TIE

    RIE

    TE

    RE

    MPIE

    TEIE

    CKE [1:0]

    0

    0

    0

    0

    0

    0

    0

    0

     

    1. Smart Card Communication.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    TIE

    RIE

    TE

    RE

    MPIE

    TEIE

    CKE [1:0]

    0

    0

    0

    0

    0

    0

    0

    1

     

    Bit

    Bit Value in Non-Smart Card

    Bit Value in Smart Card

    Description in Non-Smart Card

    Description in Smart Card

    TIE

    0

    0

    TX Interrupt Enable

    TX Interrupt Enable

    RIE

    0

    0

    RX Interrupt Enable

    RX Interrupt Enable

    TE

    0

    1

    Transmit Enable

    Transmit Enable

    RE

    0

    0

    Receive Enable

    Receive Enable

    MPIE

    0

    0

    Multi-Processor Interrupt Enable

    Multi-processor interrupt must be disable in this mode

    TEIE

    0

    0

    TX End Interrupt Enable

    TX End interrupt must be disable in this mode.

    CKE [1:0]

    0

    1

    No output clock on SCK

    Output clock on SCK

     

     

     

     

     

     

     

    1. SSR – Serial Status Register.
    2. Non-Smart Card Communication.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    TDRE

    RDRF

    ORER

    FER

    PER

    TEND

    MPB

    MPBT

    0

    0

    0

    0

    0

    0

    0

    0

     

    1. Smart Card Communication.

    B7

    B6

    B5

    B4

    B3

    B2

    B1

    B0

    TDRE

    RDRF

    ORER

    ERS

    PER

    TEND

    MPB

    MPBT

    0

    0

    0

    0

    0

    0

    0

    1

     

    Bit

    Bit Value in Non-Smart Card

    Bit Value in Smart Card

    Description in Non-Smart Card

    Description in Smart Card

    TDRE

     

     

    TX Data Empty Flag

    TX Data Empty Flag

    RDRF

     

     

    RX Data Full Flag

    RX Data Full Flag

    ORER

     

     

    Overrun Error Flag

    Overrun Error Flag

    FER/ERS

     

     

    Framing Error Flag

    Error Signal Status

    PER

     

     

    Parity Error Flag

    Parity Error Flag

    TEND

     

     

    TX End Flag Status

    TX End Flag Status

    MPB

    0

    0

    Not Effective

    Not Effective

    MPBT

    0

    0

    Not Effective

    Not Effective

     

    Form Above register description.

    1. SCMR = 0xF3 at initialization.

    2. SMR.PE = 1 at initialization for Parity enable.

    3. CSR.CKE[1:0] = 0x01 at initialization for SCK clock output.

    4. SSR is almost same as in both mode.

    Since I am using SCI channel only for Smart Card, so I modify in sh-sci.c and sh-sci.h for its SCI channel.

    So when select SCI channel form device tree, then only Smart Card mode will be selected.

    I made following changes in sh-sci.h

    1. Added "SCMR, /* Smart Card Mode register */ " in register enum.

    I made following changes in sh-sci.c

    1. add bellow line in "static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES]"

    /*Added By Pravin Raut on 07-04-2022 for Smart Card mode*/
    [SCMR] = { 0x06, 8 }, //Add by Pravin Raut 0n 07-04-2022
    /*End of line for added code*/

    2. Added below in sci_set_termios function.

    /*Added By Pravin Raut on 07-04-2022 for Smart Card mode*/
    if(port->type == PORT_SCI)
    {
    serial_port_out(port, SCMR, 0xF3); //Smart Card mode selected.
    scr = serial_port_in(port, SCSCR); //Read the SCSCR register.
    serial_port_out(port, SCSCR, scr | 0x01); //Select SCK output clk for Smart Card.
    }
    /*End of line for added code*/

    Can Smart Card Mode will work with this changes?? 

    Thanks 

    Pravin Raut

  • Can Smart Card Mode will work with this changes?? 

    You have to try it and find out.

    Linux is open source. You can modify the code however you want to.

  • Hi Chris,

    Since Smart Card registers are not added in sh-sci.c and sh-sci.h.

    I added SCMR register in enum. Also added SCMR in sci_port_param.

    And try to write value of the SCMR register as 0x F3.

    Now I wanted to check the written value. So I read that register, but I get value as zero only.

    Please find below code Part.

    enum {
    SCSMR, /* Serial Mode Register */
    SCBRR, /* Bit Rate Register */
    SCSCR, /* Serial Control Register */
    SCxSR, /* Serial Status Register */
    SCFCR, /* FIFO Control Register */
    SCFDR, /* FIFO Data Count Register */
    SCxTDR, /* Transmit (FIFO) Data Register */
    SCxRDR, /* Receive (FIFO) Data Register */
    SCLSR, /* Line Status Register */
    SCTFDR, /* Transmit FIFO Data Count Register */
    SCRFDR, /* Receive FIFO Data Count Register */
    SCSPTR, /* Serial Port Register */
    HSSRR, /* Sampling Rate Register */
    SCPCR, /* Serial Port Control Register */
    SCPDR, /* Serial Port Data Register */
    SCDL, /* BRG Frequency Division Register */
    SCCKS, /* BRG Clock Select Register */
    HSRTRGR, /* Rx FIFO Data Count Trigger Register */
    HSTTRGR, /* Tx FIFO Data Count Trigger Register */
    SCSEMR, /* Serial extended mode register */

    SCSCMR,

    SCIx_NR_REGS,
    };

    added in .h file

    After that 

    [SCIx_SCI_REGTYPE] = {
    .regs = {
    [SCSMR] = { 0x00, 8 },
    [SCBRR] = { 0x01, 8 },
    [SCSCR] = { 0x02, 8 },
    [SCxTDR] = { 0x03, 8 },
    [SCxSR] = { 0x04, 8 },
    [SCxRDR] = { 0x05, 8 },
    /*Added By Pravin Raut on 07-04-2022 for Smart Card mode*/
    [SCSCMR] = { 0x06, 8 }, //Add by Pravin Raut 0n 07-04-2022
    /*End of line for added code*/

    },
    .fifosize = 1,
    .overrun_reg = SCxSR,
    .overrun_mask = SCI_ORER,
    .sampling_rate_mask = SCI_SR(32),
    .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,
    .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,
    },

    And Get called in 

    /*Added By Pravin Raut on 07-04-2022 for Smart Card mode*/
    if(port->type == PORT_SCI)
    {

    dev_err(port->dev, "Pravin SCI Smart Card Init start");

    serial_port_out(port, SCSCR, 0x00); //Init SCR to 0x00
    scr = serial_port_in(port, SCSCR);
    dev_err(port->dev, "Pravin = SCI-SCSCR = %d = 0X%x", scr, scr);

    serial_port_out(port, SCxSR, 0x00); //Init SSR to 0x00
    scr = serial_port_in(port, SCxSR);
    dev_err(port->dev, "Pravin = SCI-SCxSR = %d = 0X%x", scr, scr);

    serial_port_out(port, SCSMR, 0x20); //Init Serial Mode Register to 0x00
    scr = serial_port_in(port, SCSMR);
    dev_err(port->dev, "Pravin = SCI-SCSMR = %d = 0X%x", scr, scr);

    serial_port_out(port, SCSCMR, 0xF3); //Smart Card mode selected.
    scr = serial_port_in(port, SCSCMR);
    dev_err(port->dev, "Pravin = SCI-SCSCMR = %d = 0X%x", scr, scr);

    serial_port_out(port, SCSCR, 0xD1); //Select SCK output clk for Smart Card.
    scr = serial_port_in(port, SCSCR);
    dev_err(port->dev, "Pravin = SCI-SCSCR = %d = 0X%x", scr, scr);


    dev_err(port->dev, "Pravin SCI Smart Card Init Complete");

    }
    /*End of line for added code*/

    this much added in,c files.

    Can u guide use for the same.

  • Now I wanted to check the written value. So I read that register, but I get value as zero only.

    Looking at the driver, it has pm_runtime (pm = Power Management).

    It means when the driver is not used, the kernel will stop the clock to the peripheral to save power.

    When the clock is stopped, if you try to read a register, it will be read as 0.

    For debug, maybe you can disable runtime pm.

    static struct platform_driver sci_driver = {
        .probe = sci_probe,
        .remove = sci_remove,
        .driver = {
             .name = "sh-sci",
    //       .pm = &sci_dev_pm_ops,      <<<<< comment out this line in the driver
             .of_match_table = of_match_ptr(of_sci_match),
        },
    };

  • Hi Chris,

    Thanks for the replay.

    I tried as per our suggestion.

    Still I get the same response.

    Now I added serial init function in application as follows

    e_PRINTER_RET_VAL Printer_Init(stSerialCnfg *printer)
    {
    e_SERIAL_RET_VAL ret;

    strcpy(printer->ser_file_path, THPRINTER_SERIAL_UART_PORT);
    printer->baud_rate = THPRINTER_BAUDRATE;
    printer->read_wait_time = THPRINTER_READ_WAIT_TIME;
    ret = serial_port_open(printer);
    if(ret != SERIAL_OPEN_OK)
    {
    return THPRINTER_SERIAL_ERR;
    }
    return(THPRINTER_OK);
    }

    I selected the serial channel as a SCIg in device tree.

    When I call this function form main the following function get call from sh-sci.c

    static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
    struct ktermios *old)

    I added log in this function.

    In this function, I added SCIg initialization for Smart Card interface. and try to readback the written values.

    I tried as as per your suggestion, still not getting SCMR value which set as 0xF3.

    following are the log for this function.

    [ 56.166802] sh-sci 1004d400.serial: Pravin = SCI Set termios started
    [ 56.173673] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.178503] sh-sci 1004d400.serial: Pravin = SCI-SCSCR = 0 = 0X0
    [ 56.184554] sh-sci 1004d400.serial: Out Offset = 6
    [ 56.189368] sh-sci 1004d400.serial: Pravin = SCI-SCSCMR = 0 = 0X0
    [ 56.195592] sh-sci 1004d400.serial: Pravin = SCI Set termios processing
    [ 56.202236] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.207020] sh-sci 1004d400.serial: Out Offset = 4
    [ 56.211800] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.216577] sh-sci 1004d400.serial: Out Offset = 0
    [ 56.221352] sh-sci 1004d400.serial: Out Offset = 1
    [ 56.226236] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.231015] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.235837] sh-sci 1004d400.serial: Pravin SCI Smart Card Init start
    [ 56.242233] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.247055] sh-sci 1004d400.serial: Pravin = SCI-SCSCR = 0 = 0X0
    [ 56.253102] sh-sci 1004d400.serial: Out Offset = 4
    [ 56.257912] sh-sci 1004d400.serial: Pravin = SCI-SCxSR = 0 = 0X0
    [ 56.264044] sh-sci 1004d400.serial: Out Offset = 0
    [ 56.268853] sh-sci 1004d400.serial: Pravin = SCI-SCSMR = 32 = 0X20
    [ 56.275070] sh-sci 1004d400.serial: Out Offset = 6
    [ 56.279883] sh-sci 1004d400.serial: Pravin = SCI-SCSCMR = 0 = 0X0
    [ 56.286113] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.290943] sh-sci 1004d400.serial: Pravin = SCI-SCSCR = 1 = 0X1
    [ 56.296994] sh-sci 1004d400.serial: Pravin SCI Smart Card Init Complete

    Can you suggest any changes required or any thing I missed.

    Thanks

    Pravin Raut 

  • Hi Chris,

    Thanks for the replay.

    I tried as per our suggestion.

    Still I get the same response.

    Now I added serial init function in application as follows

    e_PRINTER_RET_VAL Printer_Init(stSerialCnfg *printer)
    {
    e_SERIAL_RET_VAL ret;

    strcpy(printer->ser_file_path, THPRINTER_SERIAL_UART_PORT);
    printer->baud_rate = THPRINTER_BAUDRATE;
    printer->read_wait_time = THPRINTER_READ_WAIT_TIME;
    ret = serial_port_open(printer);
    if(ret != SERIAL_OPEN_OK)
    {
    return THPRINTER_SERIAL_ERR;
    }
    return(THPRINTER_OK);
    }

    I selected the serial channel as a SCIg in device tree.

    When I call this function form main the following function get call from sh-sci.c

    static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
    struct ktermios *old)

    I added log in this function.

    In this function, I added SCIg initialization for Smart Card interface. and try to readback the written values.

    I tried as as per your suggestion, still not getting SCMR value which set as 0xF3.

    following are the log for this function.

    [ 56.166802] sh-sci 1004d400.serial: Pravin = SCI Set termios started
    [ 56.173673] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.178503] sh-sci 1004d400.serial: Pravin = SCI-SCSCR = 0 = 0X0
    [ 56.184554] sh-sci 1004d400.serial: Out Offset = 6
    [ 56.189368] sh-sci 1004d400.serial: Pravin = SCI-SCSCMR = 0 = 0X0
    [ 56.195592] sh-sci 1004d400.serial: Pravin = SCI Set termios processing
    [ 56.202236] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.207020] sh-sci 1004d400.serial: Out Offset = 4
    [ 56.211800] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.216577] sh-sci 1004d400.serial: Out Offset = 0
    [ 56.221352] sh-sci 1004d400.serial: Out Offset = 1
    [ 56.226236] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.231015] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.235837] sh-sci 1004d400.serial: Pravin SCI Smart Card Init start
    [ 56.242233] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.247055] sh-sci 1004d400.serial: Pravin = SCI-SCSCR = 0 = 0X0
    [ 56.253102] sh-sci 1004d400.serial: Out Offset = 4
    [ 56.257912] sh-sci 1004d400.serial: Pravin = SCI-SCxSR = 0 = 0X0
    [ 56.264044] sh-sci 1004d400.serial: Out Offset = 0
    [ 56.268853] sh-sci 1004d400.serial: Pravin = SCI-SCSMR = 32 = 0X20
    [ 56.275070] sh-sci 1004d400.serial: Out Offset = 6
    [ 56.279883] sh-sci 1004d400.serial: Pravin = SCI-SCSCMR = 0 = 0X0
    [ 56.286113] sh-sci 1004d400.serial: Out Offset = 2
    [ 56.290943] sh-sci 1004d400.serial: Pravin = SCI-SCSCR = 1 = 0X1
    [ 56.296994] sh-sci 1004d400.serial: Pravin SCI Smart Card Init Complete

    Can you suggest any changes required or any thing I missed.

    Thanks

    Pravin Raut 

  • Hi Chris,

    For testing SCIg channel, I am using RZG2L SMARC EVK. Since SCI1 channel pins are not assessable on EVK board.

    Meanwhile for writing code or enabling SCI1 channel, I use P45_0, P45_1, P45_2 for SCI1 pins.

    Those pin are connected to Audio codec.

    I disable the codec section from dtsi file and enable SCI1.    

    Can you please confirm that, It is compulsory to have TX and RX short and pull up as require for the SCIg SMART Card configuration for initialization of the SCIg channel. (Not for Data transfer in initial stage).

    Thanks 

    Pravin Raut.

  • Can you please confirm that, It is compulsory to have TX and RX short and pull up as require for the SCIg SMART Card configuration for initialization of the SCIg channel. (Not for Data transfer in initial stage).

    Sorry, I do not know.

  • Hi Chris,

    We conform about the hardware connectivity. That is not required for SCIg channel initialization.

    In the sh-sci.c file, function static int sci_probe(struct platform_device *dev),

    We found that, sysfs_create_file function is not get call. so we add following code patch in that.

    if (sp->port.type == PORT_SCIFA || sp->port.type == PORT_SCIFB ||
        sp->port.type == PORT_HSCIF || sp->port.type == PORT_SCI) {
    ret = sysfs_create_file(&dev->dev.kobj,
    &dev_attr_rx_fifo_timeout.attr);

    Also in the function sci_serial_in and sci_serial_out, i added regshift = 0 in both function.

    By doing this I can write and Read SCIg channel register.

    Can you conform why below statement is added in the sci_init_single function.

    if (port->type == PORT_SCI) {
    if (sci_port->reg_size >= 0x20)
    port->regshift = 2;
    else
    port->regshift = 1;
    }

     In this function regshift value is change to regshift=2;

    Please guide us this.

    Thanks 

    Pravin Raut

  • Can you conform why below statement is added in the sci_init_single function.

    if (port->type == PORT_SCI) {
    if (sci_port->reg_size >= 0x20)
    port->regshift = 2;
    else
    port->regshift = 1;
    }

    What happens is, the chip designers start with a standard IP block (SCI). But, they might modify it for the SoC they are making. But....then next time another design team might modify it. Many years later......you have many difference versions of the same SCI. For the Linux driver, it does not know what modifications were done or what version it is.

    In the code you show, what you will see is that design team did not change the registers....but they did change the addresses of them. The original SCI was 8-bit, and the register addresses were next to each other. But later, the register addressed needed to be 16-bit. And years later....32-bit. This means the addresses of the registers hanged. That is what "regshift" means.

    regshift=0 means 8-bit register addresses

    regshift=1 means 16-bit register addresses

    regshift=2 means 32-bit register addresses

    They are still the same registers....but at different addresses.

  • Hi Chris,

    I completed Initialization of the SCIg channel in smart card configration.

    Validate the configuration by the reading back the registers.

    Now I am trying to transmit data on SCIg channel.

    I found that the function sci_start_tx function get call after I transmit the character over TX line, but 

    sci_poll_put_char or sci_transmit_chars function is not called to transmit character.

    After  sci_start_tx, sci_stop_tx function get call with some delay.

    Can you guide us for the same.

    Thanks

    Chris

      

  • Sorry, I do not know the reason.