1 /* 2 * Copyright (C) 2006, 2007 Eugene Konev <ejka@openwrt.org> 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 as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * Parts of the VLYNQ specification can be found here: 19 * http://www.ti.com/litv/pdf/sprue36a 20 */ 21 22 #include <linux/init.h> 23 #include <linux/types.h> 24 #include <linux/kernel.h> 25 #include <linux/string.h> 26 #include <linux/device.h> 27 #include <linux/module.h> 28 #include <linux/errno.h> 29 #include <linux/platform_device.h> 30 #include <linux/interrupt.h> 31 #include <linux/device.h> 32 #include <linux/delay.h> 33 #include <linux/io.h> 34 35 #include <linux/vlynq.h> 36 37 #define VLYNQ_CTRL_PM_ENABLE 0x80000000 38 #define VLYNQ_CTRL_CLOCK_INT 0x00008000 39 #define VLYNQ_CTRL_CLOCK_DIV(x) (((x) & 7) << 16) 40 #define VLYNQ_CTRL_INT_LOCAL 0x00004000 41 #define VLYNQ_CTRL_INT_ENABLE 0x00002000 42 #define VLYNQ_CTRL_INT_VECTOR(x) (((x) & 0x1f) << 8) 43 #define VLYNQ_CTRL_INT2CFG 0x00000080 44 #define VLYNQ_CTRL_RESET 0x00000001 45 46 #define VLYNQ_CTRL_CLOCK_MASK (0x7 << 16) 47 48 #define VLYNQ_INT_OFFSET 0x00000014 49 #define VLYNQ_REMOTE_OFFSET 0x00000080 50 51 #define VLYNQ_STATUS_LINK 0x00000001 52 #define VLYNQ_STATUS_LERROR 0x00000080 53 #define VLYNQ_STATUS_RERROR 0x00000100 54 55 #define VINT_ENABLE 0x00000100 56 #define VINT_TYPE_EDGE 0x00000080 57 #define VINT_LEVEL_LOW 0x00000040 58 #define VINT_VECTOR(x) ((x) & 0x1f) 59 #define VINT_OFFSET(irq) (8 * ((irq) % 4)) 60 61 #define VLYNQ_AUTONEGO_V2 0x00010000 62 63 struct vlynq_regs { 64 u32 revision; 65 u32 control; 66 u32 status; 67 u32 int_prio; 68 u32 int_status; 69 u32 int_pending; 70 u32 int_ptr; 71 u32 tx_offset; 72 struct vlynq_mapping rx_mapping[4]; 73 u32 chip; 74 u32 autonego; 75 u32 unused[6]; 76 u32 int_device[8]; 77 }; 78 79 #ifdef CONFIG_VLYNQ_DEBUG 80 static void vlynq_dump_regs(struct vlynq_device *dev) 81 { 82 int i; 83 84 printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n", 85 dev->local, dev->remote); 86 for (i = 0; i < 32; i++) { 87 printk(KERN_DEBUG "VLYNQ: local %d: %08x\n", 88 i + 1, ((u32 *)dev->local)[i]); 89 printk(KERN_DEBUG "VLYNQ: remote %d: %08x\n", 90 i + 1, ((u32 *)dev->remote)[i]); 91 } 92 } 93 94 static void vlynq_dump_mem(u32 *base, int count) 95 { 96 int i; 97 98 for (i = 0; i < (count + 3) / 4; i++) { 99 if (i % 4 == 0) 100 printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4); 101 printk(KERN_DEBUG " 0x%08x", *(base + i)); 102 } 103 printk(KERN_DEBUG "\n"); 104 } 105 #endif 106 107 /* Check the VLYNQ link status with a given device */ 108 static int vlynq_linked(struct vlynq_device *dev) 109 { 110 int i; 111 112 for (i = 0; i < 100; i++) 113 if (readl(&dev->local->status) & VLYNQ_STATUS_LINK) 114 return 1; 115 else 116 cpu_relax(); 117 118 return 0; 119 } 120 121 static void vlynq_reset(struct vlynq_device *dev) 122 { 123 writel(readl(&dev->local->control) | VLYNQ_CTRL_RESET, 124 &dev->local->control); 125 126 /* Wait for the devices to finish resetting */ 127 msleep(5); 128 129 /* Remove reset bit */ 130 writel(readl(&dev->local->control) & ~VLYNQ_CTRL_RESET, 131 &dev->local->control); 132 133 /* Give some time for the devices to settle */ 134 msleep(5); 135 } 136 137 static void vlynq_irq_unmask(unsigned int irq) 138 { 139 u32 val; 140 struct vlynq_device *dev = get_irq_chip_data(irq); 141 int virq; 142 143 BUG_ON(!dev); 144 virq = irq - dev->irq_start; 145 val = readl(&dev->remote->int_device[virq >> 2]); 146 val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq); 147 writel(val, &dev->remote->int_device[virq >> 2]); 148 } 149 150 static void vlynq_irq_mask(unsigned int irq) 151 { 152 u32 val; 153 struct vlynq_device *dev = get_irq_chip_data(irq); 154 int virq; 155 156 BUG_ON(!dev); 157 virq = irq - dev->irq_start; 158 val = readl(&dev->remote->int_device[virq >> 2]); 159 val &= ~(VINT_ENABLE << VINT_OFFSET(virq)); 160 writel(val, &dev->remote->int_device[virq >> 2]); 161 } 162 163 static int vlynq_irq_type(unsigned int irq, unsigned int flow_type) 164 { 165 u32 val; 166 struct vlynq_device *dev = get_irq_chip_data(irq); 167 int virq; 168 169 BUG_ON(!dev); 170 virq = irq - dev->irq_start; 171 val = readl(&dev->remote->int_device[virq >> 2]); 172 switch (flow_type & IRQ_TYPE_SENSE_MASK) { 173 case IRQ_TYPE_EDGE_RISING: 174 case IRQ_TYPE_EDGE_FALLING: 175 case IRQ_TYPE_EDGE_BOTH: 176 val |= VINT_TYPE_EDGE << VINT_OFFSET(virq); 177 val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); 178 break; 179 case IRQ_TYPE_LEVEL_HIGH: 180 val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); 181 val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); 182 break; 183 case IRQ_TYPE_LEVEL_LOW: 184 val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); 185 val |= VINT_LEVEL_LOW << VINT_OFFSET(virq); 186 break; 187 default: 188 return -EINVAL; 189 } 190 writel(val, &dev->remote->int_device[virq >> 2]); 191 return 0; 192 } 193 194 static void vlynq_local_ack(unsigned int irq) 195 { 196 struct vlynq_device *dev = get_irq_chip_data(irq); 197 198 u32 status = readl(&dev->local->status); 199 200 pr_debug("%s: local status: 0x%08x\n", 201 dev_name(&dev->dev), status); 202 writel(status, &dev->local->status); 203 } 204 205 static void vlynq_remote_ack(unsigned int irq) 206 { 207 struct vlynq_device *dev = get_irq_chip_data(irq); 208 209 u32 status = readl(&dev->remote->status); 210 211 pr_debug("%s: remote status: 0x%08x\n", 212 dev_name(&dev->dev), status); 213 writel(status, &dev->remote->status); 214 } 215 216 static irqreturn_t vlynq_irq(int irq, void *dev_id) 217 { 218 struct vlynq_device *dev = dev_id; 219 u32 status; 220 int virq = 0; 221 222 status = readl(&dev->local->int_status); 223 writel(status, &dev->local->int_status); 224 225 if (unlikely(!status)) 226 spurious_interrupt(); 227 228 while (status) { 229 if (status & 1) 230 do_IRQ(dev->irq_start + virq); 231 status >>= 1; 232 virq++; 233 } 234 235 return IRQ_HANDLED; 236 } 237 238 static struct irq_chip vlynq_irq_chip = { 239 .name = "vlynq", 240 .unmask = vlynq_irq_unmask, 241 .mask = vlynq_irq_mask, 242 .set_type = vlynq_irq_type, 243 }; 244 245 static struct irq_chip vlynq_local_chip = { 246 .name = "vlynq local error", 247 .unmask = vlynq_irq_unmask, 248 .mask = vlynq_irq_mask, 249 .ack = vlynq_local_ack, 250 }; 251 252 static struct irq_chip vlynq_remote_chip = { 253 .name = "vlynq local error", 254 .unmask = vlynq_irq_unmask, 255 .mask = vlynq_irq_mask, 256 .ack = vlynq_remote_ack, 257 }; 258 259 static int vlynq_setup_irq(struct vlynq_device *dev) 260 { 261 u32 val; 262 int i, virq; 263 264 if (dev->local_irq == dev->remote_irq) { 265 printk(KERN_ERR 266 "%s: local vlynq irq should be different from remote\n", 267 dev_name(&dev->dev)); 268 return -EINVAL; 269 } 270 271 /* Clear local and remote error bits */ 272 writel(readl(&dev->local->status), &dev->local->status); 273 writel(readl(&dev->remote->status), &dev->remote->status); 274 275 /* Now setup interrupts */ 276 val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq); 277 val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL | 278 VLYNQ_CTRL_INT2CFG; 279 val |= readl(&dev->local->control); 280 writel(VLYNQ_INT_OFFSET, &dev->local->int_ptr); 281 writel(val, &dev->local->control); 282 283 val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq); 284 val |= VLYNQ_CTRL_INT_ENABLE; 285 val |= readl(&dev->remote->control); 286 writel(VLYNQ_INT_OFFSET, &dev->remote->int_ptr); 287 writel(val, &dev->remote->int_ptr); 288 writel(val, &dev->remote->control); 289 290 for (i = dev->irq_start; i <= dev->irq_end; i++) { 291 virq = i - dev->irq_start; 292 if (virq == dev->local_irq) { 293 set_irq_chip_and_handler(i, &vlynq_local_chip, 294 handle_level_irq); 295 set_irq_chip_data(i, dev); 296 } else if (virq == dev->remote_irq) { 297 set_irq_chip_and_handler(i, &vlynq_remote_chip, 298 handle_level_irq); 299 set_irq_chip_data(i, dev); 300 } else { 301 set_irq_chip_and_handler(i, &vlynq_irq_chip, 302 handle_simple_irq); 303 set_irq_chip_data(i, dev); 304 writel(0, &dev->remote->int_device[virq >> 2]); 305 } 306 } 307 308 if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) { 309 printk(KERN_ERR "%s: request_irq failed\n", 310 dev_name(&dev->dev)); 311 return -EAGAIN; 312 } 313 314 return 0; 315 } 316 317 static void vlynq_device_release(struct device *dev) 318 { 319 struct vlynq_device *vdev = to_vlynq_device(dev); 320 kfree(vdev); 321 } 322 323 static int vlynq_device_match(struct device *dev, 324 struct device_driver *drv) 325 { 326 struct vlynq_device *vdev = to_vlynq_device(dev); 327 struct vlynq_driver *vdrv = to_vlynq_driver(drv); 328 struct vlynq_device_id *ids = vdrv->id_table; 329 330 while (ids->id) { 331 if (ids->id == vdev->dev_id) { 332 vdev->divisor = ids->divisor; 333 vlynq_set_drvdata(vdev, ids); 334 printk(KERN_INFO "Driver found for VLYNQ " 335 "device: %08x\n", vdev->dev_id); 336 return 1; 337 } 338 printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver" 339 " for VLYNQ device: %08x\n", ids->id, vdev->dev_id); 340 ids++; 341 } 342 return 0; 343 } 344 345 static int vlynq_device_probe(struct device *dev) 346 { 347 struct vlynq_device *vdev = to_vlynq_device(dev); 348 struct vlynq_driver *drv = to_vlynq_driver(dev->driver); 349 struct vlynq_device_id *id = vlynq_get_drvdata(vdev); 350 int result = -ENODEV; 351 352 if (drv->probe) 353 result = drv->probe(vdev, id); 354 if (result) 355 put_device(dev); 356 return result; 357 } 358 359 static int vlynq_device_remove(struct device *dev) 360 { 361 struct vlynq_driver *drv = to_vlynq_driver(dev->driver); 362 363 if (drv->remove) 364 drv->remove(to_vlynq_device(dev)); 365 366 return 0; 367 } 368 369 int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner) 370 { 371 driver->driver.name = driver->name; 372 driver->driver.bus = &vlynq_bus_type; 373 return driver_register(&driver->driver); 374 } 375 EXPORT_SYMBOL(__vlynq_register_driver); 376 377 void vlynq_unregister_driver(struct vlynq_driver *driver) 378 { 379 driver_unregister(&driver->driver); 380 } 381 EXPORT_SYMBOL(vlynq_unregister_driver); 382 383 /* 384 * A VLYNQ remote device can clock the VLYNQ bus master 385 * using a dedicated clock line. In that case, both the 386 * remove device and the bus master should have the same 387 * serial clock dividers configured. Iterate through the 388 * 8 possible dividers until we actually link with the 389 * device. 390 */ 391 static int __vlynq_try_remote(struct vlynq_device *dev) 392 { 393 int i; 394 395 vlynq_reset(dev); 396 for (i = dev->dev_id ? vlynq_rdiv2 : vlynq_rdiv8; dev->dev_id ? 397 i <= vlynq_rdiv8 : i >= vlynq_rdiv2; 398 dev->dev_id ? i++ : i--) { 399 400 if (!vlynq_linked(dev)) 401 break; 402 403 writel((readl(&dev->remote->control) & 404 ~VLYNQ_CTRL_CLOCK_MASK) | 405 VLYNQ_CTRL_CLOCK_INT | 406 VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), 407 &dev->remote->control); 408 writel((readl(&dev->local->control) 409 & ~(VLYNQ_CTRL_CLOCK_INT | 410 VLYNQ_CTRL_CLOCK_MASK)) | 411 VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), 412 &dev->local->control); 413 414 if (vlynq_linked(dev)) { 415 printk(KERN_DEBUG 416 "%s: using remote clock divisor %d\n", 417 dev_name(&dev->dev), i - vlynq_rdiv1 + 1); 418 dev->divisor = i; 419 return 0; 420 } else { 421 vlynq_reset(dev); 422 } 423 } 424 425 return -ENODEV; 426 } 427 428 /* 429 * A VLYNQ remote device can be clocked by the VLYNQ bus 430 * master using a dedicated clock line. In that case, only 431 * the bus master configures the serial clock divider. 432 * Iterate through the 8 possible dividers until we 433 * actually get a link with the device. 434 */ 435 static int __vlynq_try_local(struct vlynq_device *dev) 436 { 437 int i; 438 439 vlynq_reset(dev); 440 441 for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ? 442 i <= vlynq_ldiv8 : i >= vlynq_ldiv2; 443 dev->dev_id ? i++ : i--) { 444 445 writel((readl(&dev->local->control) & 446 ~VLYNQ_CTRL_CLOCK_MASK) | 447 VLYNQ_CTRL_CLOCK_INT | 448 VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1), 449 &dev->local->control); 450 451 if (vlynq_linked(dev)) { 452 printk(KERN_DEBUG 453 "%s: using local clock divisor %d\n", 454 dev_name(&dev->dev), i - vlynq_ldiv1 + 1); 455 dev->divisor = i; 456 return 0; 457 } else { 458 vlynq_reset(dev); 459 } 460 } 461 462 return -ENODEV; 463 } 464 465 /* 466 * When using external clocking method, serial clock 467 * is supplied by an external oscillator, therefore we 468 * should mask the local clock bit in the clock control 469 * register for both the bus master and the remote device. 470 */ 471 static int __vlynq_try_external(struct vlynq_device *dev) 472 { 473 vlynq_reset(dev); 474 if (!vlynq_linked(dev)) 475 return -ENODEV; 476 477 writel((readl(&dev->remote->control) & 478 ~VLYNQ_CTRL_CLOCK_INT), 479 &dev->remote->control); 480 481 writel((readl(&dev->local->control) & 482 ~VLYNQ_CTRL_CLOCK_INT), 483 &dev->local->control); 484 485 if (vlynq_linked(dev)) { 486 printk(KERN_DEBUG "%s: using external clock\n", 487 dev_name(&dev->dev)); 488 dev->divisor = vlynq_div_external; 489 return 0; 490 } 491 492 return -ENODEV; 493 } 494 495 static int __vlynq_enable_device(struct vlynq_device *dev) 496 { 497 int result; 498 struct plat_vlynq_ops *ops = dev->dev.platform_data; 499 500 result = ops->on(dev); 501 if (result) 502 return result; 503 504 switch (dev->divisor) { 505 case vlynq_div_external: 506 case vlynq_div_auto: 507 /* When the device is brought from reset it should have clock 508 * generation negotiated by hardware. 509 * Check which device is generating clocks and perform setup 510 * accordingly */ 511 if (vlynq_linked(dev) && readl(&dev->remote->control) & 512 VLYNQ_CTRL_CLOCK_INT) { 513 if (!__vlynq_try_remote(dev) || 514 !__vlynq_try_local(dev) || 515 !__vlynq_try_external(dev)) 516 return 0; 517 } else { 518 if (!__vlynq_try_external(dev) || 519 !__vlynq_try_local(dev) || 520 !__vlynq_try_remote(dev)) 521 return 0; 522 } 523 break; 524 case vlynq_ldiv1: 525 case vlynq_ldiv2: 526 case vlynq_ldiv3: 527 case vlynq_ldiv4: 528 case vlynq_ldiv5: 529 case vlynq_ldiv6: 530 case vlynq_ldiv7: 531 case vlynq_ldiv8: 532 writel(VLYNQ_CTRL_CLOCK_INT | 533 VLYNQ_CTRL_CLOCK_DIV(dev->divisor - 534 vlynq_ldiv1), &dev->local->control); 535 writel(0, &dev->remote->control); 536 if (vlynq_linked(dev)) { 537 printk(KERN_DEBUG 538 "%s: using local clock divisor %d\n", 539 dev_name(&dev->dev), 540 dev->divisor - vlynq_ldiv1 + 1); 541 return 0; 542 } 543 break; 544 case vlynq_rdiv1: 545 case vlynq_rdiv2: 546 case vlynq_rdiv3: 547 case vlynq_rdiv4: 548 case vlynq_rdiv5: 549 case vlynq_rdiv6: 550 case vlynq_rdiv7: 551 case vlynq_rdiv8: 552 writel(0, &dev->local->control); 553 writel(VLYNQ_CTRL_CLOCK_INT | 554 VLYNQ_CTRL_CLOCK_DIV(dev->divisor - 555 vlynq_rdiv1), &dev->remote->control); 556 if (vlynq_linked(dev)) { 557 printk(KERN_DEBUG 558 "%s: using remote clock divisor %d\n", 559 dev_name(&dev->dev), 560 dev->divisor - vlynq_rdiv1 + 1); 561 return 0; 562 } 563 break; 564 } 565 566 ops->off(dev); 567 return -ENODEV; 568 } 569 570 int vlynq_enable_device(struct vlynq_device *dev) 571 { 572 struct plat_vlynq_ops *ops = dev->dev.platform_data; 573 int result = -ENODEV; 574 575 result = __vlynq_enable_device(dev); 576 if (result) 577 return result; 578 579 result = vlynq_setup_irq(dev); 580 if (result) 581 ops->off(dev); 582 583 dev->enabled = !result; 584 return result; 585 } 586 EXPORT_SYMBOL(vlynq_enable_device); 587 588 589 void vlynq_disable_device(struct vlynq_device *dev) 590 { 591 struct plat_vlynq_ops *ops = dev->dev.platform_data; 592 593 dev->enabled = 0; 594 free_irq(dev->irq, dev); 595 ops->off(dev); 596 } 597 EXPORT_SYMBOL(vlynq_disable_device); 598 599 int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset, 600 struct vlynq_mapping *mapping) 601 { 602 int i; 603 604 if (!dev->enabled) 605 return -ENXIO; 606 607 writel(tx_offset, &dev->local->tx_offset); 608 for (i = 0; i < 4; i++) { 609 writel(mapping[i].offset, &dev->local->rx_mapping[i].offset); 610 writel(mapping[i].size, &dev->local->rx_mapping[i].size); 611 } 612 return 0; 613 } 614 EXPORT_SYMBOL(vlynq_set_local_mapping); 615 616 int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset, 617 struct vlynq_mapping *mapping) 618 { 619 int i; 620 621 if (!dev->enabled) 622 return -ENXIO; 623 624 writel(tx_offset, &dev->remote->tx_offset); 625 for (i = 0; i < 4; i++) { 626 writel(mapping[i].offset, &dev->remote->rx_mapping[i].offset); 627 writel(mapping[i].size, &dev->remote->rx_mapping[i].size); 628 } 629 return 0; 630 } 631 EXPORT_SYMBOL(vlynq_set_remote_mapping); 632 633 int vlynq_set_local_irq(struct vlynq_device *dev, int virq) 634 { 635 int irq = dev->irq_start + virq; 636 if (dev->enabled) 637 return -EBUSY; 638 639 if ((irq < dev->irq_start) || (irq > dev->irq_end)) 640 return -EINVAL; 641 642 if (virq == dev->remote_irq) 643 return -EINVAL; 644 645 dev->local_irq = virq; 646 647 return 0; 648 } 649 EXPORT_SYMBOL(vlynq_set_local_irq); 650 651 int vlynq_set_remote_irq(struct vlynq_device *dev, int virq) 652 { 653 int irq = dev->irq_start + virq; 654 if (dev->enabled) 655 return -EBUSY; 656 657 if ((irq < dev->irq_start) || (irq > dev->irq_end)) 658 return -EINVAL; 659 660 if (virq == dev->local_irq) 661 return -EINVAL; 662 663 dev->remote_irq = virq; 664 665 return 0; 666 } 667 EXPORT_SYMBOL(vlynq_set_remote_irq); 668 669 static int vlynq_probe(struct platform_device *pdev) 670 { 671 struct vlynq_device *dev; 672 struct resource *regs_res, *mem_res, *irq_res; 673 int len, result; 674 675 regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); 676 if (!regs_res) 677 return -ENODEV; 678 679 mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem"); 680 if (!mem_res) 681 return -ENODEV; 682 683 irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "devirq"); 684 if (!irq_res) 685 return -ENODEV; 686 687 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 688 if (!dev) { 689 printk(KERN_ERR 690 "vlynq: failed to allocate device structure\n"); 691 return -ENOMEM; 692 } 693 694 dev->id = pdev->id; 695 dev->dev.bus = &vlynq_bus_type; 696 dev->dev.parent = &pdev->dev; 697 dev_set_name(&dev->dev, "vlynq%d", dev->id); 698 dev->dev.platform_data = pdev->dev.platform_data; 699 dev->dev.release = vlynq_device_release; 700 701 dev->regs_start = regs_res->start; 702 dev->regs_end = regs_res->end; 703 dev->mem_start = mem_res->start; 704 dev->mem_end = mem_res->end; 705 706 len = regs_res->end - regs_res->start; 707 if (!request_mem_region(regs_res->start, len, dev_name(&dev->dev))) { 708 printk(KERN_ERR "%s: Can't request vlynq registers\n", 709 dev_name(&dev->dev)); 710 result = -ENXIO; 711 goto fail_request; 712 } 713 714 dev->local = ioremap(regs_res->start, len); 715 if (!dev->local) { 716 printk(KERN_ERR "%s: Can't remap vlynq registers\n", 717 dev_name(&dev->dev)); 718 result = -ENXIO; 719 goto fail_remap; 720 } 721 722 dev->remote = (struct vlynq_regs *)((void *)dev->local + 723 VLYNQ_REMOTE_OFFSET); 724 725 dev->irq = platform_get_irq_byname(pdev, "irq"); 726 dev->irq_start = irq_res->start; 727 dev->irq_end = irq_res->end; 728 dev->local_irq = dev->irq_end - dev->irq_start; 729 dev->remote_irq = dev->local_irq - 1; 730 731 if (device_register(&dev->dev)) 732 goto fail_register; 733 platform_set_drvdata(pdev, dev); 734 735 printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n", 736 dev_name(&dev->dev), (void *)dev->regs_start, dev->irq, 737 (void *)dev->mem_start); 738 739 dev->dev_id = 0; 740 dev->divisor = vlynq_div_auto; 741 result = __vlynq_enable_device(dev); 742 if (result == 0) { 743 dev->dev_id = readl(&dev->remote->chip); 744 ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev); 745 } 746 if (dev->dev_id) 747 printk(KERN_INFO "Found a VLYNQ device: %08x\n", dev->dev_id); 748 749 return 0; 750 751 fail_register: 752 iounmap(dev->local); 753 fail_remap: 754 fail_request: 755 release_mem_region(regs_res->start, len); 756 kfree(dev); 757 return result; 758 } 759 760 static int vlynq_remove(struct platform_device *pdev) 761 { 762 struct vlynq_device *dev = platform_get_drvdata(pdev); 763 764 device_unregister(&dev->dev); 765 iounmap(dev->local); 766 release_mem_region(dev->regs_start, dev->regs_end - dev->regs_start); 767 768 kfree(dev); 769 770 return 0; 771 } 772 773 static struct platform_driver vlynq_platform_driver = { 774 .driver.name = "vlynq", 775 .probe = vlynq_probe, 776 .remove = __devexit_p(vlynq_remove), 777 }; 778 779 struct bus_type vlynq_bus_type = { 780 .name = "vlynq", 781 .match = vlynq_device_match, 782 .probe = vlynq_device_probe, 783 .remove = vlynq_device_remove, 784 }; 785 EXPORT_SYMBOL(vlynq_bus_type); 786 787 static int __devinit vlynq_init(void) 788 { 789 int res = 0; 790 791 res = bus_register(&vlynq_bus_type); 792 if (res) 793 goto fail_bus; 794 795 res = platform_driver_register(&vlynq_platform_driver); 796 if (res) 797 goto fail_platform; 798 799 return 0; 800 801 fail_platform: 802 bus_unregister(&vlynq_bus_type); 803 fail_bus: 804 return res; 805 } 806 807 static void __devexit vlynq_exit(void) 808 { 809 platform_driver_unregister(&vlynq_platform_driver); 810 bus_unregister(&vlynq_bus_type); 811 } 812 813 module_init(vlynq_init); 814 module_exit(vlynq_exit); 815