0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

全志T507 PF4引脚无法被正常设置为中断模式的问题分析

冬至子 来源:丨budboool 作者:丨budboool 2023-11-24 17:42 次阅读

相关信息

硬件平台:全志T507
系统版本:Android 10 / Linux 4.9.170
问题描述:PF4 无法通过标准接口设置为中断模式,而 PF1、PF2、PF3、PF5 正常可用。

分析过程

一开始以为是引脚被其它驱动占用引起,或者该引脚不具备中断功能,经过排查,已排除这两种可能,因此通过从源码分析来找问题的根因。

以下是以 gpio_keys.c 驱动为入口进行分析:

// drivers/input/keyboard/gpio_keys.c
static int gpio_keys_setup_key(struct platform_device *pdev,
                struct input_dev *input,
                struct gpio_button_data *bdata,
                const struct gpio_keys_button *button)
{
    ......
    error = devm_request_any_context_irq(&pdev- >dev, bdata- >irq,
                         isr, irqflags, desc, bdata);
}

// kernel/irq/devres.c
int devm_request_any_context_irq(struct device *dev, unsigned int irq,
                  irq_handler_t handler, unsigned long irqflags,
                  const char *devname, void *dev_id)
{
    ......
    rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
    if (rc < 0) {
        devres_free(dr);
        return rc;
    }
    ......
    return rc;
}

// kernel/irq/manage.c
int request_any_context_irq(unsigned int irq, irq_handler_t handler,
                unsigned long flags, const char *name, void *dev_id)
{
    ......
    ret = request_irq(irq, handler, flags, name, dev_id);
    return !ret ? IRQC_IS_HARDIRQ : ret;
}

// include/linux/interrupt.h
static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
        const char *name, void *dev)
{
    return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

// kernel/irq/manage.c
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
             irq_handler_t thread_fn, unsigned long irqflags,
             const char *devname, void *dev_id)
{
    ......
    chip_bus_lock(desc);
    retval = __setup_irq(irq, desc, action);
    chip_bus_sync_unlock(desc);
    ......
    return retval;
}

// kernel/irq/manage.c
static int __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
    ......

    if (!shared) {
        ret = irq_request_resources(desc);
        if (ret) {
            pr_err("Failed to request resources for %s (irq %d) on irqchip %sn",
                   new- >name, irq, desc- >irq_data.chip- >name);
            goto out_mask;
        }
        ......
    } 
    ......
}

// kernel/irq/manage.c
static int irq_request_resources(struct irq_desc *desc)
{
    struct irq_data *d = &desc- >irq_data;
    struct irq_chip *c = d- >chip;

    return c- >irq_request_resources ? c- >irq_request_resources(d) : 0;
}

// drivers/pinctrl/sunxi/pinctrl-sunxi.c
static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
    .name        = "sunxi_pio_edge",
    .irq_ack    = sunxi_pinctrl_irq_ack,
    .irq_mask    = sunxi_pinctrl_irq_mask,
    .irq_unmask    = sunxi_pinctrl_irq_unmask,
    .irq_request_resources = sunxi_pinctrl_irq_request_resources,
    .irq_release_resources = sunxi_pinctrl_irq_release_resources,
    .irq_set_type    = sunxi_pinctrl_irq_set_type,
    .irq_set_wake    = sunxi_pinctrl_irq_set_wake,
};

// drivers/pinctrl/sunxi/pinctrl-sunxi.c
static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
{
    struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
    struct sunxi_desc_function *func;

    func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
                    pctl- >irq_array[d- >hwirq], "irq");
    if (!func)
        return -EINVAL;

    /* Change muxing to INT mode */
    printk(KERN_EMERG"[lmx] irq:%d set int mode pin:%d d- >hwirq:%ld func- >muxval:%dn", d- >irq, pctl- >irq_array[d- >hwirq], d- >hwirq, func- >muxval);
    sunxi_pmx_set(pctl- >pctl_dev, pctl- >irq_array[d- >hwirq], func- >muxval);

    return 0;
}

