contrib: replace the GPLv2-or-later license tag
[fw/openocd] / contrib / libdcc / dcc_stdio.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2008 by Dominic Rath                                    *
5  *   Dominic.Rath@gmx.de                                                   *
6  *   Copyright (C) 2008 by Spencer Oliver                                  *
7  *   spen@spen-soft.co.uk                                                  *
8  *   Copyright (C) 2008 by Frederik Kriewtz                                *
9  *   frederik@kriewitz.eu                                                  *
10  ***************************************************************************/
11
12 #include "dcc_stdio.h"
13
14 #define TARGET_REQ_TRACEMSG                                     0x00
15 #define TARGET_REQ_DEBUGMSG_ASCII                       0x01
16 #define TARGET_REQ_DEBUGMSG_HEXMSG(size)        (0x01 | ((size & 0xff) << 8))
17 #define TARGET_REQ_DEBUGCHAR                            0x02
18
19 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_6SM__)
20
21 /* we use the System Control Block DCRDR reg to simulate a arm7_9 dcc channel
22  * DCRDR[7:0] is used by target for status
23  * DCRDR[15:8] is used by target for write buffer
24  * DCRDR[23:16] is used for by host for status
25  * DCRDR[31:24] is used for by host for write buffer */
26
27 #define NVIC_DBG_DATA_R         (*((volatile unsigned short *)0xE000EDF8))
28
29 #define BUSY    1
30
31 void dbg_write(unsigned long dcc_data)
32 {
33         int len = 4;
34
35         while (len--)
36         {
37                 /* wait for data ready */
38                 while (NVIC_DBG_DATA_R & BUSY);
39
40                 /* write our data and set write flag - tell host there is data*/
41                 NVIC_DBG_DATA_R = (unsigned short)(((dcc_data & 0xff) << 8) | BUSY);
42                 dcc_data >>= 8;
43         }
44 }
45
46 #elif defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5T__)
47
48 void dbg_write(unsigned long dcc_data)
49 {
50         unsigned long dcc_status;
51
52         do {
53                 asm volatile("mrc p14, 0, %0, c0, c0" : "=r" (dcc_status));
54         } while (dcc_status & 0x2);
55
56         asm volatile("mcr p14, 0, %0, c1, c0" : : "r" (dcc_data));
57 }
58
59 #else
60  #error unsupported target
61 #endif
62
63 void dbg_trace_point(unsigned long number)
64 {
65         dbg_write(TARGET_REQ_TRACEMSG | (number << 8));
66 }
67
68 void dbg_write_u32(const unsigned long *val, long len)
69 {
70         dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(4) | ((len & 0xffff) << 16));
71
72         while (len > 0)
73         {
74                 dbg_write(*val);
75
76                 val++;
77                 len--;
78         }
79 }
80
81 void dbg_write_u16(const unsigned short *val, long len)
82 {
83         unsigned long dcc_data;
84
85         dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(2) | ((len & 0xffff) << 16));
86
87         while (len > 0)
88         {
89                 dcc_data = val[0]
90                         | ((len > 1) ? val[1] << 16: 0x0000);
91
92                 dbg_write(dcc_data);
93
94                 val += 2;
95                 len -= 2;
96         }
97 }
98
99 void dbg_write_u8(const unsigned char *val, long len)
100 {
101         unsigned long dcc_data;
102
103         dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(1) | ((len & 0xffff) << 16));
104
105         while (len > 0)
106         {
107                 dcc_data = val[0]
108                         | ((len > 1) ? val[1] << 8 : 0x00)
109                         | ((len > 2) ? val[2] << 16 : 0x00)
110                         | ((len > 3) ? val[3] << 24 : 0x00);
111
112                 dbg_write(dcc_data);
113
114                 val += 4;
115                 len -= 4;
116         }
117 }
118
119 void dbg_write_str(const char *msg)
120 {
121         long len;
122         unsigned long dcc_data;
123
124         for (len = 0; msg[len] && (len < 65536); len++);
125
126         dbg_write(TARGET_REQ_DEBUGMSG_ASCII | ((len & 0xffff) << 16));
127
128         while (len > 0)
129         {
130                 dcc_data = msg[0]
131                         | ((len > 1) ? msg[1] << 8 : 0x00)
132                         | ((len > 2) ? msg[2] << 16 : 0x00)
133                         | ((len > 3) ? msg[3] << 24 : 0x00);
134                 dbg_write(dcc_data);
135
136                 msg += 4;
137                 len -= 4;
138         }
139 }
140
141 void dbg_write_char(char msg)
142 {
143         dbg_write(TARGET_REQ_DEBUGCHAR | ((msg & 0xff) << 16));
144 }