Linux 6.7-rc7
[linux-modified.git] / drivers / ata / pata_parport / bpck6.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * (c) 2001 Micro Solutions Inc.
4  *
5  * backpack.c is a low-level protocol driver for the Micro Solutions
6  * "BACKPACK" parallel port IDE adapter (works on Series 6 drives).
7  *
8  * Written by: Ken Hahn (linux-dev@micro-solutions.com)
9  *             Clive Turvey (linux-dev@micro-solutions.com)
10  */
11
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/parport.h>
17 #include "pata_parport.h"
18
19 /* 60772 Commands */
20 #define ACCESS_REG              0x00
21 #define ACCESS_PORT             0x40
22
23 #define ACCESS_READ             0x00
24 #define ACCESS_WRITE            0x20
25
26 /* 60772 Command Prefix */
27 #define CMD_PREFIX_SET          0xe0    // Special command that modifies next command's operation
28 #define CMD_PREFIX_RESET        0xc0    // Resets current cmd modifier reg bits
29  #define PREFIX_IO16            0x01    // perform 16-bit wide I/O
30  #define PREFIX_FASTWR          0x04    // enable PPC mode fast-write
31  #define PREFIX_BLK             0x08    // enable block transfer mode
32
33 /* 60772 Registers */
34 #define REG_STATUS              0x00    // status register
35  #define STATUS_IRQA            0x01    // Peripheral IRQA line
36  #define STATUS_EEPROM_DO       0x40    // Serial EEPROM data bit
37 #define REG_VERSION             0x01    // PPC version register (read)
38 #define REG_HWCFG               0x02    // Hardware Config register
39 #define REG_RAMSIZE             0x03    // Size of RAM Buffer
40  #define RAMSIZE_128K           0x02
41 #define REG_EEPROM              0x06    // EEPROM control register
42  #define EEPROM_SK              0x01    // eeprom SK bit
43  #define EEPROM_DI              0x02    // eeprom DI bit
44  #define EEPROM_CS              0x04    // eeprom CS bit
45  #define EEPROM_EN              0x08    // eeprom output enable
46 #define REG_BLKSIZE             0x08    // Block transfer len (24 bit)
47
48 /* flags */
49 #define fifo_wait               0x10
50
51 /* DONT CHANGE THESE LEST YOU BREAK EVERYTHING - BIT FIELD DEPENDENCIES */
52 #define PPCMODE_UNI_SW          0
53 #define PPCMODE_UNI_FW          1
54 #define PPCMODE_BI_SW           2
55 #define PPCMODE_BI_FW           3
56 #define PPCMODE_EPP_BYTE        4
57 #define PPCMODE_EPP_WORD        5
58 #define PPCMODE_EPP_DWORD       6
59
60 static int mode_map[] = { PPCMODE_UNI_FW, PPCMODE_BI_FW, PPCMODE_EPP_BYTE,
61                           PPCMODE_EPP_WORD, PPCMODE_EPP_DWORD };
62
63 static void bpck6_send_cmd(struct pi_adapter *pi, u8 cmd)
64 {
65         switch (mode_map[pi->mode]) {
66         case PPCMODE_UNI_SW:
67         case PPCMODE_UNI_FW:
68         case PPCMODE_BI_SW:
69         case PPCMODE_BI_FW:
70                 parport_write_data(pi->pardev->port, cmd);
71                 parport_frob_control(pi->pardev->port, 0, PARPORT_CONTROL_AUTOFD);
72                 break;
73         case PPCMODE_EPP_BYTE:
74         case PPCMODE_EPP_WORD:
75         case PPCMODE_EPP_DWORD:
76                 pi->pardev->port->ops->epp_write_addr(pi->pardev->port, &cmd, 1, 0);
77                 break;
78         }
79 }
80
81 static u8 bpck6_rd_data_byte(struct pi_adapter *pi)
82 {
83         u8 data = 0;
84
85         switch (mode_map[pi->mode]) {
86         case PPCMODE_UNI_SW:
87         case PPCMODE_UNI_FW:
88                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
89                                                         PARPORT_CONTROL_INIT);
90                 data = parport_read_status(pi->pardev->port);
91                 data = ((data & 0x80) >> 1) | ((data & 0x38) >> 3);
92                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
93                                                         PARPORT_CONTROL_STROBE);
94                 data |= parport_read_status(pi->pardev->port) & 0xB8;
95                 break;
96         case PPCMODE_BI_SW:
97         case PPCMODE_BI_FW:
98                 parport_data_reverse(pi->pardev->port);
99                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
100                                 PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT);
101                 data = parport_read_data(pi->pardev->port);
102                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE, 0);
103                 parport_data_forward(pi->pardev->port);
104                 break;
105         case PPCMODE_EPP_BYTE:
106         case PPCMODE_EPP_WORD:
107         case PPCMODE_EPP_DWORD:
108                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, &data, 1, 0);
109                 break;
110         }
111
112         return data;
113 }
114
115 static void bpck6_wr_data_byte(struct pi_adapter *pi, u8 data)
116 {
117         switch (mode_map[pi->mode]) {
118         case PPCMODE_UNI_SW:
119         case PPCMODE_UNI_FW:
120         case PPCMODE_BI_SW:
121         case PPCMODE_BI_FW:
122                 parport_write_data(pi->pardev->port, data);
123                 parport_frob_control(pi->pardev->port, 0, PARPORT_CONTROL_INIT);
124                 break;
125         case PPCMODE_EPP_BYTE:
126         case PPCMODE_EPP_WORD:
127         case PPCMODE_EPP_DWORD:
128                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, &data, 1, 0);
129                 break;
130         }
131 }
132
133 static int bpck6_read_regr(struct pi_adapter *pi, int cont, int reg)
134 {
135         u8 port = cont ? reg | 8 : reg;
136
137         bpck6_send_cmd(pi, port | ACCESS_PORT | ACCESS_READ);
138         return bpck6_rd_data_byte(pi);
139 }
140
141 static void bpck6_write_regr(struct pi_adapter *pi, int cont, int reg, int val)
142 {
143         u8 port = cont ? reg | 8 : reg;
144
145         bpck6_send_cmd(pi, port | ACCESS_PORT | ACCESS_WRITE);
146         bpck6_wr_data_byte(pi, val);
147 }
148
149 static void bpck6_wait_for_fifo(struct pi_adapter *pi)
150 {
151         int i;
152
153         if (pi->private & fifo_wait) {
154                 for (i = 0; i < 20; i++)
155                         parport_read_status(pi->pardev->port);
156         }
157 }
158
159 static void bpck6_write_block(struct pi_adapter *pi, char *buf, int len)
160 {
161         u8 this, last;
162
163         bpck6_send_cmd(pi, REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE);
164         bpck6_wr_data_byte(pi, (u8)len);
165         bpck6_wr_data_byte(pi, (u8)(len >> 8));
166         bpck6_wr_data_byte(pi, 0);
167
168         bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK);
169         bpck6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_WRITE);
170
171         switch (mode_map[pi->mode]) {
172         case PPCMODE_UNI_SW:
173         case PPCMODE_BI_SW:
174                 while (len--) {
175                         parport_write_data(pi->pardev->port, *buf++);
176                         parport_frob_control(pi->pardev->port, 0,
177                                                         PARPORT_CONTROL_INIT);
178                 }
179                 break;
180         case PPCMODE_UNI_FW:
181         case PPCMODE_BI_FW:
182                 bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_FASTWR);
183
184                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
185                                                         PARPORT_CONTROL_STROBE);
186
187                 last = *buf;
188
189                 parport_write_data(pi->pardev->port, last);
190
191                 while (len) {
192                         this = *buf++;
193                         len--;
194
195                         if (this == last) {
196                                 parport_frob_control(pi->pardev->port, 0,
197                                                         PARPORT_CONTROL_INIT);
198                         } else {
199                                 parport_write_data(pi->pardev->port, this);
200                                 last = this;
201                         }
202                 }
203
204                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
205                                                         0);
206                 bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_FASTWR);
207                 break;
208         case PPCMODE_EPP_BYTE:
209                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, buf,
210                                                 len, PARPORT_EPP_FAST_8);
211                 bpck6_wait_for_fifo(pi);
212                 break;
213         case PPCMODE_EPP_WORD:
214                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, buf,
215                                                 len, PARPORT_EPP_FAST_16);
216                 bpck6_wait_for_fifo(pi);
217                 break;
218         case PPCMODE_EPP_DWORD:
219                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, buf,
220                                                 len, PARPORT_EPP_FAST_32);
221                 bpck6_wait_for_fifo(pi);
222                 break;
223         }
224
225         bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK);
226 }
227
228 static void bpck6_read_block(struct pi_adapter *pi, char *buf, int len)
229 {
230         bpck6_send_cmd(pi, REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE);
231         bpck6_wr_data_byte(pi, (u8)len);
232         bpck6_wr_data_byte(pi, (u8)(len >> 8));
233         bpck6_wr_data_byte(pi, 0);
234
235         bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK);
236         bpck6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_READ);
237
238         switch (mode_map[pi->mode]) {
239         case PPCMODE_UNI_SW:
240         case PPCMODE_UNI_FW:
241                 while (len) {
242                         u8 d;
243
244                         parport_frob_control(pi->pardev->port,
245                                         PARPORT_CONTROL_STROBE,
246                                         PARPORT_CONTROL_INIT); /* DATA STROBE */
247                         d = parport_read_status(pi->pardev->port);
248                         d = ((d & 0x80) >> 1) | ((d & 0x38) >> 3);
249                         parport_frob_control(pi->pardev->port,
250                                         PARPORT_CONTROL_STROBE,
251                                         PARPORT_CONTROL_STROBE);
252                         d |= parport_read_status(pi->pardev->port) & 0xB8;
253                         *buf++ = d;
254                         len--;
255                 }
256                 break;
257         case PPCMODE_BI_SW:
258         case PPCMODE_BI_FW:
259                 parport_data_reverse(pi->pardev->port);
260                 while (len) {
261                         parport_frob_control(pi->pardev->port,
262                                 PARPORT_CONTROL_STROBE,
263                                 PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT);
264                         *buf++ = parport_read_data(pi->pardev->port);
265                         len--;
266                 }
267                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
268                                         0);
269                 parport_data_forward(pi->pardev->port);
270                 break;
271         case PPCMODE_EPP_BYTE:
272                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
273                                                 PARPORT_EPP_FAST_8);
274                 break;
275         case PPCMODE_EPP_WORD:
276                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
277                                                 PARPORT_EPP_FAST_16);
278                 break;
279         case PPCMODE_EPP_DWORD:
280                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
281                                                 PARPORT_EPP_FAST_32);
282                 break;
283         }
284
285         bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK);
286 }
287
288 static int bpck6_open(struct pi_adapter *pi)
289 {
290         u8 i, j, k;
291
292         pi->saved_r0 = parport_read_data(pi->pardev->port);
293         pi->saved_r2 = parport_read_control(pi->pardev->port) & 0x5F;
294
295         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
296                                                 PARPORT_CONTROL_SELECT);
297         if (pi->saved_r0 == 'b')
298                 parport_write_data(pi->pardev->port, 'x');
299         parport_write_data(pi->pardev->port, 'b');
300         parport_write_data(pi->pardev->port, 'p');
301         parport_write_data(pi->pardev->port, pi->unit);
302         parport_write_data(pi->pardev->port, ~pi->unit);
303
304         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
305         parport_write_control(pi->pardev->port, PARPORT_CONTROL_INIT);
306
307         i = mode_map[pi->mode] & 0x0C;
308         if (i == 0)
309                 i = (mode_map[pi->mode] & 2) | 1;
310         parport_write_data(pi->pardev->port, i);
311
312         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
313                                                 PARPORT_CONTROL_SELECT);
314         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_AUTOFD,
315                                                 PARPORT_CONTROL_AUTOFD);
316
317         j = ((i & 0x08) << 4) | ((i & 0x07) << 3);
318         k = parport_read_status(pi->pardev->port) & 0xB8;
319         if (j != k)
320                 goto fail;
321
322         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_AUTOFD, 0);
323         k = (parport_read_status(pi->pardev->port) & 0xB8) ^ 0xB8;
324         if (j != k)
325                 goto fail;
326
327         if (i & 4) {
328                 /* EPP */
329                 parport_frob_control(pi->pardev->port,
330                         PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
331         } else {
332                 /* PPC/ECP */
333                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
334         }
335
336         pi->private = 0;
337
338         bpck6_send_cmd(pi, ACCESS_REG | ACCESS_WRITE | REG_RAMSIZE);
339         bpck6_wr_data_byte(pi, RAMSIZE_128K);
340
341         bpck6_send_cmd(pi, ACCESS_REG | ACCESS_READ | REG_VERSION);
342         if ((bpck6_rd_data_byte(pi) & 0x3F) == 0x0C)
343                 pi->private |= fifo_wait;
344
345         return 1;
346
347 fail:
348         parport_write_control(pi->pardev->port, pi->saved_r2);
349         parport_write_data(pi->pardev->port, pi->saved_r0);
350
351         return 0;
352 }
353
354 static void bpck6_deselect(struct pi_adapter *pi)
355 {
356         if (mode_map[pi->mode] & 4) {
357                 /* EPP */
358                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT,
359                                      PARPORT_CONTROL_INIT);
360         } else {
361                 /* PPC/ECP */
362                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
363                                      PARPORT_CONTROL_SELECT);
364         }
365
366         parport_write_data(pi->pardev->port, pi->saved_r0);
367         parport_write_control(pi->pardev->port,
368                         pi->saved_r2 | PARPORT_CONTROL_SELECT);
369         parport_write_control(pi->pardev->port, pi->saved_r2);
370 }
371
372 static void bpck6_wr_extout(struct pi_adapter *pi, u8 regdata)
373 {
374         bpck6_send_cmd(pi, REG_VERSION | ACCESS_REG | ACCESS_WRITE);
375         bpck6_wr_data_byte(pi, (u8)((regdata & 0x03) << 6));
376 }
377
378 static void bpck6_connect(struct pi_adapter *pi)
379 {
380         dev_dbg(&pi->dev, "connect\n");
381
382         bpck6_open(pi);
383         bpck6_wr_extout(pi, 0x3);
384 }
385
386 static void bpck6_disconnect(struct pi_adapter *pi)
387 {
388         dev_dbg(&pi->dev, "disconnect\n");
389         bpck6_wr_extout(pi, 0x0);
390         bpck6_deselect(pi);
391 }
392
393 /* check for 8-bit port */
394 static int bpck6_test_port(struct pi_adapter *pi)
395 {
396         dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n",
397                 pi->pardev->port->modes, pi->pardev->port->base);
398
399         /* look at the parport device to see what modes we can use */
400         if (pi->pardev->port->modes & PARPORT_MODE_EPP)
401                 return 5; /* Can do EPP */
402         if (pi->pardev->port->modes & PARPORT_MODE_TRISTATE)
403                 return 2;
404         return 1; /* Just flat SPP */
405 }
406
407 static int bpck6_probe_unit(struct pi_adapter *pi)
408 {
409         int out, saved_mode;
410
411         dev_dbg(&pi->dev, "PROBE UNIT %x on port:%x\n", pi->unit, pi->port);
412
413         saved_mode = pi->mode;
414         /*LOWER DOWN TO UNIDIRECTIONAL*/
415         pi->mode = 0;
416
417         out = bpck6_open(pi);
418
419         dev_dbg(&pi->dev, "ppc_open returned %2x\n", out);
420
421         if (out) {
422                 bpck6_deselect(pi);
423                 dev_dbg(&pi->dev, "leaving probe\n");
424                 pi->mode = saved_mode;
425                 return 1;
426         }
427
428         dev_dbg(&pi->dev, "Failed open\n");
429         pi->mode = saved_mode;
430
431         return 0;
432 }
433
434 static void bpck6_log_adapter(struct pi_adapter *pi)
435 {
436         char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
437
438         dev_info(&pi->dev,
439                  "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n",
440                  pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
441 }
442
443 static struct pi_protocol bpck6 = {
444         .owner          = THIS_MODULE,
445         .name           = "bpck6",
446         .max_mode       = 5,
447         .epp_first      = 2, /* 2-5 use epp (need 8 ports) */
448         .max_units      = 255,
449         .write_regr     = bpck6_write_regr,
450         .read_regr      = bpck6_read_regr,
451         .write_block    = bpck6_write_block,
452         .read_block     = bpck6_read_block,
453         .connect        = bpck6_connect,
454         .disconnect     = bpck6_disconnect,
455         .test_port      = bpck6_test_port,
456         .probe_unit     = bpck6_probe_unit,
457         .log_adapter    = bpck6_log_adapter,
458 };
459
460 MODULE_LICENSE("GPL");
461 MODULE_AUTHOR("Micro Solutions Inc.");
462 MODULE_DESCRIPTION("Micro Solutions BACKPACK parallel port IDE adapter "
463                    "(version 6 drives) protocol driver");
464 module_pata_parport_driver(bpck6);