1 /* 2 * Copyright (C) 2004-2007 ARM Limited. 3 * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 4 * Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek 5 * 6 * SPDX-License-Identifier: GPL-2.0 7 * 8 * As a special exception, if other files instantiate templates or use macros 9 * or inline functions from this file, or you compile this file and link it 10 * with other works to produce a work based on this file, this file does not 11 * by itself cause the resulting work to be covered by the GNU General Public 12 * License. However the source code for this file must still be made available 13 * in accordance with section (3) of the GNU General Public License. 14 15 * This exception does not invalidate any other reasons why a work based on 16 * this file might be covered by the GNU General Public License. 17 */ 18 19 #include <common.h> 20 #include <dm.h> 21 #include <serial.h> 22 23 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7) 24 /* 25 * ARMV6 & ARMV7 26 */ 27 #define DCC_RBIT (1 << 30) 28 #define DCC_WBIT (1 << 29) 29 30 #define write_dcc(x) \ 31 __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x)) 32 33 #define read_dcc(x) \ 34 __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x)) 35 36 #define status_dcc(x) \ 37 __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x)) 38 39 #elif defined(CONFIG_CPU_XSCALE) 40 /* 41 * XSCALE 42 */ 43 #define DCC_RBIT (1 << 31) 44 #define DCC_WBIT (1 << 28) 45 46 #define write_dcc(x) \ 47 __asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x)) 48 49 #define read_dcc(x) \ 50 __asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x)) 51 52 #define status_dcc(x) \ 53 __asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x)) 54 55 #elif defined(CONFIG_CPU_ARMV8) 56 /* 57 * ARMV8 58 */ 59 #define DCC_RBIT (1 << 30) 60 #define DCC_WBIT (1 << 29) 61 62 #define write_dcc(x) \ 63 __asm__ volatile ("msr dbgdtrtx_el0, %0\n" : : "r" (x)) 64 65 #define read_dcc(x) \ 66 __asm__ volatile ("mrs %0, dbgdtrrx_el0\n" : "=r" (x)) 67 68 #define status_dcc(x) \ 69 __asm__ volatile ("mrs %0, mdccsr_el0\n" : "=r" (x)) 70 71 #else 72 #define DCC_RBIT (1 << 0) 73 #define DCC_WBIT (1 << 1) 74 75 #define write_dcc(x) \ 76 __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x)) 77 78 #define read_dcc(x) \ 79 __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x)) 80 81 #define status_dcc(x) \ 82 __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x)) 83 84 #endif 85 86 #define can_read_dcc(x) do { \ 87 status_dcc(x); \ 88 x &= DCC_RBIT; \ 89 } while (0); 90 91 #define can_write_dcc(x) do { \ 92 status_dcc(x); \ 93 x &= DCC_WBIT; \ 94 x = (x == 0); \ 95 } while (0); 96 97 #define TIMEOUT_COUNT 0x4000000 98 99 static int arm_dcc_getc(struct udevice *dev) 100 { 101 int ch; 102 register unsigned int reg; 103 104 do { 105 can_read_dcc(reg); 106 } while (!reg); 107 read_dcc(ch); 108 109 return ch; 110 } 111 112 static int arm_dcc_putc(struct udevice *dev, char ch) 113 { 114 register unsigned int reg; 115 unsigned int timeout_count = TIMEOUT_COUNT; 116 117 while (--timeout_count) { 118 can_write_dcc(reg); 119 if (reg) 120 break; 121 } 122 if (timeout_count == 0) 123 return -EAGAIN; 124 else 125 write_dcc(ch); 126 127 return 0; 128 } 129 130 static int arm_dcc_pending(struct udevice *dev, bool input) 131 { 132 register unsigned int reg; 133 134 if (input) { 135 can_read_dcc(reg); 136 } else { 137 can_write_dcc(reg); 138 } 139 140 return reg; 141 } 142 143 static const struct dm_serial_ops arm_dcc_ops = { 144 .putc = arm_dcc_putc, 145 .pending = arm_dcc_pending, 146 .getc = arm_dcc_getc, 147 }; 148 149 static const struct udevice_id arm_dcc_ids[] = { 150 { .compatible = "arm,dcc", }, 151 { } 152 }; 153 154 U_BOOT_DRIVER(serial_dcc) = { 155 .name = "arm_dcc", 156 .id = UCLASS_SERIAL, 157 .of_match = arm_dcc_ids, 158 .ops = &arm_dcc_ops, 159 .flags = DM_FLAG_PRE_RELOC, 160 }; 161 162 #ifdef CONFIG_DEBUG_UART_ARM_DCC 163 164 #include <debug_uart.h> 165 166 static inline void _debug_uart_init(void) 167 { 168 } 169 170 static inline void _debug_uart_putc(int ch) 171 { 172 arm_dcc_putc(NULL, ch); 173 } 174 175 DEBUG_UART_FUNCS 176 #endif 177