Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AppliedMicro X-Gene SoC GPIO Driver
0004  *
0005  * Copyright (c) 2014, Applied Micro Circuits Corporation
0006  * Author: Feng Kan <fkan@apm.com>.
0007  */
0008 
0009 #include <linux/acpi.h>
0010 #include <linux/kernel.h>
0011 #include <linux/init.h>
0012 #include <linux/io.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/gpio/driver.h>
0016 #include <linux/types.h>
0017 #include <linux/bitops.h>
0018 
0019 #define GPIO_SET_DR_OFFSET  0x0C
0020 #define GPIO_DATA_OFFSET    0x14
0021 #define GPIO_BANK_STRIDE    0x0C
0022 
0023 #define XGENE_GPIOS_PER_BANK    16
0024 #define XGENE_MAX_GPIO_BANKS    3
0025 #define XGENE_MAX_GPIOS     (XGENE_GPIOS_PER_BANK * XGENE_MAX_GPIO_BANKS)
0026 
0027 #define GPIO_BIT_OFFSET(x)  (x % XGENE_GPIOS_PER_BANK)
0028 #define GPIO_BANK_OFFSET(x) ((x / XGENE_GPIOS_PER_BANK) * GPIO_BANK_STRIDE)
0029 
0030 struct xgene_gpio {
0031     struct gpio_chip    chip;
0032     void __iomem        *base;
0033     spinlock_t      lock;
0034     u32         set_dr_val[XGENE_MAX_GPIO_BANKS];
0035 };
0036 
0037 static int xgene_gpio_get(struct gpio_chip *gc, unsigned int offset)
0038 {
0039     struct xgene_gpio *chip = gpiochip_get_data(gc);
0040     unsigned long bank_offset;
0041     u32 bit_offset;
0042 
0043     bank_offset = GPIO_DATA_OFFSET + GPIO_BANK_OFFSET(offset);
0044     bit_offset = GPIO_BIT_OFFSET(offset);
0045     return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset));
0046 }
0047 
0048 static void __xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val)
0049 {
0050     struct xgene_gpio *chip = gpiochip_get_data(gc);
0051     unsigned long bank_offset;
0052     u32 setval, bit_offset;
0053 
0054     bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset);
0055     bit_offset = GPIO_BIT_OFFSET(offset) + XGENE_GPIOS_PER_BANK;
0056 
0057     setval = ioread32(chip->base + bank_offset);
0058     if (val)
0059         setval |= BIT(bit_offset);
0060     else
0061         setval &= ~BIT(bit_offset);
0062     iowrite32(setval, chip->base + bank_offset);
0063 }
0064 
0065 static void xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val)
0066 {
0067     struct xgene_gpio *chip = gpiochip_get_data(gc);
0068     unsigned long flags;
0069 
0070     spin_lock_irqsave(&chip->lock, flags);
0071     __xgene_gpio_set(gc, offset, val);
0072     spin_unlock_irqrestore(&chip->lock, flags);
0073 }
0074 
0075 static int xgene_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
0076 {
0077     struct xgene_gpio *chip = gpiochip_get_data(gc);
0078     unsigned long bank_offset, bit_offset;
0079 
0080     bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset);
0081     bit_offset = GPIO_BIT_OFFSET(offset);
0082 
0083     if (ioread32(chip->base + bank_offset) & BIT(bit_offset))
0084         return GPIO_LINE_DIRECTION_IN;
0085 
0086     return GPIO_LINE_DIRECTION_OUT;
0087 }
0088 
0089 static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
0090 {
0091     struct xgene_gpio *chip = gpiochip_get_data(gc);
0092     unsigned long flags, bank_offset;
0093     u32 dirval, bit_offset;
0094 
0095     bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset);
0096     bit_offset = GPIO_BIT_OFFSET(offset);
0097 
0098     spin_lock_irqsave(&chip->lock, flags);
0099 
0100     dirval = ioread32(chip->base + bank_offset);
0101     dirval |= BIT(bit_offset);
0102     iowrite32(dirval, chip->base + bank_offset);
0103 
0104     spin_unlock_irqrestore(&chip->lock, flags);
0105 
0106     return 0;
0107 }
0108 
0109 static int xgene_gpio_dir_out(struct gpio_chip *gc,
0110                     unsigned int offset, int val)
0111 {
0112     struct xgene_gpio *chip = gpiochip_get_data(gc);
0113     unsigned long flags, bank_offset;
0114     u32 dirval, bit_offset;
0115 
0116     bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset);
0117     bit_offset = GPIO_BIT_OFFSET(offset);
0118 
0119     spin_lock_irqsave(&chip->lock, flags);
0120 
0121     dirval = ioread32(chip->base + bank_offset);
0122     dirval &= ~BIT(bit_offset);
0123     iowrite32(dirval, chip->base + bank_offset);
0124     __xgene_gpio_set(gc, offset, val);
0125 
0126     spin_unlock_irqrestore(&chip->lock, flags);
0127 
0128     return 0;
0129 }
0130 
0131 static __maybe_unused int xgene_gpio_suspend(struct device *dev)
0132 {
0133     struct xgene_gpio *gpio = dev_get_drvdata(dev);
0134     unsigned long bank_offset;
0135     unsigned int bank;
0136 
0137     for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) {
0138         bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE;
0139         gpio->set_dr_val[bank] = ioread32(gpio->base + bank_offset);
0140     }
0141     return 0;
0142 }
0143 
0144 static __maybe_unused int xgene_gpio_resume(struct device *dev)
0145 {
0146     struct xgene_gpio *gpio = dev_get_drvdata(dev);
0147     unsigned long bank_offset;
0148     unsigned int bank;
0149 
0150     for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) {
0151         bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE;
0152         iowrite32(gpio->set_dr_val[bank], gpio->base + bank_offset);
0153     }
0154     return 0;
0155 }
0156 
0157 static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume);
0158 
0159 static int xgene_gpio_probe(struct platform_device *pdev)
0160 {
0161     struct xgene_gpio *gpio;
0162 
0163     gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
0164     if (!gpio)
0165         return -ENOMEM;
0166 
0167     gpio->base = devm_platform_ioremap_resource(pdev, 0);
0168     if (IS_ERR(gpio->base))
0169         return PTR_ERR(gpio->base);
0170 
0171     gpio->chip.ngpio = XGENE_MAX_GPIOS;
0172 
0173     spin_lock_init(&gpio->lock);
0174     gpio->chip.parent = &pdev->dev;
0175     gpio->chip.get_direction = xgene_gpio_get_direction;
0176     gpio->chip.direction_input = xgene_gpio_dir_in;
0177     gpio->chip.direction_output = xgene_gpio_dir_out;
0178     gpio->chip.get = xgene_gpio_get;
0179     gpio->chip.set = xgene_gpio_set;
0180     gpio->chip.label = dev_name(&pdev->dev);
0181     gpio->chip.base = -1;
0182 
0183     platform_set_drvdata(pdev, gpio);
0184 
0185     return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
0186 }
0187 
0188 static const struct of_device_id xgene_gpio_of_match[] = {
0189     { .compatible = "apm,xgene-gpio", },
0190     {},
0191 };
0192 
0193 #ifdef CONFIG_ACPI
0194 static const struct acpi_device_id xgene_gpio_acpi_match[] = {
0195     { "APMC0D14", 0 },
0196     { },
0197 };
0198 #endif
0199 
0200 static struct platform_driver xgene_gpio_driver = {
0201     .driver = {
0202         .name = "xgene-gpio",
0203         .of_match_table = xgene_gpio_of_match,
0204         .acpi_match_table = ACPI_PTR(xgene_gpio_acpi_match),
0205         .pm     = &xgene_gpio_pm,
0206     },
0207     .probe = xgene_gpio_probe,
0208 };
0209 builtin_platform_driver(xgene_gpio_driver);