xref: /openbmc/u-boot/drivers/serial/arm_dcc.c (revision 1d6edcbfed2af33c748f2beb399810a0441888da)
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