diff options
Diffstat (limited to 'arch/ppc/xmon/adb.c')
-rw-r--r-- | arch/ppc/xmon/adb.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/arch/ppc/xmon/adb.c b/arch/ppc/xmon/adb.c new file mode 100644 index 000000000000..e91384dcccac --- /dev/null +++ b/arch/ppc/xmon/adb.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996 Paul Mackerras. | ||
3 | */ | ||
4 | #include "nonstdio.h" | ||
5 | #include "privinst.h" | ||
6 | |||
7 | #define scanhex xmon_scanhex | ||
8 | #define skipbl xmon_skipbl | ||
9 | |||
10 | #define ADB_B (*(volatile unsigned char *)0xf3016000) | ||
11 | #define ADB_SR (*(volatile unsigned char *)0xf3017400) | ||
12 | #define ADB_ACR (*(volatile unsigned char *)0xf3017600) | ||
13 | #define ADB_IFR (*(volatile unsigned char *)0xf3017a00) | ||
14 | |||
15 | static inline void eieio(void) { asm volatile ("eieio" : :); } | ||
16 | |||
17 | #define N_ADB_LOG 1000 | ||
18 | struct adb_log { | ||
19 | unsigned char b; | ||
20 | unsigned char ifr; | ||
21 | unsigned char acr; | ||
22 | unsigned int time; | ||
23 | } adb_log[N_ADB_LOG]; | ||
24 | int n_adb_log; | ||
25 | |||
26 | void | ||
27 | init_adb_log(void) | ||
28 | { | ||
29 | adb_log[0].b = ADB_B; | ||
30 | adb_log[0].ifr = ADB_IFR; | ||
31 | adb_log[0].acr = ADB_ACR; | ||
32 | adb_log[0].time = get_dec(); | ||
33 | n_adb_log = 0; | ||
34 | } | ||
35 | |||
36 | void | ||
37 | dump_adb_log(void) | ||
38 | { | ||
39 | unsigned t, t0; | ||
40 | struct adb_log *ap; | ||
41 | int i; | ||
42 | |||
43 | ap = adb_log; | ||
44 | t0 = ap->time; | ||
45 | for (i = 0; i <= n_adb_log; ++i, ++ap) { | ||
46 | t = t0 - ap->time; | ||
47 | printf("b=%x ifr=%x acr=%x at %d.%.7d\n", ap->b, ap->ifr, ap->acr, | ||
48 | t / 1000000000, (t % 1000000000) / 100); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | void | ||
53 | adb_chklog(void) | ||
54 | { | ||
55 | struct adb_log *ap = &adb_log[n_adb_log + 1]; | ||
56 | |||
57 | ap->b = ADB_B; | ||
58 | ap->ifr = ADB_IFR; | ||
59 | ap->acr = ADB_ACR; | ||
60 | if (ap->b != ap[-1].b || (ap->ifr & 4) != (ap[-1].ifr & 4) | ||
61 | || ap->acr != ap[-1].acr) { | ||
62 | ap->time = get_dec(); | ||
63 | ++n_adb_log; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | int | ||
68 | adb_bitwait(int bmask, int bval, int fmask, int fval) | ||
69 | { | ||
70 | int i; | ||
71 | struct adb_log *ap; | ||
72 | |||
73 | for (i = 10000; i > 0; --i) { | ||
74 | adb_chklog(); | ||
75 | ap = &adb_log[n_adb_log]; | ||
76 | if ((ap->b & bmask) == bval && (ap->ifr & fmask) == fval) | ||
77 | return 0; | ||
78 | } | ||
79 | return -1; | ||
80 | } | ||
81 | |||
82 | int | ||
83 | adb_wait(void) | ||
84 | { | ||
85 | if (adb_bitwait(0, 0, 4, 4) < 0) { | ||
86 | printf("adb: ready wait timeout\n"); | ||
87 | return -1; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | void | ||
93 | adb_readin(void) | ||
94 | { | ||
95 | int i, j; | ||
96 | unsigned char d[64]; | ||
97 | |||
98 | if (ADB_B & 8) { | ||
99 | printf("ADB_B: %x\n", ADB_B); | ||
100 | return; | ||
101 | } | ||
102 | i = 0; | ||
103 | adb_wait(); | ||
104 | j = ADB_SR; | ||
105 | eieio(); | ||
106 | ADB_B &= ~0x20; | ||
107 | eieio(); | ||
108 | for (;;) { | ||
109 | if (adb_wait() < 0) | ||
110 | break; | ||
111 | d[i++] = ADB_SR; | ||
112 | eieio(); | ||
113 | if (ADB_B & 8) | ||
114 | break; | ||
115 | ADB_B ^= 0x10; | ||
116 | eieio(); | ||
117 | } | ||
118 | ADB_B |= 0x30; | ||
119 | if (adb_wait() == 0) | ||
120 | j = ADB_SR; | ||
121 | for (j = 0; j < i; ++j) | ||
122 | printf("%.2x ", d[j]); | ||
123 | printf("\n"); | ||
124 | } | ||
125 | |||
126 | int | ||
127 | adb_write(unsigned char *d, int i) | ||
128 | { | ||
129 | int j; | ||
130 | unsigned x; | ||
131 | |||
132 | if ((ADB_B & 8) == 0) { | ||
133 | printf("r: "); | ||
134 | adb_readin(); | ||
135 | } | ||
136 | for (;;) { | ||
137 | ADB_ACR = 0x1c; | ||
138 | eieio(); | ||
139 | ADB_SR = d[0]; | ||
140 | eieio(); | ||
141 | ADB_B &= ~0x20; | ||
142 | eieio(); | ||
143 | if (ADB_B & 8) | ||
144 | break; | ||
145 | ADB_ACR = 0xc; | ||
146 | eieio(); | ||
147 | ADB_B |= 0x20; | ||
148 | eieio(); | ||
149 | adb_readin(); | ||
150 | } | ||
151 | adb_wait(); | ||
152 | for (j = 1; j < i; ++j) { | ||
153 | ADB_SR = d[j]; | ||
154 | eieio(); | ||
155 | ADB_B ^= 0x10; | ||
156 | eieio(); | ||
157 | if (adb_wait() < 0) | ||
158 | break; | ||
159 | } | ||
160 | ADB_ACR = 0xc; | ||
161 | eieio(); | ||
162 | x = ADB_SR; | ||
163 | eieio(); | ||
164 | ADB_B |= 0x30; | ||
165 | return j; | ||
166 | } | ||
167 | |||
168 | void | ||
169 | adbcmds(void) | ||
170 | { | ||
171 | char cmd; | ||
172 | unsigned rtcu, rtcl, dec, pdec, x; | ||
173 | int i, j; | ||
174 | unsigned char d[64]; | ||
175 | |||
176 | cmd = skipbl(); | ||
177 | switch (cmd) { | ||
178 | case 't': | ||
179 | for (;;) { | ||
180 | rtcl = get_rtcl(); | ||
181 | rtcu = get_rtcu(); | ||
182 | dec = get_dec(); | ||
183 | printf("rtc u=%u l=%u dec=%x (%d = %d.%.7d)\n", | ||
184 | rtcu, rtcl, dec, pdec - dec, (pdec - dec) / 1000000000, | ||
185 | ((pdec - dec) % 1000000000) / 100); | ||
186 | pdec = dec; | ||
187 | if (cmd == 'x') | ||
188 | break; | ||
189 | while (xmon_read(stdin, &cmd, 1) != 1) | ||
190 | ; | ||
191 | } | ||
192 | break; | ||
193 | case 'r': | ||
194 | init_adb_log(); | ||
195 | while (adb_bitwait(8, 0, 0, 0) == 0) | ||
196 | adb_readin(); | ||
197 | break; | ||
198 | case 'w': | ||
199 | i = 0; | ||
200 | while (scanhex(&x)) | ||
201 | d[i++] = x; | ||
202 | init_adb_log(); | ||
203 | j = adb_write(d, i); | ||
204 | printf("sent %d bytes\n", j); | ||
205 | while (adb_bitwait(8, 0, 0, 0) == 0) | ||
206 | adb_readin(); | ||
207 | break; | ||
208 | case 'l': | ||
209 | dump_adb_log(); | ||
210 | break; | ||
211 | } | ||
212 | } | ||