mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
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>
This commit is contained in:
parent
d74423687f
commit
b3222f7147
@ -21,6 +21,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/gpio/driver.h>
|
#include <linux/gpio/driver.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
#define MPC8XXX_GPIO_PINS 32
|
#define MPC8XXX_GPIO_PINS 32
|
||||||
|
|
||||||
@ -44,6 +45,16 @@ struct mpc8xxx_gpio_chip {
|
|||||||
unsigned int irqn;
|
unsigned int irqn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This hardware has a big endian bit assignment such that GPIO line 0 is
|
||||||
|
* connected to bit 31, line 1 to bit 30 ... line 31 to bit 0.
|
||||||
|
* This inline helper give the right bitmask for a certain line.
|
||||||
|
*/
|
||||||
|
static inline u32 mpc_pin2mask(unsigned int offset)
|
||||||
|
{
|
||||||
|
return BIT(31 - offset);
|
||||||
|
}
|
||||||
|
|
||||||
/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
|
/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
|
||||||
* defined as output cannot be determined by reading GPDAT register,
|
* defined as output cannot be determined by reading GPDAT register,
|
||||||
* so we use shadow data register instead. The status of input pins
|
* so we use shadow data register instead. The status of input pins
|
||||||
@ -59,7 +70,7 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
|||||||
val = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask;
|
val = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask;
|
||||||
out_shadow = gc->bgpio_data & out_mask;
|
out_shadow = gc->bgpio_data & out_mask;
|
||||||
|
|
||||||
return !!((val | out_shadow) & gc->pin2mask(gc, gpio));
|
return !!((val | out_shadow) & mpc_pin2mask(gpio));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mpc5121_gpio_dir_out(struct gpio_chip *gc,
|
static int mpc5121_gpio_dir_out(struct gpio_chip *gc,
|
||||||
@ -120,7 +131,7 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
|
|||||||
|
|
||||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
|
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
|
||||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
|
gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
|
||||||
| gc->pin2mask(gc, irqd_to_hwirq(d)));
|
| mpc_pin2mask(irqd_to_hwirq(d)));
|
||||||
|
|
||||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||||
}
|
}
|
||||||
@ -135,7 +146,7 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
|
|||||||
|
|
||||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
|
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
|
||||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
|
gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
|
||||||
& ~(gc->pin2mask(gc, irqd_to_hwirq(d))));
|
& ~mpc_pin2mask(irqd_to_hwirq(d)));
|
||||||
|
|
||||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||||
}
|
}
|
||||||
@ -146,7 +157,7 @@ static void mpc8xxx_irq_ack(struct irq_data *d)
|
|||||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||||
|
|
||||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER,
|
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER,
|
||||||
gc->pin2mask(gc, irqd_to_hwirq(d)));
|
mpc_pin2mask(irqd_to_hwirq(d)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||||
@ -160,7 +171,7 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
|||||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
||||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
||||||
| gc->pin2mask(gc, irqd_to_hwirq(d)));
|
| mpc_pin2mask(irqd_to_hwirq(d)));
|
||||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -168,7 +179,7 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
|||||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
||||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
||||||
& ~(gc->pin2mask(gc, irqd_to_hwirq(d))));
|
& ~mpc_pin2mask(irqd_to_hwirq(d)));
|
||||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user