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 v3.0 456 lines 11 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#include <linux/pm_runtime.h> 37 38/* 39 * Langwell chip has 64 pins and thus there are 2 32bit registers to control 40 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit 41 * registers to control them, so we only define the order here instead of a 42 * structure, to get a bit offset for a pin (use GPDR as an example): 43 * 44 * nreg = ngpio / 32; 45 * reg = offset / 32; 46 * bit = offset % 32; 47 * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4; 48 * 49 * so the bit of reg_addr is to control pin offset's GPDR feature 50*/ 51 52enum GPIO_REG { 53 GPLR = 0, /* pin level read-only */ 54 GPDR, /* pin direction */ 55 GPSR, /* pin set */ 56 GPCR, /* pin clear */ 57 GRER, /* rising edge detect */ 58 GFER, /* falling edge detect */ 59 GEDR, /* edge detect result */ 60}; 61 62struct lnw_gpio { 63 struct gpio_chip chip; 64 void *reg_base; 65 spinlock_t lock; 66 unsigned irq_base; 67 struct pci_dev *pdev; 68}; 69 70static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, 71 enum GPIO_REG reg_type) 72{ 73 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 74 unsigned nreg = chip->ngpio / 32; 75 u8 reg = offset / 32; 76 void __iomem *ptr; 77 78 ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4); 79 return ptr; 80} 81 82static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) 83{ 84 void __iomem *gplr = gpio_reg(chip, offset, GPLR); 85 86 return readl(gplr) & BIT(offset % 32); 87} 88 89static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 90{ 91 void __iomem *gpsr, *gpcr; 92 93 if (value) { 94 gpsr = gpio_reg(chip, offset, GPSR); 95 writel(BIT(offset % 32), gpsr); 96 } else { 97 gpcr = gpio_reg(chip, offset, GPCR); 98 writel(BIT(offset % 32), gpcr); 99 } 100} 101 102static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 103{ 104 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 105 void __iomem *gpdr = gpio_reg(chip, offset, GPDR); 106 u32 value; 107 unsigned long flags; 108 109 if (lnw->pdev) 110 pm_runtime_get(&lnw->pdev->dev); 111 112 spin_lock_irqsave(&lnw->lock, flags); 113 value = readl(gpdr); 114 value &= ~BIT(offset % 32); 115 writel(value, gpdr); 116 spin_unlock_irqrestore(&lnw->lock, flags); 117 118 if (lnw->pdev) 119 pm_runtime_put(&lnw->pdev->dev); 120 121 return 0; 122} 123 124static int lnw_gpio_direction_output(struct gpio_chip *chip, 125 unsigned offset, int value) 126{ 127 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 128 void __iomem *gpdr = gpio_reg(chip, offset, GPDR); 129 unsigned long flags; 130 131 lnw_gpio_set(chip, offset, value); 132 133 if (lnw->pdev) 134 pm_runtime_get(&lnw->pdev->dev); 135 136 spin_lock_irqsave(&lnw->lock, flags); 137 value = readl(gpdr); 138 value |= BIT(offset % 32); 139 writel(value, gpdr); 140 spin_unlock_irqrestore(&lnw->lock, flags); 141 142 if (lnw->pdev) 143 pm_runtime_put(&lnw->pdev->dev); 144 145 return 0; 146} 147 148static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 149{ 150 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 151 return lnw->irq_base + offset; 152} 153 154static int lnw_irq_type(struct irq_data *d, unsigned type) 155{ 156 struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); 157 u32 gpio = d->irq - lnw->irq_base; 158 unsigned long flags; 159 u32 value; 160 void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); 161 void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER); 162 163 if (gpio >= lnw->chip.ngpio) 164 return -EINVAL; 165 166 if (lnw->pdev) 167 pm_runtime_get(&lnw->pdev->dev); 168 169 spin_lock_irqsave(&lnw->lock, flags); 170 if (type & IRQ_TYPE_EDGE_RISING) 171 value = readl(grer) | BIT(gpio % 32); 172 else 173 value = readl(grer) & (~BIT(gpio % 32)); 174 writel(value, grer); 175 176 if (type & IRQ_TYPE_EDGE_FALLING) 177 value = readl(gfer) | BIT(gpio % 32); 178 else 179 value = readl(gfer) & (~BIT(gpio % 32)); 180 writel(value, gfer); 181 spin_unlock_irqrestore(&lnw->lock, flags); 182 183 if (lnw->pdev) 184 pm_runtime_put(&lnw->pdev->dev); 185 186 return 0; 187} 188 189static void lnw_irq_unmask(struct irq_data *d) 190{ 191} 192 193static void lnw_irq_mask(struct irq_data *d) 194{ 195} 196 197static struct irq_chip lnw_irqchip = { 198 .name = "LNW-GPIO", 199 .irq_mask = lnw_irq_mask, 200 .irq_unmask = lnw_irq_unmask, 201 .irq_set_type = lnw_irq_type, 202}; 203 204static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ 205 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, 206 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, 207 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, 208 { 0, } 209}; 210MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); 211 212static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) 213{ 214 struct irq_data *data = irq_desc_get_irq_data(desc); 215 struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); 216 struct irq_chip *chip = irq_data_get_irq_chip(data); 217 u32 base, gpio, mask; 218 unsigned long pending; 219 void __iomem *gedr; 220 221 /* check GPIO controller to check which pin triggered the interrupt */ 222 for (base = 0; base < lnw->chip.ngpio; base += 32) { 223 gedr = gpio_reg(&lnw->chip, base, GEDR); 224 pending = readl(gedr); 225 while (pending) { 226 gpio = __ffs(pending); 227 mask = BIT(gpio); 228 pending &= ~mask; 229 /* Clear before handling so we can't lose an edge */ 230 writel(mask, gedr); 231 generic_handle_irq(lnw->irq_base + base + gpio); 232 } 233 } 234 235 chip->irq_eoi(data); 236} 237 238#ifdef CONFIG_PM 239static int lnw_gpio_runtime_resume(struct device *dev) 240{ 241 return 0; 242} 243 244static int lnw_gpio_runtime_suspend(struct device *dev) 245{ 246 return 0; 247} 248 249static int lnw_gpio_runtime_idle(struct device *dev) 250{ 251 int err = pm_schedule_suspend(dev, 500); 252 253 if (!err) 254 return 0; 255 256 return -EBUSY; 257} 258 259#else 260#define lnw_gpio_runtime_suspend NULL 261#define lnw_gpio_runtime_resume NULL 262#define lnw_gpio_runtime_idle NULL 263#endif 264 265static const struct dev_pm_ops lnw_gpio_pm_ops = { 266 .runtime_suspend = lnw_gpio_runtime_suspend, 267 .runtime_resume = lnw_gpio_runtime_resume, 268 .runtime_idle = lnw_gpio_runtime_idle, 269}; 270 271static int __devinit lnw_gpio_probe(struct pci_dev *pdev, 272 const struct pci_device_id *id) 273{ 274 void *base; 275 int i; 276 resource_size_t start, len; 277 struct lnw_gpio *lnw; 278 u32 irq_base; 279 u32 gpio_base; 280 int retval = 0; 281 282 retval = pci_enable_device(pdev); 283 if (retval) 284 goto done; 285 286 retval = pci_request_regions(pdev, "langwell_gpio"); 287 if (retval) { 288 dev_err(&pdev->dev, "error requesting resources\n"); 289 goto err2; 290 } 291 /* get the irq_base from bar1 */ 292 start = pci_resource_start(pdev, 1); 293 len = pci_resource_len(pdev, 1); 294 base = ioremap_nocache(start, len); 295 if (!base) { 296 dev_err(&pdev->dev, "error mapping bar1\n"); 297 goto err3; 298 } 299 irq_base = *(u32 *)base; 300 gpio_base = *((u32 *)base + 1); 301 /* release the IO mapping, since we already get the info from bar1 */ 302 iounmap(base); 303 /* get the register base from bar0 */ 304 start = pci_resource_start(pdev, 0); 305 len = pci_resource_len(pdev, 0); 306 base = ioremap_nocache(start, len); 307 if (!base) { 308 dev_err(&pdev->dev, "error mapping bar0\n"); 309 retval = -EFAULT; 310 goto err3; 311 } 312 313 lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); 314 if (!lnw) { 315 dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n"); 316 retval = -ENOMEM; 317 goto err4; 318 } 319 lnw->reg_base = base; 320 lnw->irq_base = irq_base; 321 lnw->chip.label = dev_name(&pdev->dev); 322 lnw->chip.direction_input = lnw_gpio_direction_input; 323 lnw->chip.direction_output = lnw_gpio_direction_output; 324 lnw->chip.get = lnw_gpio_get; 325 lnw->chip.set = lnw_gpio_set; 326 lnw->chip.to_irq = lnw_gpio_to_irq; 327 lnw->chip.base = gpio_base; 328 lnw->chip.ngpio = id->driver_data; 329 lnw->chip.can_sleep = 0; 330 lnw->pdev = pdev; 331 pci_set_drvdata(pdev, lnw); 332 retval = gpiochip_add(&lnw->chip); 333 if (retval) { 334 dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); 335 goto err5; 336 } 337 irq_set_handler_data(pdev->irq, lnw); 338 irq_set_chained_handler(pdev->irq, lnw_irq_handler); 339 for (i = 0; i < lnw->chip.ngpio; i++) { 340 irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, 341 handle_simple_irq, "demux"); 342 irq_set_chip_data(i + lnw->irq_base, lnw); 343 } 344 345 spin_lock_init(&lnw->lock); 346 347 pm_runtime_put_noidle(&pdev->dev); 348 pm_runtime_allow(&pdev->dev); 349 350 goto done; 351err5: 352 kfree(lnw); 353err4: 354 iounmap(base); 355err3: 356 pci_release_regions(pdev); 357err2: 358 pci_disable_device(pdev); 359done: 360 return retval; 361} 362 363static struct pci_driver lnw_gpio_driver = { 364 .name = "langwell_gpio", 365 .id_table = lnw_gpio_ids, 366 .probe = lnw_gpio_probe, 367 .driver = { 368 .pm = &lnw_gpio_pm_ops, 369 }, 370}; 371 372 373static int __devinit wp_gpio_probe(struct platform_device *pdev) 374{ 375 struct lnw_gpio *lnw; 376 struct gpio_chip *gc; 377 struct resource *rc; 378 int retval = 0; 379 380 rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); 381 if (!rc) 382 return -EINVAL; 383 384 lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); 385 if (!lnw) { 386 dev_err(&pdev->dev, 387 "can't allocate whitneypoint_gpio chip data\n"); 388 return -ENOMEM; 389 } 390 lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc)); 391 if (lnw->reg_base == NULL) { 392 retval = -EINVAL; 393 goto err_kmalloc; 394 } 395 spin_lock_init(&lnw->lock); 396 gc = &lnw->chip; 397 gc->label = dev_name(&pdev->dev); 398 gc->owner = THIS_MODULE; 399 gc->direction_input = lnw_gpio_direction_input; 400 gc->direction_output = lnw_gpio_direction_output; 401 gc->get = lnw_gpio_get; 402 gc->set = lnw_gpio_set; 403 gc->to_irq = NULL; 404 gc->base = 0; 405 gc->ngpio = 64; 406 gc->can_sleep = 0; 407 retval = gpiochip_add(gc); 408 if (retval) { 409 dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n", 410 retval); 411 goto err_ioremap; 412 } 413 platform_set_drvdata(pdev, lnw); 414 return 0; 415err_ioremap: 416 iounmap(lnw->reg_base); 417err_kmalloc: 418 kfree(lnw); 419 return retval; 420} 421 422static int __devexit wp_gpio_remove(struct platform_device *pdev) 423{ 424 struct lnw_gpio *lnw = platform_get_drvdata(pdev); 425 int err; 426 err = gpiochip_remove(&lnw->chip); 427 if (err) 428 dev_err(&pdev->dev, "failed to remove gpio_chip.\n"); 429 iounmap(lnw->reg_base); 430 kfree(lnw); 431 platform_set_drvdata(pdev, NULL); 432 return 0; 433} 434 435static struct platform_driver wp_gpio_driver = { 436 .probe = wp_gpio_probe, 437 .remove = __devexit_p(wp_gpio_remove), 438 .driver = { 439 .name = "wp_gpio", 440 .owner = THIS_MODULE, 441 }, 442}; 443 444static int __init lnw_gpio_init(void) 445{ 446 int ret; 447 ret = pci_register_driver(&lnw_gpio_driver); 448 if (ret < 0) 449 return ret; 450 ret = platform_driver_register(&wp_gpio_driver); 451 if (ret < 0) 452 pci_unregister_driver(&lnw_gpio_driver); 453 return ret; 454} 455 456device_initcall(lnw_gpio_init);