// drivers/pinctrl/sunxi/pinctrl-sunxi.c
static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
                 unsigned pin,
                 u8 config)
{
    struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
    unsigned long flags;
    u32 val, mask;

    raw_spin_lock_irqsave(&pctl- >lock, flags);
    pin -= pctl- >desc- >pin_base;
    val = readl(pctl- >membase + sunxi_mux_reg(pin));
    mask = MUX_PINS_MASK < < sunxi_mux_offset(pin);
    writel((val & ~mask) | config < < sunxi_mux_offset(pin),
        pctl- >membase + sunxi_mux_reg(pin));
    raw_spin_unlock_irqrestore(&pctl- >lock, flags);
}

无论有多复杂的代码,最终都需要通过读写寄存器的方式来实现控制芯片,而通过上述代码分析,即可发现 sunxi_pmx_set() 接口用于配置寄存器,是最底层的接口,可以通过打印输出传入的参数,来检查是否有问题。

PF3 打印输出为:

[   10.683205] [lmx] irq:148 set int mode pin:163 d- >hwirq:131 func- >muxval:6

PF4 打印输出为:

[   10.683557] [lmx] irq:149 set int mode pin:196 d- >hwirq:132 func- >muxval:6

这里就能看出很奇怪的地方,PF3 的引脚编号是 163,而 PF4 却是 196,跨度很大。

通过以下指令查询 PF4 的正确引脚编号,也可以得知 196 引脚编号是哪一组:

mercury-demo:/ # cat /sys/kernel/debug/pinctrl/pio/pins
registered pins: 137
......
pin 160 (PF0)
pin 161 (PF1)
pin 162 (PF2)
pin 163 (PF3)
pin 164 (PF4)
pin 165 (PF5)
pin 166 (PF6)
......
pin 196 (PG4)
pin 197 (PG5)
......

确认 PF4 正确引脚编号是 164,而 196 对应是 PG4,实际生效的是 PG4,通过以下指令即可确认:

mercury-demo:/sys/kernel/debug/sunxi_pinctrl # echo PG4 > sunxi_pin
mercury-demo:/sys/kernel/debug/sunxi_pinctrl # cat *
pin[PG4] data: 1
pio
pin[PG4] dlevel: 1
pin[PG4] funciton: 6
NOMATCH
pin[PG4] pull: 1
PG4
pin[PG4] funciton: 6
pin[PG4] data: 1
pin[PG4] dlevel: 1
pin[PG4] pull: 1

根据代码确定引脚编号来源于 pctl->irq_array 数组,通过 pctl->irq_array 赋值的地方进行打印输出,是否一开始就出错了:

// drivers/pinctrl/sunxi/pinctrl-sunxi.c
static int sunxi_pinctrl_build_state(struct platform_device *pdev)
{
    ......
    /* Count functions associated groups */
    for (i = 0; i  pctl- >desc- >npins; i++) {
        const struct sunxi_desc_pin *pin = pctl- >desc- >pins + i;
        struct sunxi_desc_function *func = pin- >functions;
        while (func- >name) {
            /* Create interrupt mapping while we're at it */
            if (!strcmp(func- >name, "irq")) {
                int irqnum = func- >irqnum + func- >irqbank * IRQ_PER_BANK;
                pctl- >irq_array[irqnum] = pin- >pin.number;
                printk(KERN_EMERG"[lmx] pctl- >irq_array[%d] = %d   (func- >irqnum:%d func- >irqbank:%d)n", irqnum, pin- >pin.number, func- >irqnum, func- >irqbank);
            }
            sunxi_pinctrl_add_function(pctl, func- >name);
            func++;
        }
    }
    ......
    return 0;
}
// drivers/pinctrl/sunxi/pinctrl-sunxi.h
#define IRQ_PER_BANK        32

1.png

可以发现,PF4(164)对应的索引是 132,原本被正确赋值为 164,但又被覆盖为 PG4(196)。
不难发现,出现覆盖的原因是因为 PG4 的 func->irqbank 数值错误(4),导致索引下标计算错误。

根据前后文来看,func->irqbank 的正确数值应该是 5,代入计算得到正确的值 164:
int irqnum(164) = func->irqnum(4) + func->irqbank(5) * IRQ_PER_BANK(32);

大概率硬件资源描述配置出错,通过搜索 irqbank 被赋值的方法,来定位描述配置出错的地方:

