From: David Brownell <david-b@pacbell.net>
To: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 10/22] gpio: Add WM831X GPIO driver
Date: Mon, 27 Jul 2009 13:27:51 -0700 [thread overview]
Message-ID: <200907271327.51674.david-b@pacbell.net> (raw)
In-Reply-To: <1248702372-29534-10-git-send-email-broonie@opensource.wolfsonmicro.com>
On Monday 27 July 2009, Mark Brown wrote:
> Add support for the GPIO pins on the WM831x. No direct support is
> currently supplied for configuring non-gpiolib functionality such
> as pull configuration and alternate functions, soft configuration
> of these will be provided in a future patch.
>
> Currently use of these pins as interrupts is not supported due to
> the ongoing issues with generic irq not support interrupt controllers
> on interrupt driven buses. Users can directly request the interrupts
> with the wm831x-specific APIs currently provided if required.
>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
> ---
> drivers/gpio/Kconfig | 7 +
> drivers/gpio/Makefile | 1 +
> drivers/gpio/wm831x-gpio.c | 252 +++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/wm831x/gpio.h | 55 +++++++++
> 4 files changed, 315 insertions(+), 0 deletions(-)
> create mode 100644 drivers/gpio/wm831x-gpio.c
> create mode 100644 include/linux/mfd/wm831x/gpio.h
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 96dda81..6b4c484 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -155,6 +155,13 @@ config GPIO_TWL4030
> Say yes here to access the GPIO signals of various multi-function
> power management chips from Texas Instruments.
>
> +config GPIO_WM831X
> + tristate "WM831x GPIOs"
> + depends on MFD_WM831X
> + help
> + Say yes here to access the GPIO signals of WM831x power management
> + chips from Wolfson Microelectronics.
> +
> comment "PCI GPIO expanders:"
>
> config GPIO_BT8XX
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 9244c6f..ea7c745 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
> obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
> obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
> obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
> +obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
> diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
> new file mode 100644
> index 0000000..f9c09a5
> --- /dev/null
> +++ b/drivers/gpio/wm831x-gpio.c
> @@ -0,0 +1,252 @@
> +/*
> + * wm831x-gpio.c -- gpiolib support for Wolfson WM831x PMICs
> + *
> + * Copyright 2009 Wolfson Microelectronics PLC.
> + *
> + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
> + *
> + * 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 <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/gpio.h>
> +#include <linux/mfd/core.h>
> +#include <linux/platform_device.h>
> +#include <linux/seq_file.h>
> +
> +#include <linux/mfd/wm831x/core.h>
> +#include <linux/mfd/wm831x/pdata.h>
> +#include <linux/mfd/wm831x/gpio.h>
> +
> +#define WM831X_GPIO_MAX 16
> +
> +struct wm831x_gpio {
> + struct wm831x *wm831x;
> + struct gpio_chip gpio_chip;
> +};
> +
> +static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip)
> +{
> + return container_of(chip, struct wm831x_gpio, gpio_chip);
> +}
> +
> +static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
> +{
> + struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
> + struct wm831x *wm831x = wm831x_gpio->wm831x;
> +
> + return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
> + WM831X_GPN_DIR | WM831X_GPN_TRI,
> + WM831X_GPN_DIR);
> +}
> +
> +static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
> +{
> + struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
> + struct wm831x *wm831x = wm831x_gpio->wm831x;
> + int ret;
> +
> + ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
> + if (ret < 0)
> + return ret;
> +
> + if (ret & 1 << offset)
> + return 1;
> + else
> + return 0;
> +}
> +
> +static int wm831x_gpio_direction_out(struct gpio_chip *chip,
> + unsigned offset, int value)
> +{
> + struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
> + struct wm831x *wm831x = wm831x_gpio->wm831x;
> +
> + return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
> + WM831X_GPN_DIR | WM831X_GPN_TRI, 0);
> +}
> +
> +static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
> +{
> + struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
> + struct wm831x *wm831x = wm831x_gpio->wm831x;
> +
> + wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
> + value << offset);
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
> +{
> + struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
> + struct wm831x *wm831x = wm831x_gpio->wm831x;
> + int i;
> +
> + for (i = 0; i < chip->ngpio; i++) {
> + int gpio = i + chip->base;
> + int reg;
> + const char *label, *pull, *powerdomain;
> +
> + /* We report the GPIO even if it's not requested since
> + * we're also reporting things like alternate
> + * functions which apply even when the GPIO is not in
> + * use as a GPIO.
> + */
> + label = gpiochip_is_requested(chip, i);
> + if (!label)
> + label = "Unrequested";
> +
> + seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
> +
> + reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
> + if (reg < 0) {
> + dev_err(wm831x->dev,
> + "GPIO control %d read failed: %d\n",
> + gpio, reg);
> + seq_printf(s, "\n");
> + continue;
> + }
> +
> + switch (reg & WM831X_GPN_PULL_MASK) {
> + case WM831X_GPIO_PULL_NONE:
> + pull = "nopull";
> + break;
> + case WM831X_GPIO_PULL_DOWN:
> + pull = "pulldown";
> + break;
> + case WM831X_GPIO_PULL_UP:
> + pull = "pullup";
> + default:
> + pull = "INVALID PULL";
> + break;
> + }
> +
> + switch (i + 1) {
> + case 1 ... 3:
> + case 7 ... 9:
> + if (reg & WM831X_GPN_PWR_DOM)
> + powerdomain = "VPMIC";
> + else
> + powerdomain = "DBVDD";
> + break;
> +
> + case 4 ... 6:
> + case 10 ... 12:
> + if (reg & WM831X_GPN_PWR_DOM)
> + powerdomain = "SYSVDD";
> + else
> + powerdomain = "DBVDD";
> + break;
> +
> + case 13 ... 16:
> + powerdomain = "TPVDD";
> + break;
> +
> + default:
> + BUG();
> + break;
> + }
> +
> + seq_printf(s, " %s %s %s %s%s\n"
> + " %s%s (0x%4x)\n",
> + reg & WM831X_GPN_DIR ? "in" : "out",
> + wm831x_gpio_get(chip, i) ? "high" : "low",
> + pull,
> + powerdomain,
> + reg & WM831X_GPN_POL ? " inverted" : "",
> + reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
> + reg & WM831X_GPN_TRI ? " tristated" : "",
> + reg);
> + }
> +}
> +#else
> +#define wm831x_gpio_dbg_show NULL
> +#endif
> +
> +static struct gpio_chip template_chip = {
> + .label = "wm831x",
> + .owner = THIS_MODULE,
> + .direction_input = wm831x_gpio_direction_in,
> + .get = wm831x_gpio_get,
> + .direction_output = wm831x_gpio_direction_out,
> + .set = wm831x_gpio_set,
> + .dbg_show = wm831x_gpio_dbg_show,
> + .can_sleep = 1,
> +};
> +
> +static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
> +{
> + struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
> + struct wm831x_pdata *pdata = wm831x->dev->platform_data;
> + struct wm831x_gpio *wm831x_gpio;
> + int ret;
> +
> + wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL);
> + if (wm831x_gpio == NULL)
> + return -ENOMEM;
> +
> + wm831x_gpio->wm831x = wm831x;
> + wm831x_gpio->gpio_chip = template_chip;
> + wm831x_gpio->gpio_chip.ngpio = WM831X_GPIO_MAX;
> + wm831x_gpio->gpio_chip.dev = &pdev->dev;
> + if (pdata && pdata->gpio_base)
> + wm831x_gpio->gpio_chip.base = pdata->gpio_base;
> + else
> + wm831x_gpio->gpio_chip.base = -1;
> +
> + ret = gpiochip_add(&wm831x_gpio->gpio_chip);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
> + ret);
> + goto err;
> + }
> +
> + platform_set_drvdata(pdev, wm831x_gpio);
> +
> + return ret;
> +
> +err:
> + kfree(wm831x_gpio);
> + return ret;
> +}
> +
> +static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
> +{
> + struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
> + int ret;
> +
> + ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
> + if (ret == 0)
> + kfree(wm831x_gpio);
> +
> + return ret;
> +}
> +
> +static struct platform_driver wm831x_gpio_driver = {
> + .driver.name = "wm831x-gpio",
> + .driver.owner = THIS_MODULE,
> + .probe = wm831x_gpio_probe,
> + .remove = __devexit_p(wm831x_gpio_remove),
> +};
> +
> +static int __init wm831x_gpio_init(void)
> +{
> + return platform_driver_register(&wm831x_gpio_driver);
> +}
> +subsys_initcall(wm831x_gpio_init);
> +
> +static void __exit wm831x_gpio_exit(void)
> +{
> + platform_driver_unregister(&wm831x_gpio_driver);
> +}
> +module_exit(wm831x_gpio_exit);
> +
> +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
> +MODULE_DESCRIPTION("GPIO interface for WM831x PMICs");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:wm831x-gpio");
> diff --git a/include/linux/mfd/wm831x/gpio.h b/include/linux/mfd/wm831x/gpio.h
> new file mode 100644
> index 0000000..2835614
> --- /dev/null
> +++ b/include/linux/mfd/wm831x/gpio.h
> @@ -0,0 +1,55 @@
> +/*
> + * include/linux/mfd/wm831x/gpio.h -- GPIO for WM831x
> + *
> + * Copyright 2009 Wolfson Microelectronics PLC.
> + *
> + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef __MFD_WM831X_GPIO_H__
> +#define __MFD_WM831X_GPIO_H__
> +
> +/*
> + * R16440-16455 (0x4038-0x4047) - GPIOx Control
> + */
> +#define WM831X_GPN_DIR 0x8000 /* GPN_DIR */
> +#define WM831X_GPN_DIR_MASK 0x8000 /* GPN_DIR */
> +#define WM831X_GPN_DIR_SHIFT 15 /* GPN_DIR */
> +#define WM831X_GPN_DIR_WIDTH 1 /* GPN_DIR */
> +#define WM831X_GPN_PULL_MASK 0x6000 /* GPN_PULL - [14:13] */
> +#define WM831X_GPN_PULL_SHIFT 13 /* GPN_PULL - [14:13] */
> +#define WM831X_GPN_PULL_WIDTH 2 /* GPN_PULL - [14:13] */
> +#define WM831X_GPN_INT_MODE 0x1000 /* GPN_INT_MODE */
> +#define WM831X_GPN_INT_MODE_MASK 0x1000 /* GPN_INT_MODE */
> +#define WM831X_GPN_INT_MODE_SHIFT 12 /* GPN_INT_MODE */
> +#define WM831X_GPN_INT_MODE_WIDTH 1 /* GPN_INT_MODE */
> +#define WM831X_GPN_PWR_DOM 0x0800 /* GPN_PWR_DOM */
> +#define WM831X_GPN_PWR_DOM_MASK 0x0800 /* GPN_PWR_DOM */
> +#define WM831X_GPN_PWR_DOM_SHIFT 11 /* GPN_PWR_DOM */
> +#define WM831X_GPN_PWR_DOM_WIDTH 1 /* GPN_PWR_DOM */
> +#define WM831X_GPN_POL 0x0400 /* GPN_POL */
> +#define WM831X_GPN_POL_MASK 0x0400 /* GPN_POL */
> +#define WM831X_GPN_POL_SHIFT 10 /* GPN_POL */
> +#define WM831X_GPN_POL_WIDTH 1 /* GPN_POL */
> +#define WM831X_GPN_OD 0x0200 /* GPN_OD */
> +#define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */
> +#define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */
> +#define WM831X_GPN_OD_WIDTH 1 /* GPN_OD */
> +#define WM831X_GPN_TRI 0x0080 /* GPN_TRI */
> +#define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */
> +#define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */
> +#define WM831X_GPN_TRI_WIDTH 1 /* GPN_TRI */
> +#define WM831X_GPN_FN_MASK 0x000F /* GPN_FN - [3:0] */
> +#define WM831X_GPN_FN_SHIFT 0 /* GPN_FN - [3:0] */
> +#define WM831X_GPN_FN_WIDTH 4 /* GPN_FN - [3:0] */
> +
> +#define WM831X_GPIO_PULL_NONE (0 << WM831X_GPN_PULL_SHIFT)
> +#define WM831X_GPIO_PULL_DOWN (1 << WM831X_GPN_PULL_SHIFT)
> +#define WM831X_GPIO_PULL_UP (2 << WM831X_GPN_PULL_SHIFT)
> +#endif
> --
> 1.6.3.3
>
>
next prev parent reply other threads:[~2009-07-27 20:27 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-27 13:45 [PATCH 0/22] WM831x drivers Mark Brown
2009-07-27 13:45 ` Mark Brown
2009-07-27 13:45 ` [lm-sensors] " Mark Brown
2009-07-27 13:45 ` [PATCH 01/22] mfd: Allow multiple MFD cells with the same name Mark Brown
2009-07-27 13:45 ` [PATCH 02/22] mfd: Initial core support for WM831x series devices Mark Brown
2009-07-27 15:00 ` [PATCH] mfd: Fix comment cut'n'paste in register lock code Mark Brown
2009-07-27 13:45 ` [PATCH 03/22] mfd: Add WM831x interrupt support Mark Brown
2009-07-27 13:45 ` [PATCH 04/22] mfd: Add WM831x AUXADC support Mark Brown
2009-07-27 13:45 ` [PATCH 05/22] mfd: Conditionally add WM831x backlight subdevice Mark Brown
2009-07-27 13:45 ` [PATCH 06/22] mfd: Add basic WM831x OTP support Mark Brown
2009-07-27 13:45 ` [PATCH 07/22] mfd: Export ISEL values from WM831x core Mark Brown
2009-07-27 13:45 ` [PATCH 08/22] mfd: Hook WM831x into build system Mark Brown
2009-07-27 13:45 ` [PATCH 09/22] backlight: Add WM831x backlight driver Mark Brown
2009-07-27 13:46 ` [PATCH 10/22] gpio: Add WM831X GPIO driver Mark Brown
2009-07-27 20:27 ` David Brownell [this message]
2009-07-27 13:46 ` [lm-sensors] [PATCH 11/22] hwmon: Add WM835x PMIC hardware Mark Brown
2009-07-27 13:46 ` [PATCH 11/22] hwmon: Add WM835x PMIC hardware monitoring driver Mark Brown
2009-07-27 13:46 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware monitoring Mark Brown
2009-07-27 13:46 ` [PATCH 12/22] hwmon: WM831x PMIC hardware monitoring driver Mark Brown
2009-07-27 19:44 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware Jean Delvare
2009-07-27 19:44 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware monitoring driver Jean Delvare
2009-07-27 20:46 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware Mark Brown
2009-07-27 20:46 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware monitoring driver Mark Brown
2009-07-28 7:26 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware Jean Delvare
2009-07-28 7:26 ` [lm-sensors] [PATCH 12/22] hwmon: WM831x PMIC hardware monitoring driver Jean Delvare
2009-07-28 14:11 ` [lm-sensors] [PATCH] " Mark Brown
2009-07-28 14:11 ` Mark Brown
2009-07-28 14:26 ` [lm-sensors] [PATCH] hwmon: WM831x PMIC hardware monitoring Jean Delvare
2009-07-28 14:26 ` [PATCH] hwmon: WM831x PMIC hardware monitoring driver Jean Delvare
2009-07-28 14:50 ` [lm-sensors] [PATCH] hwmon: WM831x PMIC hardware monitoring Mark Brown
2009-07-28 14:50 ` [PATCH] hwmon: WM831x PMIC hardware monitoring driver Mark Brown
2009-07-28 14:52 ` [lm-sensors] " Mark Brown
2009-07-28 14:52 ` Mark Brown
2009-08-04 11:33 ` [lm-sensors] [PATCH] hwmon: WM831x PMIC hardware monitoring Samuel Ortiz
2009-08-04 11:33 ` [PATCH] hwmon: WM831x PMIC hardware monitoring driver Samuel Ortiz
2009-08-04 11:53 ` [lm-sensors] [PATCH] hwmon: WM831x PMIC hardware monitoring Jean Delvare
2009-08-04 11:53 ` [PATCH] hwmon: WM831x PMIC hardware monitoring driver Jean Delvare
2009-07-27 13:46 ` [PATCH 13/22] Input: Add support for the WM831x ON pin Mark Brown
2009-07-27 15:38 ` Dmitry Torokhov
2009-07-27 15:41 ` Mark Brown
2009-07-28 14:13 ` [PATCH] " Mark Brown
2009-07-27 13:46 ` [PATCH 14/22] leds: Add WM831x status LED driver Mark Brown
2009-07-27 13:46 ` [PATCH 15/22] power_supply: Add driver for the PMU on WM831x PMICs Mark Brown
2009-07-27 13:46 ` [PATCH 16/22] regulator: Add WM831x DC-DC buck convertor support Mark Brown
2009-07-28 14:21 ` [PATCH 17/23] " Mark Brown
2009-07-27 13:46 ` [PATCH 17/22] regulator: Add WM831x LDO support Mark Brown
2009-07-28 14:22 ` [PATCH 18/23] " Mark Brown
2009-07-27 13:46 ` [PATCH 18/22] regulator: Add WM831x EPE support Mark Brown
2009-07-28 14:22 ` [PATCH 19/23] " Mark Brown
2009-07-27 13:46 ` [PATCH 19/22] regulator: Add WM831x DC-DC boost convertor support Mark Brown
2009-07-28 14:23 ` [PATCH] " Mark Brown
2009-07-27 13:46 ` [PATCH 20/22] regulator: Add WM831x ISINK support Mark Brown
2009-07-28 14:23 ` [PATCH] " Mark Brown
2009-07-27 13:46 ` [PATCH 21/22] RTC: Add support for RTCs on Wolfson WM831x devices Mark Brown
2009-07-28 14:18 ` [PATCH] " Mark Brown
2009-07-27 13:46 ` [PATCH 22/22] [WATCHDOG] Add support for WM831x watchdog Mark Brown
2009-08-04 11:35 ` [PATCH 0/22] WM831x drivers Samuel Ortiz
2009-08-04 11:35 ` [lm-sensors] " Samuel Ortiz
2009-08-04 11:44 ` Liam Girdwood
2009-08-04 11:44 ` [lm-sensors] " Liam Girdwood
2009-08-04 14:07 ` Samuel Ortiz
2009-08-04 14:07 ` [lm-sensors] " Samuel Ortiz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200907271327.51674.david-b@pacbell.net \
--to=david-b@pacbell.net \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=linux-kernel@vger.kernel.org \
--cc=sameo@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.