linux/drivers/gpio/gpio-wm8350.c
<<
>>
Prefs
   1/*
   2 * gpiolib support for Wolfson WM835x PMICs
   3 *
   4 * Copyright 2009 Wolfson Microelectronics PLC.
   5 *
   6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 *
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/slab.h>
  17#include <linux/module.h>
  18#include <linux/gpio.h>
  19#include <linux/mfd/core.h>
  20#include <linux/platform_device.h>
  21#include <linux/seq_file.h>
  22
  23#include <linux/mfd/wm8350/core.h>
  24#include <linux/mfd/wm8350/gpio.h>
  25
  26struct wm8350_gpio_data {
  27        struct wm8350 *wm8350;
  28        struct gpio_chip gpio_chip;
  29};
  30
  31static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
  32{
  33        return container_of(chip, struct wm8350_gpio_data, gpio_chip);
  34}
  35
  36static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
  37{
  38        struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
  39        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  40
  41        return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
  42                               1 << offset);
  43}
  44
  45static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
  46{
  47        struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
  48        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  49        int ret;
  50
  51        ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
  52        if (ret < 0)
  53                return ret;
  54
  55        if (ret & (1 << offset))
  56                return 1;
  57        else
  58                return 0;
  59}
  60
  61static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  62{
  63        struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
  64        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  65
  66        if (value)
  67                wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
  68        else
  69                wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
  70}
  71
  72static int wm8350_gpio_direction_out(struct gpio_chip *chip,
  73                                     unsigned offset, int value)
  74{
  75        struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
  76        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  77        int ret;
  78
  79        ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
  80                                1 << offset);
  81        if (ret < 0)
  82                return ret;
  83
  84        /* Don't have an atomic direction/value setup */
  85        wm8350_gpio_set(chip, offset, value);
  86
  87        return 0;
  88}
  89
  90static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  91{
  92        struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
  93        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  94
  95        if (!wm8350->irq_base)
  96                return -EINVAL;
  97
  98        return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
  99}
 100
 101static struct gpio_chip template_chip = {
 102        .label                  = "wm8350",
 103        .owner                  = THIS_MODULE,
 104        .direction_input        = wm8350_gpio_direction_in,
 105        .get                    = wm8350_gpio_get,
 106        .direction_output       = wm8350_gpio_direction_out,
 107        .set                    = wm8350_gpio_set,
 108        .to_irq                 = wm8350_gpio_to_irq,
 109        .can_sleep              = 1,
 110};
 111
 112static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
 113{
 114        struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
 115        struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
 116        struct wm8350_gpio_data *wm8350_gpio;
 117        int ret;
 118
 119        wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
 120        if (wm8350_gpio == NULL)
 121                return -ENOMEM;
 122
 123        wm8350_gpio->wm8350 = wm8350;
 124        wm8350_gpio->gpio_chip = template_chip;
 125        wm8350_gpio->gpio_chip.ngpio = 13;
 126        wm8350_gpio->gpio_chip.dev = &pdev->dev;
 127        if (pdata && pdata->gpio_base)
 128                wm8350_gpio->gpio_chip.base = pdata->gpio_base;
 129        else
 130                wm8350_gpio->gpio_chip.base = -1;
 131
 132        ret = gpiochip_add(&wm8350_gpio->gpio_chip);
 133        if (ret < 0) {
 134                dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
 135                        ret);
 136                goto err;
 137        }
 138
 139        platform_set_drvdata(pdev, wm8350_gpio);
 140
 141        return ret;
 142
 143err:
 144        kfree(wm8350_gpio);
 145        return ret;
 146}
 147
 148static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
 149{
 150        struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
 151        int ret;
 152
 153        ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
 154        if (ret == 0)
 155                kfree(wm8350_gpio);
 156
 157        return ret;
 158}
 159
 160static struct platform_driver wm8350_gpio_driver = {
 161        .driver.name    = "wm8350-gpio",
 162        .driver.owner   = THIS_MODULE,
 163        .probe          = wm8350_gpio_probe,
 164        .remove         = __devexit_p(wm8350_gpio_remove),
 165};
 166
 167static int __init wm8350_gpio_init(void)
 168{
 169        return platform_driver_register(&wm8350_gpio_driver);
 170}
 171subsys_initcall(wm8350_gpio_init);
 172
 173static void __exit wm8350_gpio_exit(void)
 174{
 175        platform_driver_unregister(&wm8350_gpio_driver);
 176}
 177module_exit(wm8350_gpio_exit);
 178
 179MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 180MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
 181MODULE_LICENSE("GPL");
 182MODULE_ALIAS("platform:wm8350-gpio");
 183