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

gpio: mpc8xxx: Do not reverse bits using bgpio

The MPC8xxx driver is always instantiating its generic GPIO functions
with the flag BGPIOF_BIG_ENDIAN. This means "big-endian bit order"
and means the bits representing the GPIO lines in the registers are
reversed around 31 bits so line 0 is at bit 31 and so forth down to
line 31 in bit 0.

Instead of looping into the generic MMIO gpio to do the simple
calculation of a bitmask, through a vtable call with two parameters
likely using stack frames etc (unless the compiler optimize it)
and obscuring the view for the programmer, let's just open-code
what the call does. This likely executes faster, saves space and
makes the code easier to read.

Cc: Liu Gang <Gang.Liu@nxp.com>
Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

+17 -6
+17 -6
drivers/gpio/gpio-mpc8xxx.c
··· 21 21 #include <linux/slab.h> 22 22 #include <linux/irq.h> 23 23 #include <linux/gpio/driver.h> 24 + #include <linux/bitops.h> 24 25 25 26 #define MPC8XXX_GPIO_PINS 32 26 27 ··· 45 44 unsigned int irqn; 46 45 }; 47 46 47 + /* 48 + * This hardware has a big endian bit assignment such that GPIO line 0 is 49 + * connected to bit 31, line 1 to bit 30 ... line 31 to bit 0. 50 + * This inline helper give the right bitmask for a certain line. 51 + */ 52 + static inline u32 mpc_pin2mask(unsigned int offset) 53 + { 54 + return BIT(31 - offset); 55 + } 56 + 48 57 /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs 49 58 * defined as output cannot be determined by reading GPDAT register, 50 59 * so we use shadow data register instead. The status of input pins ··· 70 59 val = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask; 71 60 out_shadow = gc->bgpio_data & out_mask; 72 61 73 - return !!((val | out_shadow) & gc->pin2mask(gc, gpio)); 62 + return !!((val | out_shadow) & mpc_pin2mask(gpio)); 74 63 } 75 64 76 65 static int mpc5121_gpio_dir_out(struct gpio_chip *gc, ··· 131 120 132 121 gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 133 122 gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR) 134 - | gc->pin2mask(gc, irqd_to_hwirq(d))); 123 + | mpc_pin2mask(irqd_to_hwirq(d))); 135 124 136 125 raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); 137 126 } ··· 146 135 147 136 gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 148 137 gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR) 149 - & ~(gc->pin2mask(gc, irqd_to_hwirq(d)))); 138 + & ~mpc_pin2mask(irqd_to_hwirq(d))); 150 139 151 140 raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); 152 141 } ··· 157 146 struct gpio_chip *gc = &mpc8xxx_gc->gc; 158 147 159 148 gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 160 - gc->pin2mask(gc, irqd_to_hwirq(d))); 149 + mpc_pin2mask(irqd_to_hwirq(d))); 161 150 } 162 151 163 152 static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) ··· 171 160 raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); 172 161 gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR, 173 162 gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR) 174 - | gc->pin2mask(gc, irqd_to_hwirq(d))); 163 + | mpc_pin2mask(irqd_to_hwirq(d))); 175 164 raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); 176 165 break; 177 166 ··· 179 168 raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); 180 169 gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR, 181 170 gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR) 182 - & ~(gc->pin2mask(gc, irqd_to_hwirq(d)))); 171 + & ~mpc_pin2mask(irqd_to_hwirq(d))); 183 172 raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); 184 173 break; 185 174