// drivers/pinctrl/sunxi/pinctrl-sunxi.h
#define SUNXI_FUNCTION_IRQ_BANK(_val, _bank, _irq)        
    {                            
        .name = "irq",                    
        .muxval = _val,                    
        .irqbank = _bank,                
        .irqnum = _irq,                    
    }

使用的是 SUNXI_FUNCTION_IRQ_BANK 宏,重点检查第二个参数:

//    drivers/pinctrl/sunxi/pinctrl-sun50iw9p1.c
static const struct sunxi_desc_pin sun50iw9p1_pins[] = {
    ......
    SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
        SUNXI_FUNCTION(0x0, "gpio_in"),
        SUNXI_FUNCTION(0x1, "gpio_out"),
        SUNXI_FUNCTION(0x2, "sdc1"),        /* D1 */
        SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 3),  /*  PG_EINT3    */
        SUNXI_FUNCTION(0x7, "io_disabled")),
    SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
        SUNXI_FUNCTION(0x0, "gpio_in"),
        SUNXI_FUNCTION(0x1, "gpio_out"),
        SUNXI_FUNCTION(0x2, "sdc1"),        /* D2 */
        // 可以发现第二个参数恰好是 4,根据分析结果,以及结合上下文,正确的应该是 5
        SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 4),  /*  PG_EINT4    */
        SUNXI_FUNCTION(0x7, "io_disabled")),
    SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
        SUNXI_FUNCTION(0x0, "gpio_in"),
        SUNXI_FUNCTION(0x1, "gpio_out"),
        SUNXI_FUNCTION(0x2, "sdc1"),        /* D3 */
        SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 5),  /*  PG_EINT5    */
        SUNXI_FUNCTION(0x7, "io_disabled")),
    ......
};

修改之后的 pctl->irq_array 打印输出正确:

2.png

进行实测,PF4 已经可以正常的被设置为中断模式。

问题总结

全志原厂提供的 SoCs pinctrl driver 中的 PG4 中断信息描述错误,导致覆盖了 PF4 的引脚编号,因此只要修正 PG4 的描述信息,即可解决问题。

这个问题不仅仅会影响 PF4 无法使用,也会影响 PG4 引脚无法使用,从代码来看,想要设置为 PG4 为中断模式,实际修改的会 PA0(0)。

--- a/longan/kernel/linux-4.9/drivers/pinctrl/sunxi/pinctrl-sun50iw9p1.c
+++ b/longan/kernel/linux-4.9/drivers/pinctrl/sunxi/pinctrl-sun50iw9p1.c
@@ -693,7 +693,7 @@
                SUNXI_FUNCTION(0x0, "gpio_in"),
                SUNXI_FUNCTION(0x1, "gpio_out"),
                SUNXI_FUNCTION(0x2, "sdc1"),            /* D2 */
-               SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 4),  /*  PG_EINT4       */
+               SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 4),  /*  PG_EINT4       */
                SUNXI_FUNCTION(0x7, "io_disabled")),
        SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
                SUNXI_FUNCTION(0x0, "gpio_in"),
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动器
    +关注

    关注

    52

    文章

    8226

    浏览量

    146253
  • 寄存器
    +关注

    关注

    31

    文章

    5336

    浏览量

    120230
  • Linux系统
    +关注

    关注

    4

    文章

    593

    浏览量

    27392
  • IRQ
    IRQ
    +关注

    关注

    0

    文章

    16

    浏览量

    10761
