描述:
在调试gpio_keys驱动时,出现了 can't find function irq on pin 17的问题。
问题查找
打印信息
[ 5.140936] can't find function irq on pin 17
[ 5.145711] can't find function irq on pin 17
[ 5.150664] gpio-keys gpiokey.16: Unable to get irq number for GPIO 17, error -22
[ 5.158901] gpio-keys: probe of gpiokey.16 failed with error -22
kernel/drivers/input/keyboard/gpio_keys.c
包含了 #include <linux/gpio.h>
irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
dev_err(dev,
"Unable to get irq number for GPIO %d, error %d\n",
button->gpio, error);
goto fail;
}
bdata->irq = irq;
通过打印的信息可以知道 在使用gpio_to_irq()函数读取中断失败。下面查找该函数的具体实现
kernel/include/linux/gpio.h
static inline int gpio_to_irq(unsigned int gpio)
{
return __gpio_to_irq(gpio);
}
kernel/drivers/gpio/gpiolib.c
int __gpio_to_irq(unsigned gpio)
{
return gpiod_to_irq(gpio_to_desc(gpio));
}
static int gpiod_to_irq(const struct gpio_desc *desc)
{
struct gpio_chip *chip;
int offset;
if (!desc)
return -EINVAL;
chip = desc->chip;
offset = gpio_chip_hwgpio(desc);
//需要执行chip->to_irq()函数
return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
}
接下来寻找chip->to_irq
kernel/drivers/pinctrl/sunxi/pinctrl-sunxi.c
int sunxi_pinctrl_init(struct platform_device *pdev,
const struct sunxi_pinctrl_desc *desc)
{
....
....
pctl->chip->to_irq = sunxi_pinctrl_gpio_to_irq,
....
}
static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
struct sunxi_desc_function *desc;
unsigned pinnum = pctl->desc->pin_base + offset;
unsigned irqnum;
if (offset >= chip->ngpio)
return -ENXIO;
desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pinnum, "irq");
if (!desc)
return -EINVAL;
irqnum = desc->irqbank * IRQ_PER_BANK + desc->irqnum;
dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
chip->label, offset + chip->base, irqnum);
return irq_find_mapping(pctl->domain, irqnum);
}
static struct sunxi_desc_function *
sunxi_pinctrl_desc_find_function_by_pin(struct sunxi_pinctrl *pctl,
const u16 pin_num,
const char *func_name)
{
.................
省略
.................
pr_warn("can't find function %s on pin %d\n", func_name, pin_num);
return NULL;
}
最终在 kernel/drivers/pinctrl/sunxi/pinctrl-sun8iw11p1.c 中的 static const struct sunxi_desc_pin sun8iw11p1_pins[] 定义中发现,A-H 不支持外部中断,H-I支持
static const struct sunxi_desc_pin sun8iw11p1_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD3 */
SUNXI_FUNCTION(0x3, "spi1"), /* CS0 */
SUNXI_FUNCTION(0x4, "uart2"), /* RTS */
SUNXI_FUNCTION(0x5, "gmac0"), /* GRXD3 */
SUNXI_FUNCTION(0x7, "io_disabled")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "emac0"), /* ERXD2 */
SUNXI_FUNCTION(0x3, "spi1"), /* CLK */
SUNXI_FUNCTION(0x4, "uart2"), /* CTS */
SUNXI_FUNCTION(0x5, "gmac0"), /* GRXD2 */
SUNXI_FUNCTION(0x7, "io_disabled")),
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
.....
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd1"), /* D0 */
SUNXI_FUNCTION(0x3, "io_disabled"),
SUNXI_FUNCTION(0x4, "uart3"), /* TX */
SUNXI_FUNCTION(0x7, "csi1"), /* D0 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd1"), /* D1 */
SUNXI_FUNCTION(0x3, "io_disabled"),
SUNXI_FUNCTION(0x4, "uart3"), /* RX */
SUNXI_FUNCTION(0x7, "csi1"), /* D1 */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
......
问题原因
gpio_keys驱动IO需要支持外部中断,A40I 支持外部中断的IO,在软件配置上只有H-I 32个引脚支持。从规格书得知也只有这些IO支持外部中断。
解决办法
只能使用支持外部中断的IO了 H0-H21 、I10-I19