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

gpio: add ETRAXFS GPIO driver

Add a GPIO driver for the General I/O block on Axis ETRAX FS SoCs.

Signed-off-by: Rabin Vincent <rabin@rab.in>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Rabin Vincent and committed by
Linus Walleij
d342571e e2bfba41

+206
+21
Documentation/devicetree/bindings/gpio/gpio-etraxfs.txt
··· 1 + Axis ETRAX FS General I/O controller bindings 2 + 3 + Required properties: 4 + 5 + - compatible: 6 + - "axis,etraxfs-gio" 7 + - reg: Physical base address and length of the controller's registers. 8 + - #gpio-cells: Should be 3 9 + - The first cell is the gpio offset number. 10 + - The second cell is reserved and is currently unused. 11 + - The third cell is the port number (hex). 12 + - gpio-controller: Marks the device node as a GPIO controller. 13 + 14 + Example: 15 + 16 + gio: gpio@b001a000 { 17 + compatible = "axis,etraxfs-gio"; 18 + reg = <0xb001a000 0x1000>; 19 + gpio-controller; 20 + #gpio-cells = <3>; 21 + };
+8
drivers/gpio/Kconfig
··· 167 167 depends on ARCH_EP93XX 168 168 select GPIO_GENERIC 169 169 170 + config GPIO_ETRAXFS 171 + bool "Axis ETRAX FS General I/O" 172 + depends on CRIS || COMPILE_TEST 173 + depends on OF 174 + select GPIO_GENERIC 175 + help 176 + Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. 177 + 170 178 config GPIO_F7188X 171 179 tristate "F71869, F71869A, F71882FG and F71889F GPIO support" 172 180 depends on X86
+1
drivers/gpio/Makefile
··· 33 33 obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o 34 34 obj-$(CONFIG_GPIO_EM) += gpio-em.o 35 35 obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o 36 + obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o 36 37 obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o 37 38 obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o 38 39 obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
+176
drivers/gpio/gpio-etraxfs.c
··· 1 + #include <linux/kernel.h> 2 + #include <linux/init.h> 3 + #include <linux/gpio.h> 4 + #include <linux/of_gpio.h> 5 + #include <linux/io.h> 6 + #include <linux/platform_device.h> 7 + #include <linux/basic_mmio_gpio.h> 8 + 9 + #define ETRAX_FS_rw_pa_dout 0 10 + #define ETRAX_FS_r_pa_din 4 11 + #define ETRAX_FS_rw_pa_oe 8 12 + #define ETRAX_FS_rw_intr_cfg 12 13 + #define ETRAX_FS_rw_intr_mask 16 14 + #define ETRAX_FS_rw_ack_intr 20 15 + #define ETRAX_FS_r_intr 24 16 + #define ETRAX_FS_rw_pb_dout 32 17 + #define ETRAX_FS_r_pb_din 36 18 + #define ETRAX_FS_rw_pb_oe 40 19 + #define ETRAX_FS_rw_pc_dout 48 20 + #define ETRAX_FS_r_pc_din 52 21 + #define ETRAX_FS_rw_pc_oe 56 22 + #define ETRAX_FS_rw_pd_dout 64 23 + #define ETRAX_FS_r_pd_din 68 24 + #define ETRAX_FS_rw_pd_oe 72 25 + #define ETRAX_FS_rw_pe_dout 80 26 + #define ETRAX_FS_r_pe_din 84 27 + #define ETRAX_FS_rw_pe_oe 88 28 + 29 + struct etraxfs_gpio_port { 30 + const char *label; 31 + unsigned int oe; 32 + unsigned int dout; 33 + unsigned int din; 34 + unsigned int ngpio; 35 + }; 36 + 37 + struct etraxfs_gpio_info { 38 + unsigned int num_ports; 39 + const struct etraxfs_gpio_port *ports; 40 + }; 41 + 42 + static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = { 43 + { 44 + .label = "A", 45 + .ngpio = 8, 46 + .oe = ETRAX_FS_rw_pa_oe, 47 + .dout = ETRAX_FS_rw_pa_dout, 48 + .din = ETRAX_FS_r_pa_din, 49 + }, 50 + { 51 + .label = "B", 52 + .ngpio = 18, 53 + .oe = ETRAX_FS_rw_pb_oe, 54 + .dout = ETRAX_FS_rw_pb_dout, 55 + .din = ETRAX_FS_r_pb_din, 56 + }, 57 + { 58 + .label = "C", 59 + .ngpio = 18, 60 + .oe = ETRAX_FS_rw_pc_oe, 61 + .dout = ETRAX_FS_rw_pc_dout, 62 + .din = ETRAX_FS_r_pc_din, 63 + }, 64 + { 65 + .label = "D", 66 + .ngpio = 18, 67 + .oe = ETRAX_FS_rw_pd_oe, 68 + .dout = ETRAX_FS_rw_pd_dout, 69 + .din = ETRAX_FS_r_pd_din, 70 + }, 71 + { 72 + .label = "E", 73 + .ngpio = 18, 74 + .oe = ETRAX_FS_rw_pe_oe, 75 + .dout = ETRAX_FS_rw_pe_dout, 76 + .din = ETRAX_FS_r_pe_din, 77 + }, 78 + }; 79 + 80 + static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = { 81 + .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports), 82 + .ports = etraxfs_gpio_etraxfs_ports, 83 + }; 84 + 85 + static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, 86 + const struct of_phandle_args *gpiospec, 87 + u32 *flags) 88 + { 89 + /* 90 + * Port numbers are A to E, and the properties are integers, so we 91 + * specify them as 0xA - 0xE. 92 + */ 93 + if (gc->label[0] - 'A' + 0xA != gpiospec->args[2]) 94 + return -EINVAL; 95 + 96 + return of_gpio_simple_xlate(gc, gpiospec, flags); 97 + } 98 + 99 + static const struct of_device_id etraxfs_gpio_of_table[] = { 100 + { 101 + .compatible = "axis,etraxfs-gio", 102 + .data = &etraxfs_gpio_etraxfs, 103 + }, 104 + {}, 105 + }; 106 + 107 + static int etraxfs_gpio_probe(struct platform_device *pdev) 108 + { 109 + struct device *dev = &pdev->dev; 110 + const struct etraxfs_gpio_info *info; 111 + const struct of_device_id *match; 112 + struct bgpio_chip *chips; 113 + struct resource *res; 114 + void __iomem *regs; 115 + int ret; 116 + int i; 117 + 118 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 119 + regs = devm_ioremap_resource(dev, res); 120 + if (!regs) 121 + return -ENOMEM; 122 + 123 + match = of_match_node(etraxfs_gpio_of_table, dev->of_node); 124 + if (!match) 125 + return -EINVAL; 126 + 127 + info = match->data; 128 + 129 + chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL); 130 + if (!chips) 131 + return -ENOMEM; 132 + 133 + for (i = 0; i < info->num_ports; i++) { 134 + struct bgpio_chip *bgc = &chips[i]; 135 + const struct etraxfs_gpio_port *port = &info->ports[i]; 136 + 137 + ret = bgpio_init(bgc, dev, 4, 138 + regs + port->din, /* dat */ 139 + regs + port->dout, /* set */ 140 + NULL, /* clr */ 141 + regs + port->oe, /* dirout */ 142 + NULL, /* dirin */ 143 + BGPIOF_UNREADABLE_REG_SET); 144 + if (ret) 145 + return ret; 146 + 147 + bgc->gc.ngpio = port->ngpio; 148 + bgc->gc.label = port->label; 149 + 150 + bgc->gc.of_node = dev->of_node; 151 + bgc->gc.of_gpio_n_cells = 3; 152 + bgc->gc.of_xlate = etraxfs_gpio_of_xlate; 153 + 154 + ret = gpiochip_add(&bgc->gc); 155 + if (ret) 156 + dev_err(dev, "Unable to register port %s\n", 157 + bgc->gc.label); 158 + } 159 + 160 + return 0; 161 + } 162 + 163 + static struct platform_driver etraxfs_gpio_driver = { 164 + .driver = { 165 + .name = "etraxfs-gpio", 166 + .of_match_table = of_match_ptr(etraxfs_gpio_of_table), 167 + }, 168 + .probe = etraxfs_gpio_probe, 169 + }; 170 + 171 + static int __init etraxfs_gpio_init(void) 172 + { 173 + return platform_driver_register(&etraxfs_gpio_driver); 174 + } 175 + 176 + device_initcall(etraxfs_gpio_init);