Re: mt7621: gpio-hog not working properly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Quoting Linus Walleij <linus.walleij@xxxxxxxxxx>:

On Wed, Nov 13, 2019 at 9:54 PM René van Dorst <opensource@xxxxxxxxxx> wrote:

mt7621 used bgpio_set_with_clear() because we have `set` and `clear`
registers.
(...)
It seems that writing to the 'clear' register doesn't do anything.
I noticed that register address is 0x1e000000 in the DTS but in the
code it is 0xbe000000.

Do you mean physical memory 0x1e000000 gets remapped
at virtual memory 0xbe000000?

Yes. mtk->base = be000600.

[    3.094301] mediatek_gpio_bank_probe: mtk->base = be000600
[    3.105165] gpiochip_find_base: found new base at 480
[ 3.115135] bgpio_set_with_clear: gc-base-480 gpio:7 val:0x0 mask:0x80 data-reg-val:0xbe000640 [ 3.132196] bgpio_set_with_clear: before: g7 reg:0xbe000640: data:0xb75f7da, masked data:0x80
[    3.149297] bgpio_write32: 0xbe000640 <= 0x80
[ 3.157935] bgpio_set_with_clear: after: g7 reg:0xbe000640: data:0xb75f7da, masked data:0x80
[    3.175040] bgpio_write32: 0xbe000600 <= 0x80
[    3.183682] GPIO line 487 (sfp_i2c_clk_gate) hogged as output/high
[    3.195955] gpiochip_add_data_with_key: gpiochip0 gpio7: 0x843
[ 3.207692] gpio gpiochip0: (1e000600.gpio-bank0): added GPIO chardev (254:0)



[    3.158002] bgpio_write32: 0xbe000600 <= 0x80
[    3.165258] GPIO line 487 (sfp_i2c_clk_gate) hogged as output/high
[    3.177532] gpiochip_add_data_with_key: gpiochip0 gpio7: 0x843

When using program 'io' writing to the `clear` register 0x1e000640
does have effect.

root@OpenWrt:/# io -4 0x1e000620
1e000620:  0b75f7de
root@OpenWrt:/# io -4 -w 0x1e000640 0x80
root@OpenWrt:/# io -4 0x1e000620
1e000620:  0b75f74e
(...)
If I change the bgpio_init() values so that we don't have the `set`
and `clear` registers.
With the patch below I do get right results.

That's weird!

So this means that changing data register thru the 'set'/'clear'
registers is not working but writing direct to the data register does.

So the question is: why is writel() in bgpio_write32() not working on
the 'set'/'clear' registers.


Any idea what this can be?

Try to pass the flag BGPIOF_UNREADABLE_REG_SET,
it seems the code is using the set register to read back the
value. In this case it is actually working you just don't see
it in debugfs.

debugfs is showing the actual results.
Also I know when it is working. The kernel prints the SFP module info to the dmesg.


read the gpio status:

root@OpenWrt:/# cat /sys/kernel/debug/gpio
gpiochip3: GPIOs 400-415, parent: i2c/0-0025, 0-0025, can sleep:
 gpio-405 (                    |mod-def0            ) in  lo ACTIVE LOW

gpiochip2: GPIOs 416-447, parent: platform/1e000600.gpio, 1e000600.gpio-bank2:

gpiochip1: GPIOs 448-479, parent: platform/1e000600.gpio, 1e000600.gpio-bank1:

gpiochip0: GPIOs 480-511, parent: platform/1e000600.gpio, 1e000600.gpio-bank0:
 gpio-487 (                    |sfp_i2c_clk_gate    ) out hi ACTIVE LOW
 gpio-492 (                    |reset               ) in  hi IRQ ACTIVE LOW
 gpio-496 (                    |sysfs               ) out hi
 gpio-497 (                    |sysfs               ) out lo
 gpio-498 (                    |sysfs               ) out hi
 gpio-499 (                    |sysfs               ) out lo
 gpio-500 (                    |sysfs               ) out hi
