aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
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/ide
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/ide')
-rw-r--r--drivers/ide/pmac.c92
1 files changed, 57 insertions, 35 deletions
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 97642a7a79c4..7a4e788cab2f 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -43,10 +43,7 @@
43#include <asm/pmac_feature.h> 43#include <asm/pmac_feature.h>
44#include <asm/sections.h> 44#include <asm/sections.h>
45#include <asm/irq.h> 45#include <asm/irq.h>
46
47#ifndef CONFIG_PPC64
48#include <asm/mediabay.h> 46#include <asm/mediabay.h>
49#endif
50 47
51#define DRV_NAME "ide-pmac" 48#define DRV_NAME "ide-pmac"
52 49
@@ -59,13 +56,14 @@ typedef struct pmac_ide_hwif {
59 int irq; 56 int irq;
60 int kind; 57 int kind;
61 int aapl_bus_id; 58 int aapl_bus_id;
62 unsigned mediabay : 1;
63 unsigned broken_dma : 1; 59 unsigned broken_dma : 1;
64 unsigned broken_dma_warn : 1; 60 unsigned broken_dma_warn : 1;
65 struct device_node* node; 61 struct device_node* node;
66 struct macio_dev *mdev; 62 struct macio_dev *mdev;
67 u32 timings[4]; 63 u32 timings[4];
68 volatile u32 __iomem * *kauai_fcr; 64 volatile u32 __iomem * *kauai_fcr;
65 ide_hwif_t *hwif;
66
69 /* Those fields are duplicating what is in hwif. We currently 67 /* Those fields are duplicating what is in hwif. We currently
70 * can't use the hwif ones because of some assumptions that are 68 * can't use the hwif ones because of some assumptions that are
71 * beeing done by the generic code about the kind of dma controller 69 * beeing done by the generic code about the kind of dma controller
@@ -854,6 +852,11 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
854 pmif->timings[2] = pmif->timings[3] = value2; 852 pmif->timings[2] = pmif->timings[3] = value2;
855} 853}
856 854
855static int on_media_bay(pmac_ide_hwif_t *pmif)
856{
857 return pmif->mdev && pmif->mdev->media_bay != NULL;
858}
859
857/* Suspend call back, should be called after the child devices 860/* Suspend call back, should be called after the child devices
858 * have actually been suspended 861 * have actually been suspended
859 */ 862 */
@@ -866,7 +869,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
866 disable_irq(pmif->irq); 869 disable_irq(pmif->irq);
867 870
868 /* The media bay will handle itself just fine */ 871 /* The media bay will handle itself just fine */
869 if (pmif->mediabay) 872 if (on_media_bay(pmif))
870 return 0; 873 return 0;
871 874
872 /* Kauai has bus control FCRs directly here */ 875 /* Kauai has bus control FCRs directly here */
@@ -889,7 +892,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
889static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif) 892static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
890{ 893{
891 /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ 894 /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
892 if (!pmif->mediabay) { 895 if (!on_media_bay(pmif)) {
893 ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); 896 ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
894 ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); 897 ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
895 msleep(10); 898 msleep(10);
@@ -950,13 +953,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive)
950 pmac_ide_hwif_t *pmif = 953 pmac_ide_hwif_t *pmif =
951 (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); 954 (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
952 955
953 if (pmif->mediabay) { 956 if (on_media_bay(pmif)) {
954#ifdef CONFIG_PMAC_MEDIABAY 957 if (check_media_bay(pmif->mdev->media_bay) == MB_CD) {
955 if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
956 drive->dev_flags &= ~IDE_DFLAG_NOPROBE; 958 drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
957 return; 959 return;
958 } 960 }
959#endif
960 drive->dev_flags |= IDE_DFLAG_NOPROBE; 961 drive->dev_flags |= IDE_DFLAG_NOPROBE;
961 } 962 }
962} 963}
@@ -1072,26 +1073,23 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
1072 writel(KAUAI_FCR_UATA_MAGIC | 1073 writel(KAUAI_FCR_UATA_MAGIC |
1073 KAUAI_FCR_UATA_RESET_N | 1074 KAUAI_FCR_UATA_RESET_N |
1074 KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); 1075 KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
1075
1076 pmif->mediabay = 0;
1077 1076
1078 /* Make sure we have sane timings */ 1077 /* Make sure we have sane timings */
1079 sanitize_timings(pmif); 1078 sanitize_timings(pmif);
1080 1079
1080 /* If we are on a media bay, wait for it to settle and lock it */
1081 if (pmif->mdev)
1082 lock_media_bay(pmif->mdev->media_bay);
1083
1081 host = ide_host_alloc(&d, hws, 1); 1084 host = ide_host_alloc(&d, hws, 1);
1082 if (host == NULL) 1085 if (host == NULL) {
1083 return -ENOMEM; 1086 rc = -ENOMEM;
1084 hwif = host->ports[0]; 1087 goto bail;
1088 }
1089 hwif = pmif->hwif = host->ports[0];
1085 1090
1086#ifndef CONFIG_PPC64 1091 if (on_media_bay(pmif)) {
1087 /* XXX FIXME: Media bay stuff need re-organizing */ 1092 /* Fixup bus ID for media bay */
1088 if (np->parent && np->parent->name
1089 && strcasecmp(np->parent->name, "media-bay") == 0) {
1090#ifdef CONFIG_PMAC_MEDIABAY
1091 media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
1092 hwif);
1093#endif /* CONFIG_PMAC_MEDIABAY */
1094 pmif->mediabay = 1;
1095 if (!bidp) 1093 if (!bidp)
1096 pmif->aapl_bus_id = 1; 1094 pmif->aapl_bus_id = 1;
1097 } else if (pmif->kind == controller_ohare) { 1095 } else if (pmif->kind == controller_ohare) {
@@ -1100,9 +1098,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
1100 * units, I keep the old way 1098 * units, I keep the old way
1101 */ 1099 */
1102 ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); 1100 ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
1103 } else 1101 } else {
1104#endif
1105 {
1106 /* This is necessary to enable IDE when net-booting */ 1102 /* This is necessary to enable IDE when net-booting */
1107 ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); 1103 ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
1108 ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); 1104 ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
@@ -1112,17 +1108,21 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
1112 } 1108 }
1113 1109
1114 printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), " 1110 printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
1115 "bus ID %d%s, irq %d\n", model_name[pmif->kind], 1111 "bus ID %d%s, irq %d\n", model_name[pmif->kind],
1116 pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, 1112 pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
1117 pmif->mediabay ? " (mediabay)" : "", hw->irq); 1113 on_media_bay(pmif) ? " (mediabay)" : "", hw->irq);
1118 1114
1119 rc = ide_host_register(host, &d, hws); 1115 rc = ide_host_register(host, &d, hws);
1120 if (rc) { 1116 if (rc)
1121 ide_host_free(host); 1117 pmif->hwif = NULL;
1122 return rc;
1123 }
1124 1118
1125 return 0; 1119 if (pmif->mdev)
1120 unlock_media_bay(pmif->mdev->media_bay);
1121
1122 bail:
1123 if (rc && host)
1124 ide_host_free(host);
1125 return rc;
1126} 1126}
1127 1127
1128static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base) 1128static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base)
@@ -1362,6 +1362,25 @@ pmac_ide_pci_resume(struct pci_dev *pdev)
1362 return rc; 1362 return rc;
1363} 1363}
1364 1364
1365#ifdef CONFIG_PMAC_MEDIABAY
1366static void pmac_ide_macio_mb_event(struct macio_dev* mdev, int mb_state)
1367{
1368 pmac_ide_hwif_t *pmif =
1369 (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
1370
1371 switch(mb_state) {
1372 case MB_CD:
1373 if (!pmif->hwif->present)
1374 ide_port_scan(pmif->hwif);
1375 break;
1376 default:
1377 if (pmif->hwif->present)
1378 ide_port_unregister_devices(pmif->hwif);
1379 }
1380}
1381#endif /* CONFIG_PMAC_MEDIABAY */
1382
1383
1365static struct of_device_id pmac_ide_macio_match[] = 1384static struct of_device_id pmac_ide_macio_match[] =
1366{ 1385{
1367 { 1386 {
@@ -1386,6 +1405,9 @@ static struct macio_driver pmac_ide_macio_driver =
1386 .probe = pmac_ide_macio_attach, 1405 .probe = pmac_ide_macio_attach,
1387 .suspend = pmac_ide_macio_suspend, 1406 .suspend = pmac_ide_macio_suspend,
1388 .resume = pmac_ide_macio_resume, 1407 .resume = pmac_ide_macio_resume,
1408#ifdef CONFIG_PMAC_MEDIABAY
1409 .mediabay_event = pmac_ide_macio_mb_event,
1410#endif
1389}; 1411};
1390 1412
1391static const struct pci_device_id pmac_ide_pci_match[] = { 1413static const struct pci_device_id pmac_ide_pci_match[] = {