收藏 人收藏

    评论

    相关推荐

    T507-C核心板引脚功能修改指引

    飞凌T507-C核心板CPU四核Cortex-A53,1.5GHz主频;GPUG31 MP2;核心板集成2GB DDR3 RAM,8
    发表于 12-09 09:04

    T507操作小技巧连载1-T507屏幕切换的两种方式

    、Android、Ubuntu*操作系统,适用于车载电子、电力、医疗、工业控制、物联网、智能终端等领域。本文不再对硬件参数进行叙述,在参考本文进行软件开发前请阅读飞凌嵌入式提供的T507用户手册 ,路径
    发表于 01-14 11:26

    硬件调试笔记--T507电源防漏电设计

    TLV809ED29DBZR的2引脚会输出低电平导致Q1关闭,FDS4435因为4引脚电平高,所以FDS4435管子关闭不输出电压而达到断电的目的,如图下图所示:方法2:参考以下图,
    发表于 03-23 16:47

    分析笔记】 T507 PF4 引脚无法正常设置中断模式的问题分析

    相关信息 硬件平台:T507 系统版本:Android 10/ Linux 4.9.170 问题描述:PF4 无法通过标准接口
    发表于 11-24 10:57

    T507开发板以太网配置方法

    本文硬件平台采用T507四核车规级处理器设计开发板,本文讲解T507开发板以太网配置方法。其它板卡设置略有不同,请参考使用。
    发表于 06-29 11:10 1002次阅读
    <b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>开发板以太网配置方法

    T507实现SPI转CAN 全过程的详细讲解

    T507处理器本身不支持CAN功能,那有什么方法可以实现CAN功能呢? 我们已知FETT507-C核心板是支持SPI接口的,但底板没有引出该接口,所以小编打算通过
    发表于 01-19 11:38 2041次阅读

    详解T507实现SPI转CAN功能

      ​T507处理器本身不支持CAN功能,那有什么方法可以实现CAN功能呢?
    发表于 02-10 14:53 1220次阅读
    详解<b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>实现SPI转CAN功能

    T507核心板常见问题解析

    本文硬件平台采用T507四核车规级处理器设计核心板,本文整理在使用飞凌嵌入式T507产品过程种,常常碰到的几个问题,其它板卡设置,请参考
    发表于 03-18 16:41 1036次阅读
    <b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>核心板常见问题解析

    T507处理器如何实现SPI转CAN功能

    T507处理器本身不支持CAN功能,那有什么方法可以实现CAN功能呢?
    的头像 发表于 04-15 10:06 2540次阅读

    T507平台,应用于运动控制行业

    快来戳,快来戳, 天嵌科技的T507平台 专为运动控制类行业打造的合适Arm 平台 T507 平台国产4核A53工业级平台,支持 Liu
    的头像 发表于 12-05 17:25 1171次阅读
    <b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>平台,应用于运动控制行业

    方案 | 基于T507核心板设计电子AI后视镜

    电子AI后视镜终端产品可借助飞凌FETT507-C核心板实现,该核心板基于T507四核车规级处理器设计开发,并且通过了汽车AEC-Q100测试,且FETT
    的头像 发表于 08-31 18:37 1138次阅读
    方案 | 基于<b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>核心板设计电子AI后视镜

    T3(A40I)/T5(T507)性能对比,一代更比一代强

    T3(A40I)/T5(T507)性能对比
    的头像 发表于 05-27 15:47 8347次阅读
    <b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T</b>3(A40I)/<b class='flag-5'>T</b>5(<b class='flag-5'>T507</b>)性能对比,一代更比一代强

    T507操作小技巧连载2-T507以太网配置方法

    本文硬件平台采用T507四核车规级处理器设计开发板,本文讲解T507开发板以太网配置方法。其它板卡设置略有不同,请参考使用。 一、
    的头像 发表于 08-31 19:19 2673次阅读
    <b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>操作小技巧连载2-<b class='flag-5'>T507</b>以太网配置方法

    T507|T507核心板价格|芯片参数配置|资料|原理图|性能|功耗-飞凌

    T5系列是一个高性能四核CortexTM – A53处理器,适用于新一代汽车市场。T507系列符合汽车AEC – Q100测试要求。T507
    的头像 发表于 11-10 17:02 2w次阅读
    <b class='flag-5'>T507</b>|<b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>核心板价格|芯片参数配置|资料|原理图|性能|功耗-飞凌

    T507-T507核心板常见问题解析-飞凌嵌入式T507核心板

    本文硬件平台采用T507四核车规级处理器设计核心板,本文整理在使用飞凌嵌入式T507产品过程种,常常碰到的几个问题,其它T507板卡
    的头像 发表于 10-28 17:54 1908次阅读
    <b class='flag-5'>T507</b>-<b class='flag-5'>全</b><b class='flag-5'>志</b><b class='flag-5'>T507</b>核心板常见问题解析-飞凌嵌入式<b class='flag-5'>T507</b>核心板