Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: Loongson1: add Loongson1 GPIO driver

This patch adds GPIO driver for Loongson1B.

Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Kelvin Cheung and committed by
Linus Walleij
bd37c999 6b5029d3

+110
+7
drivers/gpio/Kconfig
··· 511 511 help 512 512 Say yes here to support the GPIO device on ZTE ZX SoCs. 513 513 514 + config GPIO_LOONGSON1 515 + tristate "Loongson1 GPIO support" 516 + depends on MACH_LOONGSON32 517 + select GPIO_GENERIC 518 + help 519 + Say Y or M here to support GPIO on Loongson1 SoCs. 520 + 514 521 endmenu 515 522 516 523 menu "Port-mapped I/O GPIO drivers"
+1
drivers/gpio/Makefile
··· 127 127 obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o 128 128 obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o 129 129 obj-$(CONFIG_GPIO_ZX) += gpio-zx.o 130 + obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
+102
drivers/gpio/gpio-loongson1.c
··· 1 + /* 2 + * GPIO Driver for Loongson 1 SoC 3 + * 4 + * Copyright (C) 2015-2016 Zhang, Keguang <keguang.zhang@gmail.com> 5 + * 6 + * This file is licensed under the terms of the GNU General Public 7 + * License version 2. This program is licensed "as is" without any 8 + * warranty of any kind, whether express or implied. 9 + */ 10 + 11 + #include <linux/gpio/driver.h> 12 + #include <linux/platform_device.h> 13 + 14 + /* Loongson 1 GPIO Register Definitions */ 15 + #define GPIO_CFG 0x0 16 + #define GPIO_DIR 0x10 17 + #define GPIO_DATA 0x20 18 + #define GPIO_OUTPUT 0x30 19 + 20 + static void __iomem *gpio_reg_base; 21 + 22 + static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) 23 + { 24 + unsigned long pinmask = gc->pin2mask(gc, offset); 25 + unsigned long flags; 26 + 27 + spin_lock_irqsave(&gc->bgpio_lock, flags); 28 + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | pinmask, 29 + gpio_reg_base + GPIO_CFG); 30 + spin_unlock_irqrestore(&gc->bgpio_lock, flags); 31 + 32 + return 0; 33 + } 34 + 35 + static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset) 36 + { 37 + unsigned long pinmask = gc->pin2mask(gc, offset); 38 + unsigned long flags; 39 + 40 + spin_lock_irqsave(&gc->bgpio_lock, flags); 41 + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~pinmask, 42 + gpio_reg_base + GPIO_CFG); 43 + spin_unlock_irqrestore(&gc->bgpio_lock, flags); 44 + } 45 + 46 + static int ls1x_gpio_probe(struct platform_device *pdev) 47 + { 48 + struct device *dev = &pdev->dev; 49 + struct gpio_chip *gc; 50 + struct resource *res; 51 + int ret; 52 + 53 + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); 54 + if (!gc) 55 + return -ENOMEM; 56 + 57 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 58 + if (!res) { 59 + dev_err(dev, "failed to get I/O memory\n"); 60 + return -EINVAL; 61 + } 62 + 63 + gpio_reg_base = devm_ioremap_resource(dev, res); 64 + if (IS_ERR(gpio_reg_base)) 65 + return PTR_ERR(gpio_reg_base); 66 + 67 + ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA, 68 + gpio_reg_base + GPIO_OUTPUT, NULL, 69 + NULL, gpio_reg_base + GPIO_DIR, 0); 70 + if (ret) 71 + goto err; 72 + 73 + gc->owner = THIS_MODULE; 74 + gc->request = ls1x_gpio_request; 75 + gc->free = ls1x_gpio_free; 76 + gc->base = pdev->id * 32; 77 + 78 + ret = devm_gpiochip_add_data(dev, gc, NULL); 79 + if (ret) 80 + goto err; 81 + 82 + platform_set_drvdata(pdev, gc); 83 + dev_info(dev, "Loongson1 GPIO driver registered\n"); 84 + 85 + return 0; 86 + err: 87 + dev_err(dev, "failed to register GPIO device\n"); 88 + return ret; 89 + } 90 + 91 + static struct platform_driver ls1x_gpio_driver = { 92 + .probe = ls1x_gpio_probe, 93 + .driver = { 94 + .name = "ls1x-gpio", 95 + }, 96 + }; 97 + 98 + module_platform_driver(ls1x_gpio_driver); 99 + 100 + MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>"); 101 + MODULE_DESCRIPTION("Loongson1 GPIO driver"); 102 + MODULE_LICENSE("GPL");