root@OpenWrt:/# io -4 0x1e000620
1e000620:  0355f7de

Clear gpio7 via 'clear' register:

root@OpenWrt:/# io -4 -w 0x1e000640 0x80

read the gpio status again:

root@OpenWrt:/# cat /sys/kernel/debug/gpio
gpiochip3: GPIOs 400-415, parent: i2c/0-0025, 0-0025, can sleep:
 gpio-405 (                    |mod-def0            ) in  lo ACTIVE LOW

gpiochip2: GPIOs 416-447, parent: platform/1e000600.gpio, 1e000600.gpio-bank2:

gpiochip1: GPIOs 448-479, parent: platform/1e000600.gpio, 1e000600.gpio-bank1:

gpiochip0: GPIOs 480-511, parent: platform/1e000600.gpio, 1e000600.gpio-bank0:
 gpio-487 (                    |sfp_i2c_clk_gate    ) out lo ACTIVE LOW
 gpio-492 (                    |reset               ) in  hi IRQ ACTIVE LOW
 gpio-496 (                    |sysfs               ) out hi
 gpio-497 (                    |sysfs               ) out lo
 gpio-498 (                    |sysfs               ) out hi
 gpio-499 (                    |sysfs               ) out lo
 gpio-500 (                    |sysfs               ) out hi
root@OpenWrt:/# io -4 0x1e000620
1e000620:  0b75f74e

Values shown by debugfs are correct.

Below the diff of my debug code and assembly of the bgpio_write32();

Greats,

René


Cc:ed Sergio maybe he has some ideas.

It seems to be hardware related then, hm.

Yours,
Linus Walleij

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index cd07c948649f..18d1b6937092 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -82,6 +82,7 @@ static unsigned long bgpio_read16(void __iomem *reg)

 static void bgpio_write32(void __iomem *reg, unsigned long data)
 {
+       pr_info("%s: 0x%px <= 0x%lx\n", __func__, reg, data);
        writel(data, reg);
 }

@@ -150,6 +151,8 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask,
        unsigned long get_mask = 0;
        unsigned long set_mask = 0;

+ pr_info("%s: gpio-%d b0x%lx m0x%lx", __func__, gc->base, *bits, *mask);
+
/* Make sure we first clear any bits that are zero when we read the register */
        *bits &= ~*mask;

@@ -222,6 +225,8 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
        unsigned long mask = bgpio_line2mask(gc, gpio);
        unsigned long flags;

+       pr_info("%s: gpio:%d val:0x%x mask:0x%lx", __func__, gpio, val, mask);
+
        spin_lock_irqsave(&gc->bgpio_lock, flags);

        if (val)
@@ -239,10 +244,22 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
 {
        unsigned long mask = bgpio_line2mask(gc, gpio);

+ pr_info("%s: gc-base-%d gpio:%d val:0x%x mask:0x%lx data-reg-val:0x%px\n", __func__, gc->base,
+               gpio, val, mask, val ? gc->reg_set : gc->reg_clr);
+
+ pr_info("%s: before: g%d reg:0x%px: data:0x%lx, masked data:0x%lx \n", __func__,
+               gpio, val ? gc->reg_set : gc->reg_clr,
+               gc->read_reg(gc->reg_dat), gc->read_reg(gc->reg_dat) & mask);
+
        if (val)
                gc->write_reg(gc->reg_set, mask);
        else
                gc->write_reg(gc->reg_clr, mask);
+
+ pr_info("%s: after: g%d reg:0x%px: data:0x%lx, masked data:0x%lx \n", __func__,
+               gpio, val ? gc->reg_set : gc->reg_clr,
+               gc->read_reg(gc->reg_dat), gc->read_reg(gc->reg_dat) & mask);
+
 }

 static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
@@ -250,6 +267,8 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
        unsigned long mask = bgpio_line2mask(gc, gpio);
        unsigned long flags;

+       pr_info("%s: g%d v0x%x m0x%lx", __func__, gpio, val, mask);
+
        spin_lock_irqsave(&gc->bgpio_lock, flags);

        if (val)
