Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754697Ab1ECTlZ (ORCPT ); Tue, 3 May 2011 15:41:25 -0400 Received: from mail-pw0-f46.google.com ([209.85.160.46]:46180 "EHLO mail-pw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754655Ab1ECTlY (ORCPT ); Tue, 3 May 2011 15:41:24 -0400 Date: Tue, 3 May 2011 13:41:19 -0600 From: Grant Likely To: Jamie Iles Cc: linux-kernel@vger.kernel.org, linux@arm.linux.org.uk, tglx@linutronix.de, cbouatmailru@gmail.com, arnd@arndb.de, nico@fluxnic.net Subject: Re: [PATCHv3 1/7] basic_mmio_gpio: remove runtime width/endianness evaluation Message-ID: <20110503194119.GA9401@ponder.secretlab.ca> References: <1302520914-22816-1-git-send-email-jamie@jamieiles.com> <1302520914-22816-2-git-send-email-jamie@jamieiles.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1302520914-22816-2-git-send-email-jamie@jamieiles.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6667 Lines: 235 On Mon, Apr 11, 2011 at 12:21:48PM +0100, Jamie Iles wrote: > Remove endianness/width calculations at runtime by installing function > pointers for bit-to-mask conversion and register accessors. > > Reported-by: Thomas Gleixner > Signed-off-by: Jamie Iles > Acked-by: Anton Vorontsov > Cc: Grant Likely Merged, thanks. g. > --- > drivers/gpio/basic_mmio_gpio.c | 136 +++++++++++++++++++++++++++------------- > 1 files changed, 92 insertions(+), 44 deletions(-) > > diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/basic_mmio_gpio.c > index 3addea6..e935a24 100644 > --- a/drivers/gpio/basic_mmio_gpio.c > +++ b/drivers/gpio/basic_mmio_gpio.c > @@ -63,6 +63,10 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` > > struct bgpio_chip { > struct gpio_chip gc; > + > + unsigned long (*read_reg)(void __iomem *reg); > + void (*write_reg)(void __iomem *reg, unsigned long data); > + > void __iomem *reg_dat; > void __iomem *reg_set; > void __iomem *reg_clr; > @@ -74,7 +78,7 @@ struct bgpio_chip { > * Some GPIO controllers work with the big-endian bits notation, > * e.g. in a 8-bits register, GPIO7 is the least significant bit. > */ > - int big_endian_bits; > + unsigned long (*pin2mask)(struct bgpio_chip *bgc, unsigned int pin); > > /* > * Used to lock bgpio_chip->data. Also, this is needed to keep > @@ -91,70 +95,77 @@ static struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc) > return container_of(gc, struct bgpio_chip, gc); > } > > -static unsigned long bgpio_in(struct bgpio_chip *bgc) > +static void bgpio_write8(void __iomem *reg, unsigned long data) > { > - switch (bgc->bits) { > - case 8: > - return __raw_readb(bgc->reg_dat); > - case 16: > - return __raw_readw(bgc->reg_dat); > - case 32: > - return __raw_readl(bgc->reg_dat); > -#if BITS_PER_LONG >= 64 > - case 64: > - return __raw_readq(bgc->reg_dat); > -#endif > - } > - return -EINVAL; > + __raw_writeb(data, reg); > } > > -static void bgpio_out(struct bgpio_chip *bgc, void __iomem *reg, > - unsigned long data) > +static unsigned long bgpio_read8(void __iomem *reg) > { > - switch (bgc->bits) { > - case 8: > - __raw_writeb(data, reg); > - return; > - case 16: > - __raw_writew(data, reg); > - return; > - case 32: > - __raw_writel(data, reg); > - return; > + return __raw_readb(reg); > +} > + > +static void bgpio_write16(void __iomem *reg, unsigned long data) > +{ > + __raw_writew(data, reg); > +} > + > +static unsigned long bgpio_read16(void __iomem *reg) > +{ > + return __raw_readw(reg); > +} > + > +static void bgpio_write32(void __iomem *reg, unsigned long data) > +{ > + __raw_writel(data, reg); > +} > + > +static unsigned long bgpio_read32(void __iomem *reg) > +{ > + return __raw_readl(reg); > +} > + > #if BITS_PER_LONG >= 64 > - case 64: > - __raw_writeq(data, reg); > - return; > -#endif > - } > +static void bgpio_write64(void __iomem *reg, unsigned long data) > +{ > + __raw_writeq(data, reg); > } > > +static unsigned long bgpio_read64(void __iomem *reg) > +{ > + return __raw_readq(reg); > +} > +#endif /* BITS_PER_LONG >= 64 */ > + > static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) > { > - if (bgc->big_endian_bits) > - return 1 << (bgc->bits - 1 - pin); > - else > - return 1 << pin; > + return 1 << pin; > +} > + > +static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc, > + unsigned int pin) > +{ > + return 1 << (bgc->bits - 1 - pin); > } > > static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) > { > struct bgpio_chip *bgc = to_bgpio_chip(gc); > > - return bgpio_in(bgc) & bgpio_pin2mask(bgc, gpio); > + return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio); > } > > static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) > { > struct bgpio_chip *bgc = to_bgpio_chip(gc); > - unsigned long mask = bgpio_pin2mask(bgc, gpio); > + unsigned long mask = bgc->pin2mask(bgc, gpio); > unsigned long flags; > > if (bgc->reg_set) { > if (val) > - bgpio_out(bgc, bgc->reg_set, mask); > + bgc->write_reg(bgc->reg_set, mask); > else > - bgpio_out(bgc, bgc->reg_clr, mask); > + bgc->write_reg(bgc->reg_clr, mask); > return; > } > > @@ -165,7 +176,7 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) > else > bgc->data &= ~mask; > > - bgpio_out(bgc, bgc->reg_dat, bgc->data); > + bgc->write_reg(bgc->reg_dat, bgc->data); > > spin_unlock_irqrestore(&bgc->lock, flags); > } > @@ -181,9 +192,44 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) > return 0; > } > > -static int __devinit bgpio_probe(struct platform_device *pdev) > +static int bgpio_setup_accessors(struct platform_device *pdev, > + struct bgpio_chip *bgc) > { > const struct platform_device_id *platid = platform_get_device_id(pdev); > + > + switch (bgc->bits) { > + case 8: > + bgc->read_reg = bgpio_read8; > + bgc->write_reg = bgpio_write8; > + break; > + case 16: > + bgc->read_reg = bgpio_read16; > + bgc->write_reg = bgpio_write16; > + break; > + case 32: > + bgc->read_reg = bgpio_read32; > + bgc->write_reg = bgpio_write32; > + break; > +#if BITS_PER_LONG >= 64 > + case 64: > + bgc->read_reg = bgpio_read64; > + bgc->write_reg = bgpio_write64; > + break; > +#endif /* BITS_PER_LONG >= 64 */ > + default: > + dev_err(&pdev->dev, "unsupported data width %u bits\n", > + bgc->bits); > + return -EINVAL; > + } > + > + bgc->pin2mask = strcmp(platid->name, "basic-mmio-gpio-be") ? > + bgpio_pin2mask : bgpio_pin2mask_be; > + > + return 0; > +} > + > +static int __devinit bgpio_probe(struct platform_device *pdev) > +{ > struct device *dev = &pdev->dev; > struct bgpio_pdata *pdata = dev_get_platdata(dev); > struct bgpio_chip *bgc; > @@ -232,9 +278,11 @@ static int __devinit bgpio_probe(struct platform_device *pdev) > spin_lock_init(&bgc->lock); > > bgc->bits = bits; > - bgc->big_endian_bits = !strcmp(platid->name, "basic-mmio-gpio-be"); > - bgc->data = bgpio_in(bgc); > + ret = bgpio_setup_accessors(pdev, bgc); > + if (ret) > + return ret; > > + bgc->data = bgc->read_reg(bgc->reg_dat); > bgc->gc.ngpio = bits; > bgc->gc.direction_input = bgpio_dir_in; > bgc->gc.direction_output = bgpio_dir_out; > -- > 1.7.4.2 > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/