@@ -41,6 +41,12 @@ GPL version 2.
41
41
</abstract >
42
42
43
43
<revhistory >
44
+ <revision >
45
+ <revnumber >0.7</revnumber >
46
+ <date >2008-12-23</date >
47
+ <authorinitials >hjk</authorinitials >
48
+ <revremark >Added generic platform drivers and offset attribute.</revremark >
49
+ </revision >
44
50
<revision >
45
51
<revnumber >0.6</revnumber >
46
52
<date >2008-12-05</date >
@@ -312,6 +318,16 @@ interested in translating it, please email me
312
318
pointed to by addr.
313
319
</para >
314
320
</listitem >
321
+ <listitem >
322
+ <para >
323
+ <filename >offset</filename >: The offset, in bytes, that has to be
324
+ added to the pointer returned by <function >mmap()</function > to get
325
+ to the actual device memory. This is important if the device's memory
326
+ is not page aligned. Remember that pointers returned by
327
+ <function >mmap()</function > are always page aligned, so it is good
328
+ style to always add this offset.
329
+ </para >
330
+ </listitem >
315
331
</itemizedlist >
316
332
317
333
<para >
@@ -594,6 +610,78 @@ framework to set up sysfs files for this region. Simply leave it alone.
594
610
</para >
595
611
</sect1 >
596
612
613
+ <sect1 id =" using_uio_pdrv" >
614
+ <title >Using uio_pdrv for platform devices</title >
615
+ <para >
616
+ In many cases, UIO drivers for platform devices can be handled in a
617
+ generic way. In the same place where you define your
618
+ <varname >struct platform_device</varname >, you simply also implement
619
+ your interrupt handler and fill your
620
+ <varname >struct uio_info</varname >. A pointer to this
621
+ <varname >struct uio_info</varname > is then used as
622
+ <varname >platform_data</varname > for your platform device.
623
+ </para >
624
+ <para >
625
+ You also need to set up an array of <varname >struct resource</varname >
626
+ containing addresses and sizes of your memory mappings. This
627
+ information is passed to the driver using the
628
+ <varname >.resource</varname > and <varname >.num_resources</varname >
629
+ elements of <varname >struct platform_device</varname >.
630
+ </para >
631
+ <para >
632
+ You now have to set the <varname >.name</varname > element of
633
+ <varname >struct platform_device</varname > to
634
+ <varname >"uio_pdrv"</varname > to use the generic UIO platform device
635
+ driver. This driver will fill the <varname >mem[]</varname > array
636
+ according to the resources given, and register the device.
637
+ </para >
638
+ <para >
639
+ The advantage of this approach is that you only have to edit a file
640
+ you need to edit anyway. You do not have to create an extra driver.
641
+ </para >
642
+ </sect1 >
643
+
644
+ <sect1 id =" using_uio_pdrv_genirq" >
645
+ <title >Using uio_pdrv_genirq for platform devices</title >
646
+ <para >
647
+ Especially in embedded devices, you frequently find chips where the
648
+ irq pin is tied to its own dedicated interrupt line. In such cases,
649
+ where you can be really sure the interrupt is not shared, we can take
650
+ the concept of <varname >uio_pdrv</varname > one step further and use a
651
+ generic interrupt handler. That's what
652
+ <varname >uio_pdrv_genirq</varname > does.
653
+ </para >
654
+ <para >
655
+ The setup for this driver is the same as described above for
656
+ <varname >uio_pdrv</varname >, except that you do not implement an
657
+ interrupt handler. The <varname >.handler</varname > element of
658
+ <varname >struct uio_info</varname > must remain
659
+ <varname >NULL</varname >. The <varname >.irq_flags</varname > element
660
+ must not contain <varname >IRQF_SHARED</varname >.
661
+ </para >
662
+ <para >
663
+ You will set the <varname >.name</varname > element of
664
+ <varname >struct platform_device</varname > to
665
+ <varname >"uio_pdrv_genirq"</varname > to use this driver.
666
+ </para >
667
+ <para >
668
+ The generic interrupt handler of <varname >uio_pdrv_genirq</varname >
669
+ will simply disable the interrupt line using
670
+ <function >disable_irq_nosync()</function >. After doing its work,
671
+ userspace can reenable the interrupt by writing 0x00000001 to the UIO
672
+ device file. The driver already implements an
673
+ <function >irq_control()</function > to make this possible, you must not
674
+ implement your own.
675
+ </para >
676
+ <para >
677
+ Using <varname >uio_pdrv_genirq</varname > not only saves a few lines of
678
+ interrupt handler code. You also do not need to know anything about
679
+ the chip's internal registers to create the kernel part of the driver.
680
+ All you need to know is the irq number of the pin the chip is
681
+ connected to.
682
+ </para >
683
+ </sect1 >
684
+
597
685
</chapter >
598
686
599
687
<chapter id =" userspace_driver" xreflabel =" Writing a driver in user space" >