@@ -322,6 +341,8 @@ static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
 {
+       pr_info("%s: g%d v0x%x m0x%lx", __func__, gpio, val, mask);
+
        spin_lock_irqsave(&gc->bgpio_lock, flags);

        if (val)
@@ -322,6 +341,8 @@ static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
 {
        unsigned long set_mask, clear_mask;

+       pr_info("%s: gpio-%d b%lx m%lx\n", __func__, gc->base, *bits, *mask);
+
        bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);

        if (set_mask)
diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c
index d1d785f983a7..cff3c79e3561 100644
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -222,13 +222,19 @@ mediatek_gpio_bank_probe(struct device *dev,
        rg->chip.of_node = node;
        rg->bank = bank;

+       pr_info("%s: mtk->base = %px\n", __func__, mtk->base);
+
        dat = mtk->base + GPIO_REG_DATA + (rg->bank * GPIO_BANK_STRIDE);
        set = mtk->base + GPIO_REG_DSET + (rg->bank * GPIO_BANK_STRIDE);
        ctrl = mtk->base + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_STRIDE);
        diro = mtk->base + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_STRIDE);

+       //ret = bgpio_init(&rg->chip, dev, 4,
+       //               dat, NULL, NULL, diro, NULL, 0);
+
        ret = bgpio_init(&rg->chip, dev, 4,
                         dat, set, ctrl, diro, NULL, 0);
+
        if (ret) {
                dev_err(dev, "bgpio_init() failed\n");
                return ret;
@@ -283,6 +289,8 @@ mediatek_gpio_bank_probe(struct device *dev,
                return ret;
        }

+ pr_info("%s: data: %px(0x%x), set: %px, clr: %px\n", __func__, dat, mtk_gpio_r32(rg, GPIO_REG_DATA) , set, ctrl);
+
        /* set polarity to low for all gpios */
        mtk_gpio_w32(rg, GPIO_REG_POL, 0);

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index dba5f08f308c..ca797fc1528e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1518,6 +1518,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
                        else
                                clear_bit(FLAG_IS_OUT, &desc->flags);
                }
+               if (i == 7)
+ pr_info("%s: gpiochip%d gpio7: 0x%lx\n", __func__, gdev->id, desc->flags);
        }

        acpi_gpiochip_add(chip);


bgpio_write32 decompiled.

Normal:

8037c5b0 <bgpio_write32>:
8037c5b0:	0000000f 	sync
8037c5b4:	ac850000 	sw	a1,0(a0)
8037c5b8:	03e00008 	jr	ra
8037c5bc:	00000000 	nop

With the debug pr_info()

8037cfa8 <bgpio_write32>:
8037cfa8:	27bdffe0 	addiu	sp,sp,-32
8037cfac:	afb10018 	sw	s1,24(sp)
8037cfb0:	00a08825 	move	s1,a1
8037cfb4:	afb00014 	sw	s0,20(sp)
8037cfb8:	3c058077 	lui	a1,0x8077
8037cfbc:	00808025 	move	s0,a0
8037cfc0:	afbf001c 	sw	ra,28(sp)
8037cfc4:	3c048077 	lui	a0,0x8077
8037cfc8:	24a5789c 	addiu	a1,a1,30876
8037cfcc:	24847864 	addiu	a0,a0,30820
8037cfd0:	02203825 	move	a3,s1
8037cfd4:	0c01d729 	jal	80075ca4 <printk>
8037cfd8:	02003025 	move	a2,s0
8037cfdc:	0000000f 	sync
8037cfe0:	ae110000 	sw	s1,0(s0)
8037cfe4:	8fbf001c 	lw	ra,28(sp)
8037cfe8:	8fb10018 	lw	s1,24(sp)
8037cfec:	8fb00014 	lw	s0,20(sp)
8037cff0:	03e00008 	jr	ra
8037cff4:	27bd0020 	addiu	sp,sp,32





[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux