0001
0002
0003
0004
0005
0006
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);