kernel4.x imx6 GPIOLIB_API 输出电平问题

很高兴之前分析gpioLib能有机会帮助解决问题。

描述下遇到的问题的现象:
将GPIO设置为output并设置为高电平,这时候再去读取电平却读到低电平,使用万用表测量管脚,确认是实实在在的高电平。用命令演示一下拗口的文字:
# echo out > /sys/class/gpio/gpio34/direciton
# echo 1 >   /sys/class/gpio/gpio34/value
# cat       /sys/class/gpio/gpio34/value
# 0 

因为已经确认实际管脚的上是能够正常工作的,初步判断出读功能那里出错,最后定位到gpio-generic.c下gpio_get.

static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
{
        struct bgpio_chip *bgc = to_bgpio_chip(gc);
        return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));
}

在之前的文章中我们分析过初始化的过程就不展开来说了,乍一看这个读寄存器并没有问题。
我们翻看芯片手册看看这个芯片描述:
PSR寄存器:
Each bit stores the value of the corresponding input signal
DR寄存器:
GPIO_DR register stores data that is ready to be driven to the output lines.
这里PSR寄存器只说了记录输出的信号,没有说输入的情况,而DR寄存器是配置输出电平。

所以实际上配置为输出时,我们只能回读DR寄存器,而不能读PSR,以前我用过3.x的内核并没有这个问题,所以参考一下对应的代码。

static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
{
        struct mxc_gpio_port *port =
                container_of(chip, struct mxc_gpio_port, chip);
        u32 gpio_direction;

        gpio_direction = __raw_readl(port->base + GPIO_GDIR);
        if (((gpio_direction >> offset) & 1)) /* output mode */
                return (__raw_readl(port->base + GPIO_DR) >> offset) & 1;
        else /* input mode */
                return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1;
}

很明显是判断了当前的输入输出 配置,然后分别读GPIO_DR/GPIO_PSR寄存器。

所以,我们将4.x代码修改一下:

static int bgpio_get_mxc(struct gpio_chip *gc, unsigned int gpio)
{
        struct bgpio_chip *bgc = to_bgpio_chip(gc);
        if( !!(bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ){
                        return  !!(bgc->read_reg(bgc->reg_set) & bgc->pin2mask(bgc, gpio));
        }else{
                        return  !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));
        }
}
#endif

你可能感兴趣的:(Linux内核)