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