1 /* 2 * Copyright (C) 2004-2007 ARM Limited. 3 * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0 6 * 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 18 #include <common.h> 19 #include <serial.h> 20 21 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7) 22 /* 23 * ARMV6 & ARMV7 24 */ 25 #define DCC_RBIT (1 << 30) 26 #define DCC_WBIT (1 << 29) 27 28 #define write_dcc(x) \ 29 __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x)) 30 31 #define read_dcc(x) \ 32 __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x)) 33 34 #define status_dcc(x) \ 35 __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x)) 36 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 53 #elif defined(CONFIG_CPU_ARMV8) 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 69 #else 70 #define DCC_RBIT (1 << 0) 71 #define DCC_WBIT (1 << 1) 72 73 #define write_dcc(x) \ 74 __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x)) 75 76 #define read_dcc(x) \ 77 __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x)) 78 79 #define status_dcc(x) \ 80 __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x)) 81 82 #endif 83 84 #define can_read_dcc(x) do { \ 85 status_dcc(x); \ 86 x &= DCC_RBIT; \ 87 } while (0); 88 89 #define can_write_dcc(x) do { \ 90 status_dcc(x); \ 91 x &= DCC_WBIT; \ 92 x = (x == 0); \ 93 } while (0); 94 95 #define TIMEOUT_COUNT 0x4000000 96 97 static int arm_dcc_init(void) 98 { 99 return 0; 100 } 101 102 static int arm_dcc_getc(void) 103 { 104 int ch; 105 register unsigned int reg; 106 107 do { 108 can_read_dcc(reg); 109 } while (!reg); 110 read_dcc(ch); 111 112 return ch; 113 } 114 115 static void arm_dcc_putc(char ch) 116 { 117 register unsigned int reg; 118 unsigned int timeout_count = TIMEOUT_COUNT; 119 120 while (--timeout_count) { 121 can_write_dcc(reg); 122 if (reg) 123 break; 124 } 125 if (timeout_count == 0) 126 return; 127 else 128 write_dcc(ch); 129 } 130 131 static int arm_dcc_tstc(void) 132 { 133 register unsigned int reg; 134 135 can_read_dcc(reg); 136 137 return reg; 138 } 139 140 static void arm_dcc_setbrg(void) 141 { 142 } 143 144 static struct serial_device arm_dcc_drv = { 145 .name = "arm_dcc", 146 .start = arm_dcc_init, 147 .stop = NULL, 148 .setbrg = arm_dcc_setbrg, 149 .putc = arm_dcc_putc, 150 .puts = default_serial_puts, 151 .getc = arm_dcc_getc, 152 .tstc = arm_dcc_tstc, 153 }; 154 155 void arm_dcc_initialize(void) 156 { 157 serial_register(&arm_dcc_drv); 158 } 159 160 __weak struct serial_device *default_serial_console(void) 161 { 162 return &arm_dcc_drv; 163 } 164