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