blob: eb141619b87448a8aa45c5794ddb8db1d54047d0 [file] [log] [blame]
wdenk945af8d2003-07-16 21:53:01 +00001/*
2 * (C) Copyright 2000 - 2003
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
Stefan Roesea47a12b2010-04-15 16:07:28 +020024 * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
wdenk945af8d2003-07-16 21:53:01 +000025 * Linux/PPC sources (m8260_tty.c had no copyright info in it).
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020026 *
27 * Martin Krause, 8 Jun 2006
Marek Vasuta3827252012-09-14 23:44:09 +020028 * Added SERIAL_MULTI support
wdenk945af8d2003-07-16 21:53:01 +000029 */
30
31/*
32 * Minimal serial functions needed to use one of the PSC ports
33 * as serial console interface.
34 */
35
36#include <common.h>
Mike Frysinger6c768ca2011-04-29 18:03:29 +000037#include <linux/compiler.h>
wdenk945af8d2003-07-16 21:53:01 +000038#include <mpc5xxx.h>
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020039#include <serial.h>
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020040
Wolfgang Denkd87080b2006-03-31 18:32:53 +020041DECLARE_GLOBAL_DATA_PTR;
42
wdenk945af8d2003-07-16 21:53:01 +000043#if defined(CONFIG_PSC_CONSOLE)
44
45#if CONFIG_PSC_CONSOLE == 1
46#define PSC_BASE MPC5XXX_PSC1
47#elif CONFIG_PSC_CONSOLE == 2
48#define PSC_BASE MPC5XXX_PSC2
49#elif CONFIG_PSC_CONSOLE == 3
50#define PSC_BASE MPC5XXX_PSC3
wdenk945af8d2003-07-16 21:53:01 +000051#elif CONFIG_PSC_CONSOLE == 4
52#define PSC_BASE MPC5XXX_PSC4
53#elif CONFIG_PSC_CONSOLE == 5
54#define PSC_BASE MPC5XXX_PSC5
55#elif CONFIG_PSC_CONSOLE == 6
56#define PSC_BASE MPC5XXX_PSC6
57#else
58#error CONFIG_PSC_CONSOLE must be in 1 ... 6
59#endif
60
Marek Vasuta3827252012-09-14 23:44:09 +020061#if defined(CONFIG_PSC_CONSOLE2)
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020062
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020063#if CONFIG_PSC_CONSOLE2 == 1
64#define PSC_BASE2 MPC5XXX_PSC1
65#elif CONFIG_PSC_CONSOLE2 == 2
66#define PSC_BASE2 MPC5XXX_PSC2
67#elif CONFIG_PSC_CONSOLE2 == 3
68#define PSC_BASE2 MPC5XXX_PSC3
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020069#elif CONFIG_PSC_CONSOLE2 == 4
70#define PSC_BASE2 MPC5XXX_PSC4
71#elif CONFIG_PSC_CONSOLE2 == 5
72#define PSC_BASE2 MPC5XXX_PSC5
73#elif CONFIG_PSC_CONSOLE2 == 6
74#define PSC_BASE2 MPC5XXX_PSC6
75#else
76#error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
77#endif
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020078
Marek Vasuta3827252012-09-14 23:44:09 +020079#endif
80
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020081int serial_init_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +000082{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020083 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +000084 unsigned long baseclk;
85 int div;
86
87 /* reset PSC */
88 psc->command = PSC_SEL_MODE_REG_1;
89
90 /* select clock sources */
wdenk945af8d2003-07-16 21:53:01 +000091 psc->psc_clock_select = 0;
wdenkb98fff12004-02-09 20:51:26 +000092 baseclk = (gd->ipb_clk + 16) / 32;
wdenk945af8d2003-07-16 21:53:01 +000093
94 /* switch to UART mode */
95 psc->sicr = 0;
96
97 /* configure parity, bit length and so on */
wdenk945af8d2003-07-16 21:53:01 +000098 psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
wdenk945af8d2003-07-16 21:53:01 +000099 psc->mode = PSC_MODE_ONE_STOP;
100
101 /* set up UART divisor */
wdenkb98fff12004-02-09 20:51:26 +0000102 div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
103 psc->ctur = (div >> 8) & 0xff;
wdenk945af8d2003-07-16 21:53:01 +0000104 psc->ctlr = div & 0xff;
105
106 /* disable all interrupts */
107 psc->psc_imr = 0;
108
109 /* reset and enable Rx/Tx */
110 psc->command = PSC_RST_RX;
111 psc->command = PSC_RST_TX;
112 psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
113
114 return (0);
115}
116
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200117void serial_putc_dev (unsigned long dev_base, const char c)
wdenk945af8d2003-07-16 21:53:01 +0000118{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200119 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000120
121 if (c == '\n')
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200122 serial_putc_dev (dev_base, '\r');
wdenk945af8d2003-07-16 21:53:01 +0000123
124 /* Wait for last character to go. */
125 while (!(psc->psc_status & PSC_SR_TXEMP))
126 ;
127
128 psc->psc_buffer_8 = c;
129}
130
Wolfgang Denke8143e72006-08-30 23:09:00 +0200131void serial_putc_raw_dev(unsigned long dev_base, const char c)
Wolfgang Denke8143e72006-08-30 23:09:00 +0200132{
Wolfgang Denke8143e72006-08-30 23:09:00 +0200133 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
Wolfgang Denke8143e72006-08-30 23:09:00 +0200134 /* Wait for last character to go. */
135 while (!(psc->psc_status & PSC_SR_TXEMP))
136 ;
137
138 psc->psc_buffer_8 = c;
139}
140
141
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200142void serial_puts_dev (unsigned long dev_base, const char *s)
wdenk945af8d2003-07-16 21:53:01 +0000143{
144 while (*s) {
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200145 serial_putc_dev (dev_base, *s++);
wdenk945af8d2003-07-16 21:53:01 +0000146 }
147}
148
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200149int serial_getc_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +0000150{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200151 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000152
153 /* Wait for a character to arrive. */
154 while (!(psc->psc_status & PSC_SR_RXRDY))
155 ;
156
157 return psc->psc_buffer_8;
158}
159
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200160int serial_tstc_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +0000161{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200162 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000163
164 return (psc->psc_status & PSC_SR_RXRDY);
165}
166
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200167void serial_setbrg_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +0000168{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200169 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000170 unsigned long baseclk, div;
171
wdenk342717f2005-06-27 13:30:03 +0000172 baseclk = (gd->ipb_clk + 16) / 32;
wdenk945af8d2003-07-16 21:53:01 +0000173
174 /* set up UART divisor */
wdenk342717f2005-06-27 13:30:03 +0000175 div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
Wolfgang Denk9f221d02005-09-25 01:09:58 +0200176 psc->ctur = (div >> 8) & 0xFF;
177 psc->ctlr = div & 0xff;
wdenk945af8d2003-07-16 21:53:01 +0000178}
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200179
Wolfgang Denke8143e72006-08-30 23:09:00 +0200180void serial_setrts_dev (unsigned long dev_base, int s)
Wolfgang Denke8143e72006-08-30 23:09:00 +0200181{
Wolfgang Denke8143e72006-08-30 23:09:00 +0200182 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
Wolfgang Denke8143e72006-08-30 23:09:00 +0200183
184 if (s) {
185 /* Assert RTS (become LOW) */
186 psc->op1 = 0x1;
187 }
188 else {
189 /* Negate RTS (become HIGH) */
190 psc->op0 = 0x1;
191 }
192}
193
Wolfgang Denke8143e72006-08-30 23:09:00 +0200194int serial_getcts_dev (unsigned long dev_base)
Wolfgang Denke8143e72006-08-30 23:09:00 +0200195{
Wolfgang Denke8143e72006-08-30 23:09:00 +0200196 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
Wolfgang Denke8143e72006-08-30 23:09:00 +0200197
198 return (psc->ip & 0x1) ? 0 : 1;
199}
200
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200201int serial0_init(void)
202{
203 return (serial_init_dev(PSC_BASE));
204}
205
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200206void serial0_setbrg (void)
207{
208 serial_setbrg_dev(PSC_BASE);
209}
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200210
211void serial0_putc(const char c)
212{
213 serial_putc_dev(PSC_BASE,c);
214}
215
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200216void serial0_puts(const char *s)
217{
218 serial_puts_dev(PSC_BASE, s);
219}
220
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200221int serial0_getc(void)
222{
223 return(serial_getc_dev(PSC_BASE));
224}
225
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200226int serial0_tstc(void)
227{
228 return (serial_tstc_dev(PSC_BASE));
229}
230
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200231struct serial_device serial0_device =
232{
Marek Vasut90bad892012-09-09 18:48:28 +0200233 .name = "serial0",
234 .start = serial0_init,
235 .stop = NULL,
236 .setbrg = serial0_setbrg,
237 .getc = serial0_getc,
238 .tstc = serial0_tstc,
239 .putc = serial0_putc,
240 .puts = serial0_puts,
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200241};
242
Mike Frysinger6c768ca2011-04-29 18:03:29 +0000243__weak struct serial_device *default_serial_console(void)
244{
245 return &serial0_device;
246}
247
Marek Vasuta3827252012-09-14 23:44:09 +0200248#ifdef CONFIG_PSC_CONSOLE2
249int serial1_init(void)
250{
251 return serial_init_dev(PSC_BASE2);
252}
253
254void serial1_setbrg(void)
255{
256 serial_setbrg_dev(PSC_BASE2);
257}
258
259void serial1_putc(const char c)
260{
261 serial_putc_dev(PSC_BASE2, c);
262}
263
264void serial1_puts(const char *s)
265{
266 serial_puts_dev(PSC_BASE2, s);
267}
268
269int serial1_getc(void)
270{
271 return serial_getc_dev(PSC_BASE2);
272}
273
274int serial1_tstc(void)
275{
276 return serial_tstc_dev(PSC_BASE2);
277}
278
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200279struct serial_device serial1_device =
280{
Marek Vasut90bad892012-09-09 18:48:28 +0200281 .name = "serial1",
282 .start = serial1_init,
283 .stop = NULL,
284 .setbrg = serial1_setbrg,
285 .getc = serial1_getc,
286 .tstc = serial1_tstc,
287 .putc = serial1_putc,
288 .puts = serial1_puts,
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200289};
Marek Vasuta3827252012-09-14 23:44:09 +0200290#endif /* CONFIG_PSC_CONSOLE2 */
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200291
wdenk945af8d2003-07-16 21:53:01 +0000292#endif /* CONFIG_PSC_CONSOLE */