X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=blobdiff_plain;f=drivers%2Fide%2Fppc%2Fpmac.c;h=569f16767442bf7fc0193425579a33b0eb4fb289;hp=9c7ea648d471a46e3ab4724d61ad95b5a7ebcab2;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hpb=e3f6fb6212a7102bdb56ba38fa1e98fe72950475 diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 9c7ea648d..569f16767 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -68,6 +68,7 @@ typedef struct pmac_ide_hwif { struct device_node* node; struct macio_dev *mdev; u32 timings[4]; + volatile u32 __iomem * *kauai_fcr; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC /* Those fields are duplicating what is in hwif. We currently * can't use the hwif ones because of some assumptions that are @@ -89,7 +90,8 @@ enum { controller_kl_ata3, /* KeyLargo ATA-3 */ controller_kl_ata4, /* KeyLargo ATA-4 */ controller_un_ata6, /* UniNorth2 ATA-6 */ - controller_k2_ata6 /* K2 ATA-6 */ + controller_k2_ata6, /* K2 ATA-6 */ + controller_sh_ata6, /* Shasta ATA-6 */ }; static const char* model_name[] = { @@ -99,6 +101,7 @@ static const char* model_name[] = { "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ + "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ }; /* @@ -122,6 +125,15 @@ static const char* model_name[] = { #define IDE_SYSCLK_NS 30 /* 33Mhz cell */ #define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ +/* 133Mhz cell, found in shasta. + * See comments about 100 Mhz Uninorth 2... + * Note that PIO_MASK and MDMA_MASK seem to overlap + */ +#define TR_133_PIOREG_PIO_MASK 0xff000fff +#define TR_133_PIOREG_MDMA_MASK 0x00fff800 +#define TR_133_UDMAREG_UDMA_MASK 0x0003ffff +#define TR_133_UDMAREG_UDMA_EN 0x00000001 + /* 100Mhz cell, found in Uninorth 2. I don't have much infos about * this one yet, it appears as a pci device (106b/0033) on uninorth * internal PCI bus and it's clock is controlled like gem or fw. It @@ -209,6 +221,13 @@ static const char* model_name[] = { #define IDE_INTR_DMA 0x80000000 #define IDE_INTR_DEVICE 0x40000000 +/* + * FCR Register on Kauai. Not sure what bit 0x4 is ... + */ +#define KAUAI_FCR_UATA_MAGIC 0x00000004 +#define KAUAI_FCR_UATA_RESET_N 0x00000002 +#define KAUAI_FCR_UATA_ENABLE 0x00000001 + #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC /* Rounded Multiword DMA timings @@ -322,6 +341,48 @@ static struct kauai_timing kauai_udma_timings[] __pmacdata = { 0 , 0 }, }; +static struct kauai_timing shasta_pio_timings[] __pmacdata = +{ + { 930 , 0x08000fff }, + { 600 , 0x0A000c97 }, + { 383 , 0x07000712 }, + { 360 , 0x040003cd }, + { 330 , 0x040003cd }, + { 300 , 0x040003cd }, + { 270 , 0x040003cd }, + { 240 , 0x040003cd }, + { 239 , 0x040003cd }, + { 180 , 0x0400028b }, + { 120 , 0x0400010a } +}; + +static struct kauai_timing shasta_mdma_timings[] __pmacdata = +{ + { 1260 , 0x00fff000 }, + { 480 , 0x00820800 }, + { 360 , 0x00820800 }, + { 270 , 0x00820800 }, + { 240 , 0x00820800 }, + { 210 , 0x00820800 }, + { 180 , 0x00820800 }, + { 150 , 0x0028b000 }, + { 120 , 0x001ca000 }, + { 0 , 0 }, +}; + +static struct kauai_timing shasta_udma133_timings[] __pmacdata = +{ + { 120 , 0x00035901, }, + { 90 , 0x000348b1, }, + { 60 , 0x00033881, }, + { 45 , 0x00033861, }, + { 30 , 0x00033841, }, + { 20 , 0x00033031, }, + { 15 , 0x00033021, }, + { 0 , 0 }, +}; + + static inline u32 kauai_lookup_timing(struct kauai_timing* table, int cycle_time) { @@ -547,7 +608,9 @@ pmac_ide_do_update_timings(ide_drive_t *drive) if (pmif == NULL) return; - if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6) + if (pmif->kind == controller_sh_ata6 || + pmif->kind == controller_un_ata6 || + pmif->kind == controller_k2_ata6) pmac_ide_kauai_selectproc(drive); else pmac_ide_selectproc(drive); @@ -665,6 +728,14 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8 pio) pio = ide_get_best_pio_mode(drive, pio, 4, &d); switch (pmif->kind) { + case controller_sh_ata6: { + /* 133Mhz cell */ + u32 tr = kauai_lookup_timing(shasta_pio_timings, d.cycle_time); + if (tr == 0) + return; + *timings = ((*timings) & ~TR_133_PIOREG_PIO_MASK) | tr; + break; + } case controller_un_ata6: case controller_k2_ata6: { /* 100Mhz cell */ @@ -775,6 +846,26 @@ set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed) return 0; } +/* + * Calculate Shasta ATA/133 UDMA timings + */ +static int __pmac +set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed) +{ + struct ide_timing *t = ide_timing_find_mode(speed); + u32 tr; + + if (speed > XFER_UDMA_6 || t == NULL) + return 1; + tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma); + if (tr == 0) + return 1; + *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr; + *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN; + + return 0; +} + /* * Calculate MDMA timings for all cells */ @@ -803,6 +894,7 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, cycleTime = 150; /* Get the proper timing array for this controller */ switch(intf_type) { + case controller_sh_ata6: case controller_un_ata6: case controller_k2_ata6: break; @@ -836,6 +928,14 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, #endif } switch(intf_type) { + case controller_sh_ata6: { + /* 133Mhz cell */ + u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime); + if (tr == 0) + return 1; + *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr; + *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN; + } case controller_un_ata6: case controller_k2_ata6: { /* 100Mhz cell */ @@ -930,9 +1030,13 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + case XFER_UDMA_6: + if (pmif->kind != controller_sh_ata6) + return 1; case XFER_UDMA_5: if (pmif->kind != controller_un_ata6 && - pmif->kind != controller_k2_ata6) + pmif->kind != controller_k2_ata6 && + pmif->kind != controller_sh_ata6) return 1; case XFER_UDMA_4: case XFER_UDMA_3: @@ -946,6 +1050,8 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) else if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6) ret = set_timings_udma_ata6(timings, timings2, speed); + else if (pmif->kind == controller_sh_ata6) + ret = set_timings_udma_shasta(timings, timings2, speed); else ret = 1; break; @@ -992,6 +1098,10 @@ sanitize_timings(pmac_ide_hwif_t *pmif) unsigned int value, value2 = 0; switch(pmif->kind) { + case controller_sh_ata6: + value = 0x0a820c97; + value2 = 0x00033031; + break; case controller_un_ata6: case controller_k2_ata6: value = 0x08618a92; @@ -1094,12 +1204,22 @@ pmac_ide_do_suspend(ide_hwif_t *hwif) } #endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ + disable_irq(pmif->irq); + /* The media bay will handle itself just fine */ if (pmif->mediabay) return 0; - /* Disable the bus */ - ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 0); + /* Kauai has bus control FCRs directly here */ + if (pmif->kauai_fcr) { + u32 fcr = readl(pmif->kauai_fcr); + fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); + writel(fcr, pmif->kauai_fcr); + } + + /* Disable the bus on older machines and the cell on kauai */ + ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, + 0); return 0; } @@ -1118,12 +1238,22 @@ pmac_ide_do_resume(ide_hwif_t *hwif) ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); msleep(10); ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0); + + /* Kauai has it different */ + if (pmif->kauai_fcr) { + u32 fcr = readl(pmif->kauai_fcr); + fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE; + writel(fcr, pmif->kauai_fcr); + } + msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); } /* Sanitize drive timings */ sanitize_timings(pmif); + enable_irq(pmif->irq); + return 0; } @@ -1142,7 +1272,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; - if (device_is_compatible(np, "kauai-ata")) + if (device_is_compatible(np, "shasta-ata")) + pmif->kind = controller_sh_ata6; + else if (device_is_compatible(np, "kauai-ata")) pmif->kind = controller_un_ata6; else if (device_is_compatible(np, "K2-UATA")) pmif->kind = controller_k2_ata6; @@ -1163,11 +1295,25 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* Get cable type from device-tree */ if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6 - || pmif->kind == controller_k2_ata6) { + || pmif->kind == controller_k2_ata6 + || pmif->kind == controller_sh_ata6) { char* cable = get_property(np, "cable-type", NULL); if (cable && !strncmp(cable, "80-", 3)) pmif->cable_80 = 1; } + /* G5's seem to have incorrect cable type in device-tree. Let's assume + * they have a 80 conductor cable, this seem to be always the case unless + * the user mucked around + */ + if (device_is_compatible(np, "K2-UATA") || + device_is_compatible(np, "shasta-ata")) + pmif->cable_80 = 1; + + /* On Kauai-type controllers, we make sure the FCR is correct */ + if (pmif->kauai_fcr) + writel(KAUAI_FCR_UATA_MAGIC | + KAUAI_FCR_UATA_RESET_N | + KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); pmif->mediabay = 0; @@ -1217,7 +1363,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->drives[0].unmask = 1; hwif->drives[1].unmask = 1; hwif->tuneproc = pmac_ide_tuneproc; - if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6) + if (pmif->kind == controller_un_ata6 + || pmif->kind == controller_k2_ata6 + || pmif->kind == controller_sh_ata6) hwif->selectproc = pmac_ide_kauai_selectproc; else hwif->selectproc = pmac_ide_selectproc; @@ -1327,6 +1475,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match) pmif->node = mdev->ofdev.node; pmif->regbase = regbase; pmif->irq = irq; + pmif->kauai_fcr = NULL; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (macio_resource_count(mdev) >= 2) { if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) @@ -1440,13 +1589,9 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) pmif->regbase = (unsigned long) base + 0x2000; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC pmif->dma_regs = base + 0x1000; -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - - /* We use the OF node irq mapping */ - if (np->n_intrs == 0) - pmif->irq = pdev->irq; - else - pmif->irq = np->intrs[0].line; +#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + pmif->kauai_fcr = base; + pmif->irq = pdev->irq; pci_set_drvdata(pdev, hwif); @@ -1530,6 +1675,8 @@ static struct pci_device_id pmac_ide_pci_match[] = { { PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, }; static struct pci_driver pmac_ide_pci_driver = { @@ -1539,6 +1686,7 @@ static struct pci_driver pmac_ide_pci_driver = { .suspend = pmac_ide_pci_suspend, .resume = pmac_ide_pci_resume, }; +MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); void __init pmac_ide_probe(void) @@ -1737,10 +1885,15 @@ pmac_ide_udma_enable(ide_drive_t *drive, u16 mode) timing_local[1] = *timings2; /* Calculate timings for interface */ - if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6) + if (pmif->kind == controller_un_ata6 + || pmif->kind == controller_k2_ata6) ret = set_timings_udma_ata6( &timing_local[0], &timing_local[1], mode); + else if (pmif->kind == controller_sh_ata6) + ret = set_timings_udma_shasta( &timing_local[0], + &timing_local[1], + mode); else ret = set_timings_udma_ata4(&timing_local[0], mode); if (ret) @@ -1791,14 +1944,19 @@ pmac_ide_dma_check(ide_drive_t *drive) short mode; map = XFER_MWDMA; - if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6 - || pmif->kind == controller_k2_ata6) { + if (pmif->kind == controller_kl_ata4 + || pmif->kind == controller_un_ata6 + || pmif->kind == controller_k2_ata6 + || pmif->kind == controller_sh_ata6) { map |= XFER_UDMA; if (pmif->cable_80) { map |= XFER_UDMA_66; if (pmif->kind == controller_un_ata6 || - pmif->kind == controller_k2_ata6) + pmif->kind == controller_k2_ata6 || + pmif->kind == controller_sh_ata6) map |= XFER_UDMA_100; + if (pmif->kind == controller_sh_ata6) + map |= XFER_UDMA_133; } } mode = ide_find_best_mode(drive, map); @@ -2028,6 +2186,11 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->atapi_dma = 1; switch(pmif->kind) { + case controller_sh_ata6: + hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x00; + break; case controller_un_ata6: case controller_k2_ata6: hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;