1 /* 2 * GPIO interface for Intel Sodaville SoCs. 3 * 4 * Copyright (c) 2010, 2011 Intel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License 2 as published 8 * by the Free Software Foundation. 9 * 10 */ 11 12 #include <linux/errno.h> 13 #include <linux/gpio.h> 14 #include <linux/init.h> 15 #include <linux/io.h> 16 #include <linux/irq.h> 17 #include <linux/interrupt.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/pci.h> 21 #include <linux/platform_device.h> 22 #include <linux/of_irq.h> 23 #include <linux/basic_mmio_gpio.h> 24 25 #define DRV_NAME "sdv_gpio" 26 #define SDV_NUM_PUB_GPIOS 12 27 #define PCI_DEVICE_ID_SDV_GPIO 0x2e67 28 #define GPIO_BAR 0 29 30 #define GPOUTR 0x00 31 #define GPOER 0x04 32 #define GPINR 0x08 33 34 #define GPSTR 0x0c 35 #define GPIT1R0 0x10 36 #define GPIO_INT 0x14 37 #define GPIT1R1 0x18 38 39 #define GPMUXCTL 0x1c 40 41 struct sdv_gpio_chip_data { 42 int irq_base; 43 void __iomem *gpio_pub_base; 44 struct irq_domain *id; 45 struct irq_chip_generic *gc; 46 struct bgpio_chip bgpio; 47 }; 48 49 static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type) 50 { 51 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 52 struct sdv_gpio_chip_data *sd = gc->private; 53 void __iomem *type_reg; 54 u32 reg; 55 56 if (d->hwirq < 8) 57 type_reg = sd->gpio_pub_base + GPIT1R0; 58 else 59 type_reg = sd->gpio_pub_base + GPIT1R1; 60 61 reg = readl(type_reg); 62 63 switch (type) { 64 case IRQ_TYPE_LEVEL_HIGH: 65 reg &= ~BIT(4 * (d->hwirq % 8)); 66 break; 67 68 case IRQ_TYPE_LEVEL_LOW: 69 reg |= BIT(4 * (d->hwirq % 8)); 70 break; 71 72 default: 73 return -EINVAL; 74 } 75 76 writel(reg, type_reg); 77 return 0; 78 } 79 80 static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data) 81 { 82 struct sdv_gpio_chip_data *sd = data; 83 u32 irq_stat = readl(sd->gpio_pub_base + GPSTR); 84 85 irq_stat &= readl(sd->gpio_pub_base + GPIO_INT); 86 if (!irq_stat) 87 return IRQ_NONE; 88 89 while (irq_stat) { 90 u32 irq_bit = __fls(irq_stat); 91 92 irq_stat &= ~BIT(irq_bit); 93 generic_handle_irq(irq_find_mapping(sd->id, irq_bit)); 94 } 95 96 return IRQ_HANDLED; 97 } 98 99 static int sdv_xlate(struct irq_domain *h, struct device_node *node, 100 const u32 *intspec, u32 intsize, irq_hw_number_t *out_hwirq, 101 u32 *out_type) 102 { 103 u32 line, type; 104 105 if (node != h->of_node) 106 return -EINVAL; 107 108 if (intsize < 2) 109 return -EINVAL; 110 111 line = *intspec; 112 *out_hwirq = line; 113 114 intspec++; 115 type = *intspec; 116 117 switch (type) { 118 case IRQ_TYPE_LEVEL_LOW: 119 case IRQ_TYPE_LEVEL_HIGH: 120 *out_type = type; 121 break; 122 default: 123 return -EINVAL; 124 } 125 return 0; 126 } 127 128 static struct irq_domain_ops irq_domain_sdv_ops = { 129 .xlate = sdv_xlate, 130 }; 131 132 static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, 133 struct pci_dev *pdev) 134 { 135 struct irq_chip_type *ct; 136 int ret; 137 138 sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1); 139 if (sd->irq_base < 0) 140 return sd->irq_base; 141 142 /* mask + ACK all interrupt sources */ 143 writel(0, sd->gpio_pub_base + GPIO_INT); 144 writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR); 145 146 ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED, 147 "sdv_gpio", sd); 148 if (ret) 149 goto out_free_desc; 150 151 /* 152 * This gpio irq controller latches level irqs. Testing shows that if 153 * we unmask & ACK the IRQ before the source of the interrupt is gone 154 * then the interrupt is active again. 155 */ 156 sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base, 157 sd->gpio_pub_base, handle_fasteoi_irq); 158 if (!sd->gc) { 159 ret = -ENOMEM; 160 goto out_free_irq; 161 } 162 163 sd->gc->private = sd; 164 ct = sd->gc->chip_types; 165 ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; 166 ct->regs.eoi = GPSTR; 167 ct->regs.mask = GPIO_INT; 168 ct->chip.irq_mask = irq_gc_mask_clr_bit; 169 ct->chip.irq_unmask = irq_gc_mask_set_bit; 170 ct->chip.irq_eoi = irq_gc_eoi; 171 ct->chip.irq_set_type = sdv_gpio_pub_set_type; 172 173 irq_setup_generic_chip(sd->gc, IRQ_MSK(SDV_NUM_PUB_GPIOS), 174 IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 175 IRQ_LEVEL | IRQ_NOPROBE); 176 177 sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS, 178 sd->irq_base, 0, &irq_domain_sdv_ops, sd); 179 if (!sd->id) 180 goto out_free_irq; 181 return 0; 182 out_free_irq: 183 free_irq(pdev->irq, sd); 184 out_free_desc: 185 irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); 186 return ret; 187 } 188 189 static int __devinit sdv_gpio_probe(struct pci_dev *pdev, 190 const struct pci_device_id *pci_id) 191 { 192 struct sdv_gpio_chip_data *sd; 193 unsigned long addr; 194 const void *prop; 195 int len; 196 int ret; 197 u32 mux_val; 198 199 sd = kzalloc(sizeof(struct sdv_gpio_chip_data), GFP_KERNEL); 200 if (!sd) 201 return -ENOMEM; 202 ret = pci_enable_device(pdev); 203 if (ret) { 204 dev_err(&pdev->dev, "can't enable device.\n"); 205 goto done; 206 } 207 208 ret = pci_request_region(pdev, GPIO_BAR, DRV_NAME); 209 if (ret) { 210 dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR); 211 goto disable_pci; 212 } 213 214 addr = pci_resource_start(pdev, GPIO_BAR); 215 if (!addr) 216 goto release_reg; 217 sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR)); 218 219 prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len); 220 if (prop && len == 4) { 221 mux_val = of_read_number(prop, 1); 222 writel(mux_val, sd->gpio_pub_base + GPMUXCTL); 223 } 224 225 ret = bgpio_init(&sd->bgpio, &pdev->dev, 4, 226 sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR, 227 NULL, sd->gpio_pub_base + GPOER, NULL, false); 228 if (ret) 229 goto unmap; 230 sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS; 231 232 ret = gpiochip_add(&sd->bgpio.gc); 233 if (ret < 0) { 234 dev_err(&pdev->dev, "gpiochip_add() failed.\n"); 235 goto unmap; 236 } 237 238 ret = sdv_register_irqsupport(sd, pdev); 239 if (ret) 240 goto unmap; 241 242 pci_set_drvdata(pdev, sd); 243 dev_info(&pdev->dev, "Sodaville GPIO driver registered.\n"); 244 return 0; 245 246 unmap: 247 iounmap(sd->gpio_pub_base); 248 release_reg: 249 pci_release_region(pdev, GPIO_BAR); 250 disable_pci: 251 pci_disable_device(pdev); 252 done: 253 kfree(sd); 254 return ret; 255 } 256 257 static void sdv_gpio_remove(struct pci_dev *pdev) 258 { 259 struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev); 260 261 free_irq(pdev->irq, sd); 262 irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); 263 264 if (gpiochip_remove(&sd->bgpio.gc)) 265 dev_err(&pdev->dev, "gpiochip_remove() failed.\n"); 266 267 pci_release_region(pdev, GPIO_BAR); 268 iounmap(sd->gpio_pub_base); 269 pci_disable_device(pdev); 270 kfree(sd); 271 } 272 273 static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = { 274 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, 275 { 0, }, 276 }; 277 278 static struct pci_driver sdv_gpio_driver = { 279 .name = DRV_NAME, 280 .id_table = sdv_gpio_pci_ids, 281 .probe = sdv_gpio_probe, 282 .remove = sdv_gpio_remove, 283 }; 284 285 static int __init sdv_gpio_init(void) 286 { 287 return pci_register_driver(&sdv_gpio_driver); 288 } 289 module_init(sdv_gpio_init); 290 291 static void __exit sdv_gpio_exit(void) 292 { 293 pci_unregister_driver(&sdv_gpio_driver); 294 } 295 module_exit(sdv_gpio_exit); 296 297 MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>"); 298 MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs"); 299 MODULE_LICENSE("GPL v2"); 300