xref: /openbmc/linux/drivers/ata/pata_parport/kbic.c (revision 2c08ec0f)
172f2b0b2SOndrej Zary /*
272f2b0b2SOndrej Zary         kbic.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
372f2b0b2SOndrej Zary                               Under the terms of the GNU General Public License.
472f2b0b2SOndrej Zary 
572f2b0b2SOndrej Zary         This is a low-level driver for the KBIC-951A and KBIC-971A
672f2b0b2SOndrej Zary         parallel to IDE adapter chips from KingByte Information Systems.
772f2b0b2SOndrej Zary 
872f2b0b2SOndrej Zary 	The chips are almost identical, however, the wakeup code
972f2b0b2SOndrej Zary 	required for the 971A interferes with the correct operation of
1072f2b0b2SOndrej Zary         the 951A, so this driver registers itself twice, once for
1172f2b0b2SOndrej Zary 	each chip.
1272f2b0b2SOndrej Zary 
1372f2b0b2SOndrej Zary */
1472f2b0b2SOndrej Zary 
1572f2b0b2SOndrej Zary /* Changes:
1672f2b0b2SOndrej Zary 
1772f2b0b2SOndrej Zary         1.01    GRG 1998.05.06 init_proto, release_proto
1872f2b0b2SOndrej Zary 
1972f2b0b2SOndrej Zary */
2072f2b0b2SOndrej Zary 
2172f2b0b2SOndrej Zary #define KBIC_VERSION      "1.01"
2272f2b0b2SOndrej Zary 
2372f2b0b2SOndrej Zary #include <linux/module.h>
2472f2b0b2SOndrej Zary #include <linux/init.h>
2572f2b0b2SOndrej Zary #include <linux/delay.h>
2672f2b0b2SOndrej Zary #include <linux/kernel.h>
2772f2b0b2SOndrej Zary #include <linux/types.h>
2872f2b0b2SOndrej Zary #include <linux/wait.h>
2972f2b0b2SOndrej Zary #include <asm/io.h>
3072f2b0b2SOndrej Zary 
3172f2b0b2SOndrej Zary #include <linux/pata_parport.h>
3272f2b0b2SOndrej Zary 
3372f2b0b2SOndrej Zary #define r12w()			(delay_p,inw(pi->port+1)&0xffff)
3472f2b0b2SOndrej Zary 
3572f2b0b2SOndrej Zary #define j44(a,b)                ((((a>>4)&0x0f)|(b&0xf0))^0x88)
3672f2b0b2SOndrej Zary #define j53(w)                  (((w>>3)&0x1f)|((w>>4)&0xe0))
3772f2b0b2SOndrej Zary 
3872f2b0b2SOndrej Zary 
3972f2b0b2SOndrej Zary /* cont = 0 - access the IDE register file
4072f2b0b2SOndrej Zary    cont = 1 - access the IDE command set
4172f2b0b2SOndrej Zary */
4272f2b0b2SOndrej Zary 
4372f2b0b2SOndrej Zary static int  cont_map[2] = { 0x80, 0x40 };
4472f2b0b2SOndrej Zary 
4572f2b0b2SOndrej Zary static int kbic_read_regr( PIA *pi, int cont, int regr )
4672f2b0b2SOndrej Zary 
4772f2b0b2SOndrej Zary {       int     a, b, s;
4872f2b0b2SOndrej Zary 
4972f2b0b2SOndrej Zary         s = cont_map[cont];
5072f2b0b2SOndrej Zary 
5172f2b0b2SOndrej Zary 	switch (pi->mode) {
5272f2b0b2SOndrej Zary 
5372f2b0b2SOndrej Zary 	case 0: w0(regr|0x18|s); w2(4); w2(6); w2(4); w2(1); w0(8);
5472f2b0b2SOndrej Zary 	        a = r1(); w0(0x28); b = r1(); w2(4);
5572f2b0b2SOndrej Zary 		return j44(a,b);
5672f2b0b2SOndrej Zary 
5772f2b0b2SOndrej Zary 	case 1: w0(regr|0x38|s); w2(4); w2(6); w2(4); w2(5); w0(8);
5872f2b0b2SOndrej Zary 		a = r12w(); w2(4);
5972f2b0b2SOndrej Zary 		return j53(a);
6072f2b0b2SOndrej Zary 
6172f2b0b2SOndrej Zary 	case 2: w0(regr|0x08|s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
6272f2b0b2SOndrej Zary 		a = r0(); w2(4);
6372f2b0b2SOndrej Zary        		return a;
6472f2b0b2SOndrej Zary 
6572f2b0b2SOndrej Zary 	case 3:
6672f2b0b2SOndrej Zary 	case 4:
6772f2b0b2SOndrej Zary 	case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr);
6872f2b0b2SOndrej Zary 		a = r4(); b = r4(); w2(4); w2(0); w2(4);
6972f2b0b2SOndrej Zary 		return a;
7072f2b0b2SOndrej Zary 
7172f2b0b2SOndrej Zary 	}
7272f2b0b2SOndrej Zary 	return -1;
7372f2b0b2SOndrej Zary }
7472f2b0b2SOndrej Zary 
7572f2b0b2SOndrej Zary static void  kbic_write_regr( PIA *pi, int cont, int regr, int val)
7672f2b0b2SOndrej Zary 
7772f2b0b2SOndrej Zary {       int  s;
7872f2b0b2SOndrej Zary 
7972f2b0b2SOndrej Zary         s = cont_map[cont];
8072f2b0b2SOndrej Zary 
8172f2b0b2SOndrej Zary         switch (pi->mode) {
8272f2b0b2SOndrej Zary 
8372f2b0b2SOndrej Zary 	case 0:
8472f2b0b2SOndrej Zary         case 1:
8572f2b0b2SOndrej Zary 	case 2:	w0(regr|0x10|s); w2(4); w2(6); w2(4);
8672f2b0b2SOndrej Zary 		w0(val); w2(5); w2(4);
8772f2b0b2SOndrej Zary 		break;
8872f2b0b2SOndrej Zary 
8972f2b0b2SOndrej Zary 	case 3:
9072f2b0b2SOndrej Zary 	case 4:
9172f2b0b2SOndrej Zary 	case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr);
9272f2b0b2SOndrej Zary 		w4(val); w4(val);
9372f2b0b2SOndrej Zary 		w2(4); w2(0); w2(4);
9472f2b0b2SOndrej Zary                 break;
9572f2b0b2SOndrej Zary 
9672f2b0b2SOndrej Zary 	}
9772f2b0b2SOndrej Zary }
9872f2b0b2SOndrej Zary 
9972f2b0b2SOndrej Zary static void k951_connect ( PIA *pi  )
10072f2b0b2SOndrej Zary 
10172f2b0b2SOndrej Zary { 	pi->saved_r0 = r0();
10272f2b0b2SOndrej Zary         pi->saved_r2 = r2();
10372f2b0b2SOndrej Zary         w2(4);
10472f2b0b2SOndrej Zary }
10572f2b0b2SOndrej Zary 
10672f2b0b2SOndrej Zary static void k951_disconnect ( PIA *pi )
10772f2b0b2SOndrej Zary 
10872f2b0b2SOndrej Zary {      	w0(pi->saved_r0);
10972f2b0b2SOndrej Zary         w2(pi->saved_r2);
11072f2b0b2SOndrej Zary }
11172f2b0b2SOndrej Zary 
11272f2b0b2SOndrej Zary #define	CCP(x)	w2(0xc4);w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);\
11372f2b0b2SOndrej Zary 		w0(0x78);w0(x);w2(0xc5);w2(0xc4);w0(0xff);
11472f2b0b2SOndrej Zary 
11572f2b0b2SOndrej Zary static void k971_connect ( PIA *pi  )
11672f2b0b2SOndrej Zary 
11772f2b0b2SOndrej Zary { 	pi->saved_r0 = r0();
11872f2b0b2SOndrej Zary         pi->saved_r2 = r2();
11972f2b0b2SOndrej Zary 	CCP(0x20);
12072f2b0b2SOndrej Zary         w2(4);
12172f2b0b2SOndrej Zary }
12272f2b0b2SOndrej Zary 
12372f2b0b2SOndrej Zary static void k971_disconnect ( PIA *pi )
12472f2b0b2SOndrej Zary 
12572f2b0b2SOndrej Zary {       CCP(0x30);
12672f2b0b2SOndrej Zary 	w0(pi->saved_r0);
12772f2b0b2SOndrej Zary         w2(pi->saved_r2);
12872f2b0b2SOndrej Zary }
12972f2b0b2SOndrej Zary 
13072f2b0b2SOndrej Zary /* counts must be congruent to 0 MOD 4, but all known applications
13172f2b0b2SOndrej Zary    have this property.
13272f2b0b2SOndrej Zary */
13372f2b0b2SOndrej Zary 
13472f2b0b2SOndrej Zary static void kbic_read_block( PIA *pi, char * buf, int count )
13572f2b0b2SOndrej Zary 
13672f2b0b2SOndrej Zary {       int     k, a, b;
13772f2b0b2SOndrej Zary 
13872f2b0b2SOndrej Zary         switch (pi->mode) {
13972f2b0b2SOndrej Zary 
14072f2b0b2SOndrej Zary         case 0: w0(0x98); w2(4); w2(6); w2(4);
14172f2b0b2SOndrej Zary                 for (k=0;k<count/2;k++) {
14272f2b0b2SOndrej Zary 			w2(1); w0(8);    a = r1();
14372f2b0b2SOndrej Zary 			       w0(0x28); b = r1();
14472f2b0b2SOndrej Zary 			buf[2*k]   = j44(a,b);
14572f2b0b2SOndrej Zary 			w2(5);           b = r1();
14672f2b0b2SOndrej Zary 			       w0(8);    a = r1();
14772f2b0b2SOndrej Zary 			buf[2*k+1] = j44(a,b);
14872f2b0b2SOndrej Zary 			w2(4);
14972f2b0b2SOndrej Zary                 }
15072f2b0b2SOndrej Zary                 break;
15172f2b0b2SOndrej Zary 
15272f2b0b2SOndrej Zary         case 1: w0(0xb8); w2(4); w2(6); w2(4);
15372f2b0b2SOndrej Zary                 for (k=0;k<count/4;k++) {
15472f2b0b2SOndrej Zary                         w0(0xb8);
15572f2b0b2SOndrej Zary 			w2(4); w2(5);
15672f2b0b2SOndrej Zary                         w0(8);    buf[4*k]   = j53(r12w());
15772f2b0b2SOndrej Zary 			w0(0xb8); buf[4*k+1] = j53(r12w());
15872f2b0b2SOndrej Zary 			w2(4); w2(5);
15972f2b0b2SOndrej Zary 			          buf[4*k+3] = j53(r12w());
16072f2b0b2SOndrej Zary 			w0(8);    buf[4*k+2] = j53(r12w());
16172f2b0b2SOndrej Zary                 }
16272f2b0b2SOndrej Zary                 w2(4);
16372f2b0b2SOndrej Zary                 break;
16472f2b0b2SOndrej Zary 
16572f2b0b2SOndrej Zary         case 2: w0(0x88); w2(4); w2(6); w2(4);
16672f2b0b2SOndrej Zary                 for (k=0;k<count/2;k++) {
16772f2b0b2SOndrej Zary                         w2(0xa0); w2(0xa1); buf[2*k] = r0();
16872f2b0b2SOndrej Zary                         w2(0xa5); buf[2*k+1] = r0();
16972f2b0b2SOndrej Zary                 }
17072f2b0b2SOndrej Zary                 w2(4);
17172f2b0b2SOndrej Zary                 break;
17272f2b0b2SOndrej Zary 
17372f2b0b2SOndrej Zary         case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
17472f2b0b2SOndrej Zary                 for (k=0;k<count;k++) buf[k] = r4();
17572f2b0b2SOndrej Zary                 w2(4); w2(0); w2(4);
17672f2b0b2SOndrej Zary                 break;
17772f2b0b2SOndrej Zary 
17872f2b0b2SOndrej Zary 	case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
17972f2b0b2SOndrej Zary                 for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
18072f2b0b2SOndrej Zary                 w2(4); w2(0); w2(4);
18172f2b0b2SOndrej Zary                 break;
18272f2b0b2SOndrej Zary 
18372f2b0b2SOndrej Zary         case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
18472f2b0b2SOndrej Zary                 for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
18572f2b0b2SOndrej Zary                 w2(4); w2(0); w2(4);
18672f2b0b2SOndrej Zary                 break;
18772f2b0b2SOndrej Zary 
18872f2b0b2SOndrej Zary 
18972f2b0b2SOndrej Zary         }
19072f2b0b2SOndrej Zary }
19172f2b0b2SOndrej Zary 
19272f2b0b2SOndrej Zary static void kbic_write_block( PIA *pi, char * buf, int count )
19372f2b0b2SOndrej Zary 
19472f2b0b2SOndrej Zary {       int     k;
19572f2b0b2SOndrej Zary 
19672f2b0b2SOndrej Zary         switch (pi->mode) {
19772f2b0b2SOndrej Zary 
19872f2b0b2SOndrej Zary         case 0:
19972f2b0b2SOndrej Zary         case 1:
20072f2b0b2SOndrej Zary         case 2: w0(0x90); w2(4); w2(6); w2(4);
20172f2b0b2SOndrej Zary 		for(k=0;k<count/2;k++) {
20272f2b0b2SOndrej Zary 			w0(buf[2*k+1]); w2(0); w2(4);
20372f2b0b2SOndrej Zary 			w0(buf[2*k]);   w2(5); w2(4);
20472f2b0b2SOndrej Zary 		}
20572f2b0b2SOndrej Zary 		break;
20672f2b0b2SOndrej Zary 
20772f2b0b2SOndrej Zary         case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
20872f2b0b2SOndrej Zary 		for(k=0;k<count/2;k++) {
20972f2b0b2SOndrej Zary 			w4(buf[2*k+1]);
21072f2b0b2SOndrej Zary                         w4(buf[2*k]);
21172f2b0b2SOndrej Zary                 }
21272f2b0b2SOndrej Zary 		w2(4); w2(0); w2(4);
21372f2b0b2SOndrej Zary 		break;
21472f2b0b2SOndrej Zary 
21572f2b0b2SOndrej Zary 	case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
216e02c625dSOndrej Zary 		for (k = 0; k < count / 2; k++)
217e02c625dSOndrej Zary 			w4w(swab16(((u16 *)buf)[k]));
21872f2b0b2SOndrej Zary                 w2(4); w2(0); w2(4);
21972f2b0b2SOndrej Zary                 break;
22072f2b0b2SOndrej Zary 
22172f2b0b2SOndrej Zary         case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
222e02c625dSOndrej Zary 		for (k = 0; k < count / 4; k++)
223e02c625dSOndrej Zary 			w4l(swab16(((u16 *)buf)[2 * k]) |
224e02c625dSOndrej Zary 			    swab16(((u16 *)buf)[2 * k + 1]) << 16);
22572f2b0b2SOndrej Zary                 w2(4); w2(0); w2(4);
22672f2b0b2SOndrej Zary                 break;
22772f2b0b2SOndrej Zary 
22872f2b0b2SOndrej Zary         }
22972f2b0b2SOndrej Zary 
23072f2b0b2SOndrej Zary }
23172f2b0b2SOndrej Zary 
23272f2b0b2SOndrej Zary static void kbic_log_adapter( PIA *pi, char * scratch,
23372f2b0b2SOndrej Zary 			      int verbose, char * chip )
23472f2b0b2SOndrej Zary 
23572f2b0b2SOndrej Zary {       char    *mode_string[6] = {"4-bit","5/3","8-bit",
23672f2b0b2SOndrej Zary 				   "EPP-8","EPP_16","EPP-32"};
23772f2b0b2SOndrej Zary 
23872f2b0b2SOndrej Zary         printk("%s: kbic %s, KingByte %s at 0x%x, ",
23972f2b0b2SOndrej Zary                 pi->device,KBIC_VERSION,chip,pi->port);
24072f2b0b2SOndrej Zary         printk("mode %d (%s), delay %d\n",pi->mode,
24172f2b0b2SOndrej Zary 		mode_string[pi->mode],pi->delay);
24272f2b0b2SOndrej Zary 
24372f2b0b2SOndrej Zary }
24472f2b0b2SOndrej Zary 
24572f2b0b2SOndrej Zary static void k951_log_adapter( PIA *pi, char * scratch, int verbose )
24672f2b0b2SOndrej Zary 
24772f2b0b2SOndrej Zary {	kbic_log_adapter(pi,scratch,verbose,"KBIC-951A");
24872f2b0b2SOndrej Zary }
24972f2b0b2SOndrej Zary 
25072f2b0b2SOndrej Zary static void k971_log_adapter( PIA *pi, char * scratch, int verbose )
25172f2b0b2SOndrej Zary 
25272f2b0b2SOndrej Zary {       kbic_log_adapter(pi,scratch,verbose,"KBIC-971A");
25372f2b0b2SOndrej Zary }
25472f2b0b2SOndrej Zary 
25572f2b0b2SOndrej Zary static struct pi_protocol k951 = {
25672f2b0b2SOndrej Zary 	.owner		= THIS_MODULE,
25772f2b0b2SOndrej Zary 	.name		= "k951",
25872f2b0b2SOndrej Zary 	.max_mode	= 6,
25972f2b0b2SOndrej Zary 	.epp_first	= 3,
26072f2b0b2SOndrej Zary 	.default_delay	= 1,
26172f2b0b2SOndrej Zary 	.max_units	= 1,
26272f2b0b2SOndrej Zary 	.write_regr	= kbic_write_regr,
26372f2b0b2SOndrej Zary 	.read_regr	= kbic_read_regr,
26472f2b0b2SOndrej Zary 	.write_block	= kbic_write_block,
26572f2b0b2SOndrej Zary 	.read_block	= kbic_read_block,
26672f2b0b2SOndrej Zary 	.connect	= k951_connect,
26772f2b0b2SOndrej Zary 	.disconnect	= k951_disconnect,
26872f2b0b2SOndrej Zary 	.log_adapter	= k951_log_adapter,
26972f2b0b2SOndrej Zary };
27072f2b0b2SOndrej Zary 
27172f2b0b2SOndrej Zary static struct pi_protocol k971 = {
27272f2b0b2SOndrej Zary 	.owner		= THIS_MODULE,
27372f2b0b2SOndrej Zary 	.name		= "k971",
27472f2b0b2SOndrej Zary 	.max_mode	= 6,
27572f2b0b2SOndrej Zary 	.epp_first	= 3,
27672f2b0b2SOndrej Zary 	.default_delay	= 1,
27772f2b0b2SOndrej Zary 	.max_units	= 1,
27872f2b0b2SOndrej Zary 	.write_regr	= kbic_write_regr,
27972f2b0b2SOndrej Zary 	.read_regr	= kbic_read_regr,
28072f2b0b2SOndrej Zary 	.write_block	= kbic_write_block,
28172f2b0b2SOndrej Zary 	.read_block	= kbic_read_block,
28272f2b0b2SOndrej Zary 	.connect	= k971_connect,
28372f2b0b2SOndrej Zary 	.disconnect	= k971_disconnect,
28472f2b0b2SOndrej Zary 	.log_adapter	= k971_log_adapter,
28572f2b0b2SOndrej Zary };
28672f2b0b2SOndrej Zary 
28772f2b0b2SOndrej Zary static int __init kbic_init(void)
28872f2b0b2SOndrej Zary {
28972f2b0b2SOndrej Zary 	int rv;
29072f2b0b2SOndrej Zary 
291*2c08ec0fSOndrej Zary 	rv = pata_parport_register_driver(&k951);
29272f2b0b2SOndrej Zary 	if (rv < 0)
29372f2b0b2SOndrej Zary 		return rv;
294*2c08ec0fSOndrej Zary 	rv = pata_parport_register_driver(&k971);
29572f2b0b2SOndrej Zary 	if (rv < 0)
296*2c08ec0fSOndrej Zary 		pata_parport_unregister_driver(&k951);
29772f2b0b2SOndrej Zary 	return rv;
29872f2b0b2SOndrej Zary }
29972f2b0b2SOndrej Zary 
30072f2b0b2SOndrej Zary static void __exit kbic_exit(void)
30172f2b0b2SOndrej Zary {
302*2c08ec0fSOndrej Zary 	pata_parport_unregister_driver(&k951);
303*2c08ec0fSOndrej Zary 	pata_parport_unregister_driver(&k971);
30472f2b0b2SOndrej Zary }
30572f2b0b2SOndrej Zary 
30672f2b0b2SOndrej Zary MODULE_LICENSE("GPL");
30772f2b0b2SOndrej Zary module_init(kbic_init)
30872f2b0b2SOndrej Zary module_exit(kbic_exit)
309