Commit 24efd94b authored by Linus Walleij's avatar Linus Walleij
Browse files

gpio: mmio: Make pin2mask() a private business



The vtable call pin2mask() was introducing a vtable function call
in every gpiochip callback for a generic MMIO GPIO chip. This was
not exactly efficient. (Maybe link-time optimization could get rid of
it, I don't know.)

After removing all external calls into this API we can make it a
boolean flag in the struct gpio_chip call and sink the function into
the gpio-mmio driver yielding encapsulation and potential speedups.

Cc: Anton Vorontsov <anton@enomsg.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent b3222f71
...@@ -126,20 +126,16 @@ static unsigned long bgpio_read32be(void __iomem *reg) ...@@ -126,20 +126,16 @@ static unsigned long bgpio_read32be(void __iomem *reg)
return ioread32be(reg); return ioread32be(reg);
} }
static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin) static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line)
{ {
return BIT(pin); if (gc->be_bits)
} return BIT(gc->bgpio_bits - 1 - line);
return BIT(line);
static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc,
unsigned int pin)
{
return BIT(gc->bgpio_bits - 1 - pin);
} }
static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
{ {
unsigned long pinmask = gc->pin2mask(gc, gpio); unsigned long pinmask = bgpio_line2mask(gc, gpio);
if (gc->bgpio_dir & pinmask) if (gc->bgpio_dir & pinmask)
return !!(gc->read_reg(gc->reg_set) & pinmask); return !!(gc->read_reg(gc->reg_set) & pinmask);
...@@ -149,7 +145,7 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) ...@@ -149,7 +145,7 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
{ {
return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio)); return !!(gc->read_reg(gc->reg_dat) & bgpio_line2mask(gc, gpio));
} }
static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
...@@ -158,7 +154,7 @@ static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -158,7 +154,7 @@ static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{ {
unsigned long mask = gc->pin2mask(gc, gpio); unsigned long mask = bgpio_line2mask(gc, gpio);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
...@@ -176,7 +172,7 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -176,7 +172,7 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
int val) int val)
{ {
unsigned long mask = gc->pin2mask(gc, gpio); unsigned long mask = bgpio_line2mask(gc, gpio);
if (val) if (val)
gc->write_reg(gc->reg_set, mask); gc->write_reg(gc->reg_set, mask);
...@@ -186,7 +182,7 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, ...@@ -186,7 +182,7 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
{ {
unsigned long mask = gc->pin2mask(gc, gpio); unsigned long mask = bgpio_line2mask(gc, gpio);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
...@@ -216,9 +212,9 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc, ...@@ -216,9 +212,9 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc,
break; break;
if (__test_and_clear_bit(i, mask)) { if (__test_and_clear_bit(i, mask)) {
if (test_bit(i, bits)) if (test_bit(i, bits))
*set_mask |= gc->pin2mask(gc, i); *set_mask |= bgpio_line2mask(gc, i);
else else
*clear_mask |= gc->pin2mask(gc, i); *clear_mask |= bgpio_line2mask(gc, i);
} }
} }
} }
...@@ -294,7 +290,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -294,7 +290,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
...@@ -305,7 +301,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -305,7 +301,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
{ {
/* Return 0 if output, 1 of input */ /* Return 0 if output, 1 of input */
return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio));
} }
static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
...@@ -316,7 +312,7 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -316,7 +312,7 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir |= gc->pin2mask(gc, gpio); gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
...@@ -330,7 +326,7 @@ static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) ...@@ -330,7 +326,7 @@ static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir |= gc->pin2mask(gc, gpio); gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
...@@ -346,7 +342,7 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -346,7 +342,7 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
...@@ -357,12 +353,11 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -357,12 +353,11 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio)
{ {
/* Return 0 if output, 1 if input */ /* Return 0 if output, 1 if input */
return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio));
} }
static int bgpio_setup_accessors(struct device *dev, static int bgpio_setup_accessors(struct device *dev,
struct gpio_chip *gc, struct gpio_chip *gc,
bool bit_be,
bool byte_be) bool byte_be)
{ {
...@@ -406,8 +401,6 @@ static int bgpio_setup_accessors(struct device *dev, ...@@ -406,8 +401,6 @@ static int bgpio_setup_accessors(struct device *dev,
return -EINVAL; return -EINVAL;
} }
gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask;
return 0; return 0;
} }
...@@ -531,8 +524,8 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, ...@@ -531,8 +524,8 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
if (ret) if (ret)
return ret; return ret;
ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN, gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN);
flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret) if (ret)
return ret; return ret;
......
...@@ -67,9 +67,9 @@ struct module; ...@@ -67,9 +67,9 @@ struct module;
* registers. * registers.
* @read_reg: reader function for generic GPIO * @read_reg: reader function for generic GPIO
* @write_reg: writer function for generic GPIO * @write_reg: writer function for generic GPIO
* @pin2mask: some generic GPIO controllers work with the big-endian bits * @be_bits: if the generic GPIO has big endian bit order (bit 31 is representing
* notation, e.g. in a 8-bits register, GPIO7 is the least significant * line 0, bit 30 is line 1 ... bit 0 is line 31) this is set to true by the
* bit. This callback assigns the right bit mask. * generic GPIO core. It is for internal housekeeping only.
* @reg_dat: data (in) register for generic GPIO * @reg_dat: data (in) register for generic GPIO
* @reg_set: output set register (out=high) for generic GPIO * @reg_set: output set register (out=high) for generic GPIO
* @reg_clr: output clear register (out=low) for generic GPIO * @reg_clr: output clear register (out=low) for generic GPIO
...@@ -151,7 +151,7 @@ struct gpio_chip { ...@@ -151,7 +151,7 @@ struct gpio_chip {
#if IS_ENABLED(CONFIG_GPIO_GENERIC) #if IS_ENABLED(CONFIG_GPIO_GENERIC)
unsigned long (*read_reg)(void __iomem *reg); unsigned long (*read_reg)(void __iomem *reg);
void (*write_reg)(void __iomem *reg, unsigned long data); void (*write_reg)(void __iomem *reg, unsigned long data);
unsigned long (*pin2mask)(struct gpio_chip *gc, unsigned int pin); bool be_bits;
void __iomem *reg_dat; void __iomem *reg_dat;
void __iomem *reg_set; void __iomem *reg_set;
void __iomem *reg_clr; void __iomem *reg_clr;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment