blob: 65483960b9cb092eb2d8388840460d9717dd9c9f [file] [log] [blame]
Sonic Zhang7a91b9b2012-08-16 11:16:02 +08001/*
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_SERIAL4_H__
12#define __BFIN_CPU_SERIAL4_H__
13
14#include <asm/mach-common/bits/uart4.h>
15
16#ifndef __ASSEMBLY__
17
Sonic Zhangc15c4032013-02-05 19:10:34 +080018#include <asm/clock.h>
19
Sonic Zhang7a91b9b2012-08-16 11:16:02 +080020#define MMR_UART(n) _PASTE_UART(n, UART, REVID)
21#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE)
22
23struct bfin_mmr_serial {
24 u32 revid;
25 u32 control;
26 u32 status;
27 u32 scr;
28 u32 clock;
29 u32 emask;
30 u32 emaskst;
31 u32 emaskcl;
32 u32 rbr;
33 u32 thr;
34 u32 taip;
35 u32 tsr;
36 u32 rsr;
37 u32 txdiv_cnt;
38 u32 rxdiv_cnt;
39};
40#define uart_lsr_t uint32_t
41#define _lsr_read(p) bfin_read(&p->status)
42#define _lsr_write(p, v) bfin_write(&p->status, v)
43
44__attribute__((always_inline))
45static inline void serial_early_do_mach_portmux(char port, int mux_mask,
46 int mux_func, int port_pin)
47{
48 switch (port) {
49 case 'D':
50 bfin_write_PORTD_MUX((bfin_read_PORTD_MUX() &
51 ~mux_mask) | mux_func);
52 bfin_write_PORTD_FER_SET(port_pin);
53 break;
54 case 'G':
55 bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() &
56 ~mux_mask) | mux_func);
57 bfin_write_PORTG_FER_SET(port_pin);
58 break;
59 }
60}
61
62__attribute__((always_inline))
63static inline void serial_early_do_portmux(void)
64{
65#if defined(__ADSPBF60x__)
66 switch (CONFIG_UART_CONSOLE) {
67 case 0:
68 serial_early_do_mach_portmux('D', PORT_x_MUX_7_MASK,
69 PORT_x_MUX_7_FUNC_2, PD7); /* TX: D; mux 7; func 2; PD7 */
70 serial_early_do_mach_portmux('D', PORT_x_MUX_8_MASK,
71 PORT_x_MUX_8_FUNC_2, PD8); /* RX: D; mux 8; func 2; PD8 */
72 break;
73 case 1:
74 serial_early_do_mach_portmux('G', PORT_x_MUX_15_MASK,
75 PORT_x_MUX_15_FUNC_1, PG15); /* TX: G; mux 15; func 1; PG15 */
76 serial_early_do_mach_portmux('G', PORT_x_MUX_14_MASK,
77 PORT_x_MUX_14_FUNC_1, PG14); /* RX: G; mux 14; func 1; PG14 */
78 break;
79 }
80#else
81# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED)
82# error "missing portmux logic for UART"
83# endif
84#endif
85 SSYNC();
86}
87
88__attribute__((always_inline))
Sonic Zhang7a91b9b2012-08-16 11:16:02 +080089static inline int uart_init(uint32_t uart_base)
90{
91 /* always enable UART to 8-bit mode */
92 bfin_write(&pUART->control, UEN | UMOD_UART | WLS_8);
93
94 SSYNC();
95
96 return 0;
97}
98
99__attribute__((always_inline))
100static inline int serial_early_init(uint32_t uart_base)
101{
102 /* handle portmux crap on different Blackfins */
103 serial_do_portmux();
104
105 return uart_init(uart_base);
106}
107
108__attribute__((always_inline))
109static inline int serial_early_uninit(uint32_t uart_base)
110{
111 /* disable the UART by clearing UEN */
112 bfin_write(&pUART->control, 0);
113
114 return 0;
115}
116
117__attribute__((always_inline))
Sonic Zhangc15c4032013-02-05 19:10:34 +0800118static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor)
Sonic Zhang7a91b9b2012-08-16 11:16:02 +0800119{
Sonic Zhangc15c4032013-02-05 19:10:34 +0800120 /* Program the divisor to get the baud rate we want */
121 bfin_write(&pUART->clock, divisor);
122 SSYNC();
Sonic Zhang7a91b9b2012-08-16 11:16:02 +0800123}
124
125__attribute__((always_inline))
126static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
127{
Sonic Zhangc15c4032013-02-05 19:10:34 +0800128 uint16_t divisor = early_division(early_get_uart_clk(), baud * 16);
Sonic Zhang7a91b9b2012-08-16 11:16:02 +0800129
130 /* Program the divisor to get the baud rate we want */
Sonic Zhangc15c4032013-02-05 19:10:34 +0800131 serial_set_divisor(uart_base, divisor);
Sonic Zhang7a91b9b2012-08-16 11:16:02 +0800132}
133
134__attribute__((always_inline))
135static inline void serial_early_put_div(uint32_t divisor)
136{
137 uint32_t uart_base = UART_BASE;
138 bfin_write(&pUART->clock, divisor);
139}
140
141__attribute__((always_inline))
142static inline uint32_t serial_early_get_div(void)
143{
144 uint32_t uart_base = UART_BASE;
145 return bfin_read(&pUART->clock);
146}
147
148#endif
149
150#endif