1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (c) 1997-1998 Grant R. Guenther <grant@torque.net> 4 * 5 * on26.c is a low-level protocol driver for the 6 * OnSpec 90c26 parallel to IDE adapter chip. 7 */ 8 9 #include <linux/module.h> 10 #include <linux/init.h> 11 #include <linux/delay.h> 12 #include <linux/kernel.h> 13 #include <linux/types.h> 14 #include <linux/wait.h> 15 #include <asm/io.h> 16 #include "pata_parport.h" 17 18 /* 19 * mode codes: 0 nybble reads, 8-bit writes 20 * 1 8-bit reads and writes 21 * 2 8-bit EPP mode 22 * 3 EPP-16 23 * 4 EPP-32 24 */ 25 26 #define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) 27 28 #define P1 \ 29 do { \ 30 w2(5); w2(0xd); w2(5); w2(0xd); w2(5); w2(4); \ 31 } while (0) 32 33 #define P2 \ 34 do { \ 35 w2(5); w2(7); w2(5); w2(4); \ 36 } while (0) 37 38 /* 39 * cont = 0 - access the IDE register file 40 * cont = 1 - access the IDE command set 41 */ 42 43 static int on26_read_regr(struct pi_adapter *pi, int cont, int regr) 44 { 45 int a, b, r; 46 47 r = (regr << 2) + 1 + cont; 48 49 switch (pi->mode) { 50 case 0: 51 w0(1); P1; w0(r); P2; w0(0); P1; 52 w2(6); a = r1(); w2(4); 53 w2(6); b = r1(); w2(4); 54 w2(6); w2(4); w2(6); w2(4); 55 return j44(a, b); 56 case 1: 57 w0(1); P1; w0(r); P2; w0(0); P1; 58 w2(0x26); a = r0(); w2(4); w2(0x26); w2(4); 59 return a; 60 case 2: 61 case 3: 62 case 4: 63 w3(1); w3(1); w2(5); w4(r); w2(4); 64 w3(0); w3(0); w2(0x24); a = r4(); w2(4); 65 w2(0x24); (void)r4(); w2(4); 66 return a; 67 } 68 69 return -1; 70 } 71 72 static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 73 { 74 int r = (regr << 2) + 1 + cont; 75 76 switch (pi->mode) { 77 case 0: 78 case 1: 79 w0(1); P1; w0(r); P2; w0(0); P1; 80 w0(val); P2; w0(val); P2; 81 break; 82 case 2: 83 case 3: 84 case 4: 85 w3(1); w3(1); w2(5); w4(r); w2(4); 86 w3(0); w3(0); 87 w2(5); w4(val); w2(4); 88 w2(5); w4(val); w2(4); 89 break; 90 } 91 } 92 93 #define CCP(x) \ 94 do { \ 95 w0(0xfe); w0(0xaa); w0(0x55); w0(0); \ 96 w0(0xff); w0(0x87); w0(0x78); w0(x); \ 97 w2(4); w2(5); w2(4); w0(0xff); \ 98 } while (0) 99 100 static void on26_connect(struct pi_adapter *pi) 101 { 102 int x; 103 104 pi->saved_r0 = r0(); 105 pi->saved_r2 = r2(); 106 107 CCP(0x20); 108 if (pi->mode) 109 x = 9; 110 else 111 x = 8; 112 113 w0(2); P1; w0(8); P2; 114 w0(2); P1; w0(x); P2; 115 } 116 117 static void on26_disconnect(struct pi_adapter *pi) 118 { 119 if (pi->mode >= 2) { 120 w3(4); w3(4); w3(4); w3(4); 121 } else { 122 w0(4); P1; w0(4); P1; 123 } 124 CCP(0x30); 125 w0(pi->saved_r0); 126 w2(pi->saved_r2); 127 } 128 129 #define RESET_WAIT 200 130 131 /* hard reset */ 132 static int on26_test_port(struct pi_adapter *pi) 133 { 134 int i, m, d, x = 0, y = 0; 135 136 pi->saved_r0 = r0(); 137 pi->saved_r2 = r2(); 138 139 d = pi->delay; 140 m = pi->mode; 141 pi->delay = 5; 142 pi->mode = 0; 143 144 w2(0xc); 145 146 CCP(0x30); CCP(0); 147 148 w0(0xfe); w0(0xaa); w0(0x55); w0(0); w0(0xff); 149 i = ((r1() & 0xf0) << 4); w0(0x87); 150 i |= (r1() & 0xf0); w0(0x78); 151 w0(0x20); w2(4); w2(5); 152 i |= ((r1() & 0xf0) >> 4); 153 w2(4); w0(0xff); 154 155 if (i == 0xb5f) { 156 w0(2); P1; w0(0); P2; 157 w0(3); P1; w0(0); P2; 158 w0(2); P1; w0(8); P2; udelay(100); 159 w0(2); P1; w0(0xa); P2; udelay(100); 160 w0(2); P1; w0(8); P2; udelay(1000); 161 162 on26_write_regr(pi, 0, 6, 0xa0); 163 164 for (i = 0; i < RESET_WAIT; i++) { 165 on26_write_regr(pi, 0, 6, 0xa0); 166 x = on26_read_regr(pi, 0, 7); 167 on26_write_regr(pi, 0, 6, 0xb0); 168 y = on26_read_regr(pi, 0, 7); 169 if (!((x & 0x80) || (y & 0x80))) 170 break; 171 mdelay(100); 172 } 173 174 if (i == RESET_WAIT) 175 dev_err(&pi->dev, 176 "on26: Device reset failed (%x,%x)\n", x, y); 177 178 w0(4); P1; w0(4); P1; 179 } 180 181 CCP(0x30); 182 183 pi->delay = d; 184 pi->mode = m; 185 w0(pi->saved_r0); 186 w2(pi->saved_r2); 187 188 return 5; 189 } 190 191 static void on26_read_block(struct pi_adapter *pi, char *buf, int count) 192 { 193 int k, a, b; 194 195 switch (pi->mode) { 196 case 0: 197 w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1; 198 udelay(10); 199 for (k = 0; k < count; k++) { 200 w2(6); a = r1(); 201 w2(4); b = r1(); 202 buf[k] = j44(a, b); 203 } 204 w0(2); P1; w0(8); P2; 205 break; 206 case 1: 207 w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1; 208 udelay(10); 209 for (k = 0; k < count / 2; k++) { 210 w2(0x26); buf[2 * k] = r0(); 211 w2(0x24); buf[2 * k + 1] = r0(); 212 } 213 w0(2); P1; w0(9); P2; 214 break; 215 case 2: 216 w3(1); w3(1); w2(5); w4(1); w2(4); 217 w3(0); w3(0); w2(0x24); 218 udelay(10); 219 for (k = 0; k < count; k++) 220 buf[k] = r4(); 221 w2(4); 222 break; 223 case 3: 224 w3(1); w3(1); w2(5); w4(1); w2(4); 225 w3(0); w3(0); w2(0x24); 226 udelay(10); 227 for (k = 0; k < count / 2; k++) 228 ((u16 *)buf)[k] = r4w(); 229 w2(4); 230 break; 231 case 4: 232 w3(1); w3(1); w2(5); w4(1); w2(4); 233 w3(0); w3(0); w2(0x24); 234 udelay(10); 235 for (k = 0; k < count / 4; k++) 236 ((u32 *)buf)[k] = r4l(); 237 w2(4); 238 break; 239 } 240 } 241 242 static void on26_write_block(struct pi_adapter *pi, char *buf, int count) 243 { 244 int k; 245 246 switch (pi->mode) { 247 case 0: 248 case 1: 249 w0(1); P1; w0(1); P2; 250 w0(2); P1; w0(0x18 + pi->mode); P2; w0(0); P1; 251 udelay(10); 252 for (k = 0; k < count / 2; k++) { 253 w2(5); w0(buf[2 * k]); 254 w2(7); w0(buf[2 * k + 1]); 255 } 256 w2(5); w2(4); 257 w0(2); P1; w0(8 + pi->mode); P2; 258 break; 259 case 2: 260 w3(1); w3(1); w2(5); w4(1); w2(4); 261 w3(0); w3(0); w2(0xc5); 262 udelay(10); 263 for (k = 0; k < count; k++) 264 w4(buf[k]); 265 w2(0xc4); 266 break; 267 case 3: 268 w3(1); w3(1); w2(5); w4(1); w2(4); 269 w3(0); w3(0); w2(0xc5); 270 udelay(10); 271 for (k = 0; k < count / 2; k++) 272 w4w(((u16 *)buf)[k]); 273 w2(0xc4); 274 break; 275 case 4: 276 w3(1); w3(1); w2(5); w4(1); w2(4); 277 w3(0); w3(0); w2(0xc5); 278 udelay(10); 279 for (k = 0; k < count / 4; k++) 280 w4l(((u32 *)buf)[k]); 281 w2(0xc4); 282 break; 283 } 284 } 285 286 static void on26_log_adapter(struct pi_adapter *pi) 287 { 288 char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; 289 290 dev_info(&pi->dev, 291 "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n", 292 pi->port, pi->mode, mode_string[pi->mode], pi->delay); 293 } 294 295 static struct pi_protocol on26 = { 296 .owner = THIS_MODULE, 297 .name = "on26", 298 .max_mode = 5, 299 .epp_first = 2, 300 .default_delay = 1, 301 .max_units = 1, 302 .write_regr = on26_write_regr, 303 .read_regr = on26_read_regr, 304 .write_block = on26_write_block, 305 .read_block = on26_read_block, 306 .connect = on26_connect, 307 .disconnect = on26_disconnect, 308 .test_port = on26_test_port, 309 .log_adapter = on26_log_adapter, 310 }; 311 312 MODULE_LICENSE("GPL"); 313 MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>"); 314 MODULE_DESCRIPTION("Onspec 90c26 parallel port IDE adapter protocol driver"); 315 module_pata_parport_driver(on26); 316