Toggle a GPIO pin using Register Access

Dear All,

Can we access the GPIO using registers like any other MCU ?

we aim to toggle a gpio pin at high frequency

Regards
Shashank

Hi @Shashank_Jagadish

Of course you can access the registers that operate the GPIO just like any other micro-controller, but the control of GPIOs is inside the kernel and you would likely have to make significant mods to the kernel to get it running, even then it would not be a very stable frequency since the other activities on the CPU may cause you to be early or late in accessing the register.

Instead why not use the hardware clock generators inside the APQ8016E? There are quite a few of them. Take a look at the APQ8016E Device specification DEVSPEC , and the 410c board Schematic SCHEM. On Pages 33,34,35 of the DEVSPEC you will find quite a few General purpose clock outputs that can be used. Following each of the GPIOs from the APQ8016E on the SCHEM you find that a few of them get connected to Low Speed Connector:

APQ8106E   Name         Connector   Name
GPIO_25    GP_PDM_0B    LS30        GPIO_H
GPIO_113   GP_PDM_1B    LS18        MI2S_SCLK
GPIO_12    GP_CLK_2B    LS24        GPIO_B
GPIO_13    GP_CLK_3B    LS25        GPIO_C
GPIO_110   GP_MN        LS16        MI2S_WS

I have a code snippet from Android that turns GPIO_13 (GPIO_C on pin 25 of the low speed connector) into a 19.2MHz clock. This is not the frequency you want (I think you were looking for 40kHz), and may not be the pin you want, but it gives you a clue on how to do this.

In the DSTI files add:

pwm_clkout { 
    qcom,pins = <&gp 13>; /* GP_CLK_3 */ 
    qcom,num-grp-pins = <1>; 
    qcom,pin-func = <3>; 
    label = "gp_clk3"; 

    gp_clk3_active: gp_clk3_active { 
        drive-strengh = <8>; 
        bias-disable; 
    }; 
    gp_clk3_suspend: gp_clk3_suspend { 
        drive-strengh = <2>; 
        bias-disable; 
    }; 
}; 

and

    clocks = <&clock_gcc gcc_gp3_clk>; 
    clock-name = "pwm-clk"; 

Then in your code add

struct clk *pwm_clk = NULL; 
int ret; 

pwm_clk = clk_get(dev, "pwm-clk"); 
if (IS_ERR(pwm_clk)) { 
   dev_err(dev, "%s: Get pwm_clk error\n", __func__); 
    return -ENODEV; 
} 

ret = clk_set_rate(pwm_clk, (unsigned long)19200000); 
if (ret < 0) { 
    dev_err(dev, "%s: Can't set pwm_clk rate 19.2MHz (%d)\n",   __func__, ret); 
    clk_put(pwm_clk); 
    return ret; 
} 

ret = clk_prepare_enable(pwm_clk); 
if (ret < 0) { 
    dev_err(dev, "%s: Can't enable pwm_clk %d\n",  __func__, ret); 
    clk_put(pwm_clk); 
    return ret; 
} 

NOTE: I haven’t tested this code, and I don’t know exactly which files you need to modify. Also this code is for the Android kernel, not for the Linaro kernel, so it won’t work ‘as-is’. I am not even sure that the code has been migrated to the Linaro kernel, so you may have to port it from the Android kernel to the Linaro kernel.

Looking at the functions that the code is calling, I believe it is accessing the RPM (Resource and Power Manager) to turn on the clocks. You can look in this document for more details on the RPM APIs

There are also a couple other signals that you could hijack to create a clock, such as the MCLK pins for the cameras, or the SCLK pin for the I2S, or possibly even the SPI clock pin.

Full Disclosure, I am an employee of Qualcomm Canada. Any opinions I may have expressed in this or any other post may not reflect the opinions of my employer.

Hi @Shashank_Jagadish,

Based on great inputs by @ljking I’ve added sample PWM support for on chip GP_CLK3 module in linux. I should say that the driver I’ve added is bare minimum which just outputs default 19.2MHz clock on GPIO_13 exposed on LS connector. But this will give you an overall idea of how to configure various clock generators present in chipset for linux.

Link to the patched kernel: https://github.com/Mani-Sadhasivam/linux-qcom
Branch: gpclk-pwm
Commit: 629056dc11a3cbf0eb58be01e0d5c46fc93f3416

Note: The branch has been rebased to latest 17.06.1 debian release. So, after checking out gpclk-pwm branch, you can use the instructions mentioned in release notes[1] for compiling and deploying the kernel.

Thanks @ljking once gain for your help!

  1. http://builds.96boards.org/releases/dragonboard410c/linaro/debian/latest/

-Mani

So, is there a solution for generating a 100khz square pulse out of the dragonboard GPIO?