linux_dsm_epyc7002/drivers/gpio/gpio-arizona.c
Linus Torvalds 510965dd4a This is the bulk of GPIO changes for the v4.1 development
cycle:
 
 - A new GPIO hogging mechanism has been added. This can
   be used on boards that want to drive some GPIO line high,
   low, or set it as input on boot and then never touch it
   again. For some embedded systems this is bliss and
   simplifies things to a great extent.
 
 - Some API cleanup and closure: gpiod_get_array() and
   gpiod_put_array() has been added to get and put GPIOs
   in bulk as was possible with the non-descriptor API.
 
 - Encapsulate cross-calls to the pin control subsystem in
   <linux/gpio/driver.h>. Now this should be the only header
   any GPIO driver needs to include or something is wrong.
   Cleanups restricting drivers to this include are welcomed
   if tested.
 
 - Sort the GPIO Kconfig and split it into submenus, as
   it was becoming and unstructured, illogical and
   unnavigatable mess. I hope this is easier to follow.
   Menus that require a certain subsystem like I2C can
   now be hidden nicely for example, still working on
   others.
 
 - New drivers:
 
     - New driver for the Altera Soft GPIO.
 
     - The F7188x driver now handles the F71869 and
       F71869A variants.
 
     - The MIPS Loongson driver has been moved to
       drivers/gpio for consolidation and cleanup.
 
 - Cleanups:
 
    - The MAX732x is converted to use the GPIOLIB_IRQCHIP
      infrastructure.
 
    - The PCF857x is converted to use the GPIOLIB_IRQCHIP
      infrastructure.
 
    - Radical cleanup of the OMAP driver.
 
 - Misc:
 
    - Enable the DWAPB GPIO for all architectures. This is
      a "hard IP" block from Synopsys which has started to
      turn up in so diverse architectures as X86 Quark, ARC
      and a slew of ARM systems. So even though it's not an
      expander, it's generic enough to be available for all.
 
    - We add a mock GPIO on Crystalcove PMIC after a long
      discussion with Daniel Vetter et al, tracing back to
      the shootout at the kernel summit where DRM drivers
      and sub-componentization was discussed. In this case
      a mock GPIO is assumed to be the best compromise
      gaining some reuse of infrastructure without making
      DRM drivers overly complex at the same time. Let's
      see.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJVMNYHAAoJEEEQszewGV1zSmwP/2oCk4CB4fexrqM+irUJrDnT
 3D/8tuaq7EghMnwPXCfHa8R8eWF6XEDvHPcJNVgXiWbtCGRMpdsiobFunzwLQv5A
 CbcuAOzWmzA0ePbfa0+xpLpWM/RJP9u1an/RboIzeeS7oQ1Yj/VjF8uS8Se+Pe3r
 nPKvTpoU5lGpIUTEEYjiJhL8pBmp8k75a6NGM4U8VwXI9BsdhDkpRGsfG3NK8hs2
 vSvWDB19NCW6iOd3gN4KA4f0Zz57WONMS7jY2WaipqYRlr37o4i2CA0ME1xoXEfg
 3JT1lmg7esNCvnjQOaGTaM6nf66j7/nleNtnMmAAJcJeMNoh9yS6397TGaYFThsn
 C1WmAoaonor3RAujrL3oRenxfq2+Vl63OvsClDiWz7LL9YYJ/G2nS3MggFHpZUhu
 /CHXSt08j0Kewfc5SkvFCTnrPG7aWy/YDou6PfuXIvkFp5h1FXDkHTXvOD33turD
 ohEPlg/9i2uCnVQfN+GV4h69WSyEiOpxG5W7ryE+nIo6XzWIctHLIH2V6aE7YrwG
 FBg7hC1QV1cI776HFOuM4rPwG1N80IQeC3vr5z/jEtZVPXrIaGvupxFC+O1DAx4W
 rzBD8lX45B96WmIW2odg11KXXyPO1srW4ZFWghm95HTfvnQc3O6LmV9riv1k7DYA
 gR+aRYNiLO01UmoTPYbK
 =QFbC
 -----END PGP SIGNATURE-----

Merge tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.1 development cycle:

   - A new GPIO hogging mechanism has been added.  This can be used on
     boards that want to drive some GPIO line high, low, or set it as
     input on boot and then never touch it again.  For some embedded
     systems this is bliss and simplifies things to a great extent.

   - Some API cleanup and closure: gpiod_get_array() and
     gpiod_put_array() has been added to get and put GPIOs in bulk as
     was possible with the non-descriptor API.

   - Encapsulate cross-calls to the pin control subsystem in
     <linux/gpio/driver.h>.  Now this should be the only header any GPIO
     driver needs to include or something is wrong.  Cleanups
     restricting drivers to this include are welcomed if tested.

   - Sort the GPIO Kconfig and split it into submenus, as it was
     becoming and unstructured, illogical and unnavigatable mess.  I
     hope this is easier to follow.  Menus that require a certain
     subsystem like I2C can now be hidden nicely for example, still
     working on others.

   - New drivers:

       - New driver for the Altera Soft GPIO.

       - The F7188x driver now handles the F71869 and F71869A variants.

       - The MIPS Loongson driver has been moved to drivers/gpio for
         consolidation and cleanup.

   - Cleanups:

       - The MAX732x is converted to use the GPIOLIB_IRQCHIP
         infrastructure.

       - The PCF857x is converted to use the GPIOLIB_IRQCHIP
         infrastructure.

       - Radical cleanup of the OMAP driver.

   - Misc:

       - Enable the DWAPB GPIO for all architectures.  This is a "hard
         IP" block from Synopsys which has started to turn up in so
         diverse architectures as X86 Quark, ARC and a slew of ARM
         systems.  So even though it's not an expander, it's generic
         enough to be available for all.

       - We add a mock GPIO on Crystalcove PMIC after a long discussion
         with Daniel Vetter et al, tracing back to the shootout at the
         kernel summit where DRM drivers and sub-componentization was
         discussed.  In this case a mock GPIO is assumed to be the best
         compromise gaining some reuse of infrastructure without making
         DRM drivers overly complex at the same time.  Let's see"

* tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (62 commits)
  Revert "gpio: sch: use uapi/linux/pci_ids.h directly"
  gpio: dwapb: remove dependencies
  gpio: dwapb: enable for ARC
  gpio: removing kfree remove functionality
  gpio: mvebu: Fix mask/unmask managment per irq chip type
  gpio: split GPIO drivers in submenus
  gpio: move MFD GPIO drivers under their own comment
  gpio: move BCM Kona Kconfig option
  gpio: arrange SPI Kconfig symbols alphabetically
  gpio: arrange PCI GPIO controllers alphabetically
  gpio: arrange I2C Kconfig symbols alphabetically
  gpio: arrange Kconfig symbols alphabetically
  gpio: ich: Implement get_direction function
  gpio: use (!foo) instead of (foo == NULL)
  gpio: arizona: drop owner assignment from platform_drivers
  gpio: max7300: remove 'ret' variable
  gpio: use devm_kzalloc
  gpio: sch: use uapi/linux/pci_ids.h directly
  gpio: x-gene: fix devm_ioremap_resource() check
  gpio: loongson: Add Loongson-3A/3B GPIO driver support
  ...
2015-04-18 08:22:10 -04:00

169 lines
4.2 KiB
C

/*
* gpiolib support for Wolfson Arizona class devices
*
* Copyright 2012 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/slab.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>
struct arizona_gpio {
struct arizona *arizona;
struct gpio_chip gpio_chip;
};
static inline struct arizona_gpio *to_arizona_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct arizona_gpio, gpio_chip);
}
static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
struct arizona *arizona = arizona_gpio->arizona;
return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
ARIZONA_GPN_DIR, ARIZONA_GPN_DIR);
}
static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
struct arizona *arizona = arizona_gpio->arizona;
unsigned int val;
int ret;
ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val);
if (ret < 0)
return ret;
if (val & ARIZONA_GPN_LVL)
return 1;
else
return 0;
}
static int arizona_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value)
{
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
struct arizona *arizona = arizona_gpio->arizona;
if (value)
value = ARIZONA_GPN_LVL;
return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
ARIZONA_GPN_DIR | ARIZONA_GPN_LVL, value);
}
static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
struct arizona *arizona = arizona_gpio->arizona;
if (value)
value = ARIZONA_GPN_LVL;
regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
ARIZONA_GPN_LVL, value);
}
static struct gpio_chip template_chip = {
.label = "arizona",
.owner = THIS_MODULE,
.direction_input = arizona_gpio_direction_in,
.get = arizona_gpio_get,
.direction_output = arizona_gpio_direction_out,
.set = arizona_gpio_set,
.can_sleep = true,
};
static int arizona_gpio_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata = dev_get_platdata(arizona->dev);
struct arizona_gpio *arizona_gpio;
int ret;
arizona_gpio = devm_kzalloc(&pdev->dev, sizeof(*arizona_gpio),
GFP_KERNEL);
if (!arizona_gpio)
return -ENOMEM;
arizona_gpio->arizona = arizona;
arizona_gpio->gpio_chip = template_chip;
arizona_gpio->gpio_chip.dev = &pdev->dev;
#ifdef CONFIG_OF_GPIO
arizona_gpio->gpio_chip.of_node = arizona->dev->of_node;
#endif
switch (arizona->type) {
case WM5102:
case WM5110:
case WM8280:
case WM8997:
arizona_gpio->gpio_chip.ngpio = 5;
break;
default:
dev_err(&pdev->dev, "Unknown chip variant %d\n",
arizona->type);
return -EINVAL;
}
if (pdata && pdata->gpio_base)
arizona_gpio->gpio_chip.base = pdata->gpio_base;
else
arizona_gpio->gpio_chip.base = -1;
ret = gpiochip_add(&arizona_gpio->gpio_chip);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
ret);
goto err;
}
platform_set_drvdata(pdev, arizona_gpio);
return ret;
err:
return ret;
}
static int arizona_gpio_remove(struct platform_device *pdev)
{
struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
gpiochip_remove(&arizona_gpio->gpio_chip);
return 0;
}
static struct platform_driver arizona_gpio_driver = {
.driver.name = "arizona-gpio",
.probe = arizona_gpio_probe,
.remove = arizona_gpio_remove,
};
module_platform_driver(arizona_gpio_driver);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("GPIO interface for Arizona devices");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:arizona-gpio");