This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Memory mapped I/O Linux 3.12 GPIO register offsets incorrect?

I am doing memory mapped I/O from user space under Linux kernel 3.12.  This works as expected EXCEPT that the offsets to the registers in the I/O bank that I needed to use don't match the offsets given in the TRM.  There is an article here that gave me invaluable insights into making this work...

http://stackoverflow.com/questions/13124271/driving-beaglebone-gpio-through-dev-mem

The relevant part is this code snippet...

#define GPIO0_BASE 0x44E07000
#define GPIO1_BASE 0x4804C000
#define GPIO2_BASE 0x481AC000
#define GPIO3_BASE 0x481AE000

#define GPIO_SIZE  0x00000FFF

// OE: 0 is output, 1 is input
#define GPIO_OE 0x14d
#define GPIO_IN 0x14e
#define GPIO_OUT 0x14f

#define GPIO0_BASE 0x44E07000
#define GPIO1_BASE 0x4804C000
#define GPIO2_BASE 0x481AC000
#define GPIO3_BASE 0x481AE000

#define GPIO_SIZE  0x00000FFF

// OE: 0 is output, 1 is input
#define GPIO_OE 0x14d
#define GPIO_IN 0x14e
#define GPIO_OUT 0x14f

Note that the GPIOx_BASE register addresses are correct as per the TRM, but the offsets to the GPIO_OE, GPIO_IN, GPIO_OUT registers are not.  These should be 0x134, 0x138, 0x13C as per the TRM.

This is very bizarre.  Not only are the register offsets that are needed different than documented, they are not on 4-byte boundaries.  I don't understand how that is possible.

From the article referenced above it seems that using the documented register offsets worked in kernel versions previous to 3.12.  The silicon has not changed.  This must be an issue related to the kernel version.

I would like to do the I/O using the GPIO_CLEARDATAOUT and GPIO_SETDATAOUT registers so that  I can be sure of doing atomic operations on the I/O and not need to worry about concurrency issues when doing the read/modify/write operations necessary when using the GPIO_DATAIN and GPIO_DATAOUT registers. 

Can someone please explain what is going on here?  And please provide the offsets to the GPIO_CLEARDATAOUT and GPIO_SETDATAOUT registers that will work under kernel 3.12?

  • Hi Bob,

    Where did you download the Linux from?

  • I noticed that error at http://stackoverflow.com/questions/13124271/driving-beaglebone-gpio-through-dev-mem 

    Error 0x14d, 0x14e, 0x14f

    It should have been 0x4d, 0x4e, 0x4f

    unsigned int offset address derived from the unsigned char address

    Posted it on Stack overflow 

  • It is the AM335x SDK 7 distribution from TI.

  • This issue is solved.  Both 0x4D, 0x4E, and 0x4F as well as 0x14D, 0x14E, and 0x14F work as offsets from the base for accessing these registers.  Obviously the 0x4D etc. offsets are correct due to C/C++ pointer arithmetic multiplying the offsets by 4 to get 0x134, 0x138, and 0x13C for these registers which matches what is documented in the TRM.

    Why offsets of 0x14D, 0x14E, 0x14F also work is a mystery.  Perhaps there is some incomplete address decoding being done in the CPU where only enough address lines are being decoded to resolve the offset of the register.

    The SETDATAOUT and CLRDATAOUT registers can be accessed using offsets 0x65 and 0x64 using the code presented in the stack overflow article referenced above/