1 /* 2 * Driver for GE FPGA based GPIO 3 * 4 * Author: Martyn Welch <martyn.welch@ge.com> 5 * 6 * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc. 7 * 8 * This file is licensed under the terms of the GNU General Public License 9 * version 2. This program is licensed "as is" without any warranty of any 10 * kind, whether express or implied. 11 */ 12 13 /* TODO 14 * 15 * Configuration of output modes (totem-pole/open-drain) 16 * Interrupt configuration - interrupts are always generated the FPGA relies on 17 * the I/O interrupt controllers mask to stop them propergating 18 */ 19 20 #include <linux/kernel.h> 21 #include <linux/io.h> 22 #include <linux/of_device.h> 23 #include <linux/of_gpio.h> 24 #include <linux/module.h> 25 26 #define GEF_GPIO_DIRECT 0x00 27 #define GEF_GPIO_IN 0x04 28 #define GEF_GPIO_OUT 0x08 29 #define GEF_GPIO_TRIG 0x0C 30 #define GEF_GPIO_POLAR_A 0x10 31 #define GEF_GPIO_POLAR_B 0x14 32 #define GEF_GPIO_INT_STAT 0x18 33 #define GEF_GPIO_OVERRUN 0x1C 34 #define GEF_GPIO_MODE 0x20 35 36 static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 37 { 38 struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); 39 unsigned int data; 40 41 data = ioread32be(mmchip->regs + GEF_GPIO_OUT); 42 if (value) 43 data = data | BIT(offset); 44 else 45 data = data & ~BIT(offset); 46 iowrite32be(data, mmchip->regs + GEF_GPIO_OUT); 47 } 48 49 static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset) 50 { 51 unsigned int data; 52 struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); 53 54 data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT); 55 data = data | BIT(offset); 56 iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT); 57 58 return 0; 59 } 60 61 static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) 62 { 63 unsigned int data; 64 struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); 65 66 /* Set value before switching to output */ 67 gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); 68 69 data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT); 70 data = data & ~BIT(offset); 71 iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT); 72 73 return 0; 74 } 75 76 static int gef_gpio_get(struct gpio_chip *chip, unsigned offset) 77 { 78 struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); 79 80 return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset)); 81 } 82 83 static const struct of_device_id gef_gpio_ids[] = { 84 { 85 .compatible = "gef,sbc610-gpio", 86 .data = (void *)19, 87 }, { 88 .compatible = "gef,sbc310-gpio", 89 .data = (void *)6, 90 }, { 91 .compatible = "ge,imp3a-gpio", 92 .data = (void *)16, 93 }, 94 { } 95 }; 96 MODULE_DEVICE_TABLE(of, gef_gpio_ids); 97 98 static int __init gef_gpio_probe(struct platform_device *pdev) 99 { 100 const struct of_device_id *of_id = 101 of_match_device(gef_gpio_ids, &pdev->dev); 102 struct of_mm_gpio_chip *mmchip; 103 104 mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL); 105 if (!mmchip) 106 return -ENOMEM; 107 108 /* Setup pointers to chip functions */ 109 mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data; 110 mmchip->gc.of_gpio_n_cells = 2; 111 mmchip->gc.direction_input = gef_gpio_dir_in; 112 mmchip->gc.direction_output = gef_gpio_dir_out; 113 mmchip->gc.get = gef_gpio_get; 114 mmchip->gc.set = gef_gpio_set; 115 116 /* This function adds a memory mapped GPIO chip */ 117 return of_mm_gpiochip_add(pdev->dev.of_node, mmchip); 118 }; 119 120 static struct platform_driver gef_gpio_driver = { 121 .driver = { 122 .name = "gef-gpio", 123 .owner = THIS_MODULE, 124 .of_match_table = gef_gpio_ids, 125 }, 126 }; 127 module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe); 128 129 MODULE_DESCRIPTION("GE I/O FPGA GPIO driver"); 130 MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); 131 MODULE_LICENSE("GPL"); 132