aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-01 09:36:28 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-09 01:09:14 -0500
commitd58b0c39e32f1b410af4d070f9d1a1416057c166 (patch)
treea4a9011c229c5d8d7b953dd5e1b0b70fa28d0a37 /drivers/macintosh
parent128b4a0ef74e8d48033513e41a413087ba30e36b (diff)
powerpc/macio: Rework hotplug media bay support
The hotplug mediabay has tendrils deep into drivers/ide code which makes a libata port reather difficult. In addition it's ugly and could be done better. This reworks the interface between the mediabay and the rest of the world so that: - Any macio_driver can now have a mediabay_event callback which will be called when that driver sits on a mediabay and it's been either plugged or unplugged. The device type is passed as an argument. We can now move all the IDE cruft into the IDE driver itself - A check_media_bay() function can be used to take a peek at the type of device currently in the bay if any, a cleaner variant of the previous function with the same name. - A pair of lock/unlock functions are exposed to allow the IDE driver to block the hotplug callbacks during the initial setup and probing of the bay in order to avoid nasty race conditions. - The mediabay code no longer needs to spin on the status register of the IDE interface when it detects an IDE device, this is done just fine by the IDE code itself Overall, less code, simpler, and allows for another driver than our old drivers/ide based one. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/macintosh')
-rw-r--r--drivers/macintosh/mediabay.c328
1 files changed, 122 insertions, 206 deletions
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 029ad8ce8a7e..08002b88f342 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -33,15 +33,6 @@
33#include <linux/adb.h> 33#include <linux/adb.h>
34#include <linux/pmu.h> 34#include <linux/pmu.h>
35 35
36
37#define MB_DEBUG
38
39#ifdef MB_DEBUG
40#define MBDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg)
41#else
42#define MBDBG(fmt, arg...) do { } while (0)
43#endif
44
45#define MB_FCR32(bay, r) ((bay)->base + ((r) >> 2)) 36#define MB_FCR32(bay, r) ((bay)->base + ((r) >> 2))
46#define MB_FCR8(bay, r) (((volatile u8 __iomem *)((bay)->base)) + (r)) 37#define MB_FCR8(bay, r) (((volatile u8 __iomem *)((bay)->base)) + (r))
47 38
@@ -76,28 +67,14 @@ struct media_bay_info {
76 int index; 67 int index;
77 int cached_gpio; 68 int cached_gpio;
78 int sleeping; 69 int sleeping;
70 int user_lock;
79 struct mutex lock; 71 struct mutex lock;
80#ifdef CONFIG_BLK_DEV_IDE_PMAC
81 ide_hwif_t *cd_port;
82 void __iomem *cd_base;
83 int cd_irq;
84 int cd_retry;
85#endif
86#if defined(CONFIG_BLK_DEV_IDE_PMAC)
87 int cd_index;
88#endif
89}; 72};
90 73
91#define MAX_BAYS 2 74#define MAX_BAYS 2
92 75
93static struct media_bay_info media_bays[MAX_BAYS]; 76static struct media_bay_info media_bays[MAX_BAYS];
94int media_bay_count = 0; 77static int media_bay_count = 0;
95
96#ifdef CONFIG_BLK_DEV_IDE_PMAC
97/* check the busy bit in the media-bay ide interface
98 (assumes the media-bay contains an ide device) */
99#define MB_IDE_READY(i) ((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
100#endif
101 78
102/* 79/*
103 * Wait that number of ms between each step in normal polling mode 80 * Wait that number of ms between each step in normal polling mode
@@ -130,21 +107,11 @@ int media_bay_count = 0;
130 107
131/* 108/*
132 * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted 109 * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted
133 * (or until the device is ready) before waiting for busy bit to disappear 110 * (or until the device is ready) before calling into the driver
134 */ 111 */
135#define MB_IDE_WAIT 1000 112#define MB_IDE_WAIT 1000
136 113
137/* 114/*
138 * Timeout waiting for busy bit of an IDE device to go down
139 */
140#define MB_IDE_TIMEOUT 5000
141
142/*
143 * Max retries of the full power up/down sequence for an IDE device
144 */
145#define MAX_CD_RETRIES 3
146
147/*
148 * States of a media bay 115 * States of a media bay
149 */ 116 */
150enum { 117enum {
@@ -153,7 +120,6 @@ enum {
153 mb_enabling_bay, /* enable bits set, waiting MB_RESET_DELAY */ 120 mb_enabling_bay, /* enable bits set, waiting MB_RESET_DELAY */
154 mb_resetting, /* reset bit unset, waiting MB_SETUP_DELAY */ 121 mb_resetting, /* reset bit unset, waiting MB_SETUP_DELAY */
155 mb_ide_resetting, /* IDE reset bit unser, waiting MB_IDE_WAIT */ 122 mb_ide_resetting, /* IDE reset bit unser, waiting MB_IDE_WAIT */
156 mb_ide_waiting, /* Waiting for BUSY bit to go away until MB_IDE_TIMEOUT */
157 mb_up, /* Media bay full */ 123 mb_up, /* Media bay full */
158 mb_powering_down /* Powering down (avoid too fast down/up) */ 124 mb_powering_down /* Powering down (avoid too fast down/up) */
159}; 125};
@@ -373,12 +339,12 @@ static inline void set_mb_power(struct media_bay_info* bay, int onoff)
373 if (onoff) { 339 if (onoff) {
374 bay->ops->power(bay, 1); 340 bay->ops->power(bay, 1);
375 bay->state = mb_powering_up; 341 bay->state = mb_powering_up;
376 MBDBG("mediabay%d: powering up\n", bay->index); 342 pr_debug("mediabay%d: powering up\n", bay->index);
377 } else { 343 } else {
378 /* Make sure everything is powered down & disabled */ 344 /* Make sure everything is powered down & disabled */
379 bay->ops->power(bay, 0); 345 bay->ops->power(bay, 0);
380 bay->state = mb_powering_down; 346 bay->state = mb_powering_down;
381 MBDBG("mediabay%d: powering down\n", bay->index); 347 pr_debug("mediabay%d: powering down\n", bay->index);
382 } 348 }
383 bay->timer = msecs_to_jiffies(MB_POWER_DELAY); 349 bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
384} 350}
@@ -387,107 +353,118 @@ static void poll_media_bay(struct media_bay_info* bay)
387{ 353{
388 int id = bay->ops->content(bay); 354 int id = bay->ops->content(bay);
389 355
390 if (id == bay->last_value) { 356 static char *mb_content_types[] = {
391 if (id != bay->content_id) { 357 "a floppy drive",
392 bay->value_count += msecs_to_jiffies(MB_POLL_DELAY); 358 "a floppy drive",
393 if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) { 359 "an unsuported audio device",
394 /* If the device type changes without going thru 360 "an ATA device",
395 * "MB_NO", we force a pass by "MB_NO" to make sure 361 "an unsupported PCI device",
396 * things are properly reset 362 "an unknown device",
397 */ 363 };
398 if ((id != MB_NO) && (bay->content_id != MB_NO)) { 364
399 id = MB_NO; 365 if (id != bay->last_value) {
400 MBDBG("mediabay%d: forcing MB_NO\n", bay->index);
401 }
402 MBDBG("mediabay%d: switching to %d\n", bay->index, id);
403 set_mb_power(bay, id != MB_NO);
404 bay->content_id = id;
405 if (id == MB_NO) {
406#ifdef CONFIG_BLK_DEV_IDE_PMAC
407 bay->cd_retry = 0;
408#endif
409 printk(KERN_INFO "media bay %d is empty\n", bay->index);
410 }
411 }
412 }
413 } else {
414 bay->last_value = id; 366 bay->last_value = id;
415 bay->value_count = 0; 367 bay->value_count = 0;
368 return;
369 }
370 if (id == bay->content_id)
371 return;
372
373 bay->value_count += msecs_to_jiffies(MB_POLL_DELAY);
374 if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) {
375 /* If the device type changes without going thru
376 * "MB_NO", we force a pass by "MB_NO" to make sure
377 * things are properly reset
378 */
379 if ((id != MB_NO) && (bay->content_id != MB_NO)) {
380 id = MB_NO;
381 pr_debug("mediabay%d: forcing MB_NO\n", bay->index);
382 }
383 pr_debug("mediabay%d: switching to %d\n", bay->index, id);
384 set_mb_power(bay, id != MB_NO);
385 bay->content_id = id;
386 if (id >= MB_NO || id < 0)
387 printk(KERN_INFO "mediabay%d: Bay is now empty\n", bay->index);
388 else
389 printk(KERN_INFO "mediabay%d: Bay contains %s\n",
390 bay->index, mb_content_types[id]);
416 } 391 }
417} 392}
418 393
419#ifdef CONFIG_BLK_DEV_IDE_PMAC 394int check_media_bay(struct macio_dev *baydev)
420int check_media_bay(struct device_node *which_bay, int what)
421{ 395{
422 int i; 396 struct media_bay_info* bay;
397 int id;
423 398
424 for (i=0; i<media_bay_count; i++) 399 if (baydev == NULL)
425 if (media_bays[i].mdev && which_bay == media_bays[i].mdev->ofdev.node) { 400 return MB_NO;
426 if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) 401
427 return 0; 402 /* This returns an instant snapshot, not locking, sine
428 media_bays[i].cd_index = -1; 403 * we may be called with the bay lock held. The resulting
429 return -EINVAL; 404 * fuzzyness of the result if called at the wrong time is
430 } 405 * not actually a huge deal
431 return -ENODEV; 406 */
407 bay = macio_get_drvdata(baydev);
408 if (bay == NULL)
409 return MB_NO;
410 id = bay->content_id;
411 if (bay->state != mb_up)
412 return MB_NO;
413 if (id == MB_FD1)
414 return MB_FD;
415 return id;
432} 416}
433EXPORT_SYMBOL(check_media_bay); 417EXPORT_SYMBOL_GPL(check_media_bay);
434 418
435int check_media_bay_by_base(unsigned long base, int what) 419void lock_media_bay(struct macio_dev *baydev)
436{ 420{
437 int i; 421 struct media_bay_info* bay;
438
439 for (i=0; i<media_bay_count; i++)
440 if (media_bays[i].mdev && base == (unsigned long) media_bays[i].cd_base) {
441 if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up)
442 return 0;
443 media_bays[i].cd_index = -1;
444 return -EINVAL;
445 }
446 422
447 return -ENODEV; 423 if (baydev == NULL)
424 return;
425 bay = macio_get_drvdata(baydev);
426 if (bay == NULL)
427 return;
428 mutex_lock(&bay->lock);
429 bay->user_lock = 1;
448} 430}
449EXPORT_SYMBOL_GPL(check_media_bay_by_base); 431EXPORT_SYMBOL_GPL(lock_media_bay);
450 432
451int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, 433void unlock_media_bay(struct macio_dev *baydev)
452 int irq, ide_hwif_t *hwif)
453{ 434{
454 int i; 435 struct media_bay_info* bay;
455 436
456 for (i=0; i<media_bay_count; i++) { 437 if (baydev == NULL)
457 struct media_bay_info* bay = &media_bays[i]; 438 return;
458 439 bay = macio_get_drvdata(baydev);
459 if (bay->mdev && which_bay == bay->mdev->ofdev.node) { 440 if (bay == NULL)
460 int timeout = 5000, index = hwif->index; 441 return;
461 442 if (bay->user_lock) {
462 mutex_lock(&bay->lock); 443 bay->user_lock = 0;
463 444 mutex_unlock(&bay->lock);
464 bay->cd_port = hwif;
465 bay->cd_base = (void __iomem *) base;
466 bay->cd_irq = irq;
467
468 if ((MB_CD != bay->content_id) || bay->state != mb_up) {
469 mutex_unlock(&bay->lock);
470 return 0;
471 }
472 printk(KERN_DEBUG "Registered ide%d for media bay %d\n", index, i);
473 do {
474 if (MB_IDE_READY(i)) {
475 bay->cd_index = index;
476 mutex_unlock(&bay->lock);
477 return 0;
478 }
479 mdelay(1);
480 } while(--timeout);
481 printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i);
482 mutex_unlock(&bay->lock);
483 return -ENODEV;
484 }
485 } 445 }
446}
447EXPORT_SYMBOL_GPL(unlock_media_bay);
486 448
487 return -ENODEV; 449static int mb_broadcast_hotplug(struct device *dev, void *data)
450{
451 struct media_bay_info* bay = data;
452 struct macio_dev *mdev;
453 struct macio_driver *drv;
454 int state;
455
456 if (dev->bus != &macio_bus_type)
457 return 0;
458
459 state = bay->state == mb_up ? bay->content_id : MB_NO;
460 if (state == MB_FD1)
461 state = MB_FD;
462 mdev = to_macio_device(dev);
463 drv = to_macio_driver(dev->driver);
464 if (dev->driver && drv->mediabay_event)
465 drv->mediabay_event(mdev, state);
466 return 0;
488} 467}
489EXPORT_SYMBOL_GPL(media_bay_set_ide_infos);
490#endif /* CONFIG_BLK_DEV_IDE_PMAC */
491 468
492static void media_bay_step(int i) 469static void media_bay_step(int i)
493{ 470{
@@ -497,8 +474,8 @@ static void media_bay_step(int i)
497 if (bay->state != mb_powering_down) 474 if (bay->state != mb_powering_down)
498 poll_media_bay(bay); 475 poll_media_bay(bay);
499 476
500 /* If timer expired or polling IDE busy, run state machine */ 477 /* If timer expired run state machine */
501 if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) { 478 if (bay->timer != 0) {
502 bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); 479 bay->timer -= msecs_to_jiffies(MB_POLL_DELAY);
503 if (bay->timer > 0) 480 if (bay->timer > 0)
504 return; 481 return;
@@ -508,100 +485,50 @@ static void media_bay_step(int i)
508 switch(bay->state) { 485 switch(bay->state) {
509 case mb_powering_up: 486 case mb_powering_up:
510 if (bay->ops->setup_bus(bay, bay->last_value) < 0) { 487 if (bay->ops->setup_bus(bay, bay->last_value) < 0) {
511 MBDBG("mediabay%d: device not supported (kind:%d)\n", i, bay->content_id); 488 pr_debug("mediabay%d: device not supported (kind:%d)\n",
489 i, bay->content_id);
512 set_mb_power(bay, 0); 490 set_mb_power(bay, 0);
513 break; 491 break;
514 } 492 }
515 bay->timer = msecs_to_jiffies(MB_RESET_DELAY); 493 bay->timer = msecs_to_jiffies(MB_RESET_DELAY);
516 bay->state = mb_enabling_bay; 494 bay->state = mb_enabling_bay;
517 MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); 495 pr_debug("mediabay%d: enabling (kind:%d)\n", i, bay->content_id);
518 break; 496 break;
519 case mb_enabling_bay: 497 case mb_enabling_bay:
520 bay->ops->un_reset(bay); 498 bay->ops->un_reset(bay);
521 bay->timer = msecs_to_jiffies(MB_SETUP_DELAY); 499 bay->timer = msecs_to_jiffies(MB_SETUP_DELAY);
522 bay->state = mb_resetting; 500 bay->state = mb_resetting;
523 MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id); 501 pr_debug("mediabay%d: releasing bay reset (kind:%d)\n",
502 i, bay->content_id);
524 break; 503 break;
525 case mb_resetting: 504 case mb_resetting:
526 if (bay->content_id != MB_CD) { 505 if (bay->content_id != MB_CD) {
527 MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); 506 pr_debug("mediabay%d: bay is up (kind:%d)\n", i,
507 bay->content_id);
528 bay->state = mb_up; 508 bay->state = mb_up;
509 device_for_each_child(&bay->mdev->ofdev.dev,
510 bay, mb_broadcast_hotplug);
529 break; 511 break;
530 } 512 }
531#ifdef CONFIG_BLK_DEV_IDE_PMAC 513 pr_debug("mediabay%d: releasing ATA reset (kind:%d)\n",
532 MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id); 514 i, bay->content_id);
533 bay->ops->un_reset_ide(bay); 515 bay->ops->un_reset_ide(bay);
534 bay->timer = msecs_to_jiffies(MB_IDE_WAIT); 516 bay->timer = msecs_to_jiffies(MB_IDE_WAIT);
535 bay->state = mb_ide_resetting; 517 bay->state = mb_ide_resetting;
536#else
537 printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i);
538 set_mb_power(bay, 0);
539#endif /* CONFIG_BLK_DEV_IDE_PMAC */
540 break; 518 break;
541#ifdef CONFIG_BLK_DEV_IDE_PMAC 519
542 case mb_ide_resetting: 520 case mb_ide_resetting:
543 bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT); 521 pr_debug("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id);
544 bay->state = mb_ide_waiting; 522 bay->state = mb_up;
545 MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id); 523 device_for_each_child(&bay->mdev->ofdev.dev,
524 bay, mb_broadcast_hotplug);
546 break; 525 break;
547 case mb_ide_waiting: 526
548 if (bay->cd_base == NULL) {
549 bay->timer = 0;
550 bay->state = mb_up;
551 MBDBG("mediabay%d: up before IDE init\n", i);
552 break;
553 } else if (MB_IDE_READY(i)) {
554 bay->timer = 0;
555 bay->state = mb_up;
556 if (bay->cd_index < 0) {
557 printk("mediabay %d, registering IDE...\n", i);
558 pmu_suspend();
559 ide_port_scan(bay->cd_port);
560 if (bay->cd_port->present)
561 bay->cd_index = bay->cd_port->index;
562 pmu_resume();
563 }
564 if (bay->cd_index == -1) {
565 /* We eventually do a retry */
566 bay->cd_retry++;
567 printk("IDE register error\n");
568 set_mb_power(bay, 0);
569 } else {
570 printk(KERN_DEBUG "media-bay %d is ide%d\n", i, bay->cd_index);
571 MBDBG("mediabay %d IDE ready\n", i);
572 }
573 break;
574 } else if (bay->timer > 0)
575 bay->timer -= msecs_to_jiffies(MB_POLL_DELAY);
576 if (bay->timer <= 0) {
577 printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n",
578 i, readb(bay->cd_base + 0x70));
579 MBDBG("mediabay%d: nIDE Timeout !\n", i);
580 set_mb_power(bay, 0);
581 bay->timer = 0;
582 }
583 break;
584#endif /* CONFIG_BLK_DEV_IDE_PMAC */
585 case mb_powering_down: 527 case mb_powering_down:
586 bay->state = mb_empty; 528 bay->state = mb_empty;
587#ifdef CONFIG_BLK_DEV_IDE_PMAC 529 device_for_each_child(&bay->mdev->ofdev.dev,
588 if (bay->cd_index >= 0) { 530 bay, mb_broadcast_hotplug);
589 printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, 531 pr_debug("mediabay%d: end of power down\n", i);
590 bay->cd_index);
591 ide_port_unregister_devices(bay->cd_port);
592 bay->cd_index = -1;
593 }
594 if (bay->cd_retry) {
595 if (bay->cd_retry > MAX_CD_RETRIES) {
596 /* Should add an error sound (sort of beep in dmasound) */
597 printk("\nmedia-bay %d, IDE device badly inserted or unrecognised\n", i);
598 } else {
599 /* Force a new power down/up sequence */
600 bay->content_id = MB_NO;
601 }
602 }
603#endif /* CONFIG_BLK_DEV_IDE_PMAC */
604 MBDBG("mediabay%d: end of power down\n", i);
605 break; 532 break;
606 } 533 }
607} 534}
@@ -676,11 +603,6 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
676 bay->last_value = bay->ops->content(bay); 603 bay->last_value = bay->ops->content(bay);
677 bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); 604 bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY);
678 bay->state = mb_empty; 605 bay->state = mb_empty;
679 do {
680 msleep(MB_POLL_DELAY);
681 media_bay_step(i);
682 } while((bay->state != mb_empty) &&
683 (bay->state != mb_up));
684 606
685 /* Mark us ready by filling our mdev data */ 607 /* Mark us ready by filling our mdev data */
686 macio_set_drvdata(mdev, bay); 608 macio_set_drvdata(mdev, bay);
@@ -725,7 +647,7 @@ static int media_bay_resume(struct macio_dev *mdev)
725 set_mb_power(bay, 0); 647 set_mb_power(bay, 0);
726 msleep(MB_POWER_DELAY); 648 msleep(MB_POWER_DELAY);
727 if (bay->ops->content(bay) != bay->content_id) { 649 if (bay->ops->content(bay) != bay->content_id) {
728 printk("mediabay%d: content changed during sleep...\n", bay->index); 650 printk("mediabay%d: Content changed during sleep...\n", bay->index);
729 mutex_unlock(&bay->lock); 651 mutex_unlock(&bay->lock);
730 return 0; 652 return 0;
731 } 653 }
@@ -733,9 +655,6 @@ static int media_bay_resume(struct macio_dev *mdev)
733 bay->last_value = bay->content_id; 655 bay->last_value = bay->content_id;
734 bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); 656 bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY);
735 bay->timer = msecs_to_jiffies(MB_POWER_DELAY); 657 bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
736#ifdef CONFIG_BLK_DEV_IDE_PMAC
737 bay->cd_retry = 0;
738#endif
739 do { 658 do {
740 msleep(MB_POLL_DELAY); 659 msleep(MB_POLL_DELAY);
741 media_bay_step(bay->index); 660 media_bay_step(bay->index);
@@ -823,9 +742,6 @@ static int __init media_bay_init(void)
823 for (i=0; i<MAX_BAYS; i++) { 742 for (i=0; i<MAX_BAYS; i++) {
824 memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info)); 743 memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info));
825 media_bays[i].content_id = -1; 744 media_bays[i].content_id = -1;
826#ifdef CONFIG_BLK_DEV_IDE_PMAC
827 media_bays[i].cd_index = -1;
828#endif
829 } 745 }
830 if (!machine_is(powermac)) 746 if (!machine_is(powermac))
831 return 0; 747 return 0;