~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/blackfin/include/asm/serial1.h

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * serial.h - common serial defines for early debug and serial driver.
 
3
 *            any functions defined here must be always_inline since
 
4
 *            initcode cannot have function calls.
 
5
 *
 
6
 * Copyright (c) 2004-2011 Analog Devices Inc.
 
7
 *
 
8
 * Licensed under the GPL-2 or later.
 
9
 */
 
10
 
 
11
#ifndef __BFIN_CPU_SERIAL1_H__
 
12
#define __BFIN_CPU_SERIAL1_H__
 
13
 
 
14
#include <asm/mach-common/bits/uart.h>
 
15
 
 
16
#ifndef __ASSEMBLY__
 
17
 
 
18
#include <asm/clock.h>
 
19
 
 
20
#define MMR_UART(n) _PASTE_UART(n, UART, DLL)
 
21
#ifdef UART_DLL
 
22
# define UART0_DLL UART_DLL
 
23
# if CONFIG_UART_CONSOLE != 0
 
24
#  error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
 
25
# endif
 
26
#endif
 
27
#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE)
 
28
 
 
29
#define LOB(x) ((x) & 0xFF)
 
30
#define HIB(x) (((x) >> 8) & 0xFF)
 
31
 
 
32
/*
 
33
 * All Blackfin system MMRs are padded to 32bits even if the register
 
34
 * itself is only 16bits.  So use a helper macro to streamline this.
 
35
 */
 
36
struct bfin_mmr_serial {
 
37
#if BFIN_UART_HW_VER == 2
 
38
        u16 dll;
 
39
        u16 __pad_0;
 
40
        u16 dlh;
 
41
        u16 __pad_1;
 
42
        u16 gctl;
 
43
        u16 __pad_2;
 
44
        u16 lcr;
 
45
        u16 __pad_3;
 
46
        u16 mcr;
 
47
        u16 __pad_4;
 
48
        u16 lsr;
 
49
        u16 __pad_5;
 
50
        u16 msr;
 
51
        u16 __pad_6;
 
52
        u16 scr;
 
53
        u16 __pad_7;
 
54
        u16 ier_set;
 
55
        u16 __pad_8;
 
56
        u16 ier_clear;
 
57
        u16 __pad_9;
 
58
        u16 thr;
 
59
        u16 __pad_10;
 
60
        u16 rbr;
 
61
        u16 __pad_11;
 
62
#else
 
63
        union {
 
64
                u16 dll;
 
65
                u16 thr;
 
66
                const u16 rbr;
 
67
        };
 
68
        const u16 __spad0;
 
69
        union {
 
70
                u16 dlh;
 
71
                u16 ier;
 
72
        };
 
73
        const u16 __spad1;
 
74
        const u16 iir;
 
75
        u16 __pad_0;
 
76
        u16 lcr;
 
77
        u16 __pad_1;
 
78
        u16 mcr;
 
79
        u16 __pad_2;
 
80
        u16 lsr;
 
81
        u16 __pad_3;
 
82
        u16 msr;
 
83
        u16 __pad_4;
 
84
        u16 scr;
 
85
        u16 __pad_5;
 
86
        const u32 __spad2;
 
87
        u16 gctl;
 
88
        u16 __pad_6;
 
89
#endif
 
90
};
 
91
 
 
92
#define uart_lsr_t uint32_t
 
93
#define _lsr_read(p)     bfin_read(&p->lsr)
 
94
#define _lsr_write(p, v) bfin_write(&p->lsr, v)
 
95
 
 
96
#if BFIN_UART_HW_VER == 2
 
97
# define ACCESS_LATCH()
 
98
# define ACCESS_PORT_IER()
 
99
#else
 
100
# define ACCESS_LATCH()    bfin_write_or(&pUART->lcr, DLAB)
 
101
# define ACCESS_PORT_IER() bfin_write_and(&pUART->lcr, ~DLAB)
 
102
#endif
 
103
 
 
104
__attribute__((always_inline))
 
105
static inline void serial_early_do_mach_portmux(char port, int mux_mask,
 
106
        int mux_func, int port_pin)
 
107
{
 
108
        switch (port) {
 
109
#if defined(__ADSPBF54x__)
 
110
        case 'B':
 
111
                bfin_write_PORTB_MUX((bfin_read_PORTB_MUX() &
 
112
                        ~mux_mask) | mux_func);
 
113
                bfin_write_PORTB_FER(bfin_read_PORTB_FER() | port_pin);
 
114
                break;
 
115
        case 'E':
 
116
                bfin_write_PORTE_MUX((bfin_read_PORTE_MUX() &
 
117
                        ~mux_mask) | mux_func);
 
118
                bfin_write_PORTE_FER(bfin_read_PORTE_FER() | port_pin);
 
119
                break;
 
120
#endif
 
121
#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF52x__)
 
122
        case 'F':
 
123
                bfin_write_PORTF_MUX((bfin_read_PORTF_MUX() &
 
124
                        ~mux_mask) | mux_func);
 
125
                bfin_write_PORTF_FER(bfin_read_PORTF_FER() | port_pin);
 
126
                break;
 
127
        case 'G':
 
128
                bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() &
 
129
                        ~mux_mask) | mux_func);
 
