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.

Linux/PROCESSOR-SDK-AM57X: Toggle GPIO for camera module from driver code

Part Number: PROCESSOR-SDK-AM57X
Other Parts Discussed in Thread: TMDSEVM572X

Tool/software: Linux

Hi,

I am having TMDSEVM572X with AM572x Evaluation Module with latest linux-processor sdk.

This time i am not connecting the camera, just want to check the pin status hardwarely. My question is can i set  GPIO pin manually from driver side code?(ti-processor-sdk-linux-am57xx-evm-03.03.00.04/board-support/linux-4.4.41+gitAUTOINC+f9f6f0db2d-gf9f6f0db2d/drivers/media/i2c/mt9t11x.c)? e.g. i did following in "mt9t11x_probe()" function-

gpio_read = gpiod_get_raw_value(priv->bufen_gpio);
dev_err(&client->dev, "BUFEN_PREV %d", gpio_read);
gpiod_set_raw_value_cansleep(priv->bufen_gpio, 1);
gpio_read = gpiod_get_raw_value(priv->bufen_gpio);
dev_err(&client->dev, "BUFEN_AFTER %d", gpio_read);

It is reflecting my changes in log (dmesg |grep mt9t11x), as-

[ 7.867966] mt9t11x 4-003c: BUFEN_PREV 0
[ 7.871907] mt9t11x 4-003c: BUFEN_AFTER 1

but not able to get high at hardware pin level.

