1/* $Id: parport_sunbpp.c,v 1.1.1.1 2008/10/15 03:26:46 james26_jang 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 <Philip.Blundell@pobox.com> 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 47static void parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_regs *regs) 48{ 49 parport_generic_irq(irq, (struct parport *) dev_id, regs); 50} 51 52static void parport_sunbpp_disable_irq(struct parport *p) 53{ 54 struct bpp_regs *regs = (struct bpp_regs *)p->base; 55 u32 tmp; 56 57 tmp = sbus_readl(®s->p_csr); 58 tmp &= ~DMA_INT_ENAB; 59 sbus_writel(tmp, ®s->p_csr); 60} 61 62static void parport_sunbpp_enable_irq(struct parport *p) 63{ 64 struct bpp_regs *regs = (struct bpp_regs *)p->base; 65 u32 tmp; 66 67 tmp = sbus_readl(®s->p_csr); 68 tmp |= DMA_INT_ENAB; 69 sbus_writel(tmp, ®s->p_csr); 70} 71 72static void parport_sunbpp_write_data(struct parport *p, unsigned char d) 73{ 74 struct bpp_regs *regs = (struct bpp_regs *)p->base; 75 76 sbus_writeb(d, ®s->p_dr); 77 dprintk((KERN_DEBUG "wrote 0x%x\n", d)); 78} 79 80static unsigned char parport_sunbpp_read_data(struct parport *p) 81{ 82 struct bpp_regs *regs = (struct bpp_regs *)p->base; 83 84 return sbus_readb(®s->p_dr); 85} 86 87 88static unsigned char status_sunbpp_to_pc(struct parport *p) 89{ 90 struct bpp_regs *regs = (struct bpp_regs *)p->base; 91 unsigned char bits = 0; 92 unsigned char value_tcr = sbus_readb(®s->p_tcr); 93 unsigned char value_ir = sbus_readb(®s->p_ir); 94 95 if (!(value_ir & P_IR_ERR)) 96 bits |= PARPORT_STATUS_ERROR; 97 if (!(value_ir & P_IR_SLCT)) 98 bits |= PARPORT_STATUS_SELECT; 99 if (!(value_ir & P_IR_PE)) 100 bits |= PARPORT_STATUS_PAPEROUT; 101 if (value_tcr & P_TCR_ACK) 102 bits |= PARPORT_STATUS_ACK; 103 if (!(value_tcr & P_TCR_BUSY)) 104 bits |= PARPORT_STATUS_BUSY; 105 106 dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir)); 107 dprintk((KERN_DEBUG "read status 0x%x\n", bits)); 108 return bits; 109} 110 111static unsigned char control_sunbpp_to_pc(struct parport *p) 112{ 113 struct bpp_regs *regs = (struct bpp_regs *)p->base; 114 unsigned char bits = 0; 115 unsigned char value_tcr = sbus_readb(®s->p_tcr); 116 unsigned char value_or = sbus_readb(®s->p_or); 117 118 if (!(value_tcr & P_TCR_DS)) 119 bits |= PARPORT_CONTROL_STROBE; 120 if (!(value_or & P_OR_AFXN)) 121 bits |= PARPORT_CONTROL_AUTOFD; 122 if (!(value_or & P_OR_INIT)) 123 bits |= PARPORT_CONTROL_INIT; 124 if (value_or & P_OR_SLCT_IN) 125 bits |= PARPORT_CONTROL_SELECT; 126 127 dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); 128 dprintk((KERN_DEBUG "read control 0x%x\n", bits)); 129 return bits; 130} 131 132static unsigned char parport_sunbpp_read_control(struct parport *p) 133{ 134 return control_sunbpp_to_pc(p); 135} 136 137static unsigned char parport_sunbpp_frob_control(struct parport *p, 138 unsigned char mask, 139 unsigned char val) 140{ 141 struct bpp_regs *regs = (struct bpp_regs *)p->base; 142 unsigned char value_tcr = sbus_readb(®s->p_tcr); 143 unsigned char value_or = sbus_readb(®s->p_or); 144 145 dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); 146 if (mask & PARPORT_CONTROL_STROBE) { 147 if (val & PARPORT_CONTROL_STROBE) { 148 value_tcr &= ~P_TCR_DS; 149 } else { 150 value_tcr |= P_TCR_DS; 151 } 152 } 153 if (mask & PARPORT_CONTROL_AUTOFD) { 154 if (val & PARPORT_CONTROL_AUTOFD) { 155 value_or &= ~P_OR_AFXN; 156 } else { 157 value_or |= P_OR_AFXN; 158 } 159 } 160 if (mask & PARPORT_CONTROL_INIT) { 161 if (val & PARPORT_CONTROL_INIT) { 162 value_or &= ~P_OR_INIT; 163 } else { 164 value_or |= P_OR_INIT; 165 } 166 } 167 if (mask & PARPORT_CONTROL_SELECT) { 168 if (val & PARPORT_CONTROL_SELECT) { 169 value_or |= P_OR_SLCT_IN; 170 } else { 171 value_or &= ~P_OR_SLCT_IN; 172 } 173 } 174 175 sbus_writeb(value_or, ®s->p_or); 176 sbus_writeb(value_tcr, ®s->p_tcr); 177 dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); 178 return parport_sunbpp_read_control(p); 179} 180 181static void parport_sunbpp_write_control(struct parport *p, unsigned char d) 182{ 183 const unsigned char wm = (PARPORT_CONTROL_STROBE | 184 PARPORT_CONTROL_AUTOFD | 185 PARPORT_CONTROL_INIT | 186 PARPORT_CONTROL_SELECT); 187 188 parport_sunbpp_frob_control (p, wm, d & wm); 189} 190 191static unsigned char parport_sunbpp_read_status(struct parport *p) 192{ 193 return status_sunbpp_to_pc(p); 194} 195 196static void parport_sunbpp_data_forward (struct parport *p) 197{ 198 struct bpp_regs *regs = (struct bpp_regs *)p->base; 199 unsigned char value_tcr = sbus_readb(®s->p_tcr); 200 201 dprintk((KERN_DEBUG "forward\n")); 202 value_tcr &= ~P_TCR_DIR; 203 sbus_writeb(value_tcr, ®s->p_tcr); 204} 205 206static void parport_sunbpp_data_reverse (struct parport *p) 207{ 208 struct bpp_regs *regs = (struct bpp_regs *)p->base; 209 u8 val = sbus_readb(®s->p_tcr); 210 211 dprintk((KERN_DEBUG "reverse\n")); 212 val |= P_TCR_DIR; 213 sbus_writeb(val, ®s->p_tcr); 214} 215 216static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s) 217{ 218 s->u.pc.ctr = 0xc; 219 s->u.pc.ecr = 0x0; 220} 221 222static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s) 223{ 224 s->u.pc.ctr = parport_sunbpp_read_control(p); 225} 226 227static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s) 228{ 229 parport_sunbpp_write_control(p, s->u.pc.ctr); 230} 231 232static void parport_sunbpp_inc_use_count(void) 233{ 234#ifdef MODULE 235 MOD_INC_USE_COUNT; 236#endif 237} 238 239static void parport_sunbpp_dec_use_count(void) 240{ 241#ifdef MODULE 242 MOD_DEC_USE_COUNT; 243#endif 244} 245 246static struct parport_operations parport_sunbpp_ops = 247{ 248 parport_sunbpp_write_data, 249 parport_sunbpp_read_data, 250 251 parport_sunbpp_write_control, 252 parport_sunbpp_read_control, 253 parport_sunbpp_frob_control, 254 255 parport_sunbpp_read_status, 256 257 parport_sunbpp_enable_irq, 258 parport_sunbpp_disable_irq, 259 260 parport_sunbpp_data_forward, 261 parport_sunbpp_data_reverse, 262 263 parport_sunbpp_init_state, 264 parport_sunbpp_save_state, 265 parport_sunbpp_restore_state, 266 267 parport_sunbpp_inc_use_count, 268 parport_sunbpp_dec_use_count, 269 270 parport_ieee1284_epp_write_data, 271 parport_ieee1284_epp_read_data, 272 parport_ieee1284_epp_write_addr, 273 parport_ieee1284_epp_read_addr, 274 275 parport_ieee1284_ecp_write_data, 276 parport_ieee1284_ecp_read_data, 277 parport_ieee1284_ecp_write_addr, 278 279 parport_ieee1284_write_compat, 280 parport_ieee1284_read_nibble, 281 parport_ieee1284_read_byte, 282}; 283 284static int __init init_one_port(struct sbus_dev *sdev) 285{ 286 struct parport *p; 287 /* at least in theory there may be a "we don't dma" case */ 288 struct parport_operations *ops; 289 unsigned long base; 290 int irq, dma, err, size; 291 struct bpp_regs *regs; 292 unsigned char value_tcr; 293 294 dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); 295 irq = sdev->irqs[0]; 296 base = sbus_ioremap(&sdev->resource[0], 0, 297 sdev->reg_addrs[0].reg_size, 298 "sunbpp"); 299 size = sdev->reg_addrs[0].reg_size; 300 dma = PARPORT_DMA_NONE; 301 302 dprintk(("alloc(ppops), ")); 303 ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); 304 if (!ops) { 305 sbus_iounmap(base, size); 306 return 0; 307 } 308 309 memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); 310 311 dprintk(("register_port\n")); 312 if (!(p = parport_register_port(base, irq, dma, ops))) { 313 kfree(ops); 314 sbus_iounmap(base, size); 315 return 0; 316 } 317 318 p->size = size; 319 320 dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ", 321 p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)); 322 if ((err = request_irq(p->irq, parport_sunbpp_interrupt, 323 SA_SHIRQ, p->name, p)) != 0) { 324 dprintk(("ERROR %d\n", err)); 325 parport_unregister_port(p); 326 kfree(ops); 327 sbus_iounmap(base, size); 328 return err; 329 } else { 330 dprintk(("OK\n")); 331 parport_sunbpp_enable_irq(p); 332 } 333 334 regs = (struct bpp_regs *)p->base; 335 dprintk((KERN_DEBUG "forward\n")); 336 value_tcr = sbus_readb(®s->p_tcr); 337 value_tcr &= ~P_TCR_DIR; 338 sbus_writeb(value_tcr, ®s->p_tcr); 339 340 printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); 341 parport_proc_register(p); 342 parport_announce_port (p); 343 344 return 1; 345} 346 347EXPORT_NO_SYMBOLS; 348 349#ifdef MODULE 350int init_module(void) 351#else 352int __init parport_sunbpp_init(void) 353#endif 354{ 355 struct sbus_bus *sbus; 356 struct sbus_dev *sdev; 357 int count = 0; 358 359 for_each_sbus(sbus) { 360 for_each_sbusdev(sdev, sbus) { 361 if (!strcmp(sdev->prom_name, "SUNW,bpp")) 362 count += init_one_port(sdev); 363 } 364 } 365 return count ? 0 : -ENODEV; 366} 367 368#ifdef MODULE 369MODULE_AUTHOR("Derrick J Brashear"); 370MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); 371MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); 372 373void 374cleanup_module(void) 375{ 376 struct parport *p = parport_enumerate(); 377 378 while (p) { 379 struct parport *next = p->next; 380 381 if (1/*p->modes & PARPORT_MODE_PCSPP*/) { 382 struct parport_operations *ops = p->ops; 383 384 if (p->irq != PARPORT_IRQ_NONE) { 385 parport_sunbpp_disable_irq(p); 386 free_irq(p->irq, p); 387 } 388 sbus_iounmap(p->base, p->size); 389 parport_proc_unregister(p); 390 parport_unregister_port(p); 391 kfree (ops); 392 } 393 p = next; 394 } 395} 396#endif 397