Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | /* * Driver for GE FPGA based GPIO * * Author: Martyn Welch <martyn.welch@ge.com> * * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc. * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. */ /* TODO * * Configuration of output modes (totem-pole/open-drain) * Interrupt configuration - interrupts are always generated the FPGA relies on * the I/O interrupt controllers mask to stop them propergating */ #include <linux/kernel.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/of_address.h> #include <linux/module.h> #include <linux/basic_mmio_gpio.h> #define GEF_GPIO_DIRECT 0x00 #define GEF_GPIO_IN 0x04 #define GEF_GPIO_OUT 0x08 #define GEF_GPIO_TRIG 0x0C #define GEF_GPIO_POLAR_A 0x10 #define GEF_GPIO_POLAR_B 0x14 #define GEF_GPIO_INT_STAT 0x18 #define GEF_GPIO_OVERRUN 0x1C #define GEF_GPIO_MODE 0x20 static const struct of_device_id gef_gpio_ids[] = { { .compatible = "gef,sbc610-gpio", .data = (void *)19, }, { .compatible = "gef,sbc310-gpio", .data = (void *)6, }, { .compatible = "ge,imp3a-gpio", .data = (void *)16, }, { } }; MODULE_DEVICE_TABLE(of, gef_gpio_ids); static int __init gef_gpio_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(gef_gpio_ids, &pdev->dev); struct bgpio_chip *bgc; void __iomem *regs; int ret; bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); if (!bgc) return -ENOMEM; regs = of_iomap(pdev->dev.of_node, 0); if (!regs) return -ENOMEM; ret = bgpio_init(bgc, &pdev->dev, 4, regs + GEF_GPIO_IN, regs + GEF_GPIO_OUT, NULL, NULL, regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER); if (ret) { dev_err(&pdev->dev, "bgpio_init failed\n"); goto err0; } /* Setup pointers to chip functions */ bgc->gc.label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name, GFP_KERNEL); if (!bgc->gc.label) { ret = -ENOMEM; goto err0; } bgc->gc.base = -1; bgc->gc.ngpio = (u16)(uintptr_t)of_id->data; bgc->gc.of_gpio_n_cells = 2; bgc->gc.of_node = pdev->dev.of_node; /* This function adds a memory mapped GPIO chip */ ret = gpiochip_add(&bgc->gc); if (ret) goto err0; return 0; err0: iounmap(regs); pr_err("%s: GPIO chip registration failed\n", pdev->dev.of_node->full_name); return ret; }; static struct platform_driver gef_gpio_driver = { .driver = { .name = "gef-gpio", .of_match_table = gef_gpio_ids, }, }; module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe); MODULE_DESCRIPTION("GE I/O FPGA GPIO driver"); MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); MODULE_LICENSE("GPL"); |