pinctrl: mxs: atomically switch mux and drive strength config
commit53f806e46b32db0468bd4fdf132a8d1c3cd0e011
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Thu, 18 May 2017 09:23:55 +0000 (18 11:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Jul 2017 14:53:57 +0000 (12 16:53 +0200)
treef7649d5fac28cc2c9cbb4ea1db080e717220847c
parent9c89b4cc991e4988e83b09c917bf025b3e51916d
pinctrl: mxs: atomically switch mux and drive strength config

commit da6c2addf66d7ff7d0b090d6267d4292f951e4e6 upstream.

To set the mux mode of a pin two bits must be set. Up to now this is
implemented using the following idiom:

writel(mask, reg + CLR);
writel(value, reg + SET);

. This however results in the mux mode being 0 between the two writes.

On my machine there is an IC's reset pin connected to LCD_D20. The
bootloader configures this pin as GPIO output-high (i.e. not holding the
IC in reset). When Linux reconfigures the pin to GPIO the short time
LCD_D20 is muxed as LCD_D20 instead of GPIO_1_20 is enough to confuse
the connected IC.

The same problem is present for the pin's drive strength setting which is
reset to low drive strength before using the right value.

So instead of relying on the hardware to modify the register setting
using two writes implement the bit toggling using read-modify-write.

Fixes: 17723111e64f ("pinctrl: add pinctrl-mxs support")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Shawn Guo <shawnguo@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pinctrl/freescale/pinctrl-mxs.c