arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / drivers / ata / pata_parport / epat.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * (c) 1997-1998  Grant R. Guenther <grant@torque.net>
4  *
5  * This is the low level protocol driver for the EPAT parallel
6  * to IDE adapter from Shuttle Technologies.  This adapter is
7  * used in many popular parallel port disk products such as the
8  * SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
9  */
10
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/wait.h>
17 #include <asm/io.h>
18 #include "pata_parport.h"
19
20 #define j44(a, b)       (((a >> 4) & 0x0f) + (b & 0xf0))
21 #define j53(a, b)       (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
22
23 static int epatc8;
24
25 module_param(epatc8, int, 0);
26 MODULE_PARM_DESC(epatc8,
27                  "support for the Shuttle EP1284 chip, "
28                  "used in any recent Imation SuperDisk (LS-120) drive.");
29
30 /*
31  * cont =  0   IDE register file
32  * cont =  1   IDE control registers
33  * cont =  2   internal EPAT registers
34  */
35 static int cont_map[3] = { 0x18, 0x10, 0 };
36
37 static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
38 {
39         int r = regr + cont_map[cont];
40
41         switch (pi->mode) {
42         case 0:
43         case 1:
44         case 2:
45                 w0(0x60+r); w2(1); w0(val); w2(4);
46                 break;
47         case 3:
48         case 4:
49         case 5:
50                 w3(0x40+r); w4(val);
51                 break;
52         }
53 }
54
55 static int epat_read_regr(struct pi_adapter *pi, int cont, int regr)
56 {
57         int  a, b, r;
58
59         r = regr + cont_map[cont];
60
61         switch (pi->mode) {
62
63         case 0:
64                 w0(r); w2(1); w2(3);
65                 a = r1(); w2(4); b = r1();
66                 return j44(a, b);
67         case 1:
68                 w0(0x40+r); w2(1); w2(4);
69                 a = r1(); b = r2(); w0(0xff);
70                 return j53(a, b);
71         case 2:
72                 w0(0x20+r); w2(1); w2(0x25);
73                 a = r0(); w2(4);
74                 return a;
75         case 3:
76         case 4:
77         case 5:
78                 w3(r); w2(0x24); a = r4(); w2(4);
79                 return a;
80         }
81
82         return -1;      /* never gets here */
83 }
84
85 static void epat_read_block(struct pi_adapter *pi, char *buf, int count)
86 {
87         int  k, ph, a, b;
88
89         switch (pi->mode) {
90
91         case 0:
92                 w0(7); w2(1); w2(3); w0(0xff);
93                 ph = 0;
94                 for (k = 0; k < count; k++) {
95                         if (k == count-1)
96                                 w0(0xfd);
97                         w2(6 + ph); a = r1();
98                         if (a & 8) {
99                                 b = a;
100                         } else {
101                                 w2(4+ph); b = r1();
102                         }
103                         buf[k] = j44(a, b);
104                         ph =  1 - ph;
105                 }
106                 w0(0); w2(4);
107                 break;
108
109         case 1:
110                 w0(0x47); w2(1); w2(5); w0(0xff);
111                 ph = 0;
112                 for (k = 0; k < count; k++) {
113                         if (k == count - 1)
114                                 w0(0xfd);
115                         w2(4 + ph);
116                         a = r1(); b = r2();
117                         buf[k] = j53(a, b);
118                         ph = 1 - ph;
119                 }
120                 w0(0); w2(4);
121                 break;
122
123         case 2:
124                 w0(0x27); w2(1); w2(0x25); w0(0);
125                 ph = 0;
126                 for (k = 0; k < count - 1; k++) {
127                         w2(0x24 + ph);
128                         buf[k] = r0();
129                         ph = 1 - ph;
130                 }
131                 w2(0x26); w2(0x27);
132                 buf[count - 1] = r0();
133                 w2(0x25); w2(4);
134                 break;
135
136         case 3:
137                 w3(0x80); w2(0x24);
138                 for (k = 0; k < count - 1; k++)
139                         buf[k] = r4();
140                 w2(4); w3(0xa0); w2(0x24);
141                 buf[count - 1] = r4();
142                 w2(4);
143                 break;
144
145         case 4:
146                 w3(0x80); w2(0x24);
147                 for (k = 0; k < count / 2 - 1; k++)
148                         ((u16 *)buf)[k] = r4w();
149                 buf[count - 2] = r4();
150                 w2(4); w3(0xa0); w2(0x24);
151                 buf[count - 1] = r4();
152                 w2(4);
153                 break;
154
155         case 5:
156                 w3(0x80); w2(0x24);
157                 for (k = 0; k < count / 4 - 1; k++)
158                         ((u32 *)buf)[k] = r4l();
159                 for (k = count - 4; k < count - 1; k++)
160                         buf[k] = r4();
161                 w2(4); w3(0xa0); w2(0x24);
162                 buf[count - 1] = r4();
163                 w2(4);
164                 break;
165         }
166 }
167
168 static void epat_write_block(struct pi_adapter *pi, char *buf, int count)
169 {
170         int ph, k;
171
172         switch (pi->mode) {
173         case 0:
174         case 1:
175         case 2:
176                 w0(0x67); w2(1); w2(5);
177                 ph = 0;
178                 for (k = 0; k < count; k++) {
179                         w0(buf[k]);
180                         w2(4 + ph);
181                         ph = 1 - ph;
182                 }
183                 w2(7); w2(4);
184                 break;
185         case 3:
186                 w3(0xc0);
187                 for (k = 0; k < count; k++)
188                         w4(buf[k]);
189                 w2(4);
190                 break;
191         case 4:
192                 w3(0xc0);
193                 for (k = 0; k < count / 2; k++)
194                         w4w(((u16 *)buf)[k]);
195                 w2(4);
196                 break;
197         case 5:
198                 w3(0xc0);
199                 for (k = 0; k < count / 4; k++)
200                         w4l(((u32 *)buf)[k]);
201                 w2(4);
202                 break;
203         }
204 }
205
206 /* these macros access the EPAT registers in native addressing */
207
208 #define WR(r, v)        epat_write_regr(pi, 2, r, v)
209 #define RR(r)           epat_read_regr(pi, 2, r)
210
211 /* and these access the IDE task file */
212
213 #define WRi(r, v)       epat_write_regr(pi, 0, r, v)
214 #define RRi(r)          epat_read_regr(pi, 0, r)
215
216 /* FIXME:  the CPP stuff should be fixed to handle multiple EPATs on a chain */
217
218 #define CPP(x)                                  \
219         do {                                    \
220                 w2(4); w0(0x22); w0(0xaa);      \
221                 w0(0x55); w0(0); w0(0xff);      \
222                 w0(0x87); w0(0x78); w0(x);      \
223                 w2(4); w2(5); w2(4); w0(0xff);  \
224         } while (0)
225
226 static void epat_connect(struct pi_adapter *pi)
227 {
228         pi->saved_r0 = r0();
229         pi->saved_r2 = r2();
230
231         /* Initialize the chip */
232         CPP(0);
233
234         if (epatc8) {
235                 CPP(0x40); CPP(0xe0);
236                 w0(0); w2(1); w2(4);
237                 WR(0x8, 0x12);
238                 WR(0xc, 0x14);
239                 WR(0x12, 0x10);
240                 WR(0xe, 0xf);
241                 WR(0xf, 4);
242                 /* WR(0xe,0xa);WR(0xf,4); */
243                 WR(0xe, 0xd);
244                 WR(0xf, 0);
245                 /* CPP(0x30); */
246         }
247
248         /* Connect to the chip */
249         CPP(0xe0);
250         w0(0); w2(1); w2(4); /* Idle into SPP */
251         if (pi->mode >= 3) {
252                 w0(0); w2(1); w2(4); w2(0xc);
253                 /* Request EPP */
254                 w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4);
255         }
256
257         if (!epatc8) {
258                 WR(8, 0x10);
259                 WR(0xc, 0x14);
260                 WR(0xa, 0x38);
261                 WR(0x12, 0x10);
262         }
263 }
264
265 static void epat_disconnect(struct pi_adapter *pi)
266 {
267         CPP(0x30);
268         w0(pi->saved_r0);
269         w2(pi->saved_r2);
270 }
271
272 static int epat_test_proto(struct pi_adapter *pi)
273 {
274         int k, j, f, cc;
275         int e[2] = { 0, 0 };
276         char scratch[512];
277
278         epat_connect(pi);
279         cc = RR(0xd);
280         epat_disconnect(pi);
281
282         epat_connect(pi);
283         for (j=0;j<2;j++) {
284                 WRi(6, 0xa0 + j * 0x10);
285                 for (k = 0; k < 256; k++) {
286                         WRi(2, k ^ 0xaa);
287                         WRi(3, k ^ 0x55);
288                         if (RRi(2) != (k ^ 0xaa))
289                                 e[j]++;
290                 }
291         }
292         epat_disconnect(pi);
293
294         f = 0;
295         epat_connect(pi);
296         WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11);
297         epat_read_block(pi, scratch, 512);
298
299         for (k = 0; k < 256; k++) {
300                 if ((scratch[2 * k] & 0xff) != k)
301                         f++;
302                 if ((scratch[2 * k + 1] & 0xff) != 0xff - k)
303                         f++;
304         }
305         epat_disconnect(pi);
306
307         dev_dbg(&pi->dev,
308                 "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
309                 pi->port, pi->mode, cc, e[0], e[1], f);
310
311         return (e[0] && e[1]) || f;
312 }
313
314 static void epat_log_adapter(struct pi_adapter *pi)
315 {
316         int ver;
317         char *mode_string[6] =
318                 { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
319
320         epat_connect(pi);
321         WR(0xa, 0x38);          /* read the version code */
322         ver = RR(0xb);
323         epat_disconnect(pi);
324
325         dev_info(&pi->dev,
326                  "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n",
327                  ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
328 }
329
330 static struct pi_protocol epat = {
331         .owner          = THIS_MODULE,
332         .name           = "epat",
333         .max_mode       = 6,
334         .epp_first      = 3,
335         .default_delay  = 1,
336         .max_units      = 1,
337         .write_regr     = epat_write_regr,
338         .read_regr      = epat_read_regr,
339         .write_block    = epat_write_block,
340         .read_block     = epat_read_block,
341         .connect        = epat_connect,
342         .disconnect     = epat_disconnect,
343         .test_proto     = epat_test_proto,
344         .log_adapter    = epat_log_adapter,
345 };
346
347 static int __init epat_init(void)
348 {
349 #ifdef CONFIG_PATA_PARPORT_EPATC8
350         epatc8 = 1;
351 #endif
352         return pata_parport_register_driver(&epat);
353 }
354
355 static void __exit epat_exit(void)
356 {
357         pata_parport_unregister_driver(&epat);
358 }
359
360 MODULE_LICENSE("GPL");
361 MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
362 MODULE_DESCRIPTION("Shuttle Technologies EPAT parallel port IDE adapter "
363                    "protocol driver");
364 module_init(epat_init)
365 module_exit(epat_exit)