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