129cbf458SFeng Kan /* 229cbf458SFeng Kan * AppliedMicro X-Gene SoC GPIO Driver 329cbf458SFeng Kan * 429cbf458SFeng Kan * Copyright (c) 2014, Applied Micro Circuits Corporation 529cbf458SFeng Kan * Author: Feng Kan <fkan@apm.com>. 629cbf458SFeng Kan * 729cbf458SFeng Kan * This program is free software; you can redistribute it and/or modify 829cbf458SFeng Kan * it under the terms of the GNU General Public License version 2 as 929cbf458SFeng Kan * published by the Free Software Foundation. 1029cbf458SFeng Kan * 1129cbf458SFeng Kan * This program is distributed in the hope that it will be useful, 1229cbf458SFeng Kan * but WITHOUT ANY WARRANTY; without even the implied warranty of 1329cbf458SFeng Kan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1429cbf458SFeng Kan * GNU General Public License for more details. 1529cbf458SFeng Kan * 1629cbf458SFeng Kan * You should have received a copy of the GNU General Public License 1729cbf458SFeng Kan * along with this program. If not, see <http://www.gnu.org/licenses/>. 1829cbf458SFeng Kan */ 1929cbf458SFeng Kan 2029cbf458SFeng Kan #include <linux/module.h> 2129cbf458SFeng Kan #include <linux/kernel.h> 2229cbf458SFeng Kan #include <linux/init.h> 2329cbf458SFeng Kan #include <linux/io.h> 2429cbf458SFeng Kan #include <linux/spinlock.h> 2529cbf458SFeng Kan #include <linux/platform_device.h> 2629cbf458SFeng Kan #include <linux/gpio/driver.h> 2729cbf458SFeng Kan #include <linux/types.h> 2829cbf458SFeng Kan #include <linux/bitops.h> 2929cbf458SFeng Kan 3029cbf458SFeng Kan #define GPIO_SET_DR_OFFSET 0x0C 3129cbf458SFeng Kan #define GPIO_DATA_OFFSET 0x14 3229cbf458SFeng Kan #define GPIO_BANK_STRIDE 0x0C 3329cbf458SFeng Kan 3429cbf458SFeng Kan #define XGENE_GPIOS_PER_BANK 16 3529cbf458SFeng Kan #define XGENE_MAX_GPIO_BANKS 3 3629cbf458SFeng Kan #define XGENE_MAX_GPIOS (XGENE_GPIOS_PER_BANK * XGENE_MAX_GPIO_BANKS) 3729cbf458SFeng Kan 3829cbf458SFeng Kan #define GPIO_BIT_OFFSET(x) (x % XGENE_GPIOS_PER_BANK) 3929cbf458SFeng Kan #define GPIO_BANK_OFFSET(x) ((x / XGENE_GPIOS_PER_BANK) * GPIO_BANK_STRIDE) 4029cbf458SFeng Kan 4129cbf458SFeng Kan struct xgene_gpio; 4229cbf458SFeng Kan 4329cbf458SFeng Kan struct xgene_gpio { 4429cbf458SFeng Kan struct gpio_chip chip; 4529cbf458SFeng Kan void __iomem *base; 4629cbf458SFeng Kan spinlock_t lock; 4729cbf458SFeng Kan #ifdef CONFIG_PM 4829cbf458SFeng Kan u32 set_dr_val[XGENE_MAX_GPIO_BANKS]; 4929cbf458SFeng Kan #endif 5029cbf458SFeng Kan }; 5129cbf458SFeng Kan 5229cbf458SFeng Kan static inline struct xgene_gpio *to_xgene_gpio(struct gpio_chip *chip) 5329cbf458SFeng Kan { 5429cbf458SFeng Kan return container_of(chip, struct xgene_gpio, chip); 5529cbf458SFeng Kan } 5629cbf458SFeng Kan 5729cbf458SFeng Kan static int xgene_gpio_get(struct gpio_chip *gc, unsigned int offset) 5829cbf458SFeng Kan { 5929cbf458SFeng Kan struct xgene_gpio *chip = to_xgene_gpio(gc); 6029cbf458SFeng Kan unsigned long bank_offset; 6129cbf458SFeng Kan u32 bit_offset; 6229cbf458SFeng Kan 6329cbf458SFeng Kan bank_offset = GPIO_DATA_OFFSET + GPIO_BANK_OFFSET(offset); 6429cbf458SFeng Kan bit_offset = GPIO_BIT_OFFSET(offset); 6529cbf458SFeng Kan return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset)); 6629cbf458SFeng Kan } 6729cbf458SFeng Kan 6829cbf458SFeng Kan static void __xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) 6929cbf458SFeng Kan { 7029cbf458SFeng Kan struct xgene_gpio *chip = to_xgene_gpio(gc); 7129cbf458SFeng Kan unsigned long bank_offset; 7229cbf458SFeng Kan u32 setval, bit_offset; 7329cbf458SFeng Kan 7429cbf458SFeng Kan bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); 7529cbf458SFeng Kan bit_offset = GPIO_BIT_OFFSET(offset) + XGENE_GPIOS_PER_BANK; 7629cbf458SFeng Kan 7729cbf458SFeng Kan setval = ioread32(chip->base + bank_offset); 7829cbf458SFeng Kan if (val) 7929cbf458SFeng Kan setval |= BIT(bit_offset); 8029cbf458SFeng Kan else 8129cbf458SFeng Kan setval &= ~BIT(bit_offset); 8229cbf458SFeng Kan iowrite32(setval, chip->base + bank_offset); 8329cbf458SFeng Kan } 8429cbf458SFeng Kan 8529cbf458SFeng Kan static void xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) 8629cbf458SFeng Kan { 8729cbf458SFeng Kan struct xgene_gpio *chip = to_xgene_gpio(gc); 8829cbf458SFeng Kan unsigned long flags; 8929cbf458SFeng Kan 9029cbf458SFeng Kan spin_lock_irqsave(&chip->lock, flags); 9129cbf458SFeng Kan __xgene_gpio_set(gc, offset, val); 9229cbf458SFeng Kan spin_unlock_irqrestore(&chip->lock, flags); 9329cbf458SFeng Kan } 9429cbf458SFeng Kan 9529cbf458SFeng Kan static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) 9629cbf458SFeng Kan { 9729cbf458SFeng Kan struct xgene_gpio *chip = to_xgene_gpio(gc); 9829cbf458SFeng Kan unsigned long flags, bank_offset; 9929cbf458SFeng Kan u32 dirval, bit_offset; 10029cbf458SFeng Kan 10129cbf458SFeng Kan bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); 10229cbf458SFeng Kan bit_offset = GPIO_BIT_OFFSET(offset); 10329cbf458SFeng Kan 10429cbf458SFeng Kan spin_lock_irqsave(&chip->lock, flags); 10529cbf458SFeng Kan 10629cbf458SFeng Kan dirval = ioread32(chip->base + bank_offset); 10729cbf458SFeng Kan dirval |= BIT(bit_offset); 10829cbf458SFeng Kan iowrite32(dirval, chip->base + bank_offset); 10929cbf458SFeng Kan 11029cbf458SFeng Kan spin_unlock_irqrestore(&chip->lock, flags); 11129cbf458SFeng Kan 11229cbf458SFeng Kan return 0; 11329cbf458SFeng Kan } 11429cbf458SFeng Kan 11529cbf458SFeng Kan static int xgene_gpio_dir_out(struct gpio_chip *gc, 11629cbf458SFeng Kan unsigned int offset, int val) 11729cbf458SFeng Kan { 11829cbf458SFeng Kan struct xgene_gpio *chip = to_xgene_gpio(gc); 11929cbf458SFeng Kan unsigned long flags, bank_offset; 12029cbf458SFeng Kan u32 dirval, bit_offset; 12129cbf458SFeng Kan 12229cbf458SFeng Kan bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); 12329cbf458SFeng Kan bit_offset = GPIO_BIT_OFFSET(offset); 12429cbf458SFeng Kan 12529cbf458SFeng Kan spin_lock_irqsave(&chip->lock, flags); 12629cbf458SFeng Kan 12729cbf458SFeng Kan dirval = ioread32(chip->base + bank_offset); 12829cbf458SFeng Kan dirval &= ~BIT(bit_offset); 12929cbf458SFeng Kan iowrite32(dirval, chip->base + bank_offset); 13029cbf458SFeng Kan __xgene_gpio_set(gc, offset, val); 13129cbf458SFeng Kan 13229cbf458SFeng Kan spin_unlock_irqrestore(&chip->lock, flags); 13329cbf458SFeng Kan 13429cbf458SFeng Kan return 0; 13529cbf458SFeng Kan } 13629cbf458SFeng Kan 13729cbf458SFeng Kan #ifdef CONFIG_PM 13829cbf458SFeng Kan static int xgene_gpio_suspend(struct device *dev) 13929cbf458SFeng Kan { 14029cbf458SFeng Kan struct xgene_gpio *gpio = dev_get_drvdata(dev); 14129cbf458SFeng Kan unsigned long bank_offset; 14229cbf458SFeng Kan unsigned int bank; 14329cbf458SFeng Kan 14429cbf458SFeng Kan for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) { 14529cbf458SFeng Kan bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE; 14629cbf458SFeng Kan gpio->set_dr_val[bank] = ioread32(gpio->base + bank_offset); 14729cbf458SFeng Kan } 14829cbf458SFeng Kan return 0; 14929cbf458SFeng Kan } 15029cbf458SFeng Kan 15129cbf458SFeng Kan static int xgene_gpio_resume(struct device *dev) 15229cbf458SFeng Kan { 15329cbf458SFeng Kan struct xgene_gpio *gpio = dev_get_drvdata(dev); 15429cbf458SFeng Kan unsigned long bank_offset; 15529cbf458SFeng Kan unsigned int bank; 15629cbf458SFeng Kan 15729cbf458SFeng Kan for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) { 15829cbf458SFeng Kan bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE; 15929cbf458SFeng Kan iowrite32(gpio->set_dr_val[bank], gpio->base + bank_offset); 16029cbf458SFeng Kan } 16129cbf458SFeng Kan return 0; 16229cbf458SFeng Kan } 16329cbf458SFeng Kan 16429cbf458SFeng Kan static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); 16529cbf458SFeng Kan #define XGENE_GPIO_PM_OPS (&xgene_gpio_pm) 16629cbf458SFeng Kan #else 16729cbf458SFeng Kan #define XGENE_GPIO_PM_OPS NULL 16829cbf458SFeng Kan #endif 16929cbf458SFeng Kan 17029cbf458SFeng Kan static int xgene_gpio_probe(struct platform_device *pdev) 17129cbf458SFeng Kan { 17229cbf458SFeng Kan struct resource *res; 17329cbf458SFeng Kan struct xgene_gpio *gpio; 17429cbf458SFeng Kan int err = 0; 17529cbf458SFeng Kan 17629cbf458SFeng Kan gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 17729cbf458SFeng Kan if (!gpio) { 17829cbf458SFeng Kan err = -ENOMEM; 17929cbf458SFeng Kan goto err; 18029cbf458SFeng Kan } 18129cbf458SFeng Kan 18229cbf458SFeng Kan res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 18329cbf458SFeng Kan gpio->base = devm_ioremap_nocache(&pdev->dev, res->start, 18429cbf458SFeng Kan resource_size(res)); 18529cbf458SFeng Kan if (IS_ERR(gpio->base)) { 18629cbf458SFeng Kan err = PTR_ERR(gpio->base); 18729cbf458SFeng Kan goto err; 18829cbf458SFeng Kan } 18929cbf458SFeng Kan 19029cbf458SFeng Kan gpio->chip.ngpio = XGENE_MAX_GPIOS; 19129cbf458SFeng Kan 19229cbf458SFeng Kan gpio->chip.dev = &pdev->dev; 19329cbf458SFeng Kan gpio->chip.direction_input = xgene_gpio_dir_in; 19429cbf458SFeng Kan gpio->chip.direction_output = xgene_gpio_dir_out; 19529cbf458SFeng Kan gpio->chip.get = xgene_gpio_get; 19629cbf458SFeng Kan gpio->chip.set = xgene_gpio_set; 19729cbf458SFeng Kan gpio->chip.label = dev_name(&pdev->dev); 19829cbf458SFeng Kan gpio->chip.base = -1; 19929cbf458SFeng Kan 20029cbf458SFeng Kan platform_set_drvdata(pdev, gpio); 20129cbf458SFeng Kan 20229cbf458SFeng Kan err = gpiochip_add(&gpio->chip); 20329cbf458SFeng Kan if (err) { 20429cbf458SFeng Kan dev_err(&pdev->dev, 20529cbf458SFeng Kan "failed to register gpiochip.\n"); 20629cbf458SFeng Kan goto err; 20729cbf458SFeng Kan } 20829cbf458SFeng Kan 20929cbf458SFeng Kan dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); 21029cbf458SFeng Kan return 0; 21129cbf458SFeng Kan err: 21229cbf458SFeng Kan dev_err(&pdev->dev, "X-Gene GPIO driver registration failed.\n"); 21329cbf458SFeng Kan return err; 21429cbf458SFeng Kan } 21529cbf458SFeng Kan 21629cbf458SFeng Kan static int xgene_gpio_remove(struct platform_device *pdev) 21729cbf458SFeng Kan { 21829cbf458SFeng Kan struct xgene_gpio *gpio = platform_get_drvdata(pdev); 21929cbf458SFeng Kan int ret = 0; 22029cbf458SFeng Kan 22129cbf458SFeng Kan ret = gpiochip_remove(&gpio->chip); 22229cbf458SFeng Kan if (ret) 22329cbf458SFeng Kan dev_err(&pdev->dev, "unable to remove gpio_chip.\n"); 22429cbf458SFeng Kan return ret; 22529cbf458SFeng Kan } 22629cbf458SFeng Kan 22729cbf458SFeng Kan #ifdef CONFIG_OF 22829cbf458SFeng Kan static const struct of_device_id xgene_gpio_of_match[] = { 22929cbf458SFeng Kan { .compatible = "apm,xgene-gpio", }, 23029cbf458SFeng Kan {}, 23129cbf458SFeng Kan }; 23229cbf458SFeng Kan MODULE_DEVICE_TABLE(of, xgene_gpio_of_match); 23329cbf458SFeng Kan #endif 23429cbf458SFeng Kan 23529cbf458SFeng Kan static struct platform_driver xgene_gpio_driver = { 23629cbf458SFeng Kan .driver = { 23729cbf458SFeng Kan .name = "xgene-gpio", 23829cbf458SFeng Kan .owner = THIS_MODULE, 23929cbf458SFeng Kan .of_match_table = xgene_gpio_of_match, 24029cbf458SFeng Kan .pm = XGENE_GPIO_PM_OPS, 24129cbf458SFeng Kan }, 24229cbf458SFeng Kan .probe = xgene_gpio_probe, 24329cbf458SFeng Kan .remove = xgene_gpio_remove, 24429cbf458SFeng Kan }; 24529cbf458SFeng Kan 24629cbf458SFeng Kan module_platform_driver(xgene_gpio_driver); 24729cbf458SFeng Kan 24829cbf458SFeng Kan MODULE_AUTHOR("Feng Kan <fkan@apm.com>"); 24929cbf458SFeng Kan MODULE_DESCRIPTION("APM X-Gene GPIO driver"); 25029cbf458SFeng Kan MODULE_LICENSE("GPL"); 251