linux/drivers/gpio/gpio-xgene-sb.c
<<
>>
Prefs
   1/*
   2 * AppliedMicro X-Gene SoC GPIO-Standby Driver
   3 *
   4 * Copyright (c) 2014, Applied Micro Circuits Corporation
   5 * Author:      Tin Huynh <tnhuynh@apm.com>.
   6 *              Y Vo <yvo@apm.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 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/io.h>
  24#include <linux/platform_device.h>
  25#include <linux/of_gpio.h>
  26#include <linux/gpio.h>
  27#include <linux/gpio/driver.h>
  28#include <linux/acpi.h>
  29#include <linux/basic_mmio_gpio.h>
  30
  31#include "gpiolib.h"
  32
  33#define XGENE_MAX_GPIO_DS               22
  34#define XGENE_MAX_GPIO_DS_IRQ           6
  35
  36#define GPIO_MASK(x)                    (1U << ((x) % 32))
  37
  38#define MPA_GPIO_INT_LVL                0x0290
  39#define MPA_GPIO_OE_ADDR                0x029c
  40#define MPA_GPIO_OUT_ADDR               0x02a0
  41#define MPA_GPIO_IN_ADDR                0x02a4
  42#define MPA_GPIO_SEL_LO                 0x0294
  43
  44/**
  45 * struct xgene_gpio_sb - GPIO-Standby private data structure.
  46 * @bgc:                        memory-mapped GPIO controllers.
  47 * @irq:                        Mapping GPIO pins and interrupt number
  48 * nirq:                        Number of GPIO pins that supports interrupt
  49 */
  50struct xgene_gpio_sb {
  51        struct bgpio_chip       bgc;
  52        u32 *irq;
  53        u32 nirq;
  54};
  55
  56static inline struct xgene_gpio_sb *to_xgene_gpio_sb(struct gpio_chip *gc)
  57{
  58        struct bgpio_chip *bgc = to_bgpio_chip(gc);
  59
  60        return container_of(bgc, struct xgene_gpio_sb, bgc);
  61}
  62
  63static void xgene_gpio_set_bit(struct bgpio_chip *bgc, void __iomem *reg, u32 gpio, int val)
  64{
  65        u32 data;
  66
  67        data = bgc->read_reg(reg);
  68        if (val)
  69                data |= GPIO_MASK(gpio);
  70        else
  71                data &= ~GPIO_MASK(gpio);
  72        bgc->write_reg(reg, data);
  73}
  74
  75static int apm_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
  76{
  77        struct xgene_gpio_sb *priv = to_xgene_gpio_sb(gc);
  78
  79        if (priv->irq[gpio])
  80                return priv->irq[gpio];
  81
  82        return -ENXIO;
  83}
  84
  85static int xgene_gpio_sb_probe(struct platform_device *pdev)
  86{
  87        struct xgene_gpio_sb *priv;
  88        u32 ret, i;
  89        u32 default_lines[] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D};
  90        struct resource *res;
  91        void __iomem *regs;
  92
  93        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  94        if (!priv)
  95                return -ENOMEM;
  96
  97        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  98        regs = devm_ioremap_resource(&pdev->dev, res);
  99        if (IS_ERR(regs))
 100                return PTR_ERR(regs);
 101
 102        ret = bgpio_init(&priv->bgc, &pdev->dev, 4,
 103                        regs + MPA_GPIO_IN_ADDR,
 104                        regs + MPA_GPIO_OUT_ADDR, NULL,
 105                        regs + MPA_GPIO_OE_ADDR, NULL, 0);
 106        if (ret)
 107                return ret;
 108
 109        priv->bgc.gc.to_irq = apm_gpio_sb_to_irq;
 110        priv->bgc.gc.ngpio = XGENE_MAX_GPIO_DS;
 111
 112        priv->nirq = XGENE_MAX_GPIO_DS_IRQ;
 113
 114        priv->irq = devm_kzalloc(&pdev->dev, sizeof(u32) * XGENE_MAX_GPIO_DS,
 115                                   GFP_KERNEL);
 116        if (!priv->irq)
 117                return -ENOMEM;
 118
 119        for (i = 0; i < priv->nirq; i++) {
 120                priv->irq[default_lines[i]] = platform_get_irq(pdev, i);
 121                xgene_gpio_set_bit(&priv->bgc, regs + MPA_GPIO_SEL_LO,
 122                                   default_lines[i] * 2, 1);
 123                xgene_gpio_set_bit(&priv->bgc, regs + MPA_GPIO_INT_LVL, i, 1);
 124        }
 125
 126        platform_set_drvdata(pdev, priv);
 127
 128        ret = gpiochip_add(&priv->bgc.gc);
 129        if (ret)
 130                dev_err(&pdev->dev, "failed to register X-Gene GPIO Standby driver\n");
 131        else
 132                dev_info(&pdev->dev, "X-Gene GPIO Standby driver registered\n");
 133
 134        if (priv->nirq > 0) {
 135                /* Register interrupt handlers for gpio signaled acpi events */
 136                acpi_gpiochip_request_interrupts(&priv->bgc.gc);
 137        }
 138
 139        return ret;
 140}
 141
 142static int xgene_gpio_sb_remove(struct platform_device *pdev)
 143{
 144        struct xgene_gpio_sb *priv = platform_get_drvdata(pdev);
 145
 146        if (priv->nirq > 0) {
 147                acpi_gpiochip_free_interrupts(&priv->bgc.gc);
 148        }
 149
 150        return bgpio_remove(&priv->bgc);
 151}
 152
 153static const struct of_device_id xgene_gpio_sb_of_match[] = {
 154        {.compatible = "apm,xgene-gpio-sb", },
 155        {},
 156};
 157MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match);
 158
 159#ifdef CONFIG_ACPI
 160static const struct acpi_device_id xgene_gpio_sb_acpi_match[] = {
 161        {"APMC0D15", 0},
 162        {},
 163};
 164MODULE_DEVICE_TABLE(acpi, xgene_gpio_sb_acpi_match);
 165#endif
 166
 167static struct platform_driver xgene_gpio_sb_driver = {
 168        .driver = {
 169                   .name = "xgene-gpio-sb",
 170                   .of_match_table = xgene_gpio_sb_of_match,
 171                   .acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match),
 172                   },
 173        .probe = xgene_gpio_sb_probe,
 174        .remove = xgene_gpio_sb_remove,
 175};
 176module_platform_driver(xgene_gpio_sb_driver);
 177
 178MODULE_AUTHOR("AppliedMicro");
 179MODULE_DESCRIPTION("APM X-Gene GPIO Standby driver");
 180MODULE_LICENSE("GPL");
 181