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.

AM437x Device tree and GPIO

Other Parts Discussed in Thread: AM4372

What exactly am I getting by adding entries of the form “ti,hwmods = “ in the device tree? Does anyone have a reference on how the TI hwmod system works?  arch/arm/mach-omap2/omap_hwmod.c has a nice introduction, but it’s limited

The rest of this post is FYI on how I got the GPIO to work on the AM437X. The main “got ya” was that using “ti,hwmods = gpio6” in the dts causes the gpio module’s clocks to be initially disabled, and you have to enable them before you can write to the gpio modules registers.

I wanted to use GPIO5 for controlling LEDs from kernel and user space. The starting point is the gpio5 device tree entry in the AM437x eval board file arch/arm/boot/dts/am4372.dtsi.

            gpio5: gpio@48322000 {

                  compatible = "ti,am4372-gpio","ti,omap4-gpio";

                  reg = <0x48322000 0x1000>;

                  interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;

                  gpio-controller;

                  #gpio-cells = <2>;

                  interrupt-controller;

                  #interrupt-cells = <2>;            

                  ti,hwmods = "gpio6";               

                  status = "disabled";

            };

This file is included in my custom dts along with the entry

&gpio5 {

      status = "okay";

};

My kernel module uses the standard technique of requesting and mapping io memory:

MemoryRegion = request_mem_region(physicalAddr, length);

VirtualAddr = ioremap(physicalAddr,length);

and the user application (which does not require my kernel module) uses the Linux /dev/mem driver and mmap

fd=open(“/dev/mem”,O_RDWR | O_SYNC);

VirtualAddr = mmap(0,size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, physicalAddr);

Note that the physical address must be page aligned. Corbet, et. al.,Linux Device Drivers explain these in detail.

Gpio can also be accessed through the sysfs as explained in Documentation/gpio-legacy.txt. The confusing part is finding the gpio number. Here is a simple way to find the number. Do a ls –l in the /sys/class/gpio directory. In my case I see the link in the output

gpiochip64 -> ../../devices/platform/44000000.ocp/4832200.gpio/gpio/gpiochip64

The thing to note is the 4832200 which corresponds to the device tree entry above for gpio5. So the gpio5 pins are handled by gpiochip64. The “64” is the Linux gpio number for the first pin handed by gpiochip64. Therefore, gpio5_0 is Linux gpio number 64 (gpio5_1 is 65, etc). To use the sysfs to access gpio5_0,

cd /sys/class/gpio

echo 64 > export

This creates the subdirectory /sys/class/gpio/gpio64, then

cd gpio64

echo out > direction

echo 0 > value

This makes Linux gpio 64, which is gpio5_0, an output and assigns it the value 0.

Here’s what I found. Both my kernel module and user application caused an exception (the dreaded Custom Error: MASTER M2) unless I removed the “ti,hwmods = gpio6” from the device tree, or unless I accessed the gpio using the sysfs before loading the kernel module or running the application. This was because the hwmod initialization left the gpio5 module’s clock disabled. The sysfs access enables the clock, so after using it, everything worked.

The solution is to enable the gpio module’s clock in the kernel module and user application BEFORE trying to access any of the gpio modules registers. So I needed to map two memory regions: first the CM_PER region in L4WKUP memory to access the gpio5 clock control register (CM_PER is for gpio1-5, for gpio0, it’s the CM_WKUP region), then, after enabling the clock, map the GPIO5 device in L4_PER memory (or for gpio0, map GPIO0 in L4_WKUP). Once these regions were mapped and I had virtual addresses for the registers, I configured them as described in the TRM and everything worked.

  • I will ask the software team to comment.
  • Hi, 

    Mark Doyle said:
    What exactly am I getting by adding entries of the form “ti,hwmods = “ in the device tree? Does anyone have a reference on how the TI hwmod system works?

     

    This is described in linux documentation, see Documentation/devicetree/bindings/gpio/gpio-omap.txt: 
       

    OMAP specific properties:
    - ti,hwmods:                              Name of the hwmod associated to the GPIO:
                                                      "gpio<X>", <X> being the 1-based instance number
                                                      from the HW spec.

    Hope this helps. 

    Best Regards, 

    Yordan