162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* parport_sunbpp.c: Parallel-port routines for SBUS 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Author: Derrick J. Brashear <shadow@dementia.org> 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * based on work by: 762306a36Sopenharmony_ci * Phil Blundell <philb@gnu.org> 862306a36Sopenharmony_ci * Tim Waugh <tim@cyberelk.demon.co.uk> 962306a36Sopenharmony_ci * Jose Renau <renau@acm.org> 1062306a36Sopenharmony_ci * David Campbell <campbell@tirian.che.curtin.edu.au> 1162306a36Sopenharmony_ci * Grant Guenther <grant@torque.net> 1262306a36Sopenharmony_ci * Eddie C. Dost <ecd@skynet.be> 1362306a36Sopenharmony_ci * Stephen Williams (steve@icarus.com) 1462306a36Sopenharmony_ci * Gus Baldauf (gbaldauf@ix.netcom.com) 1562306a36Sopenharmony_ci * Peter Zaitcev 1662306a36Sopenharmony_ci * Tom Dyas 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Updated to new SBUS device framework: David S. Miller <davem@davemloft.net> 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/string.h> 2362306a36Sopenharmony_ci#include <linux/module.h> 2462306a36Sopenharmony_ci#include <linux/delay.h> 2562306a36Sopenharmony_ci#include <linux/errno.h> 2662306a36Sopenharmony_ci#include <linux/ioport.h> 2762306a36Sopenharmony_ci#include <linux/kernel.h> 2862306a36Sopenharmony_ci#include <linux/slab.h> 2962306a36Sopenharmony_ci#include <linux/init.h> 3062306a36Sopenharmony_ci#include <linux/of.h> 3162306a36Sopenharmony_ci#include <linux/platform_device.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <linux/parport.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <asm/ptrace.h> 3662306a36Sopenharmony_ci#include <linux/interrupt.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <asm/io.h> 3962306a36Sopenharmony_ci#include <asm/oplib.h> /* OpenProm Library */ 4062306a36Sopenharmony_ci#include <asm/dma.h> /* BPP uses LSI 64854 for DMA */ 4162306a36Sopenharmony_ci#include <asm/irq.h> 4262306a36Sopenharmony_ci#include <asm/sunbpp.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#undef __SUNBPP_DEBUG 4562306a36Sopenharmony_ci#ifdef __SUNBPP_DEBUG 4662306a36Sopenharmony_ci#define dprintk(x) printk x 4762306a36Sopenharmony_ci#else 4862306a36Sopenharmony_ci#define dprintk(x) 4962306a36Sopenharmony_ci#endif 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic void parport_sunbpp_disable_irq(struct parport *p) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 5462306a36Sopenharmony_ci u32 tmp; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci tmp = sbus_readl(®s->p_csr); 5762306a36Sopenharmony_ci tmp &= ~DMA_INT_ENAB; 5862306a36Sopenharmony_ci sbus_writel(tmp, ®s->p_csr); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic void parport_sunbpp_enable_irq(struct parport *p) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 6462306a36Sopenharmony_ci u32 tmp; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci tmp = sbus_readl(®s->p_csr); 6762306a36Sopenharmony_ci tmp |= DMA_INT_ENAB; 6862306a36Sopenharmony_ci sbus_writel(tmp, ®s->p_csr); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic void parport_sunbpp_write_data(struct parport *p, unsigned char d) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci sbus_writeb(d, ®s->p_dr); 7662306a36Sopenharmony_ci dprintk((KERN_DEBUG "wrote 0x%x\n", d)); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic unsigned char parport_sunbpp_read_data(struct parport *p) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return sbus_readb(®s->p_dr); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic unsigned char status_sunbpp_to_pc(struct parport *p) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 8962306a36Sopenharmony_ci unsigned char bits = 0; 9062306a36Sopenharmony_ci unsigned char value_tcr = sbus_readb(®s->p_tcr); 9162306a36Sopenharmony_ci unsigned char value_ir = sbus_readb(®s->p_ir); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (!(value_ir & P_IR_ERR)) 9462306a36Sopenharmony_ci bits |= PARPORT_STATUS_ERROR; 9562306a36Sopenharmony_ci if (!(value_ir & P_IR_SLCT)) 9662306a36Sopenharmony_ci bits |= PARPORT_STATUS_SELECT; 9762306a36Sopenharmony_ci if (!(value_ir & P_IR_PE)) 9862306a36Sopenharmony_ci bits |= PARPORT_STATUS_PAPEROUT; 9962306a36Sopenharmony_ci if (value_tcr & P_TCR_ACK) 10062306a36Sopenharmony_ci bits |= PARPORT_STATUS_ACK; 10162306a36Sopenharmony_ci if (!(value_tcr & P_TCR_BUSY)) 10262306a36Sopenharmony_ci bits |= PARPORT_STATUS_BUSY; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", value_tcr, value_ir)); 10562306a36Sopenharmony_ci dprintk((KERN_DEBUG "read status 0x%x\n", bits)); 10662306a36Sopenharmony_ci return bits; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic unsigned char control_sunbpp_to_pc(struct parport *p) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 11262306a36Sopenharmony_ci unsigned char bits = 0; 11362306a36Sopenharmony_ci unsigned char value_tcr = sbus_readb(®s->p_tcr); 11462306a36Sopenharmony_ci unsigned char value_or = sbus_readb(®s->p_or); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!(value_tcr & P_TCR_DS)) 11762306a36Sopenharmony_ci bits |= PARPORT_CONTROL_STROBE; 11862306a36Sopenharmony_ci if (!(value_or & P_OR_AFXN)) 11962306a36Sopenharmony_ci bits |= PARPORT_CONTROL_AUTOFD; 12062306a36Sopenharmony_ci if (!(value_or & P_OR_INIT)) 12162306a36Sopenharmony_ci bits |= PARPORT_CONTROL_INIT; 12262306a36Sopenharmony_ci if (value_or & P_OR_SLCT_IN) 12362306a36Sopenharmony_ci bits |= PARPORT_CONTROL_SELECT; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", value_tcr, value_or)); 12662306a36Sopenharmony_ci dprintk((KERN_DEBUG "read control 0x%x\n", bits)); 12762306a36Sopenharmony_ci return bits; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic unsigned char parport_sunbpp_read_control(struct parport *p) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci return control_sunbpp_to_pc(p); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic unsigned char parport_sunbpp_frob_control(struct parport *p, 13662306a36Sopenharmony_ci unsigned char mask, 13762306a36Sopenharmony_ci unsigned char val) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 14062306a36Sopenharmony_ci unsigned char value_tcr = sbus_readb(®s->p_tcr); 14162306a36Sopenharmony_ci unsigned char value_or = sbus_readb(®s->p_or); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", 14462306a36Sopenharmony_ci value_tcr, value_or)); 14562306a36Sopenharmony_ci if (mask & PARPORT_CONTROL_STROBE) { 14662306a36Sopenharmony_ci if (val & PARPORT_CONTROL_STROBE) { 14762306a36Sopenharmony_ci value_tcr &= ~P_TCR_DS; 14862306a36Sopenharmony_ci } else { 14962306a36Sopenharmony_ci value_tcr |= P_TCR_DS; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci if (mask & PARPORT_CONTROL_AUTOFD) { 15362306a36Sopenharmony_ci if (val & PARPORT_CONTROL_AUTOFD) { 15462306a36Sopenharmony_ci value_or &= ~P_OR_AFXN; 15562306a36Sopenharmony_ci } else { 15662306a36Sopenharmony_ci value_or |= P_OR_AFXN; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci if (mask & PARPORT_CONTROL_INIT) { 16062306a36Sopenharmony_ci if (val & PARPORT_CONTROL_INIT) { 16162306a36Sopenharmony_ci value_or &= ~P_OR_INIT; 16262306a36Sopenharmony_ci } else { 16362306a36Sopenharmony_ci value_or |= P_OR_INIT; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci if (mask & PARPORT_CONTROL_SELECT) { 16762306a36Sopenharmony_ci if (val & PARPORT_CONTROL_SELECT) { 16862306a36Sopenharmony_ci value_or |= P_OR_SLCT_IN; 16962306a36Sopenharmony_ci } else { 17062306a36Sopenharmony_ci value_or &= ~P_OR_SLCT_IN; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci sbus_writeb(value_or, ®s->p_or); 17562306a36Sopenharmony_ci sbus_writeb(value_tcr, ®s->p_tcr); 17662306a36Sopenharmony_ci dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", 17762306a36Sopenharmony_ci value_tcr, value_or)); 17862306a36Sopenharmony_ci return parport_sunbpp_read_control(p); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic void parport_sunbpp_write_control(struct parport *p, unsigned char d) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci const unsigned char wm = (PARPORT_CONTROL_STROBE | 18462306a36Sopenharmony_ci PARPORT_CONTROL_AUTOFD | 18562306a36Sopenharmony_ci PARPORT_CONTROL_INIT | 18662306a36Sopenharmony_ci PARPORT_CONTROL_SELECT); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci parport_sunbpp_frob_control (p, wm, d & wm); 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic unsigned char parport_sunbpp_read_status(struct parport *p) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci return status_sunbpp_to_pc(p); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic void parport_sunbpp_data_forward (struct parport *p) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 19962306a36Sopenharmony_ci unsigned char value_tcr = sbus_readb(®s->p_tcr); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci dprintk((KERN_DEBUG "forward\n")); 20262306a36Sopenharmony_ci value_tcr &= ~P_TCR_DIR; 20362306a36Sopenharmony_ci sbus_writeb(value_tcr, ®s->p_tcr); 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic void parport_sunbpp_data_reverse (struct parport *p) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 20962306a36Sopenharmony_ci u8 val = sbus_readb(®s->p_tcr); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci dprintk((KERN_DEBUG "reverse\n")); 21262306a36Sopenharmony_ci val |= P_TCR_DIR; 21362306a36Sopenharmony_ci sbus_writeb(val, ®s->p_tcr); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci s->u.pc.ctr = 0xc; 21962306a36Sopenharmony_ci s->u.pc.ecr = 0x0; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic void parport_sunbpp_save_state(struct parport *p, struct parport_state *s) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci s->u.pc.ctr = parport_sunbpp_read_control(p); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci parport_sunbpp_write_control(p, s->u.pc.ctr); 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic struct parport_operations parport_sunbpp_ops = 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci .write_data = parport_sunbpp_write_data, 23562306a36Sopenharmony_ci .read_data = parport_sunbpp_read_data, 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci .write_control = parport_sunbpp_write_control, 23862306a36Sopenharmony_ci .read_control = parport_sunbpp_read_control, 23962306a36Sopenharmony_ci .frob_control = parport_sunbpp_frob_control, 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci .read_status = parport_sunbpp_read_status, 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci .enable_irq = parport_sunbpp_enable_irq, 24462306a36Sopenharmony_ci .disable_irq = parport_sunbpp_disable_irq, 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci .data_forward = parport_sunbpp_data_forward, 24762306a36Sopenharmony_ci .data_reverse = parport_sunbpp_data_reverse, 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci .init_state = parport_sunbpp_init_state, 25062306a36Sopenharmony_ci .save_state = parport_sunbpp_save_state, 25162306a36Sopenharmony_ci .restore_state = parport_sunbpp_restore_state, 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci .epp_write_data = parport_ieee1284_epp_write_data, 25462306a36Sopenharmony_ci .epp_read_data = parport_ieee1284_epp_read_data, 25562306a36Sopenharmony_ci .epp_write_addr = parport_ieee1284_epp_write_addr, 25662306a36Sopenharmony_ci .epp_read_addr = parport_ieee1284_epp_read_addr, 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci .ecp_write_data = parport_ieee1284_ecp_write_data, 25962306a36Sopenharmony_ci .ecp_read_data = parport_ieee1284_ecp_read_data, 26062306a36Sopenharmony_ci .ecp_write_addr = parport_ieee1284_ecp_write_addr, 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci .compat_write_data = parport_ieee1284_write_compat, 26362306a36Sopenharmony_ci .nibble_read_data = parport_ieee1284_read_nibble, 26462306a36Sopenharmony_ci .byte_read_data = parport_ieee1284_read_byte, 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci .owner = THIS_MODULE, 26762306a36Sopenharmony_ci}; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int bpp_probe(struct platform_device *op) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct parport_operations *ops; 27262306a36Sopenharmony_ci struct bpp_regs __iomem *regs; 27362306a36Sopenharmony_ci int irq, dma, err = 0, size; 27462306a36Sopenharmony_ci unsigned char value_tcr; 27562306a36Sopenharmony_ci void __iomem *base; 27662306a36Sopenharmony_ci struct parport *p; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci irq = op->archdata.irqs[0]; 27962306a36Sopenharmony_ci base = of_ioremap(&op->resource[0], 0, 28062306a36Sopenharmony_ci resource_size(&op->resource[0]), 28162306a36Sopenharmony_ci "sunbpp"); 28262306a36Sopenharmony_ci if (!base) 28362306a36Sopenharmony_ci return -ENODEV; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci size = resource_size(&op->resource[0]); 28662306a36Sopenharmony_ci dma = PARPORT_DMA_NONE; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci ops = kmemdup(&parport_sunbpp_ops, sizeof(struct parport_operations), 28962306a36Sopenharmony_ci GFP_KERNEL); 29062306a36Sopenharmony_ci if (!ops) { 29162306a36Sopenharmony_ci err = -ENOMEM; 29262306a36Sopenharmony_ci goto out_unmap; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci dprintk(("register_port\n")); 29662306a36Sopenharmony_ci if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) { 29762306a36Sopenharmony_ci err = -ENOMEM; 29862306a36Sopenharmony_ci goto out_free_ops; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci p->size = size; 30262306a36Sopenharmony_ci p->dev = &op->dev; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci if ((err = request_irq(p->irq, parport_irq_handler, 30562306a36Sopenharmony_ci IRQF_SHARED, p->name, p)) != 0) { 30662306a36Sopenharmony_ci goto out_put_port; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci parport_sunbpp_enable_irq(p); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci regs = (struct bpp_regs __iomem *)p->base; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci value_tcr = sbus_readb(®s->p_tcr); 31462306a36Sopenharmony_ci value_tcr &= ~P_TCR_DIR; 31562306a36Sopenharmony_ci sbus_writeb(value_tcr, ®s->p_tcr); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci pr_info("%s: sunbpp at 0x%lx\n", p->name, p->base); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci dev_set_drvdata(&op->dev, p); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci parport_announce_port(p); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci return 0; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ciout_put_port: 32662306a36Sopenharmony_ci parport_put_port(p); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ciout_free_ops: 32962306a36Sopenharmony_ci kfree(ops); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ciout_unmap: 33262306a36Sopenharmony_ci of_iounmap(&op->resource[0], base, size); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return err; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic int bpp_remove(struct platform_device *op) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci struct parport *p = dev_get_drvdata(&op->dev); 34062306a36Sopenharmony_ci struct parport_operations *ops = p->ops; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci parport_remove_port(p); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (p->irq != PARPORT_IRQ_NONE) { 34562306a36Sopenharmony_ci parport_sunbpp_disable_irq(p); 34662306a36Sopenharmony_ci free_irq(p->irq, p); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size); 35062306a36Sopenharmony_ci parport_put_port(p); 35162306a36Sopenharmony_ci kfree(ops); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci dev_set_drvdata(&op->dev, NULL); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci return 0; 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic const struct of_device_id bpp_match[] = { 35962306a36Sopenharmony_ci { 36062306a36Sopenharmony_ci .name = "SUNW,bpp", 36162306a36Sopenharmony_ci }, 36262306a36Sopenharmony_ci {}, 36362306a36Sopenharmony_ci}; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, bpp_match); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic struct platform_driver bpp_sbus_driver = { 36862306a36Sopenharmony_ci .driver = { 36962306a36Sopenharmony_ci .name = "bpp", 37062306a36Sopenharmony_ci .of_match_table = bpp_match, 37162306a36Sopenharmony_ci }, 37262306a36Sopenharmony_ci .probe = bpp_probe, 37362306a36Sopenharmony_ci .remove = bpp_remove, 37462306a36Sopenharmony_ci}; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cimodule_platform_driver(bpp_sbus_driver); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ciMODULE_AUTHOR("Derrick J Brashear"); 37962306a36Sopenharmony_ciMODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); 38062306a36Sopenharmony_ciMODULE_VERSION("2.0"); 38162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 382