blob: ee44ba26445c356d91a078364b89dce487b561dd [file] [log] [blame]
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +09001/*
2 * SuperH SCIF device driver.
3 * Copyright (c) 2007 Nobuhiro Iwamatsu
Wolfgang Denk0a5c2142007-12-27 01:52:50 +01004 *
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +09005 * 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/processor.h>
22
23#ifdef CFG_SCIF_CONSOLE
24
25#if defined (CONFIG_CONS_SCIF0)
26#define SCIF_BASE SCIF0_BASE
27#elif defined (CONFIG_CONS_SCIF1)
28#define SCIF_BASE SCIF1_BASE
29#else
30#error "Default SCIF doesn't set....."
31#endif
32
Nobuhiro Iwamatsu8c6fe762007-11-25 02:32:13 +090033#define SCSMR (vu_short *)(SCIF_BASE + 0x0)
Wolfgang Denk0a5c2142007-12-27 01:52:50 +010034#define SCBRR (vu_char *)(SCIF_BASE + 0x4)
Nobuhiro Iwamatsu8c6fe762007-11-25 02:32:13 +090035#define SCSCR (vu_short *)(SCIF_BASE + 0x8)
36#define SCFTDR (vu_char *)(SCIF_BASE + 0xC)
37#define SCFSR (vu_short *)(SCIF_BASE + 0x10)
38#define SCFRDR (vu_char *)(SCIF_BASE + 0x14)
39#define SCFCR (vu_short *)(SCIF_BASE + 0x18)
40#define SCFDR (vu_short *)(SCIF_BASE + 0x1C)
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +090041#if defined(CONFIG_SH4A)
Nobuhiro Iwamatsu8c6fe762007-11-25 02:32:13 +090042#define SCRFDR (vu_short *)(SCIF_BASE + 0x20)
43#define SCSPTR (vu_short *)(SCIF_BASE + 0x24)
44#define SCLSR (vu_short *)(SCIF_BASE + 0x28)
45#define SCRER (vu_short *)(SCIF_BASE + 0x2C)
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +090046#elif defined (CONFIG_SH4)
Nobuhiro Iwamatsu8c6fe762007-11-25 02:32:13 +090047#define SCSPTR (vu_short *)(SCIF_BASE + 0x20)
48#define SCLSR (vu_short *)(SCIF_BASE + 0x24)
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +090049#elif defined (CONFIG_SH3)
Nobuhiro Iwamatsu8c6fe762007-11-25 02:32:13 +090050#define SCLSR (vu_short *)(SCIF_BASE + 0x24)
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +090051#endif
52
53#define SCR_RE (1 << 4)
Wolfgang Denk0a5c2142007-12-27 01:52:50 +010054#define SCR_TE (1 << 5)
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +090055#define FCR_RFRST (1 << 1) /* RFCL */
56#define FCR_TFRST (1 << 2) /* TFCL */
57#define FSR_DR (1 << 0)
58#define FSR_RDF (1 << 1)
59#define FSR_FER (1 << 3)
60#define FSR_BRK (1 << 4)
61#define FSR_FER (1 << 3)
62#define FSR_TEND (1 << 6)
63#define FSR_ER (1 << 7)
64
65/*----------------------------------------------------------------------*/
66
67void serial_setbrg (void)
68{
69 DECLARE_GLOBAL_DATA_PTR;
70 int divisor = gd->baudrate * 32;
71
Wolfgang Denk0a5c2142007-12-27 01:52:50 +010072 *SCBRR = (CONFIG_SYS_CLK_FREQ + (divisor / 2)) /
Nobuhiro Iwamatsu970dc332007-05-13 20:58:00 +090073 (gd->baudrate * 32) - 1;
74}
75
76int serial_init (void)
77{
78 *SCSCR = (SCR_RE | SCR_TE);
79 *SCSMR = 0 ;
80 *SCSMR = 0;
81 *SCFCR = (FCR_RFRST | FCR_TFRST);
82 *SCFCR;
83 *SCFCR = 0;
84
85 serial_setbrg();
86 return 0;
87}
88
89static int serial_tx_fifo_level (void)
90{
91 return (*SCFDR >> 8) & 0x1F;
92}
93
94static int serial_rx_fifo_level (void)
95{
96 return (*SCFDR >> 0) & 0x1F;
97}
98
99void serial_raw_putc (const char c)
100{
101 unsigned int fsr_bits_to_clear;
102
103 while (1) {
104 if (*SCFSR & FSR_TEND) { /* Tx fifo is empty */
105 fsr_bits_to_clear = FSR_TEND;
106 break;
107 }
108 }
109
110 *SCFTDR = c;
111 if (fsr_bits_to_clear != 0)
112 *SCFSR &= ~fsr_bits_to_clear;
113}
114
115void serial_putc (const char c)
116{
117 if (c == '\n')
118 serial_raw_putc ('\r');
119 serial_raw_putc (c);
120}
121
122void serial_puts (const char *s)
123{
124 char c;
125 while ((c = *s++) != 0)
126 serial_putc (c);
127}
128
129int serial_tstc (void)
130{
131 return serial_rx_fifo_level() ? 1 : 0;
132}
133
134#define FSR_ERR_CLEAR 0x0063
135#define RDRF_CLEAR 0x00fc
136#define LSR_ORER 1
137void handle_error( void ){
138
139 (void)*SCFSR ;
140 *SCFSR = FSR_ERR_CLEAR ;
141 (void)*SCLSR ;
142 *SCLSR = 0x00 ;
143}
144
145int serial_getc_check( void ){
146 unsigned short status;
147
148 status = *SCFSR ;
149
150 if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
151 handle_error();
152 if( *SCLSR & LSR_ORER )
153 handle_error();
154 return (status & ( FSR_DR | FSR_RDF ));
155}
156
157int serial_getc (void)
158{
159 unsigned short status ;
160 char ch;
161 while(!serial_getc_check());
162
163 ch = *SCFRDR;
164 status = *SCFSR ;
165
166 *SCFSR = RDRF_CLEAR ;
167
168 if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
169 handle_error();
170
171 if( *SCLSR & LSR_ORER )
172 handle_error();
173
174 return ch ;
175}
176
177#endif /* CFG_SCIF_CONSOLE */