Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 #include <linux/of.h>
 30 #include <linux/of_device.h>
 31 
 32 #include <linux/parport.h>
 33 
 34 #include <asm/ptrace.h>
 35 #include <linux/interrupt.h>
 36 
 37 #include <asm/io.h>
 38 #include <asm/oplib.h>           /* OpenProm Library */
 39 #include <asm/dma.h>             /* BPP uses LSI 64854 for DMA */
 40 #include <asm/irq.h>
 41 #include <asm/sunbpp.h>
 42 
 43 #undef __SUNBPP_DEBUG
 44 #ifdef __SUNBPP_DEBUG
 45 #define dprintk(x) printk x
 46 #else
 47 #define dprintk(x)
 48 #endif
 49 
 50 static void parport_sunbpp_disable_irq(struct parport *p)
 51 {
 52         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
 53         u32 tmp;
 54 
 55         tmp = sbus_readl(&regs->p_csr);
 56         tmp &= ~DMA_INT_ENAB;
 57         sbus_writel(tmp, &regs->p_csr);
 58 }
 59 
 60 static void parport_sunbpp_enable_irq(struct parport *p)
 61 {
 62         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
 63         u32 tmp;
 64 
 65         tmp = sbus_readl(&regs->p_csr);
 66         tmp |= DMA_INT_ENAB;
 67         sbus_writel(tmp, &regs->p_csr);
 68 }
 69 
 70 static void parport_sunbpp_write_data(struct parport *p, unsigned char d)
 71 {
 72         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
 73 
 74         sbus_writeb(d, &regs->p_dr);
 75         dprintk((KERN_DEBUG "wrote 0x%x\n", d));
 76 }
 77 
 78 static unsigned char parport_sunbpp_read_data(struct parport *p)
 79 {
 80         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
 81 
 82         return sbus_readb(&regs->p_dr);
 83 }
 84 
 85 #if 0
 86 static void control_pc_to_sunbpp(struct parport *p, unsigned char status)
 87 {
 88         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
 89         unsigned char value_tcr = sbus_readb(&regs->p_tcr);
 90         unsigned char value_or = sbus_readb(&regs->p_or);
 91 
 92         if (status & PARPORT_CONTROL_STROBE) 
 93                 value_tcr |= P_TCR_DS;
 94         if (status & PARPORT_CONTROL_AUTOFD) 
 95                 value_or |= P_OR_AFXN;
 96         if (status & PARPORT_CONTROL_INIT) 
 97                 value_or |= P_OR_INIT;
 98         if (status & PARPORT_CONTROL_SELECT) 
 99                 value_or |= P_OR_SLCT_IN;
100 
101         sbus_writeb(value_or, &regs->p_or);
102         sbus_writeb(value_tcr, &regs->p_tcr);
103 }
104 #endif
105 
106 static unsigned char status_sunbpp_to_pc(struct parport *p)
107 {
108         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
109         unsigned char bits = 0;
110         unsigned char value_tcr = sbus_readb(&regs->p_tcr);
111         unsigned char value_ir = sbus_readb(&regs->p_ir);
112 
113         if (!(value_ir & P_IR_ERR))
114                 bits |= PARPORT_STATUS_ERROR;
115         if (!(value_ir & P_IR_SLCT))
116                 bits |= PARPORT_STATUS_SELECT;
117         if (!(value_ir & P_IR_PE))
118                 bits |= PARPORT_STATUS_PAPEROUT;
119         if (value_tcr & P_TCR_ACK)
120                 bits |= PARPORT_STATUS_ACK;
121         if (!(value_tcr & P_TCR_BUSY))
122                 bits |= PARPORT_STATUS_BUSY;
123 
124         dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", value_tcr, value_ir));
125         dprintk((KERN_DEBUG "read status 0x%x\n", bits));
126         return bits;
127 }
128 
129 static unsigned char control_sunbpp_to_pc(struct parport *p)
130 {
131         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
132         unsigned char bits = 0;
133         unsigned char value_tcr = sbus_readb(&regs->p_tcr);
134         unsigned char value_or = sbus_readb(&regs->p_or);
135 
136         if (!(value_tcr & P_TCR_DS))
137                 bits |= PARPORT_CONTROL_STROBE;
138         if (!(value_or & P_OR_AFXN))
139                 bits |= PARPORT_CONTROL_AUTOFD;
140         if (!(value_or & P_OR_INIT))
141                 bits |= PARPORT_CONTROL_INIT;
142         if (value_or & P_OR_SLCT_IN)
143                 bits |= PARPORT_CONTROL_SELECT;
144 
145         dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", value_tcr, value_or));
146         dprintk((KERN_DEBUG "read control 0x%x\n", bits));
147         return bits;
148 }
149 
150 static unsigned char parport_sunbpp_read_control(struct parport *p)
151 {
152         return control_sunbpp_to_pc(p);
153 }
154 
155 static unsigned char parport_sunbpp_frob_control(struct parport *p,
156                                                  unsigned char mask,
157                                                  unsigned char val)
158 {
159         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
160         unsigned char value_tcr = sbus_readb(&regs->p_tcr);
161         unsigned char value_or = sbus_readb(&regs->p_or);
162 
163         dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n",
164                  value_tcr, value_or));
165         if (mask & PARPORT_CONTROL_STROBE) {
166                 if (val & PARPORT_CONTROL_STROBE) {
167                         value_tcr &= ~P_TCR_DS;
168                 } else {
169                         value_tcr |= P_TCR_DS;
170                 }
171         }
172         if (mask & PARPORT_CONTROL_AUTOFD) {
173                 if (val & PARPORT_CONTROL_AUTOFD) {
174                         value_or &= ~P_OR_AFXN;
175                 } else {
176                         value_or |= P_OR_AFXN;
177                 }
178         }
179         if (mask & PARPORT_CONTROL_INIT) {
180                 if (val & PARPORT_CONTROL_INIT) {
181                         value_or &= ~P_OR_INIT;
182                 } else {
183                         value_or |= P_OR_INIT;
184                 }
185         }
186         if (mask & PARPORT_CONTROL_SELECT) {
187                 if (val & PARPORT_CONTROL_SELECT) {
188                         value_or |= P_OR_SLCT_IN;
189                 } else {
190                         value_or &= ~P_OR_SLCT_IN;
191                 }
192         }
193 
194         sbus_writeb(value_or, &regs->p_or);
195         sbus_writeb(value_tcr, &regs->p_tcr);
196         dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n",
197                  value_tcr, value_or));
198         return parport_sunbpp_read_control(p);
199 }
200 
201 static void parport_sunbpp_write_control(struct parport *p, unsigned char d)
202 {
203         const unsigned char wm = (PARPORT_CONTROL_STROBE |
204                                   PARPORT_CONTROL_AUTOFD |
205                                   PARPORT_CONTROL_INIT |
206                                   PARPORT_CONTROL_SELECT);
207 
208         parport_sunbpp_frob_control (p, wm, d & wm);
209 }
210 
211 static unsigned char parport_sunbpp_read_status(struct parport *p)
212 {
213         return status_sunbpp_to_pc(p);
214 }
215 
216 static void parport_sunbpp_data_forward (struct parport *p)
217 {
218         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
219         unsigned char value_tcr = sbus_readb(&regs->p_tcr);
220 
221         dprintk((KERN_DEBUG "forward\n"));
222         value_tcr &= ~P_TCR_DIR;
223         sbus_writeb(value_tcr, &regs->p_tcr);
224 }
225 
226 static void parport_sunbpp_data_reverse (struct parport *p)
227 {
228         struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base;
229         u8 val = sbus_readb(&regs->p_tcr);
230 
231         dprintk((KERN_DEBUG "reverse\n"));
232         val |= P_TCR_DIR;
233         sbus_writeb(val, &regs->p_tcr);
234 }
235 
236 static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s)
237 {
238         s->u.pc.ctr = 0xc;
239         s->u.pc.ecr = 0x0;
240 }
241 
242 static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s)
243 {
244         s->u.pc.ctr = parport_sunbpp_read_control(p);
245 }
246 
247 static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s)
248 {
249         parport_sunbpp_write_control(p, s->u.pc.ctr);
250 }
251 
252 static struct parport_operations parport_sunbpp_ops = 
253 {
254         .write_data     = parport_sunbpp_write_data,
255         .read_data      = parport_sunbpp_read_data,
256 
257         .write_control  = parport_sunbpp_write_control,
258         .read_control   = parport_sunbpp_read_control,
259         .frob_control   = parport_sunbpp_frob_control,
260 
261         .read_status    = parport_sunbpp_read_status,
262 
263         .enable_irq     = parport_sunbpp_enable_irq,
264         .disable_irq    = parport_sunbpp_disable_irq,
265 
266         .data_forward   = parport_sunbpp_data_forward,
267         .data_reverse   = parport_sunbpp_data_reverse,
268 
269         .init_state     = parport_sunbpp_init_state,
270         .save_state     = parport_sunbpp_save_state,
271         .restore_state  = parport_sunbpp_restore_state,
272 
273         .epp_write_data = parport_ieee1284_epp_write_data,
274         .epp_read_data  = parport_ieee1284_epp_read_data,
275         .epp_write_addr = parport_ieee1284_epp_write_addr,
276         .epp_read_addr  = parport_ieee1284_epp_read_addr,
277 
278         .ecp_write_data = parport_ieee1284_ecp_write_data,
279         .ecp_read_data  = parport_ieee1284_ecp_read_data,
280         .ecp_write_addr = parport_ieee1284_ecp_write_addr,
281 
282         .compat_write_data      = parport_ieee1284_write_compat,
283         .nibble_read_data       = parport_ieee1284_read_nibble,
284         .byte_read_data         = parport_ieee1284_read_byte,
285 
286         .owner          = THIS_MODULE,
287 };
288 
289 static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match)
290 {
291         struct parport_operations *ops;
292         struct bpp_regs __iomem *regs;
293         int irq, dma, err = 0, size;
294         unsigned char value_tcr;
295         void __iomem *base;
296         struct parport *p;
297 
298         irq = op->irqs[0];
299         base = of_ioremap(&op->resource[0], 0,
300                           resource_size(&op->resource[0]),
301                           "sunbpp");
302         if (!base)
303                 return -ENODEV;
304 
305         size = resource_size(&op->resource[0]);
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 = &op->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(&op->dev, p);
337 
338         parport_announce_port(p);
339 
340         return 0;
341 
342 out_put_port:
343         parport_put_port(p);
344 
345 out_free_ops:
346         kfree(ops);
347 
348 out_unmap:
349         of_iounmap(&op->resource[0], base, size);
350 
351         return err;
352 }
353 
354 static int __devexit bpp_remove(struct of_device *op)
355 {
356         struct parport *p = dev_get_drvdata(&op->dev);
357         struct parport_operations *ops = p->ops;
358 
359         parport_remove_port(p);
360 
361         if (p->irq != PARPORT_IRQ_NONE) {
362                 parport_sunbpp_disable_irq(p);
363                 free_irq(p->irq, p);
364         }
365 
366         of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size);
367         parport_put_port(p);
368         kfree(ops);
369 
370         dev_set_drvdata(&op->dev, NULL);
371 
372         return 0;
373 }
374 
375 static const struct of_device_id bpp_match[] = {
376         {
377                 .name = "SUNW,bpp",
378         },
379         {},
380 };
381 
382 MODULE_DEVICE_TABLE(of, bpp_match);
383 
384 static struct of_platform_driver bpp_sbus_driver = {
385         .name           = "bpp",
386         .match_table    = bpp_match,
387         .probe          = bpp_probe,
388         .remove         = __devexit_p(bpp_remove),
389 };
390 
391 static int __init parport_sunbpp_init(void)
392 {
393         return of_register_driver(&bpp_sbus_driver, &of_bus_type);
394 }
395 
396 static void __exit parport_sunbpp_exit(void)
397 {
398         of_unregister_driver(&bpp_sbus_driver);
399 }
400 
401 MODULE_AUTHOR("Derrick J Brashear");
402 MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
403 MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
404 MODULE_VERSION("2.0");
405 MODULE_LICENSE("GPL");
406 
407 module_init(parport_sunbpp_init)
408 module_exit(parport_sunbpp_exit)
409 
  This page was automatically generated by the LXR engine.