Linux 6.7-rc7
[linux-modified.git] / drivers / ata / pata_parport / on26.c
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);