1ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks/* linux/drivers/parport/parport_ax88796.c 2ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * 3ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * (c) 2005,2006 Simtec Electronics 4ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * Ben Dooks <ben@simtec.co.uk> 5ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * 6ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * This program is free software; you can redistribute it and/or modify 7ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * it under the terms of the GNU General Public License version 2 as 8ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * published by the Free Software Foundation. 9ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks * 10ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks*/ 11ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 12ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <linux/module.h> 13ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <linux/kernel.h> 14ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <linux/parport.h> 15ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <linux/interrupt.h> 16ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <linux/errno.h> 17ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <linux/platform_device.h> 185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 19ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 20ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <asm/io.h> 21ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#include <asm/irq.h> 22ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 23ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_SPR_BUSY (1<<7) 24ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_SPR_ACK (1<<6) 25ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_SPR_PE (1<<5) 26ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_SPR_SLCT (1<<4) 27ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_SPR_ERR (1<<3) 28ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 29ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_CPR_nDOE (1<<5) 30ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_CPR_SLCTIN (1<<3) 31ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_CPR_nINIT (1<<2) 32ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_CPR_ATFD (1<<1) 33ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define AX_CPR_STRB (1<<0) 34ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 35ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstruct ax_drvdata { 36ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct parport *parport; 37ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct parport_state suspend; 38ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 39ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct device *dev; 40ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct resource *io; 41ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 42ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned char irq_enabled; 43ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 44ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks void __iomem *base; 45ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks void __iomem *spp_data; 46ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks void __iomem *spp_spr; 47ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks void __iomem *spp_cpr; 48ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks}; 49ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 50ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic inline struct ax_drvdata *pp_to_drv(struct parport *p) 51ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 52ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return p->private_data; 53ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 54ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 55ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic unsigned char 56ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_read_data(struct parport *p) 57ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 58ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 59ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 60ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return readb(dd->spp_data); 61ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 62ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 63ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 64ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_write_data(struct parport *p, unsigned char data) 65ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 66ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 67ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 68ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb(data, dd->spp_data); 69ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 70ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 71ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic unsigned char 72ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_read_control(struct parport *p) 73ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 74ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 75ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned int cpr = readb(dd->spp_cpr); 76ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned int ret = 0; 77ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 78ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!(cpr & AX_CPR_STRB)) 79ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_CONTROL_STROBE; 80ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 81ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!(cpr & AX_CPR_ATFD)) 82ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_CONTROL_AUTOFD; 83ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 84ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (cpr & AX_CPR_nINIT) 85ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_CONTROL_INIT; 86ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 87ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!(cpr & AX_CPR_SLCTIN)) 88ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_CONTROL_SELECT; 89ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 90ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return ret; 91ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 92ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 93ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 94ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_write_control(struct parport *p, unsigned char control) 95ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 96ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 97ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned int cpr = readb(dd->spp_cpr); 98ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 99ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks cpr &= AX_CPR_nDOE; 100ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 101ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!(control & PARPORT_CONTROL_STROBE)) 102ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks cpr |= AX_CPR_STRB; 103ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 104ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!(control & PARPORT_CONTROL_AUTOFD)) 105ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks cpr |= AX_CPR_ATFD; 106ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 107ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (control & PARPORT_CONTROL_INIT) 108ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks cpr |= AX_CPR_nINIT; 109ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 110ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!(control & PARPORT_CONTROL_SELECT)) 111ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks cpr |= AX_CPR_SLCTIN; 112ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 113ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr); 114ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb(cpr, dd->spp_cpr); 115ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 116ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (parport_ax88796_read_control(p) != control) { 117ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n", 118ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_ax88796_read_control(p), control); 119ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 120ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 121ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 122ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic unsigned char 123ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_read_status(struct parport *p) 124ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 125ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 126ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned int status = readb(dd->spp_spr); 127ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned int ret = 0; 128ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 129ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (status & AX_SPR_BUSY) 130ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_STATUS_BUSY; 131ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 132ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (status & AX_SPR_ACK) 133ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_STATUS_ACK; 134ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 135ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (status & AX_SPR_ERR) 136ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_STATUS_ERROR; 137ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 138ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (status & AX_SPR_SLCT) 139ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_STATUS_SELECT; 140ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 141ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (status & AX_SPR_PE) 142ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret |= PARPORT_STATUS_PAPEROUT; 143ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 144ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return ret; 145ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 146ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 147ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic unsigned char 148ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_frob_control(struct parport *p, unsigned char mask, 149ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned char val) 150ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 151ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 152ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned char old = parport_ax88796_read_control(p); 153ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 154ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n", 155ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks mask, val, old); 156ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 157ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_ax88796_write_control(p, (old & ~mask) | val); 158ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return old; 159ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 160ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 161ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 162ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_enable_irq(struct parport *p) 163ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 164ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 165ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned long flags; 166ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 167ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks local_irq_save(flags); 168ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (!dd->irq_enabled) { 169ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks enable_irq(p->irq); 170ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->irq_enabled = 1; 171ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 172ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks local_irq_restore(flags); 173ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 174ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 175ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 176ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_disable_irq(struct parport *p) 177ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 178ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 179ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned long flags; 180ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 181ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks local_irq_save(flags); 182ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (dd->irq_enabled) { 183ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks disable_irq(p->irq); 184ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->irq_enabled = 0; 185ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 186ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks local_irq_restore(flags); 187ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 188ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 189ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 190ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_data_forward(struct parport *p) 191ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 192ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 193ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks void __iomem *cpr = dd->spp_cpr; 194ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 195ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb((readb(cpr) & ~AX_CPR_nDOE), cpr); 196ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 197ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 198ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 199ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_data_reverse(struct parport *p) 200ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 201ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 202ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks void __iomem *cpr = dd->spp_cpr; 203ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 204ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb(readb(cpr) | AX_CPR_nDOE, cpr); 205ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 206ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 207ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 208ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_init_state(struct pardevice *d, struct parport_state *s) 209ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 210ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(d->port); 211ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 212ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks memset(s, 0, sizeof(struct parport_state)); 213ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 214ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s); 215ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks s->u.ax88796.cpr = readb(dd->spp_cpr); 216ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 217ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 218ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 219ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_save_state(struct parport *p, struct parport_state *s) 220ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 221ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 222ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 223ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s); 224ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks s->u.ax88796.cpr = readb(dd->spp_cpr); 225ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 226ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 227ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic void 228ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksparport_ax88796_restore_state(struct parport *p, struct parport_state *s) 229ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 230ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 231ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 232ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s); 233ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb(s->u.ax88796.cpr, dd->spp_cpr); 234ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 235ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 236ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic struct parport_operations parport_ax88796_ops = { 237ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .write_data = parport_ax88796_write_data, 238ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .read_data = parport_ax88796_read_data, 239ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 240ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .write_control = parport_ax88796_write_control, 241ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .read_control = parport_ax88796_read_control, 242ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .frob_control = parport_ax88796_frob_control, 243ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 244ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .read_status = parport_ax88796_read_status, 245ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 246ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .enable_irq = parport_ax88796_enable_irq, 247ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .disable_irq = parport_ax88796_disable_irq, 248ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 249ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .data_forward = parport_ax88796_data_forward, 250ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .data_reverse = parport_ax88796_data_reverse, 251ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 252ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .init_state = parport_ax88796_init_state, 253ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .save_state = parport_ax88796_save_state, 254ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .restore_state = parport_ax88796_restore_state, 255ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 256ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .epp_write_data = parport_ieee1284_epp_write_data, 257ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .epp_read_data = parport_ieee1284_epp_read_data, 258ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .epp_write_addr = parport_ieee1284_epp_write_addr, 259ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .epp_read_addr = parport_ieee1284_epp_read_addr, 260ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 261ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .ecp_write_data = parport_ieee1284_ecp_write_data, 262ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .ecp_read_data = parport_ieee1284_ecp_read_data, 263ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .ecp_write_addr = parport_ieee1284_ecp_write_addr, 264ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 265ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .compat_write_data = parport_ieee1284_write_compat, 266ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .nibble_read_data = parport_ieee1284_read_nibble, 267ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .byte_read_data = parport_ieee1284_read_byte, 268ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 269ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .owner = THIS_MODULE, 270ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks}; 271ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 272ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic int parport_ax88796_probe(struct platform_device *pdev) 273ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 274ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct device *_dev = &pdev->dev; 275ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd; 276ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct parport *pp = NULL; 277ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct resource *res; 278ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks unsigned long size; 279ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks int spacing; 280ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks int irq; 281ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks int ret; 282ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 283ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL); 284ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (dd == NULL) { 285ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_err(_dev, "no memory for private data\n"); 286ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return -ENOMEM; 287ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 288ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 289ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 290ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (res == NULL) { 291ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_err(_dev, "no MEM specified\n"); 292ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret = -ENXIO; 293ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks goto exit_mem; 294ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 295ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 29628f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches size = resource_size(res); 297ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks spacing = size / 3; 298ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 299ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->io = request_mem_region(res->start, size, pdev->name); 300ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (dd->io == NULL) { 301ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_err(_dev, "cannot reserve memory\n"); 302ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret = -ENXIO; 303ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks goto exit_mem; 304ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 305ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 306ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->base = ioremap(res->start, size); 307ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (dd->base == NULL) { 308ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_err(_dev, "cannot ioremap region\n"); 309ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret = -ENXIO; 310ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks goto exit_res; 311ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 312ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 313ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks irq = platform_get_irq(pdev, 0); 314ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (irq <= 0) 315ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks irq = PARPORT_IRQ_NONE; 316ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 317ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks pp = parport_register_port((unsigned long)dd->base, irq, 318ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks PARPORT_DMA_NONE, 319ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks &parport_ax88796_ops); 320ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 321ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (pp == NULL) { 322ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_err(_dev, "failed to register parallel port\n"); 323ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks ret = -ENOMEM; 324ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks goto exit_unmap; 325ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 326ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 327ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks pp->private_data = dd; 328ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->parport = pp; 329ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->dev = _dev; 330ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 331ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->spp_data = dd->base; 332ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->spp_spr = dd->base + (spacing * 1); 333ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->spp_cpr = dd->base + (spacing * 2); 334ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 335ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks /* initialise the port controls */ 336ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb(AX_CPR_STRB, dd->spp_cpr); 337ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 338ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (irq >= 0) { 339ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks /* request irq */ 3403f2e40df0e1d7694224c3083b0bebd129039a40aJeff Garzik ret = request_irq(irq, parport_irq_handler, 341dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner IRQF_TRIGGER_FALLING, pdev->name, pp); 342ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 343ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks if (ret < 0) 344ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks goto exit_port; 345ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 346ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dd->irq_enabled = 1; 347ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks } 348ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 349ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks platform_set_drvdata(pdev, pp); 350ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 351ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks dev_info(_dev, "attached parallel port driver\n"); 352ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_announce_port(pp); 353ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 354ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return 0; 355ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 356ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks exit_port: 357ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_remove_port(pp); 358ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks exit_unmap: 359ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks iounmap(dd->base); 360ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks exit_res: 361ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks release_resource(dd->io); 362ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks kfree(dd->io); 363ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks exit_mem: 364ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks kfree(dd); 365ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return ret; 366ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 367ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 368ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic int parport_ax88796_remove(struct platform_device *pdev) 369ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 370ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct parport *p = platform_get_drvdata(pdev); 371ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 372ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 373ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks free_irq(p->irq, p); 374ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_remove_port(p); 375ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks iounmap(dd->base); 376ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks release_resource(dd->io); 377ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks kfree(dd->io); 378ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks kfree(dd); 379ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 380ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return 0; 381ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 382ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 383ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#ifdef CONFIG_PM 384ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 385ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic int parport_ax88796_suspend(struct platform_device *dev, 386ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks pm_message_t state) 387ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 388ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct parport *p = platform_get_drvdata(dev); 389ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 390ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 391ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_ax88796_save_state(p, &dd->suspend); 392ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr); 393ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return 0; 394ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 395ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 396ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic int parport_ax88796_resume(struct platform_device *dev) 397ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks{ 398ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct parport *p = platform_get_drvdata(dev); 399ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks struct ax_drvdata *dd = pp_to_drv(p); 400ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 401ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks parport_ax88796_restore_state(p, &dd->suspend); 402ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks return 0; 403ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks} 404ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 405ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#else 406ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define parport_ax88796_suspend NULL 407ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#define parport_ax88796_resume NULL 408ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks#endif 409ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 410db358b40e0674fd4079204d8e3e1c8ab3829a1b9Kay SieversMODULE_ALIAS("platform:ax88796-pp"); 411db358b40e0674fd4079204d8e3e1c8ab3829a1b9Kay Sievers 412ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooksstatic struct platform_driver axdrv = { 413ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .driver = { 414ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .name = "ax88796-pp", 415ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .owner = THIS_MODULE, 416ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks }, 417ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .probe = parport_ax88796_probe, 418ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .remove = parport_ax88796_remove, 419ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .suspend = parport_ax88796_suspend, 420ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks .resume = parport_ax88796_resume, 421ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks}; 422ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 423782ee87702fbd0a175da64a8e71e029b19ef97bfAxel Linmodule_platform_driver(axdrv); 424ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben Dooks 425ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben DooksMODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 426ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben DooksMODULE_DESCRIPTION("AX88796 Parport parallel port driver"); 427ad4063b0b2ffd7c8359b62c830e88152fc39ab20Ben DooksMODULE_LICENSE("GPL"); 428