109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24f62d158SDavid S. Miller /* parport_sunbpp.c: Parallel-port routines for SBUS
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * Author: Derrick J. Brashear <shadow@dementia.org>
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * based on work by:
71da177e4SLinus Torvalds * Phil Blundell <philb@gnu.org>
81da177e4SLinus Torvalds * Tim Waugh <tim@cyberelk.demon.co.uk>
91da177e4SLinus Torvalds * Jose Renau <renau@acm.org>
101da177e4SLinus Torvalds * David Campbell <campbell@tirian.che.curtin.edu.au>
111da177e4SLinus Torvalds * Grant Guenther <grant@torque.net>
121da177e4SLinus Torvalds * Eddie C. Dost <ecd@skynet.be>
131da177e4SLinus Torvalds * Stephen Williams (steve@icarus.com)
141da177e4SLinus Torvalds * Gus Baldauf (gbaldauf@ix.netcom.com)
151da177e4SLinus Torvalds * Peter Zaitcev
161da177e4SLinus Torvalds * Tom Dyas
174f62d158SDavid S. Miller *
184f62d158SDavid S. Miller * Updated to new SBUS device framework: David S. Miller <davem@davemloft.net>
194f62d158SDavid S. Miller *
201da177e4SLinus Torvalds */
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds #include <linux/string.h>
231da177e4SLinus Torvalds #include <linux/module.h>
241da177e4SLinus Torvalds #include <linux/delay.h>
251da177e4SLinus Torvalds #include <linux/errno.h>
261da177e4SLinus Torvalds #include <linux/ioport.h>
271da177e4SLinus Torvalds #include <linux/kernel.h>
281da177e4SLinus Torvalds #include <linux/slab.h>
291da177e4SLinus Torvalds #include <linux/init.h>
3027167e0eSDavid S. Miller #include <linux/of.h>
31*6f75dff1SRob Herring #include <linux/platform_device.h>
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds #include <linux/parport.h>
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds #include <asm/ptrace.h>
361da177e4SLinus Torvalds #include <linux/interrupt.h>
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds #include <asm/io.h>
391da177e4SLinus Torvalds #include <asm/oplib.h> /* OpenProm Library */
401da177e4SLinus Torvalds #include <asm/dma.h> /* BPP uses LSI 64854 for DMA */
411da177e4SLinus Torvalds #include <asm/irq.h>
421da177e4SLinus Torvalds #include <asm/sunbpp.h>
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds #undef __SUNBPP_DEBUG
451da177e4SLinus Torvalds #ifdef __SUNBPP_DEBUG
461da177e4SLinus Torvalds #define dprintk(x) printk x
471da177e4SLinus Torvalds #else
481da177e4SLinus Torvalds #define dprintk(x)
491da177e4SLinus Torvalds #endif
501da177e4SLinus Torvalds
parport_sunbpp_disable_irq(struct parport * p)511da177e4SLinus Torvalds static void parport_sunbpp_disable_irq(struct parport *p)
521da177e4SLinus Torvalds {
531da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
541da177e4SLinus Torvalds u32 tmp;
551da177e4SLinus Torvalds
561da177e4SLinus Torvalds tmp = sbus_readl(®s->p_csr);
571da177e4SLinus Torvalds tmp &= ~DMA_INT_ENAB;
581da177e4SLinus Torvalds sbus_writel(tmp, ®s->p_csr);
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
parport_sunbpp_enable_irq(struct parport * p)611da177e4SLinus Torvalds static void parport_sunbpp_enable_irq(struct parport *p)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
641da177e4SLinus Torvalds u32 tmp;
651da177e4SLinus Torvalds
661da177e4SLinus Torvalds tmp = sbus_readl(®s->p_csr);
671da177e4SLinus Torvalds tmp |= DMA_INT_ENAB;
681da177e4SLinus Torvalds sbus_writel(tmp, ®s->p_csr);
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds
parport_sunbpp_write_data(struct parport * p,unsigned char d)711da177e4SLinus Torvalds static void parport_sunbpp_write_data(struct parport *p, unsigned char d)
721da177e4SLinus Torvalds {
731da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
741da177e4SLinus Torvalds
751da177e4SLinus Torvalds sbus_writeb(d, ®s->p_dr);
761da177e4SLinus Torvalds dprintk((KERN_DEBUG "wrote 0x%x\n", d));
771da177e4SLinus Torvalds }
781da177e4SLinus Torvalds
parport_sunbpp_read_data(struct parport * p)791da177e4SLinus Torvalds static unsigned char parport_sunbpp_read_data(struct parport *p)
801da177e4SLinus Torvalds {
811da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
821da177e4SLinus Torvalds
831da177e4SLinus Torvalds return sbus_readb(®s->p_dr);
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds
status_sunbpp_to_pc(struct parport * p)861da177e4SLinus Torvalds static unsigned char status_sunbpp_to_pc(struct parport *p)
871da177e4SLinus Torvalds {
881da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
891da177e4SLinus Torvalds unsigned char bits = 0;
901da177e4SLinus Torvalds unsigned char value_tcr = sbus_readb(®s->p_tcr);
911da177e4SLinus Torvalds unsigned char value_ir = sbus_readb(®s->p_ir);
921da177e4SLinus Torvalds
931da177e4SLinus Torvalds if (!(value_ir & P_IR_ERR))
941da177e4SLinus Torvalds bits |= PARPORT_STATUS_ERROR;
951da177e4SLinus Torvalds if (!(value_ir & P_IR_SLCT))
961da177e4SLinus Torvalds bits |= PARPORT_STATUS_SELECT;
971da177e4SLinus Torvalds if (!(value_ir & P_IR_PE))
981da177e4SLinus Torvalds bits |= PARPORT_STATUS_PAPEROUT;
991da177e4SLinus Torvalds if (value_tcr & P_TCR_ACK)
1001da177e4SLinus Torvalds bits |= PARPORT_STATUS_ACK;
1011da177e4SLinus Torvalds if (!(value_tcr & P_TCR_BUSY))
1021da177e4SLinus Torvalds bits |= PARPORT_STATUS_BUSY;
1031da177e4SLinus Torvalds
1045a68b2e3SDavid S. Miller dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", value_tcr, value_ir));
1051da177e4SLinus Torvalds dprintk((KERN_DEBUG "read status 0x%x\n", bits));
1061da177e4SLinus Torvalds return bits;
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds
control_sunbpp_to_pc(struct parport * p)1091da177e4SLinus Torvalds static unsigned char control_sunbpp_to_pc(struct parport *p)
1101da177e4SLinus Torvalds {
1111da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
1121da177e4SLinus Torvalds unsigned char bits = 0;
1131da177e4SLinus Torvalds unsigned char value_tcr = sbus_readb(®s->p_tcr);
1141da177e4SLinus Torvalds unsigned char value_or = sbus_readb(®s->p_or);
1151da177e4SLinus Torvalds
1161da177e4SLinus Torvalds if (!(value_tcr & P_TCR_DS))
1171da177e4SLinus Torvalds bits |= PARPORT_CONTROL_STROBE;
1181da177e4SLinus Torvalds if (!(value_or & P_OR_AFXN))
1191da177e4SLinus Torvalds bits |= PARPORT_CONTROL_AUTOFD;
1201da177e4SLinus Torvalds if (!(value_or & P_OR_INIT))
1211da177e4SLinus Torvalds bits |= PARPORT_CONTROL_INIT;
1221da177e4SLinus Torvalds if (value_or & P_OR_SLCT_IN)
1231da177e4SLinus Torvalds bits |= PARPORT_CONTROL_SELECT;
1241da177e4SLinus Torvalds
1255a68b2e3SDavid S. Miller dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", value_tcr, value_or));
1261da177e4SLinus Torvalds dprintk((KERN_DEBUG "read control 0x%x\n", bits));
1271da177e4SLinus Torvalds return bits;
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds
parport_sunbpp_read_control(struct parport * p)1301da177e4SLinus Torvalds static unsigned char parport_sunbpp_read_control(struct parport *p)
1311da177e4SLinus Torvalds {
1321da177e4SLinus Torvalds return control_sunbpp_to_pc(p);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds
parport_sunbpp_frob_control(struct parport * p,unsigned char mask,unsigned char val)1351da177e4SLinus Torvalds static unsigned char parport_sunbpp_frob_control(struct parport *p,
1361da177e4SLinus Torvalds unsigned char mask,
1371da177e4SLinus Torvalds unsigned char val)
1381da177e4SLinus Torvalds {
1391da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
1401da177e4SLinus Torvalds unsigned char value_tcr = sbus_readb(®s->p_tcr);
1411da177e4SLinus Torvalds unsigned char value_or = sbus_readb(®s->p_or);
1421da177e4SLinus Torvalds
1435a68b2e3SDavid S. Miller dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n",
1445a68b2e3SDavid S. Miller value_tcr, value_or));
1451da177e4SLinus Torvalds if (mask & PARPORT_CONTROL_STROBE) {
1461da177e4SLinus Torvalds if (val & PARPORT_CONTROL_STROBE) {
1471da177e4SLinus Torvalds value_tcr &= ~P_TCR_DS;
1481da177e4SLinus Torvalds } else {
1491da177e4SLinus Torvalds value_tcr |= P_TCR_DS;
1501da177e4SLinus Torvalds }
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds if (mask & PARPORT_CONTROL_AUTOFD) {
1531da177e4SLinus Torvalds if (val & PARPORT_CONTROL_AUTOFD) {
1541da177e4SLinus Torvalds value_or &= ~P_OR_AFXN;
1551da177e4SLinus Torvalds } else {
1561da177e4SLinus Torvalds value_or |= P_OR_AFXN;
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds }
1591da177e4SLinus Torvalds if (mask & PARPORT_CONTROL_INIT) {
1601da177e4SLinus Torvalds if (val & PARPORT_CONTROL_INIT) {
1611da177e4SLinus Torvalds value_or &= ~P_OR_INIT;
1621da177e4SLinus Torvalds } else {
1631da177e4SLinus Torvalds value_or |= P_OR_INIT;
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds }
1661da177e4SLinus Torvalds if (mask & PARPORT_CONTROL_SELECT) {
1671da177e4SLinus Torvalds if (val & PARPORT_CONTROL_SELECT) {
1681da177e4SLinus Torvalds value_or |= P_OR_SLCT_IN;
1691da177e4SLinus Torvalds } else {
1701da177e4SLinus Torvalds value_or &= ~P_OR_SLCT_IN;
1711da177e4SLinus Torvalds }
1721da177e4SLinus Torvalds }
1731da177e4SLinus Torvalds
1741da177e4SLinus Torvalds sbus_writeb(value_or, ®s->p_or);
1751da177e4SLinus Torvalds sbus_writeb(value_tcr, ®s->p_tcr);
1765a68b2e3SDavid S. Miller dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n",
1775a68b2e3SDavid S. Miller value_tcr, value_or));
1781da177e4SLinus Torvalds return parport_sunbpp_read_control(p);
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds
parport_sunbpp_write_control(struct parport * p,unsigned char d)1811da177e4SLinus Torvalds static void parport_sunbpp_write_control(struct parport *p, unsigned char d)
1821da177e4SLinus Torvalds {
1831da177e4SLinus Torvalds const unsigned char wm = (PARPORT_CONTROL_STROBE |
1841da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
1851da177e4SLinus Torvalds PARPORT_CONTROL_INIT |
1861da177e4SLinus Torvalds PARPORT_CONTROL_SELECT);
1871da177e4SLinus Torvalds
1881da177e4SLinus Torvalds parport_sunbpp_frob_control (p, wm, d & wm);
1891da177e4SLinus Torvalds }
1901da177e4SLinus Torvalds
parport_sunbpp_read_status(struct parport * p)1911da177e4SLinus Torvalds static unsigned char parport_sunbpp_read_status(struct parport *p)
1921da177e4SLinus Torvalds {
1931da177e4SLinus Torvalds return status_sunbpp_to_pc(p);
1941da177e4SLinus Torvalds }
1951da177e4SLinus Torvalds
parport_sunbpp_data_forward(struct parport * p)1961da177e4SLinus Torvalds static void parport_sunbpp_data_forward (struct parport *p)
1971da177e4SLinus Torvalds {
1981da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
1991da177e4SLinus Torvalds unsigned char value_tcr = sbus_readb(®s->p_tcr);
2001da177e4SLinus Torvalds
2011da177e4SLinus Torvalds dprintk((KERN_DEBUG "forward\n"));
2021da177e4SLinus Torvalds value_tcr &= ~P_TCR_DIR;
2031da177e4SLinus Torvalds sbus_writeb(value_tcr, ®s->p_tcr);
2041da177e4SLinus Torvalds }
2051da177e4SLinus Torvalds
parport_sunbpp_data_reverse(struct parport * p)2061da177e4SLinus Torvalds static void parport_sunbpp_data_reverse (struct parport *p)
2071da177e4SLinus Torvalds {
2081da177e4SLinus Torvalds struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
2091da177e4SLinus Torvalds u8 val = sbus_readb(®s->p_tcr);
2101da177e4SLinus Torvalds
2111da177e4SLinus Torvalds dprintk((KERN_DEBUG "reverse\n"));
2121da177e4SLinus Torvalds val |= P_TCR_DIR;
2131da177e4SLinus Torvalds sbus_writeb(val, ®s->p_tcr);
2141da177e4SLinus Torvalds }
2151da177e4SLinus Torvalds
parport_sunbpp_init_state(struct pardevice * dev,struct parport_state * s)2161da177e4SLinus Torvalds static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s)
2171da177e4SLinus Torvalds {
2181da177e4SLinus Torvalds s->u.pc.ctr = 0xc;
2191da177e4SLinus Torvalds s->u.pc.ecr = 0x0;
2201da177e4SLinus Torvalds }
2211da177e4SLinus Torvalds
parport_sunbpp_save_state(struct parport * p,struct parport_state * s)2221da177e4SLinus Torvalds static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s)
2231da177e4SLinus Torvalds {
2241da177e4SLinus Torvalds s->u.pc.ctr = parport_sunbpp_read_control(p);
2251da177e4SLinus Torvalds }
2261da177e4SLinus Torvalds
parport_sunbpp_restore_state(struct parport * p,struct parport_state * s)2271da177e4SLinus Torvalds static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s)
2281da177e4SLinus Torvalds {
2291da177e4SLinus Torvalds parport_sunbpp_write_control(p, s->u.pc.ctr);
2301da177e4SLinus Torvalds }
2311da177e4SLinus Torvalds
2321da177e4SLinus Torvalds static struct parport_operations parport_sunbpp_ops =
2331da177e4SLinus Torvalds {
2341da177e4SLinus Torvalds .write_data = parport_sunbpp_write_data,
2351da177e4SLinus Torvalds .read_data = parport_sunbpp_read_data,
2361da177e4SLinus Torvalds
2371da177e4SLinus Torvalds .write_control = parport_sunbpp_write_control,
2381da177e4SLinus Torvalds .read_control = parport_sunbpp_read_control,
2391da177e4SLinus Torvalds .frob_control = parport_sunbpp_frob_control,
2401da177e4SLinus Torvalds
2411da177e4SLinus Torvalds .read_status = parport_sunbpp_read_status,
2421da177e4SLinus Torvalds
2431da177e4SLinus Torvalds .enable_irq = parport_sunbpp_enable_irq,
2441da177e4SLinus Torvalds .disable_irq = parport_sunbpp_disable_irq,
2451da177e4SLinus Torvalds
2461da177e4SLinus Torvalds .data_forward = parport_sunbpp_data_forward,
2471da177e4SLinus Torvalds .data_reverse = parport_sunbpp_data_reverse,
2481da177e4SLinus Torvalds
2491da177e4SLinus Torvalds .init_state = parport_sunbpp_init_state,
2501da177e4SLinus Torvalds .save_state = parport_sunbpp_save_state,
2511da177e4SLinus Torvalds .restore_state = parport_sunbpp_restore_state,
2521da177e4SLinus Torvalds
2531da177e4SLinus Torvalds .epp_write_data = parport_ieee1284_epp_write_data,
2541da177e4SLinus Torvalds .epp_read_data = parport_ieee1284_epp_read_data,
2551da177e4SLinus Torvalds .epp_write_addr = parport_ieee1284_epp_write_addr,
2561da177e4SLinus Torvalds .epp_read_addr = parport_ieee1284_epp_read_addr,
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds .ecp_write_data = parport_ieee1284_ecp_write_data,
2591da177e4SLinus Torvalds .ecp_read_data = parport_ieee1284_ecp_read_data,
2601da177e4SLinus Torvalds .ecp_write_addr = parport_ieee1284_ecp_write_addr,
2611da177e4SLinus Torvalds
2621da177e4SLinus Torvalds .compat_write_data = parport_ieee1284_write_compat,
2631da177e4SLinus Torvalds .nibble_read_data = parport_ieee1284_read_nibble,
2641da177e4SLinus Torvalds .byte_read_data = parport_ieee1284_read_byte,
2651da177e4SLinus Torvalds
2661da177e4SLinus Torvalds .owner = THIS_MODULE,
2671da177e4SLinus Torvalds };
2681da177e4SLinus Torvalds
bpp_probe(struct platform_device * op)269312facafSGreg Kroah-Hartman static int bpp_probe(struct platform_device *op)
2701da177e4SLinus Torvalds {
2711da177e4SLinus Torvalds struct parport_operations *ops;
2721da177e4SLinus Torvalds struct bpp_regs __iomem *regs;
27327167e0eSDavid S. Miller int irq, dma, err = 0, size;
2741da177e4SLinus Torvalds unsigned char value_tcr;
27527167e0eSDavid S. Miller void __iomem *base;
27627167e0eSDavid S. Miller struct parport *p;
2771da177e4SLinus Torvalds
2781636f8acSGrant Likely irq = op->archdata.irqs[0];
27927167e0eSDavid S. Miller base = of_ioremap(&op->resource[0], 0,
28027167e0eSDavid S. Miller resource_size(&op->resource[0]),
2811da177e4SLinus Torvalds "sunbpp");
2821da177e4SLinus Torvalds if (!base)
2834f62d158SDavid S. Miller return -ENODEV;
2841da177e4SLinus Torvalds
28527167e0eSDavid S. Miller size = resource_size(&op->resource[0]);
2861da177e4SLinus Torvalds dma = PARPORT_DMA_NONE;
2871da177e4SLinus Torvalds
2882451a848SSilviu-Mihai Popescu ops = kmemdup(&parport_sunbpp_ops, sizeof(struct parport_operations),
2892451a848SSilviu-Mihai Popescu GFP_KERNEL);
290faa1a473SJulia Lawall if (!ops) {
291faa1a473SJulia Lawall err = -ENOMEM;
2924f62d158SDavid S. Miller goto out_unmap;
293faa1a473SJulia Lawall }
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvalds dprintk(("register_port\n"));
296faa1a473SJulia Lawall if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) {
297faa1a473SJulia Lawall err = -ENOMEM;
2984f62d158SDavid S. Miller goto out_free_ops;
299faa1a473SJulia Lawall }
3001da177e4SLinus Torvalds
3011da177e4SLinus Torvalds p->size = size;
30227167e0eSDavid S. Miller p->dev = &op->dev;
3031da177e4SLinus Torvalds
3043f2e40dfSJeff Garzik if ((err = request_irq(p->irq, parport_irq_handler,
305dace1453SThomas Gleixner IRQF_SHARED, p->name, p)) != 0) {
3064f62d158SDavid S. Miller goto out_put_port;
3071da177e4SLinus Torvalds }
3084f62d158SDavid S. Miller
3091da177e4SLinus Torvalds parport_sunbpp_enable_irq(p);
3101da177e4SLinus Torvalds
3111da177e4SLinus Torvalds regs = (struct bpp_regs __iomem *)p->base;
3124f62d158SDavid S. Miller
3131da177e4SLinus Torvalds value_tcr = sbus_readb(®s->p_tcr);
3141da177e4SLinus Torvalds value_tcr &= ~P_TCR_DIR;
3151da177e4SLinus Torvalds sbus_writeb(value_tcr, ®s->p_tcr);
3161da177e4SLinus Torvalds
317decf26f6SJoe Perches pr_info("%s: sunbpp at 0x%lx\n", p->name, p->base);
3184f62d158SDavid S. Miller
31927167e0eSDavid S. Miller dev_set_drvdata(&op->dev, p);
3204f62d158SDavid S. Miller
3211da177e4SLinus Torvalds parport_announce_port(p);
3221da177e4SLinus Torvalds
3234f62d158SDavid S. Miller return 0;
3241da177e4SLinus Torvalds
3254f62d158SDavid S. Miller out_put_port:
3261da177e4SLinus Torvalds parport_put_port(p);
3274f62d158SDavid S. Miller
3284f62d158SDavid S. Miller out_free_ops:
3291da177e4SLinus Torvalds kfree(ops);
3304f62d158SDavid S. Miller
3314f62d158SDavid S. Miller out_unmap:
33227167e0eSDavid S. Miller of_iounmap(&op->resource[0], base, size);
3334f62d158SDavid S. Miller
3341da177e4SLinus Torvalds return err;
3351da177e4SLinus Torvalds }
3361da177e4SLinus Torvalds
bpp_remove(struct platform_device * op)337312facafSGreg Kroah-Hartman static int bpp_remove(struct platform_device *op)
3381da177e4SLinus Torvalds {
33927167e0eSDavid S. Miller struct parport *p = dev_get_drvdata(&op->dev);
3401da177e4SLinus Torvalds struct parport_operations *ops = p->ops;
3414f62d158SDavid S. Miller
3421da177e4SLinus Torvalds parport_remove_port(p);
3431da177e4SLinus Torvalds
3441da177e4SLinus Torvalds if (p->irq != PARPORT_IRQ_NONE) {
3451da177e4SLinus Torvalds parport_sunbpp_disable_irq(p);
3461da177e4SLinus Torvalds free_irq(p->irq, p);
3471da177e4SLinus Torvalds }
3484f62d158SDavid S. Miller
34927167e0eSDavid S. Miller of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size);
3501da177e4SLinus Torvalds parport_put_port(p);
3511da177e4SLinus Torvalds kfree(ops);
3524f62d158SDavid S. Miller
35327167e0eSDavid S. Miller dev_set_drvdata(&op->dev, NULL);
3544f62d158SDavid S. Miller
3554f62d158SDavid S. Miller return 0;
3561da177e4SLinus Torvalds }
3574f62d158SDavid S. Miller
358fd098316SDavid S. Miller static const struct of_device_id bpp_match[] = {
3594f62d158SDavid S. Miller {
3604f62d158SDavid S. Miller .name = "SUNW,bpp",
3614f62d158SDavid S. Miller },
3624f62d158SDavid S. Miller {},
3634f62d158SDavid S. Miller };
3644f62d158SDavid S. Miller
36509ec4314SDavid S. Miller MODULE_DEVICE_TABLE(of, bpp_match);
3664f62d158SDavid S. Miller
3674ebb24f7SGrant Likely static struct platform_driver bpp_sbus_driver = {
3684018294bSGrant Likely .driver = {
3694f62d158SDavid S. Miller .name = "bpp",
3704018294bSGrant Likely .of_match_table = bpp_match,
3714018294bSGrant Likely },
3724f62d158SDavid S. Miller .probe = bpp_probe,
373312facafSGreg Kroah-Hartman .remove = bpp_remove,
3744f62d158SDavid S. Miller };
3754f62d158SDavid S. Miller
376782ee877SAxel Lin module_platform_driver(bpp_sbus_driver);
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds MODULE_AUTHOR("Derrick J Brashear");
3791da177e4SLinus Torvalds MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
3804f62d158SDavid S. Miller MODULE_VERSION("2.0");
3811da177e4SLinus Torvalds MODULE_LICENSE("GPL");
382