1669a5db4SJeff Garzik /* 2669a5db4SJeff Garzik * Libata driver for the highpoint 37x and 30x UDMA66 ATA controllers. 3669a5db4SJeff Garzik * 4669a5db4SJeff Garzik * This driver is heavily based upon: 5669a5db4SJeff Garzik * 6669a5db4SJeff Garzik * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 7669a5db4SJeff Garzik * 8669a5db4SJeff Garzik * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> 9669a5db4SJeff Garzik * Portions Copyright (C) 2001 Sun Microsystems, Inc. 10669a5db4SJeff Garzik * Portions Copyright (C) 2003 Red Hat Inc 11265b7215SSergei Shtylyov * Portions Copyright (C) 2005-2009 MontaVista Software, Inc. 12669a5db4SJeff Garzik * 13669a5db4SJeff Garzik * TODO 14d44a65f7SSergei Shtylyov * Look into engine reset on timeout errors. Should not be required. 15669a5db4SJeff Garzik */ 16669a5db4SJeff Garzik 17669a5db4SJeff Garzik #include <linux/kernel.h> 18669a5db4SJeff Garzik #include <linux/module.h> 19669a5db4SJeff Garzik #include <linux/pci.h> 20669a5db4SJeff Garzik #include <linux/init.h> 21669a5db4SJeff Garzik #include <linux/blkdev.h> 22669a5db4SJeff Garzik #include <linux/delay.h> 23669a5db4SJeff Garzik #include <scsi/scsi_host.h> 24669a5db4SJeff Garzik #include <linux/libata.h> 25669a5db4SJeff Garzik 26669a5db4SJeff Garzik #define DRV_NAME "pata_hpt37x" 271a1b172bSSergei Shtylyov #define DRV_VERSION "0.6.15" 28669a5db4SJeff Garzik 29669a5db4SJeff Garzik struct hpt_clock { 30669a5db4SJeff Garzik u8 xfer_speed; 31669a5db4SJeff Garzik u32 timing; 32669a5db4SJeff Garzik }; 33669a5db4SJeff Garzik 34669a5db4SJeff Garzik struct hpt_chip { 35669a5db4SJeff Garzik const char *name; 36669a5db4SJeff Garzik unsigned int base; 37669a5db4SJeff Garzik struct hpt_clock const *clocks[4]; 38669a5db4SJeff Garzik }; 39669a5db4SJeff Garzik 40669a5db4SJeff Garzik /* key for bus clock timings 41669a5db4SJeff Garzik * bit 42fd5e62e2SSergei Shtylyov * 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. 43fd5e62e2SSergei Shtylyov * cycles = value + 1 44fd5e62e2SSergei Shtylyov * 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. 45fd5e62e2SSergei Shtylyov * cycles = value + 1 46fd5e62e2SSergei Shtylyov * 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file 47669a5db4SJeff Garzik * register access. 48fd5e62e2SSergei Shtylyov * 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file 49669a5db4SJeff Garzik * register access. 50fd5e62e2SSergei Shtylyov * 18:20 udma_cycle_time. Clock cycles for UDMA xfer. 51fd5e62e2SSergei Shtylyov * 21 CLK frequency for UDMA: 0=ATA clock, 1=dual ATA clock. 52fd5e62e2SSergei Shtylyov * 22:24 pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer. 53fd5e62e2SSergei Shtylyov * 25:27 cmd_pre_high_time. Time to initialize 1st PIO cycle for task file 54669a5db4SJeff Garzik * register access. 55fd5e62e2SSergei Shtylyov * 28 UDMA enable. 56fd5e62e2SSergei Shtylyov * 29 DMA enable. 57fd5e62e2SSergei Shtylyov * 30 PIO_MST enable. If set, the chip is in bus master mode during 58fd5e62e2SSergei Shtylyov * PIO xfer. 59fd5e62e2SSergei Shtylyov * 31 FIFO enable. Only for PIO. 60669a5db4SJeff Garzik */ 61669a5db4SJeff Garzik 62fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_33[] = { 63fcc2f69aSAlan Cox { XFER_UDMA_6, 0x12446231 }, /* 0x12646231 ?? */ 64669a5db4SJeff Garzik { XFER_UDMA_5, 0x12446231 }, 65669a5db4SJeff Garzik { XFER_UDMA_4, 0x12446231 }, 66669a5db4SJeff Garzik { XFER_UDMA_3, 0x126c6231 }, 67669a5db4SJeff Garzik { XFER_UDMA_2, 0x12486231 }, 68669a5db4SJeff Garzik { XFER_UDMA_1, 0x124c6233 }, 69669a5db4SJeff Garzik { XFER_UDMA_0, 0x12506297 }, 70669a5db4SJeff Garzik 71669a5db4SJeff Garzik { XFER_MW_DMA_2, 0x22406c31 }, 72669a5db4SJeff Garzik { XFER_MW_DMA_1, 0x22406c33 }, 73669a5db4SJeff Garzik { XFER_MW_DMA_0, 0x22406c97 }, 74669a5db4SJeff Garzik 75669a5db4SJeff Garzik { XFER_PIO_4, 0x06414e31 }, 76669a5db4SJeff Garzik { XFER_PIO_3, 0x06414e42 }, 77669a5db4SJeff Garzik { XFER_PIO_2, 0x06414e53 }, 78669a5db4SJeff Garzik { XFER_PIO_1, 0x06814e93 }, 79fcc2f69aSAlan Cox { XFER_PIO_0, 0x06814ea7 } 80669a5db4SJeff Garzik }; 81669a5db4SJeff Garzik 82fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_50[] = { 83fcc2f69aSAlan Cox { XFER_UDMA_6, 0x12848242 }, 84669a5db4SJeff Garzik { XFER_UDMA_5, 0x12848242 }, 85669a5db4SJeff Garzik { XFER_UDMA_4, 0x12ac8242 }, 86669a5db4SJeff Garzik { XFER_UDMA_3, 0x128c8242 }, 87669a5db4SJeff Garzik { XFER_UDMA_2, 0x120c8242 }, 88669a5db4SJeff Garzik { XFER_UDMA_1, 0x12148254 }, 89669a5db4SJeff Garzik { XFER_UDMA_0, 0x121882ea }, 90669a5db4SJeff Garzik 91669a5db4SJeff Garzik { XFER_MW_DMA_2, 0x22808242 }, 92669a5db4SJeff Garzik { XFER_MW_DMA_1, 0x22808254 }, 93669a5db4SJeff Garzik { XFER_MW_DMA_0, 0x228082ea }, 94669a5db4SJeff Garzik 95669a5db4SJeff Garzik { XFER_PIO_4, 0x0a81f442 }, 96669a5db4SJeff Garzik { XFER_PIO_3, 0x0a81f443 }, 97669a5db4SJeff Garzik { XFER_PIO_2, 0x0a81f454 }, 98669a5db4SJeff Garzik { XFER_PIO_1, 0x0ac1f465 }, 99fcc2f69aSAlan Cox { XFER_PIO_0, 0x0ac1f48a } 100669a5db4SJeff Garzik }; 101669a5db4SJeff Garzik 102fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_66[] = { 103669a5db4SJeff Garzik { XFER_UDMA_6, 0x1c869c62 }, 104fcc2f69aSAlan Cox { XFER_UDMA_5, 0x1cae9c62 }, /* 0x1c8a9c62 */ 105669a5db4SJeff Garzik { XFER_UDMA_4, 0x1c8a9c62 }, 106669a5db4SJeff Garzik { XFER_UDMA_3, 0x1c8e9c62 }, 107669a5db4SJeff Garzik { XFER_UDMA_2, 0x1c929c62 }, 108669a5db4SJeff Garzik { XFER_UDMA_1, 0x1c9a9c62 }, 109669a5db4SJeff Garzik { XFER_UDMA_0, 0x1c829c62 }, 110669a5db4SJeff Garzik 111669a5db4SJeff Garzik { XFER_MW_DMA_2, 0x2c829c62 }, 112669a5db4SJeff Garzik { XFER_MW_DMA_1, 0x2c829c66 }, 113669a5db4SJeff Garzik { XFER_MW_DMA_0, 0x2c829d2e }, 114669a5db4SJeff Garzik 115669a5db4SJeff Garzik { XFER_PIO_4, 0x0c829c62 }, 116669a5db4SJeff Garzik { XFER_PIO_3, 0x0c829c84 }, 117669a5db4SJeff Garzik { XFER_PIO_2, 0x0c829ca6 }, 118669a5db4SJeff Garzik { XFER_PIO_1, 0x0d029d26 }, 119fcc2f69aSAlan Cox { XFER_PIO_0, 0x0d029d5e } 120669a5db4SJeff Garzik }; 121669a5db4SJeff Garzik 122669a5db4SJeff Garzik 123669a5db4SJeff Garzik static const struct hpt_chip hpt370 = { 124669a5db4SJeff Garzik "HPT370", 125669a5db4SJeff Garzik 48, 126669a5db4SJeff Garzik { 127fcc2f69aSAlan Cox hpt37x_timings_33, 128669a5db4SJeff Garzik NULL, 129669a5db4SJeff Garzik NULL, 130a4734468SAlan Cox NULL 131669a5db4SJeff Garzik } 132669a5db4SJeff Garzik }; 133669a5db4SJeff Garzik 134669a5db4SJeff Garzik static const struct hpt_chip hpt370a = { 135669a5db4SJeff Garzik "HPT370A", 136669a5db4SJeff Garzik 48, 137669a5db4SJeff Garzik { 138fcc2f69aSAlan Cox hpt37x_timings_33, 139669a5db4SJeff Garzik NULL, 140fcc2f69aSAlan Cox hpt37x_timings_50, 141a4734468SAlan Cox NULL 142669a5db4SJeff Garzik } 143669a5db4SJeff Garzik }; 144669a5db4SJeff Garzik 145669a5db4SJeff Garzik static const struct hpt_chip hpt372 = { 146669a5db4SJeff Garzik "HPT372", 147669a5db4SJeff Garzik 55, 148669a5db4SJeff Garzik { 149fcc2f69aSAlan Cox hpt37x_timings_33, 150669a5db4SJeff Garzik NULL, 151fcc2f69aSAlan Cox hpt37x_timings_50, 152fcc2f69aSAlan Cox hpt37x_timings_66 153669a5db4SJeff Garzik } 154669a5db4SJeff Garzik }; 155669a5db4SJeff Garzik 156669a5db4SJeff Garzik static const struct hpt_chip hpt302 = { 157669a5db4SJeff Garzik "HPT302", 158669a5db4SJeff Garzik 66, 159669a5db4SJeff Garzik { 160fcc2f69aSAlan Cox hpt37x_timings_33, 161669a5db4SJeff Garzik NULL, 162fcc2f69aSAlan Cox hpt37x_timings_50, 163fcc2f69aSAlan Cox hpt37x_timings_66 164669a5db4SJeff Garzik } 165669a5db4SJeff Garzik }; 166669a5db4SJeff Garzik 167669a5db4SJeff Garzik static const struct hpt_chip hpt371 = { 168669a5db4SJeff Garzik "HPT371", 169669a5db4SJeff Garzik 66, 170669a5db4SJeff Garzik { 171fcc2f69aSAlan Cox hpt37x_timings_33, 172669a5db4SJeff Garzik NULL, 173fcc2f69aSAlan Cox hpt37x_timings_50, 174fcc2f69aSAlan Cox hpt37x_timings_66 175669a5db4SJeff Garzik } 176669a5db4SJeff Garzik }; 177669a5db4SJeff Garzik 178669a5db4SJeff Garzik static const struct hpt_chip hpt372a = { 179669a5db4SJeff Garzik "HPT372A", 180669a5db4SJeff Garzik 66, 181669a5db4SJeff Garzik { 182fcc2f69aSAlan Cox hpt37x_timings_33, 183669a5db4SJeff Garzik NULL, 184fcc2f69aSAlan Cox hpt37x_timings_50, 185fcc2f69aSAlan Cox hpt37x_timings_66 186669a5db4SJeff Garzik } 187669a5db4SJeff Garzik }; 188669a5db4SJeff Garzik 189669a5db4SJeff Garzik static const struct hpt_chip hpt374 = { 190669a5db4SJeff Garzik "HPT374", 191669a5db4SJeff Garzik 48, 192669a5db4SJeff Garzik { 193fcc2f69aSAlan Cox hpt37x_timings_33, 194669a5db4SJeff Garzik NULL, 195669a5db4SJeff Garzik NULL, 196669a5db4SJeff Garzik NULL 197669a5db4SJeff Garzik } 198669a5db4SJeff Garzik }; 199669a5db4SJeff Garzik 200669a5db4SJeff Garzik /** 201669a5db4SJeff Garzik * hpt37x_find_mode - reset the hpt37x bus 202669a5db4SJeff Garzik * @ap: ATA port 203669a5db4SJeff Garzik * @speed: transfer mode 204669a5db4SJeff Garzik * 205669a5db4SJeff Garzik * Return the 32bit register programming information for this channel 206669a5db4SJeff Garzik * that matches the speed provided. 207669a5db4SJeff Garzik */ 208669a5db4SJeff Garzik 209669a5db4SJeff Garzik static u32 hpt37x_find_mode(struct ata_port *ap, int speed) 210669a5db4SJeff Garzik { 211669a5db4SJeff Garzik struct hpt_clock *clocks = ap->host->private_data; 212669a5db4SJeff Garzik 213669a5db4SJeff Garzik while(clocks->xfer_speed) { 214669a5db4SJeff Garzik if (clocks->xfer_speed == speed) 215669a5db4SJeff Garzik return clocks->timing; 216669a5db4SJeff Garzik clocks++; 217669a5db4SJeff Garzik } 218669a5db4SJeff Garzik BUG(); 219669a5db4SJeff Garzik return 0xffffffffU; /* silence compiler warning */ 220669a5db4SJeff Garzik } 221669a5db4SJeff Garzik 222669a5db4SJeff Garzik static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) 223669a5db4SJeff Garzik { 2248bfa79fcSTejun Heo unsigned char model_num[ATA_ID_PROD_LEN + 1]; 225669a5db4SJeff Garzik int i = 0; 226669a5db4SJeff Garzik 2278bfa79fcSTejun Heo ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); 228669a5db4SJeff Garzik 229669a5db4SJeff Garzik while (list[i] != NULL) { 2308bfa79fcSTejun Heo if (!strcmp(list[i], model_num)) { 231669a5db4SJeff Garzik printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", 232669a5db4SJeff Garzik modestr, list[i]); 233669a5db4SJeff Garzik return 1; 234669a5db4SJeff Garzik } 235669a5db4SJeff Garzik i++; 236669a5db4SJeff Garzik } 237669a5db4SJeff Garzik return 0; 238669a5db4SJeff Garzik } 239669a5db4SJeff Garzik 240669a5db4SJeff Garzik static const char *bad_ata33[] = { 241669a5db4SJeff Garzik "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", 242669a5db4SJeff Garzik "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", 243669a5db4SJeff Garzik "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", 244669a5db4SJeff Garzik "Maxtor 90510D4", 245669a5db4SJeff Garzik "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", 246669a5db4SJeff Garzik "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", 247669a5db4SJeff Garzik "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", 248669a5db4SJeff Garzik NULL 249669a5db4SJeff Garzik }; 250669a5db4SJeff Garzik 251669a5db4SJeff Garzik static const char *bad_ata100_5[] = { 252669a5db4SJeff Garzik "IBM-DTLA-307075", 253669a5db4SJeff Garzik "IBM-DTLA-307060", 254669a5db4SJeff Garzik "IBM-DTLA-307045", 255669a5db4SJeff Garzik "IBM-DTLA-307030", 256669a5db4SJeff Garzik "IBM-DTLA-307020", 257669a5db4SJeff Garzik "IBM-DTLA-307015", 258669a5db4SJeff Garzik "IBM-DTLA-305040", 259669a5db4SJeff Garzik "IBM-DTLA-305030", 260669a5db4SJeff Garzik "IBM-DTLA-305020", 261669a5db4SJeff Garzik "IC35L010AVER07-0", 262669a5db4SJeff Garzik "IC35L020AVER07-0", 263669a5db4SJeff Garzik "IC35L030AVER07-0", 264669a5db4SJeff Garzik "IC35L040AVER07-0", 265669a5db4SJeff Garzik "IC35L060AVER07-0", 266669a5db4SJeff Garzik "WDC AC310200R", 267669a5db4SJeff Garzik NULL 268669a5db4SJeff Garzik }; 269669a5db4SJeff Garzik 270669a5db4SJeff Garzik /** 271669a5db4SJeff Garzik * hpt370_filter - mode selection filter 272669a5db4SJeff Garzik * @adev: ATA device 273669a5db4SJeff Garzik * 274669a5db4SJeff Garzik * Block UDMA on devices that cause trouble with this controller. 275669a5db4SJeff Garzik */ 276669a5db4SJeff Garzik 277a76b62caSAlan Cox static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask) 278669a5db4SJeff Garzik { 2796929da44SAlan if (adev->class == ATA_DEV_ATA) { 280669a5db4SJeff Garzik if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) 281669a5db4SJeff Garzik mask &= ~ATA_MASK_UDMA; 282669a5db4SJeff Garzik if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) 2836ddd6861SAlan Cox mask &= ~(0xE0 << ATA_SHIFT_UDMA); 284669a5db4SJeff Garzik } 285c7087652STejun Heo return mask; 286669a5db4SJeff Garzik } 287669a5db4SJeff Garzik 288669a5db4SJeff Garzik /** 289669a5db4SJeff Garzik * hpt370a_filter - mode selection filter 290669a5db4SJeff Garzik * @adev: ATA device 291669a5db4SJeff Garzik * 292669a5db4SJeff Garzik * Block UDMA on devices that cause trouble with this controller. 293669a5db4SJeff Garzik */ 294669a5db4SJeff Garzik 295a76b62caSAlan Cox static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) 296669a5db4SJeff Garzik { 29773946f9fSAlan Cox if (adev->class == ATA_DEV_ATA) { 298669a5db4SJeff Garzik if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) 2996ddd6861SAlan Cox mask &= ~(0xE0 << ATA_SHIFT_UDMA); 300669a5db4SJeff Garzik } 301c7087652STejun Heo return mask; 302669a5db4SJeff Garzik } 303669a5db4SJeff Garzik 304669a5db4SJeff Garzik /** 3059e87be9eSBartlomiej Zolnierkiewicz * hpt37x_cable_detect - Detect the cable type 3069e87be9eSBartlomiej Zolnierkiewicz * @ap: ATA port to detect on 307669a5db4SJeff Garzik * 3089e87be9eSBartlomiej Zolnierkiewicz * Return the cable type attached to this port 309669a5db4SJeff Garzik */ 310669a5db4SJeff Garzik 3119e87be9eSBartlomiej Zolnierkiewicz static int hpt37x_cable_detect(struct ata_port *ap) 312669a5db4SJeff Garzik { 313669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3149e87be9eSBartlomiej Zolnierkiewicz u8 scr2, ata66; 315669a5db4SJeff Garzik 316669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x5B, &scr2); 317669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); 31810a9c969SBartlomiej Zolnierkiewicz 31910a9c969SBartlomiej Zolnierkiewicz udelay(10); /* debounce */ 32010a9c969SBartlomiej Zolnierkiewicz 321669a5db4SJeff Garzik /* Cable register now active */ 322669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x5A, &ata66); 323669a5db4SJeff Garzik /* Restore state */ 324669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x5B, scr2); 325669a5db4SJeff Garzik 32622d5c760SAlan Cox if (ata66 & (2 >> ap->port_no)) 3279e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA40; 328669a5db4SJeff Garzik else 3299e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA80; 3309e87be9eSBartlomiej Zolnierkiewicz } 3319e87be9eSBartlomiej Zolnierkiewicz 3329e87be9eSBartlomiej Zolnierkiewicz /** 3339e87be9eSBartlomiej Zolnierkiewicz * hpt374_fn1_cable_detect - Detect the cable type 3349e87be9eSBartlomiej Zolnierkiewicz * @ap: ATA port to detect on 3359e87be9eSBartlomiej Zolnierkiewicz * 3369e87be9eSBartlomiej Zolnierkiewicz * Return the cable type attached to this port 3379e87be9eSBartlomiej Zolnierkiewicz */ 3389e87be9eSBartlomiej Zolnierkiewicz 3399e87be9eSBartlomiej Zolnierkiewicz static int hpt374_fn1_cable_detect(struct ata_port *ap) 3409e87be9eSBartlomiej Zolnierkiewicz { 3419e87be9eSBartlomiej Zolnierkiewicz struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3429e87be9eSBartlomiej Zolnierkiewicz unsigned int mcrbase = 0x50 + 4 * ap->port_no; 3439e87be9eSBartlomiej Zolnierkiewicz u16 mcr3; 3449e87be9eSBartlomiej Zolnierkiewicz u8 ata66; 3459e87be9eSBartlomiej Zolnierkiewicz 3469e87be9eSBartlomiej Zolnierkiewicz /* Do the extra channel work */ 3479e87be9eSBartlomiej Zolnierkiewicz pci_read_config_word(pdev, mcrbase + 2, &mcr3); 3489e87be9eSBartlomiej Zolnierkiewicz /* Set bit 15 of 0x52 to enable TCBLID as input */ 3499e87be9eSBartlomiej Zolnierkiewicz pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000); 3509e87be9eSBartlomiej Zolnierkiewicz pci_read_config_byte(pdev, 0x5A, &ata66); 3519e87be9eSBartlomiej Zolnierkiewicz /* Reset TCBLID/FCBLID to output */ 3529e87be9eSBartlomiej Zolnierkiewicz pci_write_config_word(pdev, mcrbase + 2, mcr3); 3539e87be9eSBartlomiej Zolnierkiewicz 3549e87be9eSBartlomiej Zolnierkiewicz if (ata66 & (2 >> ap->port_no)) 3559e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA40; 3569e87be9eSBartlomiej Zolnierkiewicz else 3579e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA80; 3589e87be9eSBartlomiej Zolnierkiewicz } 3599e87be9eSBartlomiej Zolnierkiewicz 3609e87be9eSBartlomiej Zolnierkiewicz /** 3619e87be9eSBartlomiej Zolnierkiewicz * hpt37x_pre_reset - reset the hpt37x bus 3629e87be9eSBartlomiej Zolnierkiewicz * @link: ATA link to reset 3639e87be9eSBartlomiej Zolnierkiewicz * @deadline: deadline jiffies for the operation 3649e87be9eSBartlomiej Zolnierkiewicz * 365ab81a505SBartlomiej Zolnierkiewicz * Perform the initial reset handling for the HPT37x. 3669e87be9eSBartlomiej Zolnierkiewicz */ 3679e87be9eSBartlomiej Zolnierkiewicz 3689e87be9eSBartlomiej Zolnierkiewicz static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) 3699e87be9eSBartlomiej Zolnierkiewicz { 3709e87be9eSBartlomiej Zolnierkiewicz struct ata_port *ap = link->ap; 3719e87be9eSBartlomiej Zolnierkiewicz struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3729e87be9eSBartlomiej Zolnierkiewicz static const struct pci_bits hpt37x_enable_bits[] = { 3739e87be9eSBartlomiej Zolnierkiewicz { 0x50, 1, 0x04, 0x04 }, 3749e87be9eSBartlomiej Zolnierkiewicz { 0x54, 1, 0x04, 0x04 } 3759e87be9eSBartlomiej Zolnierkiewicz }; 3769e87be9eSBartlomiej Zolnierkiewicz if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) 3779e87be9eSBartlomiej Zolnierkiewicz return -ENOENT; 378669a5db4SJeff Garzik 379669a5db4SJeff Garzik /* Reset the state machine */ 380fcc2f69aSAlan Cox pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 381669a5db4SJeff Garzik udelay(100); 382669a5db4SJeff Garzik 3839363c382STejun Heo return ata_sff_prereset(link, deadline); 384669a5db4SJeff Garzik } 385669a5db4SJeff Garzik 3861a1b172bSSergei Shtylyov static void hpt370_set_mode(struct ata_port *ap, struct ata_device *adev, 3871a1b172bSSergei Shtylyov u8 mode) 3881a1b172bSSergei Shtylyov { 3891a1b172bSSergei Shtylyov struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3901a1b172bSSergei Shtylyov u32 addr1, addr2; 3911a1b172bSSergei Shtylyov u32 reg, timing, mask; 3921a1b172bSSergei Shtylyov u8 fast; 3931a1b172bSSergei Shtylyov 3941a1b172bSSergei Shtylyov addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 3951a1b172bSSergei Shtylyov addr2 = 0x51 + 4 * ap->port_no; 3961a1b172bSSergei Shtylyov 3971a1b172bSSergei Shtylyov /* Fast interrupt prediction disable, hold off interrupt disable */ 3981a1b172bSSergei Shtylyov pci_read_config_byte(pdev, addr2, &fast); 3991a1b172bSSergei Shtylyov fast &= ~0x02; 4001a1b172bSSergei Shtylyov fast |= 0x01; 4011a1b172bSSergei Shtylyov pci_write_config_byte(pdev, addr2, fast); 4021a1b172bSSergei Shtylyov 4031a1b172bSSergei Shtylyov /* Determine timing mask and find matching mode entry */ 4041a1b172bSSergei Shtylyov if (mode < XFER_MW_DMA_0) 4051a1b172bSSergei Shtylyov mask = 0xcfc3ffff; 4061a1b172bSSergei Shtylyov else if (mode < XFER_UDMA_0) 4071a1b172bSSergei Shtylyov mask = 0x31c001ff; 4081a1b172bSSergei Shtylyov else 4091a1b172bSSergei Shtylyov mask = 0x303c0000; 4101a1b172bSSergei Shtylyov 4111a1b172bSSergei Shtylyov timing = hpt37x_find_mode(ap, mode); 4121a1b172bSSergei Shtylyov 4131a1b172bSSergei Shtylyov pci_read_config_dword(pdev, addr1, ®); 4141a1b172bSSergei Shtylyov reg = (reg & ~mask) | (timing & mask); 4151a1b172bSSergei Shtylyov pci_write_config_dword(pdev, addr1, reg); 4161a1b172bSSergei Shtylyov } 417669a5db4SJeff Garzik /** 418669a5db4SJeff Garzik * hpt370_set_piomode - PIO setup 419669a5db4SJeff Garzik * @ap: ATA interface 420669a5db4SJeff Garzik * @adev: device on the interface 421669a5db4SJeff Garzik * 422669a5db4SJeff Garzik * Perform PIO mode setup. 423669a5db4SJeff Garzik */ 424669a5db4SJeff Garzik 425669a5db4SJeff Garzik static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) 426669a5db4SJeff Garzik { 4271a1b172bSSergei Shtylyov hpt370_set_mode(ap, adev, adev->pio_mode); 428669a5db4SJeff Garzik } 429669a5db4SJeff Garzik 430669a5db4SJeff Garzik /** 431669a5db4SJeff Garzik * hpt370_set_dmamode - DMA timing setup 432669a5db4SJeff Garzik * @ap: ATA interface 433669a5db4SJeff Garzik * @adev: Device being configured 434669a5db4SJeff Garzik * 4351a1b172bSSergei Shtylyov * Set up the channel for MWDMA or UDMA modes. 436669a5db4SJeff Garzik */ 437669a5db4SJeff Garzik 438669a5db4SJeff Garzik static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) 439669a5db4SJeff Garzik { 4401a1b172bSSergei Shtylyov hpt370_set_mode(ap, adev, adev->dma_mode); 441669a5db4SJeff Garzik } 442669a5db4SJeff Garzik 443669a5db4SJeff Garzik /** 444669a5db4SJeff Garzik * hpt370_bmdma_end - DMA engine stop 445669a5db4SJeff Garzik * @qc: ATA command 446669a5db4SJeff Garzik * 447669a5db4SJeff Garzik * Work around the HPT370 DMA engine. 448669a5db4SJeff Garzik */ 449669a5db4SJeff Garzik 450669a5db4SJeff Garzik static void hpt370_bmdma_stop(struct ata_queued_cmd *qc) 451669a5db4SJeff Garzik { 452669a5db4SJeff Garzik struct ata_port *ap = qc->ap; 453669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 4540d5ff566STejun Heo void __iomem *bmdma = ap->ioaddr.bmdma_addr; 45556f46f8cSSergei Shtylyov u8 dma_stat = ioread8(bmdma + ATA_DMA_STATUS); 45656f46f8cSSergei Shtylyov u8 dma_cmd; 457669a5db4SJeff Garzik 45856f46f8cSSergei Shtylyov if (dma_stat & ATA_DMA_ACTIVE) { 459669a5db4SJeff Garzik udelay(20); 46056f46f8cSSergei Shtylyov dma_stat = ioread8(bmdma + ATA_DMA_STATUS); 461669a5db4SJeff Garzik } 46256f46f8cSSergei Shtylyov if (dma_stat & ATA_DMA_ACTIVE) { 463669a5db4SJeff Garzik /* Clear the engine */ 464669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 465669a5db4SJeff Garzik udelay(10); 466669a5db4SJeff Garzik /* Stop DMA */ 46756f46f8cSSergei Shtylyov dma_cmd = ioread8(bmdma + ATA_DMA_CMD); 46856f46f8cSSergei Shtylyov iowrite8(dma_cmd & ~ATA_DMA_START, bmdma + ATA_DMA_CMD); 469669a5db4SJeff Garzik /* Clear Error */ 47056f46f8cSSergei Shtylyov dma_stat = ioread8(bmdma + ATA_DMA_STATUS); 47156f46f8cSSergei Shtylyov iowrite8(dma_stat | ATA_DMA_INTR | ATA_DMA_ERR, 47256f46f8cSSergei Shtylyov bmdma + ATA_DMA_STATUS); 473669a5db4SJeff Garzik /* Clear the engine */ 474669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 475669a5db4SJeff Garzik udelay(10); 476669a5db4SJeff Garzik } 477669a5db4SJeff Garzik ata_bmdma_stop(qc); 478669a5db4SJeff Garzik } 479669a5db4SJeff Garzik 4801a1b172bSSergei Shtylyov static void hpt372_set_mode(struct ata_port *ap, struct ata_device *adev, 4811a1b172bSSergei Shtylyov u8 mode) 4821a1b172bSSergei Shtylyov { 4831a1b172bSSergei Shtylyov struct pci_dev *pdev = to_pci_dev(ap->host->dev); 4841a1b172bSSergei Shtylyov u32 addr1, addr2; 4851a1b172bSSergei Shtylyov u32 reg, timing, mask; 4861a1b172bSSergei Shtylyov u8 fast; 4871a1b172bSSergei Shtylyov 4881a1b172bSSergei Shtylyov addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 4891a1b172bSSergei Shtylyov addr2 = 0x51 + 4 * ap->port_no; 4901a1b172bSSergei Shtylyov 4911a1b172bSSergei Shtylyov /* Fast interrupt prediction disable, hold off interrupt disable */ 4921a1b172bSSergei Shtylyov pci_read_config_byte(pdev, addr2, &fast); 4931a1b172bSSergei Shtylyov fast &= ~0x07; 4941a1b172bSSergei Shtylyov pci_write_config_byte(pdev, addr2, fast); 4951a1b172bSSergei Shtylyov 4961a1b172bSSergei Shtylyov /* Determine timing mask and find matching mode entry */ 4971a1b172bSSergei Shtylyov if (mode < XFER_MW_DMA_0) 4981a1b172bSSergei Shtylyov mask = 0xcfc3ffff; 4991a1b172bSSergei Shtylyov else if (mode < XFER_UDMA_0) 5001a1b172bSSergei Shtylyov mask = 0x31c001ff; 5011a1b172bSSergei Shtylyov else 5021a1b172bSSergei Shtylyov mask = 0x303c0000; 5031a1b172bSSergei Shtylyov 5041a1b172bSSergei Shtylyov timing = hpt37x_find_mode(ap, mode); 5051a1b172bSSergei Shtylyov 5061a1b172bSSergei Shtylyov pci_read_config_dword(pdev, addr1, ®); 5071a1b172bSSergei Shtylyov reg = (reg & ~mask) | (timing & mask); 5081a1b172bSSergei Shtylyov pci_write_config_dword(pdev, addr1, reg); 5091a1b172bSSergei Shtylyov } 5101a1b172bSSergei Shtylyov 511669a5db4SJeff Garzik /** 512669a5db4SJeff Garzik * hpt372_set_piomode - PIO setup 513669a5db4SJeff Garzik * @ap: ATA interface 514669a5db4SJeff Garzik * @adev: device on the interface 515669a5db4SJeff Garzik * 516669a5db4SJeff Garzik * Perform PIO mode setup. 517669a5db4SJeff Garzik */ 518669a5db4SJeff Garzik 519669a5db4SJeff Garzik static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) 520669a5db4SJeff Garzik { 5211a1b172bSSergei Shtylyov hpt372_set_mode(ap, adev, adev->pio_mode); 522669a5db4SJeff Garzik } 523669a5db4SJeff Garzik 524669a5db4SJeff Garzik /** 525669a5db4SJeff Garzik * hpt372_set_dmamode - DMA timing setup 526669a5db4SJeff Garzik * @ap: ATA interface 527669a5db4SJeff Garzik * @adev: Device being configured 528669a5db4SJeff Garzik * 5291a1b172bSSergei Shtylyov * Set up the channel for MWDMA or UDMA modes. 530669a5db4SJeff Garzik */ 531669a5db4SJeff Garzik 532669a5db4SJeff Garzik static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) 533669a5db4SJeff Garzik { 5341a1b172bSSergei Shtylyov hpt372_set_mode(ap, adev, adev->dma_mode); 535669a5db4SJeff Garzik } 536669a5db4SJeff Garzik 537669a5db4SJeff Garzik /** 538669a5db4SJeff Garzik * hpt37x_bmdma_end - DMA engine stop 539669a5db4SJeff Garzik * @qc: ATA command 540669a5db4SJeff Garzik * 541669a5db4SJeff Garzik * Clean up after the HPT372 and later DMA engine 542669a5db4SJeff Garzik */ 543669a5db4SJeff Garzik 544669a5db4SJeff Garzik static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc) 545669a5db4SJeff Garzik { 546669a5db4SJeff Garzik struct ata_port *ap = qc->ap; 547669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 5486929da44SAlan int mscreg = 0x50 + 4 * ap->port_no; 549669a5db4SJeff Garzik u8 bwsr_stat, msc_stat; 550669a5db4SJeff Garzik 551669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x6A, &bwsr_stat); 552669a5db4SJeff Garzik pci_read_config_byte(pdev, mscreg, &msc_stat); 553669a5db4SJeff Garzik if (bwsr_stat & (1 << ap->port_no)) 554669a5db4SJeff Garzik pci_write_config_byte(pdev, mscreg, msc_stat | 0x30); 555669a5db4SJeff Garzik ata_bmdma_stop(qc); 556669a5db4SJeff Garzik } 557669a5db4SJeff Garzik 558669a5db4SJeff Garzik 559669a5db4SJeff Garzik static struct scsi_host_template hpt37x_sht = { 56068d1d07bSTejun Heo ATA_BMDMA_SHT(DRV_NAME), 561669a5db4SJeff Garzik }; 562669a5db4SJeff Garzik 563669a5db4SJeff Garzik /* 564669a5db4SJeff Garzik * Configuration for HPT370 565669a5db4SJeff Garzik */ 566669a5db4SJeff Garzik 567669a5db4SJeff Garzik static struct ata_port_operations hpt370_port_ops = { 568029cfd6bSTejun Heo .inherits = &ata_bmdma_port_ops, 569669a5db4SJeff Garzik 570669a5db4SJeff Garzik .bmdma_stop = hpt370_bmdma_stop, 571669a5db4SJeff Garzik 572029cfd6bSTejun Heo .mode_filter = hpt370_filter, 5739e87be9eSBartlomiej Zolnierkiewicz .cable_detect = hpt37x_cable_detect, 574029cfd6bSTejun Heo .set_piomode = hpt370_set_piomode, 575029cfd6bSTejun Heo .set_dmamode = hpt370_set_dmamode, 576a1efdabaSTejun Heo .prereset = hpt37x_pre_reset, 577669a5db4SJeff Garzik }; 578669a5db4SJeff Garzik 579669a5db4SJeff Garzik /* 580669a5db4SJeff Garzik * Configuration for HPT370A. Close to 370 but less filters 581669a5db4SJeff Garzik */ 582669a5db4SJeff Garzik 583669a5db4SJeff Garzik static struct ata_port_operations hpt370a_port_ops = { 584029cfd6bSTejun Heo .inherits = &hpt370_port_ops, 585669a5db4SJeff Garzik .mode_filter = hpt370a_filter, 586669a5db4SJeff Garzik }; 587669a5db4SJeff Garzik 588669a5db4SJeff Garzik /* 589669a5db4SJeff Garzik * Configuration for HPT372, HPT371, HPT302. Slightly different PIO 590669a5db4SJeff Garzik * and DMA mode setting functionality. 591669a5db4SJeff Garzik */ 592669a5db4SJeff Garzik 593669a5db4SJeff Garzik static struct ata_port_operations hpt372_port_ops = { 594029cfd6bSTejun Heo .inherits = &ata_bmdma_port_ops, 595029cfd6bSTejun Heo 596029cfd6bSTejun Heo .bmdma_stop = hpt37x_bmdma_stop, 597029cfd6bSTejun Heo 5989e87be9eSBartlomiej Zolnierkiewicz .cable_detect = hpt37x_cable_detect, 599669a5db4SJeff Garzik .set_piomode = hpt372_set_piomode, 600669a5db4SJeff Garzik .set_dmamode = hpt372_set_dmamode, 601a1efdabaSTejun Heo .prereset = hpt37x_pre_reset, 602669a5db4SJeff Garzik }; 603669a5db4SJeff Garzik 604669a5db4SJeff Garzik /* 605669a5db4SJeff Garzik * Configuration for HPT374. Mode setting works like 372 and friends 606a1efdabaSTejun Heo * but we have a different cable detection procedure for function 1. 607669a5db4SJeff Garzik */ 608669a5db4SJeff Garzik 609a1efdabaSTejun Heo static struct ata_port_operations hpt374_fn1_port_ops = { 610029cfd6bSTejun Heo .inherits = &hpt372_port_ops, 6119e87be9eSBartlomiej Zolnierkiewicz .cable_detect = hpt374_fn1_cable_detect, 612ab81a505SBartlomiej Zolnierkiewicz .prereset = hpt37x_pre_reset, 613669a5db4SJeff Garzik }; 614669a5db4SJeff Garzik 615669a5db4SJeff Garzik /** 616ad452d64SKrzysztof Halasa * hpt37x_clock_slot - Turn timing to PC clock entry 617669a5db4SJeff Garzik * @freq: Reported frequency timing 618669a5db4SJeff Garzik * @base: Base timing 619669a5db4SJeff Garzik * 620669a5db4SJeff Garzik * Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50 621669a5db4SJeff Garzik * and 3 for 66Mhz) 622669a5db4SJeff Garzik */ 623669a5db4SJeff Garzik 624669a5db4SJeff Garzik static int hpt37x_clock_slot(unsigned int freq, unsigned int base) 625669a5db4SJeff Garzik { 626669a5db4SJeff Garzik unsigned int f = (base * freq) / 192; /* Mhz */ 627669a5db4SJeff Garzik if (f < 40) 628669a5db4SJeff Garzik return 0; /* 33Mhz slot */ 629669a5db4SJeff Garzik if (f < 45) 630669a5db4SJeff Garzik return 1; /* 40Mhz slot */ 631669a5db4SJeff Garzik if (f < 55) 632669a5db4SJeff Garzik return 2; /* 50Mhz slot */ 633669a5db4SJeff Garzik return 3; /* 60Mhz slot */ 634669a5db4SJeff Garzik } 635669a5db4SJeff Garzik 636669a5db4SJeff Garzik /** 637669a5db4SJeff Garzik * hpt37x_calibrate_dpll - Calibrate the DPLL loop 638669a5db4SJeff Garzik * @dev: PCI device 639669a5db4SJeff Garzik * 640669a5db4SJeff Garzik * Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this 641669a5db4SJeff Garzik * succeeds 642669a5db4SJeff Garzik */ 643669a5db4SJeff Garzik 644669a5db4SJeff Garzik static int hpt37x_calibrate_dpll(struct pci_dev *dev) 645669a5db4SJeff Garzik { 646669a5db4SJeff Garzik u8 reg5b; 647669a5db4SJeff Garzik u32 reg5c; 648669a5db4SJeff Garzik int tries; 649669a5db4SJeff Garzik 650669a5db4SJeff Garzik for(tries = 0; tries < 0x5000; tries++) { 651669a5db4SJeff Garzik udelay(50); 652669a5db4SJeff Garzik pci_read_config_byte(dev, 0x5b, ®5b); 653669a5db4SJeff Garzik if (reg5b & 0x80) { 654669a5db4SJeff Garzik /* See if it stays set */ 655669a5db4SJeff Garzik for(tries = 0; tries < 0x1000; tries ++) { 656669a5db4SJeff Garzik pci_read_config_byte(dev, 0x5b, ®5b); 657669a5db4SJeff Garzik /* Failed ? */ 658669a5db4SJeff Garzik if ((reg5b & 0x80) == 0) 659669a5db4SJeff Garzik return 0; 660669a5db4SJeff Garzik } 661669a5db4SJeff Garzik /* Turn off tuning, we have the DPLL set */ 662669a5db4SJeff Garzik pci_read_config_dword(dev, 0x5c, ®5c); 663669a5db4SJeff Garzik pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); 664669a5db4SJeff Garzik return 1; 665669a5db4SJeff Garzik } 666669a5db4SJeff Garzik } 667669a5db4SJeff Garzik /* Never went stable */ 668669a5db4SJeff Garzik return 0; 669669a5db4SJeff Garzik } 67073946f9fSAlan Cox 67173946f9fSAlan Cox static u32 hpt374_read_freq(struct pci_dev *pdev) 67273946f9fSAlan Cox { 67373946f9fSAlan Cox u32 freq; 67473946f9fSAlan Cox unsigned long io_base = pci_resource_start(pdev, 4); 67573946f9fSAlan Cox if (PCI_FUNC(pdev->devfn) & 1) { 67640f46f17SAndrew Morton struct pci_dev *pdev_0; 67740f46f17SAndrew Morton 67840f46f17SAndrew Morton pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1); 67973946f9fSAlan Cox /* Someone hot plugged the controller on us ? */ 68073946f9fSAlan Cox if (pdev_0 == NULL) 68173946f9fSAlan Cox return 0; 68273946f9fSAlan Cox io_base = pci_resource_start(pdev_0, 4); 68373946f9fSAlan Cox freq = inl(io_base + 0x90); 68473946f9fSAlan Cox pci_dev_put(pdev_0); 68540f46f17SAndrew Morton } else 68673946f9fSAlan Cox freq = inl(io_base + 0x90); 68773946f9fSAlan Cox return freq; 68873946f9fSAlan Cox } 68973946f9fSAlan Cox 690669a5db4SJeff Garzik /** 691669a5db4SJeff Garzik * hpt37x_init_one - Initialise an HPT37X/302 692669a5db4SJeff Garzik * @dev: PCI device 693669a5db4SJeff Garzik * @id: Entry in match table 694669a5db4SJeff Garzik * 695669a5db4SJeff Garzik * Initialise an HPT37x device. There are some interesting complications 696669a5db4SJeff Garzik * here. Firstly the chip may report 366 and be one of several variants. 697669a5db4SJeff Garzik * Secondly all the timings depend on the clock for the chip which we must 698669a5db4SJeff Garzik * detect and look up 699669a5db4SJeff Garzik * 700669a5db4SJeff Garzik * This is the known chip mappings. It may be missing a couple of later 701669a5db4SJeff Garzik * releases. 702669a5db4SJeff Garzik * 703669a5db4SJeff Garzik * Chip version PCI Rev Notes 704669a5db4SJeff Garzik * HPT366 4 (HPT366) 0 Other driver 705669a5db4SJeff Garzik * HPT366 4 (HPT366) 1 Other driver 706669a5db4SJeff Garzik * HPT368 4 (HPT366) 2 Other driver 707669a5db4SJeff Garzik * HPT370 4 (HPT366) 3 UDMA100 708669a5db4SJeff Garzik * HPT370A 4 (HPT366) 4 UDMA100 709669a5db4SJeff Garzik * HPT372 4 (HPT366) 5 UDMA133 (1) 710669a5db4SJeff Garzik * HPT372N 4 (HPT366) 6 Other driver 711669a5db4SJeff Garzik * HPT372A 5 (HPT372) 1 UDMA133 (1) 712669a5db4SJeff Garzik * HPT372N 5 (HPT372) 2 Other driver 713669a5db4SJeff Garzik * HPT302 6 (HPT302) 1 UDMA133 714669a5db4SJeff Garzik * HPT302N 6 (HPT302) 2 Other driver 715669a5db4SJeff Garzik * HPT371 7 (HPT371) * UDMA133 716669a5db4SJeff Garzik * HPT374 8 (HPT374) * UDMA133 4 channel 717669a5db4SJeff Garzik * HPT372N 9 (HPT372N) * Other driver 718669a5db4SJeff Garzik * 719669a5db4SJeff Garzik * (1) UDMA133 support depends on the bus clock 720669a5db4SJeff Garzik */ 721669a5db4SJeff Garzik 722669a5db4SJeff Garzik static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) 723669a5db4SJeff Garzik { 724669a5db4SJeff Garzik /* HPT370 - UDMA100 */ 7251626aeb8STejun Heo static const struct ata_port_info info_hpt370 = { 7261d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 72714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 72814bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 729bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 730669a5db4SJeff Garzik .port_ops = &hpt370_port_ops 731669a5db4SJeff Garzik }; 732669a5db4SJeff Garzik /* HPT370A - UDMA100 */ 7331626aeb8STejun Heo static const struct ata_port_info info_hpt370a = { 7341d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 73514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 73614bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 737bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 738669a5db4SJeff Garzik .port_ops = &hpt370a_port_ops 739669a5db4SJeff Garzik }; 740fcc2f69aSAlan Cox /* HPT370 - UDMA100 */ 7411626aeb8STejun Heo static const struct ata_port_info info_hpt370_33 = { 7421d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 74314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 74414bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 74573946f9fSAlan Cox .udma_mask = ATA_UDMA5, 746fcc2f69aSAlan Cox .port_ops = &hpt370_port_ops 747fcc2f69aSAlan Cox }; 748fcc2f69aSAlan Cox /* HPT370A - UDMA100 */ 7491626aeb8STejun Heo static const struct ata_port_info info_hpt370a_33 = { 7501d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 75114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 75214bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 75373946f9fSAlan Cox .udma_mask = ATA_UDMA5, 754fcc2f69aSAlan Cox .port_ops = &hpt370a_port_ops 755fcc2f69aSAlan Cox }; 756669a5db4SJeff Garzik /* HPT371, 372 and friends - UDMA133 */ 7571626aeb8STejun Heo static const struct ata_port_info info_hpt372 = { 7581d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 75914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 76014bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 761bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 762669a5db4SJeff Garzik .port_ops = &hpt372_port_ops 763669a5db4SJeff Garzik }; 764a1efdabaSTejun Heo /* HPT374 - UDMA100, function 1 uses different prereset method */ 765a1efdabaSTejun Heo static const struct ata_port_info info_hpt374_fn0 = { 7661d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 76714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 76814bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 769bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 770a1efdabaSTejun Heo .port_ops = &hpt372_port_ops 771a1efdabaSTejun Heo }; 772a1efdabaSTejun Heo static const struct ata_port_info info_hpt374_fn1 = { 773a1efdabaSTejun Heo .flags = ATA_FLAG_SLAVE_POSS, 77414bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 77514bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 776a1efdabaSTejun Heo .udma_mask = ATA_UDMA5, 777a1efdabaSTejun Heo .port_ops = &hpt374_fn1_port_ops 778669a5db4SJeff Garzik }; 779669a5db4SJeff Garzik 780669a5db4SJeff Garzik static const int MHz[4] = { 33, 40, 50, 66 }; 7811626aeb8STejun Heo void *private_data = NULL; 782887125e3STejun Heo const struct ata_port_info *ppi[] = { NULL, NULL }; 78389d3b360SSergei Shtylyov u8 rev = dev->revision; 784669a5db4SJeff Garzik u8 irqmask; 785fcc2f69aSAlan Cox u8 mcr1; 786669a5db4SJeff Garzik u32 freq; 787fcc2f69aSAlan Cox int prefer_dpll = 1; 788fcc2f69aSAlan Cox 789fcc2f69aSAlan Cox unsigned long iobase = pci_resource_start(dev, 4); 790669a5db4SJeff Garzik 791669a5db4SJeff Garzik const struct hpt_chip *chip_table; 792669a5db4SJeff Garzik int clock_slot; 793f08048e9STejun Heo int rc; 794f08048e9STejun Heo 795f08048e9STejun Heo rc = pcim_enable_device(dev); 796f08048e9STejun Heo if (rc) 797f08048e9STejun Heo return rc; 798669a5db4SJeff Garzik 799669a5db4SJeff Garzik if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { 800669a5db4SJeff Garzik /* May be a later chip in disguise. Check */ 801669a5db4SJeff Garzik /* Older chips are in the HPT366 driver. Ignore them */ 80289d3b360SSergei Shtylyov if (rev < 3) 803669a5db4SJeff Garzik return -ENODEV; 804669a5db4SJeff Garzik /* N series chips have their own driver. Ignore */ 80589d3b360SSergei Shtylyov if (rev == 6) 806669a5db4SJeff Garzik return -ENODEV; 807669a5db4SJeff Garzik 80889d3b360SSergei Shtylyov switch(rev) { 809669a5db4SJeff Garzik case 3: 810887125e3STejun Heo ppi[0] = &info_hpt370; 811669a5db4SJeff Garzik chip_table = &hpt370; 812fcc2f69aSAlan Cox prefer_dpll = 0; 813669a5db4SJeff Garzik break; 814669a5db4SJeff Garzik case 4: 815887125e3STejun Heo ppi[0] = &info_hpt370a; 816669a5db4SJeff Garzik chip_table = &hpt370a; 817fcc2f69aSAlan Cox prefer_dpll = 0; 818669a5db4SJeff Garzik break; 819669a5db4SJeff Garzik case 5: 820887125e3STejun Heo ppi[0] = &info_hpt372; 821669a5db4SJeff Garzik chip_table = &hpt372; 822669a5db4SJeff Garzik break; 823669a5db4SJeff Garzik default: 82489d3b360SSergei Shtylyov printk(KERN_ERR "pata_hpt37x: Unknown HPT366 " 82589d3b360SSergei Shtylyov "subtype, please report (%d).\n", rev); 826669a5db4SJeff Garzik return -ENODEV; 827669a5db4SJeff Garzik } 828669a5db4SJeff Garzik } else { 829669a5db4SJeff Garzik switch(dev->device) { 830669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT372: 831669a5db4SJeff Garzik /* 372N if rev >= 2*/ 83289d3b360SSergei Shtylyov if (rev >= 2) 833669a5db4SJeff Garzik return -ENODEV; 834887125e3STejun Heo ppi[0] = &info_hpt372; 835669a5db4SJeff Garzik chip_table = &hpt372a; 836669a5db4SJeff Garzik break; 837669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT302: 838669a5db4SJeff Garzik /* 302N if rev > 1 */ 83989d3b360SSergei Shtylyov if (rev > 1) 840669a5db4SJeff Garzik return -ENODEV; 841887125e3STejun Heo ppi[0] = &info_hpt372; 842669a5db4SJeff Garzik /* Check this */ 843669a5db4SJeff Garzik chip_table = &hpt302; 844669a5db4SJeff Garzik break; 845669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT371: 84689d3b360SSergei Shtylyov if (rev > 1) 847fcc2f69aSAlan Cox return -ENODEV; 848887125e3STejun Heo ppi[0] = &info_hpt372; 849669a5db4SJeff Garzik chip_table = &hpt371; 850a4734468SAlan Cox /* Single channel device, master is not present 851a4734468SAlan Cox but the BIOS (or us for non x86) must mark it 852fcc2f69aSAlan Cox absent */ 853fcc2f69aSAlan Cox pci_read_config_byte(dev, 0x50, &mcr1); 854fcc2f69aSAlan Cox mcr1 &= ~0x04; 855fcc2f69aSAlan Cox pci_write_config_byte(dev, 0x50, mcr1); 856669a5db4SJeff Garzik break; 857669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT374: 858669a5db4SJeff Garzik chip_table = &hpt374; 859a1efdabaSTejun Heo if (!(PCI_FUNC(dev->devfn) & 1)) 860a1efdabaSTejun Heo *ppi = &info_hpt374_fn0; 861a1efdabaSTejun Heo else 862a1efdabaSTejun Heo *ppi = &info_hpt374_fn1; 863669a5db4SJeff Garzik break; 864669a5db4SJeff Garzik default: 865669a5db4SJeff Garzik printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device); 866669a5db4SJeff Garzik return -ENODEV; 867669a5db4SJeff Garzik } 868669a5db4SJeff Garzik } 869669a5db4SJeff Garzik /* Ok so this is a chip we support */ 870669a5db4SJeff Garzik 871669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); 872669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); 873669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); 874669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); 875669a5db4SJeff Garzik 876669a5db4SJeff Garzik pci_read_config_byte(dev, 0x5A, &irqmask); 877669a5db4SJeff Garzik irqmask &= ~0x10; 878669a5db4SJeff Garzik pci_write_config_byte(dev, 0x5a, irqmask); 879669a5db4SJeff Garzik 880669a5db4SJeff Garzik /* 881669a5db4SJeff Garzik * default to pci clock. make sure MA15/16 are set to output 882669a5db4SJeff Garzik * to prevent drives having problems with 40-pin cables. Needed 883669a5db4SJeff Garzik * for some drives such as IBM-DTLA which will not enter ready 884669a5db4SJeff Garzik * state on reset when PDIAG is a input. 885669a5db4SJeff Garzik */ 886669a5db4SJeff Garzik 887669a5db4SJeff Garzik pci_write_config_byte(dev, 0x5b, 0x23); 888669a5db4SJeff Garzik 889fcc2f69aSAlan Cox /* 890fcc2f69aSAlan Cox * HighPoint does this for HPT372A. 891fcc2f69aSAlan Cox * NOTE: This register is only writeable via I/O space. 892fcc2f69aSAlan Cox */ 893fcc2f69aSAlan Cox if (chip_table == &hpt372a) 894fcc2f69aSAlan Cox outb(0x0e, iobase + 0x9c); 895fcc2f69aSAlan Cox 896fcc2f69aSAlan Cox /* Some devices do not let this value be accessed via PCI space 89773946f9fSAlan Cox according to the old driver. In addition we must use the value 89873946f9fSAlan Cox from FN 0 on the HPT374 */ 899fcc2f69aSAlan Cox 90073946f9fSAlan Cox if (chip_table == &hpt374) { 90173946f9fSAlan Cox freq = hpt374_read_freq(dev); 90273946f9fSAlan Cox if (freq == 0) 90373946f9fSAlan Cox return -ENODEV; 90473946f9fSAlan Cox } else 905fcc2f69aSAlan Cox freq = inl(iobase + 0x90); 90673946f9fSAlan Cox 907669a5db4SJeff Garzik if ((freq >> 12) != 0xABCDE) { 908669a5db4SJeff Garzik int i; 909669a5db4SJeff Garzik u8 sr; 910669a5db4SJeff Garzik u32 total = 0; 911669a5db4SJeff Garzik 912669a5db4SJeff Garzik printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n"); 913669a5db4SJeff Garzik 914669a5db4SJeff Garzik /* This is the process the HPT371 BIOS is reported to use */ 915669a5db4SJeff Garzik for(i = 0; i < 128; i++) { 916669a5db4SJeff Garzik pci_read_config_byte(dev, 0x78, &sr); 917fcc2f69aSAlan Cox total += sr & 0x1FF; 918669a5db4SJeff Garzik udelay(15); 919669a5db4SJeff Garzik } 920669a5db4SJeff Garzik freq = total / 128; 921669a5db4SJeff Garzik } 922669a5db4SJeff Garzik freq &= 0x1FF; 923669a5db4SJeff Garzik 924669a5db4SJeff Garzik /* 925669a5db4SJeff Garzik * Turn the frequency check into a band and then find a timing 926669a5db4SJeff Garzik * table to match it. 927669a5db4SJeff Garzik */ 928669a5db4SJeff Garzik 929669a5db4SJeff Garzik clock_slot = hpt37x_clock_slot(freq, chip_table->base); 930fcc2f69aSAlan Cox if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) { 931669a5db4SJeff Garzik /* 932669a5db4SJeff Garzik * We need to try PLL mode instead 933fcc2f69aSAlan Cox * 934fcc2f69aSAlan Cox * For non UDMA133 capable devices we should 935fcc2f69aSAlan Cox * use a 50MHz DPLL by choice 936669a5db4SJeff Garzik */ 937fcc2f69aSAlan Cox unsigned int f_low, f_high; 938960c8a10SAlan Cox int dpll, adjust; 939669a5db4SJeff Garzik 940960c8a10SAlan Cox /* Compute DPLL */ 941887125e3STejun Heo dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2; 942fcc2f69aSAlan Cox 943960c8a10SAlan Cox f_low = (MHz[clock_slot] * 48) / MHz[dpll]; 944fcc2f69aSAlan Cox f_high = f_low + 2; 945960c8a10SAlan Cox if (clock_slot > 1) 946960c8a10SAlan Cox f_high += 2; 947fcc2f69aSAlan Cox 948fcc2f69aSAlan Cox /* Select the DPLL clock. */ 949fcc2f69aSAlan Cox pci_write_config_byte(dev, 0x5b, 0x21); 95064a81709SAlan Cox pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); 951fcc2f69aSAlan Cox 952669a5db4SJeff Garzik for(adjust = 0; adjust < 8; adjust++) { 953669a5db4SJeff Garzik if (hpt37x_calibrate_dpll(dev)) 954669a5db4SJeff Garzik break; 955669a5db4SJeff Garzik /* See if it'll settle at a fractionally different clock */ 95664a81709SAlan Cox if (adjust & 1) 95764a81709SAlan Cox f_low -= adjust >> 1; 95864a81709SAlan Cox else 95964a81709SAlan Cox f_high += adjust >> 1; 96064a81709SAlan Cox pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); 961669a5db4SJeff Garzik } 962669a5db4SJeff Garzik if (adjust == 8) { 96380b8987cSSergei Shtylyov printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n"); 964669a5db4SJeff Garzik return -ENODEV; 965669a5db4SJeff Garzik } 966960c8a10SAlan Cox if (dpll == 3) 9671626aeb8STejun Heo private_data = (void *)hpt37x_timings_66; 968fcc2f69aSAlan Cox else 9691626aeb8STejun Heo private_data = (void *)hpt37x_timings_50; 970669a5db4SJeff Garzik 97180b8987cSSergei Shtylyov printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n", 97280b8987cSSergei Shtylyov MHz[clock_slot], MHz[dpll]); 973669a5db4SJeff Garzik } else { 9741626aeb8STejun Heo private_data = (void *)chip_table->clocks[clock_slot]; 975669a5db4SJeff Garzik /* 976a4734468SAlan Cox * Perform a final fixup. Note that we will have used the 977a4734468SAlan Cox * DPLL on the HPT372 which means we don't have to worry 978a4734468SAlan Cox * about lack of UDMA133 support on lower clocks 979669a5db4SJeff Garzik */ 980669a5db4SJeff Garzik 981887125e3STejun Heo if (clock_slot < 2 && ppi[0] == &info_hpt370) 982887125e3STejun Heo ppi[0] = &info_hpt370_33; 983887125e3STejun Heo if (clock_slot < 2 && ppi[0] == &info_hpt370a) 984887125e3STejun Heo ppi[0] = &info_hpt370a_33; 98580b8987cSSergei Shtylyov printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n", 98680b8987cSSergei Shtylyov chip_table->name, MHz[clock_slot]); 987669a5db4SJeff Garzik } 988fcc2f69aSAlan Cox 989669a5db4SJeff Garzik /* Now kick off ATA set up */ 9901c5afdf7STejun Heo return ata_pci_bmdma_init_one(dev, ppi, &hpt37x_sht, private_data, 0); 991669a5db4SJeff Garzik } 992669a5db4SJeff Garzik 9932d2744fcSJeff Garzik static const struct pci_device_id hpt37x[] = { 9942d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, 9952d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), }, 9962d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), }, 9972d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), }, 9982d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), }, 9992d2744fcSJeff Garzik 10002d2744fcSJeff Garzik { }, 1001669a5db4SJeff Garzik }; 1002669a5db4SJeff Garzik 1003669a5db4SJeff Garzik static struct pci_driver hpt37x_pci_driver = { 1004669a5db4SJeff Garzik .name = DRV_NAME, 1005669a5db4SJeff Garzik .id_table = hpt37x, 1006669a5db4SJeff Garzik .probe = hpt37x_init_one, 1007669a5db4SJeff Garzik .remove = ata_pci_remove_one 1008669a5db4SJeff Garzik }; 1009669a5db4SJeff Garzik 1010669a5db4SJeff Garzik static int __init hpt37x_init(void) 1011669a5db4SJeff Garzik { 1012669a5db4SJeff Garzik return pci_register_driver(&hpt37x_pci_driver); 1013669a5db4SJeff Garzik } 1014669a5db4SJeff Garzik 1015669a5db4SJeff Garzik static void __exit hpt37x_exit(void) 1016669a5db4SJeff Garzik { 1017669a5db4SJeff Garzik pci_unregister_driver(&hpt37x_pci_driver); 1018669a5db4SJeff Garzik } 1019669a5db4SJeff Garzik 1020669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox"); 1021669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x"); 1022669a5db4SJeff Garzik MODULE_LICENSE("GPL"); 1023669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, hpt37x); 1024669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION); 1025669a5db4SJeff Garzik 1026669a5db4SJeff Garzik module_init(hpt37x_init); 1027669a5db4SJeff Garzik module_exit(hpt37x_exit); 1028