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.

omapl138 gpio input value not changing

Other Parts Discussed in Thread: OMAPL138, OMAP-L138, OMAP-L132, OMAP-L137, DA8XX

Hi All,

I have been having some problems setting up the GPIO on my omapl138.

By modifying the kernel (I am using the davinci psp) I have been able to access the relevant GPIO's and have successfully toggled the values when setup as output pins.

When I modify the pin to be an input, I get no change from the button wired up.

I am wondering what additional changes I may need to make in the kernel to enable input values to be modified.

The process I have followed to setup the pinmuxing:

include/mach/mux.h

 - add relevant identifiers for da850 (DA850_GPIO7_3 etc)

da850.c

 - added to the mux_config struct

  MUX_CFG(DA850, GPIO7_3, 17, 24, 15, 8, false)

then in the board file I have added the necessary initialization routine.

As I mentioned this all successfully exports my pin to user space and they can be access via sysfs and toggled - but only as output pins.

I think that the values in my MUX_CFG above must be incorrect (possibly the MODE_MASK - 15), but I am a little stumped as to what the values should be for different GPIO applications.

I can post any code, info etc etc. Any help would be greatly appreciated!

Thanks in advance,

George

  • The line "MUX_CFG(DA850, GPIO7_3, 17, 24, 15, 8, false)" is good. If you've got outputs working, I think you pinmux config is good.Might be a pull-up or pull-down problem. I don't remember being able specify pullups from sysfs. You might have to do that from the kernel.

    Line GP7[3] is muxed in with BOOT[3. I believe the boot pins are tied to high or low as appropriate for the boot mode. I guess is the pins are tied directly to high or low without a resistor, you probably cannot change the level, in or out. Since you can change them as outputs, I would guess that there are resistors.

  • Hi Norman,

    Thanks for your reply. I'll try the button elsewhere. I did think that the relation to BOOT pins might be an issue. I'll let you know if I have success!

    Cheers,

    George

  • Hi Norman,

    I have moved everything to GP7[13]. As far as i can tell there is nothing here that should interfere with the input from a button. As before, I am able to toggle the output values and light an led, but when I add a button, the value remains the same.

    I am using sysfs. The button runs high and on a push should set the gpio value to low. I've tested the button with an oscilloscope and confirmed that it behaves as expected.

    I am wondering if there are settings in some of the other files that should be set?

    For example, active_low (although i have tried both settings) or some settings in the power directory.

    Just for completeness I added pinmux values for GP7[13] as below:

    MUX_CFG(DA850, GPIO7_13, 16, 16, 15, 8, false);

    Thanks,

    George

  • The line "MUX_CFG(DA850, GPIO7_13, 16, 16, 15, 8, false)" looks good. Most GPIO problems are pinmux problems. If you can toggle the GPIO as an output, the input function should work without problems. Toggling the GPIO as an output proves that the pinmux and GPIO controller are good. Not much else left. I cannot think of anything in the configuration that could get in the way. If you do figure it out, please post the solution. I'd be curious. Maybe post the sysfs commands that you are using.

  • Thanks Norman. I think the issue may be related to the fact that we are using a pull-up switch, so when it is pressed it should toggle the GPIO to 0. I was digging around and saw mention of a pull up/down register. Perhaps I need to set something in there?

  • By the way, the sysfs commands are pretty standard.

    echo 115 > export

    cd gpio115

    cat direction

    "in"

    cat value

    1

    Switch is showing high on oscilloscope. Press switch, cat value - no change.

    Ive also tried modifying the values elsewhere (active_low both 0 and 1).

    If I modify the pin to be output and change the value, the oscilloscope picks up the value change via the button!

    Anyway - I'll talk to the hardware guys and make sure the wiring is correct. I'll also test it out on a different board, different switch.

    I also have a kernel driver that exports the gpios and sets them up as in/out. But still the same issue, so I normally don't insmod it.

    If you know anything about the pull up/down registers and if it is worthwhile pursuing that would be great.

    Thanks so much for your assistance,

    Cheers,

    George

  • See eye-glazing detail from the docs.

    --------
    SPRS586D - OMAP-L138 Datasheet
    2.8.11 Boot
    Table 2-15. Boot Mode Selection Terminal Functions
    NAME = VP_DOUT[11] / LCD_D[11] / UPP_XD[3] / GP7[3] / BOOT[3]
    NO. = T3
    TYPE = I
    PULL = CP[29]
    GROUP = C

    IPD = Internal Pulldown resistor; IPU = Internal Pullup resistor; CP[n] = configurable pull-up/pull-down (where n is the pin group) using
    the PUPDENA and PUPDSEL registers in the System Module. The pull-up and pull-down control of these pins is not active until the
    device is out of reset. During reset, all of the pins associated with these registers are pulled down. If the application requires a pull-up,
    an external pull-up can be used. For electrical specifications on the pull-up and and internal pull-down circuits, see the Device Operating
    Conditions section.

    2.8.25 General Purpose Input Output
    Table 2-29. General Purpose Input Output Terminal Functions
    NAME = VP_DOUT[5] / LCD_D[5] / UPP_XD[13] / GP7[13] / PRU1_R31[13]
    NO. = V3
    TYPE = I/O
    PULL = CP[28]
    GROUP = C

    NAME = VP_DOUT[11] / LCD_D[11] / UPP_XD[3] / GP7[3] / BOOT[3]
    NO. = T3
    TYPE = I/O
    PULL = CP[29]
    GROUP = C

    --------
    SPRUH77A - OMAP-L138 TRM
    11.5.22 Pullup/Pulldown Enable Register (PUPD_ENA)
    0 Internal pull-up or pull-down functionality for pin group n is disabled.
    1 Internal pull-up or pull-down functionality for pin group n is enabled.
    Reset value = 0xFFFF FFFFh

    11.5.23 Pullup/Pulldown Select Register (PUPD_SEL)
    0 Internal pull-down functionality for pin group n is enabled.
    1 Internal pull-up functionality for pin group n is enabled.
    0xC3FFFFFFh

    Group 28 mask = 1<<28 = 0x10000000
    Group 29 mask = 1<<29 = 0x20000000

    Out of reset, most pins are internally pulled up. For Group 28 and 29, those pins are pulled down. So a pull-up switch would be okay. That is not to say that PUPD_ENA and PUPD_SEL haven't been modified after boot.

    ---------
    SPRAB41D - Using the OMAP-L132/L138 Bootloader
    Appendix A Boot Mode Selection Table
    Table 11. Boot Mode Selection
    Check for Boot[3] in this table. It will be strapped high or low as appropriate. This might fight with your switch.

  • Great. I'll scan through everything tomorrow and let you know the outcome.

    Thanks again.

  • Hi Norman,

    I had a dig through everything. I'm not sure I've got the pullup/down register changes right, although the GPIO seems to be set up correctly.

    At this point I am waiting to discuss the issue with the chap that wired up the switch.

    As far as i can see from the documentation - using the internal pullup wouldn't make any difference to this situation anyway.

    I'll update with progress,

    George

  • Hi Norman,

    Is there any sample code for setting of registers from the kernel (or a kernel module).

    I can see that for the GPIO's I have chosen they default to pulldown. They require a 1 to activate the pull up.

    My problem is, I am unable to find relevant headers where the registry identifiers are declared, and the names don't seem to be globally accessible.

    I have been trying to modify another pin that has pullup set as default - but there are problems relating to the muxing and I am unable to get control and export the relevant pins. (this is totally another issue and not one for here really.)

    Anyway, your help is greatly appreciated.

    George

  • I don't quite understand about sample kernel code. The MUX code you got well in hand. Examples of gpio code are sprinked throughout the various drivers. The file "Documentation/gpio.txt" gives a good description of kernel and userspace gpio code. Each kernel version has different capabilities. I usually look at the sysfs gpio code for reference. It's at "drivers/gpio/gpiolib.c".

    Some kernels have a debugfs that can help with debugging pinmux and gpio. Works great on the Overo platform. Never got it to work with the OMAP-L137. I might have missed something in the kernel config.

    mkdir /tmp/debugfs
    mount -t debugfs none /tmp/debugfs
    cat /tmp/debugsfs/gpio

    The usual other thing that causes GPIO/pinmux problems is when some other code grabs the pin after your code. I don't think this is the case here as you can toggle the pin as an output. If the pin was assigned away, yoy shouldn't be able to toggle the pin.

    This might be nothing. Did you add "DA850_GPIO7_3" to the bottom of the enum list? Inserting in the middle would change the exising enumerations. In theory, the kernel build should detect the dependencies and recompile all the source dependent on the enumeration. To be sure, maybe try a total rebuild.

  • What I meant by sample kernel stuff is actually changing the value of the PUPDSEL and PUPDENA registers.

    As I am unable to find definitions for them in any headers I am starting to enter into "I know nothing" territory.

    The gpio headers that I can find, all offer options for setting direction, exporting, edge files etc - but the actual register that enables pull up or pull down isn't accessible via the normal gpio headers and c files.

    I'll keep hunting, but any thoughts would be appreciated.

    Oh, and I tried the suggestion of moving the enum entries and doing a clean build - but it didn't help unfortunately.

  • I don't believe either U-Boot or Linux modify those registers. The PUPD registers are part of SYSCFG1. Relevant bits in the header.

    arch/arm/mach-davinci/include/mach/da8xx.h
    #define DA8XX_SYSCFG1_VIRT(x)   (da8xx_syscfg1_base + (x))
    #define DA8XX_DEEPSLEEP_REG     0x8
    #define DA8XX_PWRDN_REG         0x18

    Looks like only DEEPSLEEP and PWRDN are used in da850.c and devices-da8xx.c.

    In U-Boot, the defines are in, "arch/arm/include/asm/arch-davinci/hardware.h". Looks like only SYSCFG0 is supported.

    That only leaves the ARMUBL. Doubt it would change those registers. I think the PUPD registers have power up reset values. As you say, the pull up/pull down setting shouldn't have that much effect. It may be a red herring. Sorry if I send you down the wrong path.

    I vaguely remember reading somewhere that boot pins can only be used as outputs after boot. And only if the pins strapped up or down with resistors. I can't the find the exact documents. I might have "misremembered". Must be something very obvious. If you find it, please post your findings.

  • Ok, for example on an omap3 you can set the pull up or down in the pinmux settings:

    MUX_VAL(GPIO_IDENTIFIER, (IEN | PD | M4));

    On other boards there is even an omap_mux file that appears in debugfs - where you can literally echo in the pull up values you require.

    The problem is definitely related to having the pullup pulldown set incorrectly.

    There must be a way to change these values on an omapl138, surely?

    For example - when I connect the board to CCS you can see the registers and set them to enable/disable and pull/up etc - but it isn't a persistent change and once I boot my kernel, those modifications are lost. But if CCS can change the values - surely it is possible for me to do it another way?

  • The OMAP1/2/3/4 and Davinci are totally different families in HW and SW. The debugfs is quite spiffy on the Omap4 processors. Never use the Davinci version. The Omap4 processors do not have as much protection on the pinmux registers. I believe the L138 requires hitting the lock-lock registers and be in priviledged mode to change the pinmux registers. Possible code to double check the PUPD registers:

    arch/arm/mach-davinci/include/mach/da8xx.h
    ...
    #define DA8XX_DEEPSLEEP_REG     0x8
    #define DA8XX_PUPDENA_REG       0x0C /*Add*/
    #define DA8XX_PUPDSEL_REG       0x10 /*Add*/
    #define DA8XX_PWRDN_REG         0x18

    arch/arm/mach-davinci/da850.c
    void __init da850_init(void)
    {
      da8xx_syscfg1_base = ioremap(DA8XX_SYSCFG1_BASE, SZ_4K);
      ...
      printk("PUPDENA=%x\n", DA8XX_SYSCFG1_VIRT(DA8XX_PUPDENA_REG)); /*Add after ioremap() */
      printk("PUPDSEL=%x\n", DA8XX_SYSCFG1_VIRT(DA8XX_PUPDSEL_REG)); /*Add after ioremap() */
      ...
    }

  • Hi Norman,

    I ran the print output and I'm not sure that the register addresses are correct. The output is definitely not what is shown in the trm or when I plug into code composed.

    Is there a map of the register addresses somewhere?

    George

  • Actually - when i print the values returned from a raw_readl the values do seem correct.

    For some reason, when I modify the value and do a raw writel the value isn't getting updated. I'll double check and let you know.

    George

  • Yes - it seems the values are correct.

    Once I have toggled the necessary bits, I perform a __raw_writel

    Unfortunately this isn't updating the register for some reason. I'm assuming it is protected in some way - or I am just doing it wrong. Could you have a go at writing a new value into the register on your end and see if it is possible?

  • Ok - fixed the __raw_writel issue. Just waiting for one of the hardware guys and we are going to test the modifications.

    I'll let you know - hopefully this is it.

  • The addresses that Linux will access are virtual. They won't match the physical addresses noted in the TRM. I can't try out the code on my end as I don't have a OMAP-L138 EVM. I do have a OMAP-L137 EVM but it's tied up on a project.  The OMAP-L137 does not even have those registers.

  • Hi Norman,

    Don't worry about testing it - I managed to get all of the software stuff working.

    Just to confirm everything is looking better. The hardware guys had chosen a set of GPIO pins that were only usable as output.

    I'm really sorry that we went through all of this stuff just to find this out - but as an exercise this has been hugely valuable. As part of the wider project it will be necessary to modify the pull up and pull down registers and go quite far into the pinmux settings in general.

    I can only assume that, once they have things wired up correctly, we should be able to see the change in input value from a button.

    Thanks so much for all of your help.

    George