183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
24f572898SJean-Christophe PLAGNIOL-VILLARD /*
34f572898SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2004-2007 ARM Limited.
44f572898SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
5966bfa73SMichal Simek * Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek
64f572898SJean-Christophe PLAGNIOL-VILLARD *
74f572898SJean-Christophe PLAGNIOL-VILLARD * As a special exception, if other files instantiate templates or use macros
84f572898SJean-Christophe PLAGNIOL-VILLARD * or inline functions from this file, or you compile this file and link it
94f572898SJean-Christophe PLAGNIOL-VILLARD * with other works to produce a work based on this file, this file does not
104f572898SJean-Christophe PLAGNIOL-VILLARD * by itself cause the resulting work to be covered by the GNU General Public
114f572898SJean-Christophe PLAGNIOL-VILLARD * License. However the source code for this file must still be made available
124f572898SJean-Christophe PLAGNIOL-VILLARD * in accordance with section (3) of the GNU General Public License.
134f572898SJean-Christophe PLAGNIOL-VILLARD
144f572898SJean-Christophe PLAGNIOL-VILLARD * This exception does not invalidate any other reasons why a work based on
154f572898SJean-Christophe PLAGNIOL-VILLARD * this file might be covered by the GNU General Public License.
164f572898SJean-Christophe PLAGNIOL-VILLARD */
174f572898SJean-Christophe PLAGNIOL-VILLARD
184f572898SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
19966bfa73SMichal Simek #include <dm.h>
20a168d3afSJagannadha Sutradharudu Teki #include <serial.h>
214f572898SJean-Christophe PLAGNIOL-VILLARD
22*5f133bb7SLokesh Vutla #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7A) || defined(CONFIG_CPU_V7R)
234f572898SJean-Christophe PLAGNIOL-VILLARD /*
24fd602c56SAlexander Merkle * ARMV6 & ARMV7
254f572898SJean-Christophe PLAGNIOL-VILLARD */
2666e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT (1 << 30)
2766e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT (1 << 29)
284f572898SJean-Christophe PLAGNIOL-VILLARD
2966e8f9daSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x) \
304f572898SJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x))
314f572898SJean-Christophe PLAGNIOL-VILLARD
3266e8f9daSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x) \
334f572898SJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x))
344f572898SJean-Christophe PLAGNIOL-VILLARD
3566e8f9daSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x) \
364f572898SJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x))
374f572898SJean-Christophe PLAGNIOL-VILLARD
3865a76d4fSJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_CPU_XSCALE)
3965a76d4fSJean-Christophe PLAGNIOL-VILLARD /*
4065a76d4fSJean-Christophe PLAGNIOL-VILLARD * XSCALE
4165a76d4fSJean-Christophe PLAGNIOL-VILLARD */
4265a76d4fSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT (1 << 31)
4365a76d4fSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT (1 << 28)
4465a76d4fSJean-Christophe PLAGNIOL-VILLARD
4565a76d4fSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x) \
4665a76d4fSJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x))
4765a76d4fSJean-Christophe PLAGNIOL-VILLARD
4865a76d4fSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x) \
4965a76d4fSJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x))
5065a76d4fSJean-Christophe PLAGNIOL-VILLARD
5165a76d4fSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x) \
5265a76d4fSJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x))
5365a76d4fSJean-Christophe PLAGNIOL-VILLARD
54e05412f5SSiva Durga Prasad Paladugu #elif defined(CONFIG_CPU_ARMV8)
55e05412f5SSiva Durga Prasad Paladugu /*
56e05412f5SSiva Durga Prasad Paladugu * ARMV8
57e05412f5SSiva Durga Prasad Paladugu */
58e05412f5SSiva Durga Prasad Paladugu #define DCC_RBIT (1 << 30)
59e05412f5SSiva Durga Prasad Paladugu #define DCC_WBIT (1 << 29)
60e05412f5SSiva Durga Prasad Paladugu
61e05412f5SSiva Durga Prasad Paladugu #define write_dcc(x) \
62e05412f5SSiva Durga Prasad Paladugu __asm__ volatile ("msr dbgdtrtx_el0, %0\n" : : "r" (x))
63e05412f5SSiva Durga Prasad Paladugu
64e05412f5SSiva Durga Prasad Paladugu #define read_dcc(x) \
65e05412f5SSiva Durga Prasad Paladugu __asm__ volatile ("mrs %0, dbgdtrrx_el0\n" : "=r" (x))
66e05412f5SSiva Durga Prasad Paladugu
67e05412f5SSiva Durga Prasad Paladugu #define status_dcc(x) \
68e05412f5SSiva Durga Prasad Paladugu __asm__ volatile ("mrs %0, mdccsr_el0\n" : "=r" (x))
69e05412f5SSiva Durga Prasad Paladugu
7066e8f9daSJean-Christophe PLAGNIOL-VILLARD #else
7166e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT (1 << 0)
7266e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT (1 << 1)
7366e8f9daSJean-Christophe PLAGNIOL-VILLARD
7466e8f9daSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x) \
7566e8f9daSJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x))
7666e8f9daSJean-Christophe PLAGNIOL-VILLARD
7766e8f9daSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x) \
7866e8f9daSJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x))
7966e8f9daSJean-Christophe PLAGNIOL-VILLARD
8066e8f9daSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x) \
8166e8f9daSJean-Christophe PLAGNIOL-VILLARD __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x))
8266e8f9daSJean-Christophe PLAGNIOL-VILLARD
8366e8f9daSJean-Christophe PLAGNIOL-VILLARD #endif
8466e8f9daSJean-Christophe PLAGNIOL-VILLARD
8566e8f9daSJean-Christophe PLAGNIOL-VILLARD #define can_read_dcc(x) do { \
8666e8f9daSJean-Christophe PLAGNIOL-VILLARD status_dcc(x); \
8766e8f9daSJean-Christophe PLAGNIOL-VILLARD x &= DCC_RBIT; \
884f572898SJean-Christophe PLAGNIOL-VILLARD } while (0);
894f572898SJean-Christophe PLAGNIOL-VILLARD
9066e8f9daSJean-Christophe PLAGNIOL-VILLARD #define can_write_dcc(x) do { \
9166e8f9daSJean-Christophe PLAGNIOL-VILLARD status_dcc(x); \
9266e8f9daSJean-Christophe PLAGNIOL-VILLARD x &= DCC_WBIT; \
934f572898SJean-Christophe PLAGNIOL-VILLARD x = (x == 0); \
944f572898SJean-Christophe PLAGNIOL-VILLARD } while (0);
954f572898SJean-Christophe PLAGNIOL-VILLARD
964f572898SJean-Christophe PLAGNIOL-VILLARD #define TIMEOUT_COUNT 0x4000000
974f572898SJean-Christophe PLAGNIOL-VILLARD
arm_dcc_getc(struct udevice * dev)98966bfa73SMichal Simek static int arm_dcc_getc(struct udevice *dev)
994f572898SJean-Christophe PLAGNIOL-VILLARD {
1004f572898SJean-Christophe PLAGNIOL-VILLARD int ch;
1014f572898SJean-Christophe PLAGNIOL-VILLARD register unsigned int reg;
1024f572898SJean-Christophe PLAGNIOL-VILLARD
1034f572898SJean-Christophe PLAGNIOL-VILLARD do {
10466e8f9daSJean-Christophe PLAGNIOL-VILLARD can_read_dcc(reg);
1054f572898SJean-Christophe PLAGNIOL-VILLARD } while (!reg);
10666e8f9daSJean-Christophe PLAGNIOL-VILLARD read_dcc(ch);
1074f572898SJean-Christophe PLAGNIOL-VILLARD
1084f572898SJean-Christophe PLAGNIOL-VILLARD return ch;
1094f572898SJean-Christophe PLAGNIOL-VILLARD }
1104f572898SJean-Christophe PLAGNIOL-VILLARD
arm_dcc_putc(struct udevice * dev,char ch)111966bfa73SMichal Simek static int arm_dcc_putc(struct udevice *dev, char ch)
1124f572898SJean-Christophe PLAGNIOL-VILLARD {
1134f572898SJean-Christophe PLAGNIOL-VILLARD register unsigned int reg;
1144f572898SJean-Christophe PLAGNIOL-VILLARD unsigned int timeout_count = TIMEOUT_COUNT;
1154f572898SJean-Christophe PLAGNIOL-VILLARD
1164f572898SJean-Christophe PLAGNIOL-VILLARD while (--timeout_count) {
11766e8f9daSJean-Christophe PLAGNIOL-VILLARD can_write_dcc(reg);
1184f572898SJean-Christophe PLAGNIOL-VILLARD if (reg)
1194f572898SJean-Christophe PLAGNIOL-VILLARD break;
1204f572898SJean-Christophe PLAGNIOL-VILLARD }
1214f572898SJean-Christophe PLAGNIOL-VILLARD if (timeout_count == 0)
122966bfa73SMichal Simek return -EAGAIN;
1234f572898SJean-Christophe PLAGNIOL-VILLARD else
12466e8f9daSJean-Christophe PLAGNIOL-VILLARD write_dcc(ch);
125966bfa73SMichal Simek
126966bfa73SMichal Simek return 0;
1274f572898SJean-Christophe PLAGNIOL-VILLARD }
1284f572898SJean-Christophe PLAGNIOL-VILLARD
arm_dcc_pending(struct udevice * dev,bool input)129966bfa73SMichal Simek static int arm_dcc_pending(struct udevice *dev, bool input)
1304f572898SJean-Christophe PLAGNIOL-VILLARD {
1314f572898SJean-Christophe PLAGNIOL-VILLARD register unsigned int reg;
1324f572898SJean-Christophe PLAGNIOL-VILLARD
133966bfa73SMichal Simek if (input) {
13466e8f9daSJean-Christophe PLAGNIOL-VILLARD can_read_dcc(reg);
135966bfa73SMichal Simek } else {
136966bfa73SMichal Simek can_write_dcc(reg);
137966bfa73SMichal Simek }
1384f572898SJean-Christophe PLAGNIOL-VILLARD
1394f572898SJean-Christophe PLAGNIOL-VILLARD return reg;
1404f572898SJean-Christophe PLAGNIOL-VILLARD }
1414f572898SJean-Christophe PLAGNIOL-VILLARD
142966bfa73SMichal Simek static const struct dm_serial_ops arm_dcc_ops = {
143a168d3afSJagannadha Sutradharudu Teki .putc = arm_dcc_putc,
144966bfa73SMichal Simek .pending = arm_dcc_pending,
145a168d3afSJagannadha Sutradharudu Teki .getc = arm_dcc_getc,
146a168d3afSJagannadha Sutradharudu Teki };
147a168d3afSJagannadha Sutradharudu Teki
148966bfa73SMichal Simek static const struct udevice_id arm_dcc_ids[] = {
149966bfa73SMichal Simek { .compatible = "arm,dcc", },
150966bfa73SMichal Simek { }
151966bfa73SMichal Simek };
152966bfa73SMichal Simek
153966bfa73SMichal Simek U_BOOT_DRIVER(serial_dcc) = {
154966bfa73SMichal Simek .name = "arm_dcc",
155966bfa73SMichal Simek .id = UCLASS_SERIAL,
156966bfa73SMichal Simek .of_match = arm_dcc_ids,
157966bfa73SMichal Simek .ops = &arm_dcc_ops,
158966bfa73SMichal Simek };
159966bfa73SMichal Simek
160966bfa73SMichal Simek #ifdef CONFIG_DEBUG_UART_ARM_DCC
161966bfa73SMichal Simek
162966bfa73SMichal Simek #include <debug_uart.h>
163966bfa73SMichal Simek
_debug_uart_init(void)164966bfa73SMichal Simek static inline void _debug_uart_init(void)
165a168d3afSJagannadha Sutradharudu Teki {
166a168d3afSJagannadha Sutradharudu Teki }
167a168d3afSJagannadha Sutradharudu Teki
_debug_uart_putc(int ch)168966bfa73SMichal Simek static inline void _debug_uart_putc(int ch)
169e70fb539SMichal Simek {
170966bfa73SMichal Simek arm_dcc_putc(NULL, ch);
171e70fb539SMichal Simek }
172966bfa73SMichal Simek
173966bfa73SMichal Simek DEBUG_UART_FUNCS
174966bfa73SMichal Simek #endif
175