uboot/drivers/serial/serial_sh.c
<<
>>
Prefs
   1/*
   2 * SuperH SCIF device driver.
   3 * Copyright (c) 2007,2008 Nobuhiro Iwamatsu
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 */
  19
  20#include <common.h>
  21#include <asm/io.h>
  22#include <asm/processor.h>
  23
  24#if defined(CONFIG_CONS_SCIF0)
  25# define SCIF_BASE      SCIF0_BASE
  26#elif defined(CONFIG_CONS_SCIF1)
  27# define SCIF_BASE      SCIF1_BASE
  28#elif defined(CONFIG_CONS_SCIF2)
  29# define SCIF_BASE      SCIF2_BASE
  30#elif defined(CONFIG_CONS_SCIF3)
  31# define SCIF_BASE      SCIF3_BASE
  32#elif defined(CONFIG_CONS_SCIF4)
  33# define SCIF_BASE      SCIF4_BASE
  34#elif defined(CONFIG_CONS_SCIF5)
  35# define SCIF_BASE      SCIF5_BASE
  36#else
  37# error "Default SCIF doesn't set....."
  38#endif
  39
  40/* Base register */
  41#define SCSMR   (vu_short *)(SCIF_BASE + 0x0)
  42#define SCBRR   (vu_char  *)(SCIF_BASE + 0x4)
  43#define SCSCR   (vu_short *)(SCIF_BASE + 0x8)
  44#define SCFCR   (vu_short *)(SCIF_BASE + 0x18)
  45#define SCFDR   (vu_short *)(SCIF_BASE + 0x1C)
  46#if defined(CONFIG_CPU_SH7720) || \
  47        (defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A))
  48# define SCFSR  (vu_short *)(SCIF_BASE + 0x14)  /* SCSSR */
  49# define SCFTDR (vu_char  *)(SCIF_BASE + 0x20)
  50# define SCFRDR (vu_char  *)(SCIF_BASE + 0x24)
  51#else
  52# define SCFTDR (vu_char  *)(SCIF_BASE + 0xC)
  53# define SCFSR  (vu_short *)(SCIF_BASE + 0x10)
  54# define SCFRDR (vu_char  *)(SCIF_BASE + 0x14)
  55#endif
  56
  57#if     defined(CONFIG_CPU_SH7780) || \
  58        defined(CONFIG_CPU_SH7785)
  59# define SCRFDR (vu_short *)(SCIF_BASE + 0x20)
  60# define SCSPTR (vu_short *)(SCIF_BASE + 0x24)
  61# define SCLSR  (vu_short *)(SCIF_BASE + 0x28)
  62# define SCRER  (vu_short *)(SCIF_BASE + 0x2C)
  63# define LSR_ORER       1
  64# define FIFOLEVEL_MASK 0xFF
  65#elif defined(CONFIG_CPU_SH7763)
  66# if defined(CONFIG_CONS_SCIF2)
  67# define SCSPTR (vu_short *)(SCIF_BASE + 0x20)
  68# define SCLSR  (vu_short *)(SCIF_BASE + 0x24)
  69# define LSR_ORER       1
  70# define FIFOLEVEL_MASK 0x1F
  71# else
  72# define SCRFDR (vu_short *)(SCIF_BASE + 0x20)
  73# define SCSPTR (vu_short *)(SCIF_BASE + 0x24)
  74# define SCLSR  (vu_short *)(SCIF_BASE + 0x28)
  75# define SCRER  (vu_short *)(SCIF_BASE + 0x2C)
  76# define LSR_ORER       1
  77# define FIFOLEVEL_MASK 0xFF
  78# endif
  79#elif defined(CONFIG_CPU_SH7723)
  80# if defined(CONFIG_SCIF_A)
  81# define SCLSR  SCFSR
  82# define LSR_ORER       0x0200
  83# define FIFOLEVEL_MASK 0x3F
  84#else
  85# define SCLSR  (vu_short *)(SCIF_BASE + 0x24)
  86# define LSR_ORER       1
  87# define FIFOLEVEL_MASK 0x1F
  88#endif
  89#elif defined(CONFIG_CPU_SH7750) || \
  90        defined(CONFIG_CPU_SH7751) || \
  91        defined(CONFIG_CPU_SH7722) || \
  92        defined(CONFIG_CPU_SH7203)
  93# define SCSPTR (vu_short *)(SCIF_BASE + 0x20)
  94# define SCLSR  (vu_short *)(SCIF_BASE + 0x24)
  95# define LSR_ORER       1
  96# define FIFOLEVEL_MASK 0x1F
  97#elif defined(CONFIG_CPU_SH7720)
  98# define SCLSR          SCFSR
  99# define LSR_ORER       0x0200
 100# define FIFOLEVEL_MASK 0x1F
 101#elif defined(CONFIG_CPU_SH7710) || \
 102        defined(CONFIG_CPU_SH7712)
 103# define SCLSR  SCFSR           /* SCSSR */
 104# define LSR_ORER       1
 105# define FIFOLEVEL_MASK 0x1F
 106#endif
 107
 108/* SCBRR register value setting */
 109#if defined(CONFIG_CPU_SH7720)
 110# define SCBRR_VALUE(bps, clk) (((clk * 2) + 16 * bps) / (32 * bps) - 1)
 111#elif defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A)
 112/* SH7723 SCIFA use bus clock. So clock *2 */
 113# define SCBRR_VALUE(bps, clk) (((clk * 2 * 2) + 16 * bps) / (32 * bps) - 1)
 114#else /* Generic SuperH */
 115# define SCBRR_VALUE(bps, clk) ((clk + 16 * bps) / (32 * bps) - 1)
 116#endif
 117
 118#define SCR_RE          (1 << 4)
 119#define SCR_TE          (1 << 5)
 120#define FCR_RFRST       (1 << 1)        /* RFCL */
 121#define FCR_TFRST       (1 << 2)        /* TFCL */
 122#define FSR_DR          (1 << 0)
 123#define FSR_RDF         (1 << 1)
 124#define FSR_FER         (1 << 3)
 125#define FSR_BRK         (1 << 4)
 126#define FSR_FER         (1 << 3)
 127#define FSR_TEND        (1 << 6)
 128#define FSR_ER          (1 << 7)
 129
 130/*----------------------------------------------------------------------*/
 131
 132void serial_setbrg(void)
 133{
 134        DECLARE_GLOBAL_DATA_PTR;
 135
 136        writeb(SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ), SCBRR);
 137}
 138
 139int serial_init(void)
 140{
 141        writew((SCR_RE | SCR_TE), SCSCR);
 142        writew(0, SCSMR);
 143        writew(0, SCSMR);
 144        writew((FCR_RFRST | FCR_TFRST), SCFCR);
 145        readw(SCFCR);
 146        writew(0, SCFCR);
 147
 148        serial_setbrg();
 149        return 0;
 150}
 151
 152static int serial_rx_fifo_level(void)
 153{
 154#if defined(SCRFDR)
 155        return (readw(SCRFDR) >> 0) & FIFOLEVEL_MASK;
 156#else
 157        return (readw(SCFDR) >> 0) & FIFOLEVEL_MASK;
 158#endif
 159}
 160
 161void serial_raw_putc(const char c)
 162{
 163        unsigned int fsr_bits_to_clear;
 164
 165        while (1) {
 166                if (readw(SCFSR) & FSR_TEND) { /* Tx fifo is empty */
 167                        fsr_bits_to_clear = FSR_TEND;
 168                        break;
 169                }
 170        }
 171
 172        writeb(c, SCFTDR);
 173        if (fsr_bits_to_clear != 0)
 174                writew(readw(SCFSR) & ~fsr_bits_to_clear, SCFSR);
 175}
 176
 177void serial_putc(const char c)
 178{
 179        if (c == '\n')
 180                serial_raw_putc('\r');
 181        serial_raw_putc(c);
 182}
 183
 184void serial_puts(const char *s)
 185{
 186        char c;
 187        while ((c = *s++) != 0)
 188                serial_putc(c);
 189}
 190
 191int serial_tstc(void)
 192{
 193        return serial_rx_fifo_level() ? 1 : 0;
 194}
 195
 196#define FSR_ERR_CLEAR   0x0063
 197#define RDRF_CLEAR              0x00fc
 198void handle_error(void)
 199{
 200        readw(SCFSR);
 201        writew(FSR_ERR_CLEAR, SCFSR);
 202        readw(SCLSR);
 203        writew(0x00, SCLSR);
 204}
 205
 206int serial_getc_check(void)
 207{
 208        unsigned short status;
 209
 210        status = readw(SCFSR);
 211
 212        if (status & (FSR_FER | FSR_ER | FSR_BRK))
 213                handle_error();
 214        if (readw(SCLSR) & LSR_ORER)
 215                handle_error();
 216        return status & (FSR_DR | FSR_RDF);
 217}
 218
 219int serial_getc(void)
 220{
 221        unsigned short status;
 222        char ch;
 223
 224        while (!serial_getc_check())
 225                ;
 226
 227        ch = readb(SCFRDR);
 228        status = readw(SCFSR);
 229
 230        writew(RDRF_CLEAR, SCFSR);
 231
 232        if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
 233                handle_error();
 234
 235        if (readw(SCLSR) & LSR_ORER)
 236                handle_error();
 237
 238        return ch;
 239}
 240