xref: /rk3399_rockchip-uboot/drivers/serial/arm_dcc.c (revision 966bfa7347ba2d1bc938988abca8ed3f65f8e57a)
14f572898SJean-Christophe PLAGNIOL-VILLARD /*
24f572898SJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2004-2007 ARM Limited.
34f572898SJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
4*966bfa73SMichal Simek  * Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek
54f572898SJean-Christophe PLAGNIOL-VILLARD  *
65b8031ccSTom Rini  * SPDX-License-Identifier:	GPL-2.0
74f572898SJean-Christophe PLAGNIOL-VILLARD  *
84f572898SJean-Christophe PLAGNIOL-VILLARD  * As a special exception, if other files instantiate templates or use macros
94f572898SJean-Christophe PLAGNIOL-VILLARD  * or inline functions from this file, or you compile this file and link it
104f572898SJean-Christophe PLAGNIOL-VILLARD  * with other works to produce a work based on this file, this file does not
114f572898SJean-Christophe PLAGNIOL-VILLARD  * by itself cause the resulting work to be covered by the GNU General Public
124f572898SJean-Christophe PLAGNIOL-VILLARD  * License. However the source code for this file must still be made available
134f572898SJean-Christophe PLAGNIOL-VILLARD  * in accordance with section (3) of the GNU General Public License.
144f572898SJean-Christophe PLAGNIOL-VILLARD 
154f572898SJean-Christophe PLAGNIOL-VILLARD  * This exception does not invalidate any other reasons why a work based on
164f572898SJean-Christophe PLAGNIOL-VILLARD  * this file might be covered by the GNU General Public License.
174f572898SJean-Christophe PLAGNIOL-VILLARD  */
184f572898SJean-Christophe PLAGNIOL-VILLARD 
194f572898SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
20*966bfa73SMichal Simek #include <dm.h>
21a168d3afSJagannadha Sutradharudu Teki #include <serial.h>
224f572898SJean-Christophe PLAGNIOL-VILLARD 
23fd602c56SAlexander Merkle #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7)
244f572898SJean-Christophe PLAGNIOL-VILLARD /*
25fd602c56SAlexander Merkle  * ARMV6 & ARMV7
264f572898SJean-Christophe PLAGNIOL-VILLARD  */
2766e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT	(1 << 30)
2866e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT	(1 << 29)
294f572898SJean-Christophe PLAGNIOL-VILLARD 
3066e8f9daSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x)	\
314f572898SJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x))
324f572898SJean-Christophe PLAGNIOL-VILLARD 
3366e8f9daSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x)	\
344f572898SJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x))
354f572898SJean-Christophe PLAGNIOL-VILLARD 
3666e8f9daSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x)	\
374f572898SJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x))
384f572898SJean-Christophe PLAGNIOL-VILLARD 
3965a76d4fSJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_CPU_XSCALE)
4065a76d4fSJean-Christophe PLAGNIOL-VILLARD /*
4165a76d4fSJean-Christophe PLAGNIOL-VILLARD  * XSCALE
4265a76d4fSJean-Christophe PLAGNIOL-VILLARD  */
4365a76d4fSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT	(1 << 31)
4465a76d4fSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT	(1 << 28)
4565a76d4fSJean-Christophe PLAGNIOL-VILLARD 
4665a76d4fSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x)	\
4765a76d4fSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x))
4865a76d4fSJean-Christophe PLAGNIOL-VILLARD 
4965a76d4fSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x)	\
5065a76d4fSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x))
5165a76d4fSJean-Christophe PLAGNIOL-VILLARD 
5265a76d4fSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x)	\
5365a76d4fSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x))
5465a76d4fSJean-Christophe PLAGNIOL-VILLARD 
55e05412f5SSiva Durga Prasad Paladugu #elif defined(CONFIG_CPU_ARMV8)
56e05412f5SSiva Durga Prasad Paladugu /*
57e05412f5SSiva Durga Prasad Paladugu  * ARMV8
58e05412f5SSiva Durga Prasad Paladugu  */
59e05412f5SSiva Durga Prasad Paladugu #define DCC_RBIT	(1 << 30)
60e05412f5SSiva Durga Prasad Paladugu #define DCC_WBIT	(1 << 29)
61e05412f5SSiva Durga Prasad Paladugu 
62e05412f5SSiva Durga Prasad Paladugu #define write_dcc(x)   \
63e05412f5SSiva Durga Prasad Paladugu 		__asm__ volatile ("msr dbgdtrtx_el0, %0\n" : : "r" (x))
64e05412f5SSiva Durga Prasad Paladugu 
65e05412f5SSiva Durga Prasad Paladugu #define read_dcc(x)    \
66e05412f5SSiva Durga Prasad Paladugu 		__asm__ volatile ("mrs %0, dbgdtrrx_el0\n" : "=r" (x))
67e05412f5SSiva Durga Prasad Paladugu 
68e05412f5SSiva Durga Prasad Paladugu #define status_dcc(x)  \
69e05412f5SSiva Durga Prasad Paladugu 		__asm__ volatile ("mrs %0, mdccsr_el0\n" : "=r" (x))
70e05412f5SSiva Durga Prasad Paladugu 
7166e8f9daSJean-Christophe PLAGNIOL-VILLARD #else
7266e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT	(1 << 0)
7366e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT	(1 << 1)
7466e8f9daSJean-Christophe PLAGNIOL-VILLARD 
7566e8f9daSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x)	\
7666e8f9daSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x))
7766e8f9daSJean-Christophe PLAGNIOL-VILLARD 
7866e8f9daSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x)	\
7966e8f9daSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x))
8066e8f9daSJean-Christophe PLAGNIOL-VILLARD 
8166e8f9daSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x)	\
8266e8f9daSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x))
8366e8f9daSJean-Christophe PLAGNIOL-VILLARD 
8466e8f9daSJean-Christophe PLAGNIOL-VILLARD #endif
8566e8f9daSJean-Christophe PLAGNIOL-VILLARD 
8666e8f9daSJean-Christophe PLAGNIOL-VILLARD #define can_read_dcc(x)	do {	\
8766e8f9daSJean-Christophe PLAGNIOL-VILLARD 		status_dcc(x);	\
8866e8f9daSJean-Christophe PLAGNIOL-VILLARD 		x &= DCC_RBIT;	\
894f572898SJean-Christophe PLAGNIOL-VILLARD 		} while (0);
904f572898SJean-Christophe PLAGNIOL-VILLARD 
9166e8f9daSJean-Christophe PLAGNIOL-VILLARD #define can_write_dcc(x) do {	\
9266e8f9daSJean-Christophe PLAGNIOL-VILLARD 		status_dcc(x);	\
9366e8f9daSJean-Christophe PLAGNIOL-VILLARD 		x &= DCC_WBIT;	\
944f572898SJean-Christophe PLAGNIOL-VILLARD 		x = (x == 0);	\
954f572898SJean-Christophe PLAGNIOL-VILLARD 		} while (0);
964f572898SJean-Christophe PLAGNIOL-VILLARD 
974f572898SJean-Christophe PLAGNIOL-VILLARD #define TIMEOUT_COUNT 0x4000000
984f572898SJean-Christophe PLAGNIOL-VILLARD 
arm_dcc_getc(struct udevice * dev)99*966bfa73SMichal Simek static int arm_dcc_getc(struct udevice *dev)
1004f572898SJean-Christophe PLAGNIOL-VILLARD {
1014f572898SJean-Christophe PLAGNIOL-VILLARD 	int ch;
1024f572898SJean-Christophe PLAGNIOL-VILLARD 	register unsigned int reg;
1034f572898SJean-Christophe PLAGNIOL-VILLARD 
1044f572898SJean-Christophe PLAGNIOL-VILLARD 	do {
10566e8f9daSJean-Christophe PLAGNIOL-VILLARD 		can_read_dcc(reg);
1064f572898SJean-Christophe PLAGNIOL-VILLARD 	} while (!reg);
10766e8f9daSJean-Christophe PLAGNIOL-VILLARD 	read_dcc(ch);
1084f572898SJean-Christophe PLAGNIOL-VILLARD 
1094f572898SJean-Christophe PLAGNIOL-VILLARD 	return ch;
1104f572898SJean-Christophe PLAGNIOL-VILLARD }
1114f572898SJean-Christophe PLAGNIOL-VILLARD 
arm_dcc_putc(struct udevice * dev,char ch)112*966bfa73SMichal Simek static int arm_dcc_putc(struct udevice *dev, char ch)
1134f572898SJean-Christophe PLAGNIOL-VILLARD {
1144f572898SJean-Christophe PLAGNIOL-VILLARD 	register unsigned int reg;
1154f572898SJean-Christophe PLAGNIOL-VILLARD 	unsigned int timeout_count = TIMEOUT_COUNT;
1164f572898SJean-Christophe PLAGNIOL-VILLARD 
1174f572898SJean-Christophe PLAGNIOL-VILLARD 	while (--timeout_count) {
11866e8f9daSJean-Christophe PLAGNIOL-VILLARD 		can_write_dcc(reg);
1194f572898SJean-Christophe PLAGNIOL-VILLARD 		if (reg)
1204f572898SJean-Christophe PLAGNIOL-VILLARD 			break;
1214f572898SJean-Christophe PLAGNIOL-VILLARD 	}
1224f572898SJean-Christophe PLAGNIOL-VILLARD 	if (timeout_count == 0)
123*966bfa73SMichal Simek 		return -EAGAIN;
1244f572898SJean-Christophe PLAGNIOL-VILLARD 	else
12566e8f9daSJean-Christophe PLAGNIOL-VILLARD 		write_dcc(ch);
126*966bfa73SMichal Simek 
127*966bfa73SMichal Simek 	return 0;
1284f572898SJean-Christophe PLAGNIOL-VILLARD }
1294f572898SJean-Christophe PLAGNIOL-VILLARD 
arm_dcc_pending(struct udevice * dev,bool input)130*966bfa73SMichal Simek static int arm_dcc_pending(struct udevice *dev, bool input)
1314f572898SJean-Christophe PLAGNIOL-VILLARD {
1324f572898SJean-Christophe PLAGNIOL-VILLARD 	register unsigned int reg;
1334f572898SJean-Christophe PLAGNIOL-VILLARD 
134*966bfa73SMichal Simek 	if (input) {
13566e8f9daSJean-Christophe PLAGNIOL-VILLARD 		can_read_dcc(reg);
136*966bfa73SMichal Simek 	} else {
137*966bfa73SMichal Simek 		can_write_dcc(reg);
138*966bfa73SMichal Simek 	}
1394f572898SJean-Christophe PLAGNIOL-VILLARD 
1404f572898SJean-Christophe PLAGNIOL-VILLARD 	return reg;
1414f572898SJean-Christophe PLAGNIOL-VILLARD }
1424f572898SJean-Christophe PLAGNIOL-VILLARD 
143*966bfa73SMichal Simek static const struct dm_serial_ops arm_dcc_ops = {
144a168d3afSJagannadha Sutradharudu Teki 	.putc = arm_dcc_putc,
145*966bfa73SMichal Simek 	.pending = arm_dcc_pending,
146a168d3afSJagannadha Sutradharudu Teki 	.getc = arm_dcc_getc,
147a168d3afSJagannadha Sutradharudu Teki };
148a168d3afSJagannadha Sutradharudu Teki 
149*966bfa73SMichal Simek static const struct udevice_id arm_dcc_ids[] = {
150*966bfa73SMichal Simek 	{ .compatible = "arm,dcc", },
151*966bfa73SMichal Simek 	{ }
152*966bfa73SMichal Simek };
153*966bfa73SMichal Simek 
154*966bfa73SMichal Simek U_BOOT_DRIVER(serial_dcc) = {
155*966bfa73SMichal Simek 	.name	= "arm_dcc",
156*966bfa73SMichal Simek 	.id	= UCLASS_SERIAL,
157*966bfa73SMichal Simek 	.of_match = arm_dcc_ids,
158*966bfa73SMichal Simek 	.ops	= &arm_dcc_ops,
159*966bfa73SMichal Simek 	.flags = DM_FLAG_PRE_RELOC,
160*966bfa73SMichal Simek };
161*966bfa73SMichal Simek 
162*966bfa73SMichal Simek #ifdef CONFIG_DEBUG_UART_ARM_DCC
163*966bfa73SMichal Simek 
164*966bfa73SMichal Simek #include <debug_uart.h>
165*966bfa73SMichal Simek 
_debug_uart_init(void)166*966bfa73SMichal Simek static inline void _debug_uart_init(void)
167a168d3afSJagannadha Sutradharudu Teki {
168a168d3afSJagannadha Sutradharudu Teki }
169a168d3afSJagannadha Sutradharudu Teki 
_debug_uart_putc(int ch)170*966bfa73SMichal Simek static inline void _debug_uart_putc(int ch)
171e70fb539SMichal Simek {
172*966bfa73SMichal Simek 	arm_dcc_putc(NULL, ch);
173e70fb539SMichal Simek }
174*966bfa73SMichal Simek 
175*966bfa73SMichal Simek DEBUG_UART_FUNCS
176*966bfa73SMichal Simek #endif
177