Hello, all! I'm using imx6ull GPIO1_IO03 to drive a LED, and I have configd the pin in the device tree. It is ok to turn on and turn off LED, that means gpio_set_value() works well. But when I use gpio_get_value() to read the pin to toggle the LED, it always return 0.Then I try to set the bit 30 of the config register, what's in your word, SION bit as 1, unfortunately, it still does not work.
Below is the LED part configuration in the device tree
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
imx6ul-evk {
pinctrl_alpha_led0: alpha-led0 {
fsl,pins = <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x400010b0
>;
};
pinctrl_alpha_led1: alpha-led1 {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x400010b0
>;
};
/* some other nodes */
};
/* some other nodes */
};
/ {
/* some other nodes */
alpha-leds {
compatible = "alientek-alpha,leds";
led-0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_alpha_led0>;
gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>;
status = "okay";
};
led-1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_alpha_led1>;
gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
status = "okay";
};
};
/* some other nodes */
};
What's may be the problem of this , why gpio_get_value dose not return pin value correctly? How can I fix this?
Hello,
it is indeed the correct way to set the bit 30 for SION, so this configuration should not have a problem.
I believe you’re using a custom board and not an EVK, have you tried manually driving the GPIO and check if the status change?
Also, since you have only shared the portion of the dts where the GPIO is defined, have you looked if this pad has not been used by another peripheral?
Best regards,
Aldo.
Yes, I have checked the usage of the pins, they are not used anywhere else. And I can turn on and turn off the led by using gpio_set_value. After few days of debugging, I found that the mux register value and config register value I set in the device-tree were not written to the corresponding registers. I read out the mux register and found that it was just the value same as default, not what I set in the pinctrl node.
Maybe there was an important point I was missing,: I'm using the pure chrdev driver, not platrom driver model. I thought gpio subsystem would call pinctrl subsystem to set mux register, but it seemed not working the way as I thought. Below is my test code:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/ide.h>
#define REG_MUX_GPIO5_IO01 0x0229000C
static void __iomem *mux_gpio5_io01;
static int gpio;
static int __init led_init(void)
{
const char *status;
int ret, value;
struct device_node *node = NULL;
node = of_find_compatible_node(NULL, NULL, "alientek-alpha,leds");
if(!node) {
printk("error: of_find_compatible_node\n");
return -ENODEV;
}
ret = of_property_read_string(node, "status", &status);
if((ret != 0) || (strcmp(status, "okay") != 0)) {
printk("error: of_property_read_string\n");
return -ENODEV;
}
gpio = of_get_named_gpio(node, "gpio", 0);
if(gpio < 0) {
printk("error: of_get_named_gpio\n");
return -ENODEV;
}
ret = gpio_request(gpio, "led-pin");
if(ret) {
printk("error: gpio_request\n");
return -ENODEV;
}
ret = gpio_direction_output(gpio, 1);
if(ret) {
printk("error: gpio_direction_output\n");
goto error;
}
value = gpio_get_value(gpio);
printk("gpio value = %d\n", value);
mux_gpio5_io01 = ioremap(REG_MUX_GPIO5_IO01, 4);
if(mux_gpio5_io01) {
value = readl(mux_gpio5_io01);
printk("reg value = %08X\n", value);
}
return 0;
error:
gpio_free(gpio);
return -1;
}
static void __exit led_exit(void)
{
int value;
value = gpio_get_value(gpio);
printk("gpio value = %d\n", value);
if(mux_gpio5_io01) {
value = readl(mux_gpio5_io01);
printk("reg value = %08X\n", value);
}
gpio_free(gpio);
if(mux_gpio5_io01) iounmap(mux_gpio5_io01);
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("David");
MODULE_LICENSE("GPL");
Does platform driver do a bit more work than pure chardev driver ? eg, call pinctrl subsystem for us ?
Appreciate the help.
Hello,
I don't know BSP version you are working with but it may be helpful to check the latest documentation available here:
Also, you may check the GPIO function implementation:
https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/gpio/gpio-mxc.c?h=lf-5.15.y
Best regards,
Aldo.
Thanks, it turns out only with platform driver interface, the pinctrl configuration would work.
Okay, I figure out that's not gpio_get_value's problem. I print the mux register and find that the SION bit is not 1. It's still 0 even when I set config register to 0x400010b0. Wha's more , I try to directly modify the MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 macro definiton in imx6ul-pinfunc.h to add SION bit , change 0x5 to 0x15, still not work. The mux register still read out as 0x5, not 0x15. Only if I use iomap to set the mux register , SION can be set to 1 successfully. Why ? anybody knows?
By the way, I use the gpio_ legacy functions , instead of gpiod_ new functions. Does it matter ? It seems that configuration datas in the pinctrl node are not written to the registers. Any ideas ?