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" 275600c70eSSergei Shtylyov #define DRV_VERSION "0.6.14" 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 42669a5db4SJeff Garzik * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW 43669a5db4SJeff Garzik * DMA. cycles = value + 1 44669a5db4SJeff Garzik * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW 45669a5db4SJeff Garzik * DMA. cycles = value + 1 46669a5db4SJeff Garzik * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file 47669a5db4SJeff Garzik * register access. 48669a5db4SJeff Garzik * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file 49669a5db4SJeff Garzik * register access. 50669a5db4SJeff Garzik * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. 51669a5db4SJeff Garzik * during task file register access. 52669a5db4SJeff Garzik * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA 53669a5db4SJeff Garzik * xfer. 54669a5db4SJeff Garzik * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task 55669a5db4SJeff Garzik * register access. 56669a5db4SJeff Garzik * 28 UDMA enable 57669a5db4SJeff Garzik * 29 DMA enable 58669a5db4SJeff Garzik * 30 PIO_MST enable. if set, the chip is in bus master mode during 59669a5db4SJeff Garzik * PIO. 60669a5db4SJeff Garzik * 31 FIFO enable. 61669a5db4SJeff Garzik */ 62669a5db4SJeff Garzik 63fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_33[] = { 64fcc2f69aSAlan Cox { XFER_UDMA_6, 0x12446231 }, /* 0x12646231 ?? */ 65669a5db4SJeff Garzik { XFER_UDMA_5, 0x12446231 }, 66669a5db4SJeff Garzik { XFER_UDMA_4, 0x12446231 }, 67669a5db4SJeff Garzik { XFER_UDMA_3, 0x126c6231 }, 68669a5db4SJeff Garzik { XFER_UDMA_2, 0x12486231 }, 69669a5db4SJeff Garzik { XFER_UDMA_1, 0x124c6233 }, 70669a5db4SJeff Garzik { XFER_UDMA_0, 0x12506297 }, 71669a5db4SJeff Garzik 72669a5db4SJeff Garzik { XFER_MW_DMA_2, 0x22406c31 }, 73669a5db4SJeff Garzik { XFER_MW_DMA_1, 0x22406c33 }, 74669a5db4SJeff Garzik { XFER_MW_DMA_0, 0x22406c97 }, 75669a5db4SJeff Garzik 76669a5db4SJeff Garzik { XFER_PIO_4, 0x06414e31 }, 77669a5db4SJeff Garzik { XFER_PIO_3, 0x06414e42 }, 78669a5db4SJeff Garzik { XFER_PIO_2, 0x06414e53 }, 79669a5db4SJeff Garzik { XFER_PIO_1, 0x06814e93 }, 80fcc2f69aSAlan Cox { XFER_PIO_0, 0x06814ea7 } 81669a5db4SJeff Garzik }; 82669a5db4SJeff Garzik 83fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_50[] = { 84fcc2f69aSAlan Cox { XFER_UDMA_6, 0x12848242 }, 85669a5db4SJeff Garzik { XFER_UDMA_5, 0x12848242 }, 86669a5db4SJeff Garzik { XFER_UDMA_4, 0x12ac8242 }, 87669a5db4SJeff Garzik { XFER_UDMA_3, 0x128c8242 }, 88669a5db4SJeff Garzik { XFER_UDMA_2, 0x120c8242 }, 89669a5db4SJeff Garzik { XFER_UDMA_1, 0x12148254 }, 90669a5db4SJeff Garzik { XFER_UDMA_0, 0x121882ea }, 91669a5db4SJeff Garzik 92669a5db4SJeff Garzik { XFER_MW_DMA_2, 0x22808242 }, 93669a5db4SJeff Garzik { XFER_MW_DMA_1, 0x22808254 }, 94669a5db4SJeff Garzik { XFER_MW_DMA_0, 0x228082ea }, 95669a5db4SJeff Garzik 96669a5db4SJeff Garzik { XFER_PIO_4, 0x0a81f442 }, 97669a5db4SJeff Garzik { XFER_PIO_3, 0x0a81f443 }, 98669a5db4SJeff Garzik { XFER_PIO_2, 0x0a81f454 }, 99669a5db4SJeff Garzik { XFER_PIO_1, 0x0ac1f465 }, 100fcc2f69aSAlan Cox { XFER_PIO_0, 0x0ac1f48a } 101669a5db4SJeff Garzik }; 102669a5db4SJeff Garzik 103fcc2f69aSAlan Cox static struct hpt_clock hpt37x_timings_66[] = { 104669a5db4SJeff Garzik { XFER_UDMA_6, 0x1c869c62 }, 105fcc2f69aSAlan Cox { XFER_UDMA_5, 0x1cae9c62 }, /* 0x1c8a9c62 */ 106669a5db4SJeff Garzik { XFER_UDMA_4, 0x1c8a9c62 }, 107669a5db4SJeff Garzik { XFER_UDMA_3, 0x1c8e9c62 }, 108669a5db4SJeff Garzik { XFER_UDMA_2, 0x1c929c62 }, 109669a5db4SJeff Garzik { XFER_UDMA_1, 0x1c9a9c62 }, 110669a5db4SJeff Garzik { XFER_UDMA_0, 0x1c829c62 }, 111669a5db4SJeff Garzik 112669a5db4SJeff Garzik { XFER_MW_DMA_2, 0x2c829c62 }, 113669a5db4SJeff Garzik { XFER_MW_DMA_1, 0x2c829c66 }, 114669a5db4SJeff Garzik { XFER_MW_DMA_0, 0x2c829d2e }, 115669a5db4SJeff Garzik 116669a5db4SJeff Garzik { XFER_PIO_4, 0x0c829c62 }, 117669a5db4SJeff Garzik { XFER_PIO_3, 0x0c829c84 }, 118669a5db4SJeff Garzik { XFER_PIO_2, 0x0c829ca6 }, 119669a5db4SJeff Garzik { XFER_PIO_1, 0x0d029d26 }, 120fcc2f69aSAlan Cox { XFER_PIO_0, 0x0d029d5e } 121669a5db4SJeff Garzik }; 122669a5db4SJeff Garzik 123669a5db4SJeff Garzik 124669a5db4SJeff Garzik static const struct hpt_chip hpt370 = { 125669a5db4SJeff Garzik "HPT370", 126669a5db4SJeff Garzik 48, 127669a5db4SJeff Garzik { 128fcc2f69aSAlan Cox hpt37x_timings_33, 129669a5db4SJeff Garzik NULL, 130669a5db4SJeff Garzik NULL, 131a4734468SAlan Cox NULL 132669a5db4SJeff Garzik } 133669a5db4SJeff Garzik }; 134669a5db4SJeff Garzik 135669a5db4SJeff Garzik static const struct hpt_chip hpt370a = { 136669a5db4SJeff Garzik "HPT370A", 137669a5db4SJeff Garzik 48, 138669a5db4SJeff Garzik { 139fcc2f69aSAlan Cox hpt37x_timings_33, 140669a5db4SJeff Garzik NULL, 141fcc2f69aSAlan Cox hpt37x_timings_50, 142a4734468SAlan Cox NULL 143669a5db4SJeff Garzik } 144669a5db4SJeff Garzik }; 145669a5db4SJeff Garzik 146669a5db4SJeff Garzik static const struct hpt_chip hpt372 = { 147669a5db4SJeff Garzik "HPT372", 148669a5db4SJeff Garzik 55, 149669a5db4SJeff Garzik { 150fcc2f69aSAlan Cox hpt37x_timings_33, 151669a5db4SJeff Garzik NULL, 152fcc2f69aSAlan Cox hpt37x_timings_50, 153fcc2f69aSAlan Cox hpt37x_timings_66 154669a5db4SJeff Garzik } 155669a5db4SJeff Garzik }; 156669a5db4SJeff Garzik 157669a5db4SJeff Garzik static const struct hpt_chip hpt302 = { 158669a5db4SJeff Garzik "HPT302", 159669a5db4SJeff Garzik 66, 160669a5db4SJeff Garzik { 161fcc2f69aSAlan Cox hpt37x_timings_33, 162669a5db4SJeff Garzik NULL, 163fcc2f69aSAlan Cox hpt37x_timings_50, 164fcc2f69aSAlan Cox hpt37x_timings_66 165669a5db4SJeff Garzik } 166669a5db4SJeff Garzik }; 167669a5db4SJeff Garzik 168669a5db4SJeff Garzik static const struct hpt_chip hpt371 = { 169669a5db4SJeff Garzik "HPT371", 170669a5db4SJeff Garzik 66, 171669a5db4SJeff Garzik { 172fcc2f69aSAlan Cox hpt37x_timings_33, 173669a5db4SJeff Garzik NULL, 174fcc2f69aSAlan Cox hpt37x_timings_50, 175fcc2f69aSAlan Cox hpt37x_timings_66 176669a5db4SJeff Garzik } 177669a5db4SJeff Garzik }; 178669a5db4SJeff Garzik 179669a5db4SJeff Garzik static const struct hpt_chip hpt372a = { 180669a5db4SJeff Garzik "HPT372A", 181669a5db4SJeff Garzik 66, 182669a5db4SJeff Garzik { 183fcc2f69aSAlan Cox hpt37x_timings_33, 184669a5db4SJeff Garzik NULL, 185fcc2f69aSAlan Cox hpt37x_timings_50, 186fcc2f69aSAlan Cox hpt37x_timings_66 187669a5db4SJeff Garzik } 188669a5db4SJeff Garzik }; 189669a5db4SJeff Garzik 190669a5db4SJeff Garzik static const struct hpt_chip hpt374 = { 191669a5db4SJeff Garzik "HPT374", 192669a5db4SJeff Garzik 48, 193669a5db4SJeff Garzik { 194fcc2f69aSAlan Cox hpt37x_timings_33, 195669a5db4SJeff Garzik NULL, 196669a5db4SJeff Garzik NULL, 197669a5db4SJeff Garzik NULL 198669a5db4SJeff Garzik } 199669a5db4SJeff Garzik }; 200669a5db4SJeff Garzik 201669a5db4SJeff Garzik /** 202669a5db4SJeff Garzik * hpt37x_find_mode - reset the hpt37x bus 203669a5db4SJeff Garzik * @ap: ATA port 204669a5db4SJeff Garzik * @speed: transfer mode 205669a5db4SJeff Garzik * 206669a5db4SJeff Garzik * Return the 32bit register programming information for this channel 207669a5db4SJeff Garzik * that matches the speed provided. 208669a5db4SJeff Garzik */ 209669a5db4SJeff Garzik 210669a5db4SJeff Garzik static u32 hpt37x_find_mode(struct ata_port *ap, int speed) 211669a5db4SJeff Garzik { 212669a5db4SJeff Garzik struct hpt_clock *clocks = ap->host->private_data; 213669a5db4SJeff Garzik 214669a5db4SJeff Garzik while(clocks->xfer_speed) { 215669a5db4SJeff Garzik if (clocks->xfer_speed == speed) 216669a5db4SJeff Garzik return clocks->timing; 217669a5db4SJeff Garzik clocks++; 218669a5db4SJeff Garzik } 219669a5db4SJeff Garzik BUG(); 220669a5db4SJeff Garzik return 0xffffffffU; /* silence compiler warning */ 221669a5db4SJeff Garzik } 222669a5db4SJeff Garzik 223669a5db4SJeff Garzik static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) 224669a5db4SJeff Garzik { 2258bfa79fcSTejun Heo unsigned char model_num[ATA_ID_PROD_LEN + 1]; 226669a5db4SJeff Garzik int i = 0; 227669a5db4SJeff Garzik 2288bfa79fcSTejun Heo ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); 229669a5db4SJeff Garzik 230669a5db4SJeff Garzik while (list[i] != NULL) { 2318bfa79fcSTejun Heo if (!strcmp(list[i], model_num)) { 232669a5db4SJeff Garzik printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", 233669a5db4SJeff Garzik modestr, list[i]); 234669a5db4SJeff Garzik return 1; 235669a5db4SJeff Garzik } 236669a5db4SJeff Garzik i++; 237669a5db4SJeff Garzik } 238669a5db4SJeff Garzik return 0; 239669a5db4SJeff Garzik } 240669a5db4SJeff Garzik 241669a5db4SJeff Garzik static const char *bad_ata33[] = { 242669a5db4SJeff Garzik "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", 243669a5db4SJeff Garzik "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", 244669a5db4SJeff Garzik "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", 245669a5db4SJeff Garzik "Maxtor 90510D4", 246669a5db4SJeff Garzik "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", 247669a5db4SJeff Garzik "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", 248669a5db4SJeff Garzik "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", 249669a5db4SJeff Garzik NULL 250669a5db4SJeff Garzik }; 251669a5db4SJeff Garzik 252669a5db4SJeff Garzik static const char *bad_ata100_5[] = { 253669a5db4SJeff Garzik "IBM-DTLA-307075", 254669a5db4SJeff Garzik "IBM-DTLA-307060", 255669a5db4SJeff Garzik "IBM-DTLA-307045", 256669a5db4SJeff Garzik "IBM-DTLA-307030", 257669a5db4SJeff Garzik "IBM-DTLA-307020", 258669a5db4SJeff Garzik "IBM-DTLA-307015", 259669a5db4SJeff Garzik "IBM-DTLA-305040", 260669a5db4SJeff Garzik "IBM-DTLA-305030", 261669a5db4SJeff Garzik "IBM-DTLA-305020", 262669a5db4SJeff Garzik "IC35L010AVER07-0", 263669a5db4SJeff Garzik "IC35L020AVER07-0", 264669a5db4SJeff Garzik "IC35L030AVER07-0", 265669a5db4SJeff Garzik "IC35L040AVER07-0", 266669a5db4SJeff Garzik "IC35L060AVER07-0", 267669a5db4SJeff Garzik "WDC AC310200R", 268669a5db4SJeff Garzik NULL 269669a5db4SJeff Garzik }; 270669a5db4SJeff Garzik 271669a5db4SJeff Garzik /** 272669a5db4SJeff Garzik * hpt370_filter - mode selection filter 273669a5db4SJeff Garzik * @adev: ATA device 274669a5db4SJeff Garzik * 275669a5db4SJeff Garzik * Block UDMA on devices that cause trouble with this controller. 276669a5db4SJeff Garzik */ 277669a5db4SJeff Garzik 278a76b62caSAlan Cox static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask) 279669a5db4SJeff Garzik { 2806929da44SAlan if (adev->class == ATA_DEV_ATA) { 281669a5db4SJeff Garzik if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) 282669a5db4SJeff Garzik mask &= ~ATA_MASK_UDMA; 283669a5db4SJeff Garzik if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) 2846ddd6861SAlan Cox mask &= ~(0xE0 << ATA_SHIFT_UDMA); 285669a5db4SJeff Garzik } 2869363c382STejun Heo return ata_bmdma_mode_filter(adev, mask); 287669a5db4SJeff Garzik } 288669a5db4SJeff Garzik 289669a5db4SJeff Garzik /** 290669a5db4SJeff Garzik * hpt370a_filter - mode selection filter 291669a5db4SJeff Garzik * @adev: ATA device 292669a5db4SJeff Garzik * 293669a5db4SJeff Garzik * Block UDMA on devices that cause trouble with this controller. 294669a5db4SJeff Garzik */ 295669a5db4SJeff Garzik 296a76b62caSAlan Cox static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) 297669a5db4SJeff Garzik { 29873946f9fSAlan Cox if (adev->class == ATA_DEV_ATA) { 299669a5db4SJeff Garzik if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) 3006ddd6861SAlan Cox mask &= ~(0xE0 << ATA_SHIFT_UDMA); 301669a5db4SJeff Garzik } 3029363c382STejun Heo return ata_bmdma_mode_filter(adev, mask); 303669a5db4SJeff Garzik } 304669a5db4SJeff Garzik 305669a5db4SJeff Garzik /** 3069e87be9eSBartlomiej Zolnierkiewicz * hpt37x_cable_detect - Detect the cable type 3079e87be9eSBartlomiej Zolnierkiewicz * @ap: ATA port to detect on 308669a5db4SJeff Garzik * 3099e87be9eSBartlomiej Zolnierkiewicz * Return the cable type attached to this port 310669a5db4SJeff Garzik */ 311669a5db4SJeff Garzik 3129e87be9eSBartlomiej Zolnierkiewicz static int hpt37x_cable_detect(struct ata_port *ap) 313669a5db4SJeff Garzik { 314669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3159e87be9eSBartlomiej Zolnierkiewicz u8 scr2, ata66; 316669a5db4SJeff Garzik 317669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x5B, &scr2); 318669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); 31910a9c969SBartlomiej Zolnierkiewicz 32010a9c969SBartlomiej Zolnierkiewicz udelay(10); /* debounce */ 32110a9c969SBartlomiej Zolnierkiewicz 322669a5db4SJeff Garzik /* Cable register now active */ 323669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x5A, &ata66); 324669a5db4SJeff Garzik /* Restore state */ 325669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x5B, scr2); 326669a5db4SJeff Garzik 32722d5c760SAlan Cox if (ata66 & (2 >> ap->port_no)) 3289e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA40; 329669a5db4SJeff Garzik else 3309e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA80; 3319e87be9eSBartlomiej Zolnierkiewicz } 3329e87be9eSBartlomiej Zolnierkiewicz 3339e87be9eSBartlomiej Zolnierkiewicz /** 3349e87be9eSBartlomiej Zolnierkiewicz * hpt374_fn1_cable_detect - Detect the cable type 3359e87be9eSBartlomiej Zolnierkiewicz * @ap: ATA port to detect on 3369e87be9eSBartlomiej Zolnierkiewicz * 3379e87be9eSBartlomiej Zolnierkiewicz * Return the cable type attached to this port 3389e87be9eSBartlomiej Zolnierkiewicz */ 3399e87be9eSBartlomiej Zolnierkiewicz 3409e87be9eSBartlomiej Zolnierkiewicz static int hpt374_fn1_cable_detect(struct ata_port *ap) 3419e87be9eSBartlomiej Zolnierkiewicz { 3429e87be9eSBartlomiej Zolnierkiewicz struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3439e87be9eSBartlomiej Zolnierkiewicz unsigned int mcrbase = 0x50 + 4 * ap->port_no; 3449e87be9eSBartlomiej Zolnierkiewicz u16 mcr3; 3459e87be9eSBartlomiej Zolnierkiewicz u8 ata66; 3469e87be9eSBartlomiej Zolnierkiewicz 3479e87be9eSBartlomiej Zolnierkiewicz /* Do the extra channel work */ 3489e87be9eSBartlomiej Zolnierkiewicz pci_read_config_word(pdev, mcrbase + 2, &mcr3); 3499e87be9eSBartlomiej Zolnierkiewicz /* Set bit 15 of 0x52 to enable TCBLID as input */ 3509e87be9eSBartlomiej Zolnierkiewicz pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000); 3519e87be9eSBartlomiej Zolnierkiewicz pci_read_config_byte(pdev, 0x5A, &ata66); 3529e87be9eSBartlomiej Zolnierkiewicz /* Reset TCBLID/FCBLID to output */ 3539e87be9eSBartlomiej Zolnierkiewicz pci_write_config_word(pdev, mcrbase + 2, mcr3); 3549e87be9eSBartlomiej Zolnierkiewicz 3559e87be9eSBartlomiej Zolnierkiewicz if (ata66 & (2 >> ap->port_no)) 3569e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA40; 3579e87be9eSBartlomiej Zolnierkiewicz else 3589e87be9eSBartlomiej Zolnierkiewicz return ATA_CBL_PATA80; 3599e87be9eSBartlomiej Zolnierkiewicz } 3609e87be9eSBartlomiej Zolnierkiewicz 3619e87be9eSBartlomiej Zolnierkiewicz /** 3629e87be9eSBartlomiej Zolnierkiewicz * hpt37x_pre_reset - reset the hpt37x bus 3639e87be9eSBartlomiej Zolnierkiewicz * @link: ATA link to reset 3649e87be9eSBartlomiej Zolnierkiewicz * @deadline: deadline jiffies for the operation 3659e87be9eSBartlomiej Zolnierkiewicz * 366ab81a505SBartlomiej Zolnierkiewicz * Perform the initial reset handling for the HPT37x. 3679e87be9eSBartlomiej Zolnierkiewicz */ 3689e87be9eSBartlomiej Zolnierkiewicz 3699e87be9eSBartlomiej Zolnierkiewicz static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) 3709e87be9eSBartlomiej Zolnierkiewicz { 3719e87be9eSBartlomiej Zolnierkiewicz struct ata_port *ap = link->ap; 3729e87be9eSBartlomiej Zolnierkiewicz struct pci_dev *pdev = to_pci_dev(ap->host->dev); 3739e87be9eSBartlomiej Zolnierkiewicz static const struct pci_bits hpt37x_enable_bits[] = { 3749e87be9eSBartlomiej Zolnierkiewicz { 0x50, 1, 0x04, 0x04 }, 3759e87be9eSBartlomiej Zolnierkiewicz { 0x54, 1, 0x04, 0x04 } 3769e87be9eSBartlomiej Zolnierkiewicz }; 3779e87be9eSBartlomiej Zolnierkiewicz if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) 3789e87be9eSBartlomiej Zolnierkiewicz return -ENOENT; 379669a5db4SJeff Garzik 380669a5db4SJeff Garzik /* Reset the state machine */ 381fcc2f69aSAlan Cox pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 382669a5db4SJeff Garzik udelay(100); 383669a5db4SJeff Garzik 3849363c382STejun Heo return ata_sff_prereset(link, deadline); 385669a5db4SJeff Garzik } 386669a5db4SJeff Garzik 387669a5db4SJeff Garzik /** 388669a5db4SJeff Garzik * hpt370_set_piomode - PIO setup 389669a5db4SJeff Garzik * @ap: ATA interface 390669a5db4SJeff Garzik * @adev: device on the interface 391669a5db4SJeff Garzik * 392669a5db4SJeff Garzik * Perform PIO mode setup. 393669a5db4SJeff Garzik */ 394669a5db4SJeff Garzik 395669a5db4SJeff Garzik static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) 396669a5db4SJeff Garzik { 397669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 398669a5db4SJeff Garzik u32 addr1, addr2; 399669a5db4SJeff Garzik u32 reg; 400669a5db4SJeff Garzik u32 mode; 401669a5db4SJeff Garzik u8 fast; 402669a5db4SJeff Garzik 403669a5db4SJeff Garzik addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 404669a5db4SJeff Garzik addr2 = 0x51 + 4 * ap->port_no; 405669a5db4SJeff Garzik 406669a5db4SJeff Garzik /* Fast interrupt prediction disable, hold off interrupt disable */ 407669a5db4SJeff Garzik pci_read_config_byte(pdev, addr2, &fast); 408669a5db4SJeff Garzik fast &= ~0x02; 409669a5db4SJeff Garzik fast |= 0x01; 410669a5db4SJeff Garzik pci_write_config_byte(pdev, addr2, fast); 411669a5db4SJeff Garzik 412669a5db4SJeff Garzik pci_read_config_dword(pdev, addr1, ®); 413669a5db4SJeff Garzik mode = hpt37x_find_mode(ap, adev->pio_mode); 4145600c70eSSergei Shtylyov mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ 4155600c70eSSergei Shtylyov reg &= ~0xCFC3FFFF; /* Strip timing bits */ 416669a5db4SJeff Garzik pci_write_config_dword(pdev, addr1, reg | mode); 417669a5db4SJeff Garzik } 418669a5db4SJeff Garzik 419669a5db4SJeff Garzik /** 420669a5db4SJeff Garzik * hpt370_set_dmamode - DMA timing setup 421669a5db4SJeff Garzik * @ap: ATA interface 422669a5db4SJeff Garzik * @adev: Device being configured 423669a5db4SJeff Garzik * 424669a5db4SJeff Garzik * Set up the channel for MWDMA or UDMA modes. Much the same as with 425669a5db4SJeff Garzik * PIO, load the mode number and then set MWDMA or UDMA flag. 426669a5db4SJeff Garzik */ 427669a5db4SJeff Garzik 428669a5db4SJeff Garzik static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) 429669a5db4SJeff Garzik { 430669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 431669a5db4SJeff Garzik u32 addr1, addr2; 4325600c70eSSergei Shtylyov u32 reg, mode, mask; 433669a5db4SJeff Garzik u8 fast; 434669a5db4SJeff Garzik 435669a5db4SJeff Garzik addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 436669a5db4SJeff Garzik addr2 = 0x51 + 4 * ap->port_no; 437669a5db4SJeff Garzik 438669a5db4SJeff Garzik /* Fast interrupt prediction disable, hold off interrupt disable */ 439669a5db4SJeff Garzik pci_read_config_byte(pdev, addr2, &fast); 440669a5db4SJeff Garzik fast &= ~0x02; 441669a5db4SJeff Garzik fast |= 0x01; 442669a5db4SJeff Garzik pci_write_config_byte(pdev, addr2, fast); 443669a5db4SJeff Garzik 4445600c70eSSergei Shtylyov mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; 4455600c70eSSergei Shtylyov 446669a5db4SJeff Garzik pci_read_config_dword(pdev, addr1, ®); 447669a5db4SJeff Garzik mode = hpt37x_find_mode(ap, adev->dma_mode); 4485600c70eSSergei Shtylyov mode &= mask; 4495600c70eSSergei Shtylyov reg &= ~mask; 450669a5db4SJeff Garzik pci_write_config_dword(pdev, addr1, reg | mode); 451669a5db4SJeff Garzik } 452669a5db4SJeff Garzik 453669a5db4SJeff Garzik /** 454669a5db4SJeff Garzik * hpt370_bmdma_end - DMA engine stop 455669a5db4SJeff Garzik * @qc: ATA command 456669a5db4SJeff Garzik * 457669a5db4SJeff Garzik * Work around the HPT370 DMA engine. 458669a5db4SJeff Garzik */ 459669a5db4SJeff Garzik 460669a5db4SJeff Garzik static void hpt370_bmdma_stop(struct ata_queued_cmd *qc) 461669a5db4SJeff Garzik { 462669a5db4SJeff Garzik struct ata_port *ap = qc->ap; 463669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 4640d5ff566STejun Heo void __iomem *bmdma = ap->ioaddr.bmdma_addr; 46556f46f8cSSergei Shtylyov u8 dma_stat = ioread8(bmdma + ATA_DMA_STATUS); 46656f46f8cSSergei Shtylyov u8 dma_cmd; 467669a5db4SJeff Garzik 46856f46f8cSSergei Shtylyov if (dma_stat & ATA_DMA_ACTIVE) { 469669a5db4SJeff Garzik udelay(20); 47056f46f8cSSergei Shtylyov dma_stat = ioread8(bmdma + ATA_DMA_STATUS); 471669a5db4SJeff Garzik } 47256f46f8cSSergei Shtylyov if (dma_stat & ATA_DMA_ACTIVE) { 473669a5db4SJeff Garzik /* Clear the engine */ 474669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 475669a5db4SJeff Garzik udelay(10); 476669a5db4SJeff Garzik /* Stop DMA */ 47756f46f8cSSergei Shtylyov dma_cmd = ioread8(bmdma + ATA_DMA_CMD); 47856f46f8cSSergei Shtylyov iowrite8(dma_cmd & ~ATA_DMA_START, bmdma + ATA_DMA_CMD); 479669a5db4SJeff Garzik /* Clear Error */ 48056f46f8cSSergei Shtylyov dma_stat = ioread8(bmdma + ATA_DMA_STATUS); 48156f46f8cSSergei Shtylyov iowrite8(dma_stat | ATA_DMA_INTR | ATA_DMA_ERR, 48256f46f8cSSergei Shtylyov bmdma + ATA_DMA_STATUS); 483669a5db4SJeff Garzik /* Clear the engine */ 484669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 485669a5db4SJeff Garzik udelay(10); 486669a5db4SJeff Garzik } 487669a5db4SJeff Garzik ata_bmdma_stop(qc); 488669a5db4SJeff Garzik } 489669a5db4SJeff Garzik 490669a5db4SJeff Garzik /** 491669a5db4SJeff Garzik * hpt372_set_piomode - PIO setup 492669a5db4SJeff Garzik * @ap: ATA interface 493669a5db4SJeff Garzik * @adev: device on the interface 494669a5db4SJeff Garzik * 495669a5db4SJeff Garzik * Perform PIO mode setup. 496669a5db4SJeff Garzik */ 497669a5db4SJeff Garzik 498669a5db4SJeff Garzik static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) 499669a5db4SJeff Garzik { 500669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 501669a5db4SJeff Garzik u32 addr1, addr2; 502669a5db4SJeff Garzik u32 reg; 503669a5db4SJeff Garzik u32 mode; 504669a5db4SJeff Garzik u8 fast; 505669a5db4SJeff Garzik 506669a5db4SJeff Garzik addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 507669a5db4SJeff Garzik addr2 = 0x51 + 4 * ap->port_no; 508669a5db4SJeff Garzik 509669a5db4SJeff Garzik /* Fast interrupt prediction disable, hold off interrupt disable */ 510669a5db4SJeff Garzik pci_read_config_byte(pdev, addr2, &fast); 511669a5db4SJeff Garzik fast &= ~0x07; 512669a5db4SJeff Garzik pci_write_config_byte(pdev, addr2, fast); 513669a5db4SJeff Garzik 514669a5db4SJeff Garzik pci_read_config_dword(pdev, addr1, ®); 515669a5db4SJeff Garzik mode = hpt37x_find_mode(ap, adev->pio_mode); 516669a5db4SJeff Garzik 517669a5db4SJeff Garzik printk("Find mode for %d reports %X\n", adev->pio_mode, mode); 5185600c70eSSergei Shtylyov mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ 5195600c70eSSergei Shtylyov reg &= ~0xCFC3FFFF; /* Strip timing bits */ 520669a5db4SJeff Garzik pci_write_config_dword(pdev, addr1, reg | mode); 521669a5db4SJeff Garzik } 522669a5db4SJeff Garzik 523669a5db4SJeff Garzik /** 524669a5db4SJeff Garzik * hpt372_set_dmamode - DMA timing setup 525669a5db4SJeff Garzik * @ap: ATA interface 526669a5db4SJeff Garzik * @adev: Device being configured 527669a5db4SJeff Garzik * 528669a5db4SJeff Garzik * Set up the channel for MWDMA or UDMA modes. Much the same as with 529669a5db4SJeff Garzik * PIO, load the mode number and then set MWDMA or UDMA flag. 530669a5db4SJeff Garzik */ 531669a5db4SJeff Garzik 532669a5db4SJeff Garzik static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) 533669a5db4SJeff Garzik { 534669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 535669a5db4SJeff Garzik u32 addr1, addr2; 5365600c70eSSergei Shtylyov u32 reg, mode, mask; 537669a5db4SJeff Garzik u8 fast; 538669a5db4SJeff Garzik 539669a5db4SJeff Garzik addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); 540669a5db4SJeff Garzik addr2 = 0x51 + 4 * ap->port_no; 541669a5db4SJeff Garzik 542669a5db4SJeff Garzik /* Fast interrupt prediction disable, hold off interrupt disable */ 543669a5db4SJeff Garzik pci_read_config_byte(pdev, addr2, &fast); 544669a5db4SJeff Garzik fast &= ~0x07; 545669a5db4SJeff Garzik pci_write_config_byte(pdev, addr2, fast); 546669a5db4SJeff Garzik 5475600c70eSSergei Shtylyov mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; 5485600c70eSSergei Shtylyov 549669a5db4SJeff Garzik pci_read_config_dword(pdev, addr1, ®); 550669a5db4SJeff Garzik mode = hpt37x_find_mode(ap, adev->dma_mode); 551669a5db4SJeff Garzik printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); 5525600c70eSSergei Shtylyov mode &= mask; 5535600c70eSSergei Shtylyov reg &= ~mask; 554669a5db4SJeff Garzik pci_write_config_dword(pdev, addr1, reg | mode); 555669a5db4SJeff Garzik } 556669a5db4SJeff Garzik 557669a5db4SJeff Garzik /** 558669a5db4SJeff Garzik * hpt37x_bmdma_end - DMA engine stop 559669a5db4SJeff Garzik * @qc: ATA command 560669a5db4SJeff Garzik * 561669a5db4SJeff Garzik * Clean up after the HPT372 and later DMA engine 562669a5db4SJeff Garzik */ 563669a5db4SJeff Garzik 564669a5db4SJeff Garzik static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc) 565669a5db4SJeff Garzik { 566669a5db4SJeff Garzik struct ata_port *ap = qc->ap; 567669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 5686929da44SAlan int mscreg = 0x50 + 4 * ap->port_no; 569669a5db4SJeff Garzik u8 bwsr_stat, msc_stat; 570669a5db4SJeff Garzik 571669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x6A, &bwsr_stat); 572669a5db4SJeff Garzik pci_read_config_byte(pdev, mscreg, &msc_stat); 573669a5db4SJeff Garzik if (bwsr_stat & (1 << ap->port_no)) 574669a5db4SJeff Garzik pci_write_config_byte(pdev, mscreg, msc_stat | 0x30); 575669a5db4SJeff Garzik ata_bmdma_stop(qc); 576669a5db4SJeff Garzik } 577669a5db4SJeff Garzik 578669a5db4SJeff Garzik 579669a5db4SJeff Garzik static struct scsi_host_template hpt37x_sht = { 58068d1d07bSTejun Heo ATA_BMDMA_SHT(DRV_NAME), 581669a5db4SJeff Garzik }; 582669a5db4SJeff Garzik 583669a5db4SJeff Garzik /* 584669a5db4SJeff Garzik * Configuration for HPT370 585669a5db4SJeff Garzik */ 586669a5db4SJeff Garzik 587669a5db4SJeff Garzik static struct ata_port_operations hpt370_port_ops = { 588029cfd6bSTejun Heo .inherits = &ata_bmdma_port_ops, 589669a5db4SJeff Garzik 590669a5db4SJeff Garzik .bmdma_stop = hpt370_bmdma_stop, 591669a5db4SJeff Garzik 592029cfd6bSTejun Heo .mode_filter = hpt370_filter, 5939e87be9eSBartlomiej Zolnierkiewicz .cable_detect = hpt37x_cable_detect, 594029cfd6bSTejun Heo .set_piomode = hpt370_set_piomode, 595029cfd6bSTejun Heo .set_dmamode = hpt370_set_dmamode, 596a1efdabaSTejun Heo .prereset = hpt37x_pre_reset, 597669a5db4SJeff Garzik }; 598669a5db4SJeff Garzik 599669a5db4SJeff Garzik /* 600669a5db4SJeff Garzik * Configuration for HPT370A. Close to 370 but less filters 601669a5db4SJeff Garzik */ 602669a5db4SJeff Garzik 603669a5db4SJeff Garzik static struct ata_port_operations hpt370a_port_ops = { 604029cfd6bSTejun Heo .inherits = &hpt370_port_ops, 605669a5db4SJeff Garzik .mode_filter = hpt370a_filter, 606669a5db4SJeff Garzik }; 607669a5db4SJeff Garzik 608669a5db4SJeff Garzik /* 609669a5db4SJeff Garzik * Configuration for HPT372, HPT371, HPT302. Slightly different PIO 610669a5db4SJeff Garzik * and DMA mode setting functionality. 611669a5db4SJeff Garzik */ 612669a5db4SJeff Garzik 613669a5db4SJeff Garzik static struct ata_port_operations hpt372_port_ops = { 614029cfd6bSTejun Heo .inherits = &ata_bmdma_port_ops, 615029cfd6bSTejun Heo 616029cfd6bSTejun Heo .bmdma_stop = hpt37x_bmdma_stop, 617029cfd6bSTejun Heo 6189e87be9eSBartlomiej Zolnierkiewicz .cable_detect = hpt37x_cable_detect, 619669a5db4SJeff Garzik .set_piomode = hpt372_set_piomode, 620669a5db4SJeff Garzik .set_dmamode = hpt372_set_dmamode, 621a1efdabaSTejun Heo .prereset = hpt37x_pre_reset, 622669a5db4SJeff Garzik }; 623669a5db4SJeff Garzik 624669a5db4SJeff Garzik /* 625669a5db4SJeff Garzik * Configuration for HPT374. Mode setting works like 372 and friends 626a1efdabaSTejun Heo * but we have a different cable detection procedure for function 1. 627669a5db4SJeff Garzik */ 628669a5db4SJeff Garzik 629a1efdabaSTejun Heo static struct ata_port_operations hpt374_fn1_port_ops = { 630029cfd6bSTejun Heo .inherits = &hpt372_port_ops, 6319e87be9eSBartlomiej Zolnierkiewicz .cable_detect = hpt374_fn1_cable_detect, 632ab81a505SBartlomiej Zolnierkiewicz .prereset = hpt37x_pre_reset, 633669a5db4SJeff Garzik }; 634669a5db4SJeff Garzik 635669a5db4SJeff Garzik /** 636ad452d64SKrzysztof Halasa * hpt37x_clock_slot - Turn timing to PC clock entry 637669a5db4SJeff Garzik * @freq: Reported frequency timing 638669a5db4SJeff Garzik * @base: Base timing 639669a5db4SJeff Garzik * 640669a5db4SJeff Garzik * Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50 641669a5db4SJeff Garzik * and 3 for 66Mhz) 642669a5db4SJeff Garzik */ 643669a5db4SJeff Garzik 644669a5db4SJeff Garzik static int hpt37x_clock_slot(unsigned int freq, unsigned int base) 645669a5db4SJeff Garzik { 646669a5db4SJeff Garzik unsigned int f = (base * freq) / 192; /* Mhz */ 647669a5db4SJeff Garzik if (f < 40) 648669a5db4SJeff Garzik return 0; /* 33Mhz slot */ 649669a5db4SJeff Garzik if (f < 45) 650669a5db4SJeff Garzik return 1; /* 40Mhz slot */ 651669a5db4SJeff Garzik if (f < 55) 652669a5db4SJeff Garzik return 2; /* 50Mhz slot */ 653669a5db4SJeff Garzik return 3; /* 60Mhz slot */ 654669a5db4SJeff Garzik } 655669a5db4SJeff Garzik 656669a5db4SJeff Garzik /** 657669a5db4SJeff Garzik * hpt37x_calibrate_dpll - Calibrate the DPLL loop 658669a5db4SJeff Garzik * @dev: PCI device 659669a5db4SJeff Garzik * 660669a5db4SJeff Garzik * Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this 661669a5db4SJeff Garzik * succeeds 662669a5db4SJeff Garzik */ 663669a5db4SJeff Garzik 664669a5db4SJeff Garzik static int hpt37x_calibrate_dpll(struct pci_dev *dev) 665669a5db4SJeff Garzik { 666669a5db4SJeff Garzik u8 reg5b; 667669a5db4SJeff Garzik u32 reg5c; 668669a5db4SJeff Garzik int tries; 669669a5db4SJeff Garzik 670669a5db4SJeff Garzik for(tries = 0; tries < 0x5000; tries++) { 671669a5db4SJeff Garzik udelay(50); 672669a5db4SJeff Garzik pci_read_config_byte(dev, 0x5b, ®5b); 673669a5db4SJeff Garzik if (reg5b & 0x80) { 674669a5db4SJeff Garzik /* See if it stays set */ 675669a5db4SJeff Garzik for(tries = 0; tries < 0x1000; tries ++) { 676669a5db4SJeff Garzik pci_read_config_byte(dev, 0x5b, ®5b); 677669a5db4SJeff Garzik /* Failed ? */ 678669a5db4SJeff Garzik if ((reg5b & 0x80) == 0) 679669a5db4SJeff Garzik return 0; 680669a5db4SJeff Garzik } 681669a5db4SJeff Garzik /* Turn off tuning, we have the DPLL set */ 682669a5db4SJeff Garzik pci_read_config_dword(dev, 0x5c, ®5c); 683669a5db4SJeff Garzik pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); 684669a5db4SJeff Garzik return 1; 685669a5db4SJeff Garzik } 686669a5db4SJeff Garzik } 687669a5db4SJeff Garzik /* Never went stable */ 688669a5db4SJeff Garzik return 0; 689669a5db4SJeff Garzik } 69073946f9fSAlan Cox 69173946f9fSAlan Cox static u32 hpt374_read_freq(struct pci_dev *pdev) 69273946f9fSAlan Cox { 69373946f9fSAlan Cox u32 freq; 69473946f9fSAlan Cox unsigned long io_base = pci_resource_start(pdev, 4); 69573946f9fSAlan Cox if (PCI_FUNC(pdev->devfn) & 1) { 69640f46f17SAndrew Morton struct pci_dev *pdev_0; 69740f46f17SAndrew Morton 69840f46f17SAndrew Morton pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1); 69973946f9fSAlan Cox /* Someone hot plugged the controller on us ? */ 70073946f9fSAlan Cox if (pdev_0 == NULL) 70173946f9fSAlan Cox return 0; 70273946f9fSAlan Cox io_base = pci_resource_start(pdev_0, 4); 70373946f9fSAlan Cox freq = inl(io_base + 0x90); 70473946f9fSAlan Cox pci_dev_put(pdev_0); 70540f46f17SAndrew Morton } else 70673946f9fSAlan Cox freq = inl(io_base + 0x90); 70773946f9fSAlan Cox return freq; 70873946f9fSAlan Cox } 70973946f9fSAlan Cox 710669a5db4SJeff Garzik /** 711669a5db4SJeff Garzik * hpt37x_init_one - Initialise an HPT37X/302 712669a5db4SJeff Garzik * @dev: PCI device 713669a5db4SJeff Garzik * @id: Entry in match table 714669a5db4SJeff Garzik * 715669a5db4SJeff Garzik * Initialise an HPT37x device. There are some interesting complications 716669a5db4SJeff Garzik * here. Firstly the chip may report 366 and be one of several variants. 717669a5db4SJeff Garzik * Secondly all the timings depend on the clock for the chip which we must 718669a5db4SJeff Garzik * detect and look up 719669a5db4SJeff Garzik * 720669a5db4SJeff Garzik * This is the known chip mappings. It may be missing a couple of later 721669a5db4SJeff Garzik * releases. 722669a5db4SJeff Garzik * 723669a5db4SJeff Garzik * Chip version PCI Rev Notes 724669a5db4SJeff Garzik * HPT366 4 (HPT366) 0 Other driver 725669a5db4SJeff Garzik * HPT366 4 (HPT366) 1 Other driver 726669a5db4SJeff Garzik * HPT368 4 (HPT366) 2 Other driver 727669a5db4SJeff Garzik * HPT370 4 (HPT366) 3 UDMA100 728669a5db4SJeff Garzik * HPT370A 4 (HPT366) 4 UDMA100 729669a5db4SJeff Garzik * HPT372 4 (HPT366) 5 UDMA133 (1) 730669a5db4SJeff Garzik * HPT372N 4 (HPT366) 6 Other driver 731669a5db4SJeff Garzik * HPT372A 5 (HPT372) 1 UDMA133 (1) 732669a5db4SJeff Garzik * HPT372N 5 (HPT372) 2 Other driver 733669a5db4SJeff Garzik * HPT302 6 (HPT302) 1 UDMA133 734669a5db4SJeff Garzik * HPT302N 6 (HPT302) 2 Other driver 735669a5db4SJeff Garzik * HPT371 7 (HPT371) * UDMA133 736669a5db4SJeff Garzik * HPT374 8 (HPT374) * UDMA133 4 channel 737669a5db4SJeff Garzik * HPT372N 9 (HPT372N) * Other driver 738669a5db4SJeff Garzik * 739669a5db4SJeff Garzik * (1) UDMA133 support depends on the bus clock 740669a5db4SJeff Garzik */ 741669a5db4SJeff Garzik 742669a5db4SJeff Garzik static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) 743669a5db4SJeff Garzik { 744669a5db4SJeff Garzik /* HPT370 - UDMA100 */ 7451626aeb8STejun Heo static const struct ata_port_info info_hpt370 = { 7461d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 74714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 74814bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 749bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 750669a5db4SJeff Garzik .port_ops = &hpt370_port_ops 751669a5db4SJeff Garzik }; 752669a5db4SJeff Garzik /* HPT370A - UDMA100 */ 7531626aeb8STejun Heo static const struct ata_port_info info_hpt370a = { 7541d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 75514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 75614bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 757bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 758669a5db4SJeff Garzik .port_ops = &hpt370a_port_ops 759669a5db4SJeff Garzik }; 760fcc2f69aSAlan Cox /* HPT370 - UDMA100 */ 7611626aeb8STejun Heo static const struct ata_port_info info_hpt370_33 = { 7621d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 76314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 76414bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 76573946f9fSAlan Cox .udma_mask = ATA_UDMA5, 766fcc2f69aSAlan Cox .port_ops = &hpt370_port_ops 767fcc2f69aSAlan Cox }; 768fcc2f69aSAlan Cox /* HPT370A - UDMA100 */ 7691626aeb8STejun Heo static const struct ata_port_info info_hpt370a_33 = { 7701d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 77114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 77214bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 77373946f9fSAlan Cox .udma_mask = ATA_UDMA5, 774fcc2f69aSAlan Cox .port_ops = &hpt370a_port_ops 775fcc2f69aSAlan Cox }; 776669a5db4SJeff Garzik /* HPT371, 372 and friends - UDMA133 */ 7771626aeb8STejun Heo static const struct ata_port_info info_hpt372 = { 7781d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 77914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 78014bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 781bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6, 782669a5db4SJeff Garzik .port_ops = &hpt372_port_ops 783669a5db4SJeff Garzik }; 784a1efdabaSTejun Heo /* HPT374 - UDMA100, function 1 uses different prereset method */ 785a1efdabaSTejun Heo static const struct ata_port_info info_hpt374_fn0 = { 7861d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS, 78714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 78814bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 789bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 790a1efdabaSTejun Heo .port_ops = &hpt372_port_ops 791a1efdabaSTejun Heo }; 792a1efdabaSTejun Heo static const struct ata_port_info info_hpt374_fn1 = { 793a1efdabaSTejun Heo .flags = ATA_FLAG_SLAVE_POSS, 79414bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 79514bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 796a1efdabaSTejun Heo .udma_mask = ATA_UDMA5, 797a1efdabaSTejun Heo .port_ops = &hpt374_fn1_port_ops 798669a5db4SJeff Garzik }; 799669a5db4SJeff Garzik 800669a5db4SJeff Garzik static const int MHz[4] = { 33, 40, 50, 66 }; 8011626aeb8STejun Heo void *private_data = NULL; 802887125e3STejun Heo const struct ata_port_info *ppi[] = { NULL, NULL }; 80389d3b360SSergei Shtylyov u8 rev = dev->revision; 804669a5db4SJeff Garzik u8 irqmask; 805fcc2f69aSAlan Cox u8 mcr1; 806669a5db4SJeff Garzik u32 freq; 807fcc2f69aSAlan Cox int prefer_dpll = 1; 808fcc2f69aSAlan Cox 809fcc2f69aSAlan Cox unsigned long iobase = pci_resource_start(dev, 4); 810669a5db4SJeff Garzik 811669a5db4SJeff Garzik const struct hpt_chip *chip_table; 812669a5db4SJeff Garzik int clock_slot; 813f08048e9STejun Heo int rc; 814f08048e9STejun Heo 815f08048e9STejun Heo rc = pcim_enable_device(dev); 816f08048e9STejun Heo if (rc) 817f08048e9STejun Heo return rc; 818669a5db4SJeff Garzik 819669a5db4SJeff Garzik if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { 820669a5db4SJeff Garzik /* May be a later chip in disguise. Check */ 821669a5db4SJeff Garzik /* Older chips are in the HPT366 driver. Ignore them */ 82289d3b360SSergei Shtylyov if (rev < 3) 823669a5db4SJeff Garzik return -ENODEV; 824669a5db4SJeff Garzik /* N series chips have their own driver. Ignore */ 82589d3b360SSergei Shtylyov if (rev == 6) 826669a5db4SJeff Garzik return -ENODEV; 827669a5db4SJeff Garzik 82889d3b360SSergei Shtylyov switch(rev) { 829669a5db4SJeff Garzik case 3: 830887125e3STejun Heo ppi[0] = &info_hpt370; 831669a5db4SJeff Garzik chip_table = &hpt370; 832fcc2f69aSAlan Cox prefer_dpll = 0; 833669a5db4SJeff Garzik break; 834669a5db4SJeff Garzik case 4: 835887125e3STejun Heo ppi[0] = &info_hpt370a; 836669a5db4SJeff Garzik chip_table = &hpt370a; 837fcc2f69aSAlan Cox prefer_dpll = 0; 838669a5db4SJeff Garzik break; 839669a5db4SJeff Garzik case 5: 840887125e3STejun Heo ppi[0] = &info_hpt372; 841669a5db4SJeff Garzik chip_table = &hpt372; 842669a5db4SJeff Garzik break; 843669a5db4SJeff Garzik default: 84489d3b360SSergei Shtylyov printk(KERN_ERR "pata_hpt37x: Unknown HPT366 " 84589d3b360SSergei Shtylyov "subtype, please report (%d).\n", rev); 846669a5db4SJeff Garzik return -ENODEV; 847669a5db4SJeff Garzik } 848669a5db4SJeff Garzik } else { 849669a5db4SJeff Garzik switch(dev->device) { 850669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT372: 851669a5db4SJeff Garzik /* 372N if rev >= 2*/ 85289d3b360SSergei Shtylyov if (rev >= 2) 853669a5db4SJeff Garzik return -ENODEV; 854887125e3STejun Heo ppi[0] = &info_hpt372; 855669a5db4SJeff Garzik chip_table = &hpt372a; 856669a5db4SJeff Garzik break; 857669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT302: 858669a5db4SJeff Garzik /* 302N if rev > 1 */ 85989d3b360SSergei Shtylyov if (rev > 1) 860669a5db4SJeff Garzik return -ENODEV; 861887125e3STejun Heo ppi[0] = &info_hpt372; 862669a5db4SJeff Garzik /* Check this */ 863669a5db4SJeff Garzik chip_table = &hpt302; 864669a5db4SJeff Garzik break; 865669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT371: 86689d3b360SSergei Shtylyov if (rev > 1) 867fcc2f69aSAlan Cox return -ENODEV; 868887125e3STejun Heo ppi[0] = &info_hpt372; 869669a5db4SJeff Garzik chip_table = &hpt371; 870a4734468SAlan Cox /* Single channel device, master is not present 871a4734468SAlan Cox but the BIOS (or us for non x86) must mark it 872fcc2f69aSAlan Cox absent */ 873fcc2f69aSAlan Cox pci_read_config_byte(dev, 0x50, &mcr1); 874fcc2f69aSAlan Cox mcr1 &= ~0x04; 875fcc2f69aSAlan Cox pci_write_config_byte(dev, 0x50, mcr1); 876669a5db4SJeff Garzik break; 877669a5db4SJeff Garzik case PCI_DEVICE_ID_TTI_HPT374: 878669a5db4SJeff Garzik chip_table = &hpt374; 879a1efdabaSTejun Heo if (!(PCI_FUNC(dev->devfn) & 1)) 880a1efdabaSTejun Heo *ppi = &info_hpt374_fn0; 881a1efdabaSTejun Heo else 882a1efdabaSTejun Heo *ppi = &info_hpt374_fn1; 883669a5db4SJeff Garzik break; 884669a5db4SJeff Garzik default: 885669a5db4SJeff Garzik printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device); 886669a5db4SJeff Garzik return -ENODEV; 887669a5db4SJeff Garzik } 888669a5db4SJeff Garzik } 889669a5db4SJeff Garzik /* Ok so this is a chip we support */ 890669a5db4SJeff Garzik 891669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); 892669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); 893669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); 894669a5db4SJeff Garzik pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); 895669a5db4SJeff Garzik 896669a5db4SJeff Garzik pci_read_config_byte(dev, 0x5A, &irqmask); 897669a5db4SJeff Garzik irqmask &= ~0x10; 898669a5db4SJeff Garzik pci_write_config_byte(dev, 0x5a, irqmask); 899669a5db4SJeff Garzik 900669a5db4SJeff Garzik /* 901669a5db4SJeff Garzik * default to pci clock. make sure MA15/16 are set to output 902669a5db4SJeff Garzik * to prevent drives having problems with 40-pin cables. Needed 903669a5db4SJeff Garzik * for some drives such as IBM-DTLA which will not enter ready 904669a5db4SJeff Garzik * state on reset when PDIAG is a input. 905669a5db4SJeff Garzik */ 906669a5db4SJeff Garzik 907669a5db4SJeff Garzik pci_write_config_byte(dev, 0x5b, 0x23); 908669a5db4SJeff Garzik 909fcc2f69aSAlan Cox /* 910fcc2f69aSAlan Cox * HighPoint does this for HPT372A. 911fcc2f69aSAlan Cox * NOTE: This register is only writeable via I/O space. 912fcc2f69aSAlan Cox */ 913fcc2f69aSAlan Cox if (chip_table == &hpt372a) 914fcc2f69aSAlan Cox outb(0x0e, iobase + 0x9c); 915fcc2f69aSAlan Cox 916fcc2f69aSAlan Cox /* Some devices do not let this value be accessed via PCI space 91773946f9fSAlan Cox according to the old driver. In addition we must use the value 91873946f9fSAlan Cox from FN 0 on the HPT374 */ 919fcc2f69aSAlan Cox 92073946f9fSAlan Cox if (chip_table == &hpt374) { 92173946f9fSAlan Cox freq = hpt374_read_freq(dev); 92273946f9fSAlan Cox if (freq == 0) 92373946f9fSAlan Cox return -ENODEV; 92473946f9fSAlan Cox } else 925fcc2f69aSAlan Cox freq = inl(iobase + 0x90); 92673946f9fSAlan Cox 927669a5db4SJeff Garzik if ((freq >> 12) != 0xABCDE) { 928669a5db4SJeff Garzik int i; 929669a5db4SJeff Garzik u8 sr; 930669a5db4SJeff Garzik u32 total = 0; 931669a5db4SJeff Garzik 932669a5db4SJeff Garzik printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n"); 933669a5db4SJeff Garzik 934669a5db4SJeff Garzik /* This is the process the HPT371 BIOS is reported to use */ 935669a5db4SJeff Garzik for(i = 0; i < 128; i++) { 936669a5db4SJeff Garzik pci_read_config_byte(dev, 0x78, &sr); 937fcc2f69aSAlan Cox total += sr & 0x1FF; 938669a5db4SJeff Garzik udelay(15); 939669a5db4SJeff Garzik } 940669a5db4SJeff Garzik freq = total / 128; 941669a5db4SJeff Garzik } 942669a5db4SJeff Garzik freq &= 0x1FF; 943669a5db4SJeff Garzik 944669a5db4SJeff Garzik /* 945669a5db4SJeff Garzik * Turn the frequency check into a band and then find a timing 946669a5db4SJeff Garzik * table to match it. 947669a5db4SJeff Garzik */ 948669a5db4SJeff Garzik 949669a5db4SJeff Garzik clock_slot = hpt37x_clock_slot(freq, chip_table->base); 950fcc2f69aSAlan Cox if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) { 951669a5db4SJeff Garzik /* 952669a5db4SJeff Garzik * We need to try PLL mode instead 953fcc2f69aSAlan Cox * 954fcc2f69aSAlan Cox * For non UDMA133 capable devices we should 955fcc2f69aSAlan Cox * use a 50MHz DPLL by choice 956669a5db4SJeff Garzik */ 957fcc2f69aSAlan Cox unsigned int f_low, f_high; 958960c8a10SAlan Cox int dpll, adjust; 959669a5db4SJeff Garzik 960960c8a10SAlan Cox /* Compute DPLL */ 961887125e3STejun Heo dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2; 962fcc2f69aSAlan Cox 963960c8a10SAlan Cox f_low = (MHz[clock_slot] * 48) / MHz[dpll]; 964fcc2f69aSAlan Cox f_high = f_low + 2; 965960c8a10SAlan Cox if (clock_slot > 1) 966960c8a10SAlan Cox f_high += 2; 967fcc2f69aSAlan Cox 968fcc2f69aSAlan Cox /* Select the DPLL clock. */ 969fcc2f69aSAlan Cox pci_write_config_byte(dev, 0x5b, 0x21); 97064a81709SAlan Cox pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); 971fcc2f69aSAlan Cox 972669a5db4SJeff Garzik for(adjust = 0; adjust < 8; adjust++) { 973669a5db4SJeff Garzik if (hpt37x_calibrate_dpll(dev)) 974669a5db4SJeff Garzik break; 975669a5db4SJeff Garzik /* See if it'll settle at a fractionally different clock */ 97664a81709SAlan Cox if (adjust & 1) 97764a81709SAlan Cox f_low -= adjust >> 1; 97864a81709SAlan Cox else 97964a81709SAlan Cox f_high += adjust >> 1; 98064a81709SAlan Cox pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); 981669a5db4SJeff Garzik } 982669a5db4SJeff Garzik if (adjust == 8) { 98380b8987cSSergei Shtylyov printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n"); 984669a5db4SJeff Garzik return -ENODEV; 985669a5db4SJeff Garzik } 986960c8a10SAlan Cox if (dpll == 3) 9871626aeb8STejun Heo private_data = (void *)hpt37x_timings_66; 988fcc2f69aSAlan Cox else 9891626aeb8STejun Heo private_data = (void *)hpt37x_timings_50; 990669a5db4SJeff Garzik 99180b8987cSSergei Shtylyov printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n", 99280b8987cSSergei Shtylyov MHz[clock_slot], MHz[dpll]); 993669a5db4SJeff Garzik } else { 9941626aeb8STejun Heo private_data = (void *)chip_table->clocks[clock_slot]; 995669a5db4SJeff Garzik /* 996a4734468SAlan Cox * Perform a final fixup. Note that we will have used the 997a4734468SAlan Cox * DPLL on the HPT372 which means we don't have to worry 998a4734468SAlan Cox * about lack of UDMA133 support on lower clocks 999669a5db4SJeff Garzik */ 1000669a5db4SJeff Garzik 1001887125e3STejun Heo if (clock_slot < 2 && ppi[0] == &info_hpt370) 1002887125e3STejun Heo ppi[0] = &info_hpt370_33; 1003887125e3STejun Heo if (clock_slot < 2 && ppi[0] == &info_hpt370a) 1004887125e3STejun Heo ppi[0] = &info_hpt370a_33; 100580b8987cSSergei Shtylyov printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n", 100680b8987cSSergei Shtylyov chip_table->name, MHz[clock_slot]); 1007669a5db4SJeff Garzik } 1008fcc2f69aSAlan Cox 1009669a5db4SJeff Garzik /* Now kick off ATA set up */ 10109363c382STejun Heo return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data); 1011669a5db4SJeff Garzik } 1012669a5db4SJeff Garzik 10132d2744fcSJeff Garzik static const struct pci_device_id hpt37x[] = { 10142d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, 10152d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), }, 10162d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), }, 10172d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), }, 10182d2744fcSJeff Garzik { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), }, 10192d2744fcSJeff Garzik 10202d2744fcSJeff Garzik { }, 1021669a5db4SJeff Garzik }; 1022669a5db4SJeff Garzik 1023669a5db4SJeff Garzik static struct pci_driver hpt37x_pci_driver = { 1024669a5db4SJeff Garzik .name = DRV_NAME, 1025669a5db4SJeff Garzik .id_table = hpt37x, 1026669a5db4SJeff Garzik .probe = hpt37x_init_one, 1027669a5db4SJeff Garzik .remove = ata_pci_remove_one 1028669a5db4SJeff Garzik }; 1029669a5db4SJeff Garzik 1030669a5db4SJeff Garzik static int __init hpt37x_init(void) 1031669a5db4SJeff Garzik { 1032669a5db4SJeff Garzik return pci_register_driver(&hpt37x_pci_driver); 1033669a5db4SJeff Garzik } 1034669a5db4SJeff Garzik 1035669a5db4SJeff Garzik static void __exit hpt37x_exit(void) 1036669a5db4SJeff Garzik { 1037669a5db4SJeff Garzik pci_unregister_driver(&hpt37x_pci_driver); 1038669a5db4SJeff Garzik } 1039669a5db4SJeff Garzik 1040669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox"); 1041669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x"); 1042669a5db4SJeff Garzik MODULE_LICENSE("GPL"); 1043669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, hpt37x); 1044669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION); 1045669a5db4SJeff Garzik 1046669a5db4SJeff Garzik module_init(hpt37x_init); 1047669a5db4SJeff Garzik module_exit(hpt37x_exit); 1048