130
                bfin_write_PORTG_FER(bfin_read_PORTG_FER() | port_pin);
 
131
                break;
 
132
        case 'H':
 
133
                bfin_write_PORTH_MUX((bfin_read_PORTH_MUX() &
 
134
                        ~mux_mask) | mux_func);
 
135
                bfin_write_PORTH_FER(bfin_read_PORTH_FER() | port_pin);
 
136
                break;
 
137
#endif
 
138
        default:
 
139
                break;
 
140
        }
 
141
}
 
142
 
 
143
__attribute__((always_inline))
 
144
static inline void serial_early_do_portmux(void)
 
145
{
 
146
#if defined(__ADSPBF50x__)
 
147
        switch (CONFIG_UART_CONSOLE) {
 
148
        case 0:
 
149
                serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK,
 
150
                PORT_x_MUX_7_FUNC_1, PG12); /* TX: G; mux 7; func 1; PG12 */
 
151
                serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK,
 
152
                PORT_x_MUX_7_FUNC_1, PG13); /* RX: G; mux 7; func 1; PG13 */
 
153
                break;
 
154
        case 1:
 
155
                serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK,
 
156
                PORT_x_MUX_3_FUNC_1, PF7); /* TX: F; mux 3; func 1; PF6 */
 
157
                serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK,
 
158
                PORT_x_MUX_3_FUNC_1, PF6); /* RX: F; mux 3; func 1; PF7 */
 
159
                break;
 
160
        }
 
161
#elif defined(__ADSPBF51x__)
 
162
        switch (CONFIG_UART_CONSOLE) {
 
163
        case 0:
 
164
                serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK,
 
165
                PORT_x_MUX_5_FUNC_2, PG9); /* TX: G; mux 5; func 2; PG9 */
 
166
                serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK,
 
167
                PORT_x_MUX_5_FUNC_2, PG10); /* RX: G; mux 5; func 2; PG10 */
 
168
                break;
 
169
        case 1:
 
170
                serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK,
 
171
                PORT_x_MUX_3_FUNC_2, PH7); /* TX: H; mux 3; func 2; PH6 */
 
172
                serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK,
 
173
                PORT_x_MUX_3_FUNC_2, PH6); /* RX: H; mux 3; func 2; PH7 */
 
174
                break;
 
175
        }
 
176
#elif defined(__ADSPBF52x__)
 
177
        switch (CONFIG_UART_CONSOLE) {
 
178
        case 0:
 
179
                serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK,
 
180
                PORT_x_MUX_2_FUNC_3, PG7); /* TX: G; mux 2; func 3; PG7 */
 
181
                serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK,
 
182
                PORT_x_MUX_2_FUNC_3, PG8); /* RX: G; mux 2; func 3; PG8 */
 
183
                break;
 
184
        case 1:
 
185
                serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK,
 
186
                PORT_x_MUX_5_FUNC_3, PF14); /* TX: F; mux 5; func 3; PF14 */
 
187
                serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK,
 
188
                PORT_x_MUX_5_FUNC_3, PF15); /* RX: F; mux 5; func 3; PF15 */
 
189
                break;
 
190
        }
 
191
#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__)
 
192
        const uint16_t func[] = { PFDE, PFTE, };
 
193
        bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]);
 
194
        bfin_write_PORTF_FER(bfin_read_PORTF_FER() |
 
195
                        (1 << P_IDENT(P_UART(RX))) |
 
196
                        (1 << P_IDENT(P_UART(TX))));
 
197
#elif defined(__ADSPBF54x__)
 
198
        switch (CONFIG_UART_CONSOLE) {
 
199
        case 0:
 
200
                serial_early_do_mach_portmux('E', PORT_x_MUX_7_MASK,
 
201
                PORT_x_MUX_7_FUNC_1, PE7); /* TX: E; mux 7; func 1; PE7 */
 
202
                serial_early_do_mach_portmux('E', PORT_x_MUX_8_MASK,
 
203
                PORT_x_MUX_8_FUNC_1, PE8); /* RX: E; mux 8; func 1; PE8 */
 
204
                break;
 
205
        case 1:
 
206
                serial_early_do_mach_portmux('H', PORT_x_MUX_0_MASK,
 
207
                PORT_x_MUX_0_FUNC_1, PH0); /* TX: H; mux 0; func 1; PH0 */
 
208
                serial_early_do_mach_portmux('H', PORT_x_MUX_1_MASK,
 
209
                PORT_x_MUX_1_FUNC_1, PH1); /* RX: H; mux 1; func 1; PH1 */
 
210
                break;
 
211
        case 2:
 
212
                serial_early_do_mach_portmux('B', PORT_x_MUX_4_MASK,
 
213
                PORT_x_MUX_4_FUNC_1, PB4); /* TX: B; mux 4; func 1; PB4 */
 
214
                serial_early_do_mach_portmux('B', PORT_x_MUX_5_MASK,
 
215
                PORT_x_MUX_5_FUNC_1, PB5); /* RX: B; mux 5; func 1; PB5 */
 
216
                break;
 
217
        case 3:
 
218
                serial_early_do_mach_portmux('B', PORT_x_MUX_6_MASK,
 
219
                PORT_x_MUX_6_FUNC_1, PB6); /* TX: B; mux 6; func 1; PB6 */
 
220
                serial_early_do_mach_portmux('B', PORT_x_MUX_7_MASK,
 
221
                PORT_x_MUX_7_FUNC_1, PB7); /* RX: B; mux 7; func 1; PB7 */
 
222
                break;
 
223
        }
 
