Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757878AbYJKOH3 (ORCPT ); Sat, 11 Oct 2008 10:07:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753370AbYJKOHS (ORCPT ); Sat, 11 Oct 2008 10:07:18 -0400 Received: from 3a.49.1343.static.theplanet.com ([67.19.73.58]:47987 "EHLO pug.o-hand.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753396AbYJKOHQ (ORCPT ); Sat, 11 Oct 2008 10:07:16 -0400 Date: Sat, 11 Oct 2008 16:09:51 +0200 From: Samuel Ortiz To: Mark Brown Cc: Liam Girdwood , linux-kernel@vger.kernel.org Subject: Re: [PATCH 10/14] mfd: Add GPIO pin configuration support for WM8350 Message-ID: <20081011140950.GB2712@sortiz.org> Reply-To: Samuel Ortiz References: <1223650696-15552-1-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-2-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-3-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-4-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-5-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-6-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-7-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-8-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-9-git-send-email-broonie@opensource.wolfsonmicro.com> <1223650696-15552-10-git-send-email-broonie@opensource.wolfsonmicro.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1223650696-15552-10-git-send-email-broonie@opensource.wolfsonmicro.com> User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9529 Lines: 295 On Fri, Oct 10, 2008 at 03:58:12PM +0100, Mark Brown wrote: > The WM8350 provides a number of user-configurable pins providing access > to various signals generated by the functions on the chip. These are > referred to as GPIO pins in the device documentation but in Linux terms > they are more general than that, providing configuration of alternate > functions. > > This patch implements support for selecting the alternate functions for > these pins. They can also be used as GPIOs in the normal Linux sense - > a subsequent patch will add support for doing so. I expect it to implement the giolib interface, right ? Cheers, Samuel. > This code was all written by Liam Girdwood and has had minor updates > and rearrangements by Mark Brown. > > Signed-off-by: Mark Brown > --- > drivers/mfd/Makefile | 2 +- > drivers/mfd/wm8350-gpio.c | 222 +++++++++++++++++++++++++++++++++++++++ > include/linux/mfd/wm8350/gpio.h | 10 ++ > 3 files changed, 233 insertions(+), 1 deletions(-) > create mode 100644 drivers/mfd/wm8350-gpio.c > > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index 746d37b..8c0b7f2 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o > obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o > > obj-$(CONFIG_MFD_WM8400) += wm8400-core.o > -wm8350-objs := wm8350-core.o wm8350-regmap.o > +wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o > obj-$(CONFIG_MFD_WM8350) += wm8350.o > obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o > > diff --git a/drivers/mfd/wm8350-gpio.c b/drivers/mfd/wm8350-gpio.c > new file mode 100644 > index 0000000..ebf99be > --- /dev/null > +++ b/drivers/mfd/wm8350-gpio.c > @@ -0,0 +1,222 @@ > +/* > + * wm8350-core.c -- Device access for Wolfson WM8350 > + * > + * Copyright 2007, 2008 Wolfson Microelectronics PLC. > + * > + * Author: Liam Girdwood > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or (at your > + * option) any later version. > + * > + */ > + > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir) > +{ > + int ret; > + > + wm8350_reg_unlock(wm8350); > + if (dir == WM8350_GPIO_DIR_OUT) > + ret = wm8350_clear_bits(wm8350, > + WM8350_GPIO_CONFIGURATION_I_O, > + 1 << gpio); > + else > + ret = wm8350_set_bits(wm8350, > + WM8350_GPIO_CONFIGURATION_I_O, > + 1 << gpio); > + wm8350_reg_lock(wm8350); > + return ret; > +} > + > +static int gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db) > +{ > + if (db == WM8350_GPIO_DEBOUNCE_ON) > + return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE, > + 1 << gpio); > + else > + return wm8350_clear_bits(wm8350, > + WM8350_GPIO_DEBOUNCE, 1 << gpio); > +} > + > +static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func) > +{ > + u16 reg; > + > + wm8350_reg_unlock(wm8350); > + switch (gpio) { > + case 0: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) > + & ~WM8350_GP0_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, > + reg | ((func & 0xf) << 0)); > + break; > + case 1: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) > + & ~WM8350_GP1_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, > + reg | ((func & 0xf) << 4)); > + break; > + case 2: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) > + & ~WM8350_GP2_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, > + reg | ((func & 0xf) << 8)); > + break; > + case 3: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) > + & ~WM8350_GP3_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, > + reg | ((func & 0xf) << 12)); > + break; > + case 4: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) > + & ~WM8350_GP4_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, > + reg | ((func & 0xf) << 0)); > + break; > + case 5: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) > + & ~WM8350_GP5_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, > + reg | ((func & 0xf) << 4)); > + break; > + case 6: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) > + & ~WM8350_GP6_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, > + reg | ((func & 0xf) << 8)); > + break; > + case 7: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) > + & ~WM8350_GP7_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, > + reg | ((func & 0xf) << 12)); > + break; > + case 8: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) > + & ~WM8350_GP8_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, > + reg | ((func & 0xf) << 0)); > + break; > + case 9: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) > + & ~WM8350_GP9_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, > + reg | ((func & 0xf) << 4)); > + break; > + case 10: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) > + & ~WM8350_GP10_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, > + reg | ((func & 0xf) << 8)); > + break; > + case 11: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) > + & ~WM8350_GP11_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, > + reg | ((func & 0xf) << 12)); > + break; > + case 12: > + reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4) > + & ~WM8350_GP12_FN_MASK; > + wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4, > + reg | ((func & 0xf) << 0)); > + break; > + default: > + wm8350_reg_lock(wm8350); > + return -EINVAL; > + } > + > + wm8350_reg_lock(wm8350); > + return 0; > +} > + > +static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up) > +{ > + if (up) > + return wm8350_set_bits(wm8350, > + WM8350_GPIO_PIN_PULL_UP_CONTROL, > + 1 << gpio); > + else > + return wm8350_clear_bits(wm8350, > + WM8350_GPIO_PIN_PULL_UP_CONTROL, > + 1 << gpio); > +} > + > +static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down) > +{ > + if (down) > + return wm8350_set_bits(wm8350, > + WM8350_GPIO_PULL_DOWN_CONTROL, > + 1 << gpio); > + else > + return wm8350_clear_bits(wm8350, > + WM8350_GPIO_PULL_DOWN_CONTROL, > + 1 << gpio); > +} > + > +static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol) > +{ > + if (pol == WM8350_GPIO_ACTIVE_HIGH) > + return wm8350_set_bits(wm8350, > + WM8350_GPIO_PIN_POLARITY_TYPE, > + 1 << gpio); > + else > + return wm8350_clear_bits(wm8350, > + WM8350_GPIO_PIN_POLARITY_TYPE, > + 1 << gpio); > +} > + > +static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert) > +{ > + if (invert == WM8350_GPIO_INVERT_ON) > + return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio); > + else > + return wm8350_clear_bits(wm8350, > + WM8350_GPIO_INT_MODE, 1 << gpio); > +} > + > +int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func, > + int pol, int pull, int invert, int debounce) > +{ > + /* make sure we never pull up and down at the same time */ > + if (pull == WM8350_GPIO_PULL_NONE) { > + if (gpio_set_pull_up(wm8350, gpio, 0)) > + goto err; > + if (gpio_set_pull_down(wm8350, gpio, 0)) > + goto err; > + } else if (pull == WM8350_GPIO_PULL_UP) { > + if (gpio_set_pull_down(wm8350, gpio, 0)) > + goto err; > + if (gpio_set_pull_up(wm8350, gpio, 1)) > + goto err; > + } else if (pull == WM8350_GPIO_PULL_DOWN) { > + if (gpio_set_pull_up(wm8350, gpio, 0)) > + goto err; > + if (gpio_set_pull_down(wm8350, gpio, 1)) > + goto err; > + } > + > + if (gpio_set_invert(wm8350, gpio, invert)) > + goto err; > + if (gpio_set_polarity(wm8350, gpio, pol)) > + goto err; > + if (gpio_set_debounce(wm8350, gpio, debounce)) > + goto err; > + if (gpio_set_dir(wm8350, gpio, dir)) > + goto err; > + return gpio_set_func(wm8350, gpio, func); > + > +err: > + return -EIO; > +} > +EXPORT_SYMBOL_GPL(wm8350_gpio_config); > diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h > index 928aa6e..c6cd2ca 100644 > --- a/include/linux/mfd/wm8350/gpio.h > +++ b/include/linux/mfd/wm8350/gpio.h > @@ -323,4 +323,14 @@ > #define WM8350_GP1_LVL 0x0002 > #define WM8350_GP0_LVL 0x0001 > > +struct wm8350; > + > +int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func, > + int pol, int pull, int invert, int debounce); > + > +/* > + * GPIO Interrupts > + */ > +#define WM8350_IRQ_GPIO(x) (50 + x) > + > #endif > -- > 1.5.6.5 > -- 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/