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

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.38-rc7 394 lines 10 kB view raw
1/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver 2 * Copyright (c) 2008 - 2009, Intel Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 */ 17 18/* Supports: 19 * Moorestown platform Langwell chip. 20 * Medfield platform Penwell chip. 21 * Whitney point. 22 */ 23 24#include <linux/module.h> 25#include <linux/pci.h> 26#include <linux/platform_device.h> 27#include <linux/kernel.h> 28#include <linux/delay.h> 29#include <linux/stddef.h> 30#include <linux/interrupt.h> 31#include <linux/init.h> 32#include <linux/irq.h> 33#include <linux/io.h> 34#include <linux/gpio.h> 35#include <linux/slab.h> 36 37/* 38 * Langwell chip has 64 pins and thus there are 2 32bit registers to control 39 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit 40 * registers to control them, so we only define the order here instead of a 41 * structure, to get a bit offset for a pin (use GPDR as an example): 42 * 43 * nreg = ngpio / 32; 44 * reg = offset / 32; 45 * bit = offset % 32; 46 * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4; 47 * 48 * so the bit of reg_addr is to control pin offset's GPDR feature 49*/ 50 51enum GPIO_REG { 52 GPLR = 0, /* pin level read-only */ 53 GPDR, /* pin direction */ 54 GPSR, /* pin set */ 55 GPCR, /* pin clear */ 56 GRER, /* rising edge detect */ 57 GFER, /* falling edge detect */ 58 GEDR, /* edge detect result */ 59}; 60 61struct lnw_gpio { 62 struct gpio_chip chip; 63 void *reg_base; 64 spinlock_t lock; 65 unsigned irq_base; 66}; 67 68static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, 69 enum GPIO_REG reg_type) 70{ 71 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 72 unsigned nreg = chip->ngpio / 32; 73 u8 reg = offset / 32; 74 void __iomem *ptr; 75 76 ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4); 77 return ptr; 78} 79 80static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) 81{ 82 void __iomem *gplr = gpio_reg(chip, offset, GPLR); 83 84 return readl(gplr) & BIT(offset % 32); 85} 86 87static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 88{ 89 void __iomem *gpsr, *gpcr; 90 91 if (value) { 92 gpsr = gpio_reg(chip, offset, GPSR); 93 writel(BIT(offset % 32), gpsr); 94 } else { 95 gpcr = gpio_reg(chip, offset, GPCR); 96 writel(BIT(offset % 32), gpcr); 97 } 98} 99 100static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 101{ 102 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 103 void __iomem *gpdr = gpio_reg(chip, offset, GPDR); 104 u32 value; 105 unsigned long flags; 106 107 spin_lock_irqsave(&lnw->lock, flags); 108 value = readl(gpdr); 109 value &= ~BIT(offset % 32); 110 writel(value, gpdr); 111 spin_unlock_irqrestore(&lnw->lock, flags); 112 return 0; 113} 114 115static int lnw_gpio_direction_output(struct gpio_chip *chip, 116 unsigned offset, int value) 117{ 118 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 119 void __iomem *gpdr = gpio_reg(chip, offset, GPDR); 120 unsigned long flags; 121 122 lnw_gpio_set(chip, offset, value); 123 spin_lock_irqsave(&lnw->lock, flags); 124 value = readl(gpdr); 125 value |= BIT(offset % 32);; 126 writel(value, gpdr); 127 spin_unlock_irqrestore(&lnw->lock, flags); 128 return 0; 129} 130 131static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 132{ 133 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 134 return lnw->irq_base + offset; 135} 136 137static int lnw_irq_type(struct irq_data *d, unsigned type) 138{ 139 struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); 140 u32 gpio = d->irq - lnw->irq_base; 141 unsigned long flags; 142 u32 value; 143 void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); 144 void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER); 145 146 if (gpio >= lnw->chip.ngpio) 147 return -EINVAL; 148 spin_lock_irqsave(&lnw->lock, flags); 149 if (type & IRQ_TYPE_EDGE_RISING) 150 value = readl(grer) | BIT(gpio % 32); 151 else 152 value = readl(grer) & (~BIT(gpio % 32)); 153 writel(value, grer); 154 155 if (type & IRQ_TYPE_EDGE_FALLING) 156 value = readl(gfer) | BIT(gpio % 32); 157 else 158 value = readl(gfer) & (~BIT(gpio % 32)); 159 writel(value, gfer); 160 spin_unlock_irqrestore(&lnw->lock, flags); 161 162 return 0; 163} 164 165static void lnw_irq_unmask(struct irq_data *d) 166{ 167} 168 169static void lnw_irq_mask(struct irq_data *d) 170{ 171} 172 173static struct irq_chip lnw_irqchip = { 174 .name = "LNW-GPIO", 175 .irq_mask = lnw_irq_mask, 176 .irq_unmask = lnw_irq_unmask, 177 .irq_set_type = lnw_irq_type, 178}; 179 180static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ 181 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, 182 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, 183 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, 184 { 0, } 185}; 186MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); 187 188static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) 189{ 190 struct lnw_gpio *lnw = get_irq_data(irq); 191 u32 base, gpio; 192 void __iomem *gedr; 193 u32 gedr_v; 194 195 /* check GPIO controller to check which pin triggered the interrupt */ 196 for (base = 0; base < lnw->chip.ngpio; base += 32) { 197 gedr = gpio_reg(&lnw->chip, base, GEDR); 198 gedr_v = readl(gedr); 199 if (!gedr_v) 200 continue; 201 for (gpio = base; gpio < base + 32; gpio++) 202 if (gedr_v & BIT(gpio % 32)) { 203 pr_debug("pin %d triggered\n", gpio); 204 generic_handle_irq(lnw->irq_base + gpio); 205 } 206 /* clear the edge detect status bit */ 207 writel(gedr_v, gedr); 208 } 209 210 if (desc->chip->irq_eoi) 211 desc->chip->irq_eoi(irq_get_irq_data(irq)); 212 else 213 dev_warn(lnw->chip.dev, "missing EOI handler for irq %d\n", irq); 214 215} 216 217static int __devinit lnw_gpio_probe(struct pci_dev *pdev, 218 const struct pci_device_id *id) 219{ 220 void *base; 221 int i; 222 resource_size_t start, len; 223 struct lnw_gpio *lnw; 224 u32 irq_base; 225 u32 gpio_base; 226 int retval = 0; 227 228 retval = pci_enable_device(pdev); 229 if (retval) 230 goto done; 231 232 retval = pci_request_regions(pdev, "langwell_gpio"); 233 if (retval) { 234 dev_err(&pdev->dev, "error requesting resources\n"); 235 goto err2; 236 } 237 /* get the irq_base from bar1 */ 238 start = pci_resource_start(pdev, 1); 239 len = pci_resource_len(pdev, 1); 240 base = ioremap_nocache(start, len); 241 if (!base) { 242 dev_err(&pdev->dev, "error mapping bar1\n"); 243 goto err3; 244 } 245 irq_base = *(u32 *)base; 246 gpio_base = *((u32 *)base + 1); 247 /* release the IO mapping, since we already get the info from bar1 */ 248 iounmap(base); 249 /* get the register base from bar0 */ 250 start = pci_resource_start(pdev, 0); 251 len = pci_resource_len(pdev, 0); 252 base = ioremap_nocache(start, len); 253 if (!base) { 254 dev_err(&pdev->dev, "error mapping bar0\n"); 255 retval = -EFAULT; 256 goto err3; 257 } 258 259 lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); 260 if (!lnw) { 261 dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n"); 262 retval = -ENOMEM; 263 goto err4; 264 } 265 lnw->reg_base = base; 266 lnw->irq_base = irq_base; 267 lnw->chip.label = dev_name(&pdev->dev); 268 lnw->chip.direction_input = lnw_gpio_direction_input; 269 lnw->chip.direction_output = lnw_gpio_direction_output; 270 lnw->chip.get = lnw_gpio_get; 271 lnw->chip.set = lnw_gpio_set; 272 lnw->chip.to_irq = lnw_gpio_to_irq; 273 lnw->chip.base = gpio_base; 274 lnw->chip.ngpio = id->driver_data; 275 lnw->chip.can_sleep = 0; 276 pci_set_drvdata(pdev, lnw); 277 retval = gpiochip_add(&lnw->chip); 278 if (retval) { 279 dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); 280 goto err5; 281 } 282 set_irq_data(pdev->irq, lnw); 283 set_irq_chained_handler(pdev->irq, lnw_irq_handler); 284 for (i = 0; i < lnw->chip.ngpio; i++) { 285 set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, 286 handle_simple_irq, "demux"); 287 set_irq_chip_data(i + lnw->irq_base, lnw); 288 } 289 290 spin_lock_init(&lnw->lock); 291 goto done; 292err5: 293 kfree(lnw); 294err4: 295 iounmap(base); 296err3: 297 pci_release_regions(pdev); 298err2: 299 pci_disable_device(pdev); 300done: 301 return retval; 302} 303 304static struct pci_driver lnw_gpio_driver = { 305 .name = "langwell_gpio", 306 .id_table = lnw_gpio_ids, 307 .probe = lnw_gpio_probe, 308}; 309 310 311static int __devinit wp_gpio_probe(struct platform_device *pdev) 312{ 313 struct lnw_gpio *lnw; 314 struct gpio_chip *gc; 315 struct resource *rc; 316 int retval = 0; 317 318 rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); 319 if (!rc) 320 return -EINVAL; 321 322 lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); 323 if (!lnw) { 324 dev_err(&pdev->dev, 325 "can't allocate whitneypoint_gpio chip data\n"); 326 return -ENOMEM; 327 } 328 lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc)); 329 if (lnw->reg_base == NULL) { 330 retval = -EINVAL; 331 goto err_kmalloc; 332 } 333 spin_lock_init(&lnw->lock); 334 gc = &lnw->chip; 335 gc->label = dev_name(&pdev->dev); 336 gc->owner = THIS_MODULE; 337 gc->direction_input = lnw_gpio_direction_input; 338 gc->direction_output = lnw_gpio_direction_output; 339 gc->get = lnw_gpio_get; 340 gc->set = lnw_gpio_set; 341 gc->to_irq = NULL; 342 gc->base = 0; 343 gc->ngpio = 64; 344 gc->can_sleep = 0; 345 retval = gpiochip_add(gc); 346 if (retval) { 347 dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n", 348 retval); 349 goto err_ioremap; 350 } 351 platform_set_drvdata(pdev, lnw); 352 return 0; 353err_ioremap: 354 iounmap(lnw->reg_base); 355err_kmalloc: 356 kfree(lnw); 357 return retval; 358} 359 360static int __devexit wp_gpio_remove(struct platform_device *pdev) 361{ 362 struct lnw_gpio *lnw = platform_get_drvdata(pdev); 363 int err; 364 err = gpiochip_remove(&lnw->chip); 365 if (err) 366 dev_err(&pdev->dev, "failed to remove gpio_chip.\n"); 367 iounmap(lnw->reg_base); 368 kfree(lnw); 369 platform_set_drvdata(pdev, NULL); 370 return 0; 371} 372 373static struct platform_driver wp_gpio_driver = { 374 .probe = wp_gpio_probe, 375 .remove = __devexit_p(wp_gpio_remove), 376 .driver = { 377 .name = "wp_gpio", 378 .owner = THIS_MODULE, 379 }, 380}; 381 382static int __init lnw_gpio_init(void) 383{ 384 int ret; 385 ret = pci_register_driver(&lnw_gpio_driver); 386 if (ret < 0) 387 return ret; 388 ret = platform_driver_register(&wp_gpio_driver); 389 if (ret < 0) 390 pci_unregister_driver(&lnw_gpio_driver); 391 return ret; 392} 393 394device_initcall(lnw_gpio_init);