memory mapped IO in kernel mode - Embedded

This is a discussion on memory mapped IO in kernel mode - Embedded ; I'm working on a device driver for a 2.4 kernel and I'm having a heck of a hard time.... I've never written a kernel module before, so it's an uphill struggle. By way of background, I am working with Linux ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: memory mapped IO in kernel mode

  1. memory mapped IO in kernel mode

    I'm working on a device driver for a 2.4 kernel and I'm having a heck of a
    hard time.... I've never written a kernel module before, so it's an
    uphill struggle. By way of background, I am working with Linux Device
    Drivers, 2nd ed.... And I have a similar driver written for x86
    architecture that I am using as a guide.

    The hardware is controlled via memory mapped registers at 0x11e0104 -
    0x11e0107. From what I've ben able to gather, I need to ioremap this and
    use the handle returned by ioremap for readb and readw...

    But... I am thoroughly confused by the kernel mode memory addressing and
    how it pertains to the ARM architecture.

    My init function is this:

    #define TSDIO24region 0x11e00104
    #define TSDIO24length 4


    static char *mem_virt_addr;


    int init_TSgpio(void)
    {
    int result;

    printk("<1>Hello world.\n");

    if (check_mem_region(TSDIO24region, TSDIO24length)) {
    printk("TSgpio: memory already in use\n"); return -EBUSY;
    }
    request_mem_region(TSDIO24region, TSDIO24length, "TSDIO24gpio");

    if( (result = register_chrdev(TSDIO24major, "TSDIO24",
    &tsdio24_fops)) < 0) {
    printk(KERN_WARNING "tsdio24: can't get major
    %d\n",TSDIO24major);
    return result;
    }
    mem_virt_addr = ioremap(TSDIO24region, TSDIO24length); return 0;
    }


    and my read function is this:

    static ssize_t tsdio24_read(struct file *file, char *buf, size_t, length,
    loff_t *ppos) {
    printk("0x%02x %02x %02x %02x\n",
    readb(mem_virt_addr),
    readb(mem_virt_addr+1),
    readb(mem_virt_addr+2),
    readb(mem_virt_addr+3));
    return 0;
    }


    While the read function does in fact spit out 4 bytes on `cat /dev/mydev`,
    they appear to be unrelated to the memory location I want. I did try this
    with page-aligned ioremap; AFAICT I got the same (wrong) memory area.

    I am completely confused by the various 'adjustments' to the memory
    addresses that I read about... Should I subtract 0x80000000 from the
    above before I ioremap? Does ioremap have to be page aligned? What *are*
    the arguments to ioremap? It doesn't seem to be documented anywhere in any
    detail.

    So... How does one do memory mapped IO on an ARM platform in kernel mode?

    The driver, BTW, is fairly simple - it will implement IRQs for GPIO pins.
    I was expecting a struggle over the IRQ code, but this has stumped me
    early.... :-(

    TIA,

    --Yan

    --
    o__
    ,>/'_ o__
    (_)\(_) ,>/'_ o__
    Yan Seiner, PE (_)\(_) ,>/'_ o__
    Certified Personal Trainer (_)\(_) ,>/'_ o__
    Licensed Professional Engineer (_)\(_) ,>/'_
    Who says engineers have to be pencil necked geeks? (_)\(_)


  2. Re: memory mapped IO in kernel mode

    Captain Dondo wrote:

    > While the read function does in fact spit out 4 bytes on `cat /dev/mydev`,
    > they appear to be unrelated to the memory location I want. I did try this
    > with page-aligned ioremap; AFAICT I got the same (wrong) memory area.


    How can you tell you are in the right memory area, do you have a probe
    (or similar) you can use to read the same address back ?

    > I am completely confused by the various 'adjustments' to the memory
    > addresses that I read about... Should I subtract 0x80000000 from the
    > above before I ioremap? Does ioremap have to be page aligned? What *are*
    > the arguments to ioremap? It doesn't seem to be documented anywhere in any
    > detail.


    You should pass the actual physical address into ioremap, the kernel's
    implementation for ARM should do any messing required to translate it
    for you.

  3. Re: memory mapped IO in kernel mode

    Captain Dondo wrote:

    > The hardware is controlled via memory mapped registers at 0x11e0104 -
    > 0x11e0107. From what I've ben able to gather, I need to ioremap this and
    > use the handle returned by ioremap for readb and readw...


    I don't see anything wrong with your code. Are you positive about the
    base address? I infer from your driver names that you are using a
    TS-DIO24. If you are also using a TS ARM processor board, wouldn't
    the base address be 0x011e0000?

    If you have access to a 'scope or logic analyzer, you might want to
    probe the device you are reading and see if the I/O read line is going
    active.

    Steve
    ------------------------------------------------------------------------
    Steve Schefter phone: +1 705 725 9999 x26
    The Software Group Limited fax: +1 705 725 9666
    642 Welham Road,
    Barrie, Ontario CANADA L4N 9A1 Web: www.wanware.com


  4. Re: memory mapped IO in kernel mode

    steve_schefter@hotmail.com wrote:
    > Captain Dondo wrote:
    >
    >
    >>The hardware is controlled via memory mapped registers at 0x11e0104 -
    >>0x11e0107. From what I've ben able to gather, I need to ioremap this and
    >>use the handle returned by ioremap for readb and readw...

    >
    >
    > I don't see anything wrong with your code. Are you positive about the
    > base address? I infer from your driver names that you are using a
    > TS-DIO24. If you are also using a TS ARM processor board, wouldn't
    > the base address be 0x011e0000?
    >
    > If you have access to a 'scope or logic analyzer, you might want to
    > probe the device you are reading and see if the I/O read line is going
    > active.


    Thanks, guys. It turns out that on an arm w/ 2.4 kernel, you need
    __ioremap, not ioremap.... Go figure.

    And yes, the base address wasn't right, but that was not the issue...
    All is almost well - at least now I am happily making kernel OOPSes... :-)

    --Yan

  5. Re: memory mapped IO in kernel mode

    Captain Dondo wrote:
    > Thanks, guys. It turns out that on an arm w/ 2.4 kernel, you need
    > __ioremap, not ioremap.... Go figure.


    Strange. ioremap() should be #defined to call __ioremap with the
    flags parameter set to zero. I use ioremap_nocache() (calls
    __ioremap() with flags set to 1). You might want to try that as
    it'll be more portable than __ioremap().

    > And yes, the base address wasn't right, but that was not the issue...
    > All is almost well - at least now I am happily making kernel OOPSes... :-)


    Fun, fun, fun.

    Regards,
    Steve

    ------------------------------------------------------------------------
    Steve Schefter phone: +1 705 725 9999 x26
    The Software Group Limited fax: +1 705 725 9666
    642 Welham Road,
    Barrie, Ontario CANADA L4N 9A1 Web: www.wanware.com


  6. Re: memory mapped IO in kernel mode

    On Mon, 20 Mar 2006 06:46:05 -0800, steve_schefter wrote:

    > Captain Dondo wrote:
    >> Thanks, guys. It turns out that on an arm w/ 2.4 kernel, you need
    >> __ioremap, not ioremap.... Go figure.

    >
    > Strange. ioremap() should be #defined to call __ioremap with the
    > flags parameter set to zero. I use ioremap_nocache() (calls
    > __ioremap() with flags set to 1). You might want to try that as
    > it'll be more portable than __ioremap().
    >


    The issue is that each board can re-define ioremap via __arch_ioremap in
    include/asm-arm/arch-???/io.h . (Something I learned from this...
    Reading kernel headers is not something I do for fun.)

    So for mine (an EP93xx board), the comments read:

    /*
    * ioremap and friends.
    *
    * ioremap takes a PCI memory address, as specified in
    * linux/Documentation/IO-mapping.txt. If you want a
    * physical address, use __ioremap instead.
    */



    --
    o__
    ,>/'_ o__
    (_)\(_) ,>/'_ o__
    Yan Seiner, PE (_)\(_) ,>/'_ o__
    Certified Personal Trainer (_)\(_) ,>/'_ o__
    Licensed Professional Engineer (_)\(_) ,>/'_
    Who says engineers have to be pencil necked geeks? (_)\(_)


  7. Re: memory mapped IO in kernel mode

    Captain Dondo wrote:
    > The issue is that each board can re-define ioremap via __arch_ioremap in
    > include/asm-arm/arch-???/io.h . (Something I learned from this...
    > Reading kernel headers is not something I do for fun.)
    >
    > So for mine (an EP93xx board), the comments read:
    >
    > /*
    > * ioremap and friends.
    > *
    > * ioremap takes a PCI memory address, as specified in
    > * linux/Documentation/IO-mapping.txt. If you want a
    > * physical address, use __ioremap instead.
    > */


    Yeah, I saw that comment too. But the code in the headers
    doesn't seem to match the comment. Also, If you take a look
    at the referenced IO-mapping.txt file, it doesn't say that
    ioremap() is for PCI only. It does however say that it's
    useful for beyond the 640-1MB area so that may be where
    the idea of using ioremap() for PCI-space came from.

    I've only seen __arch_ioremap turned around to __ioremap.
    Perhaps yours is different though.

    Regards,
    Steve


+ Reply to Thread