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 = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio),
 120                                   GFP_KERNEL);
 121        if (wm8350_gpio == NULL)
 122                return -ENOMEM;
 123
 124        wm8350_gpio->wm8350 = wm8350;
 125        wm8350_gpio->gpio_chip = template_chip;
 126        wm8350_gpio->gpio_chip.ngpio = 13;
 127        wm8350_gpio->gpio_chip.dev = &pdev->dev;
 128        if (pdata && pdata->gpio_base)
 129                wm8350_gpio->gpio_chip.base = pdata->gpio_base;
 130        else
 131                wm8350_gpio->gpio_chip.base = -1;
 132
 133        ret = gpiochip_add(&wm8350_gpio->gpio_chip);
 134        if (ret < 0) {
 135                dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
 136                return ret;
 137        }
 138
 139        platform_set_drvdata(pdev, wm8350_gpio);
 140
 141        return ret;
 142}
 143
 144static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
 145{
 146        struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
 147
 148        return gpiochip_remove(&wm8350_gpio->gpio_chip);
 149}
 150
 151static struct platform_driver wm8350_gpio_driver = {
 152        .driver.name    = "wm8350-gpio",
 153        .driver.owner   = THIS_MODULE,
 154        .probe          = wm8350_gpio_probe,
 155        .remove         = __devexit_p(wm8350_gpio_remove),
 156};
 157
 158static int __init wm8350_gpio_init(void)
 159{
 160        return platform_driver_register(&wm8350_gpio_driver);
 161}
 162subsys_initcall(wm8350_gpio_init);
 163
 164static void __exit wm8350_gpio_exit(void)
 165{
 166        platform_driver_unregister(&wm8350_gpio_driver);
 167}
 168module_exit(wm8350_gpio_exit);
 169
 170MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 171MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
 172MODULE_LICENSE("GPL");
 173MODULE_ALIAS("platform:wm8350-gpio");
 174
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.