xref: /rk3399_rockchip-uboot/drivers/serial/arm_dcc.c (revision 65a76d4f947a193e57bb8f8093c481f27e059f8f)
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>
44f572898SJean-Christophe PLAGNIOL-VILLARD  *
54f572898SJean-Christophe PLAGNIOL-VILLARD  * This program is free software; you can redistribute it and/or
64f572898SJean-Christophe PLAGNIOL-VILLARD  * modify it under the terms of the GNU General Public License version 2
74f572898SJean-Christophe PLAGNIOL-VILLARD  * as published by the Free Software Foundation.
84f572898SJean-Christophe PLAGNIOL-VILLARD  *
94f572898SJean-Christophe PLAGNIOL-VILLARD  * This program is distributed in the hope that it will be useful,
104f572898SJean-Christophe PLAGNIOL-VILLARD  * but WITHOUT ANY WARRANTY; without even the implied warranty of
114f572898SJean-Christophe PLAGNIOL-VILLARD  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
124f572898SJean-Christophe PLAGNIOL-VILLARD  * GNU General Public License for more details.
134f572898SJean-Christophe PLAGNIOL-VILLARD  *
144f572898SJean-Christophe PLAGNIOL-VILLARD  * You should have received a copy of the GNU General Public License
154f572898SJean-Christophe PLAGNIOL-VILLARD  * along with this program; if not, write to the Free Software
164f572898SJean-Christophe PLAGNIOL-VILLARD  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
174f572898SJean-Christophe PLAGNIOL-VILLARD  *
184f572898SJean-Christophe PLAGNIOL-VILLARD  * As a special exception, if other files instantiate templates or use macros
194f572898SJean-Christophe PLAGNIOL-VILLARD  * or inline functions from this file, or you compile this file and link it
204f572898SJean-Christophe PLAGNIOL-VILLARD  * with other works to produce a work based on this file, this file does not
214f572898SJean-Christophe PLAGNIOL-VILLARD  * by itself cause the resulting work to be covered by the GNU General Public
224f572898SJean-Christophe PLAGNIOL-VILLARD  * License. However the source code for this file must still be made available
234f572898SJean-Christophe PLAGNIOL-VILLARD  * in accordance with section (3) of the GNU General Public License.
244f572898SJean-Christophe PLAGNIOL-VILLARD 
254f572898SJean-Christophe PLAGNIOL-VILLARD  * This exception does not invalidate any other reasons why a work based on
264f572898SJean-Christophe PLAGNIOL-VILLARD  * this file might be covered by the GNU General Public License.
274f572898SJean-Christophe PLAGNIOL-VILLARD  */
284f572898SJean-Christophe PLAGNIOL-VILLARD 
294f572898SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
304f572898SJean-Christophe PLAGNIOL-VILLARD #include <devices.h>
314f572898SJean-Christophe PLAGNIOL-VILLARD 
3266e8f9daSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CPU_V6)
334f572898SJean-Christophe PLAGNIOL-VILLARD /*
3466e8f9daSJean-Christophe PLAGNIOL-VILLARD  * ARMV6
354f572898SJean-Christophe PLAGNIOL-VILLARD  */
3666e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT	(1 << 30)
3766e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT	(1 << 29)
384f572898SJean-Christophe PLAGNIOL-VILLARD 
3966e8f9daSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x)	\
404f572898SJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x))
414f572898SJean-Christophe PLAGNIOL-VILLARD 
4266e8f9daSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x)	\
434f572898SJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x))
444f572898SJean-Christophe PLAGNIOL-VILLARD 
4566e8f9daSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x)	\
464f572898SJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x))
474f572898SJean-Christophe PLAGNIOL-VILLARD 
48*65a76d4fSJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_CPU_XSCALE)
49*65a76d4fSJean-Christophe PLAGNIOL-VILLARD /*
50*65a76d4fSJean-Christophe PLAGNIOL-VILLARD  * XSCALE
51*65a76d4fSJean-Christophe PLAGNIOL-VILLARD  */
52*65a76d4fSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT	(1 << 31)
53*65a76d4fSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT	(1 << 28)
54*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 
55*65a76d4fSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x)	\
56*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x))
57*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 
58*65a76d4fSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x)	\
59*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x))
60*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 
61*65a76d4fSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x)	\
62*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x))
63*65a76d4fSJean-Christophe PLAGNIOL-VILLARD 
6466e8f9daSJean-Christophe PLAGNIOL-VILLARD #else
6566e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_RBIT	(1 << 0)
6666e8f9daSJean-Christophe PLAGNIOL-VILLARD #define DCC_WBIT	(1 << 1)
6766e8f9daSJean-Christophe PLAGNIOL-VILLARD 
6866e8f9daSJean-Christophe PLAGNIOL-VILLARD #define write_dcc(x)	\
6966e8f9daSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x))
7066e8f9daSJean-Christophe PLAGNIOL-VILLARD 
7166e8f9daSJean-Christophe PLAGNIOL-VILLARD #define read_dcc(x)	\
7266e8f9daSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x))
7366e8f9daSJean-Christophe PLAGNIOL-VILLARD 
7466e8f9daSJean-Christophe PLAGNIOL-VILLARD #define status_dcc(x)	\
7566e8f9daSJean-Christophe PLAGNIOL-VILLARD 		__asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x))
7666e8f9daSJean-Christophe PLAGNIOL-VILLARD 
7766e8f9daSJean-Christophe PLAGNIOL-VILLARD #endif
7866e8f9daSJean-Christophe PLAGNIOL-VILLARD 
7966e8f9daSJean-Christophe PLAGNIOL-VILLARD #define can_read_dcc(x)	do {	\
8066e8f9daSJean-Christophe PLAGNIOL-VILLARD 		status_dcc(x);	\
8166e8f9daSJean-Christophe PLAGNIOL-VILLARD 		x &= DCC_RBIT;	\
824f572898SJean-Christophe PLAGNIOL-VILLARD 		} while (0);
834f572898SJean-Christophe PLAGNIOL-VILLARD 
8466e8f9daSJean-Christophe PLAGNIOL-VILLARD #define can_write_dcc(x) do {	\
8566e8f9daSJean-Christophe PLAGNIOL-VILLARD 		status_dcc(x);	\
8666e8f9daSJean-Christophe PLAGNIOL-VILLARD 		x &= DCC_WBIT;	\
874f572898SJean-Christophe PLAGNIOL-VILLARD 		x = (x == 0);	\
884f572898SJean-Christophe PLAGNIOL-VILLARD 		} while (0);
894f572898SJean-Christophe PLAGNIOL-VILLARD 
904f572898SJean-Christophe PLAGNIOL-VILLARD #define TIMEOUT_COUNT 0x4000000
914f572898SJean-Christophe PLAGNIOL-VILLARD 
924f572898SJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_ARM_DCC_MULTI
934f572898SJean-Christophe PLAGNIOL-VILLARD #define arm_dcc_init serial_init
944f572898SJean-Christophe PLAGNIOL-VILLARD void serial_setbrg(void) {}
954f572898SJean-Christophe PLAGNIOL-VILLARD #define arm_dcc_getc serial_getc
964f572898SJean-Christophe PLAGNIOL-VILLARD #define arm_dcc_putc serial_putc
974f572898SJean-Christophe PLAGNIOL-VILLARD #define arm_dcc_puts serial_puts
984f572898SJean-Christophe PLAGNIOL-VILLARD #define arm_dcc_tstc serial_tstc
994f572898SJean-Christophe PLAGNIOL-VILLARD #endif
1004f572898SJean-Christophe PLAGNIOL-VILLARD 
1014f572898SJean-Christophe PLAGNIOL-VILLARD int arm_dcc_init(void)
1024f572898SJean-Christophe PLAGNIOL-VILLARD {
1034f572898SJean-Christophe PLAGNIOL-VILLARD 	return 0;
1044f572898SJean-Christophe PLAGNIOL-VILLARD }
1054f572898SJean-Christophe PLAGNIOL-VILLARD 
1064f572898SJean-Christophe PLAGNIOL-VILLARD int arm_dcc_getc(void)
1074f572898SJean-Christophe PLAGNIOL-VILLARD {
1084f572898SJean-Christophe PLAGNIOL-VILLARD 	int ch;
1094f572898SJean-Christophe PLAGNIOL-VILLARD 	register unsigned int reg;
1104f572898SJean-Christophe PLAGNIOL-VILLARD 
1114f572898SJean-Christophe PLAGNIOL-VILLARD 	do {
11266e8f9daSJean-Christophe PLAGNIOL-VILLARD 		can_read_dcc(reg);
1134f572898SJean-Christophe PLAGNIOL-VILLARD 	} while (!reg);
11466e8f9daSJean-Christophe PLAGNIOL-VILLARD 	read_dcc(ch);
1154f572898SJean-Christophe PLAGNIOL-VILLARD 
1164f572898SJean-Christophe PLAGNIOL-VILLARD 	return ch;
1174f572898SJean-Christophe PLAGNIOL-VILLARD }
1184f572898SJean-Christophe PLAGNIOL-VILLARD 
1194f572898SJean-Christophe PLAGNIOL-VILLARD void arm_dcc_putc(char ch)
1204f572898SJean-Christophe PLAGNIOL-VILLARD {
1214f572898SJean-Christophe PLAGNIOL-VILLARD 	register unsigned int reg;
1224f572898SJean-Christophe PLAGNIOL-VILLARD 	unsigned int timeout_count = TIMEOUT_COUNT;
1234f572898SJean-Christophe PLAGNIOL-VILLARD 
1244f572898SJean-Christophe PLAGNIOL-VILLARD 	while (--timeout_count) {
12566e8f9daSJean-Christophe PLAGNIOL-VILLARD 		can_write_dcc(reg);
1264f572898SJean-Christophe PLAGNIOL-VILLARD 		if (reg)
1274f572898SJean-Christophe PLAGNIOL-VILLARD 			break;
1284f572898SJean-Christophe PLAGNIOL-VILLARD 	}
1294f572898SJean-Christophe PLAGNIOL-VILLARD 	if (timeout_count == 0)
1304f572898SJean-Christophe PLAGNIOL-VILLARD 		return;
1314f572898SJean-Christophe PLAGNIOL-VILLARD 	else
13266e8f9daSJean-Christophe PLAGNIOL-VILLARD 		write_dcc(ch);
1334f572898SJean-Christophe PLAGNIOL-VILLARD }
1344f572898SJean-Christophe PLAGNIOL-VILLARD 
1354f572898SJean-Christophe PLAGNIOL-VILLARD void arm_dcc_puts(const char *s)
1364f572898SJean-Christophe PLAGNIOL-VILLARD {
1374f572898SJean-Christophe PLAGNIOL-VILLARD 	while (*s)
1384f572898SJean-Christophe PLAGNIOL-VILLARD 		arm_dcc_putc(*s++);
1394f572898SJean-Christophe PLAGNIOL-VILLARD }
1404f572898SJean-Christophe PLAGNIOL-VILLARD 
1414f572898SJean-Christophe PLAGNIOL-VILLARD int arm_dcc_tstc(void)
1424f572898SJean-Christophe PLAGNIOL-VILLARD {
1434f572898SJean-Christophe PLAGNIOL-VILLARD 	register unsigned int reg;
1444f572898SJean-Christophe PLAGNIOL-VILLARD 
14566e8f9daSJean-Christophe PLAGNIOL-VILLARD 	can_read_dcc(reg);
1464f572898SJean-Christophe PLAGNIOL-VILLARD 
1474f572898SJean-Christophe PLAGNIOL-VILLARD 	return reg;
1484f572898SJean-Christophe PLAGNIOL-VILLARD }
1494f572898SJean-Christophe PLAGNIOL-VILLARD 
1504f572898SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_ARM_DCC_MULTI
1514f572898SJean-Christophe PLAGNIOL-VILLARD static device_t arm_dcc_dev;
1524f572898SJean-Christophe PLAGNIOL-VILLARD 
1534f572898SJean-Christophe PLAGNIOL-VILLARD int drv_arm_dcc_init(void)
1544f572898SJean-Christophe PLAGNIOL-VILLARD {
1554f572898SJean-Christophe PLAGNIOL-VILLARD 	int rc;
1564f572898SJean-Christophe PLAGNIOL-VILLARD 
1574f572898SJean-Christophe PLAGNIOL-VILLARD 	/* Device initialization */
1584f572898SJean-Christophe PLAGNIOL-VILLARD 	memset(&arm_dcc_dev, 0, sizeof(arm_dcc_dev));
1594f572898SJean-Christophe PLAGNIOL-VILLARD 
1604f572898SJean-Christophe PLAGNIOL-VILLARD 	strcpy(arm_dcc_dev.name, "dcc");
1614f572898SJean-Christophe PLAGNIOL-VILLARD 	arm_dcc_dev.ext = 0;	/* No extensions */
1624f572898SJean-Christophe PLAGNIOL-VILLARD 	arm_dcc_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT;
1634f572898SJean-Christophe PLAGNIOL-VILLARD 	arm_dcc_dev.tstc = arm_dcc_tstc;	/* 'tstc' function */
1644f572898SJean-Christophe PLAGNIOL-VILLARD 	arm_dcc_dev.getc = arm_dcc_getc;	/* 'getc' function */
1654f572898SJean-Christophe PLAGNIOL-VILLARD 	arm_dcc_dev.putc = arm_dcc_putc;	/* 'putc' function */
1664f572898SJean-Christophe PLAGNIOL-VILLARD 	arm_dcc_dev.puts = arm_dcc_puts;	/* 'puts' function */
1674f572898SJean-Christophe PLAGNIOL-VILLARD 
16866e8f9daSJean-Christophe PLAGNIOL-VILLARD 	return device_register(&arm_dcc_dev);
1694f572898SJean-Christophe PLAGNIOL-VILLARD }
1704f572898SJean-Christophe PLAGNIOL-VILLARD #endif
171