Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27 415 lines 11 kB view raw
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 void parport_sunbpp_disable_irq(struct parport *p) 50{ 51 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 52 u32 tmp; 53 54 tmp = sbus_readl(&regs->p_csr); 55 tmp &= ~DMA_INT_ENAB; 56 sbus_writel(tmp, &regs->p_csr); 57} 58 59static void parport_sunbpp_enable_irq(struct parport *p) 60{ 61 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 62 u32 tmp; 63 64 tmp = sbus_readl(&regs->p_csr); 65 tmp |= DMA_INT_ENAB; 66 sbus_writel(tmp, &regs->p_csr); 67} 68 69static void parport_sunbpp_write_data(struct parport *p, unsigned char d) 70{ 71 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 72 73 sbus_writeb(d, &regs->p_dr); 74 dprintk((KERN_DEBUG "wrote 0x%x\n", d)); 75} 76 77static unsigned char parport_sunbpp_read_data(struct parport *p) 78{ 79 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 80 81 return sbus_readb(&regs->p_dr); 82} 83 84#if 0 85static void control_pc_to_sunbpp(struct parport *p, unsigned char status) 86{ 87 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 88 unsigned char value_tcr = sbus_readb(&regs->p_tcr); 89 unsigned char value_or = sbus_readb(&regs->p_or); 90 91 if (status & PARPORT_CONTROL_STROBE) 92 value_tcr |= P_TCR_DS; 93 if (status & PARPORT_CONTROL_AUTOFD) 94 value_or |= P_OR_AFXN; 95 if (status & PARPORT_CONTROL_INIT) 96 value_or |= P_OR_INIT; 97 if (status & PARPORT_CONTROL_SELECT) 98 value_or |= P_OR_SLCT_IN; 99 100 sbus_writeb(value_or, &regs->p_or); 101 sbus_writeb(value_tcr, &regs->p_tcr); 102} 103#endif 104 105static unsigned char status_sunbpp_to_pc(struct parport *p) 106{ 107 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 108 unsigned char bits = 0; 109 unsigned char value_tcr = sbus_readb(&regs->p_tcr); 110 unsigned char value_ir = sbus_readb(&regs->p_ir); 111 112 if (!(value_ir & P_IR_ERR)) 113 bits |= PARPORT_STATUS_ERROR; 114 if (!(value_ir & P_IR_SLCT)) 115 bits |= PARPORT_STATUS_SELECT; 116 if (!(value_ir & P_IR_PE)) 117 bits |= PARPORT_STATUS_PAPEROUT; 118 if (value_tcr & P_TCR_ACK) 119 bits |= PARPORT_STATUS_ACK; 120 if (!(value_tcr & P_TCR_BUSY)) 121 bits |= PARPORT_STATUS_BUSY; 122 123 dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", value_tcr, value_ir)); 124 dprintk((KERN_DEBUG "read status 0x%x\n", bits)); 125 return bits; 126} 127 128static unsigned char control_sunbpp_to_pc(struct parport *p) 129{ 130 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 131 unsigned char bits = 0; 132 unsigned char value_tcr = sbus_readb(&regs->p_tcr); 133 unsigned char value_or = sbus_readb(&regs->p_or); 134 135 if (!(value_tcr & P_TCR_DS)) 136 bits |= PARPORT_CONTROL_STROBE; 137 if (!(value_or & P_OR_AFXN)) 138 bits |= PARPORT_CONTROL_AUTOFD; 139 if (!(value_or & P_OR_INIT)) 140 bits |= PARPORT_CONTROL_INIT; 141 if (value_or & P_OR_SLCT_IN) 142 bits |= PARPORT_CONTROL_SELECT; 143 144 dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", value_tcr, value_or)); 145 dprintk((KERN_DEBUG "read control 0x%x\n", bits)); 146 return bits; 147} 148 149static unsigned char parport_sunbpp_read_control(struct parport *p) 150{ 151 return control_sunbpp_to_pc(p); 152} 153 154static unsigned char parport_sunbpp_frob_control(struct parport *p, 155 unsigned char mask, 156 unsigned char val) 157{ 158 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 159 unsigned char value_tcr = sbus_readb(&regs->p_tcr); 160 unsigned char value_or = sbus_readb(&regs->p_or); 161 162 dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", 163 value_tcr, value_or)); 164 if (mask & PARPORT_CONTROL_STROBE) { 165 if (val & PARPORT_CONTROL_STROBE) { 166 value_tcr &= ~P_TCR_DS; 167 } else { 168 value_tcr |= P_TCR_DS; 169 } 170 } 171 if (mask & PARPORT_CONTROL_AUTOFD) { 172 if (val & PARPORT_CONTROL_AUTOFD) { 173 value_or &= ~P_OR_AFXN; 174 } else { 175 value_or |= P_OR_AFXN; 176 } 177 } 178 if (mask & PARPORT_CONTROL_INIT) { 179 if (val & PARPORT_CONTROL_INIT) { 180 value_or &= ~P_OR_INIT; 181 } else { 182 value_or |= P_OR_INIT; 183 } 184 } 185 if (mask & PARPORT_CONTROL_SELECT) { 186 if (val & PARPORT_CONTROL_SELECT) { 187 value_or |= P_OR_SLCT_IN; 188 } else { 189 value_or &= ~P_OR_SLCT_IN; 190 } 191 } 192 193 sbus_writeb(value_or, &regs->p_or); 194 sbus_writeb(value_tcr, &regs->p_tcr); 195 dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", 196 value_tcr, value_or)); 197 return parport_sunbpp_read_control(p); 198} 199 200static void parport_sunbpp_write_control(struct parport *p, unsigned char d) 201{ 202 const unsigned char wm = (PARPORT_CONTROL_STROBE | 203 PARPORT_CONTROL_AUTOFD | 204 PARPORT_CONTROL_INIT | 205 PARPORT_CONTROL_SELECT); 206 207 parport_sunbpp_frob_control (p, wm, d & wm); 208} 209 210static unsigned char parport_sunbpp_read_status(struct parport *p) 211{ 212 return status_sunbpp_to_pc(p); 213} 214 215static void parport_sunbpp_data_forward (struct parport *p) 216{ 217 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 218 unsigned char value_tcr = sbus_readb(&regs->p_tcr); 219 220 dprintk((KERN_DEBUG "forward\n")); 221 value_tcr &= ~P_TCR_DIR; 222 sbus_writeb(value_tcr, &regs->p_tcr); 223} 224 225static void parport_sunbpp_data_reverse (struct parport *p) 226{ 227 struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; 228 u8 val = sbus_readb(&regs->p_tcr); 229 230 dprintk((KERN_DEBUG "reverse\n")); 231 val |= P_TCR_DIR; 232 sbus_writeb(val, &regs->p_tcr); 233} 234 235static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s) 236{ 237 s->u.pc.ctr = 0xc; 238 s->u.pc.ecr = 0x0; 239} 240 241static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s) 242{ 243 s->u.pc.ctr = parport_sunbpp_read_control(p); 244} 245 246static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s) 247{ 248 parport_sunbpp_write_control(p, s->u.pc.ctr); 249} 250 251static struct parport_operations parport_sunbpp_ops = 252{ 253 .write_data = parport_sunbpp_write_data, 254 .read_data = parport_sunbpp_read_data, 255 256 .write_control = parport_sunbpp_write_control, 257 .read_control = parport_sunbpp_read_control, 258 .frob_control = parport_sunbpp_frob_control, 259 260 .read_status = parport_sunbpp_read_status, 261 262 .enable_irq = parport_sunbpp_enable_irq, 263 .disable_irq = parport_sunbpp_disable_irq, 264 265 .data_forward = parport_sunbpp_data_forward, 266 .data_reverse = parport_sunbpp_data_reverse, 267 268 .init_state = parport_sunbpp_init_state, 269 .save_state = parport_sunbpp_save_state, 270 .restore_state = parport_sunbpp_restore_state, 271 272 .epp_write_data = parport_ieee1284_epp_write_data, 273 .epp_read_data = parport_ieee1284_epp_read_data, 274 .epp_write_addr = parport_ieee1284_epp_write_addr, 275 .epp_read_addr = parport_ieee1284_epp_read_addr, 276 277 .ecp_write_data = parport_ieee1284_ecp_write_data, 278 .ecp_read_data = parport_ieee1284_ecp_read_data, 279 .ecp_write_addr = parport_ieee1284_ecp_write_addr, 280 281 .compat_write_data = parport_ieee1284_write_compat, 282 .nibble_read_data = parport_ieee1284_read_nibble, 283 .byte_read_data = parport_ieee1284_read_byte, 284 285 .owner = THIS_MODULE, 286}; 287 288static int __devinit init_one_port(struct sbus_dev *sdev) 289{ 290 struct parport *p; 291 /* at least in theory there may be a "we don't dma" case */ 292 struct parport_operations *ops; 293 void __iomem *base; 294 int irq, dma, err = 0, size; 295 struct bpp_regs __iomem *regs; 296 unsigned char value_tcr; 297 298 irq = sdev->irqs[0]; 299 base = sbus_ioremap(&sdev->resource[0], 0, 300 sdev->reg_addrs[0].reg_size, 301 "sunbpp"); 302 if (!base) 303 return -ENODEV; 304 305 size = sdev->reg_addrs[0].reg_size; 306 dma = PARPORT_DMA_NONE; 307 308 ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); 309 if (!ops) 310 goto out_unmap; 311 312 memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); 313 314 dprintk(("register_port\n")); 315 if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) 316 goto out_free_ops; 317 318 p->size = size; 319 p->dev = &sdev->ofdev.dev; 320 321 if ((err = request_irq(p->irq, parport_irq_handler, 322 IRQF_SHARED, p->name, p)) != 0) { 323 goto out_put_port; 324 } 325 326 parport_sunbpp_enable_irq(p); 327 328 regs = (struct bpp_regs __iomem *)p->base; 329 330 value_tcr = sbus_readb(&regs->p_tcr); 331 value_tcr &= ~P_TCR_DIR; 332 sbus_writeb(value_tcr, &regs->p_tcr); 333 334 printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); 335 336 dev_set_drvdata(&sdev->ofdev.dev, p); 337 338 parport_announce_port(p); 339 340 return 0; 341 342out_put_port: 343 parport_put_port(p); 344 345out_free_ops: 346 kfree(ops); 347 348out_unmap: 349 sbus_iounmap(base, size); 350 351 return err; 352} 353 354static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) 355{ 356 struct sbus_dev *sdev = to_sbus_device(&dev->dev); 357 358 return init_one_port(sdev); 359} 360 361static int __devexit bpp_remove(struct of_device *dev) 362{ 363 struct parport *p = dev_get_drvdata(&dev->dev); 364 struct parport_operations *ops = p->ops; 365 366 parport_remove_port(p); 367 368 if (p->irq != PARPORT_IRQ_NONE) { 369 parport_sunbpp_disable_irq(p); 370 free_irq(p->irq, p); 371 } 372 373 sbus_iounmap((void __iomem *) p->base, p->size); 374 parport_put_port(p); 375 kfree(ops); 376 377 dev_set_drvdata(&dev->dev, NULL); 378 379 return 0; 380} 381 382static struct of_device_id bpp_match[] = { 383 { 384 .name = "SUNW,bpp", 385 }, 386 {}, 387}; 388 389MODULE_DEVICE_TABLE(of, bpp_match); 390 391static struct of_platform_driver bpp_sbus_driver = { 392 .name = "bpp", 393 .match_table = bpp_match, 394 .probe = bpp_probe, 395 .remove = __devexit_p(bpp_remove), 396}; 397 398static int __init parport_sunbpp_init(void) 399{ 400 return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); 401} 402 403static void __exit parport_sunbpp_exit(void) 404{ 405 of_unregister_driver(&bpp_sbus_driver); 406} 407 408MODULE_AUTHOR("Derrick J Brashear"); 409MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); 410MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); 411MODULE_VERSION("2.0"); 412MODULE_LICENSE("GPL"); 413 414module_init(parport_sunbpp_init) 415module_exit(parport_sunbpp_exit)