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 int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
  32{
  33        struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  34        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  35
  36        return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
  37                               1 << offset);
  38}
  39
  40static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
  41{
  42        struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  43        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  44        int ret;
  45
  46        ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
  47        if (ret < 0)
  48                return ret;
  49
  50        if (ret & (1 << offset))
  51                return 1;
  52        else
  53                return 0;
  54}
  55
  56static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  57{
  58        struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  59        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  60
  61        if (value)
  62                wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
  63        else
  64                wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
  65}
  66
  67static int wm8350_gpio_direction_out(struct gpio_chip *chip,
  68                                     unsigned offset, int value)
  69{
  70        struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  71        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  72        int ret;
  73
  74        ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
  75                                1 << offset);
  76        if (ret < 0)
  77                return ret;
  78
  79        /* Don't have an atomic direction/value setup */
  80        wm8350_gpio_set(chip, offset, value);
  81
  82        return 0;
  83}
  84
  85static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  86{
  87        struct wm8350_gpio_data *wm8350_gpio = gpiochip_get_data(chip);
  88        struct wm8350 *wm8350 = wm8350_gpio->wm8350;
  89
  90        if (!wm8350->irq_base)
  91                return -EINVAL;
  92
  93        return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
  94}
  95
  96static const struct gpio_chip template_chip = {
  97        .label                  = "wm8350",
  98        .owner                  = THIS_MODULE,
  99        .direction_input        = wm8350_gpio_direction_in,
 100        .get                    = wm8350_gpio_get,
 101        .direction_output       = wm8350_gpio_direction_out,
 102        .set                    = wm8350_gpio_set,
 103        .to_irq                 = wm8350_gpio_to_irq,
 104        .can_sleep              = true,
 105};
 106
 107static int wm8350_gpio_probe(struct platform_device *pdev)
 108{
 109        struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
 110        struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev);
 111        struct wm8350_gpio_data *wm8350_gpio;
 112        int ret;
 113
 114        wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio),
 115                                   GFP_KERNEL);
 116        if (wm8350_gpio == NULL)
 117                return -ENOMEM;
 118
 119        wm8350_gpio->wm8350 = wm8350;
 120        wm8350_gpio->gpio_chip = template_chip;
 121        wm8350_gpio->gpio_chip.ngpio = 13;
 122        wm8350_gpio->gpio_chip.parent = &pdev->dev;
 123        if (pdata && pdata->gpio_base)
 124                wm8350_gpio->gpio_chip.base = pdata->gpio_base;
 125        else
 126                wm8350_gpio->gpio_chip.base = -1;
 127
 128        ret = devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip,
 129                                     wm8350_gpio);
 130        if (ret < 0) {
 131                dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
 132                return ret;
 133        }
 134
 135        platform_set_drvdata(pdev, wm8350_gpio);
 136
 137        return ret;
 138}
 139
 140static struct platform_driver wm8350_gpio_driver = {
 141        .driver.name    = "wm8350-gpio",
 142        .probe          = wm8350_gpio_probe,
 143};
 144
 145static int __init wm8350_gpio_init(void)
 146{
 147        return platform_driver_register(&wm8350_gpio_driver);
 148}
 149subsys_initcall(wm8350_gpio_init);
 150
 151static void __exit wm8350_gpio_exit(void)
 152{
 153        platform_driver_unregister(&wm8350_gpio_driver);
 154}
 155module_exit(wm8350_gpio_exit);
 156
 157MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 158MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
 159MODULE_LICENSE("GPL");
 160MODULE_ALIAS("platform:wm8350-gpio");
 161