blob: bccdcf7973af7b601c8c0c00a7f643dbd2f0f8d6 [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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk945af8d2003-07-16 21:53:01 +00006 *
7 * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
Stefan Roesea47a12b2010-04-15 16:07:28 +02008 * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
wdenk945af8d2003-07-16 21:53:01 +00009 * Linux/PPC sources (m8260_tty.c had no copyright info in it).
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020010 *
11 * Martin Krause, 8 Jun 2006
Marek Vasuta3827252012-09-14 23:44:09 +020012 * Added SERIAL_MULTI support
wdenk945af8d2003-07-16 21:53:01 +000013 */
14
15/*
16 * Minimal serial functions needed to use one of the PSC ports
17 * as serial console interface.
18 */
19
20#include <common.h>
Mike Frysinger6c768ca2011-04-29 18:03:29 +000021#include <linux/compiler.h>
wdenk945af8d2003-07-16 21:53:01 +000022#include <mpc5xxx.h>
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020023#include <serial.h>
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020024
Wolfgang Denkd87080b2006-03-31 18:32:53 +020025DECLARE_GLOBAL_DATA_PTR;
26
wdenk945af8d2003-07-16 21:53:01 +000027#if defined(CONFIG_PSC_CONSOLE)
28
29#if CONFIG_PSC_CONSOLE == 1
30#define PSC_BASE MPC5XXX_PSC1
31#elif CONFIG_PSC_CONSOLE == 2
32#define PSC_BASE MPC5XXX_PSC2
33#elif CONFIG_PSC_CONSOLE == 3
34#define PSC_BASE MPC5XXX_PSC3
wdenk945af8d2003-07-16 21:53:01 +000035#elif CONFIG_PSC_CONSOLE == 4
36#define PSC_BASE MPC5XXX_PSC4
37#elif CONFIG_PSC_CONSOLE == 5
38#define PSC_BASE MPC5XXX_PSC5
39#elif CONFIG_PSC_CONSOLE == 6
40#define PSC_BASE MPC5XXX_PSC6
41#else
42#error CONFIG_PSC_CONSOLE must be in 1 ... 6
43#endif
44
Marek Vasuta3827252012-09-14 23:44:09 +020045#if defined(CONFIG_PSC_CONSOLE2)
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020046
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020047#if CONFIG_PSC_CONSOLE2 == 1
48#define PSC_BASE2 MPC5XXX_PSC1
49#elif CONFIG_PSC_CONSOLE2 == 2
50#define PSC_BASE2 MPC5XXX_PSC2
51#elif CONFIG_PSC_CONSOLE2 == 3
52#define PSC_BASE2 MPC5XXX_PSC3
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020053#elif CONFIG_PSC_CONSOLE2 == 4
54#define PSC_BASE2 MPC5XXX_PSC4
55#elif CONFIG_PSC_CONSOLE2 == 5
56#define PSC_BASE2 MPC5XXX_PSC5
57#elif CONFIG_PSC_CONSOLE2 == 6
58#define PSC_BASE2 MPC5XXX_PSC6
59#else
60#error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
61#endif
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020062
Marek Vasuta3827252012-09-14 23:44:09 +020063#endif
64
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020065int serial_init_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +000066{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +020067 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +000068 unsigned long baseclk;
69 int div;
70
71 /* reset PSC */
72 psc->command = PSC_SEL_MODE_REG_1;
73
74 /* select clock sources */
wdenk945af8d2003-07-16 21:53:01 +000075 psc->psc_clock_select = 0;
Simon Glassb2877492012-12-13 20:48:53 +000076 baseclk = (gd->arch.ipb_clk + 16) / 32;
wdenk945af8d2003-07-16 21:53:01 +000077
78 /* switch to UART mode */
79 psc->sicr = 0;
80
81 /* configure parity, bit length and so on */
wdenk945af8d2003-07-16 21:53:01 +000082 psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
wdenk945af8d2003-07-16 21:53:01 +000083 psc->mode = PSC_MODE_ONE_STOP;
84
85 /* set up UART divisor */
wdenkb98fff12004-02-09 20:51:26 +000086 div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
87 psc->ctur = (div >> 8) & 0xff;
wdenk945af8d2003-07-16 21:53:01 +000088 psc->ctlr = div & 0xff;
89
90 /* disable all interrupts */
91 psc->psc_imr = 0;
92
93 /* reset and enable Rx/Tx */
94 psc->command = PSC_RST_RX;
95 psc->command = PSC_RST_TX;
96 psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
97
98 return (0);
99}
100
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200101void serial_putc_dev (unsigned long dev_base, const char c)
wdenk945af8d2003-07-16 21:53:01 +0000102{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200103 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000104
105 if (c == '\n')
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200106 serial_putc_dev (dev_base, '\r');
wdenk945af8d2003-07-16 21:53:01 +0000107
108 /* Wait for last character to go. */
109 while (!(psc->psc_status & PSC_SR_TXEMP))
110 ;
111
112 psc->psc_buffer_8 = c;
113}
114
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200115void serial_puts_dev (unsigned long dev_base, const char *s)
wdenk945af8d2003-07-16 21:53:01 +0000116{
117 while (*s) {
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200118 serial_putc_dev (dev_base, *s++);
wdenk945af8d2003-07-16 21:53:01 +0000119 }
120}
121
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200122int serial_getc_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +0000123{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200124 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000125
126 /* Wait for a character to arrive. */
127 while (!(psc->psc_status & PSC_SR_RXRDY))
128 ;
129
130 return psc->psc_buffer_8;
131}
132
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200133int serial_tstc_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +0000134{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200135 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000136
137 return (psc->psc_status & PSC_SR_RXRDY);
138}
139
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200140void serial_setbrg_dev (unsigned long dev_base)
wdenk945af8d2003-07-16 21:53:01 +0000141{
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200142 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
wdenk945af8d2003-07-16 21:53:01 +0000143 unsigned long baseclk, div;
144
Simon Glassb2877492012-12-13 20:48:53 +0000145 baseclk = (gd->arch.ipb_clk + 16) / 32;
wdenk945af8d2003-07-16 21:53:01 +0000146
147 /* set up UART divisor */
wdenk342717f2005-06-27 13:30:03 +0000148 div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
Wolfgang Denk9f221d02005-09-25 01:09:58 +0200149 psc->ctur = (div >> 8) & 0xFF;
150 psc->ctlr = div & 0xff;
wdenk945af8d2003-07-16 21:53:01 +0000151}
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200152
Wolfgang Denke8143e72006-08-30 23:09:00 +0200153void serial_setrts_dev (unsigned long dev_base, int s)
Wolfgang Denke8143e72006-08-30 23:09:00 +0200154{
Wolfgang Denke8143e72006-08-30 23:09:00 +0200155 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
Wolfgang Denke8143e72006-08-30 23:09:00 +0200156
157 if (s) {
158 /* Assert RTS (become LOW) */
159 psc->op1 = 0x1;
160 }
161 else {
162 /* Negate RTS (become HIGH) */
163 psc->op0 = 0x1;
164 }
165}
166
Wolfgang Denke8143e72006-08-30 23:09:00 +0200167int serial_getcts_dev (unsigned long dev_base)
Wolfgang Denke8143e72006-08-30 23:09:00 +0200168{
Wolfgang Denke8143e72006-08-30 23:09:00 +0200169 volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
Wolfgang Denke8143e72006-08-30 23:09:00 +0200170
171 return (psc->ip & 0x1) ? 0 : 1;
172}
173
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200174int serial0_init(void)
175{
176 return (serial_init_dev(PSC_BASE));
177}
178
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200179void serial0_setbrg (void)
180{
181 serial_setbrg_dev(PSC_BASE);
182}
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200183
184void serial0_putc(const char c)
185{
186 serial_putc_dev(PSC_BASE,c);
187}
188
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200189void serial0_puts(const char *s)
190{
191 serial_puts_dev(PSC_BASE, s);
192}
193
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200194int serial0_getc(void)
195{
196 return(serial_getc_dev(PSC_BASE));
197}
198
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200199int serial0_tstc(void)
200{
201 return (serial_tstc_dev(PSC_BASE));
202}
203
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200204struct serial_device serial0_device =
205{
Marek Vasut90bad892012-09-09 18:48:28 +0200206 .name = "serial0",
207 .start = serial0_init,
208 .stop = NULL,
209 .setbrg = serial0_setbrg,
210 .getc = serial0_getc,
211 .tstc = serial0_tstc,
212 .putc = serial0_putc,
213 .puts = serial0_puts,
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200214};
215
Mike Frysinger6c768ca2011-04-29 18:03:29 +0000216__weak struct serial_device *default_serial_console(void)
217{
218 return &serial0_device;
219}
220
Marek Vasuta3827252012-09-14 23:44:09 +0200221#ifdef CONFIG_PSC_CONSOLE2
222int serial1_init(void)
223{
224 return serial_init_dev(PSC_BASE2);
225}
226
227void serial1_setbrg(void)
228{
229 serial_setbrg_dev(PSC_BASE2);
230}
231
232void serial1_putc(const char c)
233{
234 serial_putc_dev(PSC_BASE2, c);
235}
236
237void serial1_puts(const char *s)
238{
239 serial_puts_dev(PSC_BASE2, s);
240}
241
242int serial1_getc(void)
243{
244 return serial_getc_dev(PSC_BASE2);
245}
246
247int serial1_tstc(void)
248{
249 return serial_tstc_dev(PSC_BASE2);
250}
251
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200252struct serial_device serial1_device =
253{
Marek Vasut90bad892012-09-09 18:48:28 +0200254 .name = "serial1",
255 .start = serial1_init,
256 .stop = NULL,
257 .setbrg = serial1_setbrg,
258 .getc = serial1_getc,
259 .tstc = serial1_tstc,
260 .putc = serial1_putc,
261 .puts = serial1_puts,
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200262};
Marek Vasuta3827252012-09-14 23:44:09 +0200263#endif /* CONFIG_PSC_CONSOLE2 */
Wolfgang Denkc12cffc2006-06-16 17:04:45 +0200264
wdenk945af8d2003-07-16 21:53:01 +0000265#endif /* CONFIG_PSC_CONSOLE */