summaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-01 14:36:28 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-09 17:09:14 +1100
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 97642a7a79c..7a4e788cab2 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -43,10 +43,7 @@
#include <asm/pmac_feature.h>
#include <asm/sections.h>
#include <asm/irq.h>
-
-#ifndef CONFIG_PPC64
#include <asm/mediabay.h>
-#endif
#define DRV_NAME "ide-pmac"
@@ -59,13 +56,14 @@ typedef struct pmac_ide_hwif {
int irq;
int kind;
int aapl_bus_id;
- unsigned mediabay : 1;
unsigned broken_dma : 1;
unsigned broken_dma_warn : 1;
struct device_node* node;
struct macio_dev *mdev;
u32 timings[4];
volatile u32 __iomem * *kauai_fcr;
+ ide_hwif_t *hwif;
+
/* Those fields are duplicating what is in hwif. We currently
* can't use the hwif ones because of some assumptions that are
* beeing done by the generic code about the kind of dma controller
@@ -854,6 +852,11 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
pmif->timings[2] = pmif->timings[3] = value2;
}
+static int on_media_bay(pmac_ide_hwif_t *pmif)
+{
+ return pmif->mdev && pmif->mdev->media_bay != NULL;
+}
+
/* Suspend call back, should be called after the child devices
* have actually been suspended
*/
@@ -866,7 +869,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
disable_irq(pmif->irq);
/* The media bay will handle itself just fine */
- if (pmif->mediabay)
+ if (on_media_bay(pmif))
return 0;
/* Kauai has bus control FCRs directly here */
@@ -889,7 +892,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
{
/* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
- if (!pmif->mediabay) {
+ if (!on_media_bay(pmif)) {
ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
msleep(10);
@@ -950,13 +953,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive)
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
- if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+ if (on_media_bay(pmif)) {
+ if (check_media_bay(pmif->mdev->media_bay) == MB_CD) {
drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
return;
}
-#endif
drive->dev_flags |= IDE_DFLAG_NOPROBE;
}
}
@@ -1072,26 +1073,23 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
writel(KAUAI_FCR_UATA_MAGIC |
KAUAI_FCR_UATA_RESET_N |
KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
-
- pmif->mediabay = 0;
/* Make sure we have sane timings */
sanitize_timings(pmif);
+ /* If we are on a media bay, wait for it to settle and lock it */
+ if (pmif->mdev)
+ lock_media_bay(pmif->mdev->media_bay);
+
host = ide_host_alloc(&d, hws, 1);
- if (host == NULL)
- return -ENOMEM;
- hwif = host->ports[0];
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto bail;
+ }
+ hwif = pmif->hwif = host->ports[0];
-#ifndef CONFIG_PPC64
- /* XXX FIXME: Media bay stuff need re-organizing */
- if (np->parent && np->parent->name
- && strcasecmp(np->parent->name, "media-bay") == 0) {
-#ifdef CONFIG_PMAC_MEDIABAY
- media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
- hwif);
-#endif /* CONFIG_PMAC_MEDIABAY */
- pmif->mediabay = 1;
+ if (on_media_bay(pmif)) {
+ /* Fixup bus ID for media bay */
if (!bidp)
pmif->aapl_bus_id = 1;
} else if (pmif->kind == controller_ohare) {
@@ -1100,9 +1098,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
* units, I keep the old way
*/
ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
- } else
-#endif
- {
+ } else {
/* This is necessary to enable IDE when net-booting */
ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
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,
}
printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
- "bus ID %d%s, irq %d\n", model_name[pmif->kind],
- pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
- pmif->mediabay ? " (mediabay)" : "", hw->irq);
+ "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+ pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+ on_media_bay(pmif) ? " (mediabay)" : "", hw->irq);
rc = ide_host_register(host, &d, hws);
- if (rc) {
- ide_host_free(host);
- return rc;
- }
+ if (rc)
+ pmif->hwif = NULL;
- return 0;
+ if (pmif->mdev)
+ unlock_media_bay(pmif->mdev->media_bay);
+
+ bail:
+ if (rc && host)
+ ide_host_free(host);
+ return rc;
}
static 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)
return rc;
}
+#ifdef CONFIG_PMAC_MEDIABAY
+static void pmac_ide_macio_mb_event(struct macio_dev* mdev, int mb_state)
+{
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+
+ switch(mb_state) {
+ case MB_CD:
+ if (!pmif->hwif->present)
+ ide_port_scan(pmif->hwif);
+ break;
+ default:
+ if (pmif->hwif->present)
+ ide_port_unregister_devices(pmif->hwif);
+ }
+}
+#endif /* CONFIG_PMAC_MEDIABAY */
+
+
static struct of_device_id pmac_ide_macio_match[] =
{
{
@@ -1386,6 +1405,9 @@ static struct macio_driver pmac_ide_macio_driver =
.probe = pmac_ide_macio_attach,
.suspend = pmac_ide_macio_suspend,
.resume = pmac_ide_macio_resume,
+#ifdef CONFIG_PMAC_MEDIABAY
+ .mediabay_event = pmac_ide_macio_mb_event,
+#endif
};
static const struct pci_device_id pmac_ide_pci_match[] = {