xref: /openbmc/linux/arch/m68k/include/asm/sun3xflop.h (revision 34e5269b)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
249148020SSam Ravnborg /* sun3xflop.h: Sun3/80 specific parts of the floppy driver.
349148020SSam Ravnborg  *
449148020SSam Ravnborg  * Derived partially from asm-sparc/floppy.h, which is:
549148020SSam Ravnborg  *     Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
649148020SSam Ravnborg  *
749148020SSam Ravnborg  * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net)
849148020SSam Ravnborg  */
949148020SSam Ravnborg 
1049148020SSam Ravnborg #ifndef __ASM_SUN3X_FLOPPY_H
1149148020SSam Ravnborg #define __ASM_SUN3X_FLOPPY_H
1249148020SSam Ravnborg 
13ca5999fdSMike Rapoport #include <linux/pgtable.h>
1465fddcfcSMike Rapoport #include <asm/page.h>
1549148020SSam Ravnborg #include <asm/irq.h>
1649148020SSam Ravnborg #include <asm/sun3x.h>
1749148020SSam Ravnborg 
1849148020SSam Ravnborg /* default interrupt vector */
1949148020SSam Ravnborg #define SUN3X_FDC_IRQ 0x40
2049148020SSam Ravnborg 
2149148020SSam Ravnborg /* some constants */
2249148020SSam Ravnborg #define FCR_TC 0x1
2349148020SSam Ravnborg #define FCR_EJECT 0x2
2449148020SSam Ravnborg #define FCR_MTRON 0x4
2549148020SSam Ravnborg #define FCR_DSEL1 0x8
2649148020SSam Ravnborg #define FCR_DSEL0 0x10
2749148020SSam Ravnborg 
2849148020SSam Ravnborg /* We don't need no stinkin' I/O port allocation crap. */
2949148020SSam Ravnborg #undef release_region
3049148020SSam Ravnborg #undef request_region
3149148020SSam Ravnborg #define release_region(X, Y)	do { } while(0)
3249148020SSam Ravnborg #define request_region(X, Y, Z)	(1)
3349148020SSam Ravnborg 
3449148020SSam Ravnborg struct sun3xflop_private {
3549148020SSam Ravnborg 	volatile unsigned char *status_r;
3649148020SSam Ravnborg 	volatile unsigned char *data_r;
3749148020SSam Ravnborg 	volatile unsigned char *fcr_r;
3849148020SSam Ravnborg 	volatile unsigned char *fvr_r;
3949148020SSam Ravnborg 	unsigned char fcr;
4049148020SSam Ravnborg } sun3x_fdc;
4149148020SSam Ravnborg 
4249148020SSam Ravnborg /* Super paranoid... */
4349148020SSam Ravnborg #undef HAVE_DISABLE_HLT
4449148020SSam Ravnborg 
4549148020SSam Ravnborg /* Routines unique to each controller type on a Sun. */
sun3x_82072_fd_inb(int port)4649148020SSam Ravnborg static unsigned char sun3x_82072_fd_inb(int port)
4749148020SSam Ravnborg {
4849148020SSam Ravnborg 	static int once = 0;
4949148020SSam Ravnborg //	udelay(5);
5049148020SSam Ravnborg 	switch(port & 7) {
5149148020SSam Ravnborg 	default:
524eee1e72SGeert Uytterhoeven 		pr_crit("floppy: Asked to read unknown port %d\n", port);
5349148020SSam Ravnborg 		panic("floppy: Port bolixed.");
5449148020SSam Ravnborg 	case 4: /* FD_STATUS */
5549148020SSam Ravnborg 		return (*sun3x_fdc.status_r) & ~STATUS_DMA;
5649148020SSam Ravnborg 	case 5: /* FD_DATA */
5749148020SSam Ravnborg 		return (*sun3x_fdc.data_r);
5849148020SSam Ravnborg 	case 7: /* FD_DIR */
5949148020SSam Ravnborg 		/* ugly hack, I can't find a way to actually detect the disk */
6049148020SSam Ravnborg 		if(!once) {
6149148020SSam Ravnborg 			once = 1;
6249148020SSam Ravnborg 			return 0x80;
6349148020SSam Ravnborg 		}
6449148020SSam Ravnborg 		return 0;
6549148020SSam Ravnborg 	};
6649148020SSam Ravnborg 	panic("sun_82072_fd_inb: How did I get here?");
6749148020SSam Ravnborg }
6849148020SSam Ravnborg 
sun3x_82072_fd_outb(unsigned char value,int port)6949148020SSam Ravnborg static void sun3x_82072_fd_outb(unsigned char value, int port)
7049148020SSam Ravnborg {
7149148020SSam Ravnborg //	udelay(5);
7249148020SSam Ravnborg 	switch(port & 7) {
7349148020SSam Ravnborg 	default:
744eee1e72SGeert Uytterhoeven 		pr_crit("floppy: Asked to write to unknown port %d\n", port);
7549148020SSam Ravnborg 		panic("floppy: Port bolixed.");
7649148020SSam Ravnborg 	case 2: /* FD_DOR */
7749148020SSam Ravnborg 		/* Oh geese, 82072 on the Sun has no DOR register,
7849148020SSam Ravnborg 		 * so we make do with taunting the FCR.
7949148020SSam Ravnborg 		 *
8049148020SSam Ravnborg 		 * ASSUMPTIONS:  There will only ever be one floppy
8149148020SSam Ravnborg 		 *               drive attached to a Sun controller
8249148020SSam Ravnborg 		 *               and it will be at drive zero.
8349148020SSam Ravnborg 		 */
8449148020SSam Ravnborg 
8549148020SSam Ravnborg 	{
8649148020SSam Ravnborg 		unsigned char fcr = sun3x_fdc.fcr;
8749148020SSam Ravnborg 
8849148020SSam Ravnborg 		if(value & 0x10) {
8949148020SSam Ravnborg 			fcr |= (FCR_DSEL0 | FCR_MTRON);
9049148020SSam Ravnborg 		} else
9149148020SSam Ravnborg 			fcr &= ~(FCR_DSEL0 | FCR_MTRON);
9249148020SSam Ravnborg 
9349148020SSam Ravnborg 
9449148020SSam Ravnborg 		if(fcr != sun3x_fdc.fcr) {
9549148020SSam Ravnborg 			*(sun3x_fdc.fcr_r) = fcr;
9649148020SSam Ravnborg 			sun3x_fdc.fcr = fcr;
9749148020SSam Ravnborg 		}
9849148020SSam Ravnborg 	}
9949148020SSam Ravnborg 		break;
10049148020SSam Ravnborg 	case 5: /* FD_DATA */
10149148020SSam Ravnborg 		*(sun3x_fdc.data_r) = value;
10249148020SSam Ravnborg 		break;
10349148020SSam Ravnborg 	case 7: /* FD_DCR */
10449148020SSam Ravnborg 		*(sun3x_fdc.status_r) = value;
10549148020SSam Ravnborg 		break;
10649148020SSam Ravnborg 	case 4: /* FD_STATUS */
10749148020SSam Ravnborg 		*(sun3x_fdc.status_r) = value;
10849148020SSam Ravnborg 		break;
109*34e5269bSWan Jiabing 	}
11049148020SSam Ravnborg 	return;
11149148020SSam Ravnborg }
11249148020SSam Ravnborg 
11349148020SSam Ravnborg 
sun3xflop_hardint(int irq,void * dev_id)11449148020SSam Ravnborg asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id)
11549148020SSam Ravnborg {
11649148020SSam Ravnborg 	register unsigned char st;
11749148020SSam Ravnborg 
11849148020SSam Ravnborg #undef TRACE_FLPY_INT
11949148020SSam Ravnborg #define NO_FLOPPY_ASSEMBLER
12049148020SSam Ravnborg 
12149148020SSam Ravnborg #ifdef TRACE_FLPY_INT
12249148020SSam Ravnborg 	static int calls=0;
12349148020SSam Ravnborg 	static int bytes=0;
12449148020SSam Ravnborg 	static int dma_wait=0;
12549148020SSam Ravnborg #endif
12649148020SSam Ravnborg 	if(!doing_pdma) {
12749148020SSam Ravnborg 		floppy_interrupt(irq, dev_id);
12849148020SSam Ravnborg 		return IRQ_HANDLED;
12949148020SSam Ravnborg 	}
13049148020SSam Ravnborg 
1314eee1e72SGeert Uytterhoeven //	pr_info("doing pdma\n");// st %x\n", sun_fdc->status_82072);
13249148020SSam Ravnborg 
13349148020SSam Ravnborg #ifdef TRACE_FLPY_INT
13449148020SSam Ravnborg 	if(!calls)
13549148020SSam Ravnborg 		bytes = virtual_dma_count;
13649148020SSam Ravnborg #endif
13749148020SSam Ravnborg 
13849148020SSam Ravnborg 	{
13949148020SSam Ravnborg 		register int lcount;
14049148020SSam Ravnborg 		register char *lptr;
14149148020SSam Ravnborg 
14249148020SSam Ravnborg 		for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
14349148020SSam Ravnborg 		    lcount; lcount--, lptr++) {
14449148020SSam Ravnborg /*			st=fd_inb(virtual_dma_port+4) & 0x80 ;  */
14549148020SSam Ravnborg 			st = *(sun3x_fdc.status_r);
14649148020SSam Ravnborg /*			if(st != 0xa0)                  */
14749148020SSam Ravnborg /*				break;                  */
14849148020SSam Ravnborg 
14949148020SSam Ravnborg 			if((st & 0x80) == 0) {
15049148020SSam Ravnborg 				virtual_dma_count = lcount;
15149148020SSam Ravnborg 				virtual_dma_addr = lptr;
15249148020SSam Ravnborg 				return IRQ_HANDLED;
15349148020SSam Ravnborg 			}
15449148020SSam Ravnborg 
15549148020SSam Ravnborg 			if((st & 0x20) == 0)
15649148020SSam Ravnborg 				break;
15749148020SSam Ravnborg 
15849148020SSam Ravnborg 			if(virtual_dma_mode)
15949148020SSam Ravnborg /*				fd_outb(*lptr, virtual_dma_port+5); */
16049148020SSam Ravnborg 				*(sun3x_fdc.data_r) = *lptr;
16149148020SSam Ravnborg 			else
16249148020SSam Ravnborg /*				*lptr = fd_inb(virtual_dma_port+5); */
16349148020SSam Ravnborg 				*lptr = *(sun3x_fdc.data_r);
16449148020SSam Ravnborg 		}
16549148020SSam Ravnborg 
16649148020SSam Ravnborg 		virtual_dma_count = lcount;
16749148020SSam Ravnborg 		virtual_dma_addr = lptr;
16849148020SSam Ravnborg /*		st = fd_inb(virtual_dma_port+4);   */
16949148020SSam Ravnborg 		st = *(sun3x_fdc.status_r);
17049148020SSam Ravnborg 	}
17149148020SSam Ravnborg 
17249148020SSam Ravnborg #ifdef TRACE_FLPY_INT
17349148020SSam Ravnborg 	calls++;
17449148020SSam Ravnborg #endif
1754eee1e72SGeert Uytterhoeven //	pr_info("st=%02x\n", st);
17649148020SSam Ravnborg 	if(st == 0x20)
17749148020SSam Ravnborg 		return IRQ_HANDLED;
17849148020SSam Ravnborg 	if(!(st & 0x20)) {
17949148020SSam Ravnborg 		virtual_dma_residue += virtual_dma_count;
18049148020SSam Ravnborg 		virtual_dma_count=0;
18149148020SSam Ravnborg 		doing_pdma = 0;
18249148020SSam Ravnborg 
18349148020SSam Ravnborg #ifdef TRACE_FLPY_INT
1844eee1e72SGeert Uytterhoeven 		pr_info("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n",
18549148020SSam Ravnborg 			virtual_dma_count, virtual_dma_residue, calls, bytes,
18649148020SSam Ravnborg 			dma_wait);
18749148020SSam Ravnborg 		calls = 0;
18849148020SSam Ravnborg 		dma_wait=0;
18949148020SSam Ravnborg #endif
19049148020SSam Ravnborg 
19149148020SSam Ravnborg 		floppy_interrupt(irq, dev_id);
19249148020SSam Ravnborg 		return IRQ_HANDLED;
19349148020SSam Ravnborg 	}
19449148020SSam Ravnborg 
19549148020SSam Ravnborg 
19649148020SSam Ravnborg #ifdef TRACE_FLPY_INT
19749148020SSam Ravnborg 	if(!virtual_dma_count)
19849148020SSam Ravnborg 		dma_wait++;
19949148020SSam Ravnborg #endif
20049148020SSam Ravnborg 	return IRQ_HANDLED;
20149148020SSam Ravnborg }
20249148020SSam Ravnborg 
sun3xflop_request_irq(void)20349148020SSam Ravnborg static int sun3xflop_request_irq(void)
20449148020SSam Ravnborg {
20549148020SSam Ravnborg 	static int once = 0;
20649148020SSam Ravnborg 	int error;
20749148020SSam Ravnborg 
20849148020SSam Ravnborg 	if(!once) {
20949148020SSam Ravnborg 		once = 1;
21049148020SSam Ravnborg 		error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
21177a42796SMichael Opdenacker 				    0, "floppy", NULL);
21249148020SSam Ravnborg 		return ((error == 0) ? 0 : -1);
21349148020SSam Ravnborg 	} else return 0;
21449148020SSam Ravnborg }
21549148020SSam Ravnborg 
21649148020SSam Ravnborg static void __init floppy_set_flags(int *ints,int param, int param2);
21749148020SSam Ravnborg 
sun3xflop_init(void)21849148020SSam Ravnborg static int sun3xflop_init(void)
21949148020SSam Ravnborg {
22049148020SSam Ravnborg 	if(FLOPPY_IRQ < 0x40)
22149148020SSam Ravnborg 		FLOPPY_IRQ = SUN3X_FDC_IRQ;
22249148020SSam Ravnborg 
22349148020SSam Ravnborg 	sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC;
22449148020SSam Ravnborg 	sun3x_fdc.data_r  = (volatile unsigned char *)(SUN3X_FDC+1);
22549148020SSam Ravnborg 	sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR;
22649148020SSam Ravnborg 	sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR;
22749148020SSam Ravnborg 	sun3x_fdc.fcr = 0;
22849148020SSam Ravnborg 
22949148020SSam Ravnborg 	/* Last minute sanity check... */
23049148020SSam Ravnborg 	if(*sun3x_fdc.status_r == 0xff) {
23149148020SSam Ravnborg 		return -1;
23249148020SSam Ravnborg 	}
23349148020SSam Ravnborg 
23449148020SSam Ravnborg 	*sun3x_fdc.fvr_r = FLOPPY_IRQ;
23549148020SSam Ravnborg 
23649148020SSam Ravnborg 	*sun3x_fdc.fcr_r = FCR_TC;
23749148020SSam Ravnborg 	udelay(10);
23849148020SSam Ravnborg 	*sun3x_fdc.fcr_r = 0;
23949148020SSam Ravnborg 
24049148020SSam Ravnborg 	/* Success... */
24149148020SSam Ravnborg 	floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this.
24249148020SSam Ravnborg 	allowed_drive_mask = 0x01;
24349148020SSam Ravnborg 	return (int) SUN3X_FDC;
24449148020SSam Ravnborg }
24549148020SSam Ravnborg 
24649148020SSam Ravnborg /* I'm not precisely sure this eject routine works */
sun3x_eject(void)24749148020SSam Ravnborg static int sun3x_eject(void)
24849148020SSam Ravnborg {
24949148020SSam Ravnborg 	if(MACH_IS_SUN3X) {
25049148020SSam Ravnborg 
25149148020SSam Ravnborg 		sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT);
25249148020SSam Ravnborg 		*(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
25349148020SSam Ravnborg 		udelay(10);
25449148020SSam Ravnborg 		sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT);
25549148020SSam Ravnborg 		*(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
25649148020SSam Ravnborg 	}
25749148020SSam Ravnborg 
25849148020SSam Ravnborg 	return 0;
25949148020SSam Ravnborg }
26049148020SSam Ravnborg 
26149148020SSam Ravnborg #define fd_eject(drive) sun3x_eject()
26249148020SSam Ravnborg 
26349148020SSam Ravnborg #endif /* !(__ASM_SUN3X_FLOPPY_H) */
264