xref: /linux/drivers/parport/parport_ip32.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28e75f744SArnaud Giersch /* Low-level parallel port routines for built-in port on SGI IP32
38e75f744SArnaud Giersch  *
48e75f744SArnaud Giersch  * Author: Arnaud Giersch <arnaud.giersch@free.fr>
58e75f744SArnaud Giersch  *
68e75f744SArnaud Giersch  * Based on parport_pc.c by
78e75f744SArnaud Giersch  *	Phil Blundell, Tim Waugh, Jose Renau, David Campbell,
88e75f744SArnaud Giersch  *	Andrea Arcangeli, et al.
98e75f744SArnaud Giersch  *
108e75f744SArnaud Giersch  * Thanks to Ilya A. Volynets-Evenbakh for his help.
118e75f744SArnaud Giersch  *
128e75f744SArnaud Giersch  * Copyright (C) 2005, 2006 Arnaud Giersch.
138e75f744SArnaud Giersch  */
148e75f744SArnaud Giersch 
158e75f744SArnaud Giersch /* Current status:
168e75f744SArnaud Giersch  *
178e75f744SArnaud Giersch  *	Basic SPP and PS2 modes are supported.
188e75f744SArnaud Giersch  *	Support for parallel port IRQ is present.
198e75f744SArnaud Giersch  *	Hardware SPP (a.k.a. compatibility), EPP, and ECP modes are
208e75f744SArnaud Giersch  *	supported.
218e75f744SArnaud Giersch  *	SPP/ECP FIFO can be driven in PIO or DMA mode.  PIO mode can work with
228e75f744SArnaud Giersch  *	or without interrupt support.
238e75f744SArnaud Giersch  *
248e75f744SArnaud Giersch  *	Hardware ECP mode is not fully implemented (ecp_read_data and
258e75f744SArnaud Giersch  *	ecp_write_addr are actually missing).
268e75f744SArnaud Giersch  *
278e75f744SArnaud Giersch  * To do:
288e75f744SArnaud Giersch  *
298e75f744SArnaud Giersch  *	Fully implement ECP mode.
308e75f744SArnaud Giersch  *	EPP and ECP mode need to be tested.  I currently do not own any
318e75f744SArnaud Giersch  *	peripheral supporting these extended mode, and cannot test them.
328e75f744SArnaud Giersch  *	If DMA mode works well, decide if support for PIO FIFO modes should be
338e75f744SArnaud Giersch  *	dropped.
348e75f744SArnaud Giersch  *	Use the io{read,write} family functions when they become available in
358e75f744SArnaud Giersch  *	the linux-mips.org tree.  Note: the MIPS specific functions readsb()
368e75f744SArnaud Giersch  *	and writesb() are to be translated by ioread8_rep() and iowrite8_rep()
378e75f744SArnaud Giersch  *	respectively.
388e75f744SArnaud Giersch  */
398e75f744SArnaud Giersch 
408e75f744SArnaud Giersch /* The built-in parallel port on the SGI 02 workstation (a.k.a. IP32) is an
418e75f744SArnaud Giersch  * IEEE 1284 parallel port driven by a Texas Instrument TL16PIR552PH chip[1].
428e75f744SArnaud Giersch  * This chip supports SPP, bidirectional, EPP and ECP modes.  It has a 16 byte
438e75f744SArnaud Giersch  * FIFO buffer and supports DMA transfers.
448e75f744SArnaud Giersch  *
458e75f744SArnaud Giersch  * [1] http://focus.ti.com/docs/prod/folders/print/tl16pir552.html
468e75f744SArnaud Giersch  *
478e75f744SArnaud Giersch  * Theoretically, we could simply use the parport_pc module.  It is however
488e75f744SArnaud Giersch  * not so simple.  The parport_pc code assumes that the parallel port
498e75f744SArnaud Giersch  * registers are port-mapped.  On the O2, they are memory-mapped.
508e75f744SArnaud Giersch  * Furthermore, each register is replicated on 256 consecutive addresses (as
518e75f744SArnaud Giersch  * it is for the built-in serial ports on the same chip).
528e75f744SArnaud Giersch  */
538e75f744SArnaud Giersch 
548e75f744SArnaud Giersch /*--- Some configuration defines ---------------------------------------*/
558e75f744SArnaud Giersch 
568e75f744SArnaud Giersch /* DEBUG_PARPORT_IP32
578e75f744SArnaud Giersch  *	0	disable debug
588e75f744SArnaud Giersch  *	1	standard level: pr_debug1 is enabled
598e75f744SArnaud Giersch  *	2	parport_ip32_dump_state is enabled
608e75f744SArnaud Giersch  *	>=3	verbose level: pr_debug is enabled
618e75f744SArnaud Giersch  */
628e75f744SArnaud Giersch #if !defined(DEBUG_PARPORT_IP32)
638e75f744SArnaud Giersch #	define DEBUG_PARPORT_IP32  0	/* 0 (disabled) for production */
648e75f744SArnaud Giersch #endif
658e75f744SArnaud Giersch 
668e75f744SArnaud Giersch /*----------------------------------------------------------------------*/
678e75f744SArnaud Giersch 
688e75f744SArnaud Giersch /* Setup DEBUG macros.  This is done before any includes, just in case we
698e75f744SArnaud Giersch  * activate pr_debug() with DEBUG_PARPORT_IP32 >= 3.
708e75f744SArnaud Giersch  */
718e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 == 1
728e75f744SArnaud Giersch #	warning DEBUG_PARPORT_IP32 == 1
738e75f744SArnaud Giersch #elif DEBUG_PARPORT_IP32 == 2
748e75f744SArnaud Giersch #	warning DEBUG_PARPORT_IP32 == 2
758e75f744SArnaud Giersch #elif DEBUG_PARPORT_IP32 >= 3
768e75f744SArnaud Giersch #	warning DEBUG_PARPORT_IP32 >= 3
778e75f744SArnaud Giersch #	if !defined(DEBUG)
788e75f744SArnaud Giersch #		define DEBUG /* enable pr_debug() in kernel.h */
798e75f744SArnaud Giersch #	endif
808e75f744SArnaud Giersch #endif
818e75f744SArnaud Giersch 
828e75f744SArnaud Giersch #include <linux/completion.h>
838e75f744SArnaud Giersch #include <linux/delay.h>
848e75f744SArnaud Giersch #include <linux/dma-mapping.h>
858e75f744SArnaud Giersch #include <linux/err.h>
868e75f744SArnaud Giersch #include <linux/init.h>
878e75f744SArnaud Giersch #include <linux/interrupt.h>
888e75f744SArnaud Giersch #include <linux/jiffies.h>
898e75f744SArnaud Giersch #include <linux/kernel.h>
908e75f744SArnaud Giersch #include <linux/module.h>
918e75f744SArnaud Giersch #include <linux/parport.h>
92174cd4b1SIngo Molnar #include <linux/sched/signal.h>
935a0e3ad6STejun Heo #include <linux/slab.h>
948e75f744SArnaud Giersch #include <linux/spinlock.h>
958e75f744SArnaud Giersch #include <linux/stddef.h>
968e75f744SArnaud Giersch #include <linux/types.h>
978e75f744SArnaud Giersch #include <asm/io.h>
988e75f744SArnaud Giersch #include <asm/ip32/ip32_ints.h>
998e75f744SArnaud Giersch #include <asm/ip32/mace.h>
1008e75f744SArnaud Giersch 
1018e75f744SArnaud Giersch /*--- Global variables -------------------------------------------------*/
1028e75f744SArnaud Giersch 
1038e75f744SArnaud Giersch /* Verbose probing on by default for debugging. */
1048e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 1
1058e75f744SArnaud Giersch #	define DEFAULT_VERBOSE_PROBING	1
1068e75f744SArnaud Giersch #else
1078e75f744SArnaud Giersch #	define DEFAULT_VERBOSE_PROBING	0
1088e75f744SArnaud Giersch #endif
1098e75f744SArnaud Giersch 
1108e75f744SArnaud Giersch /* Default prefix for printk */
1118e75f744SArnaud Giersch #define PPIP32 "parport_ip32: "
1128e75f744SArnaud Giersch 
1138e75f744SArnaud Giersch /*
1148e75f744SArnaud Giersch  * These are the module parameters:
1158e75f744SArnaud Giersch  * @features:		bit mask of features to enable/disable
1168e75f744SArnaud Giersch  *			(all enabled by default)
1178e75f744SArnaud Giersch  * @verbose_probing:	log chit-chat during initialization
1188e75f744SArnaud Giersch  */
1198e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_IRQ	(1U << 0)
1208e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_DMA	(1U << 1)
1218e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_SPP	(1U << 2)
1228e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_EPP	(1U << 3)
1238e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_ECP	(1U << 4)
1248e75f744SArnaud Giersch static unsigned int features =	~0U;
12590ab5ee9SRusty Russell static bool verbose_probing =	DEFAULT_VERBOSE_PROBING;
1268e75f744SArnaud Giersch 
1278e75f744SArnaud Giersch /* We do not support more than one port. */
128df4c756eSCarlos Palminha static struct parport *this_port;
1298e75f744SArnaud Giersch 
1308e75f744SArnaud Giersch /* Timing constants for FIFO modes.  */
1318e75f744SArnaud Giersch #define FIFO_NFAULT_TIMEOUT	100	/* milliseconds */
1328e75f744SArnaud Giersch #define FIFO_POLLING_INTERVAL	50	/* microseconds */
1338e75f744SArnaud Giersch 
1348e75f744SArnaud Giersch /*--- I/O register definitions -----------------------------------------*/
1358e75f744SArnaud Giersch 
1368e75f744SArnaud Giersch /**
1378e75f744SArnaud Giersch  * struct parport_ip32_regs - virtual addresses of parallel port registers
1388e75f744SArnaud Giersch  * @data:	Data Register
1398e75f744SArnaud Giersch  * @dsr:	Device Status Register
1408e75f744SArnaud Giersch  * @dcr:	Device Control Register
1418e75f744SArnaud Giersch  * @eppAddr:	EPP Address Register
1428e75f744SArnaud Giersch  * @eppData0:	EPP Data Register 0
1438e75f744SArnaud Giersch  * @eppData1:	EPP Data Register 1
1448e75f744SArnaud Giersch  * @eppData2:	EPP Data Register 2
1458e75f744SArnaud Giersch  * @eppData3:	EPP Data Register 3
1468e75f744SArnaud Giersch  * @ecpAFifo:	ECP Address FIFO
1478e75f744SArnaud Giersch  * @fifo:	General FIFO register.  The same address is used for:
1488e75f744SArnaud Giersch  *		- cFifo, the Parallel Port DATA FIFO
1498e75f744SArnaud Giersch  *		- ecpDFifo, the ECP Data FIFO
1508e75f744SArnaud Giersch  *		- tFifo, the ECP Test FIFO
1518e75f744SArnaud Giersch  * @cnfgA:	Configuration Register A
1528e75f744SArnaud Giersch  * @cnfgB:	Configuration Register B
1538e75f744SArnaud Giersch  * @ecr:	Extended Control Register
1548e75f744SArnaud Giersch  */
1558e75f744SArnaud Giersch struct parport_ip32_regs {
1568e75f744SArnaud Giersch 	void __iomem *data;
1578e75f744SArnaud Giersch 	void __iomem *dsr;
1588e75f744SArnaud Giersch 	void __iomem *dcr;
1598e75f744SArnaud Giersch 	void __iomem *eppAddr;
1608e75f744SArnaud Giersch 	void __iomem *eppData0;
1618e75f744SArnaud Giersch 	void __iomem *eppData1;
1628e75f744SArnaud Giersch 	void __iomem *eppData2;
1638e75f744SArnaud Giersch 	void __iomem *eppData3;
1648e75f744SArnaud Giersch 	void __iomem *ecpAFifo;
1658e75f744SArnaud Giersch 	void __iomem *fifo;
1668e75f744SArnaud Giersch 	void __iomem *cnfgA;
1678e75f744SArnaud Giersch 	void __iomem *cnfgB;
1688e75f744SArnaud Giersch 	void __iomem *ecr;
1698e75f744SArnaud Giersch };
1708e75f744SArnaud Giersch 
1718e75f744SArnaud Giersch /* Device Status Register */
1728e75f744SArnaud Giersch #define DSR_nBUSY		(1U << 7)	/* PARPORT_STATUS_BUSY */
1738e75f744SArnaud Giersch #define DSR_nACK		(1U << 6)	/* PARPORT_STATUS_ACK */
1748e75f744SArnaud Giersch #define DSR_PERROR		(1U << 5)	/* PARPORT_STATUS_PAPEROUT */
1758e75f744SArnaud Giersch #define DSR_SELECT		(1U << 4)	/* PARPORT_STATUS_SELECT */
1768e75f744SArnaud Giersch #define DSR_nFAULT		(1U << 3)	/* PARPORT_STATUS_ERROR */
1778e75f744SArnaud Giersch #define DSR_nPRINT		(1U << 2)	/* specific to TL16PIR552 */
1788e75f744SArnaud Giersch /* #define DSR_reserved		(1U << 1) */
1798e75f744SArnaud Giersch #define DSR_TIMEOUT		(1U << 0)	/* EPP timeout */
1808e75f744SArnaud Giersch 
1818e75f744SArnaud Giersch /* Device Control Register */
1828e75f744SArnaud Giersch /* #define DCR_reserved		(1U << 7) | (1U <<  6) */
1838e75f744SArnaud Giersch #define DCR_DIR			(1U << 5)	/* direction */
1848e75f744SArnaud Giersch #define DCR_IRQ			(1U << 4)	/* interrupt on nAck */
1858e75f744SArnaud Giersch #define DCR_SELECT		(1U << 3)	/* PARPORT_CONTROL_SELECT */
1868e75f744SArnaud Giersch #define DCR_nINIT		(1U << 2)	/* PARPORT_CONTROL_INIT */
1878e75f744SArnaud Giersch #define DCR_AUTOFD		(1U << 1)	/* PARPORT_CONTROL_AUTOFD */
1888e75f744SArnaud Giersch #define DCR_STROBE		(1U << 0)	/* PARPORT_CONTROL_STROBE */
1898e75f744SArnaud Giersch 
1908e75f744SArnaud Giersch /* ECP Configuration Register A */
1918e75f744SArnaud Giersch #define CNFGA_IRQ		(1U << 7)
1928e75f744SArnaud Giersch #define CNFGA_ID_MASK		((1U << 6) | (1U << 5) | (1U << 4))
1938e75f744SArnaud Giersch #define CNFGA_ID_SHIFT		4
1948e75f744SArnaud Giersch #define CNFGA_ID_16		(00U << CNFGA_ID_SHIFT)
1958e75f744SArnaud Giersch #define CNFGA_ID_8		(01U << CNFGA_ID_SHIFT)
1968e75f744SArnaud Giersch #define CNFGA_ID_32		(02U << CNFGA_ID_SHIFT)
1978e75f744SArnaud Giersch /* #define CNFGA_reserved	(1U << 3) */
1988e75f744SArnaud Giersch #define CNFGA_nBYTEINTRANS	(1U << 2)
1998e75f744SArnaud Giersch #define CNFGA_PWORDLEFT		((1U << 1) | (1U << 0))
2008e75f744SArnaud Giersch 
2018e75f744SArnaud Giersch /* ECP Configuration Register B */
2028e75f744SArnaud Giersch #define CNFGB_COMPRESS		(1U << 7)
2038e75f744SArnaud Giersch #define CNFGB_INTRVAL		(1U << 6)
2048e75f744SArnaud Giersch #define CNFGB_IRQ_MASK		((1U << 5) | (1U << 4) | (1U << 3))
2058e75f744SArnaud Giersch #define CNFGB_IRQ_SHIFT		3
2068e75f744SArnaud Giersch #define CNFGB_DMA_MASK		((1U << 2) | (1U << 1) | (1U << 0))
2078e75f744SArnaud Giersch #define CNFGB_DMA_SHIFT		0
2088e75f744SArnaud Giersch 
2098e75f744SArnaud Giersch /* Extended Control Register */
2108e75f744SArnaud Giersch #define ECR_MODE_MASK		((1U << 7) | (1U << 6) | (1U << 5))
2118e75f744SArnaud Giersch #define ECR_MODE_SHIFT		5
2128e75f744SArnaud Giersch #define ECR_MODE_SPP		(00U << ECR_MODE_SHIFT)
2138e75f744SArnaud Giersch #define ECR_MODE_PS2		(01U << ECR_MODE_SHIFT)
2148e75f744SArnaud Giersch #define ECR_MODE_PPF		(02U << ECR_MODE_SHIFT)
2158e75f744SArnaud Giersch #define ECR_MODE_ECP		(03U << ECR_MODE_SHIFT)
2168e75f744SArnaud Giersch #define ECR_MODE_EPP		(04U << ECR_MODE_SHIFT)
2178e75f744SArnaud Giersch /* #define ECR_MODE_reserved	(05U << ECR_MODE_SHIFT) */
2188e75f744SArnaud Giersch #define ECR_MODE_TST		(06U << ECR_MODE_SHIFT)
2198e75f744SArnaud Giersch #define ECR_MODE_CFG		(07U << ECR_MODE_SHIFT)
2208e75f744SArnaud Giersch #define ECR_nERRINTR		(1U << 4)
2218e75f744SArnaud Giersch #define ECR_DMAEN		(1U << 3)
2228e75f744SArnaud Giersch #define ECR_SERVINTR		(1U << 2)
2238e75f744SArnaud Giersch #define ECR_F_FULL		(1U << 1)
2248e75f744SArnaud Giersch #define ECR_F_EMPTY		(1U << 0)
2258e75f744SArnaud Giersch 
2268e75f744SArnaud Giersch /*--- Private data -----------------------------------------------------*/
2278e75f744SArnaud Giersch 
2288e75f744SArnaud Giersch /**
2298e75f744SArnaud Giersch  * enum parport_ip32_irq_mode - operation mode of interrupt handler
2308e75f744SArnaud Giersch  * @PARPORT_IP32_IRQ_FWD:	forward interrupt to the upper parport layer
2318e75f744SArnaud Giersch  * @PARPORT_IP32_IRQ_HERE:	interrupt is handled locally
2328e75f744SArnaud Giersch  */
2338e75f744SArnaud Giersch enum parport_ip32_irq_mode { PARPORT_IP32_IRQ_FWD, PARPORT_IP32_IRQ_HERE };
2348e75f744SArnaud Giersch 
2358e75f744SArnaud Giersch /**
2368e75f744SArnaud Giersch  * struct parport_ip32_private - private stuff for &struct parport
2378e75f744SArnaud Giersch  * @regs:		register addresses
2388e75f744SArnaud Giersch  * @dcr_cache:		cached contents of DCR
2398e75f744SArnaud Giersch  * @dcr_writable:	bit mask of writable DCR bits
2408e75f744SArnaud Giersch  * @pword:		number of bytes per PWord
2418e75f744SArnaud Giersch  * @fifo_depth:		number of PWords that FIFO will hold
2428e75f744SArnaud Giersch  * @readIntrThreshold:	minimum number of PWords we can read
2438e75f744SArnaud Giersch  *			if we get an interrupt
2448e75f744SArnaud Giersch  * @writeIntrThreshold:	minimum number of PWords we can write
2458e75f744SArnaud Giersch  *			if we get an interrupt
2468e75f744SArnaud Giersch  * @irq_mode:		operation mode of interrupt handler for this port
2478e75f744SArnaud Giersch  * @irq_complete:	mutex used to wait for an interrupt to occur
2488e75f744SArnaud Giersch  */
2498e75f744SArnaud Giersch struct parport_ip32_private {
2508e75f744SArnaud Giersch 	struct parport_ip32_regs	regs;
2518e75f744SArnaud Giersch 	unsigned int			dcr_cache;
2528e75f744SArnaud Giersch 	unsigned int			dcr_writable;
2538e75f744SArnaud Giersch 	unsigned int			pword;
2548e75f744SArnaud Giersch 	unsigned int			fifo_depth;
2558e75f744SArnaud Giersch 	unsigned int			readIntrThreshold;
2568e75f744SArnaud Giersch 	unsigned int			writeIntrThreshold;
2578e75f744SArnaud Giersch 	enum parport_ip32_irq_mode	irq_mode;
2588e75f744SArnaud Giersch 	struct completion		irq_complete;
2598e75f744SArnaud Giersch };
2608e75f744SArnaud Giersch 
2618e75f744SArnaud Giersch /*--- Debug code -------------------------------------------------------*/
2628e75f744SArnaud Giersch 
2638e75f744SArnaud Giersch /*
2648e75f744SArnaud Giersch  * pr_debug1 - print debug messages
2658e75f744SArnaud Giersch  *
2668e75f744SArnaud Giersch  * This is like pr_debug(), but is defined for %DEBUG_PARPORT_IP32 >= 1
2678e75f744SArnaud Giersch  */
2688e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 1
2698e75f744SArnaud Giersch #	define pr_debug1(...)	printk(KERN_DEBUG __VA_ARGS__)
2708e75f744SArnaud Giersch #else /* DEBUG_PARPORT_IP32 < 1 */
2718e75f744SArnaud Giersch #	define pr_debug1(...)	do { } while (0)
2728e75f744SArnaud Giersch #endif
2738e75f744SArnaud Giersch 
2748e75f744SArnaud Giersch /*
2758e75f744SArnaud Giersch  * pr_trace, pr_trace1 - trace function calls
2768e75f744SArnaud Giersch  * @p:		pointer to &struct parport
2778e75f744SArnaud Giersch  * @fmt:	printk format string
2788e75f744SArnaud Giersch  * @...:	parameters for format string
2798e75f744SArnaud Giersch  *
2808e75f744SArnaud Giersch  * Macros used to trace function calls.  The given string is formatted after
2818e75f744SArnaud Giersch  * function name.  pr_trace() uses pr_debug(), and pr_trace1() uses
2828e75f744SArnaud Giersch  * pr_debug1().  __pr_trace() is the low-level macro and is not to be used
2838e75f744SArnaud Giersch  * directly.
2848e75f744SArnaud Giersch  */
2858e75f744SArnaud Giersch #define __pr_trace(pr, p, fmt, ...)					\
2868e75f744SArnaud Giersch 	pr("%s: %s" fmt "\n",						\
2878e75f744SArnaud Giersch 	   ({ const struct parport *__p = (p);				\
2888e75f744SArnaud Giersch 		   __p ? __p->name : "parport_ip32"; }),		\
2898e75f744SArnaud Giersch 	   __func__ , ##__VA_ARGS__)
2908e75f744SArnaud Giersch #define pr_trace(p, fmt, ...)	__pr_trace(pr_debug, p, fmt , ##__VA_ARGS__)
2918e75f744SArnaud Giersch #define pr_trace1(p, fmt, ...)	__pr_trace(pr_debug1, p, fmt , ##__VA_ARGS__)
2928e75f744SArnaud Giersch 
2938e75f744SArnaud Giersch /*
2948e75f744SArnaud Giersch  * __pr_probe, pr_probe - print message if @verbose_probing is true
2958e75f744SArnaud Giersch  * @p:		pointer to &struct parport
2968e75f744SArnaud Giersch  * @fmt:	printk format string
2978e75f744SArnaud Giersch  * @...:	parameters for format string
2988e75f744SArnaud Giersch  *
2998e75f744SArnaud Giersch  * For new lines, use pr_probe().  Use __pr_probe() for continued lines.
3008e75f744SArnaud Giersch  */
3018e75f744SArnaud Giersch #define __pr_probe(...)							\
3028e75f744SArnaud Giersch 	do { if (verbose_probing) printk(__VA_ARGS__); } while (0)
3038e75f744SArnaud Giersch #define pr_probe(p, fmt, ...)						\
3048e75f744SArnaud Giersch 	__pr_probe(KERN_INFO PPIP32 "0x%lx: " fmt, (p)->base , ##__VA_ARGS__)
3058e75f744SArnaud Giersch 
3068e75f744SArnaud Giersch /*
3078e75f744SArnaud Giersch  * parport_ip32_dump_state - print register status of parport
3088e75f744SArnaud Giersch  * @p:		pointer to &struct parport
3098e75f744SArnaud Giersch  * @str:	string to add in message
3108e75f744SArnaud Giersch  * @show_ecp_config:	shall we dump ECP configuration registers too?
3118e75f744SArnaud Giersch  *
3128e75f744SArnaud Giersch  * This function is only here for debugging purpose, and should be used with
3138e75f744SArnaud Giersch  * care.  Reading the parallel port registers may have undesired side effects.
3148e75f744SArnaud Giersch  * Especially if @show_ecp_config is true, the parallel port is resetted.
3158e75f744SArnaud Giersch  * This function is only defined if %DEBUG_PARPORT_IP32 >= 2.
3168e75f744SArnaud Giersch  */
3178e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 2
parport_ip32_dump_state(struct parport * p,char * str,unsigned int show_ecp_config)3188e75f744SArnaud Giersch static void parport_ip32_dump_state(struct parport *p, char *str,
3198e75f744SArnaud Giersch 				    unsigned int show_ecp_config)
3208e75f744SArnaud Giersch {
3218e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
3228e75f744SArnaud Giersch 	unsigned int i;
3238e75f744SArnaud Giersch 
3248e75f744SArnaud Giersch 	printk(KERN_DEBUG PPIP32 "%s: state (%s):\n", p->name, str);
3258e75f744SArnaud Giersch 	{
3268e75f744SArnaud Giersch 		static const char ecr_modes[8][4] = {"SPP", "PS2", "PPF",
3278e75f744SArnaud Giersch 						     "ECP", "EPP", "???",
3288e75f744SArnaud Giersch 						     "TST", "CFG"};
3298e75f744SArnaud Giersch 		unsigned int ecr = readb(priv->regs.ecr);
3308e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "    ecr=0x%02x", ecr);
331*aa3d6e7cSJoe Perches 		pr_cont(" %s",
3328e75f744SArnaud Giersch 			ecr_modes[(ecr & ECR_MODE_MASK) >> ECR_MODE_SHIFT]);
3338e75f744SArnaud Giersch 		if (ecr & ECR_nERRINTR)
334*aa3d6e7cSJoe Perches 			pr_cont(",nErrIntrEn");
3358e75f744SArnaud Giersch 		if (ecr & ECR_DMAEN)
336*aa3d6e7cSJoe Perches 			pr_cont(",dmaEn");
3378e75f744SArnaud Giersch 		if (ecr & ECR_SERVINTR)
338*aa3d6e7cSJoe Perches 			pr_cont(",serviceIntr");
3398e75f744SArnaud Giersch 		if (ecr & ECR_F_FULL)
340*aa3d6e7cSJoe Perches 			pr_cont(",f_full");
3418e75f744SArnaud Giersch 		if (ecr & ECR_F_EMPTY)
342*aa3d6e7cSJoe Perches 			pr_cont(",f_empty");
343*aa3d6e7cSJoe Perches 		pr_cont("\n");
3448e75f744SArnaud Giersch 	}
3458e75f744SArnaud Giersch 	if (show_ecp_config) {
3468e75f744SArnaud Giersch 		unsigned int oecr, cnfgA, cnfgB;
3478e75f744SArnaud Giersch 		oecr = readb(priv->regs.ecr);
3488e75f744SArnaud Giersch 		writeb(ECR_MODE_PS2, priv->regs.ecr);
3498e75f744SArnaud Giersch 		writeb(ECR_MODE_CFG, priv->regs.ecr);
3508e75f744SArnaud Giersch 		cnfgA = readb(priv->regs.cnfgA);
3518e75f744SArnaud Giersch 		cnfgB = readb(priv->regs.cnfgB);
3528e75f744SArnaud Giersch 		writeb(ECR_MODE_PS2, priv->regs.ecr);
3538e75f744SArnaud Giersch 		writeb(oecr, priv->regs.ecr);
3548e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "    cnfgA=0x%02x", cnfgA);
355*aa3d6e7cSJoe Perches 		pr_cont(" ISA-%s", (cnfgA & CNFGA_IRQ) ? "Level" : "Pulses");
3568e75f744SArnaud Giersch 		switch (cnfgA & CNFGA_ID_MASK) {
3578e75f744SArnaud Giersch 		case CNFGA_ID_8:
358*aa3d6e7cSJoe Perches 			pr_cont(",8 bits");
3598e75f744SArnaud Giersch 			break;
3608e75f744SArnaud Giersch 		case CNFGA_ID_16:
361*aa3d6e7cSJoe Perches 			pr_cont(",16 bits");
3628e75f744SArnaud Giersch 			break;
3638e75f744SArnaud Giersch 		case CNFGA_ID_32:
364*aa3d6e7cSJoe Perches 			pr_cont(",32 bits");
3658e75f744SArnaud Giersch 			break;
3668e75f744SArnaud Giersch 		default:
367*aa3d6e7cSJoe Perches 			pr_cont(",unknown ID");
3688e75f744SArnaud Giersch 			break;
3698e75f744SArnaud Giersch 		}
3708e75f744SArnaud Giersch 		if (!(cnfgA & CNFGA_nBYTEINTRANS))
371*aa3d6e7cSJoe Perches 			pr_cont(",ByteInTrans");
3728e75f744SArnaud Giersch 		if ((cnfgA & CNFGA_ID_MASK) != CNFGA_ID_8)
373*aa3d6e7cSJoe Perches 			pr_cont(",%d byte%s left",
374*aa3d6e7cSJoe Perches 				cnfgA & CNFGA_PWORDLEFT,
3758e75f744SArnaud Giersch 				((cnfgA & CNFGA_PWORDLEFT) > 1) ? "s" : "");
376*aa3d6e7cSJoe Perches 		pr_cont("\n");
3778e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "    cnfgB=0x%02x", cnfgB);
378*aa3d6e7cSJoe Perches 		pr_cont(" irq=%u,dma=%u",
3798e75f744SArnaud Giersch 			(cnfgB & CNFGB_IRQ_MASK) >> CNFGB_IRQ_SHIFT,
3808e75f744SArnaud Giersch 			(cnfgB & CNFGB_DMA_MASK) >> CNFGB_DMA_SHIFT);
381*aa3d6e7cSJoe Perches 		pr_cont(",intrValue=%d", !!(cnfgB & CNFGB_INTRVAL));
3828e75f744SArnaud Giersch 		if (cnfgB & CNFGB_COMPRESS)
383*aa3d6e7cSJoe Perches 			pr_cont(",compress");
384*aa3d6e7cSJoe Perches 		pr_cont("\n");
3858e75f744SArnaud Giersch 	}
3868e75f744SArnaud Giersch 	for (i = 0; i < 2; i++) {
3878e75f744SArnaud Giersch 		unsigned int dcr = i ? priv->dcr_cache : readb(priv->regs.dcr);
3888e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "    dcr(%s)=0x%02x",
3898e75f744SArnaud Giersch 		       i ? "soft" : "hard", dcr);
390*aa3d6e7cSJoe Perches 		pr_cont(" %s", (dcr & DCR_DIR) ? "rev" : "fwd");
3918e75f744SArnaud Giersch 		if (dcr & DCR_IRQ)
392*aa3d6e7cSJoe Perches 			pr_cont(",ackIntEn");
3938e75f744SArnaud Giersch 		if (!(dcr & DCR_SELECT))
394*aa3d6e7cSJoe Perches 			pr_cont(",nSelectIn");
3958e75f744SArnaud Giersch 		if (dcr & DCR_nINIT)
396*aa3d6e7cSJoe Perches 			pr_cont(",nInit");
3978e75f744SArnaud Giersch 		if (!(dcr & DCR_AUTOFD))
398*aa3d6e7cSJoe Perches 			pr_cont(",nAutoFD");
3998e75f744SArnaud Giersch 		if (!(dcr & DCR_STROBE))
400*aa3d6e7cSJoe Perches 			pr_cont(",nStrobe");
401*aa3d6e7cSJoe Perches 		pr_cont("\n");
4028e75f744SArnaud Giersch 	}
4038e75f744SArnaud Giersch #define sep (f++ ? ',' : ' ')
4048e75f744SArnaud Giersch 	{
4058e75f744SArnaud Giersch 		unsigned int f = 0;
4068e75f744SArnaud Giersch 		unsigned int dsr = readb(priv->regs.dsr);
4078e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "    dsr=0x%02x", dsr);
4088e75f744SArnaud Giersch 		if (!(dsr & DSR_nBUSY))
409*aa3d6e7cSJoe Perches 			pr_cont("%cBusy", sep);
4108e75f744SArnaud Giersch 		if (dsr & DSR_nACK)
411*aa3d6e7cSJoe Perches 			pr_cont("%cnAck", sep);
4128e75f744SArnaud Giersch 		if (dsr & DSR_PERROR)
413*aa3d6e7cSJoe Perches 			pr_cont("%cPError", sep);
4148e75f744SArnaud Giersch 		if (dsr & DSR_SELECT)
415*aa3d6e7cSJoe Perches 			pr_cont("%cSelect", sep);
4168e75f744SArnaud Giersch 		if (dsr & DSR_nFAULT)
417*aa3d6e7cSJoe Perches 			pr_cont("%cnFault", sep);
4188e75f744SArnaud Giersch 		if (!(dsr & DSR_nPRINT))
419*aa3d6e7cSJoe Perches 			pr_cont("%c(Print)", sep);
4208e75f744SArnaud Giersch 		if (dsr & DSR_TIMEOUT)
421*aa3d6e7cSJoe Perches 			pr_cont("%cTimeout", sep);
422*aa3d6e7cSJoe Perches 		pr_cont("\n");
4238e75f744SArnaud Giersch 	}
4248e75f744SArnaud Giersch #undef sep
4258e75f744SArnaud Giersch }
4268e75f744SArnaud Giersch #else /* DEBUG_PARPORT_IP32 < 2 */
4278e75f744SArnaud Giersch #define parport_ip32_dump_state(...)	do { } while (0)
4288e75f744SArnaud Giersch #endif
4298e75f744SArnaud Giersch 
4308e75f744SArnaud Giersch /*
4318e75f744SArnaud Giersch  * CHECK_EXTRA_BITS - track and log extra bits
4328e75f744SArnaud Giersch  * @p:		pointer to &struct parport
4338e75f744SArnaud Giersch  * @b:		byte to inspect
4348e75f744SArnaud Giersch  * @m:		bit mask of authorized bits
4358e75f744SArnaud Giersch  *
4368e75f744SArnaud Giersch  * This is used to track and log extra bits that should not be there in
4378e75f744SArnaud Giersch  * parport_ip32_write_control() and parport_ip32_frob_control().  It is only
4388e75f744SArnaud Giersch  * defined if %DEBUG_PARPORT_IP32 >= 1.
4398e75f744SArnaud Giersch  */
4408e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 1
4418e75f744SArnaud Giersch #define CHECK_EXTRA_BITS(p, b, m)					\
4428e75f744SArnaud Giersch 	do {								\
4438e75f744SArnaud Giersch 		unsigned int __b = (b), __m = (m);			\
4448e75f744SArnaud Giersch 		if (__b & ~__m)						\
4458e75f744SArnaud Giersch 			pr_debug1(PPIP32 "%s: extra bits in %s(%s): "	\
4468e75f744SArnaud Giersch 				  "0x%02x/0x%02x\n",			\
4478e75f744SArnaud Giersch 				  (p)->name, __func__, #b, __b, __m);	\
4488e75f744SArnaud Giersch 	} while (0)
4498e75f744SArnaud Giersch #else /* DEBUG_PARPORT_IP32 < 1 */
4508e75f744SArnaud Giersch #define CHECK_EXTRA_BITS(...)	do { } while (0)
4518e75f744SArnaud Giersch #endif
4528e75f744SArnaud Giersch 
4538e75f744SArnaud Giersch /*--- IP32 parallel port DMA operations --------------------------------*/
4548e75f744SArnaud Giersch 
4558e75f744SArnaud Giersch /**
4568e75f744SArnaud Giersch  * struct parport_ip32_dma_data - private data needed for DMA operation
4578e75f744SArnaud Giersch  * @dir:	DMA direction (from or to device)
4588e75f744SArnaud Giersch  * @buf:	buffer physical address
4598e75f744SArnaud Giersch  * @len:	buffer length
4608e75f744SArnaud Giersch  * @next:	address of next bytes to DMA transfer
4618e75f744SArnaud Giersch  * @left:	number of bytes remaining
4628e75f744SArnaud Giersch  * @ctx:	next context to write (0: context_a; 1: context_b)
4638e75f744SArnaud Giersch  * @irq_on:	are the DMA IRQs currently enabled?
4648e75f744SArnaud Giersch  * @lock:	spinlock to protect access to the structure
4658e75f744SArnaud Giersch  */
4668e75f744SArnaud Giersch struct parport_ip32_dma_data {
4678e75f744SArnaud Giersch 	enum dma_data_direction		dir;
4688e75f744SArnaud Giersch 	dma_addr_t			buf;
4698e75f744SArnaud Giersch 	dma_addr_t			next;
4708e75f744SArnaud Giersch 	size_t				len;
4718e75f744SArnaud Giersch 	size_t				left;
4728e75f744SArnaud Giersch 	unsigned int			ctx;
4738e75f744SArnaud Giersch 	unsigned int			irq_on;
4748e75f744SArnaud Giersch 	spinlock_t			lock;
4758e75f744SArnaud Giersch };
4768e75f744SArnaud Giersch static struct parport_ip32_dma_data parport_ip32_dma;
4778e75f744SArnaud Giersch 
4788e75f744SArnaud Giersch /**
4798e75f744SArnaud Giersch  * parport_ip32_dma_setup_context - setup next DMA context
4808e75f744SArnaud Giersch  * @limit:	maximum data size for the context
4818e75f744SArnaud Giersch  *
4828e75f744SArnaud Giersch  * The alignment constraints must be verified in caller function, and the
4838e75f744SArnaud Giersch  * parameter @limit must be set accordingly.
4848e75f744SArnaud Giersch  */
parport_ip32_dma_setup_context(unsigned int limit)4858e75f744SArnaud Giersch static void parport_ip32_dma_setup_context(unsigned int limit)
4868e75f744SArnaud Giersch {
4878e75f744SArnaud Giersch 	unsigned long flags;
4888e75f744SArnaud Giersch 
4898e75f744SArnaud Giersch 	spin_lock_irqsave(&parport_ip32_dma.lock, flags);
4908e75f744SArnaud Giersch 	if (parport_ip32_dma.left > 0) {
4918e75f744SArnaud Giersch 		/* Note: ctxreg is "volatile" here only because
4928e75f744SArnaud Giersch 		 * mace->perif.ctrl.parport.context_a and context_b are
4938e75f744SArnaud Giersch 		 * "volatile".  */
4948e75f744SArnaud Giersch 		volatile u64 __iomem *ctxreg = (parport_ip32_dma.ctx == 0) ?
4958e75f744SArnaud Giersch 			&mace->perif.ctrl.parport.context_a :
4968e75f744SArnaud Giersch 			&mace->perif.ctrl.parport.context_b;
4978e75f744SArnaud Giersch 		u64 count;
4988e75f744SArnaud Giersch 		u64 ctxval;
4998e75f744SArnaud Giersch 		if (parport_ip32_dma.left <= limit) {
5008e75f744SArnaud Giersch 			count = parport_ip32_dma.left;
5018e75f744SArnaud Giersch 			ctxval = MACEPAR_CONTEXT_LASTFLAG;
5028e75f744SArnaud Giersch 		} else {
5038e75f744SArnaud Giersch 			count = limit;
5048e75f744SArnaud Giersch 			ctxval = 0;
5058e75f744SArnaud Giersch 		}
5068e75f744SArnaud Giersch 
5078e75f744SArnaud Giersch 		pr_trace(NULL,
5088e75f744SArnaud Giersch 			 "(%u): 0x%04x:0x%04x, %u -> %u%s",
5098e75f744SArnaud Giersch 			 limit,
5108e75f744SArnaud Giersch 			 (unsigned int)parport_ip32_dma.buf,
5118e75f744SArnaud Giersch 			 (unsigned int)parport_ip32_dma.next,
5128e75f744SArnaud Giersch 			 (unsigned int)count,
5138e75f744SArnaud Giersch 			 parport_ip32_dma.ctx, ctxval ? "*" : "");
5148e75f744SArnaud Giersch 
5158e75f744SArnaud Giersch 		ctxval |= parport_ip32_dma.next &
5168e75f744SArnaud Giersch 			MACEPAR_CONTEXT_BASEADDR_MASK;
5178e75f744SArnaud Giersch 		ctxval |= ((count - 1) << MACEPAR_CONTEXT_DATALEN_SHIFT) &
5188e75f744SArnaud Giersch 			MACEPAR_CONTEXT_DATALEN_MASK;
5198e75f744SArnaud Giersch 		writeq(ctxval, ctxreg);
5208e75f744SArnaud Giersch 		parport_ip32_dma.next += count;
5218e75f744SArnaud Giersch 		parport_ip32_dma.left -= count;
5228e75f744SArnaud Giersch 		parport_ip32_dma.ctx ^= 1U;
5238e75f744SArnaud Giersch 	}
5248e75f744SArnaud Giersch 	/* If there is nothing more to send, disable IRQs to avoid to
5258e75f744SArnaud Giersch 	 * face an IRQ storm which can lock the machine.  Disable them
5268e75f744SArnaud Giersch 	 * only once. */
5278e75f744SArnaud Giersch 	if (parport_ip32_dma.left == 0 && parport_ip32_dma.irq_on) {
5288e75f744SArnaud Giersch 		pr_debug(PPIP32 "IRQ off (ctx)\n");
5298e75f744SArnaud Giersch 		disable_irq_nosync(MACEISA_PAR_CTXA_IRQ);
5308e75f744SArnaud Giersch 		disable_irq_nosync(MACEISA_PAR_CTXB_IRQ);
5318e75f744SArnaud Giersch 		parport_ip32_dma.irq_on = 0;
5328e75f744SArnaud Giersch 	}
5338e75f744SArnaud Giersch 	spin_unlock_irqrestore(&parport_ip32_dma.lock, flags);
5348e75f744SArnaud Giersch }
5358e75f744SArnaud Giersch 
5368e75f744SArnaud Giersch /**
5378e75f744SArnaud Giersch  * parport_ip32_dma_interrupt - DMA interrupt handler
5388e75f744SArnaud Giersch  * @irq:	interrupt number
5398e75f744SArnaud Giersch  * @dev_id:	unused
5408e75f744SArnaud Giersch  */
parport_ip32_dma_interrupt(int irq,void * dev_id)5417d12e780SDavid Howells static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id)
5428e75f744SArnaud Giersch {
5438e75f744SArnaud Giersch 	if (parport_ip32_dma.left)
5448e75f744SArnaud Giersch 		pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx);
5458e75f744SArnaud Giersch 	parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND);
5468e75f744SArnaud Giersch 	return IRQ_HANDLED;
5478e75f744SArnaud Giersch }
5488e75f744SArnaud Giersch 
5498e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32
parport_ip32_merr_interrupt(int irq,void * dev_id)5507d12e780SDavid Howells static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id)
5518e75f744SArnaud Giersch {
5528e75f744SArnaud Giersch 	pr_trace1(NULL, "(%d)", irq);
5538e75f744SArnaud Giersch 	return IRQ_HANDLED;
5548e75f744SArnaud Giersch }
5558e75f744SArnaud Giersch #endif
5568e75f744SArnaud Giersch 
5578e75f744SArnaud Giersch /**
5588e75f744SArnaud Giersch  * parport_ip32_dma_start - begins a DMA transfer
5594217efa3SChristoph Hellwig  * @p:		partport to work on
5608e75f744SArnaud Giersch  * @dir:	DMA direction: DMA_TO_DEVICE or DMA_FROM_DEVICE
5618e75f744SArnaud Giersch  * @addr:	pointer to data buffer
5628e75f744SArnaud Giersch  * @count:	buffer size
5638e75f744SArnaud Giersch  *
5648e75f744SArnaud Giersch  * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be
5658e75f744SArnaud Giersch  * correctly balanced.
5668e75f744SArnaud Giersch  */
parport_ip32_dma_start(struct parport * p,enum dma_data_direction dir,void * addr,size_t count)5674217efa3SChristoph Hellwig static int parport_ip32_dma_start(struct parport *p,
5684217efa3SChristoph Hellwig 		enum dma_data_direction dir, void *addr, size_t count)
5698e75f744SArnaud Giersch {
5708e75f744SArnaud Giersch 	unsigned int limit;
5718e75f744SArnaud Giersch 	u64 ctrl;
5728e75f744SArnaud Giersch 
5738e75f744SArnaud Giersch 	pr_trace(NULL, "(%d, %lu)", dir, (unsigned long)count);
5748e75f744SArnaud Giersch 
5758e75f744SArnaud Giersch 	/* FIXME - add support for DMA_FROM_DEVICE.  In this case, buffer must
5768e75f744SArnaud Giersch 	 * be 64 bytes aligned. */
5778e75f744SArnaud Giersch 	BUG_ON(dir != DMA_TO_DEVICE);
5788e75f744SArnaud Giersch 
5798e75f744SArnaud Giersch 	/* Reset DMA controller */
5808e75f744SArnaud Giersch 	ctrl = MACEPAR_CTLSTAT_RESET;
5818e75f744SArnaud Giersch 	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
5828e75f744SArnaud Giersch 
5838e75f744SArnaud Giersch 	/* DMA IRQs should normally be enabled */
5848e75f744SArnaud Giersch 	if (!parport_ip32_dma.irq_on) {
5858e75f744SArnaud Giersch 		WARN_ON(1);
5868e75f744SArnaud Giersch 		enable_irq(MACEISA_PAR_CTXA_IRQ);
5878e75f744SArnaud Giersch 		enable_irq(MACEISA_PAR_CTXB_IRQ);
5888e75f744SArnaud Giersch 		parport_ip32_dma.irq_on = 1;
5898e75f744SArnaud Giersch 	}
5908e75f744SArnaud Giersch 
5918e75f744SArnaud Giersch 	/* Prepare DMA pointers */
5928e75f744SArnaud Giersch 	parport_ip32_dma.dir = dir;
5934217efa3SChristoph Hellwig 	parport_ip32_dma.buf = dma_map_single(&p->bus_dev, addr, count, dir);
5948e75f744SArnaud Giersch 	parport_ip32_dma.len = count;
5958e75f744SArnaud Giersch 	parport_ip32_dma.next = parport_ip32_dma.buf;
5968e75f744SArnaud Giersch 	parport_ip32_dma.left = parport_ip32_dma.len;
5978e75f744SArnaud Giersch 	parport_ip32_dma.ctx = 0;
5988e75f744SArnaud Giersch 
5998e75f744SArnaud Giersch 	/* Setup DMA direction and first two contexts */
6008e75f744SArnaud Giersch 	ctrl = (dir == DMA_TO_DEVICE) ? 0 : MACEPAR_CTLSTAT_DIRECTION;
6018e75f744SArnaud Giersch 	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
6028e75f744SArnaud Giersch 	/* Single transfer should not cross a 4K page boundary */
6038e75f744SArnaud Giersch 	limit = MACEPAR_CONTEXT_DATA_BOUND -
6048e75f744SArnaud Giersch 		(parport_ip32_dma.next & (MACEPAR_CONTEXT_DATA_BOUND - 1));
6058e75f744SArnaud Giersch 	parport_ip32_dma_setup_context(limit);
6068e75f744SArnaud Giersch 	parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND);
6078e75f744SArnaud Giersch 
6088e75f744SArnaud Giersch 	/* Real start of DMA transfer */
6098e75f744SArnaud Giersch 	ctrl |= MACEPAR_CTLSTAT_ENABLE;
6108e75f744SArnaud Giersch 	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
6118e75f744SArnaud Giersch 
6128e75f744SArnaud Giersch 	return 0;
6138e75f744SArnaud Giersch }
6148e75f744SArnaud Giersch 
6158e75f744SArnaud Giersch /**
6168e75f744SArnaud Giersch  * parport_ip32_dma_stop - ends a running DMA transfer
6174217efa3SChristoph Hellwig  * @p:		partport to work on
6188e75f744SArnaud Giersch  *
6198e75f744SArnaud Giersch  * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be
6208e75f744SArnaud Giersch  * correctly balanced.
6218e75f744SArnaud Giersch  */
parport_ip32_dma_stop(struct parport * p)6224217efa3SChristoph Hellwig static void parport_ip32_dma_stop(struct parport *p)
6238e75f744SArnaud Giersch {
6248e75f744SArnaud Giersch 	u64 ctx_a;
6258e75f744SArnaud Giersch 	u64 ctx_b;
6268e75f744SArnaud Giersch 	u64 ctrl;
6278e75f744SArnaud Giersch 	u64 diag;
6288e75f744SArnaud Giersch 	size_t res[2];	/* {[0] = res_a, [1] = res_b} */
6298e75f744SArnaud Giersch 
6308e75f744SArnaud Giersch 	pr_trace(NULL, "()");
6318e75f744SArnaud Giersch 
6328e75f744SArnaud Giersch 	/* Disable IRQs */
6338e75f744SArnaud Giersch 	spin_lock_irq(&parport_ip32_dma.lock);
6348e75f744SArnaud Giersch 	if (parport_ip32_dma.irq_on) {
6358e75f744SArnaud Giersch 		pr_debug(PPIP32 "IRQ off (stop)\n");
6368e75f744SArnaud Giersch 		disable_irq_nosync(MACEISA_PAR_CTXA_IRQ);
6378e75f744SArnaud Giersch 		disable_irq_nosync(MACEISA_PAR_CTXB_IRQ);
6388e75f744SArnaud Giersch 		parport_ip32_dma.irq_on = 0;
6398e75f744SArnaud Giersch 	}
6408e75f744SArnaud Giersch 	spin_unlock_irq(&parport_ip32_dma.lock);
6418e75f744SArnaud Giersch 	/* Force IRQ synchronization, even if the IRQs were disabled
6428e75f744SArnaud Giersch 	 * elsewhere. */
6438e75f744SArnaud Giersch 	synchronize_irq(MACEISA_PAR_CTXA_IRQ);
6448e75f744SArnaud Giersch 	synchronize_irq(MACEISA_PAR_CTXB_IRQ);
6458e75f744SArnaud Giersch 
6468e75f744SArnaud Giersch 	/* Stop DMA transfer */
6478e75f744SArnaud Giersch 	ctrl = readq(&mace->perif.ctrl.parport.cntlstat);
6488e75f744SArnaud Giersch 	ctrl &= ~MACEPAR_CTLSTAT_ENABLE;
6498e75f744SArnaud Giersch 	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
6508e75f744SArnaud Giersch 
6518e75f744SArnaud Giersch 	/* Adjust residue (parport_ip32_dma.left) */
6528e75f744SArnaud Giersch 	ctx_a = readq(&mace->perif.ctrl.parport.context_a);
6538e75f744SArnaud Giersch 	ctx_b = readq(&mace->perif.ctrl.parport.context_b);
6548e75f744SArnaud Giersch 	ctrl = readq(&mace->perif.ctrl.parport.cntlstat);
6558e75f744SArnaud Giersch 	diag = readq(&mace->perif.ctrl.parport.diagnostic);
6568e75f744SArnaud Giersch 	res[0] = (ctrl & MACEPAR_CTLSTAT_CTXA_VALID) ?
6578e75f744SArnaud Giersch 		1 + ((ctx_a & MACEPAR_CONTEXT_DATALEN_MASK) >>
6588e75f744SArnaud Giersch 		     MACEPAR_CONTEXT_DATALEN_SHIFT) :
6598e75f744SArnaud Giersch 		0;
6608e75f744SArnaud Giersch 	res[1] = (ctrl & MACEPAR_CTLSTAT_CTXB_VALID) ?
6618e75f744SArnaud Giersch 		1 + ((ctx_b & MACEPAR_CONTEXT_DATALEN_MASK) >>
6628e75f744SArnaud Giersch 		     MACEPAR_CONTEXT_DATALEN_SHIFT) :
6638e75f744SArnaud Giersch 		0;
6648e75f744SArnaud Giersch 	if (diag & MACEPAR_DIAG_DMACTIVE)
6658e75f744SArnaud Giersch 		res[(diag & MACEPAR_DIAG_CTXINUSE) != 0] =
6668e75f744SArnaud Giersch 			1 + ((diag & MACEPAR_DIAG_CTRMASK) >>
6678e75f744SArnaud Giersch 			     MACEPAR_DIAG_CTRSHIFT);
6688e75f744SArnaud Giersch 	parport_ip32_dma.left += res[0] + res[1];
6698e75f744SArnaud Giersch 
6708e75f744SArnaud Giersch 	/* Reset DMA controller, and re-enable IRQs */
6718e75f744SArnaud Giersch 	ctrl = MACEPAR_CTLSTAT_RESET;
6728e75f744SArnaud Giersch 	writeq(ctrl, &mace->perif.ctrl.parport.cntlstat);
6738e75f744SArnaud Giersch 	pr_debug(PPIP32 "IRQ on (stop)\n");
6748e75f744SArnaud Giersch 	enable_irq(MACEISA_PAR_CTXA_IRQ);
6758e75f744SArnaud Giersch 	enable_irq(MACEISA_PAR_CTXB_IRQ);
6768e75f744SArnaud Giersch 	parport_ip32_dma.irq_on = 1;
6778e75f744SArnaud Giersch 
6784217efa3SChristoph Hellwig 	dma_unmap_single(&p->bus_dev, parport_ip32_dma.buf,
6794217efa3SChristoph Hellwig 			 parport_ip32_dma.len, parport_ip32_dma.dir);
6808e75f744SArnaud Giersch }
6818e75f744SArnaud Giersch 
6828e75f744SArnaud Giersch /**
6838e75f744SArnaud Giersch  * parport_ip32_dma_get_residue - get residue from last DMA transfer
6848e75f744SArnaud Giersch  *
6858e75f744SArnaud Giersch  * Returns the number of bytes remaining from last DMA transfer.
6868e75f744SArnaud Giersch  */
parport_ip32_dma_get_residue(void)6878e75f744SArnaud Giersch static inline size_t parport_ip32_dma_get_residue(void)
6888e75f744SArnaud Giersch {
6898e75f744SArnaud Giersch 	return parport_ip32_dma.left;
6908e75f744SArnaud Giersch }
6918e75f744SArnaud Giersch 
6928e75f744SArnaud Giersch /**
6938e75f744SArnaud Giersch  * parport_ip32_dma_register - initialize DMA engine
6948e75f744SArnaud Giersch  *
6958e75f744SArnaud Giersch  * Returns zero for success.
6968e75f744SArnaud Giersch  */
parport_ip32_dma_register(void)6978e75f744SArnaud Giersch static int parport_ip32_dma_register(void)
6988e75f744SArnaud Giersch {
6998e75f744SArnaud Giersch 	int err;
7008e75f744SArnaud Giersch 
7018e75f744SArnaud Giersch 	spin_lock_init(&parport_ip32_dma.lock);
7028e75f744SArnaud Giersch 	parport_ip32_dma.irq_on = 1;
7038e75f744SArnaud Giersch 
7048e75f744SArnaud Giersch 	/* Reset DMA controller */
7058e75f744SArnaud Giersch 	writeq(MACEPAR_CTLSTAT_RESET, &mace->perif.ctrl.parport.cntlstat);
7068e75f744SArnaud Giersch 
7078e75f744SArnaud Giersch 	/* Request IRQs */
7088e75f744SArnaud Giersch 	err = request_irq(MACEISA_PAR_CTXA_IRQ, parport_ip32_dma_interrupt,
7098e75f744SArnaud Giersch 			  0, "parport_ip32", NULL);
7108e75f744SArnaud Giersch 	if (err)
7118e75f744SArnaud Giersch 		goto fail_a;
7128e75f744SArnaud Giersch 	err = request_irq(MACEISA_PAR_CTXB_IRQ, parport_ip32_dma_interrupt,
7138e75f744SArnaud Giersch 			  0, "parport_ip32", NULL);
7148e75f744SArnaud Giersch 	if (err)
7158e75f744SArnaud Giersch 		goto fail_b;
7168e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32
7178e75f744SArnaud Giersch 	/* FIXME - what is this IRQ for? */
7188e75f744SArnaud Giersch 	err = request_irq(MACEISA_PAR_MERR_IRQ, parport_ip32_merr_interrupt,
7198e75f744SArnaud Giersch 			  0, "parport_ip32", NULL);
7208e75f744SArnaud Giersch 	if (err)
7218e75f744SArnaud Giersch 		goto fail_merr;
7228e75f744SArnaud Giersch #endif
7238e75f744SArnaud Giersch 	return 0;
7248e75f744SArnaud Giersch 
7258e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32
7268e75f744SArnaud Giersch fail_merr:
7278e75f744SArnaud Giersch 	free_irq(MACEISA_PAR_CTXB_IRQ, NULL);
7288e75f744SArnaud Giersch #endif
7298e75f744SArnaud Giersch fail_b:
7308e75f744SArnaud Giersch 	free_irq(MACEISA_PAR_CTXA_IRQ, NULL);
7318e75f744SArnaud Giersch fail_a:
7328e75f744SArnaud Giersch 	return err;
7338e75f744SArnaud Giersch }
7348e75f744SArnaud Giersch 
7358e75f744SArnaud Giersch /**
7368e75f744SArnaud Giersch  * parport_ip32_dma_unregister - release and free resources for DMA engine
7378e75f744SArnaud Giersch  */
parport_ip32_dma_unregister(void)7388e75f744SArnaud Giersch static void parport_ip32_dma_unregister(void)
7398e75f744SArnaud Giersch {
7408e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32
7418e75f744SArnaud Giersch 	free_irq(MACEISA_PAR_MERR_IRQ, NULL);
7428e75f744SArnaud Giersch #endif
7438e75f744SArnaud Giersch 	free_irq(MACEISA_PAR_CTXB_IRQ, NULL);
7448e75f744SArnaud Giersch 	free_irq(MACEISA_PAR_CTXA_IRQ, NULL);
7458e75f744SArnaud Giersch }
7468e75f744SArnaud Giersch 
7478e75f744SArnaud Giersch /*--- Interrupt handlers and associates --------------------------------*/
7488e75f744SArnaud Giersch 
7498e75f744SArnaud Giersch /**
7508e75f744SArnaud Giersch  * parport_ip32_wakeup - wakes up code waiting for an interrupt
7518e75f744SArnaud Giersch  * @p:		pointer to &struct parport
7528e75f744SArnaud Giersch  */
parport_ip32_wakeup(struct parport * p)7538e75f744SArnaud Giersch static inline void parport_ip32_wakeup(struct parport *p)
7548e75f744SArnaud Giersch {
7558e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
7568e75f744SArnaud Giersch 	complete(&priv->irq_complete);
7578e75f744SArnaud Giersch }
7588e75f744SArnaud Giersch 
7598e75f744SArnaud Giersch /**
7608e75f744SArnaud Giersch  * parport_ip32_interrupt - interrupt handler
7618e75f744SArnaud Giersch  * @irq:	interrupt number
7628e75f744SArnaud Giersch  * @dev_id:	pointer to &struct parport
7638e75f744SArnaud Giersch  *
7648e75f744SArnaud Giersch  * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is
7658e75f744SArnaud Giersch  * %PARPORT_IP32_IRQ_FWD.
7668e75f744SArnaud Giersch  */
parport_ip32_interrupt(int irq,void * dev_id)7677d12e780SDavid Howells static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id)
7688e75f744SArnaud Giersch {
7698e75f744SArnaud Giersch 	struct parport * const p = dev_id;
7708e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
7718e75f744SArnaud Giersch 	enum parport_ip32_irq_mode irq_mode = priv->irq_mode;
7723f2e40dfSJeff Garzik 
7738e75f744SArnaud Giersch 	switch (irq_mode) {
7748e75f744SArnaud Giersch 	case PARPORT_IP32_IRQ_FWD:
7753f2e40dfSJeff Garzik 		return parport_irq_handler(irq, dev_id);
7763f2e40dfSJeff Garzik 
7778e75f744SArnaud Giersch 	case PARPORT_IP32_IRQ_HERE:
7788e75f744SArnaud Giersch 		parport_ip32_wakeup(p);
7798e75f744SArnaud Giersch 		break;
7808e75f744SArnaud Giersch 	}
7813f2e40dfSJeff Garzik 
7828e75f744SArnaud Giersch 	return IRQ_HANDLED;
7838e75f744SArnaud Giersch }
7848e75f744SArnaud Giersch 
7858e75f744SArnaud Giersch /*--- Some utility function to manipulate ECR register -----------------*/
7868e75f744SArnaud Giersch 
7878e75f744SArnaud Giersch /**
7888e75f744SArnaud Giersch  * parport_ip32_read_econtrol - read contents of the ECR register
7898e75f744SArnaud Giersch  * @p:		pointer to &struct parport
7908e75f744SArnaud Giersch  */
parport_ip32_read_econtrol(struct parport * p)7918e75f744SArnaud Giersch static inline unsigned int parport_ip32_read_econtrol(struct parport *p)
7928e75f744SArnaud Giersch {
7938e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
7948e75f744SArnaud Giersch 	return readb(priv->regs.ecr);
7958e75f744SArnaud Giersch }
7968e75f744SArnaud Giersch 
7978e75f744SArnaud Giersch /**
7988e75f744SArnaud Giersch  * parport_ip32_write_econtrol - write new contents to the ECR register
7998e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8008e75f744SArnaud Giersch  * @c:		new value to write
8018e75f744SArnaud Giersch  */
parport_ip32_write_econtrol(struct parport * p,unsigned int c)8028e75f744SArnaud Giersch static inline void parport_ip32_write_econtrol(struct parport *p,
8038e75f744SArnaud Giersch 					       unsigned int c)
8048e75f744SArnaud Giersch {
8058e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
8068e75f744SArnaud Giersch 	writeb(c, priv->regs.ecr);
8078e75f744SArnaud Giersch }
8088e75f744SArnaud Giersch 
8098e75f744SArnaud Giersch /**
8108e75f744SArnaud Giersch  * parport_ip32_frob_econtrol - change bits from the ECR register
8118e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8128e75f744SArnaud Giersch  * @mask:	bit mask of bits to change
8138e75f744SArnaud Giersch  * @val:	new value for changed bits
8148e75f744SArnaud Giersch  *
8158e75f744SArnaud Giersch  * Read from the ECR, mask out the bits in @mask, exclusive-or with the bits
8168e75f744SArnaud Giersch  * in @val, and write the result to the ECR.
8178e75f744SArnaud Giersch  */
parport_ip32_frob_econtrol(struct parport * p,unsigned int mask,unsigned int val)8188e75f744SArnaud Giersch static inline void parport_ip32_frob_econtrol(struct parport *p,
8198e75f744SArnaud Giersch 					      unsigned int mask,
8208e75f744SArnaud Giersch 					      unsigned int val)
8218e75f744SArnaud Giersch {
8228e75f744SArnaud Giersch 	unsigned int c;
8238e75f744SArnaud Giersch 	c = (parport_ip32_read_econtrol(p) & ~mask) ^ val;
8248e75f744SArnaud Giersch 	parport_ip32_write_econtrol(p, c);
8258e75f744SArnaud Giersch }
8268e75f744SArnaud Giersch 
8278e75f744SArnaud Giersch /**
8288e75f744SArnaud Giersch  * parport_ip32_set_mode - change mode of ECP port
8298e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8308e75f744SArnaud Giersch  * @mode:	new mode to write in ECR
8318e75f744SArnaud Giersch  *
8328e75f744SArnaud Giersch  * ECR is reset in a sane state (interrupts and DMA disabled), and placed in
8338e75f744SArnaud Giersch  * mode @mode.  Go through PS2 mode if needed.
8348e75f744SArnaud Giersch  */
parport_ip32_set_mode(struct parport * p,unsigned int mode)8358e75f744SArnaud Giersch static void parport_ip32_set_mode(struct parport *p, unsigned int mode)
8368e75f744SArnaud Giersch {
8378e75f744SArnaud Giersch 	unsigned int omode;
8388e75f744SArnaud Giersch 
8398e75f744SArnaud Giersch 	mode &= ECR_MODE_MASK;
8408e75f744SArnaud Giersch 	omode = parport_ip32_read_econtrol(p) & ECR_MODE_MASK;
8418e75f744SArnaud Giersch 
8428e75f744SArnaud Giersch 	if (!(mode == ECR_MODE_SPP || mode == ECR_MODE_PS2
8438e75f744SArnaud Giersch 	      || omode == ECR_MODE_SPP || omode == ECR_MODE_PS2)) {
8448e75f744SArnaud Giersch 		/* We have to go through PS2 mode */
8458e75f744SArnaud Giersch 		unsigned int ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
8468e75f744SArnaud Giersch 		parport_ip32_write_econtrol(p, ecr);
8478e75f744SArnaud Giersch 	}
8488e75f744SArnaud Giersch 	parport_ip32_write_econtrol(p, mode | ECR_nERRINTR | ECR_SERVINTR);
8498e75f744SArnaud Giersch }
8508e75f744SArnaud Giersch 
8518e75f744SArnaud Giersch /*--- Basic functions needed for parport -------------------------------*/
8528e75f744SArnaud Giersch 
8538e75f744SArnaud Giersch /**
8548e75f744SArnaud Giersch  * parport_ip32_read_data - return current contents of the DATA register
8558e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8568e75f744SArnaud Giersch  */
parport_ip32_read_data(struct parport * p)8578e75f744SArnaud Giersch static inline unsigned char parport_ip32_read_data(struct parport *p)
8588e75f744SArnaud Giersch {
8598e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
8608e75f744SArnaud Giersch 	return readb(priv->regs.data);
8618e75f744SArnaud Giersch }
8628e75f744SArnaud Giersch 
8638e75f744SArnaud Giersch /**
8648e75f744SArnaud Giersch  * parport_ip32_write_data - set new contents for the DATA register
8658e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8668e75f744SArnaud Giersch  * @d:		new value to write
8678e75f744SArnaud Giersch  */
parport_ip32_write_data(struct parport * p,unsigned char d)8688e75f744SArnaud Giersch static inline void parport_ip32_write_data(struct parport *p, unsigned char d)
8698e75f744SArnaud Giersch {
8708e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
8718e75f744SArnaud Giersch 	writeb(d, priv->regs.data);
8728e75f744SArnaud Giersch }
8738e75f744SArnaud Giersch 
8748e75f744SArnaud Giersch /**
8758e75f744SArnaud Giersch  * parport_ip32_read_status - return current contents of the DSR register
8768e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8778e75f744SArnaud Giersch  */
parport_ip32_read_status(struct parport * p)8788e75f744SArnaud Giersch static inline unsigned char parport_ip32_read_status(struct parport *p)
8798e75f744SArnaud Giersch {
8808e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
8818e75f744SArnaud Giersch 	return readb(priv->regs.dsr);
8828e75f744SArnaud Giersch }
8838e75f744SArnaud Giersch 
8848e75f744SArnaud Giersch /**
8858e75f744SArnaud Giersch  * __parport_ip32_read_control - return cached contents of the DCR register
8868e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8878e75f744SArnaud Giersch  */
__parport_ip32_read_control(struct parport * p)8888e75f744SArnaud Giersch static inline unsigned int __parport_ip32_read_control(struct parport *p)
8898e75f744SArnaud Giersch {
8908e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
8918e75f744SArnaud Giersch 	return priv->dcr_cache; /* use soft copy */
8928e75f744SArnaud Giersch }
8938e75f744SArnaud Giersch 
8948e75f744SArnaud Giersch /**
8958e75f744SArnaud Giersch  * __parport_ip32_write_control - set new contents for the DCR register
8968e75f744SArnaud Giersch  * @p:		pointer to &struct parport
8978e75f744SArnaud Giersch  * @c:		new value to write
8988e75f744SArnaud Giersch  */
__parport_ip32_write_control(struct parport * p,unsigned int c)8998e75f744SArnaud Giersch static inline void __parport_ip32_write_control(struct parport *p,
9008e75f744SArnaud Giersch 						unsigned int c)
9018e75f744SArnaud Giersch {
9028e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
9038e75f744SArnaud Giersch 	CHECK_EXTRA_BITS(p, c, priv->dcr_writable);
9048e75f744SArnaud Giersch 	c &= priv->dcr_writable; /* only writable bits */
9058e75f744SArnaud Giersch 	writeb(c, priv->regs.dcr);
9068e75f744SArnaud Giersch 	priv->dcr_cache = c;		/* update soft copy */
9078e75f744SArnaud Giersch }
9088e75f744SArnaud Giersch 
9098e75f744SArnaud Giersch /**
9108e75f744SArnaud Giersch  * __parport_ip32_frob_control - change bits from the DCR register
9118e75f744SArnaud Giersch  * @p:		pointer to &struct parport
9128e75f744SArnaud Giersch  * @mask:	bit mask of bits to change
9138e75f744SArnaud Giersch  * @val:	new value for changed bits
9148e75f744SArnaud Giersch  *
9158e75f744SArnaud Giersch  * This is equivalent to read from the DCR, mask out the bits in @mask,
9168e75f744SArnaud Giersch  * exclusive-or with the bits in @val, and write the result to the DCR.
9178e75f744SArnaud Giersch  * Actually, the cached contents of the DCR is used.
9188e75f744SArnaud Giersch  */
__parport_ip32_frob_control(struct parport * p,unsigned int mask,unsigned int val)9198e75f744SArnaud Giersch static inline void __parport_ip32_frob_control(struct parport *p,
9208e75f744SArnaud Giersch 					       unsigned int mask,
9218e75f744SArnaud Giersch 					       unsigned int val)
9228e75f744SArnaud Giersch {
9238e75f744SArnaud Giersch 	unsigned int c;
9248e75f744SArnaud Giersch 	c = (__parport_ip32_read_control(p) & ~mask) ^ val;
9258e75f744SArnaud Giersch 	__parport_ip32_write_control(p, c);
9268e75f744SArnaud Giersch }
9278e75f744SArnaud Giersch 
9288e75f744SArnaud Giersch /**
9298e75f744SArnaud Giersch  * parport_ip32_read_control - return cached contents of the DCR register
9308e75f744SArnaud Giersch  * @p:		pointer to &struct parport
9318e75f744SArnaud Giersch  *
9328e75f744SArnaud Giersch  * The return value is masked so as to only return the value of %DCR_STROBE,
9338e75f744SArnaud Giersch  * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
9348e75f744SArnaud Giersch  */
parport_ip32_read_control(struct parport * p)9358e75f744SArnaud Giersch static inline unsigned char parport_ip32_read_control(struct parport *p)
9368e75f744SArnaud Giersch {
9378e75f744SArnaud Giersch 	const unsigned int rm =
9388e75f744SArnaud Giersch 		DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
9398e75f744SArnaud Giersch 	return __parport_ip32_read_control(p) & rm;
9408e75f744SArnaud Giersch }
9418e75f744SArnaud Giersch 
9428e75f744SArnaud Giersch /**
9438e75f744SArnaud Giersch  * parport_ip32_write_control - set new contents for the DCR register
9448e75f744SArnaud Giersch  * @p:		pointer to &struct parport
9458e75f744SArnaud Giersch  * @c:		new value to write
9468e75f744SArnaud Giersch  *
9478e75f744SArnaud Giersch  * The value is masked so as to only change the value of %DCR_STROBE,
9488e75f744SArnaud Giersch  * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
9498e75f744SArnaud Giersch  */
parport_ip32_write_control(struct parport * p,unsigned char c)9508e75f744SArnaud Giersch static inline void parport_ip32_write_control(struct parport *p,
9518e75f744SArnaud Giersch 					      unsigned char c)
9528e75f744SArnaud Giersch {
9538e75f744SArnaud Giersch 	const unsigned int wm =
9548e75f744SArnaud Giersch 		DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
9558e75f744SArnaud Giersch 	CHECK_EXTRA_BITS(p, c, wm);
9568e75f744SArnaud Giersch 	__parport_ip32_frob_control(p, wm, c & wm);
9578e75f744SArnaud Giersch }
9588e75f744SArnaud Giersch 
9598e75f744SArnaud Giersch /**
9608e75f744SArnaud Giersch  * parport_ip32_frob_control - change bits from the DCR register
9618e75f744SArnaud Giersch  * @p:		pointer to &struct parport
9628e75f744SArnaud Giersch  * @mask:	bit mask of bits to change
9638e75f744SArnaud Giersch  * @val:	new value for changed bits
9648e75f744SArnaud Giersch  *
9658e75f744SArnaud Giersch  * This differs from __parport_ip32_frob_control() in that it only allows to
9668e75f744SArnaud Giersch  * change the value of %DCR_STROBE, %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT.
9678e75f744SArnaud Giersch  */
parport_ip32_frob_control(struct parport * p,unsigned char mask,unsigned char val)9688e75f744SArnaud Giersch static inline unsigned char parport_ip32_frob_control(struct parport *p,
9698e75f744SArnaud Giersch 						      unsigned char mask,
9708e75f744SArnaud Giersch 						      unsigned char val)
9718e75f744SArnaud Giersch {
9728e75f744SArnaud Giersch 	const unsigned int wm =
9738e75f744SArnaud Giersch 		DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT;
9748e75f744SArnaud Giersch 	CHECK_EXTRA_BITS(p, mask, wm);
9758e75f744SArnaud Giersch 	CHECK_EXTRA_BITS(p, val, wm);
9768e75f744SArnaud Giersch 	__parport_ip32_frob_control(p, mask & wm, val & wm);
9778e75f744SArnaud Giersch 	return parport_ip32_read_control(p);
9788e75f744SArnaud Giersch }
9798e75f744SArnaud Giersch 
9808e75f744SArnaud Giersch /**
9818e75f744SArnaud Giersch  * parport_ip32_disable_irq - disable interrupts on the rising edge of nACK
9828e75f744SArnaud Giersch  * @p:		pointer to &struct parport
9838e75f744SArnaud Giersch  */
parport_ip32_disable_irq(struct parport * p)9848e75f744SArnaud Giersch static inline void parport_ip32_disable_irq(struct parport *p)
9858e75f744SArnaud Giersch {
9868e75f744SArnaud Giersch 	__parport_ip32_frob_control(p, DCR_IRQ, 0);
9878e75f744SArnaud Giersch }
9888e75f744SArnaud Giersch 
9898e75f744SArnaud Giersch /**
9908e75f744SArnaud Giersch  * parport_ip32_enable_irq - enable interrupts on the rising edge of nACK
9918e75f744SArnaud Giersch  * @p:		pointer to &struct parport
9928e75f744SArnaud Giersch  */
parport_ip32_enable_irq(struct parport * p)9938e75f744SArnaud Giersch static inline void parport_ip32_enable_irq(struct parport *p)
9948e75f744SArnaud Giersch {
9958e75f744SArnaud Giersch 	__parport_ip32_frob_control(p, DCR_IRQ, DCR_IRQ);
9968e75f744SArnaud Giersch }
9978e75f744SArnaud Giersch 
9988e75f744SArnaud Giersch /**
9998e75f744SArnaud Giersch  * parport_ip32_data_forward - enable host-to-peripheral communications
10008e75f744SArnaud Giersch  * @p:		pointer to &struct parport
10018e75f744SArnaud Giersch  *
10028e75f744SArnaud Giersch  * Enable the data line drivers, for 8-bit host-to-peripheral communications.
10038e75f744SArnaud Giersch  */
parport_ip32_data_forward(struct parport * p)10048e75f744SArnaud Giersch static inline void parport_ip32_data_forward(struct parport *p)
10058e75f744SArnaud Giersch {
10068e75f744SArnaud Giersch 	__parport_ip32_frob_control(p, DCR_DIR, 0);
10078e75f744SArnaud Giersch }
10088e75f744SArnaud Giersch 
10098e75f744SArnaud Giersch /**
10108e75f744SArnaud Giersch  * parport_ip32_data_reverse - enable peripheral-to-host communications
10118e75f744SArnaud Giersch  * @p:		pointer to &struct parport
10128e75f744SArnaud Giersch  *
10138e75f744SArnaud Giersch  * Place the data bus in a high impedance state, if @p->modes has the
10148e75f744SArnaud Giersch  * PARPORT_MODE_TRISTATE bit set.
10158e75f744SArnaud Giersch  */
parport_ip32_data_reverse(struct parport * p)10168e75f744SArnaud Giersch static inline void parport_ip32_data_reverse(struct parport *p)
10178e75f744SArnaud Giersch {
10188e75f744SArnaud Giersch 	__parport_ip32_frob_control(p, DCR_DIR, DCR_DIR);
10198e75f744SArnaud Giersch }
10208e75f744SArnaud Giersch 
10218e75f744SArnaud Giersch /**
10228e75f744SArnaud Giersch  * parport_ip32_init_state - for core parport code
10238e75f744SArnaud Giersch  * @dev:	pointer to &struct pardevice
10248e75f744SArnaud Giersch  * @s:		pointer to &struct parport_state to initialize
10258e75f744SArnaud Giersch  */
parport_ip32_init_state(struct pardevice * dev,struct parport_state * s)10268e75f744SArnaud Giersch static void parport_ip32_init_state(struct pardevice *dev,
10278e75f744SArnaud Giersch 				    struct parport_state *s)
10288e75f744SArnaud Giersch {
10298e75f744SArnaud Giersch 	s->u.ip32.dcr = DCR_SELECT | DCR_nINIT;
10308e75f744SArnaud Giersch 	s->u.ip32.ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
10318e75f744SArnaud Giersch }
10328e75f744SArnaud Giersch 
10338e75f744SArnaud Giersch /**
10348e75f744SArnaud Giersch  * parport_ip32_save_state - for core parport code
10358e75f744SArnaud Giersch  * @p:		pointer to &struct parport
10368e75f744SArnaud Giersch  * @s:		pointer to &struct parport_state to save state to
10378e75f744SArnaud Giersch  */
parport_ip32_save_state(struct parport * p,struct parport_state * s)10388e75f744SArnaud Giersch static void parport_ip32_save_state(struct parport *p,
10398e75f744SArnaud Giersch 				    struct parport_state *s)
10408e75f744SArnaud Giersch {
10418e75f744SArnaud Giersch 	s->u.ip32.dcr = __parport_ip32_read_control(p);
10428e75f744SArnaud Giersch 	s->u.ip32.ecr = parport_ip32_read_econtrol(p);
10438e75f744SArnaud Giersch }
10448e75f744SArnaud Giersch 
10458e75f744SArnaud Giersch /**
10468e75f744SArnaud Giersch  * parport_ip32_restore_state - for core parport code
10478e75f744SArnaud Giersch  * @p:		pointer to &struct parport
10488e75f744SArnaud Giersch  * @s:		pointer to &struct parport_state to restore state from
10498e75f744SArnaud Giersch  */
parport_ip32_restore_state(struct parport * p,struct parport_state * s)10508e75f744SArnaud Giersch static void parport_ip32_restore_state(struct parport *p,
10518e75f744SArnaud Giersch 				       struct parport_state *s)
10528e75f744SArnaud Giersch {
10538e75f744SArnaud Giersch 	parport_ip32_set_mode(p, s->u.ip32.ecr & ECR_MODE_MASK);
10548e75f744SArnaud Giersch 	parport_ip32_write_econtrol(p, s->u.ip32.ecr);
10558e75f744SArnaud Giersch 	__parport_ip32_write_control(p, s->u.ip32.dcr);
10568e75f744SArnaud Giersch }
10578e75f744SArnaud Giersch 
10588e75f744SArnaud Giersch /*--- EPP mode functions -----------------------------------------------*/
10598e75f744SArnaud Giersch 
10608e75f744SArnaud Giersch /**
10618e75f744SArnaud Giersch  * parport_ip32_clear_epp_timeout - clear Timeout bit in EPP mode
10628e75f744SArnaud Giersch  * @p:		pointer to &struct parport
10638e75f744SArnaud Giersch  *
10648e75f744SArnaud Giersch  * Returns 1 if the Timeout bit is clear, and 0 otherwise.
10658e75f744SArnaud Giersch  */
parport_ip32_clear_epp_timeout(struct parport * p)10668e75f744SArnaud Giersch static unsigned int parport_ip32_clear_epp_timeout(struct parport *p)
10678e75f744SArnaud Giersch {
10688e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
10698e75f744SArnaud Giersch 	unsigned int cleared;
10708e75f744SArnaud Giersch 
10718e75f744SArnaud Giersch 	if (!(parport_ip32_read_status(p) & DSR_TIMEOUT))
10728e75f744SArnaud Giersch 		cleared = 1;
10738e75f744SArnaud Giersch 	else {
10748e75f744SArnaud Giersch 		unsigned int r;
10758e75f744SArnaud Giersch 		/* To clear timeout some chips require double read */
10768e75f744SArnaud Giersch 		parport_ip32_read_status(p);
10778e75f744SArnaud Giersch 		r = parport_ip32_read_status(p);
10788e75f744SArnaud Giersch 		/* Some reset by writing 1 */
10798e75f744SArnaud Giersch 		writeb(r | DSR_TIMEOUT, priv->regs.dsr);
10808e75f744SArnaud Giersch 		/* Others by writing 0 */
10818e75f744SArnaud Giersch 		writeb(r & ~DSR_TIMEOUT, priv->regs.dsr);
10828e75f744SArnaud Giersch 
10838e75f744SArnaud Giersch 		r = parport_ip32_read_status(p);
10848e75f744SArnaud Giersch 		cleared = !(r & DSR_TIMEOUT);
10858e75f744SArnaud Giersch 	}
10868e75f744SArnaud Giersch 
10878e75f744SArnaud Giersch 	pr_trace(p, "(): %s", cleared ? "cleared" : "failed");
10888e75f744SArnaud Giersch 	return cleared;
10898e75f744SArnaud Giersch }
10908e75f744SArnaud Giersch 
10918e75f744SArnaud Giersch /**
10928e75f744SArnaud Giersch  * parport_ip32_epp_read - generic EPP read function
10938e75f744SArnaud Giersch  * @eppreg:	I/O register to read from
10948e75f744SArnaud Giersch  * @p:		pointer to &struct parport
10958e75f744SArnaud Giersch  * @buf:	buffer to store read data
10968e75f744SArnaud Giersch  * @len:	length of buffer @buf
10978e75f744SArnaud Giersch  * @flags:	may be PARPORT_EPP_FAST
10988e75f744SArnaud Giersch  */
parport_ip32_epp_read(void __iomem * eppreg,struct parport * p,void * buf,size_t len,int flags)10998e75f744SArnaud Giersch static size_t parport_ip32_epp_read(void __iomem *eppreg,
11008e75f744SArnaud Giersch 				    struct parport *p, void *buf,
11018e75f744SArnaud Giersch 				    size_t len, int flags)
11028e75f744SArnaud Giersch {
11038e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
11048e75f744SArnaud Giersch 	size_t got;
11058e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_EPP);
11068e75f744SArnaud Giersch 	parport_ip32_data_reverse(p);
11078e75f744SArnaud Giersch 	parport_ip32_write_control(p, DCR_nINIT);
11088e75f744SArnaud Giersch 	if ((flags & PARPORT_EPP_FAST) && (len > 1)) {
11098e75f744SArnaud Giersch 		readsb(eppreg, buf, len);
11108e75f744SArnaud Giersch 		if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
11118e75f744SArnaud Giersch 			parport_ip32_clear_epp_timeout(p);
11128e75f744SArnaud Giersch 			return -EIO;
11138e75f744SArnaud Giersch 		}
11148e75f744SArnaud Giersch 		got = len;
11158e75f744SArnaud Giersch 	} else {
11168e75f744SArnaud Giersch 		u8 *bufp = buf;
11178e75f744SArnaud Giersch 		for (got = 0; got < len; got++) {
11188e75f744SArnaud Giersch 			*bufp++ = readb(eppreg);
11198e75f744SArnaud Giersch 			if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
11208e75f744SArnaud Giersch 				parport_ip32_clear_epp_timeout(p);
11218e75f744SArnaud Giersch 				break;
11228e75f744SArnaud Giersch 			}
11238e75f744SArnaud Giersch 		}
11248e75f744SArnaud Giersch 	}
11258e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
11268e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
11278e75f744SArnaud Giersch 	return got;
11288e75f744SArnaud Giersch }
11298e75f744SArnaud Giersch 
11308e75f744SArnaud Giersch /**
11318e75f744SArnaud Giersch  * parport_ip32_epp_write - generic EPP write function
11328e75f744SArnaud Giersch  * @eppreg:	I/O register to write to
11338e75f744SArnaud Giersch  * @p:		pointer to &struct parport
11348e75f744SArnaud Giersch  * @buf:	buffer of data to write
11358e75f744SArnaud Giersch  * @len:	length of buffer @buf
11368e75f744SArnaud Giersch  * @flags:	may be PARPORT_EPP_FAST
11378e75f744SArnaud Giersch  */
parport_ip32_epp_write(void __iomem * eppreg,struct parport * p,const void * buf,size_t len,int flags)11388e75f744SArnaud Giersch static size_t parport_ip32_epp_write(void __iomem *eppreg,
11398e75f744SArnaud Giersch 				     struct parport *p, const void *buf,
11408e75f744SArnaud Giersch 				     size_t len, int flags)
11418e75f744SArnaud Giersch {
11428e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
11438e75f744SArnaud Giersch 	size_t written;
11448e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_EPP);
11458e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
11468e75f744SArnaud Giersch 	parport_ip32_write_control(p, DCR_nINIT);
11478e75f744SArnaud Giersch 	if ((flags & PARPORT_EPP_FAST) && (len > 1)) {
11488e75f744SArnaud Giersch 		writesb(eppreg, buf, len);
11498e75f744SArnaud Giersch 		if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
11508e75f744SArnaud Giersch 			parport_ip32_clear_epp_timeout(p);
11518e75f744SArnaud Giersch 			return -EIO;
11528e75f744SArnaud Giersch 		}
11538e75f744SArnaud Giersch 		written = len;
11548e75f744SArnaud Giersch 	} else {
11558e75f744SArnaud Giersch 		const u8 *bufp = buf;
11568e75f744SArnaud Giersch 		for (written = 0; written < len; written++) {
11578e75f744SArnaud Giersch 			writeb(*bufp++, eppreg);
11588e75f744SArnaud Giersch 			if (readb(priv->regs.dsr) & DSR_TIMEOUT) {
11598e75f744SArnaud Giersch 				parport_ip32_clear_epp_timeout(p);
11608e75f744SArnaud Giersch 				break;
11618e75f744SArnaud Giersch 			}
11628e75f744SArnaud Giersch 		}
11638e75f744SArnaud Giersch 	}
11648e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
11658e75f744SArnaud Giersch 	return written;
11668e75f744SArnaud Giersch }
11678e75f744SArnaud Giersch 
11688e75f744SArnaud Giersch /**
11698e75f744SArnaud Giersch  * parport_ip32_epp_read_data - read a block of data in EPP mode
11708e75f744SArnaud Giersch  * @p:		pointer to &struct parport
11718e75f744SArnaud Giersch  * @buf:	buffer to store read data
11728e75f744SArnaud Giersch  * @len:	length of buffer @buf
11738e75f744SArnaud Giersch  * @flags:	may be PARPORT_EPP_FAST
11748e75f744SArnaud Giersch  */
parport_ip32_epp_read_data(struct parport * p,void * buf,size_t len,int flags)11758e75f744SArnaud Giersch static size_t parport_ip32_epp_read_data(struct parport *p, void *buf,
11768e75f744SArnaud Giersch 					 size_t len, int flags)
11778e75f744SArnaud Giersch {
11788e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
11798e75f744SArnaud Giersch 	return parport_ip32_epp_read(priv->regs.eppData0, p, buf, len, flags);
11808e75f744SArnaud Giersch }
11818e75f744SArnaud Giersch 
11828e75f744SArnaud Giersch /**
11838e75f744SArnaud Giersch  * parport_ip32_epp_write_data - write a block of data in EPP mode
11848e75f744SArnaud Giersch  * @p:		pointer to &struct parport
11858e75f744SArnaud Giersch  * @buf:	buffer of data to write
11868e75f744SArnaud Giersch  * @len:	length of buffer @buf
11878e75f744SArnaud Giersch  * @flags:	may be PARPORT_EPP_FAST
11888e75f744SArnaud Giersch  */
parport_ip32_epp_write_data(struct parport * p,const void * buf,size_t len,int flags)11898e75f744SArnaud Giersch static size_t parport_ip32_epp_write_data(struct parport *p, const void *buf,
11908e75f744SArnaud Giersch 					  size_t len, int flags)
11918e75f744SArnaud Giersch {
11928e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
11938e75f744SArnaud Giersch 	return parport_ip32_epp_write(priv->regs.eppData0, p, buf, len, flags);
11948e75f744SArnaud Giersch }
11958e75f744SArnaud Giersch 
11968e75f744SArnaud Giersch /**
11978e75f744SArnaud Giersch  * parport_ip32_epp_read_addr - read a block of addresses in EPP mode
11988e75f744SArnaud Giersch  * @p:		pointer to &struct parport
11998e75f744SArnaud Giersch  * @buf:	buffer to store read data
12008e75f744SArnaud Giersch  * @len:	length of buffer @buf
12018e75f744SArnaud Giersch  * @flags:	may be PARPORT_EPP_FAST
12028e75f744SArnaud Giersch  */
parport_ip32_epp_read_addr(struct parport * p,void * buf,size_t len,int flags)12038e75f744SArnaud Giersch static size_t parport_ip32_epp_read_addr(struct parport *p, void *buf,
12048e75f744SArnaud Giersch 					 size_t len, int flags)
12058e75f744SArnaud Giersch {
12068e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
12078e75f744SArnaud Giersch 	return parport_ip32_epp_read(priv->regs.eppAddr, p, buf, len, flags);
12088e75f744SArnaud Giersch }
12098e75f744SArnaud Giersch 
12108e75f744SArnaud Giersch /**
12118e75f744SArnaud Giersch  * parport_ip32_epp_write_addr - write a block of addresses in EPP mode
12128e75f744SArnaud Giersch  * @p:		pointer to &struct parport
12138e75f744SArnaud Giersch  * @buf:	buffer of data to write
12148e75f744SArnaud Giersch  * @len:	length of buffer @buf
12158e75f744SArnaud Giersch  * @flags:	may be PARPORT_EPP_FAST
12168e75f744SArnaud Giersch  */
parport_ip32_epp_write_addr(struct parport * p,const void * buf,size_t len,int flags)12178e75f744SArnaud Giersch static size_t parport_ip32_epp_write_addr(struct parport *p, const void *buf,
12188e75f744SArnaud Giersch 					  size_t len, int flags)
12198e75f744SArnaud Giersch {
12208e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
12218e75f744SArnaud Giersch 	return parport_ip32_epp_write(priv->regs.eppAddr, p, buf, len, flags);
12228e75f744SArnaud Giersch }
12238e75f744SArnaud Giersch 
12248e75f744SArnaud Giersch /*--- ECP mode functions (FIFO) ----------------------------------------*/
12258e75f744SArnaud Giersch 
12268e75f744SArnaud Giersch /**
12278e75f744SArnaud Giersch  * parport_ip32_fifo_wait_break - check if the waiting function should return
12288e75f744SArnaud Giersch  * @p:		pointer to &struct parport
12298e75f744SArnaud Giersch  * @expire:	timeout expiring date, in jiffies
12308e75f744SArnaud Giersch  *
12318e75f744SArnaud Giersch  * parport_ip32_fifo_wait_break() checks if the waiting function should return
12328e75f744SArnaud Giersch  * immediately or not.  The break conditions are:
12338e75f744SArnaud Giersch  *	- expired timeout;
12348e75f744SArnaud Giersch  *	- a pending signal;
12358e75f744SArnaud Giersch  *	- nFault asserted low.
12368e75f744SArnaud Giersch  * This function also calls cond_resched().
12378e75f744SArnaud Giersch  */
parport_ip32_fifo_wait_break(struct parport * p,unsigned long expire)12388e75f744SArnaud Giersch static unsigned int parport_ip32_fifo_wait_break(struct parport *p,
12398e75f744SArnaud Giersch 						 unsigned long expire)
12408e75f744SArnaud Giersch {
12418e75f744SArnaud Giersch 	cond_resched();
12428e75f744SArnaud Giersch 	if (time_after(jiffies, expire)) {
12438e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: FIFO write timed out\n", p->name);
12448e75f744SArnaud Giersch 		return 1;
12458e75f744SArnaud Giersch 	}
12468e75f744SArnaud Giersch 	if (signal_pending(current)) {
12478e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: Signal pending\n", p->name);
12488e75f744SArnaud Giersch 		return 1;
12498e75f744SArnaud Giersch 	}
12508e75f744SArnaud Giersch 	if (!(parport_ip32_read_status(p) & DSR_nFAULT)) {
12518e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: nFault asserted low\n", p->name);
12528e75f744SArnaud Giersch 		return 1;
12538e75f744SArnaud Giersch 	}
12548e75f744SArnaud Giersch 	return 0;
12558e75f744SArnaud Giersch }
12568e75f744SArnaud Giersch 
12578e75f744SArnaud Giersch /**
12588e75f744SArnaud Giersch  * parport_ip32_fwp_wait_polling - wait for FIFO to empty (polling)
12598e75f744SArnaud Giersch  * @p:		pointer to &struct parport
12608e75f744SArnaud Giersch  *
12618e75f744SArnaud Giersch  * Returns the number of bytes that can safely be written in the FIFO.  A
12628e75f744SArnaud Giersch  * return value of zero means that the calling function should terminate as
12638e75f744SArnaud Giersch  * fast as possible.
12648e75f744SArnaud Giersch  */
parport_ip32_fwp_wait_polling(struct parport * p)12658e75f744SArnaud Giersch static unsigned int parport_ip32_fwp_wait_polling(struct parport *p)
12668e75f744SArnaud Giersch {
12678e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
12688e75f744SArnaud Giersch 	struct parport * const physport = p->physport;
12698e75f744SArnaud Giersch 	unsigned long expire;
12708e75f744SArnaud Giersch 	unsigned int count;
12718e75f744SArnaud Giersch 	unsigned int ecr;
12728e75f744SArnaud Giersch 
12738e75f744SArnaud Giersch 	expire = jiffies + physport->cad->timeout;
12748e75f744SArnaud Giersch 	count = 0;
12758e75f744SArnaud Giersch 	while (1) {
12768e75f744SArnaud Giersch 		if (parport_ip32_fifo_wait_break(p, expire))
12778e75f744SArnaud Giersch 			break;
12788e75f744SArnaud Giersch 
12798e75f744SArnaud Giersch 		/* Check FIFO state.  We do nothing when the FIFO is nor full,
12808e75f744SArnaud Giersch 		 * nor empty.  It appears that the FIFO full bit is not always
12818e75f744SArnaud Giersch 		 * reliable, the FIFO state is sometimes wrongly reported, and
12828e75f744SArnaud Giersch 		 * the chip gets confused if we give it another byte. */
12838e75f744SArnaud Giersch 		ecr = parport_ip32_read_econtrol(p);
12848e75f744SArnaud Giersch 		if (ecr & ECR_F_EMPTY) {
12858e75f744SArnaud Giersch 			/* FIFO is empty, fill it up */
12868e75f744SArnaud Giersch 			count = priv->fifo_depth;
12878e75f744SArnaud Giersch 			break;
12888e75f744SArnaud Giersch 		}
12898e75f744SArnaud Giersch 
12908e75f744SArnaud Giersch 		/* Wait a moment... */
12918e75f744SArnaud Giersch 		udelay(FIFO_POLLING_INTERVAL);
12928e75f744SArnaud Giersch 	} /* while (1) */
12938e75f744SArnaud Giersch 
12948e75f744SArnaud Giersch 	return count;
12958e75f744SArnaud Giersch }
12968e75f744SArnaud Giersch 
12978e75f744SArnaud Giersch /**
12988e75f744SArnaud Giersch  * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven)
12998e75f744SArnaud Giersch  * @p:		pointer to &struct parport
13008e75f744SArnaud Giersch  *
13018e75f744SArnaud Giersch  * Returns the number of bytes that can safely be written in the FIFO.  A
13028e75f744SArnaud Giersch  * return value of zero means that the calling function should terminate as
13038e75f744SArnaud Giersch  * fast as possible.
13048e75f744SArnaud Giersch  */
parport_ip32_fwp_wait_interrupt(struct parport * p)13058e75f744SArnaud Giersch static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p)
13068e75f744SArnaud Giersch {
13078e75f744SArnaud Giersch 	static unsigned int lost_interrupt = 0;
13088e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
13098e75f744SArnaud Giersch 	struct parport * const physport = p->physport;
13108e75f744SArnaud Giersch 	unsigned long nfault_timeout;
13118e75f744SArnaud Giersch 	unsigned long expire;
13128e75f744SArnaud Giersch 	unsigned int count;
13138e75f744SArnaud Giersch 	unsigned int ecr;
13148e75f744SArnaud Giersch 
13158e75f744SArnaud Giersch 	nfault_timeout = min((unsigned long)physport->cad->timeout,
13168e75f744SArnaud Giersch 			     msecs_to_jiffies(FIFO_NFAULT_TIMEOUT));
13178e75f744SArnaud Giersch 	expire = jiffies + physport->cad->timeout;
13188e75f744SArnaud Giersch 	count = 0;
13198e75f744SArnaud Giersch 	while (1) {
13208e75f744SArnaud Giersch 		if (parport_ip32_fifo_wait_break(p, expire))
13218e75f744SArnaud Giersch 			break;
13228e75f744SArnaud Giersch 
13238e75f744SArnaud Giersch 		/* Initialize mutex used to take interrupts into account */
132416735d02SWolfram Sang 		reinit_completion(&priv->irq_complete);
13258e75f744SArnaud Giersch 
13268e75f744SArnaud Giersch 		/* Enable serviceIntr */
13278e75f744SArnaud Giersch 		parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
13288e75f744SArnaud Giersch 
13298e75f744SArnaud Giersch 		/* Enabling serviceIntr while the FIFO is empty does not
13308e75f744SArnaud Giersch 		 * always generate an interrupt, so check for emptiness
13318e75f744SArnaud Giersch 		 * now. */
13328e75f744SArnaud Giersch 		ecr = parport_ip32_read_econtrol(p);
13338e75f744SArnaud Giersch 		if (!(ecr & ECR_F_EMPTY)) {
13348e75f744SArnaud Giersch 			/* FIFO is not empty: wait for an interrupt or a
13358e75f744SArnaud Giersch 			 * timeout to occur */
13368e75f744SArnaud Giersch 			wait_for_completion_interruptible_timeout(
13378e75f744SArnaud Giersch 				&priv->irq_complete, nfault_timeout);
13388e75f744SArnaud Giersch 			ecr = parport_ip32_read_econtrol(p);
13398e75f744SArnaud Giersch 			if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR)
13408e75f744SArnaud Giersch 			    && !lost_interrupt) {
1341decf26f6SJoe Perches 				pr_warn(PPIP32 "%s: lost interrupt in %s\n",
13428e75f744SArnaud Giersch 					p->name, __func__);
13438e75f744SArnaud Giersch 				lost_interrupt = 1;
13448e75f744SArnaud Giersch 			}
13458e75f744SArnaud Giersch 		}
13468e75f744SArnaud Giersch 
13478e75f744SArnaud Giersch 		/* Disable serviceIntr */
13488e75f744SArnaud Giersch 		parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR);
13498e75f744SArnaud Giersch 
13508e75f744SArnaud Giersch 		/* Check FIFO state */
13518e75f744SArnaud Giersch 		if (ecr & ECR_F_EMPTY) {
13528e75f744SArnaud Giersch 			/* FIFO is empty, fill it up */
13538e75f744SArnaud Giersch 			count = priv->fifo_depth;
13548e75f744SArnaud Giersch 			break;
13558e75f744SArnaud Giersch 		} else if (ecr & ECR_SERVINTR) {
13568e75f744SArnaud Giersch 			/* FIFO is not empty, but we know that can safely push
13578e75f744SArnaud Giersch 			 * writeIntrThreshold bytes into it */
13588e75f744SArnaud Giersch 			count = priv->writeIntrThreshold;
13598e75f744SArnaud Giersch 			break;
13608e75f744SArnaud Giersch 		}
13618e75f744SArnaud Giersch 		/* FIFO is not empty, and we did not get any interrupt.
13628e75f744SArnaud Giersch 		 * Either it's time to check for nFault, or a signal is
13638e75f744SArnaud Giersch 		 * pending.  This is verified in
13648e75f744SArnaud Giersch 		 * parport_ip32_fifo_wait_break(), so we continue the loop. */
13658e75f744SArnaud Giersch 	} /* while (1) */
13668e75f744SArnaud Giersch 
13678e75f744SArnaud Giersch 	return count;
13688e75f744SArnaud Giersch }
13698e75f744SArnaud Giersch 
13708e75f744SArnaud Giersch /**
13718e75f744SArnaud Giersch  * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode)
13728e75f744SArnaud Giersch  * @p:		pointer to &struct parport
13738e75f744SArnaud Giersch  * @buf:	buffer of data to write
13748e75f744SArnaud Giersch  * @len:	length of buffer @buf
13758e75f744SArnaud Giersch  *
13768e75f744SArnaud Giersch  * Uses PIO to write the contents of the buffer @buf into the parallel port
13778e75f744SArnaud Giersch  * FIFO.  Returns the number of bytes that were actually written.  It can work
13788e75f744SArnaud Giersch  * with or without the help of interrupts.  The parallel port must be
13798e75f744SArnaud Giersch  * correctly initialized before calling parport_ip32_fifo_write_block_pio().
13808e75f744SArnaud Giersch  */
parport_ip32_fifo_write_block_pio(struct parport * p,const void * buf,size_t len)13818e75f744SArnaud Giersch static size_t parport_ip32_fifo_write_block_pio(struct parport *p,
13828e75f744SArnaud Giersch 						const void *buf, size_t len)
13838e75f744SArnaud Giersch {
13848e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
13858e75f744SArnaud Giersch 	const u8 *bufp = buf;
13868e75f744SArnaud Giersch 	size_t left = len;
13878e75f744SArnaud Giersch 
13888e75f744SArnaud Giersch 	priv->irq_mode = PARPORT_IP32_IRQ_HERE;
13898e75f744SArnaud Giersch 
13908e75f744SArnaud Giersch 	while (left > 0) {
13918e75f744SArnaud Giersch 		unsigned int count;
13928e75f744SArnaud Giersch 
13938e75f744SArnaud Giersch 		count = (p->irq == PARPORT_IRQ_NONE) ?
13948e75f744SArnaud Giersch 			parport_ip32_fwp_wait_polling(p) :
13958e75f744SArnaud Giersch 			parport_ip32_fwp_wait_interrupt(p);
13968e75f744SArnaud Giersch 		if (count == 0)
13978e75f744SArnaud Giersch 			break;	/* Transmission should be stopped */
13988e75f744SArnaud Giersch 		if (count > left)
13998e75f744SArnaud Giersch 			count = left;
14008e75f744SArnaud Giersch 		if (count == 1) {
14018e75f744SArnaud Giersch 			writeb(*bufp, priv->regs.fifo);
14028e75f744SArnaud Giersch 			bufp++, left--;
14038e75f744SArnaud Giersch 		} else {
14048e75f744SArnaud Giersch 			writesb(priv->regs.fifo, bufp, count);
14058e75f744SArnaud Giersch 			bufp += count, left -= count;
14068e75f744SArnaud Giersch 		}
14078e75f744SArnaud Giersch 	}
14088e75f744SArnaud Giersch 
14098e75f744SArnaud Giersch 	priv->irq_mode = PARPORT_IP32_IRQ_FWD;
14108e75f744SArnaud Giersch 
14118e75f744SArnaud Giersch 	return len - left;
14128e75f744SArnaud Giersch }
14138e75f744SArnaud Giersch 
14148e75f744SArnaud Giersch /**
14158e75f744SArnaud Giersch  * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode)
14168e75f744SArnaud Giersch  * @p:		pointer to &struct parport
14178e75f744SArnaud Giersch  * @buf:	buffer of data to write
14188e75f744SArnaud Giersch  * @len:	length of buffer @buf
14198e75f744SArnaud Giersch  *
14208e75f744SArnaud Giersch  * Uses DMA to write the contents of the buffer @buf into the parallel port
14218e75f744SArnaud Giersch  * FIFO.  Returns the number of bytes that were actually written.  The
14228e75f744SArnaud Giersch  * parallel port must be correctly initialized before calling
14238e75f744SArnaud Giersch  * parport_ip32_fifo_write_block_dma().
14248e75f744SArnaud Giersch  */
parport_ip32_fifo_write_block_dma(struct parport * p,const void * buf,size_t len)14258e75f744SArnaud Giersch static size_t parport_ip32_fifo_write_block_dma(struct parport *p,
14268e75f744SArnaud Giersch 						const void *buf, size_t len)
14278e75f744SArnaud Giersch {
14288e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
14298e75f744SArnaud Giersch 	struct parport * const physport = p->physport;
14308e75f744SArnaud Giersch 	unsigned long nfault_timeout;
14318e75f744SArnaud Giersch 	unsigned long expire;
14328e75f744SArnaud Giersch 	size_t written;
14338e75f744SArnaud Giersch 	unsigned int ecr;
14348e75f744SArnaud Giersch 
14358e75f744SArnaud Giersch 	priv->irq_mode = PARPORT_IP32_IRQ_HERE;
14368e75f744SArnaud Giersch 
14374217efa3SChristoph Hellwig 	parport_ip32_dma_start(p, DMA_TO_DEVICE, (void *)buf, len);
143816735d02SWolfram Sang 	reinit_completion(&priv->irq_complete);
14398e75f744SArnaud Giersch 	parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN);
14408e75f744SArnaud Giersch 
14418e75f744SArnaud Giersch 	nfault_timeout = min((unsigned long)physport->cad->timeout,
14428e75f744SArnaud Giersch 			     msecs_to_jiffies(FIFO_NFAULT_TIMEOUT));
14438e75f744SArnaud Giersch 	expire = jiffies + physport->cad->timeout;
14448e75f744SArnaud Giersch 	while (1) {
14458e75f744SArnaud Giersch 		if (parport_ip32_fifo_wait_break(p, expire))
14468e75f744SArnaud Giersch 			break;
14478e75f744SArnaud Giersch 		wait_for_completion_interruptible_timeout(&priv->irq_complete,
14488e75f744SArnaud Giersch 							  nfault_timeout);
14498e75f744SArnaud Giersch 		ecr = parport_ip32_read_econtrol(p);
14508e75f744SArnaud Giersch 		if (ecr & ECR_SERVINTR)
14518e75f744SArnaud Giersch 			break;	/* DMA transfer just finished */
14528e75f744SArnaud Giersch 	}
14534217efa3SChristoph Hellwig 	parport_ip32_dma_stop(p);
14548e75f744SArnaud Giersch 	written = len - parport_ip32_dma_get_residue();
14558e75f744SArnaud Giersch 
14568e75f744SArnaud Giersch 	priv->irq_mode = PARPORT_IP32_IRQ_FWD;
14578e75f744SArnaud Giersch 
14588e75f744SArnaud Giersch 	return written;
14598e75f744SArnaud Giersch }
14608e75f744SArnaud Giersch 
14618e75f744SArnaud Giersch /**
14628e75f744SArnaud Giersch  * parport_ip32_fifo_write_block - write a block of data
14638e75f744SArnaud Giersch  * @p:		pointer to &struct parport
14648e75f744SArnaud Giersch  * @buf:	buffer of data to write
14658e75f744SArnaud Giersch  * @len:	length of buffer @buf
14668e75f744SArnaud Giersch  *
14678e75f744SArnaud Giersch  * Uses PIO or DMA to write the contents of the buffer @buf into the parallel
14688e75f744SArnaud Giersch  * p FIFO.  Returns the number of bytes that were actually written.
14698e75f744SArnaud Giersch  */
parport_ip32_fifo_write_block(struct parport * p,const void * buf,size_t len)14708e75f744SArnaud Giersch static size_t parport_ip32_fifo_write_block(struct parport *p,
14718e75f744SArnaud Giersch 					    const void *buf, size_t len)
14728e75f744SArnaud Giersch {
14738e75f744SArnaud Giersch 	size_t written = 0;
14748e75f744SArnaud Giersch 	if (len)
14758e75f744SArnaud Giersch 		/* FIXME - Maybe some threshold value should be set for @len
14768e75f744SArnaud Giersch 		 * under which we revert to PIO mode? */
14778e75f744SArnaud Giersch 		written = (p->modes & PARPORT_MODE_DMA) ?
14788e75f744SArnaud Giersch 			parport_ip32_fifo_write_block_dma(p, buf, len) :
14798e75f744SArnaud Giersch 			parport_ip32_fifo_write_block_pio(p, buf, len);
14808e75f744SArnaud Giersch 	return written;
14818e75f744SArnaud Giersch }
14828e75f744SArnaud Giersch 
14838e75f744SArnaud Giersch /**
14848e75f744SArnaud Giersch  * parport_ip32_drain_fifo - wait for FIFO to empty
14858e75f744SArnaud Giersch  * @p:		pointer to &struct parport
14868e75f744SArnaud Giersch  * @timeout:	timeout, in jiffies
14878e75f744SArnaud Giersch  *
14888e75f744SArnaud Giersch  * This function waits for FIFO to empty.  It returns 1 when FIFO is empty, or
14898e75f744SArnaud Giersch  * 0 if the timeout @timeout is reached before, or if a signal is pending.
14908e75f744SArnaud Giersch  */
parport_ip32_drain_fifo(struct parport * p,unsigned long timeout)14918e75f744SArnaud Giersch static unsigned int parport_ip32_drain_fifo(struct parport *p,
14928e75f744SArnaud Giersch 					    unsigned long timeout)
14938e75f744SArnaud Giersch {
14948e75f744SArnaud Giersch 	unsigned long expire = jiffies + timeout;
14958e75f744SArnaud Giersch 	unsigned int polling_interval;
14968e75f744SArnaud Giersch 	unsigned int counter;
14978e75f744SArnaud Giersch 
14988e75f744SArnaud Giersch 	/* Busy wait for approx. 200us */
14998e75f744SArnaud Giersch 	for (counter = 0; counter < 40; counter++) {
15008e75f744SArnaud Giersch 		if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY)
15018e75f744SArnaud Giersch 			break;
15028e75f744SArnaud Giersch 		if (time_after(jiffies, expire))
15038e75f744SArnaud Giersch 			break;
15048e75f744SArnaud Giersch 		if (signal_pending(current))
15058e75f744SArnaud Giersch 			break;
15068e75f744SArnaud Giersch 		udelay(5);
15078e75f744SArnaud Giersch 	}
15088e75f744SArnaud Giersch 	/* Poll slowly.  Polling interval starts with 1 millisecond, and is
15098e75f744SArnaud Giersch 	 * increased exponentially until 128.  */
15108e75f744SArnaud Giersch 	polling_interval = 1; /* msecs */
15118e75f744SArnaud Giersch 	while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) {
15128e75f744SArnaud Giersch 		if (time_after_eq(jiffies, expire))
15138e75f744SArnaud Giersch 			break;
15148e75f744SArnaud Giersch 		msleep_interruptible(polling_interval);
15158e75f744SArnaud Giersch 		if (signal_pending(current))
15168e75f744SArnaud Giersch 			break;
15178e75f744SArnaud Giersch 		if (polling_interval < 128)
15188e75f744SArnaud Giersch 			polling_interval *= 2;
15198e75f744SArnaud Giersch 	}
15208e75f744SArnaud Giersch 
15218e75f744SArnaud Giersch 	return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY);
15228e75f744SArnaud Giersch }
15238e75f744SArnaud Giersch 
15248e75f744SArnaud Giersch /**
15258e75f744SArnaud Giersch  * parport_ip32_get_fifo_residue - reset FIFO
15268e75f744SArnaud Giersch  * @p:		pointer to &struct parport
15278e75f744SArnaud Giersch  * @mode:	current operation mode (ECR_MODE_PPF or ECR_MODE_ECP)
15288e75f744SArnaud Giersch  *
15298e75f744SArnaud Giersch  * This function resets FIFO, and returns the number of bytes remaining in it.
15308e75f744SArnaud Giersch  */
parport_ip32_get_fifo_residue(struct parport * p,unsigned int mode)15318e75f744SArnaud Giersch static unsigned int parport_ip32_get_fifo_residue(struct parport *p,
15328e75f744SArnaud Giersch 						  unsigned int mode)
15338e75f744SArnaud Giersch {
15348e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
15358e75f744SArnaud Giersch 	unsigned int residue;
15368e75f744SArnaud Giersch 	unsigned int cnfga;
15378e75f744SArnaud Giersch 
15388e75f744SArnaud Giersch 	/* FIXME - We are missing one byte if the printer is off-line.  I
15398e75f744SArnaud Giersch 	 * don't know how to detect this.  It looks that the full bit is not
15408e75f744SArnaud Giersch 	 * always reliable.  For the moment, the problem is avoided in most
15418e75f744SArnaud Giersch 	 * cases by testing for BUSY in parport_ip32_compat_write_data().
15428e75f744SArnaud Giersch 	 */
15438e75f744SArnaud Giersch 	if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY)
15448e75f744SArnaud Giersch 		residue = 0;
15458e75f744SArnaud Giersch 	else {
15468e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name);
15478e75f744SArnaud Giersch 
15488e75f744SArnaud Giersch 		/* Stop all transfers.
15498e75f744SArnaud Giersch 		 *
15508e75f744SArnaud Giersch 		 * Microsoft's document instructs to drive DCR_STROBE to 0,
15518e75f744SArnaud Giersch 		 * but it doesn't work (at least in Compatibility mode, not
15528e75f744SArnaud Giersch 		 * tested in ECP mode).  Switching directly to Test mode (as
15538e75f744SArnaud Giersch 		 * in parport_pc) is not an option: it does confuse the port,
15548e75f744SArnaud Giersch 		 * ECP service interrupts are no more working after that.  A
15558e75f744SArnaud Giersch 		 * hard reset is then needed to revert to a sane state.
15568e75f744SArnaud Giersch 		 *
15578e75f744SArnaud Giersch 		 * Let's hope that the FIFO is really stuck and that the
15588e75f744SArnaud Giersch 		 * peripheral doesn't wake up now.
15598e75f744SArnaud Giersch 		 */
15608e75f744SArnaud Giersch 		parport_ip32_frob_control(p, DCR_STROBE, 0);
15618e75f744SArnaud Giersch 
15628e75f744SArnaud Giersch 		/* Fill up FIFO */
15638e75f744SArnaud Giersch 		for (residue = priv->fifo_depth; residue > 0; residue--) {
15648e75f744SArnaud Giersch 			if (parport_ip32_read_econtrol(p) & ECR_F_FULL)
15658e75f744SArnaud Giersch 				break;
15668e75f744SArnaud Giersch 			writeb(0x00, priv->regs.fifo);
15678e75f744SArnaud Giersch 		}
15688e75f744SArnaud Giersch 	}
15698e75f744SArnaud Giersch 	if (residue)
15708e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n",
15718e75f744SArnaud Giersch 			  p->name, residue,
15728e75f744SArnaud Giersch 			  (residue == 1) ? " was" : "s were");
15738e75f744SArnaud Giersch 
15748e75f744SArnaud Giersch 	/* Now reset the FIFO */
15758e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
15768e75f744SArnaud Giersch 
15778e75f744SArnaud Giersch 	/* Host recovery for ECP mode */
15788e75f744SArnaud Giersch 	if (mode == ECR_MODE_ECP) {
15798e75f744SArnaud Giersch 		parport_ip32_data_reverse(p);
15808e75f744SArnaud Giersch 		parport_ip32_frob_control(p, DCR_nINIT, 0);
15818e75f744SArnaud Giersch 		if (parport_wait_peripheral(p, DSR_PERROR, 0))
15828e75f744SArnaud Giersch 			pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n",
15838e75f744SArnaud Giersch 				  p->name, __func__);
15848e75f744SArnaud Giersch 		parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE);
15858e75f744SArnaud Giersch 		parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT);
15868e75f744SArnaud Giersch 		if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR))
15878e75f744SArnaud Giersch 			pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n",
15888e75f744SArnaud Giersch 				  p->name, __func__);
15898e75f744SArnaud Giersch 	}
15908e75f744SArnaud Giersch 
15918e75f744SArnaud Giersch 	/* Adjust residue if needed */
15928e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_CFG);
15938e75f744SArnaud Giersch 	cnfga = readb(priv->regs.cnfgA);
15948e75f744SArnaud Giersch 	if (!(cnfga & CNFGA_nBYTEINTRANS)) {
15958e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n",
15968e75f744SArnaud Giersch 			  p->name, cnfga);
15978e75f744SArnaud Giersch 		pr_debug1(PPIP32 "%s: Accounting for extra byte\n",
15988e75f744SArnaud Giersch 			  p->name);
15998e75f744SArnaud Giersch 		residue++;
16008e75f744SArnaud Giersch 	}
16018e75f744SArnaud Giersch 
16028e75f744SArnaud Giersch 	/* Don't care about partial PWords since we do not support
16038e75f744SArnaud Giersch 	 * PWord != 1 byte. */
16048e75f744SArnaud Giersch 
16058e75f744SArnaud Giersch 	/* Back to forward PS2 mode. */
16068e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
16078e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
16088e75f744SArnaud Giersch 
16098e75f744SArnaud Giersch 	return residue;
16108e75f744SArnaud Giersch }
16118e75f744SArnaud Giersch 
16128e75f744SArnaud Giersch /**
16138e75f744SArnaud Giersch  * parport_ip32_compat_write_data - write a block of data in SPP mode
16148e75f744SArnaud Giersch  * @p:		pointer to &struct parport
16158e75f744SArnaud Giersch  * @buf:	buffer of data to write
16168e75f744SArnaud Giersch  * @len:	length of buffer @buf
16178e75f744SArnaud Giersch  * @flags:	ignored
16188e75f744SArnaud Giersch  */
parport_ip32_compat_write_data(struct parport * p,const void * buf,size_t len,int flags)16198e75f744SArnaud Giersch static size_t parport_ip32_compat_write_data(struct parport *p,
16208e75f744SArnaud Giersch 					     const void *buf, size_t len,
16218e75f744SArnaud Giersch 					     int flags)
16228e75f744SArnaud Giersch {
16238e75f744SArnaud Giersch 	static unsigned int ready_before = 1;
16248e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
16258e75f744SArnaud Giersch 	struct parport * const physport = p->physport;
16268e75f744SArnaud Giersch 	size_t written = 0;
16278e75f744SArnaud Giersch 
16288e75f744SArnaud Giersch 	/* Special case: a timeout of zero means we cannot call schedule().
16298e75f744SArnaud Giersch 	 * Also if O_NONBLOCK is set then use the default implementation. */
16308e75f744SArnaud Giersch 	if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
16318e75f744SArnaud Giersch 		return parport_ieee1284_write_compat(p, buf, len, flags);
16328e75f744SArnaud Giersch 
16338e75f744SArnaud Giersch 	/* Reset FIFO, go in forward mode, and disable ackIntEn */
16348e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
16358e75f744SArnaud Giersch 	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
16368e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
16378e75f744SArnaud Giersch 	parport_ip32_disable_irq(p);
16388e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PPF);
16398e75f744SArnaud Giersch 	physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
16408e75f744SArnaud Giersch 
16418e75f744SArnaud Giersch 	/* Wait for peripheral to become ready */
16428e75f744SArnaud Giersch 	if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT,
16438e75f744SArnaud Giersch 				       DSR_nBUSY | DSR_nFAULT)) {
16448e75f744SArnaud Giersch 		/* Avoid to flood the logs */
16458e75f744SArnaud Giersch 		if (ready_before)
1646decf26f6SJoe Perches 			pr_info(PPIP32 "%s: not ready in %s\n",
16478e75f744SArnaud Giersch 				p->name, __func__);
16488e75f744SArnaud Giersch 		ready_before = 0;
16498e75f744SArnaud Giersch 		goto stop;
16508e75f744SArnaud Giersch 	}
16518e75f744SArnaud Giersch 	ready_before = 1;
16528e75f744SArnaud Giersch 
16538e75f744SArnaud Giersch 	written = parport_ip32_fifo_write_block(p, buf, len);
16548e75f744SArnaud Giersch 
16558e75f744SArnaud Giersch 	/* Wait FIFO to empty.  Timeout is proportional to FIFO_depth.  */
16568e75f744SArnaud Giersch 	parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth);
16578e75f744SArnaud Giersch 
16588e75f744SArnaud Giersch 	/* Check for a potential residue */
16598e75f744SArnaud Giersch 	written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF);
16608e75f744SArnaud Giersch 
16618e75f744SArnaud Giersch 	/* Then, wait for BUSY to get low. */
16628e75f744SArnaud Giersch 	if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY))
16638e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n",
16648e75f744SArnaud Giersch 		       p->name, __func__);
16658e75f744SArnaud Giersch 
16668e75f744SArnaud Giersch stop:
16678e75f744SArnaud Giersch 	/* Reset FIFO */
16688e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
16698e75f744SArnaud Giersch 	physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
16708e75f744SArnaud Giersch 
16718e75f744SArnaud Giersch 	return written;
16728e75f744SArnaud Giersch }
16738e75f744SArnaud Giersch 
16748e75f744SArnaud Giersch /*
16758e75f744SArnaud Giersch  * FIXME - Insert here parport_ip32_ecp_read_data().
16768e75f744SArnaud Giersch  */
16778e75f744SArnaud Giersch 
16788e75f744SArnaud Giersch /**
16798e75f744SArnaud Giersch  * parport_ip32_ecp_write_data - write a block of data in ECP mode
16808e75f744SArnaud Giersch  * @p:		pointer to &struct parport
16818e75f744SArnaud Giersch  * @buf:	buffer of data to write
16828e75f744SArnaud Giersch  * @len:	length of buffer @buf
16838e75f744SArnaud Giersch  * @flags:	ignored
16848e75f744SArnaud Giersch  */
parport_ip32_ecp_write_data(struct parport * p,const void * buf,size_t len,int flags)16858e75f744SArnaud Giersch static size_t parport_ip32_ecp_write_data(struct parport *p,
16868e75f744SArnaud Giersch 					  const void *buf, size_t len,
16878e75f744SArnaud Giersch 					  int flags)
16888e75f744SArnaud Giersch {
16898e75f744SArnaud Giersch 	static unsigned int ready_before = 1;
16908e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
16918e75f744SArnaud Giersch 	struct parport * const physport = p->physport;
16928e75f744SArnaud Giersch 	size_t written = 0;
16938e75f744SArnaud Giersch 
16948e75f744SArnaud Giersch 	/* Special case: a timeout of zero means we cannot call schedule().
16958e75f744SArnaud Giersch 	 * Also if O_NONBLOCK is set then use the default implementation. */
16968e75f744SArnaud Giersch 	if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK)
16978e75f744SArnaud Giersch 		return parport_ieee1284_ecp_write_data(p, buf, len, flags);
16988e75f744SArnaud Giersch 
16998e75f744SArnaud Giersch 	/* Negotiate to forward mode if necessary. */
17008e75f744SArnaud Giersch 	if (physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
17018e75f744SArnaud Giersch 		/* Event 47: Set nInit high. */
17028e75f744SArnaud Giersch 		parport_ip32_frob_control(p, DCR_nINIT | DCR_AUTOFD,
17038e75f744SArnaud Giersch 					     DCR_nINIT | DCR_AUTOFD);
17048e75f744SArnaud Giersch 
17058e75f744SArnaud Giersch 		/* Event 49: PError goes high. */
17068e75f744SArnaud Giersch 		if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) {
1707*aa3d6e7cSJoe Perches 			printk(KERN_DEBUG PPIP32 "%s: PError timeout in %s\n",
17088e75f744SArnaud Giersch 			       p->name, __func__);
17098e75f744SArnaud Giersch 			physport->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
17108e75f744SArnaud Giersch 			return 0;
17118e75f744SArnaud Giersch 		}
17128e75f744SArnaud Giersch 	}
17138e75f744SArnaud Giersch 
17148e75f744SArnaud Giersch 	/* Reset FIFO, go in forward mode, and disable ackIntEn */
17158e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
17168e75f744SArnaud Giersch 	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
17178e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
17188e75f744SArnaud Giersch 	parport_ip32_disable_irq(p);
17198e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_ECP);
17208e75f744SArnaud Giersch 	physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
17218e75f744SArnaud Giersch 
17228e75f744SArnaud Giersch 	/* Wait for peripheral to become ready */
17238e75f744SArnaud Giersch 	if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT,
17248e75f744SArnaud Giersch 				       DSR_nBUSY | DSR_nFAULT)) {
17258e75f744SArnaud Giersch 		/* Avoid to flood the logs */
17268e75f744SArnaud Giersch 		if (ready_before)
1727decf26f6SJoe Perches 			pr_info(PPIP32 "%s: not ready in %s\n",
17288e75f744SArnaud Giersch 				p->name, __func__);
17298e75f744SArnaud Giersch 		ready_before = 0;
17308e75f744SArnaud Giersch 		goto stop;
17318e75f744SArnaud Giersch 	}
17328e75f744SArnaud Giersch 	ready_before = 1;
17338e75f744SArnaud Giersch 
17348e75f744SArnaud Giersch 	written = parport_ip32_fifo_write_block(p, buf, len);
17358e75f744SArnaud Giersch 
17368e75f744SArnaud Giersch 	/* Wait FIFO to empty.  Timeout is proportional to FIFO_depth.  */
17378e75f744SArnaud Giersch 	parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth);
17388e75f744SArnaud Giersch 
17398e75f744SArnaud Giersch 	/* Check for a potential residue */
17408e75f744SArnaud Giersch 	written -= parport_ip32_get_fifo_residue(p, ECR_MODE_ECP);
17418e75f744SArnaud Giersch 
17428e75f744SArnaud Giersch 	/* Then, wait for BUSY to get low. */
17438e75f744SArnaud Giersch 	if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY))
17448e75f744SArnaud Giersch 		printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n",
17458e75f744SArnaud Giersch 		       p->name, __func__);
17468e75f744SArnaud Giersch 
17478e75f744SArnaud Giersch stop:
17488e75f744SArnaud Giersch 	/* Reset FIFO */
17498e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
17508e75f744SArnaud Giersch 	physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
17518e75f744SArnaud Giersch 
17528e75f744SArnaud Giersch 	return written;
17538e75f744SArnaud Giersch }
17548e75f744SArnaud Giersch 
17558e75f744SArnaud Giersch /*
17568e75f744SArnaud Giersch  * FIXME - Insert here parport_ip32_ecp_write_addr().
17578e75f744SArnaud Giersch  */
17588e75f744SArnaud Giersch 
17598e75f744SArnaud Giersch /*--- Default parport operations ---------------------------------------*/
17608e75f744SArnaud Giersch 
1761c932806cSBhumika Goyal static const struct parport_operations parport_ip32_ops __initconst = {
17628e75f744SArnaud Giersch 	.write_data		= parport_ip32_write_data,
17638e75f744SArnaud Giersch 	.read_data		= parport_ip32_read_data,
17648e75f744SArnaud Giersch 
17658e75f744SArnaud Giersch 	.write_control		= parport_ip32_write_control,
17668e75f744SArnaud Giersch 	.read_control		= parport_ip32_read_control,
17678e75f744SArnaud Giersch 	.frob_control		= parport_ip32_frob_control,
17688e75f744SArnaud Giersch 
17698e75f744SArnaud Giersch 	.read_status		= parport_ip32_read_status,
17708e75f744SArnaud Giersch 
17718e75f744SArnaud Giersch 	.enable_irq		= parport_ip32_enable_irq,
17728e75f744SArnaud Giersch 	.disable_irq		= parport_ip32_disable_irq,
17738e75f744SArnaud Giersch 
17748e75f744SArnaud Giersch 	.data_forward		= parport_ip32_data_forward,
17758e75f744SArnaud Giersch 	.data_reverse		= parport_ip32_data_reverse,
17768e75f744SArnaud Giersch 
17778e75f744SArnaud Giersch 	.init_state		= parport_ip32_init_state,
17788e75f744SArnaud Giersch 	.save_state		= parport_ip32_save_state,
17798e75f744SArnaud Giersch 	.restore_state		= parport_ip32_restore_state,
17808e75f744SArnaud Giersch 
17818e75f744SArnaud Giersch 	.epp_write_data		= parport_ieee1284_epp_write_data,
17828e75f744SArnaud Giersch 	.epp_read_data		= parport_ieee1284_epp_read_data,
17838e75f744SArnaud Giersch 	.epp_write_addr		= parport_ieee1284_epp_write_addr,
17848e75f744SArnaud Giersch 	.epp_read_addr		= parport_ieee1284_epp_read_addr,
17858e75f744SArnaud Giersch 
17868e75f744SArnaud Giersch 	.ecp_write_data		= parport_ieee1284_ecp_write_data,
17878e75f744SArnaud Giersch 	.ecp_read_data		= parport_ieee1284_ecp_read_data,
17888e75f744SArnaud Giersch 	.ecp_write_addr		= parport_ieee1284_ecp_write_addr,
17898e75f744SArnaud Giersch 
17908e75f744SArnaud Giersch 	.compat_write_data	= parport_ieee1284_write_compat,
17918e75f744SArnaud Giersch 	.nibble_read_data	= parport_ieee1284_read_nibble,
17928e75f744SArnaud Giersch 	.byte_read_data		= parport_ieee1284_read_byte,
17938e75f744SArnaud Giersch 
17948e75f744SArnaud Giersch 	.owner			= THIS_MODULE,
17958e75f744SArnaud Giersch };
17968e75f744SArnaud Giersch 
17978e75f744SArnaud Giersch /*--- Device detection -------------------------------------------------*/
17988e75f744SArnaud Giersch 
17998e75f744SArnaud Giersch /**
18008e75f744SArnaud Giersch  * parport_ip32_ecp_supported - check for an ECP port
18018e75f744SArnaud Giersch  * @p:		pointer to the &parport structure
18028e75f744SArnaud Giersch  *
18038e75f744SArnaud Giersch  * Returns 1 if an ECP port is found, and 0 otherwise.  This function actually
18048e75f744SArnaud Giersch  * checks if an Extended Control Register seems to be present.  On successful
18058e75f744SArnaud Giersch  * return, the port is placed in SPP mode.
18068e75f744SArnaud Giersch  */
parport_ip32_ecp_supported(struct parport * p)18078e75f744SArnaud Giersch static __init unsigned int parport_ip32_ecp_supported(struct parport *p)
18088e75f744SArnaud Giersch {
18098e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
18108e75f744SArnaud Giersch 	unsigned int ecr;
18118e75f744SArnaud Giersch 
18128e75f744SArnaud Giersch 	ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR;
18138e75f744SArnaud Giersch 	writeb(ecr, priv->regs.ecr);
18148e75f744SArnaud Giersch 	if (readb(priv->regs.ecr) != (ecr | ECR_F_EMPTY))
18158e75f744SArnaud Giersch 		goto fail;
18168e75f744SArnaud Giersch 
18178e75f744SArnaud Giersch 	pr_probe(p, "Found working ECR register\n");
18188e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_SPP);
18198e75f744SArnaud Giersch 	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
18208e75f744SArnaud Giersch 	return 1;
18218e75f744SArnaud Giersch 
18228e75f744SArnaud Giersch fail:
18238e75f744SArnaud Giersch 	pr_probe(p, "ECR register not found\n");
18248e75f744SArnaud Giersch 	return 0;
18258e75f744SArnaud Giersch }
18268e75f744SArnaud Giersch 
18278e75f744SArnaud Giersch /**
18288e75f744SArnaud Giersch  * parport_ip32_fifo_supported - check for FIFO parameters
18298e75f744SArnaud Giersch  * @p:		pointer to the &parport structure
18308e75f744SArnaud Giersch  *
18318e75f744SArnaud Giersch  * Check for FIFO parameters of an Extended Capabilities Port.  Returns 1 on
18328e75f744SArnaud Giersch  * success, and 0 otherwise.  Adjust FIFO parameters in the parport structure.
18338e75f744SArnaud Giersch  * On return, the port is placed in SPP mode.
18348e75f744SArnaud Giersch  */
parport_ip32_fifo_supported(struct parport * p)18358e75f744SArnaud Giersch static __init unsigned int parport_ip32_fifo_supported(struct parport *p)
18368e75f744SArnaud Giersch {
18378e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
18388e75f744SArnaud Giersch 	unsigned int configa, configb;
18398e75f744SArnaud Giersch 	unsigned int pword;
18408e75f744SArnaud Giersch 	unsigned int i;
18418e75f744SArnaud Giersch 
18428e75f744SArnaud Giersch 	/* Configuration mode */
18438e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_CFG);
18448e75f744SArnaud Giersch 	configa = readb(priv->regs.cnfgA);
18458e75f744SArnaud Giersch 	configb = readb(priv->regs.cnfgB);
18468e75f744SArnaud Giersch 
18478e75f744SArnaud Giersch 	/* Find out PWord size */
18488e75f744SArnaud Giersch 	switch (configa & CNFGA_ID_MASK) {
18498e75f744SArnaud Giersch 	case CNFGA_ID_8:
18508e75f744SArnaud Giersch 		pword = 1;
18518e75f744SArnaud Giersch 		break;
18528e75f744SArnaud Giersch 	case CNFGA_ID_16:
18538e75f744SArnaud Giersch 		pword = 2;
18548e75f744SArnaud Giersch 		break;
18558e75f744SArnaud Giersch 	case CNFGA_ID_32:
18568e75f744SArnaud Giersch 		pword = 4;
18578e75f744SArnaud Giersch 		break;
18588e75f744SArnaud Giersch 	default:
18598e75f744SArnaud Giersch 		pr_probe(p, "Unknown implementation ID: 0x%0x\n",
18608e75f744SArnaud Giersch 			 (configa & CNFGA_ID_MASK) >> CNFGA_ID_SHIFT);
18618e75f744SArnaud Giersch 		goto fail;
18628e75f744SArnaud Giersch 		break;
18638e75f744SArnaud Giersch 	}
18648e75f744SArnaud Giersch 	if (pword != 1) {
18658e75f744SArnaud Giersch 		pr_probe(p, "Unsupported PWord size: %u\n", pword);
18668e75f744SArnaud Giersch 		goto fail;
18678e75f744SArnaud Giersch 	}
18688e75f744SArnaud Giersch 	priv->pword = pword;
18698e75f744SArnaud Giersch 	pr_probe(p, "PWord is %u bits\n", 8 * priv->pword);
18708e75f744SArnaud Giersch 
18718e75f744SArnaud Giersch 	/* Check for compression support */
18728e75f744SArnaud Giersch 	writeb(configb | CNFGB_COMPRESS, priv->regs.cnfgB);
18738e75f744SArnaud Giersch 	if (readb(priv->regs.cnfgB) & CNFGB_COMPRESS)
18748e75f744SArnaud Giersch 		pr_probe(p, "Hardware compression detected (unsupported)\n");
18758e75f744SArnaud Giersch 	writeb(configb & ~CNFGB_COMPRESS, priv->regs.cnfgB);
18768e75f744SArnaud Giersch 
18778e75f744SArnaud Giersch 	/* Reset FIFO and go in test mode (no interrupt, no DMA) */
18788e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_TST);
18798e75f744SArnaud Giersch 
18808e75f744SArnaud Giersch 	/* FIFO must be empty now */
18818e75f744SArnaud Giersch 	if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) {
18828e75f744SArnaud Giersch 		pr_probe(p, "FIFO not reset\n");
18838e75f744SArnaud Giersch 		goto fail;
18848e75f744SArnaud Giersch 	}
18858e75f744SArnaud Giersch 
18868e75f744SArnaud Giersch 	/* Find out FIFO depth. */
18878e75f744SArnaud Giersch 	priv->fifo_depth = 0;
18888e75f744SArnaud Giersch 	for (i = 0; i < 1024; i++) {
18898e75f744SArnaud Giersch 		if (readb(priv->regs.ecr) & ECR_F_FULL) {
18908e75f744SArnaud Giersch 			/* FIFO full */
18918e75f744SArnaud Giersch 			priv->fifo_depth = i;
18928e75f744SArnaud Giersch 			break;
18938e75f744SArnaud Giersch 		}
18948e75f744SArnaud Giersch 		writeb((u8)i, priv->regs.fifo);
18958e75f744SArnaud Giersch 	}
18968e75f744SArnaud Giersch 	if (i >= 1024) {
18978e75f744SArnaud Giersch 		pr_probe(p, "Can't fill FIFO\n");
18988e75f744SArnaud Giersch 		goto fail;
18998e75f744SArnaud Giersch 	}
19008e75f744SArnaud Giersch 	if (!priv->fifo_depth) {
19018e75f744SArnaud Giersch 		pr_probe(p, "Can't get FIFO depth\n");
19028e75f744SArnaud Giersch 		goto fail;
19038e75f744SArnaud Giersch 	}
19048e75f744SArnaud Giersch 	pr_probe(p, "FIFO is %u PWords deep\n", priv->fifo_depth);
19058e75f744SArnaud Giersch 
19068e75f744SArnaud Giersch 	/* Enable interrupts */
19078e75f744SArnaud Giersch 	parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
19088e75f744SArnaud Giersch 
19098e75f744SArnaud Giersch 	/* Find out writeIntrThreshold: number of PWords we know we can write
19108e75f744SArnaud Giersch 	 * if we get an interrupt. */
19118e75f744SArnaud Giersch 	priv->writeIntrThreshold = 0;
19128e75f744SArnaud Giersch 	for (i = 0; i < priv->fifo_depth; i++) {
19138e75f744SArnaud Giersch 		if (readb(priv->regs.fifo) != (u8)i) {
19148e75f744SArnaud Giersch 			pr_probe(p, "Invalid data in FIFO\n");
19158e75f744SArnaud Giersch 			goto fail;
19168e75f744SArnaud Giersch 		}
19178e75f744SArnaud Giersch 		if (!priv->writeIntrThreshold
19188e75f744SArnaud Giersch 		    && readb(priv->regs.ecr) & ECR_SERVINTR)
19198e75f744SArnaud Giersch 			/* writeIntrThreshold reached */
19208e75f744SArnaud Giersch 			priv->writeIntrThreshold = i + 1;
19218e75f744SArnaud Giersch 		if (i + 1 < priv->fifo_depth
19228e75f744SArnaud Giersch 		    && readb(priv->regs.ecr) & ECR_F_EMPTY) {
19238e75f744SArnaud Giersch 			/* FIFO empty before the last byte? */
19248e75f744SArnaud Giersch 			pr_probe(p, "Data lost in FIFO\n");
19258e75f744SArnaud Giersch 			goto fail;
19268e75f744SArnaud Giersch 		}
19278e75f744SArnaud Giersch 	}
19288e75f744SArnaud Giersch 	if (!priv->writeIntrThreshold) {
19298e75f744SArnaud Giersch 		pr_probe(p, "Can't get writeIntrThreshold\n");
19308e75f744SArnaud Giersch 		goto fail;
19318e75f744SArnaud Giersch 	}
19328e75f744SArnaud Giersch 	pr_probe(p, "writeIntrThreshold is %u\n", priv->writeIntrThreshold);
19338e75f744SArnaud Giersch 
19348e75f744SArnaud Giersch 	/* FIFO must be empty now */
19358e75f744SArnaud Giersch 	if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) {
19368e75f744SArnaud Giersch 		pr_probe(p, "Can't empty FIFO\n");
19378e75f744SArnaud Giersch 		goto fail;
19388e75f744SArnaud Giersch 	}
19398e75f744SArnaud Giersch 
19408e75f744SArnaud Giersch 	/* Reset FIFO */
19418e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
19428e75f744SArnaud Giersch 	/* Set reverse direction (must be in PS2 mode) */
19438e75f744SArnaud Giersch 	parport_ip32_data_reverse(p);
19448e75f744SArnaud Giersch 	/* Test FIFO, no interrupt, no DMA */
19458e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_TST);
19468e75f744SArnaud Giersch 	/* Enable interrupts */
19478e75f744SArnaud Giersch 	parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0);
19488e75f744SArnaud Giersch 
19498e75f744SArnaud Giersch 	/* Find out readIntrThreshold: number of PWords we can read if we get
19508e75f744SArnaud Giersch 	 * an interrupt. */
19518e75f744SArnaud Giersch 	priv->readIntrThreshold = 0;
19528e75f744SArnaud Giersch 	for (i = 0; i < priv->fifo_depth; i++) {
19538e75f744SArnaud Giersch 		writeb(0xaa, priv->regs.fifo);
19548e75f744SArnaud Giersch 		if (readb(priv->regs.ecr) & ECR_SERVINTR) {
19558e75f744SArnaud Giersch 			/* readIntrThreshold reached */
19568e75f744SArnaud Giersch 			priv->readIntrThreshold = i + 1;
19578e75f744SArnaud Giersch 			break;
19588e75f744SArnaud Giersch 		}
19598e75f744SArnaud Giersch 	}
19608e75f744SArnaud Giersch 	if (!priv->readIntrThreshold) {
19618e75f744SArnaud Giersch 		pr_probe(p, "Can't get readIntrThreshold\n");
19628e75f744SArnaud Giersch 		goto fail;
19638e75f744SArnaud Giersch 	}
19648e75f744SArnaud Giersch 	pr_probe(p, "readIntrThreshold is %u\n", priv->readIntrThreshold);
19658e75f744SArnaud Giersch 
19668e75f744SArnaud Giersch 	/* Reset ECR */
19678e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
19688e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
19698e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_SPP);
19708e75f744SArnaud Giersch 	return 1;
19718e75f744SArnaud Giersch 
19728e75f744SArnaud Giersch fail:
19738e75f744SArnaud Giersch 	priv->fifo_depth = 0;
19748e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_SPP);
19758e75f744SArnaud Giersch 	return 0;
19768e75f744SArnaud Giersch }
19778e75f744SArnaud Giersch 
19788e75f744SArnaud Giersch /*--- Initialization code ----------------------------------------------*/
19798e75f744SArnaud Giersch 
19808e75f744SArnaud Giersch /**
19818e75f744SArnaud Giersch  * parport_ip32_make_isa_registers - compute (ISA) register addresses
19828e75f744SArnaud Giersch  * @regs:	pointer to &struct parport_ip32_regs to fill
19838e75f744SArnaud Giersch  * @base:	base address of standard and EPP registers
19848e75f744SArnaud Giersch  * @base_hi:	base address of ECP registers
19858e75f744SArnaud Giersch  * @regshift:	how much to shift register offset by
19868e75f744SArnaud Giersch  *
19878e75f744SArnaud Giersch  * Compute register addresses, according to the ISA standard.  The addresses
19888e75f744SArnaud Giersch  * of the standard and EPP registers are computed from address @base.  The
19898e75f744SArnaud Giersch  * addresses of the ECP registers are computed from address @base_hi.
19908e75f744SArnaud Giersch  */
19918e75f744SArnaud Giersch static void __init
parport_ip32_make_isa_registers(struct parport_ip32_regs * regs,void __iomem * base,void __iomem * base_hi,unsigned int regshift)19928e75f744SArnaud Giersch parport_ip32_make_isa_registers(struct parport_ip32_regs *regs,
19938e75f744SArnaud Giersch 				void __iomem *base, void __iomem *base_hi,
19948e75f744SArnaud Giersch 				unsigned int regshift)
19958e75f744SArnaud Giersch {
19968e75f744SArnaud Giersch #define r_base(offset)    ((u8 __iomem *)base    + ((offset) << regshift))
19978e75f744SArnaud Giersch #define r_base_hi(offset) ((u8 __iomem *)base_hi + ((offset) << regshift))
19988e75f744SArnaud Giersch 	*regs = (struct parport_ip32_regs){
19998e75f744SArnaud Giersch 		.data		= r_base(0),
20008e75f744SArnaud Giersch 		.dsr		= r_base(1),
20018e75f744SArnaud Giersch 		.dcr		= r_base(2),
20028e75f744SArnaud Giersch 		.eppAddr	= r_base(3),
20038e75f744SArnaud Giersch 		.eppData0	= r_base(4),
20048e75f744SArnaud Giersch 		.eppData1	= r_base(5),
20058e75f744SArnaud Giersch 		.eppData2	= r_base(6),
20068e75f744SArnaud Giersch 		.eppData3	= r_base(7),
20078e75f744SArnaud Giersch 		.ecpAFifo	= r_base(0),
20088e75f744SArnaud Giersch 		.fifo		= r_base_hi(0),
20098e75f744SArnaud Giersch 		.cnfgA		= r_base_hi(0),
20108e75f744SArnaud Giersch 		.cnfgB		= r_base_hi(1),
20118e75f744SArnaud Giersch 		.ecr		= r_base_hi(2)
20128e75f744SArnaud Giersch 	};
20138e75f744SArnaud Giersch #undef r_base_hi
20148e75f744SArnaud Giersch #undef r_base
20158e75f744SArnaud Giersch }
20168e75f744SArnaud Giersch 
20178e75f744SArnaud Giersch /**
20188e75f744SArnaud Giersch  * parport_ip32_probe_port - probe and register IP32 built-in parallel port
20198e75f744SArnaud Giersch  *
20208e75f744SArnaud Giersch  * Returns the new allocated &parport structure.  On error, an error code is
20218e75f744SArnaud Giersch  * encoded in return value with the ERR_PTR function.
20228e75f744SArnaud Giersch  */
parport_ip32_probe_port(void)20238e75f744SArnaud Giersch static __init struct parport *parport_ip32_probe_port(void)
20248e75f744SArnaud Giersch {
20258e75f744SArnaud Giersch 	struct parport_ip32_regs regs;
20268e75f744SArnaud Giersch 	struct parport_ip32_private *priv = NULL;
20278e75f744SArnaud Giersch 	struct parport_operations *ops = NULL;
20288e75f744SArnaud Giersch 	struct parport *p = NULL;
20298e75f744SArnaud Giersch 	int err;
20308e75f744SArnaud Giersch 
20318e75f744SArnaud Giersch 	parport_ip32_make_isa_registers(&regs, &mace->isa.parallel,
20328e75f744SArnaud Giersch 					&mace->isa.ecp1284, 8 /* regshift */);
20338e75f744SArnaud Giersch 
20348e75f744SArnaud Giersch 	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
20358e75f744SArnaud Giersch 	priv = kmalloc(sizeof(struct parport_ip32_private), GFP_KERNEL);
20368e75f744SArnaud Giersch 	p = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops);
20378e75f744SArnaud Giersch 	if (ops == NULL || priv == NULL || p == NULL) {
20388e75f744SArnaud Giersch 		err = -ENOMEM;
20398e75f744SArnaud Giersch 		goto fail;
20408e75f744SArnaud Giersch 	}
20418e75f744SArnaud Giersch 	p->base = MACE_BASE + offsetof(struct sgi_mace, isa.parallel);
20428e75f744SArnaud Giersch 	p->base_hi = MACE_BASE + offsetof(struct sgi_mace, isa.ecp1284);
20438e75f744SArnaud Giersch 	p->private_data = priv;
20448e75f744SArnaud Giersch 
20458e75f744SArnaud Giersch 	*ops = parport_ip32_ops;
20468e75f744SArnaud Giersch 	*priv = (struct parport_ip32_private){
20478e75f744SArnaud Giersch 		.regs			= regs,
20488e75f744SArnaud Giersch 		.dcr_writable		= DCR_DIR | DCR_SELECT | DCR_nINIT |
20498e75f744SArnaud Giersch 					  DCR_AUTOFD | DCR_STROBE,
20508e75f744SArnaud Giersch 		.irq_mode		= PARPORT_IP32_IRQ_FWD,
20518e75f744SArnaud Giersch 	};
20528e75f744SArnaud Giersch 	init_completion(&priv->irq_complete);
20538e75f744SArnaud Giersch 
20548e75f744SArnaud Giersch 	/* Probe port. */
20558e75f744SArnaud Giersch 	if (!parport_ip32_ecp_supported(p)) {
20568e75f744SArnaud Giersch 		err = -ENODEV;
20578e75f744SArnaud Giersch 		goto fail;
20588e75f744SArnaud Giersch 	}
20598e75f744SArnaud Giersch 	parport_ip32_dump_state(p, "begin init", 0);
20608e75f744SArnaud Giersch 
20618e75f744SArnaud Giersch 	/* We found what looks like a working ECR register.  Simply assume
20628e75f744SArnaud Giersch 	 * that all modes are correctly supported.  Enable basic modes. */
20638e75f744SArnaud Giersch 	p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
20648e75f744SArnaud Giersch 	p->modes |= PARPORT_MODE_TRISTATE;
20658e75f744SArnaud Giersch 
20668e75f744SArnaud Giersch 	if (!parport_ip32_fifo_supported(p)) {
2067decf26f6SJoe Perches 		pr_warn(PPIP32 "%s: error: FIFO disabled\n", p->name);
20688e75f744SArnaud Giersch 		/* Disable hardware modes depending on a working FIFO. */
20698e75f744SArnaud Giersch 		features &= ~PARPORT_IP32_ENABLE_SPP;
20708e75f744SArnaud Giersch 		features &= ~PARPORT_IP32_ENABLE_ECP;
20718e75f744SArnaud Giersch 		/* DMA is not needed if FIFO is not supported.  */
20728e75f744SArnaud Giersch 		features &= ~PARPORT_IP32_ENABLE_DMA;
20738e75f744SArnaud Giersch 	}
20748e75f744SArnaud Giersch 
20758e75f744SArnaud Giersch 	/* Request IRQ */
20768e75f744SArnaud Giersch 	if (features & PARPORT_IP32_ENABLE_IRQ) {
20778e75f744SArnaud Giersch 		int irq = MACEISA_PARALLEL_IRQ;
20788e75f744SArnaud Giersch 		if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) {
2079decf26f6SJoe Perches 			pr_warn(PPIP32 "%s: error: IRQ disabled\n", p->name);
20808e75f744SArnaud Giersch 			/* DMA cannot work without interrupts. */
20818e75f744SArnaud Giersch 			features &= ~PARPORT_IP32_ENABLE_DMA;
20828e75f744SArnaud Giersch 		} else {
20838e75f744SArnaud Giersch 			pr_probe(p, "Interrupt support enabled\n");
20848e75f744SArnaud Giersch 			p->irq = irq;
20858e75f744SArnaud Giersch 			priv->dcr_writable |= DCR_IRQ;
20868e75f744SArnaud Giersch 		}
20878e75f744SArnaud Giersch 	}
20888e75f744SArnaud Giersch 
20898e75f744SArnaud Giersch 	/* Allocate DMA resources */
20908e75f744SArnaud Giersch 	if (features & PARPORT_IP32_ENABLE_DMA) {
20918e75f744SArnaud Giersch 		if (parport_ip32_dma_register())
2092decf26f6SJoe Perches 			pr_warn(PPIP32 "%s: error: DMA disabled\n", p->name);
20938e75f744SArnaud Giersch 		else {
20948e75f744SArnaud Giersch 			pr_probe(p, "DMA support enabled\n");
20958e75f744SArnaud Giersch 			p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */
20968e75f744SArnaud Giersch 			p->modes |= PARPORT_MODE_DMA;
20978e75f744SArnaud Giersch 		}
20988e75f744SArnaud Giersch 	}
20998e75f744SArnaud Giersch 
21008e75f744SArnaud Giersch 	if (features & PARPORT_IP32_ENABLE_SPP) {
21018e75f744SArnaud Giersch 		/* Enable compatibility FIFO mode */
21028e75f744SArnaud Giersch 		p->ops->compat_write_data = parport_ip32_compat_write_data;
21038e75f744SArnaud Giersch 		p->modes |= PARPORT_MODE_COMPAT;
21048e75f744SArnaud Giersch 		pr_probe(p, "Hardware support for SPP mode enabled\n");
21058e75f744SArnaud Giersch 	}
21068e75f744SArnaud Giersch 	if (features & PARPORT_IP32_ENABLE_EPP) {
21078e75f744SArnaud Giersch 		/* Set up access functions to use EPP hardware. */
21088e75f744SArnaud Giersch 		p->ops->epp_read_data = parport_ip32_epp_read_data;
21098e75f744SArnaud Giersch 		p->ops->epp_write_data = parport_ip32_epp_write_data;
21108e75f744SArnaud Giersch 		p->ops->epp_read_addr = parport_ip32_epp_read_addr;
21118e75f744SArnaud Giersch 		p->ops->epp_write_addr = parport_ip32_epp_write_addr;
21128e75f744SArnaud Giersch 		p->modes |= PARPORT_MODE_EPP;
21138e75f744SArnaud Giersch 		pr_probe(p, "Hardware support for EPP mode enabled\n");
21148e75f744SArnaud Giersch 	}
21158e75f744SArnaud Giersch 	if (features & PARPORT_IP32_ENABLE_ECP) {
21168e75f744SArnaud Giersch 		/* Enable ECP FIFO mode */
21178e75f744SArnaud Giersch 		p->ops->ecp_write_data = parport_ip32_ecp_write_data;
21188e75f744SArnaud Giersch 		/* FIXME - not implemented */
21198e75f744SArnaud Giersch /*		p->ops->ecp_read_data  = parport_ip32_ecp_read_data; */
21208e75f744SArnaud Giersch /*		p->ops->ecp_write_addr = parport_ip32_ecp_write_addr; */
21218e75f744SArnaud Giersch 		p->modes |= PARPORT_MODE_ECP;
21228e75f744SArnaud Giersch 		pr_probe(p, "Hardware support for ECP mode enabled\n");
21238e75f744SArnaud Giersch 	}
21248e75f744SArnaud Giersch 
21258e75f744SArnaud Giersch 	/* Initialize the port with sensible values */
21268e75f744SArnaud Giersch 	parport_ip32_set_mode(p, ECR_MODE_PS2);
21278e75f744SArnaud Giersch 	parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT);
21288e75f744SArnaud Giersch 	parport_ip32_data_forward(p);
21298e75f744SArnaud Giersch 	parport_ip32_disable_irq(p);
21308e75f744SArnaud Giersch 	parport_ip32_write_data(p, 0x00);
21318e75f744SArnaud Giersch 	parport_ip32_dump_state(p, "end init", 0);
21328e75f744SArnaud Giersch 
21338e75f744SArnaud Giersch 	/* Print out what we found */
2134decf26f6SJoe Perches 	pr_info("%s: SGI IP32 at 0x%lx (0x%lx)", p->name, p->base, p->base_hi);
21358e75f744SArnaud Giersch 	if (p->irq != PARPORT_IRQ_NONE)
2136*aa3d6e7cSJoe Perches 		pr_cont(", irq %d", p->irq);
2137*aa3d6e7cSJoe Perches 	pr_cont(" [");
2138*aa3d6e7cSJoe Perches #define printmode(x)							\
2139*aa3d6e7cSJoe Perches do {									\
2140*aa3d6e7cSJoe Perches 	if (p->modes & PARPORT_MODE_##x)				\
2141*aa3d6e7cSJoe Perches 		pr_cont("%s%s", f++ ? "," : "", #x);			\
2142*aa3d6e7cSJoe Perches } while (0)
21438e75f744SArnaud Giersch 	{
21448e75f744SArnaud Giersch 		unsigned int f = 0;
21458e75f744SArnaud Giersch 		printmode(PCSPP);
21468e75f744SArnaud Giersch 		printmode(TRISTATE);
21478e75f744SArnaud Giersch 		printmode(COMPAT);
21488e75f744SArnaud Giersch 		printmode(EPP);
21498e75f744SArnaud Giersch 		printmode(ECP);
21508e75f744SArnaud Giersch 		printmode(DMA);
21518e75f744SArnaud Giersch 	}
21528e75f744SArnaud Giersch #undef printmode
2153*aa3d6e7cSJoe Perches 	pr_cont("]\n");
21548e75f744SArnaud Giersch 
21558e75f744SArnaud Giersch 	parport_announce_port(p);
21568e75f744SArnaud Giersch 	return p;
21578e75f744SArnaud Giersch 
21588e75f744SArnaud Giersch fail:
21598e75f744SArnaud Giersch 	if (p)
21608e75f744SArnaud Giersch 		parport_put_port(p);
21618e75f744SArnaud Giersch 	kfree(priv);
21628e75f744SArnaud Giersch 	kfree(ops);
21638e75f744SArnaud Giersch 	return ERR_PTR(err);
21648e75f744SArnaud Giersch }
21658e75f744SArnaud Giersch 
21668e75f744SArnaud Giersch /**
21678e75f744SArnaud Giersch  * parport_ip32_unregister_port - unregister a parallel port
21688e75f744SArnaud Giersch  * @p:		pointer to the &struct parport
21698e75f744SArnaud Giersch  *
21708e75f744SArnaud Giersch  * Unregisters a parallel port and free previously allocated resources
21718e75f744SArnaud Giersch  * (memory, IRQ, ...).
21728e75f744SArnaud Giersch  */
parport_ip32_unregister_port(struct parport * p)21738e75f744SArnaud Giersch static __exit void parport_ip32_unregister_port(struct parport *p)
21748e75f744SArnaud Giersch {
21758e75f744SArnaud Giersch 	struct parport_ip32_private * const priv = p->physport->private_data;
21768e75f744SArnaud Giersch 	struct parport_operations *ops = p->ops;
21778e75f744SArnaud Giersch 
21788e75f744SArnaud Giersch 	parport_remove_port(p);
21798e75f744SArnaud Giersch 	if (p->modes & PARPORT_MODE_DMA)
21808e75f744SArnaud Giersch 		parport_ip32_dma_unregister();
21818e75f744SArnaud Giersch 	if (p->irq != PARPORT_IRQ_NONE)
21828e75f744SArnaud Giersch 		free_irq(p->irq, p);
21838e75f744SArnaud Giersch 	parport_put_port(p);
21848e75f744SArnaud Giersch 	kfree(priv);
21858e75f744SArnaud Giersch 	kfree(ops);
21868e75f744SArnaud Giersch }
21878e75f744SArnaud Giersch 
21888e75f744SArnaud Giersch /**
21898e75f744SArnaud Giersch  * parport_ip32_init - module initialization function
21908e75f744SArnaud Giersch  */
parport_ip32_init(void)21918e75f744SArnaud Giersch static int __init parport_ip32_init(void)
21928e75f744SArnaud Giersch {
21938e75f744SArnaud Giersch 	pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n");
21948e75f744SArnaud Giersch 	this_port = parport_ip32_probe_port();
2195340f365dSFabian Frederick 	return PTR_ERR_OR_ZERO(this_port);
21968e75f744SArnaud Giersch }
21978e75f744SArnaud Giersch 
21988e75f744SArnaud Giersch /**
21998e75f744SArnaud Giersch  * parport_ip32_exit - module termination function
22008e75f744SArnaud Giersch  */
parport_ip32_exit(void)22018e75f744SArnaud Giersch static void __exit parport_ip32_exit(void)
22028e75f744SArnaud Giersch {
22038e75f744SArnaud Giersch 	parport_ip32_unregister_port(this_port);
22048e75f744SArnaud Giersch }
22058e75f744SArnaud Giersch 
22068e75f744SArnaud Giersch /*--- Module stuff -----------------------------------------------------*/
22078e75f744SArnaud Giersch 
22088e75f744SArnaud Giersch MODULE_AUTHOR("Arnaud Giersch <arnaud.giersch@free.fr>");
22098e75f744SArnaud Giersch MODULE_DESCRIPTION("SGI IP32 built-in parallel port driver");
22108e75f744SArnaud Giersch MODULE_LICENSE("GPL");
22118e75f744SArnaud Giersch MODULE_VERSION("0.6");		/* update in parport_ip32_init() too */
22128e75f744SArnaud Giersch 
22138e75f744SArnaud Giersch module_init(parport_ip32_init);
22148e75f744SArnaud Giersch module_exit(parport_ip32_exit);
22158e75f744SArnaud Giersch 
22168e75f744SArnaud Giersch module_param(verbose_probing, bool, S_IRUGO);
22178e75f744SArnaud Giersch MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialization");
22188e75f744SArnaud Giersch 
22198e75f744SArnaud Giersch module_param(features, uint, S_IRUGO);
22208e75f744SArnaud Giersch MODULE_PARM_DESC(features,
22218e75f744SArnaud Giersch 		 "Bit mask of features to enable"
22228e75f744SArnaud Giersch 		 ", bit 0: IRQ support"
22238e75f744SArnaud Giersch 		 ", bit 1: DMA support"
22248e75f744SArnaud Giersch 		 ", bit 2: hardware SPP mode"
22258e75f744SArnaud Giersch 		 ", bit 3: hardware EPP mode"
22268e75f744SArnaud Giersch 		 ", bit 4: hardware ECP mode");
2227