1/* parport_sunbpp.c: Parallel-port routines for SBUS 2 * 3 * Author: Derrick J. Brashear <shadow@dementia.org> 4 * 5 * based on work by: 6 * Phil Blundell <philb@gnu.org> 7 * Tim Waugh <tim@cyberelk.demon.co.uk> 8 * Jose Renau <renau@acm.org> 9 * David Campbell <campbell@tirian.che.curtin.edu.au> 10 * Grant Guenther <grant@torque.net> 11 * Eddie C. Dost <ecd@skynet.be> 12 * Stephen Williams (steve@icarus.com) 13 * Gus Baldauf (gbaldauf@ix.netcom.com) 14 * Peter Zaitcev 15 * Tom Dyas 16 * 17 * Updated to new SBUS device framework: David S. Miller <davem@davemloft.net> 18 * 19 */ 20 21#include <linux/string.h> 22#include <linux/module.h> 23#include <linux/delay.h> 24#include <linux/errno.h> 25#include <linux/ioport.h> 26#include <linux/kernel.h> 27#include <linux/slab.h> 28#include <linux/init.h> 29 30#include <linux/parport.h> 31 32#include <asm/ptrace.h> 33#include <linux/interrupt.h> 34 35#include <asm/io.h> 36#include <asm/oplib.h> /* OpenProm Library */ 37#include <asm/sbus.h> 38#include <asm/dma.h> /* BPP uses LSI 64854 for DMA */ 39#include <asm/irq.h> 40#include <asm/sunbpp.h> 41 42#undef __SUNBPP_DEBUG 43#ifdef __SUNBPP_DEBUG 44#define dprintk(x) printk x 45#else 46#define dprintk(x) 47#endif 48 49static irqreturn_t parport_sunbpp_interrupt(int irq, void *dev_id) 50{ 51 parport_generic_irq(irq, (struct parport *) dev_id); 52 return IRQ_HANDLED; 53} 54 55static void parport_sunbpp_disable_irq(struct parport *p) 56{ 57 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 58 u32 tmp; 59 60 tmp = sbus_readl(®s->p_csr); 61 tmp &= ~DMA_INT_ENAB; 62 sbus_writel(tmp, ®s->p_csr); 63} 64 65static void parport_sunbpp_enable_irq(struct parport *p) 66{ 67 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 68 u32 tmp; 69 70 tmp = sbus_readl(®s->p_csr); 71 tmp |= DMA_INT_ENAB; 72 sbus_writel(tmp, ®s->p_csr); 73} 74 75static void parport_sunbpp_write_data(struct parport *p, unsigned char d) 76{ 77 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 78 79 sbus_writeb(d, ®s->p_dr); 80 dprintk((KERN_DEBUG "wrote 0x%x\n", d)); 81} 82 83static unsigned char parport_sunbpp_read_data(struct parport *p) 84{ 85 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 86 87 return sbus_readb(®s->p_dr); 88} 89 90 91static unsigned char status_sunbpp_to_pc(struct parport *p) 92{ 93 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 94 unsigned char bits = 0; 95 unsigned char value_tcr = sbus_readb(®s->p_tcr); 96 unsigned char value_ir = sbus_readb(®s->p_ir); 97 98 if (!(value_ir & P_IR_ERR)) 99 bits |= PARPORT_STATUS_ERROR; 100 if (!(value_ir & P_IR_SLCT)) 101 bits |= PARPORT_STATUS_SELECT; 102 if (!(value_ir & P_IR_PE)) 103 bits |= PARPORT_STATUS_PAPEROUT; 104 if (value_tcr & P_TCR_ACK) 105 bits |= PARPORT_STATUS_ACK; 106 if (!(value_tcr & P_TCR_BUSY)) 107 bits |= PARPORT_STATUS_BUSY; 108 109 dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", value_tcr, value_ir)); 110 dprintk((KERN_DEBUG "read status 0x%x\n", bits)); 111 return bits; 112} 113 114static unsigned char control_sunbpp_to_pc(struct parport *p) 115{ 116 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 117 unsigned char bits = 0; 118 unsigned char value_tcr = sbus_readb(®s->p_tcr); 119 unsigned char value_or = sbus_readb(®s->p_or); 120 121 if (!(value_tcr & P_TCR_DS)) 122 bits |= PARPORT_CONTROL_STROBE; 123 if (!(value_or & P_OR_AFXN)) 124 bits |= PARPORT_CONTROL_AUTOFD; 125 if (!(value_or & P_OR_INIT)) 126 bits |= PARPORT_CONTROL_INIT; 127 if (value_or & P_OR_SLCT_IN) 128 bits |= PARPORT_CONTROL_SELECT; 129 130 dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", value_tcr, value_or)); 131 dprintk((KERN_DEBUG "read control 0x%x\n", bits)); 132 return bits; 133} 134 135static unsigned char parport_sunbpp_read_control(struct parport *p) 136{ 137 return control_sunbpp_to_pc(p); 138} 139 140static unsigned char parport_sunbpp_frob_control(struct parport *p, 141 unsigned char mask, 142 unsigned char val) 143{ 144 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 145 unsigned char value_tcr = sbus_readb(®s->p_tcr); 146 unsigned char value_or = sbus_readb(®s->p_or); 147 148 dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", 149 value_tcr, value_or)); 150 if (mask & PARPORT_CONTROL_STROBE) { 151 if (val & PARPORT_CONTROL_STROBE) { 152 value_tcr &= ~P_TCR_DS; 153 } else { 154 value_tcr |= P_TCR_DS; 155 } 156 } 157 if (mask & PARPORT_CONTROL_AUTOFD) { 158 if (val & PARPORT_CONTROL_AUTOFD) { 159 value_or &= ~P_OR_AFXN; 160 } else { 161 value_or |= P_OR_AFXN; 162 } 163 } 164 if (mask & PARPORT_CONTROL_INIT) { 165 if (val & PARPORT_CONTROL_INIT) { 166 value_or &= ~P_OR_INIT; 167 } else { 168 value_or |= P_OR_INIT; 169 } 170 } 171 if (mask & PARPORT_CONTROL_SELECT) { 172 if (val & PARPORT_CONTROL_SELECT) { 173 value_or |= P_OR_SLCT_IN; 174 } else { 175 value_or &= ~P_OR_SLCT_IN; 176 } 177 } 178 179 sbus_writeb(value_or, ®s->p_or); 180 sbus_writeb(value_tcr, ®s->p_tcr); 181 dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", 182 value_tcr, value_or)); 183 return parport_sunbpp_read_control(p); 184} 185 186static void parport_sunbpp_write_control(struct parport *p, unsigned char d) 187{ 188 const unsigned char wm = (PARPORT_CONTROL_STROBE | 189 PARPORT_CONTROL_AUTOFD | 190 PARPORT_CONTROL_INIT | 191 PARPORT_CONTROL_SELECT); 192 193 parport_sunbpp_frob_control (p, wm, d & wm); 194} 195 196static unsigned char parport_sunbpp_read_status(struct parport *p) 197{ 198 return status_sunbpp_to_pc(p); 199} 200 201static void parport_sunbpp_data_forward (struct parport *p) 202{ 203 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 204 unsigned char value_tcr = sbus_readb(®s->p_tcr); 205 206 dprintk((KERN_DEBUG "forward\n")); 207 value_tcr &= ~P_TCR_DIR; 208 sbus_writeb(value_tcr, ®s->p_tcr); 209} 210 211static void parport_sunbpp_data_reverse (struct parport *p) 212{ 213 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 214 u8 val = sbus_readb(®s->p_tcr); 215 216 dprintk((KERN_DEBUG "reverse\n")); 217 val |= P_TCR_DIR; 218 sbus_writeb(val, ®s->p_tcr); 219} 220 221static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s) 222{ 223 s->u.pc.ctr = 0xc; 224 s->u.pc.ecr = 0x0; 225} 226 227static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s) 228{ 229 s->u.pc.ctr = parport_sunbpp_read_control(p); 230} 231 232static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s) 233{ 234 parport_sunbpp_write_control(p, s->u.pc.ctr); 235} 236 237static struct parport_operations parport_sunbpp_ops = 238{ 239 .write_data = parport_sunbpp_write_data, 240 .read_data = parport_sunbpp_read_data, 241 242 .write_control = parport_sunbpp_write_control, 243 .read_control = parport_sunbpp_read_control, 244 .frob_control = parport_sunbpp_frob_control, 245 246 .read_status = parport_sunbpp_read_status, 247 248 .enable_irq = parport_sunbpp_enable_irq, 249 .disable_irq = parport_sunbpp_disable_irq, 250 251 .data_forward = parport_sunbpp_data_forward, 252 .data_reverse = parport_sunbpp_data_reverse, 253 254 .init_state = parport_sunbpp_init_state, 255 .save_state = parport_sunbpp_save_state, 256 .restore_state = parport_sunbpp_restore_state, 257 258 .epp_write_data = parport_ieee1284_epp_write_data, 259 .epp_read_data = parport_ieee1284_epp_read_data, 260 .epp_write_addr = parport_ieee1284_epp_write_addr, 261 .epp_read_addr = parport_ieee1284_epp_read_addr, 262 263 .ecp_write_data = parport_ieee1284_ecp_write_data, 264 .ecp_read_data = parport_ieee1284_ecp_read_data, 265 .ecp_write_addr = parport_ieee1284_ecp_write_addr, 266 267 .compat_write_data = parport_ieee1284_write_compat, 268 .nibble_read_data = parport_ieee1284_read_nibble, 269 .byte_read_data = parport_ieee1284_read_byte, 270 271 .owner = THIS_MODULE, 272}; 273 274static int __devinit init_one_port(struct sbus_dev *sdev) 275{ 276 struct parport *p; 277 /* at least in theory there may be a "we don't dma" case */ 278 struct parport_operations *ops; 279 void __iomem *base; 280 int irq, dma, err = 0, size; 281 struct bpp_regs __iomem *regs; 282 unsigned char value_tcr; 283 284 irq = sdev->irqs[0]; 285 base = sbus_ioremap(&sdev->resource[0], 0, 286 sdev->reg_addrs[0].reg_size, 287 "sunbpp"); 288 if (!base) 289 return -ENODEV; 290 291 size = sdev->reg_addrs[0].reg_size; 292 dma = PARPORT_DMA_NONE; 293 294 ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); 295 if (!ops) 296 goto out_unmap; 297 298 memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); 299 300 dprintk(("register_port\n")); 301 if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) 302 goto out_free_ops; 303 304 p->size = size; 305 p->dev = &sdev->ofdev.dev; 306 307 if ((err = request_irq(p->irq, parport_sunbpp_interrupt, 308 IRQF_SHARED, p->name, p)) != 0) { 309 goto out_put_port; 310 } 311 312 parport_sunbpp_enable_irq(p); 313 314 regs = (struct bpp_regs __iomem *)p->base; 315 316 value_tcr = sbus_readb(®s->p_tcr); 317 value_tcr &= ~P_TCR_DIR; 318 sbus_writeb(value_tcr, ®s->p_tcr); 319 320 printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); 321 322 dev_set_drvdata(&sdev->ofdev.dev, p); 323 324 parport_announce_port(p); 325 326 return 0; 327 328out_put_port: 329 parport_put_port(p); 330 331out_free_ops: 332 kfree(ops); 333 334out_unmap: 335 sbus_iounmap(base, size); 336 337 return err; 338} 339 340static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) 341{ 342 struct sbus_dev *sdev = to_sbus_device(&dev->dev); 343 344 return init_one_port(sdev); 345} 346 347static int __devexit bpp_remove(struct of_device *dev) 348{ 349 struct parport *p = dev_get_drvdata(&dev->dev); 350 struct parport_operations *ops = p->ops; 351 352 parport_remove_port(p); 353 354 if (p->irq != PARPORT_IRQ_NONE) { 355 parport_sunbpp_disable_irq(p); 356 free_irq(p->irq, p); 357 } 358 359 sbus_iounmap((void __iomem *) p->base, p->size); 360 parport_put_port(p); 361 kfree(ops); 362 363 dev_set_drvdata(&dev->dev, NULL); 364 365 return 0; 366} 367 368static struct of_device_id bpp_match[] = { 369 { 370 .name = "SUNW,bpp", 371 }, 372 {}, 373}; 374 375MODULE_DEVICE_TABLE(of, bpp_match); 376 377static struct of_platform_driver bpp_sbus_driver = { 378 .name = "bpp", 379 .match_table = bpp_match, 380 .probe = bpp_probe, 381 .remove = __devexit_p(bpp_remove), 382}; 383 384static int __init parport_sunbpp_init(void) 385{ 386 return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); 387} 388 389static void __exit parport_sunbpp_exit(void) 390{ 391 of_unregister_driver(&bpp_sbus_driver); 392} 393 394MODULE_AUTHOR("Derrick J Brashear"); 395MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); 396MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); 397MODULE_VERSION("2.0"); 398MODULE_LICENSE("GPL"); 399 400module_init(parport_sunbpp_init) 401module_exit(parport_sunbpp_exit) 402