]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
4f572898 JCPV |
2 | /* |
3 | * Copyright (C) 2004-2007 ARM Limited. | |
4 | * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <[email protected]> | |
966bfa73 | 5 | * Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek |
4f572898 | 6 | * |
4f572898 JCPV |
7 | * As a special exception, if other files instantiate templates or use macros |
8 | * or inline functions from this file, or you compile this file and link it | |
9 | * with other works to produce a work based on this file, this file does not | |
10 | * by itself cause the resulting work to be covered by the GNU General Public | |
11 | * License. However the source code for this file must still be made available | |
12 | * in accordance with section (3) of the GNU General Public License. | |
13 | ||
14 | * This exception does not invalidate any other reasons why a work based on | |
15 | * this file might be covered by the GNU General Public License. | |
16 | */ | |
17 | ||
966bfa73 | 18 | #include <dm.h> |
a168d3af | 19 | #include <serial.h> |
4f572898 | 20 | |
5f133bb7 | 21 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7A) || defined(CONFIG_CPU_V7R) |
4f572898 | 22 | /* |
fd602c56 | 23 | * ARMV6 & ARMV7 |
4f572898 | 24 | */ |
66e8f9da JCPV |
25 | #define DCC_RBIT (1 << 30) |
26 | #define DCC_WBIT (1 << 29) | |
4f572898 | 27 | |
66e8f9da JCPV |
28 | #define write_dcc(x) \ |
29 | __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x)) | |
4f572898 | 30 | |
66e8f9da JCPV |
31 | #define read_dcc(x) \ |
32 | __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x)) | |
4f572898 | 33 | |
66e8f9da JCPV |
34 | #define status_dcc(x) \ |
35 | __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x)) | |
4f572898 | 36 | |
65a76d4f JCPV |
37 | #elif defined(CONFIG_CPU_XSCALE) |
38 | /* | |
39 | * XSCALE | |
40 | */ | |
41 | #define DCC_RBIT (1 << 31) | |
42 | #define DCC_WBIT (1 << 28) | |
43 | ||
44 | #define write_dcc(x) \ | |
45 | __asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x)) | |
46 | ||
47 | #define read_dcc(x) \ | |
48 | __asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x)) | |
49 | ||
50 | #define status_dcc(x) \ | |
51 | __asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x)) | |
52 | ||
6328f95e | 53 | #elif defined(CONFIG_ARM64) |
e05412f5 SDPP |
54 | /* |
55 | * ARMV8 | |
56 | */ | |
57 | #define DCC_RBIT (1 << 30) | |
58 | #define DCC_WBIT (1 << 29) | |
59 | ||
60 | #define write_dcc(x) \ | |
61 | __asm__ volatile ("msr dbgdtrtx_el0, %0\n" : : "r" (x)) | |
62 | ||
63 | #define read_dcc(x) \ | |
64 | __asm__ volatile ("mrs %0, dbgdtrrx_el0\n" : "=r" (x)) | |
65 | ||
66 | #define status_dcc(x) \ | |
67 | __asm__ volatile ("mrs %0, mdccsr_el0\n" : "=r" (x)) | |
68 | ||
66e8f9da JCPV |
69 | #else |
70 | #define DCC_RBIT (1 << 0) | |
71 | #define DCC_WBIT (1 << 1) | |
4f572898 | 72 | |
66e8f9da JCPV |
73 | #define write_dcc(x) \ |
74 | __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x)) | |
4f572898 | 75 | |
66e8f9da JCPV |
76 | #define read_dcc(x) \ |
77 | __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x)) | |
4f572898 | 78 | |
66e8f9da JCPV |
79 | #define status_dcc(x) \ |
80 | __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x)) | |
81 | ||
82 | #endif | |
4f572898 | 83 | |
66e8f9da JCPV |
84 | #define can_read_dcc(x) do { \ |
85 | status_dcc(x); \ | |
86 | x &= DCC_RBIT; \ | |
4f572898 JCPV |
87 | } while (0); |
88 | ||
66e8f9da JCPV |
89 | #define can_write_dcc(x) do { \ |
90 | status_dcc(x); \ | |
91 | x &= DCC_WBIT; \ | |
92 | x = (x == 0); \ | |
4f572898 JCPV |
93 | } while (0); |
94 | ||
95 | #define TIMEOUT_COUNT 0x4000000 | |
96 | ||
966bfa73 | 97 | static int arm_dcc_getc(struct udevice *dev) |
4f572898 JCPV |
98 | { |
99 | int ch; | |
100 | register unsigned int reg; | |
101 | ||
66e8f9da JCPV |
102 | do { |
103 | can_read_dcc(reg); | |
104 | } while (!reg); | |
105 | read_dcc(ch); | |
4f572898 JCPV |
106 | |
107 | return ch; | |
108 | } | |
109 | ||
966bfa73 | 110 | static int arm_dcc_putc(struct udevice *dev, char ch) |
4f572898 JCPV |
111 | { |
112 | register unsigned int reg; | |
113 | unsigned int timeout_count = TIMEOUT_COUNT; | |
114 | ||
66e8f9da JCPV |
115 | while (--timeout_count) { |
116 | can_write_dcc(reg); | |
117 | if (reg) | |
118 | break; | |
4f572898 | 119 | } |
66e8f9da | 120 | if (timeout_count == 0) |
966bfa73 | 121 | return -EAGAIN; |
66e8f9da JCPV |
122 | else |
123 | write_dcc(ch); | |
966bfa73 MS |
124 | |
125 | return 0; | |
4f572898 JCPV |
126 | } |
127 | ||
966bfa73 | 128 | static int arm_dcc_pending(struct udevice *dev, bool input) |
4f572898 JCPV |
129 | { |
130 | register unsigned int reg; | |
131 | ||
966bfa73 MS |
132 | if (input) { |
133 | can_read_dcc(reg); | |
134 | } else { | |
135 | can_write_dcc(reg); | |
136 | } | |
4f572898 JCPV |
137 | |
138 | return reg; | |
139 | } | |
140 | ||
966bfa73 MS |
141 | static const struct dm_serial_ops arm_dcc_ops = { |
142 | .putc = arm_dcc_putc, | |
143 | .pending = arm_dcc_pending, | |
144 | .getc = arm_dcc_getc, | |
145 | }; | |
146 | ||
147 | static const struct udevice_id arm_dcc_ids[] = { | |
148 | { .compatible = "arm,dcc", }, | |
149 | { } | |
150 | }; | |
a168d3af | 151 | |
966bfa73 | 152 | U_BOOT_DRIVER(serial_dcc) = { |
a168d3af | 153 | .name = "arm_dcc", |
966bfa73 MS |
154 | .id = UCLASS_SERIAL, |
155 | .of_match = arm_dcc_ids, | |
156 | .ops = &arm_dcc_ops, | |
a168d3af JT |
157 | }; |
158 | ||
966bfa73 MS |
159 | #ifdef CONFIG_DEBUG_UART_ARM_DCC |
160 | ||
161 | #include <debug_uart.h> | |
162 | ||
163 | static inline void _debug_uart_init(void) | |
a168d3af | 164 | { |
a168d3af JT |
165 | } |
166 | ||
966bfa73 | 167 | static inline void _debug_uart_putc(int ch) |
e70fb539 | 168 | { |
966bfa73 | 169 | arm_dcc_putc(NULL, ch); |
e70fb539 | 170 | } |
966bfa73 MS |
171 | |
172 | DEBUG_UART_FUNCS | |
173 | #endif |