]>
Commit | Line | Data |
---|---|---|
1e9a164e DH |
1 | /* GRLIB APBUART Serial controller driver |
2 | * | |
3 | * (C) Copyright 2007 | |
4 | * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. | |
5 | * | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License as | |
11 | * published by the Free Software Foundation; either version 2 of | |
12 | * the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
22 | * MA 02111-1307 USA | |
23 | * | |
24 | */ | |
25 | ||
26 | #include <common.h> | |
27 | #include <asm/processor.h> | |
28 | #include <asm/leon.h> | |
29 | #include <ambapp.h> | |
29b5ff7f MV |
30 | #include <serial.h> |
31 | #include <linux/compiler.h> | |
1e9a164e DH |
32 | |
33 | DECLARE_GLOBAL_DATA_PTR; | |
34 | ||
1e9a164e DH |
35 | ambapp_dev_apbuart *leon3_apbuart = NULL; |
36 | ||
29b5ff7f | 37 | static int leon3_serial_init(void) |
1e9a164e DH |
38 | { |
39 | ambapp_apbdev apbdev; | |
40 | unsigned int tmp; | |
41 | ||
42 | /* find UART */ | |
43 | if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_APBUART, &apbdev) == 1) { | |
44 | ||
45 | leon3_apbuart = (ambapp_dev_apbuart *) apbdev.address; | |
46 | ||
47 | /* found apbuart, let's init... | |
48 | * | |
49 | * Set scaler / baud rate | |
50 | * | |
51 | * Receiver & transmitter enable | |
52 | */ | |
6d0f6bcf | 53 | leon3_apbuart->scaler = CONFIG_SYS_GRLIB_APBUART_SCALER; |
1e9a164e DH |
54 | |
55 | /* Let bit 11 be unchanged (debug bit for GRMON) */ | |
56 | tmp = READ_WORD(leon3_apbuart->ctrl); | |
57 | ||
58 | leon3_apbuart->ctrl = ((tmp & LEON_REG_UART_CTRL_DBG) | | |
59 | LEON_REG_UART_CTRL_RE | | |
60 | LEON_REG_UART_CTRL_TE); | |
61 | ||
62 | return 0; | |
63 | } | |
64 | return -1; /* didn't find hardware */ | |
65 | } | |
66 | ||
29b5ff7f | 67 | static void leon3_serial_putc_raw(const char c) |
1e9a164e DH |
68 | { |
69 | if (!leon3_apbuart) | |
70 | return; | |
71 | ||
72 | /* Wait for last character to go. */ | |
73 | while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_THE)) ; | |
74 | ||
75 | /* Send data */ | |
76 | leon3_apbuart->data = c; | |
77 | ||
78 | #ifdef LEON_DEBUG | |
79 | /* Wait for data to be sent */ | |
80 | while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_TSE)) ; | |
81 | #endif | |
82 | } | |
83 | ||
29b5ff7f MV |
84 | static void leon3_serial_putc(const char c) |
85 | { | |
86 | if (c == '\n') | |
87 | leon3_serial_putc_raw('\r'); | |
88 | ||
89 | leon3_serial_putc_raw(c); | |
90 | } | |
91 | ||
29b5ff7f | 92 | static int leon3_serial_getc(void) |
1e9a164e DH |
93 | { |
94 | if (!leon3_apbuart) | |
95 | return 0; | |
96 | ||
97 | /* Wait for a character to arrive. */ | |
98 | while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_DR)) ; | |
99 | ||
100 | /* read data */ | |
101 | return READ_WORD(leon3_apbuart->data); | |
102 | } | |
103 | ||
29b5ff7f | 104 | static int leon3_serial_tstc(void) |
1e9a164e DH |
105 | { |
106 | if (leon3_apbuart) | |
107 | return (READ_WORD(leon3_apbuart->status) & | |
108 | LEON_REG_UART_STATUS_DR); | |
109 | return 0; | |
110 | } | |
111 | ||
112 | /* set baud rate for uart */ | |
29b5ff7f | 113 | static void leon3_serial_setbrg(void) |
1e9a164e DH |
114 | { |
115 | /* update baud rate settings, read it from gd->baudrate */ | |
116 | unsigned int scaler; | |
117 | if (leon3_apbuart && (gd->baudrate > 0)) { | |
118 | scaler = | |
119 | (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - | |
120 | 5) / 10; | |
121 | leon3_apbuart->scaler = scaler; | |
122 | } | |
123 | return; | |
124 | } | |
29b5ff7f | 125 | |
29b5ff7f MV |
126 | static struct serial_device leon3_serial_drv = { |
127 | .name = "leon3_serial", | |
128 | .start = leon3_serial_init, | |
129 | .stop = NULL, | |
130 | .setbrg = leon3_serial_setbrg, | |
131 | .putc = leon3_serial_putc, | |
ec3fd689 | 132 | .puts = default_serial_puts, |
29b5ff7f MV |
133 | .getc = leon3_serial_getc, |
134 | .tstc = leon3_serial_tstc, | |
135 | }; | |
136 | ||
137 | void leon3_serial_initialize(void) | |
138 | { | |
139 | serial_register(&leon3_serial_drv); | |
140 | } | |
141 | ||
142 | __weak struct serial_device *default_serial_console(void) | |
143 | { | |
144 | return &leon3_serial_drv; | |
145 | } |