| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | /* parport_sunbpp.c: Parallel-port routines for SBUS
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  *  | 
					
						
							|  |  |  |  * Author: Derrick J. Brashear <shadow@dementia.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * based on work by: | 
					
						
							|  |  |  |  *          Phil Blundell <philb@gnu.org> | 
					
						
							|  |  |  |  *          Tim Waugh <tim@cyberelk.demon.co.uk> | 
					
						
							|  |  |  |  *	    Jose Renau <renau@acm.org> | 
					
						
							|  |  |  |  *          David Campbell <campbell@tirian.che.curtin.edu.au> | 
					
						
							|  |  |  |  *          Grant Guenther <grant@torque.net> | 
					
						
							|  |  |  |  *          Eddie C. Dost <ecd@skynet.be> | 
					
						
							|  |  |  |  *          Stephen Williams (steve@icarus.com) | 
					
						
							|  |  |  |  *          Gus Baldauf (gbaldauf@ix.netcom.com) | 
					
						
							|  |  |  |  *          Peter Zaitcev | 
					
						
							|  |  |  |  *          Tom Dyas | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Updated to new SBUS device framework: David S. Miller <davem@davemloft.net> | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							|  |  |  | #include <linux/delay.h>
 | 
					
						
							|  |  |  | #include <linux/errno.h>
 | 
					
						
							|  |  |  | #include <linux/ioport.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/slab.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | #include <linux/of.h>
 | 
					
						
							|  |  |  | #include <linux/of_device.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <linux/parport.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/ptrace.h>
 | 
					
						
							|  |  |  | #include <linux/interrupt.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/io.h>
 | 
					
						
							|  |  |  | #include <asm/oplib.h>           /* OpenProm Library */
 | 
					
						
							|  |  |  | #include <asm/dma.h>             /* BPP uses LSI 64854 for DMA */
 | 
					
						
							|  |  |  | #include <asm/irq.h>
 | 
					
						
							|  |  |  | #include <asm/sunbpp.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef __SUNBPP_DEBUG
 | 
					
						
							|  |  |  | #ifdef __SUNBPP_DEBUG
 | 
					
						
							|  |  |  | #define dprintk(x) printk x
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define dprintk(x)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_disable_irq(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	u32 tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = sbus_readl(®s->p_csr); | 
					
						
							|  |  |  | 	tmp &= ~DMA_INT_ENAB; | 
					
						
							|  |  |  | 	sbus_writel(tmp, ®s->p_csr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_enable_irq(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	u32 tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = sbus_readl(®s->p_csr); | 
					
						
							|  |  |  | 	tmp |= DMA_INT_ENAB; | 
					
						
							|  |  |  | 	sbus_writel(tmp, ®s->p_csr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_write_data(struct parport *p, unsigned char d) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sbus_writeb(d, ®s->p_dr); | 
					
						
							|  |  |  | 	dprintk((KERN_DEBUG "wrote 0x%x\n", d)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned char parport_sunbpp_read_data(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sbus_readb(®s->p_dr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | static void control_pc_to_sunbpp(struct parport *p, unsigned char status) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	unsigned char value_tcr = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 	unsigned char value_or = sbus_readb(®s->p_or); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (status & PARPORT_CONTROL_STROBE)  | 
					
						
							|  |  |  | 		value_tcr |= P_TCR_DS; | 
					
						
							|  |  |  | 	if (status & PARPORT_CONTROL_AUTOFD)  | 
					
						
							|  |  |  | 		value_or |= P_OR_AFXN; | 
					
						
							|  |  |  | 	if (status & PARPORT_CONTROL_INIT)  | 
					
						
							|  |  |  | 		value_or |= P_OR_INIT; | 
					
						
							|  |  |  | 	if (status & PARPORT_CONTROL_SELECT)  | 
					
						
							|  |  |  | 		value_or |= P_OR_SLCT_IN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sbus_writeb(value_or, ®s->p_or); | 
					
						
							|  |  |  | 	sbus_writeb(value_tcr, ®s->p_tcr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned char status_sunbpp_to_pc(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	unsigned char bits = 0; | 
					
						
							|  |  |  | 	unsigned char value_tcr = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 	unsigned char value_ir = sbus_readb(®s->p_ir); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(value_ir & P_IR_ERR)) | 
					
						
							|  |  |  | 		bits |= PARPORT_STATUS_ERROR; | 
					
						
							|  |  |  | 	if (!(value_ir & P_IR_SLCT)) | 
					
						
							|  |  |  | 		bits |= PARPORT_STATUS_SELECT; | 
					
						
							|  |  |  | 	if (!(value_ir & P_IR_PE)) | 
					
						
							|  |  |  | 		bits |= PARPORT_STATUS_PAPEROUT; | 
					
						
							|  |  |  | 	if (value_tcr & P_TCR_ACK) | 
					
						
							|  |  |  | 		bits |= PARPORT_STATUS_ACK; | 
					
						
							|  |  |  | 	if (!(value_tcr & P_TCR_BUSY)) | 
					
						
							|  |  |  | 		bits |= PARPORT_STATUS_BUSY; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-23 23:33:17 -07:00
										 |  |  | 	dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", value_tcr, value_ir)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	dprintk((KERN_DEBUG "read status 0x%x\n", bits)); | 
					
						
							|  |  |  | 	return bits; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned char control_sunbpp_to_pc(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	unsigned char bits = 0; | 
					
						
							|  |  |  | 	unsigned char value_tcr = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 	unsigned char value_or = sbus_readb(®s->p_or); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(value_tcr & P_TCR_DS)) | 
					
						
							|  |  |  | 		bits |= PARPORT_CONTROL_STROBE; | 
					
						
							|  |  |  | 	if (!(value_or & P_OR_AFXN)) | 
					
						
							|  |  |  | 		bits |= PARPORT_CONTROL_AUTOFD; | 
					
						
							|  |  |  | 	if (!(value_or & P_OR_INIT)) | 
					
						
							|  |  |  | 		bits |= PARPORT_CONTROL_INIT; | 
					
						
							|  |  |  | 	if (value_or & P_OR_SLCT_IN) | 
					
						
							|  |  |  | 		bits |= PARPORT_CONTROL_SELECT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-23 23:33:17 -07:00
										 |  |  | 	dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", value_tcr, value_or)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	dprintk((KERN_DEBUG "read control 0x%x\n", bits)); | 
					
						
							|  |  |  | 	return bits; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned char parport_sunbpp_read_control(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return control_sunbpp_to_pc(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned char parport_sunbpp_frob_control(struct parport *p, | 
					
						
							|  |  |  | 						 unsigned char mask, | 
					
						
							|  |  |  | 						 unsigned char val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	unsigned char value_tcr = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 	unsigned char value_or = sbus_readb(®s->p_or); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-23 23:33:17 -07:00
										 |  |  | 	dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", | 
					
						
							|  |  |  | 		 value_tcr, value_or)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (mask & PARPORT_CONTROL_STROBE) { | 
					
						
							|  |  |  | 		if (val & PARPORT_CONTROL_STROBE) { | 
					
						
							|  |  |  | 			value_tcr &= ~P_TCR_DS; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			value_tcr |= P_TCR_DS; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mask & PARPORT_CONTROL_AUTOFD) { | 
					
						
							|  |  |  | 		if (val & PARPORT_CONTROL_AUTOFD) { | 
					
						
							|  |  |  | 			value_or &= ~P_OR_AFXN; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			value_or |= P_OR_AFXN; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mask & PARPORT_CONTROL_INIT) { | 
					
						
							|  |  |  | 		if (val & PARPORT_CONTROL_INIT) { | 
					
						
							|  |  |  | 			value_or &= ~P_OR_INIT; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			value_or |= P_OR_INIT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mask & PARPORT_CONTROL_SELECT) { | 
					
						
							|  |  |  | 		if (val & PARPORT_CONTROL_SELECT) { | 
					
						
							|  |  |  | 			value_or |= P_OR_SLCT_IN; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			value_or &= ~P_OR_SLCT_IN; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sbus_writeb(value_or, ®s->p_or); | 
					
						
							|  |  |  | 	sbus_writeb(value_tcr, ®s->p_tcr); | 
					
						
							| 
									
										
										
										
											2007-04-23 23:33:17 -07:00
										 |  |  | 	dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", | 
					
						
							|  |  |  | 		 value_tcr, value_or)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return parport_sunbpp_read_control(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_write_control(struct parport *p, unsigned char d) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const unsigned char wm = (PARPORT_CONTROL_STROBE | | 
					
						
							|  |  |  | 				  PARPORT_CONTROL_AUTOFD | | 
					
						
							|  |  |  | 				  PARPORT_CONTROL_INIT | | 
					
						
							|  |  |  | 				  PARPORT_CONTROL_SELECT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	parport_sunbpp_frob_control (p, wm, d & wm); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned char parport_sunbpp_read_status(struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return status_sunbpp_to_pc(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_data_forward (struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	unsigned char value_tcr = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dprintk((KERN_DEBUG "forward\n")); | 
					
						
							|  |  |  | 	value_tcr &= ~P_TCR_DIR; | 
					
						
							|  |  |  | 	sbus_writeb(value_tcr, ®s->p_tcr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_data_reverse (struct parport *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							|  |  |  | 	u8 val = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dprintk((KERN_DEBUG "reverse\n")); | 
					
						
							|  |  |  | 	val |= P_TCR_DIR; | 
					
						
							|  |  |  | 	sbus_writeb(val, ®s->p_tcr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	s->u.pc.ctr = 0xc; | 
					
						
							|  |  |  | 	s->u.pc.ecr = 0x0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	s->u.pc.ctr = parport_sunbpp_read_control(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	parport_sunbpp_write_control(p, s->u.pc.ctr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct parport_operations parport_sunbpp_ops =  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	.write_data	= parport_sunbpp_write_data, | 
					
						
							|  |  |  | 	.read_data	= parport_sunbpp_read_data, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.write_control	= parport_sunbpp_write_control, | 
					
						
							|  |  |  | 	.read_control	= parport_sunbpp_read_control, | 
					
						
							|  |  |  | 	.frob_control	= parport_sunbpp_frob_control, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.read_status	= parport_sunbpp_read_status, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.enable_irq	= parport_sunbpp_enable_irq, | 
					
						
							|  |  |  | 	.disable_irq	= parport_sunbpp_disable_irq, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.data_forward	= parport_sunbpp_data_forward, | 
					
						
							|  |  |  | 	.data_reverse	= parport_sunbpp_data_reverse, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.init_state	= parport_sunbpp_init_state, | 
					
						
							|  |  |  | 	.save_state	= parport_sunbpp_save_state, | 
					
						
							|  |  |  | 	.restore_state	= parport_sunbpp_restore_state, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.epp_write_data	= parport_ieee1284_epp_write_data, | 
					
						
							|  |  |  | 	.epp_read_data	= parport_ieee1284_epp_read_data, | 
					
						
							|  |  |  | 	.epp_write_addr	= parport_ieee1284_epp_write_addr, | 
					
						
							|  |  |  | 	.epp_read_addr	= parport_ieee1284_epp_read_addr, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.ecp_write_data	= parport_ieee1284_ecp_write_data, | 
					
						
							|  |  |  | 	.ecp_read_data	= parport_ieee1284_ecp_read_data, | 
					
						
							|  |  |  | 	.ecp_write_addr	= parport_ieee1284_ecp_write_addr, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.compat_write_data	= parport_ieee1284_write_compat, | 
					
						
							|  |  |  | 	.nibble_read_data	= parport_ieee1284_read_nibble, | 
					
						
							|  |  |  | 	.byte_read_data		= parport_ieee1284_read_byte, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.owner		= THIS_MODULE, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 09:25:50 -06:00
										 |  |  | static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct parport_operations *ops; | 
					
						
							|  |  |  | 	struct bpp_regs __iomem *regs; | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	int irq, dma, err = 0, size; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	unsigned char value_tcr; | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	void __iomem *base; | 
					
						
							|  |  |  | 	struct parport *p; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-18 11:09:58 -06:00
										 |  |  | 	irq = op->archdata.irqs[0]; | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	base = of_ioremap(&op->resource[0], 0, | 
					
						
							|  |  |  | 			  resource_size(&op->resource[0]), | 
					
						
							|  |  |  | 			  "sunbpp"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (!base) | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 		return -ENODEV; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	size = resource_size(&op->resource[0]); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	dma = PARPORT_DMA_NONE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |         if (!ops) | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 		goto out_unmap; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  |         memcpy (ops, &parport_sunbpp_ops, sizeof(struct parport_operations)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dprintk(("register_port\n")); | 
					
						
							|  |  |  | 	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 		goto out_free_ops; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	p->size = size; | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	p->dev = &op->dev; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-19 01:42:14 -04:00
										 |  |  | 	if ((err = request_irq(p->irq, parport_irq_handler, | 
					
						
							| 
									
										
										
										
											2006-07-01 19:29:38 -07:00
										 |  |  | 			       IRQF_SHARED, p->name, p)) != 0) { | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 		goto out_put_port; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	parport_sunbpp_enable_irq(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	regs = (struct bpp_regs __iomem *)p->base; | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	value_tcr = sbus_readb(®s->p_tcr); | 
					
						
							|  |  |  | 	value_tcr &= ~P_TCR_DIR; | 
					
						
							|  |  |  | 	sbus_writeb(value_tcr, ®s->p_tcr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	dev_set_drvdata(&op->dev, p); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	parport_announce_port(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | out_put_port: | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	parport_put_port(p); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | out_free_ops: | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	kfree(ops); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | out_unmap: | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	of_iounmap(&op->resource[0], base, size); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 09:25:50 -06:00
										 |  |  | static int __devexit bpp_remove(struct platform_device *op) | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	struct parport *p = dev_get_drvdata(&op->dev); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 	struct parport_operations *ops = p->ops; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	parport_remove_port(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p->irq != PARPORT_IRQ_NONE) { | 
					
						
							|  |  |  | 		parport_sunbpp_disable_irq(p); | 
					
						
							|  |  |  | 		free_irq(p->irq, p); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 	parport_put_port(p); | 
					
						
							|  |  |  | 	kfree(ops); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-27 00:17:50 -07:00
										 |  |  | 	dev_set_drvdata(&op->dev, NULL); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-31 01:23:17 -07:00
										 |  |  | static const struct of_device_id bpp_match[] = { | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		.name = "SUNW,bpp", | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-25 00:04:43 -07:00
										 |  |  | MODULE_DEVICE_TABLE(of, bpp_match); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct of_platform_driver bpp_sbus_driver = { | 
					
						
							| 
									
										
										
										
											2010-04-13 16:13:02 -07:00
										 |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name = "bpp", | 
					
						
							|  |  |  | 		.owner = THIS_MODULE, | 
					
						
							|  |  |  | 		.of_match_table = bpp_match, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | 	.probe		= bpp_probe, | 
					
						
							|  |  |  | 	.remove		= __devexit_p(bpp_remove), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init parport_sunbpp_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-24 15:14:37 -06:00
										 |  |  | 	return of_register_platform_driver(&bpp_sbus_driver); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __exit parport_sunbpp_exit(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-24 15:14:37 -06:00
										 |  |  | 	of_unregister_platform_driver(&bpp_sbus_driver); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_AUTHOR("Derrick J Brashear"); | 
					
						
							|  |  |  | MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); | 
					
						
							|  |  |  | MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); | 
					
						
							| 
									
										
										
										
											2006-06-23 22:22:13 -07:00
										 |  |  | MODULE_VERSION("2.0"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | MODULE_LICENSE("GPL"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module_init(parport_sunbpp_init) | 
					
						
							|  |  |  | module_exit(parport_sunbpp_exit) |