Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: spacemit-k1: Use PDR for pin direction, not SDR/CDR

On the SpacemiT GPIO controller, the direction control register PDR is
readable and writable [1]. Therefore, implement direction control by
using PDR as dirout, and don't mark it as unreadable.

The original implementation, using SDR as dirout and CDR as dirin, is
not actually a supported configuration by gpio-mmio. The hardware
supports changing the direction of some pins atomically by writing a
value with the corresponding bits set to SDR (set as output) or to CDR
(set as input). However, gpio-mmio does not actually handle this.

Using only PDR as dirout to match the expectations of gpio-mmio. This
also allows us to avoid clobbering potentially important GPIO direction
configurations set by pre-Linux boot stages.

Found while trying to add PCIe support to OrangePi RV2, where the
regulator (controlled by GPIO 116) turns off on boot while some other
GPIO pin in the same bank is touched, which is not desirable.

Link: https://developer.spacemit.com/documentation?token=Rn9Kw3iFHirAMgkIpTAcV2Arnkf#18.4-gpio # [1]
Fixes: d00553240ef8 ("gpio: spacemit: add support for K1 SoC")
Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Link: https://patch.msgid.link/20260127-gpio-spacemit-k1-pdr-v1-1-bb868a517dbc@iscas.ac.cn
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

authored by

Vivian Wang and committed by
Bartosz Golaszewski
aa7e37fd 4c4ff6e3

+3 -6
+3 -6
drivers/gpio/gpio-spacemit-k1.c
··· 199 199 struct gpio_chip *gc = &gb->chip.gc; 200 200 struct device *dev = sg->dev; 201 201 struct gpio_irq_chip *girq; 202 - void __iomem *dat, *set, *clr, *dirin, *dirout; 202 + void __iomem *dat, *set, *clr, *dirout; 203 203 int ret; 204 204 205 205 gb->base = regs + sg->data->bank_offsets[index]; ··· 208 208 dat = gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPLR]; 209 209 set = gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPSR]; 210 210 clr = gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPCR]; 211 - dirin = gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GCDR]; 212 - dirout = gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GSDR]; 211 + dirout = gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPDR]; 213 212 214 213 config = (struct gpio_generic_chip_config) { 215 214 .dev = dev, ··· 217 218 .set = set, 218 219 .clr = clr, 219 220 .dirout = dirout, 220 - .dirin = dirin, 221 - .flags = GPIO_GENERIC_UNREADABLE_REG_SET | 222 - GPIO_GENERIC_UNREADABLE_REG_DIR, 221 + .flags = GPIO_GENERIC_UNREADABLE_REG_SET, 223 222 }; 224 223 225 224 /* This registers 32 GPIO lines per bank */