Thanks.

  • The software team have been notified. They will respond here.
  • Hi Biser,

    Any update?
  • Feedback will be posted directly here when available.
  • Hello,

    To check the hardware you can drop the code changes above you did. Have you done the following ?
    1: Have you set the pinmux appropriately to select the gpio ?
    2: Which bank is the gpio from, is the bank enabled can you read the revision number of it ?
    3: Refer link [1] to test the hardware from user space to set the gpio pin as op/ip

    [1] elinux.org/GPIO

    Cheers,
    --Prabhakar Lad
  • Hi Prabhakar,

    Have you set the pinmux appropriately to select the gpio ?


    Yes, i did the pinmux appropriately in mux_data.h and am57xx-beagle-x15-common.dtsi files.

    Which bank is the gpio from, is the bank enabled can you read the revision number of it ?


    My gpio is gpio1_19 (Ball name- GPMC_AD13). Can you please suggest me how to find the corresponding bank and enable it?

    Refer link [1] to test the hardware from user space to set the gpio pin as op/ip 


    I have gone through this, the values are updated software but not reflecting in Hardware.

    Thanks.

  • Hi,

    [quote]My gpio is gpio1_19 (Ball name- GPMC_AD13). Can you please suggest me how to find the corresponding bank and enable it?[quote]

    Add the bellow in am57xx-beagle-x15-common.dtsi (kernel code) :
    &gpio1 {
    pinctrl-names = "default";
    pinctrl-0 = <&your_gpio1_pinmux_node_name>;
    status = "okay"; ===> This enables GPIO1.
    };

    Then in the kernel driver you should add the appropriate gpio headers & use the apis described in Documentation/gpio/gpio.txt & Documentation/gpio/driver.txt.

    Best Regards,
    Yordan
  • Hi Yordan,

    I added the above calls but still no result.

    Please just verify my steps to toggle a perticular gpio (gpio1_19)-

    1) I changed the pinmux setting in mux_data.h.

    {GPMC_AD13, (M14 | PIN_OUTPUT)}, /* gpmc_ad13.BUFF_EN gpio1_19*/

    2) Made a node in am57xx-beagle-x15-common.dtsi

    gpio1_pins_default: gpio1_pins_default {
    pinctrl-signle,pins = <
     0x34 (PIN_OUTPUT | MUX_MODE14) //gpmc_ad13.gpio1_19
    >;

    }; 

    and the added the above calls that you stated.

    &gpio1 {
    pinctrl-names = "default";
    pinctrl-0 = <&gpio1_pins_default>;
    status = "okay"; // To enable GPIO1
    };

    also in same file in &i2c5 call,


    &i2c5 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c5_pins_default>;
    clock-frequency = <400000>;
    mt9t11x@3C {
    compatible = "aptina,mt9t111";
    reg = <0x3C>;


    bufen-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;


    port {
    cam: endpoint {
    remote-endpoint = <&vin3a>;
    hsync-active = <1>;
    vsync-active = <1>;
    pclk-sample = <0>;
    input-clock-freq = <32000000>;
    pixel-clock-freq = <96000000>;
    };
    };
    };
    };

    In driver code, i added

    //reading buffen_gpio status
    gpio_read = gpiod_get_raw_value(priv->bufen_gpio);
    dev_err(&client->dev, "BUFEN_PREV %d", gpio_read);
    gpiod_set_raw_value_cansleep(priv->bufen_gpio, 1);
    gpio_read = gpiod_get_raw_value(priv->bufen_gpio);
    dev_err(&client->dev, "BUFEN_AFTER %d", gpio_read);

    Any mistake in these changes? Still not working. I am not getting HIGH output.

    Thanks.

  • Hi Yordan.
    Any suggestion?

    thanks.
  • Hi,

    Can you test with raw writes to the corresponding GPIO_DATAOUT register?
    Also have a look at omap-gpio.c driver, there is a omap_set_gpio_dataout_reg() function which is used to toggle bits (gpios) in the DATAOUT register.

    Best Regards.
    Yordan
  • Also a note for your code:
    when using gpiod_set_value_cansleep() you need to lock the gpio with mutex. This is explained in the kernel documentation, also see gpiolib-sysfs.c driver (bellow chunk of code is just one example):
    static ssize_t value_store(struct device *dev,
    struct device_attribute *attr, const char *buf, size_t size)
    {
    struct gpiod_data *data = dev_get_drvdata(dev);
    struct gpio_desc *desc = data->desc;
    ssize_t status;

    mutex_lock(&data->mutex);

    if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
    status = -EPERM;
    } else {
    long value;

    status = kstrtol(buf, 0, &value);
    if (status == 0) {
    gpiod_set_value_cansleep(desc, value);
    status = size;
    }
    }

    mutex_unlock(&data->mutex);

    return status;
    }

    Best Regards,
    Yordan
  • Hi Yordan,

    Can you test with raw writes to the corresponding GPIO_DATAOUT register? 
    Also have a look at omap-gpio.c driver, there is a omap_set_gpio_dataout_reg() function which is used to toggle bits (gpios) in the DATAOUT register. 


    I found omap_gpio_set_value() function in omap_gpio.c driver.

    What is the difference of using omap_gpio_set_value()  and gpiod_set_value_cansleep()/gpiod_set_raw_value_cansleep(). As gpiod_set_value_cansleep() is already being used in mt9t11x.c driver to set the GPIO value i guess. Is this not correct?

    Can you please go through the mt9t11x.c driver? And let me know what is the issue there if any?

    when using gpiod_set_value_cansleep() you need to lock the gpio with mutex.


    I did that but no satisfying output.

  • Hi Yordan,

    Can you test with raw writes to the corresponding GPIO_DATAOUT register?

    Also have a look at omap-gpio.c driver, there is a omap_set_gpio_dataout_reg() function which is used to toggle bits (gpios) in the DATAOUT register.

    I found omap_gpio_set_value() function in omap_gpio.c driver.

    What is the difference of using omap_gpio_set_value()  and gpiod_set_value_cansleep()/gpiod_set_raw_value_cansleep(). As gpiod_set_value_cansleep() is already being used in mt9t11x.c driver to set the GPIO value i guess. Is this not correct?

    Can you please go through the mt9t11x.c driver? And let me know what is the issue there if any?

    when using gpiod_set_value_cansleep() you need to lock the gpio with mutex.

    I did that but no satisfying output.

  • Hello,

    can you mention which gpio pin you want test ? Ill write out the register settings for you and you can test them at your end.

    Cheers,
    --Prabhakar Lad
  • Hi Prabhakar,
    Thanks for that.

    There are two GPIOs i want to set-
    1)Ball name- gpmc_ad15, Ball number-H3. I want to configure this pin as gpio1_21. This pin is pulled up in Hardware through resister hence giving 3.3v output bydefault. I want to make it LOW.
    2)Ball name- gpmc_ad12, Ball number-H1. I want to configure this pin as gpio1_18. This pin is pulled down in Hardware, giving 0v bydefault. I want to make it HIGH.

    Eagerly waiting for that:-)
    Thanks.
  • Hello,

    My bad i read thre trm wrongly its only gpio1[0:3] are as i/p only.


    Pinmux for GPIO1_18 register 0x4a003430 should be set to 0x5000E

    Pinmux for GPIO1_21 register 0x4a00343c should be set to 0x5000E

    Try this from the uboot first to check if the h/w is rite:

    mw is cmd to write and md is to display:

    0x4ae10134 = FFEBFFFF > set pins as o/p

    0x4ae10194 = 140000 > to make the pin high

    0x4ae10190 = 140000 > to make the pin low


    Cheers,
    --Prabhakar Lad

  • Hi prabhakar,
    Thanks for the clarification.

    But according to am57xx datasheet. Using muxmode 14, these pins can be configured as IO. I am not clear that these pins are only input.
    Can you please tell me where these are defined as input? Also these are declared as input in mux_data.h file, but i changed that as output. Am i wrong?
    I am doing that because I want to use the signals(HIGH and LOW) coming out from these pins to drive external hardware. Can this be done?
  • Hello,

    Sorry about that, I rewrote the post please refer that.

    Cheers,
    --Prabhakar Lad
  • Hi prabhakar,
    Please elaborate-

    mw is cmd to write and md is to display:
    0x4ae10134 = FFEBFFFF > set pins as o/p
  • Hello,

    0x4ae10134 = FFEBFFFF > set pins as o/p
    This is setting GPIO_OE register refer trm page 7110, so pin 18/21 are set as o/p.

    So in uboot if you do the following:
    mw 0x4a003430 0x5000E >>> Set the pinmux
    mw 0x4a00343c 0x5000E >>> Set the pinmux

    mw 0x4ae10134 0xFFEBFFFF >>> Make pin as o/p
    mw 0x4ae10194 0x140000 >>> Make pin high

    At this point if you scope the pin it should be high

    Now to make it low

    mw 0x4ae10190 0x140000 >>>>> Set pin low

    Now if you scope thin it should be low.

    Cheers,
    --Prabhakar Lad
  • Hi,
    I apologize, this could be a bit annoying to you. I am not expert in driver developement.
    Please tell me where to do these changes. The files known to me for changes are - mux_data.h and am57xx dts files. Where should i add these changes.
  • Hello,

    To firstly test your hardware, stop the board at uboot, And do the above steps which I mentioned. When you stop at uboot you get a prompt where you can enter commands. sp mw is a command in uboot which writes to memory.

    Once you are happy that the hardware is working as expected in uboot I'll help you out of doing this in Linux.

    Cheers,
    --Prabhakar Lad
  • Oh, Very thanks.
    I will reply you very quickly.
  • Hi Prabhakar,
    Thanks for elaboration.
    I get the output accordingly and its working correct.

    Please guide me next.
  • Hello,

    Great!

    Can you post the changes which you did in dts for the gpio pinmux ?

    Cheers,
    --Prabhakar Lad
  • In mux_data.h file, These changes are done in const struct pad_conf_entry core_padconf_array_essential_x15[] function,
    // {GPMC_AD12, (M2 | PIN_INPUT | MANUAL_MODE)}, /* gpmc_ad12.vin3a_d12 */
    // {GPMC_AD13, (M2 | PIN_INPUT | MANUAL_MODE)}, /* gpmc_ad13.vin3a_d13 */
    // {GPMC_AD14, (M2 | PIN_INPUT | MANUAL_MODE)}, /* gpmc_ad14.vin3a_d14 */
    // {GPMC_AD15, (xM2 | PIN_INPUT | MANUAL_MODE)}, /* gpmc_ad15.vin3a_d15 */

    //New Gpios for Camera
    {GPMC_AD12, (M14 | PIN_OUTPUT)}, /* gpmc_ad12.OSC_EN gpio1_18*/
    {GPMC_AD13, (M14 | PIN_OUTPUT)}, /* gpmc_ad13.BUFF_EN gpio1_19*/
    {GPMC_AD14, (M14 | PIN_OUTPUT)}, /* gpmc_ad14.GPIO gpio1_20*/
    {GPMC_AD15, (M14 | PIN_OUTPUT)}, /* gpmc_ad15.CAM_PWR gpio1_21*/
    {GPMC_A13, (M14 | PIN_OUTPUT)}, /* gpmc_a13.gpio2_3 for Cam_En */
    //New Gpios for Camera

    // {MCASP1_AXR8, (M14 | PIN_OUTPUT)}, /* mcasp1_axr8.gpio5_10 for OSC_EN */
    // {MCASP1_AXR9, (M14 | PIN_OUTPUT)}, /* mcasp1_axr9.gpio5_11 for CAM_PWRDN*/
    // {MCASP1_AXR10, (M14 | PIN_OUTPUT)}, /* mcasp1_axr10.gpio5_12 for BUFF_EN*/
    // {MCASP1_AXR11, (M14 | PIN_OUTPUT_PULLUP)}, /* mcasp1_axr11.gpio4_17 for RESET*/
    // {GPIO6_11, (M0 | PIN_OUTPUT_PULLUP)}, /* gpio6_11.gpio6_11 used for Cam_En in LCD Module*/


    In am57xx-beagle-x15-common.dtsi file i added/changed


    //changes
    &gpio1 {
    pinctrl-names = "default";
    pinctrl-0 = <&gpio1_pins_default>;
    status = "okay";
    };

    &gpio2 {
    pinctrl-names = "default";
    pinctrl-0 = <&gpio2_pins_default>;
    status = "okay";
    };
    //changes


    &i2c5 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c5_pins_default>;
    clock-frequency = <400000>;
    mt9t11x@3C {
    compatible = "aptina,mt9t111";
    reg = <0x3C>;

    //Original definitions
    // reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
    // oscen-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>;
    // powerdown-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
    // bufen-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
    // camen-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;


    //New Definitaions
    reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
    oscen-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
    powerdown-gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
    bufen-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
    camen-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
    port {
    cam: endpoint {
    remote-endpoint = <&vin3a>;
    hsync-active = <1>;
    vsync-active = <1>;
    pclk-sample = <0>;
    input-clock-freq = <32000000>;
    pixel-clock-freq = <96000000>;
    };
    };
    };
    };

    In same file, i added following in &dra7_pmx_core node-
    gpio1_pins_default: gpio1_pins_default {
    pinctrl-single,pins = <
    0x030 (PIN_OUTPUT | MUX_MODE14) //gpmc_ad12.gpio1_18
    0x034 (PIN_OUTPUT | MUX_MODE14) //gpmc_ad13.gpio1_19
    0x038 (PIN_OUTPUT | MUX_MODE14) //gpmc_ad14.gpio1_20
    0x03C (PIN_OUTPUT | MUX_MODE14) //gpmc_ad15.gpio1_21

    >;
    };

    gpio2_pins_default: gpio2_pins_default {
    pinctrl-single,pins = <
    0x074 (PIN_OUTPUT | MUX_MODE14) //gpmc_a13.gpio2_3
    >;
    };

    Actually my aim with this is to run a camera. The configuration for i2c pins in p16 header is successfully done. Only these GPIOs were not reflecting my changes.
  • Hello,

    On linux bootup what is the sate of the pins gpio1_18/gpio1_21 ? (please remove any code which you added in driver files to set the gpio pins )

    Also what is the value of the registers in Linux:
    [1] 0x4a003430
    [2] 0x4a00343c

    In case if you dont know how to read a register in linux use [1] and cross compile this application and use it on linux bootup.
    [1] free-electrons.com/.../devmem2.c

    Cheers,
    --Prabhakar Lad
  • Hi,
    Got the values-
    for 0x4a003430
    Memory mapped at address 0xb6fee000.
    Value at address 0x4A003430 (0xb6fee430): 0x1000E

    for 0x4a00343c
    Memory mapped at address 0xb6f4f000.
    Value at address 0x4A00343C (0xb6f4f43c): 0x1000E
  • On linux bootup what is the sate of the pins gpio1_18/gpio1_21 ? (please remove any code which you added in driver files to set the gpio pins )

    Cheers,
    --Prabhakar Lad
  • gpio1_18 = 0V,
    gpio1_21 = 3.3V

    Also I have removed all changes what i did in the driver code.
  • I am suspecting these values because of pulldown/pullup with 10k resister in hardware.
  • Hi prabhakar,

    Any update? :-)

  • Hi Yordan,

    Can you test with raw writes to the corresponding GPIO_DATAOUT register?


    I checked and confirmed the raw writes during uboot. Its working fine.

    Also have a look at omap-gpio.c driver, there is a omap_set_gpio_dataout_reg() function which is used to toggle bits (gpios) in the DATAOUT register. 


    I want to ask that in mt9t11x.c which i am currently using, there are calls for setting gpios. So what is the difference in using omap_set_gpio_dataout_reg()?

  • Hello Prabhakar,
    please update me the next step. I guess hardware checking is done. now need to configure the necessary dts files.
  • Hi,
    I am facing the same question as u did.Could u explain the following gpios function to me?What are they used for and how to change them?
    //Original definitions
    // reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
    // oscen-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>;
    // powerdown-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
    // bufen-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
    // camen-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
    i am confused and wondering if you can provide more insight for me on this.
    Thanks in advance n BR,
    Boycchi
  • Hi,
    These pins are used to configure the GPIO states required for the TMDSEVM572x Camera Module.
    If you want to change those pins according to your need, then have a look in am578 datasheet for pinmux setting.