224
#elif defined(__ADSPBF561__)
 
225
        /* UART pins could be GPIO, but they aren't pin muxed.  */
 
226
#else
 
227
# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED)
 
228
#  error "missing portmux logic for UART"
 
229
# endif
 
230
#endif
 
231
        SSYNC();
 
232
}
 
233
 
 
234
__attribute__((always_inline))
 
235
static inline int uart_init(uint32_t uart_base)
 
236
{
 
237
        /* always enable UART -- avoids anomalies 05000309 and 05000350 */
 
238
        bfin_write(&pUART->gctl, UCEN);
 
239
 
 
240
        /* Set LCR to Word Lengh 8-bit word select */
 
241
        bfin_write(&pUART->lcr, WLS_8);
 
242
 
 
243
        SSYNC();
 
244
 
 
245
        return 0;
 
246
}
 
247
 
 
248
__attribute__((always_inline))
 
249
static inline int serial_early_init(uint32_t uart_base)
 
250
{
 
251
        /* handle portmux crap on different Blackfins */
 
252
        serial_do_portmux();
 
253
 
 
254
        return uart_init(uart_base);
 
255
}
 
256
 
 
257
__attribute__((always_inline))
 
258
static inline int serial_early_uninit(uint32_t uart_base)
 
259
{
 
260
        /* disable the UART by clearing UCEN */
 
261
        bfin_write(&pUART->gctl, 0);
 
262
 
 
263
        return 0;
 
264
}
 
265
 
 
266
__attribute__((always_inline))
 
267
static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor)
 
268
{
 
269
        /* Set DLAB in LCR to Access DLL and DLH */
 
270
        ACCESS_LATCH();
 
271
        SSYNC();
 
272
 
 
273
        /* Program the divisor to get the baud rate we want */
 
274
        bfin_write(&pUART->dll, LOB(divisor));
 
275
        bfin_write(&pUART->dlh, HIB(divisor));
 
276
        SSYNC();
 
277
 
 
278
        /* Clear DLAB in LCR to Access THR RBR IER */
 
279
        ACCESS_PORT_IER();
 
280
        SSYNC();
 
281
}
 
282
 
 
283
__attribute__((always_inline))
 
284
static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
 
285
{
 
286
        /* Translate from baud into divisor in terms of SCLK.  The
 
287
         * weird multiplication is to make sure we over sample just
 
288
         * a little rather than under sample the incoming signals.
 
289
         */
 
290
#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS
 
291
        uint16_t divisor = (early_get_uart_clk() + baud * 8) / (baud * 16)
 
292
                        - ANOMALY_05000230;
 
293
#else
 
294
        uint16_t divisor = early_division(early_get_uart_clk() + (baud * 8),
 
295
                        baud * 16) - ANOMALY_05000230;
 
296
#endif
 
297
 
 
298
        serial_set_divisor(uart_base, divisor);
 
299
}
 
300
 
 
301
__attribute__((always_inline))
 
302
static inline void serial_early_put_div(uint16_t divisor)
 
303
{
 
304
        uint32_t uart_base = UART_BASE;
 
305
 
 
306
        /* Set DLAB in LCR to Access DLL and DLH */
 
307
        ACCESS_LATCH();
 
308
        SSYNC();
 
309
 
 
310
        /* Program the divisor to get the baud rate we want */
 
311
        bfin_write(&pUART->dll, LOB(divisor));
 
312
        bfin_write(&pUART->dlh, HIB(divisor));
 
313
        SSYNC();
 
314
 
 
315
        /* Clear DLAB in LCR to Access THR RBR IER */
 
316
        ACCESS_PORT_IER();
 
317
        SSYNC();
 
318
}
 
319
 
 
320
__attribute__((always_inline))
 
321
static inline uint16_t serial_early_get_div(void)
 
322
{
 
323
        uint32_t uart_base = UART_BASE;
 
324
 
 
325
        /* Set DLAB in LCR to Access DLL and DLH */
 
326
        ACCESS_LATCH();
 
327
        SSYNC();
 
328
 
 
329
        uint8_t dll = bfin_read(&pUART->dll);
 
330
        uint8_t dlh = bfin_read(&pUART->dlh);
 
331
        uint16_t divisor = (dlh << 8) | dll;
 
332
 
 
333
        /* Clear DLAB in LCR to Access THR RBR IER */
 
334
        ACCESS_PORT_IER();
 
335
        SSYNC();
 
336
 
 
337
        return divisor;
 
338
}
 
339
 
 
340
#endif
 
341
 
 
342
#endif