Message ID | 20140827143431.GD32243@ulmo |
---|---|
State | Superseded |
Delegated to: | Tom Warren |
Headers | show |
On 27/08/14 17:34, Thierry Reding wrote: [...] >>> On my board, this call results in UART corruption, like this: >>> >>> tegra-pcie: non-prefetchable memory: 0x13000000-0x20000000 >>> tegra-pcie: prefetchable memory: 0x20000000-0x40000000 >>> ¥É½¥¹½bªÍ¥¹b2x1, 1x1 configuration >>> ¹Í5Rþtegra-pcie: probing port 1, using 1 lanes >>> >>> Likely because GPIO#2 controls the +3.3V_LP0 rail, which powers the UART >>> level shifters. Commenting the function call out fixes the corruption and >>> PCI-E still works fine. >> >> If I add a udelay(500) after the above I'm not able to reproduce the >> UART breakage anymore. But I guess making the AS3722 GPIO code smarter >> would be helpful. In the kernel this is done by checking the invert bit >> and then setting the value accordingly. I suppose the same could be done >> for the mode bits. I'll see if I can work up a patch. > > How about this: [...] Yes, that helps.
diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c index 59d1bf1b50b0..393dc8608d07 100644 --- a/drivers/power/as3722.c +++ b/drivers/power/as3722.c @@ -17,6 +17,7 @@ #define AS3722_GPIO_CONTROL(n) (0x08 + (n)) #define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0) #define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0) +#define AS3722_GPIO_CONTROL_MODE_MASK (7 << 0) #define AS3722_GPIO_CONTROL_INVERT (1 << 7) #define AS3722_LDO_VOLTAGE(n) (0x10 + (n)) #define AS3722_GPIO_SIGNAL_OUT 0x20 @@ -220,10 +221,21 @@ int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio, if (gpio > 7) return -EINVAL; + err = as3722_read(pmic, AS3722_GPIO_CONTROL(gpio), &value); + if (err < 0) { + error("failed to read GPIO#%u control register: %d", gpio, err); + return err; + } + + if (value & AS3722_GPIO_CONTROL_INVERT) + level = !level; + + value &= ~AS3722_GPIO_CONTROL_MODE_MASK; + if (level == 0) - value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; + value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; else - value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; + value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); if (err) {