Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | } |