1669a5db4SJeff Garzik /* 2669a5db4SJeff Garzik * pata_via.c - VIA PATA for new ATA layer 3669a5db4SJeff Garzik * (C) 2005-2006 Red Hat Inc 4669a5db4SJeff Garzik * Alan Cox <alan@redhat.com> 5669a5db4SJeff Garzik * 6669a5db4SJeff Garzik * Documentation 7669a5db4SJeff Garzik * Most chipset documentation available under NDA only 8669a5db4SJeff Garzik * 9669a5db4SJeff Garzik * VIA version guide 10669a5db4SJeff Garzik * VIA VT82C561 - early design, uses ata_generic currently 11669a5db4SJeff Garzik * VIA VT82C576 - MWDMA, 33Mhz 12669a5db4SJeff Garzik * VIA VT82C586 - MWDMA, 33Mhz 13669a5db4SJeff Garzik * VIA VT82C586a - Added UDMA to 33Mhz 14669a5db4SJeff Garzik * VIA VT82C586b - UDMA33 15669a5db4SJeff Garzik * VIA VT82C596a - Nonfunctional UDMA66 16669a5db4SJeff Garzik * VIA VT82C596b - Working UDMA66 17669a5db4SJeff Garzik * VIA VT82C686 - Nonfunctional UDMA66 18669a5db4SJeff Garzik * VIA VT82C686a - Working UDMA66 19669a5db4SJeff Garzik * VIA VT82C686b - Updated to UDMA100 20669a5db4SJeff Garzik * VIA VT8231 - UDMA100 21669a5db4SJeff Garzik * VIA VT8233 - UDMA100 22669a5db4SJeff Garzik * VIA VT8233a - UDMA133 23669a5db4SJeff Garzik * VIA VT8233c - UDMA100 24669a5db4SJeff Garzik * VIA VT8235 - UDMA133 25669a5db4SJeff Garzik * VIA VT8237 - UDMA133 2605c39e50SAlan * VIA VT8237S - UDMA133 2775f609d2SAlan * VIA VT8251 - UDMA133 28669a5db4SJeff Garzik * 29669a5db4SJeff Garzik * Most registers remain compatible across chips. Others start reserved 30669a5db4SJeff Garzik * and acquire sensible semantics if set to 1 (eg cable detect). A few 31669a5db4SJeff Garzik * exceptions exist, notably around the FIFO settings. 32669a5db4SJeff Garzik * 33669a5db4SJeff Garzik * One additional quirk of the VIA design is that like ALi they use few 34669a5db4SJeff Garzik * PCI IDs for a lot of chips. 35669a5db4SJeff Garzik * 36669a5db4SJeff Garzik * Based heavily on: 37669a5db4SJeff Garzik * 38669a5db4SJeff Garzik * Version 3.38 39669a5db4SJeff Garzik * 40669a5db4SJeff Garzik * VIA IDE driver for Linux. Supported southbridges: 41669a5db4SJeff Garzik * 42669a5db4SJeff Garzik * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, 43669a5db4SJeff Garzik * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, 44669a5db4SJeff Garzik * vt8235, vt8237 45669a5db4SJeff Garzik * 46669a5db4SJeff Garzik * Copyright (c) 2000-2002 Vojtech Pavlik 47669a5db4SJeff Garzik * 48669a5db4SJeff Garzik * Based on the work of: 49669a5db4SJeff Garzik * Michel Aubry 50669a5db4SJeff Garzik * Jeff Garzik 51669a5db4SJeff Garzik * Andre Hedrick 52669a5db4SJeff Garzik 53669a5db4SJeff Garzik */ 54669a5db4SJeff Garzik 55669a5db4SJeff Garzik #include <linux/kernel.h> 56669a5db4SJeff Garzik #include <linux/module.h> 57669a5db4SJeff Garzik #include <linux/pci.h> 58669a5db4SJeff Garzik #include <linux/init.h> 59669a5db4SJeff Garzik #include <linux/blkdev.h> 60669a5db4SJeff Garzik #include <linux/delay.h> 61669a5db4SJeff Garzik #include <scsi/scsi_host.h> 62669a5db4SJeff Garzik #include <linux/libata.h> 63*cf5792d2SAlan Cox #include <linux/dmi.h> 64669a5db4SJeff Garzik 65669a5db4SJeff Garzik #define DRV_NAME "pata_via" 6697cb81c3SAlan Cox #define DRV_VERSION "0.3.1" 67669a5db4SJeff Garzik 68669a5db4SJeff Garzik /* 69669a5db4SJeff Garzik * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx 70669a5db4SJeff Garzik * driver. 71669a5db4SJeff Garzik */ 72669a5db4SJeff Garzik 73669a5db4SJeff Garzik enum { 74669a5db4SJeff Garzik VIA_UDMA = 0x007, 75669a5db4SJeff Garzik VIA_UDMA_NONE = 0x000, 76669a5db4SJeff Garzik VIA_UDMA_33 = 0x001, 77669a5db4SJeff Garzik VIA_UDMA_66 = 0x002, 78669a5db4SJeff Garzik VIA_UDMA_100 = 0x003, 79669a5db4SJeff Garzik VIA_UDMA_133 = 0x004, 80669a5db4SJeff Garzik VIA_BAD_PREQ = 0x010, /* Crashes if PREQ# till DDACK# set */ 81669a5db4SJeff Garzik VIA_BAD_CLK66 = 0x020, /* 66 MHz clock doesn't work correctly */ 82669a5db4SJeff Garzik VIA_SET_FIFO = 0x040, /* Needs to have FIFO split set */ 83669a5db4SJeff Garzik VIA_NO_UNMASK = 0x080, /* Doesn't work with IRQ unmasking on */ 84669a5db4SJeff Garzik VIA_BAD_ID = 0x100, /* Has wrong vendor ID (0x1107) */ 85669a5db4SJeff Garzik VIA_BAD_AST = 0x200, /* Don't touch Address Setup Timing */ 86669a5db4SJeff Garzik VIA_NO_ENABLES = 0x400, /* Has no enablebits */ 87669a5db4SJeff Garzik }; 88669a5db4SJeff Garzik 89669a5db4SJeff Garzik /* 90669a5db4SJeff Garzik * VIA SouthBridge chips. 91669a5db4SJeff Garzik */ 92669a5db4SJeff Garzik 93669a5db4SJeff Garzik static const struct via_isa_bridge { 94669a5db4SJeff Garzik const char *name; 95669a5db4SJeff Garzik u16 id; 96669a5db4SJeff Garzik u8 rev_min; 97669a5db4SJeff Garzik u8 rev_max; 98669a5db4SJeff Garzik u16 flags; 99669a5db4SJeff Garzik } via_isa_bridges[] = { 100e0b874dfSJosepch Chan { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 10175f609d2SAlan { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 102669a5db4SJeff Garzik { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 103669a5db4SJeff Garzik { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, 104669a5db4SJeff Garzik { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 105669a5db4SJeff Garzik { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 106669a5db4SJeff Garzik { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 107669a5db4SJeff Garzik { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, 108669a5db4SJeff Garzik { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, 109669a5db4SJeff Garzik { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, 110669a5db4SJeff Garzik { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, 111669a5db4SJeff Garzik { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, 112669a5db4SJeff Garzik { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, 113669a5db4SJeff Garzik { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, 114669a5db4SJeff Garzik { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, 115669a5db4SJeff Garzik { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, 116669a5db4SJeff Garzik { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, 117669a5db4SJeff Garzik { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, 118669a5db4SJeff Garzik { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, 119669a5db4SJeff Garzik { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, 120669a5db4SJeff Garzik { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, 121669a5db4SJeff Garzik { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK }, 122669a5db4SJeff Garzik { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, 123669a5db4SJeff Garzik { NULL } 124669a5db4SJeff Garzik }; 125669a5db4SJeff Garzik 126*cf5792d2SAlan Cox 127*cf5792d2SAlan Cox /* 128*cf5792d2SAlan Cox * Cable special cases 129*cf5792d2SAlan Cox */ 130*cf5792d2SAlan Cox 131*cf5792d2SAlan Cox static struct dmi_system_id cable_dmi_table[] = { 132*cf5792d2SAlan Cox { 133*cf5792d2SAlan Cox .ident = "Acer Ferrari 3400", 134*cf5792d2SAlan Cox .matches = { 135*cf5792d2SAlan Cox DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."), 136*cf5792d2SAlan Cox DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"), 137*cf5792d2SAlan Cox }, 138*cf5792d2SAlan Cox }, 139*cf5792d2SAlan Cox { } 140*cf5792d2SAlan Cox }; 141*cf5792d2SAlan Cox 142*cf5792d2SAlan Cox static int via_cable_override(struct pci_dev *pdev) 143*cf5792d2SAlan Cox { 144*cf5792d2SAlan Cox /* Systems by DMI */ 145*cf5792d2SAlan Cox if (dmi_check_system(cable_dmi_table)) 146*cf5792d2SAlan Cox return 1; 147*cf5792d2SAlan Cox return 0; 148*cf5792d2SAlan Cox } 149*cf5792d2SAlan Cox 150*cf5792d2SAlan Cox 151669a5db4SJeff Garzik /** 152669a5db4SJeff Garzik * via_cable_detect - cable detection 153669a5db4SJeff Garzik * @ap: ATA port 154669a5db4SJeff Garzik * 155669a5db4SJeff Garzik * Perform cable detection. Actually for the VIA case the BIOS 156669a5db4SJeff Garzik * already did this for us. We read the values provided by the 157669a5db4SJeff Garzik * BIOS. If you are using an 8235 in a non-PC configuration you 158669a5db4SJeff Garzik * may need to update this code. 159669a5db4SJeff Garzik * 160669a5db4SJeff Garzik * Hotplug also impacts on this. 161669a5db4SJeff Garzik */ 162669a5db4SJeff Garzik 163669a5db4SJeff Garzik static int via_cable_detect(struct ata_port *ap) { 16497cb81c3SAlan Cox const struct via_isa_bridge *config = ap->host->private_data; 165669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 166669a5db4SJeff Garzik u32 ata66; 167669a5db4SJeff Garzik 168*cf5792d2SAlan Cox if (via_cable_override(pdev)) 169*cf5792d2SAlan Cox return ATA_CBL_PATA40_SHORT; 170*cf5792d2SAlan Cox 17197cb81c3SAlan Cox /* Early chips are 40 wire */ 17297cb81c3SAlan Cox if ((config->flags & VIA_UDMA) < VIA_UDMA_66) 17397cb81c3SAlan Cox return ATA_CBL_PATA40; 17497cb81c3SAlan Cox /* UDMA 66 chips have only drive side logic */ 17597cb81c3SAlan Cox else if((config->flags & VIA_UDMA) < VIA_UDMA_100) 17697cb81c3SAlan Cox return ATA_CBL_PATA_UNK; 17797cb81c3SAlan Cox /* UDMA 100 or later */ 178669a5db4SJeff Garzik pci_read_config_dword(pdev, 0x50, &ata66); 179669a5db4SJeff Garzik /* Check both the drive cable reporting bits, we might not have 180669a5db4SJeff Garzik two drives */ 181669a5db4SJeff Garzik if (ata66 & (0x10100000 >> (16 * ap->port_no))) 182669a5db4SJeff Garzik return ATA_CBL_PATA80; 183669a5db4SJeff Garzik return ATA_CBL_PATA40; 184669a5db4SJeff Garzik } 185669a5db4SJeff Garzik 186d4b2bab4STejun Heo static int via_pre_reset(struct ata_port *ap, unsigned long deadline) 187669a5db4SJeff Garzik { 188669a5db4SJeff Garzik const struct via_isa_bridge *config = ap->host->private_data; 189669a5db4SJeff Garzik 190669a5db4SJeff Garzik if (!(config->flags & VIA_NO_ENABLES)) { 191669a5db4SJeff Garzik static const struct pci_bits via_enable_bits[] = { 192669a5db4SJeff Garzik { 0x40, 1, 0x02, 0x02 }, 193669a5db4SJeff Garzik { 0x40, 1, 0x01, 0x01 } 194669a5db4SJeff Garzik }; 195669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 196c961922bSAlan Cox if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no])) 197c961922bSAlan Cox return -ENOENT; 198669a5db4SJeff Garzik } 199d4b2bab4STejun Heo 200d4b2bab4STejun Heo return ata_std_prereset(ap, deadline); 201669a5db4SJeff Garzik } 202669a5db4SJeff Garzik 203669a5db4SJeff Garzik 204669a5db4SJeff Garzik /** 205669a5db4SJeff Garzik * via_error_handler - reset for VIA chips 206669a5db4SJeff Garzik * @ap: ATA port 207669a5db4SJeff Garzik * 208669a5db4SJeff Garzik * Handle the reset callback for the later chips with cable detect 209669a5db4SJeff Garzik */ 210669a5db4SJeff Garzik 211669a5db4SJeff Garzik static void via_error_handler(struct ata_port *ap) 212669a5db4SJeff Garzik { 213669a5db4SJeff Garzik ata_bmdma_drive_eh(ap, via_pre_reset, ata_std_softreset, NULL, ata_std_postreset); 214669a5db4SJeff Garzik } 215669a5db4SJeff Garzik 216669a5db4SJeff Garzik /** 217669a5db4SJeff Garzik * via_do_set_mode - set initial PIO mode data 218669a5db4SJeff Garzik * @ap: ATA interface 219669a5db4SJeff Garzik * @adev: ATA device 220669a5db4SJeff Garzik * @mode: ATA mode being programmed 221669a5db4SJeff Garzik * @tdiv: Clocks per PCI clock 222669a5db4SJeff Garzik * @set_ast: Set to program address setup 223669a5db4SJeff Garzik * @udma_type: UDMA mode/format of registers 224669a5db4SJeff Garzik * 225669a5db4SJeff Garzik * Program the VIA registers for DMA and PIO modes. Uses the ata timing 226669a5db4SJeff Garzik * support in order to compute modes. 227669a5db4SJeff Garzik * 228669a5db4SJeff Garzik * FIXME: Hotplug will require we serialize multiple mode changes 229669a5db4SJeff Garzik * on the two channels. 230669a5db4SJeff Garzik */ 231669a5db4SJeff Garzik 232669a5db4SJeff Garzik static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mode, int tdiv, int set_ast, int udma_type) 233669a5db4SJeff Garzik { 234669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev); 235669a5db4SJeff Garzik struct ata_device *peer = ata_dev_pair(adev); 236669a5db4SJeff Garzik struct ata_timing t, p; 237669a5db4SJeff Garzik static int via_clock = 33333; /* Bus clock in kHZ - ought to be tunable one day */ 238669a5db4SJeff Garzik unsigned long T = 1000000000 / via_clock; 239669a5db4SJeff Garzik unsigned long UT = T/tdiv; 240669a5db4SJeff Garzik int ut; 241669a5db4SJeff Garzik int offset = 3 - (2*ap->port_no) - adev->devno; 242669a5db4SJeff Garzik 243669a5db4SJeff Garzik 244669a5db4SJeff Garzik /* Calculate the timing values we require */ 245669a5db4SJeff Garzik ata_timing_compute(adev, mode, &t, T, UT); 246669a5db4SJeff Garzik 247669a5db4SJeff Garzik /* We share 8bit timing so we must merge the constraints */ 248669a5db4SJeff Garzik if (peer) { 249669a5db4SJeff Garzik if (peer->pio_mode) { 250669a5db4SJeff Garzik ata_timing_compute(peer, peer->pio_mode, &p, T, UT); 251669a5db4SJeff Garzik ata_timing_merge(&p, &t, &t, ATA_TIMING_8BIT); 252669a5db4SJeff Garzik } 253669a5db4SJeff Garzik } 254669a5db4SJeff Garzik 255669a5db4SJeff Garzik /* Address setup is programmable but breaks on UDMA133 setups */ 256669a5db4SJeff Garzik if (set_ast) { 257669a5db4SJeff Garzik u8 setup; /* 2 bits per drive */ 258669a5db4SJeff Garzik int shift = 2 * offset; 259669a5db4SJeff Garzik 260669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x4C, &setup); 261669a5db4SJeff Garzik setup &= ~(3 << shift); 262669a5db4SJeff Garzik setup |= FIT(t.setup, 1, 4) << shift; /* 1,4 or 1,4 - 1 FIXME */ 263669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x4C, setup); 264669a5db4SJeff Garzik } 265669a5db4SJeff Garzik 266669a5db4SJeff Garzik /* Load the PIO mode bits */ 267669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x4F - ap->port_no, 268669a5db4SJeff Garzik ((FIT(t.act8b, 1, 16) - 1) << 4) | (FIT(t.rec8b, 1, 16) - 1)); 269669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x48 + offset, 270669a5db4SJeff Garzik ((FIT(t.active, 1, 16) - 1) << 4) | (FIT(t.recover, 1, 16) - 1)); 271669a5db4SJeff Garzik 272669a5db4SJeff Garzik /* Load the UDMA bits according to type */ 273669a5db4SJeff Garzik switch(udma_type) { 274669a5db4SJeff Garzik default: 275669a5db4SJeff Garzik /* BUG() ? */ 276669a5db4SJeff Garzik /* fall through */ 277669a5db4SJeff Garzik case 33: 278669a5db4SJeff Garzik ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 5) - 2)) : 0x03; 279669a5db4SJeff Garzik break; 280669a5db4SJeff Garzik case 66: 281669a5db4SJeff Garzik ut = t.udma ? (0xe8 | (FIT(t.udma, 2, 9) - 2)) : 0x0f; 282669a5db4SJeff Garzik break; 283669a5db4SJeff Garzik case 100: 284669a5db4SJeff Garzik ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07; 285669a5db4SJeff Garzik break; 286669a5db4SJeff Garzik case 133: 287669a5db4SJeff Garzik ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07; 288669a5db4SJeff Garzik break; 289669a5db4SJeff Garzik } 290669a5db4SJeff Garzik /* Set UDMA unless device is not UDMA capable */ 291669a5db4SJeff Garzik if (udma_type) 292669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x50 + offset, ut); 293669a5db4SJeff Garzik } 294669a5db4SJeff Garzik 295669a5db4SJeff Garzik static void via_set_piomode(struct ata_port *ap, struct ata_device *adev) 296669a5db4SJeff Garzik { 297669a5db4SJeff Garzik const struct via_isa_bridge *config = ap->host->private_data; 298669a5db4SJeff Garzik int set_ast = (config->flags & VIA_BAD_AST) ? 0 : 1; 299669a5db4SJeff Garzik int mode = config->flags & VIA_UDMA; 300669a5db4SJeff Garzik static u8 tclock[5] = { 1, 1, 2, 3, 4 }; 301669a5db4SJeff Garzik static u8 udma[5] = { 0, 33, 66, 100, 133 }; 302669a5db4SJeff Garzik 303669a5db4SJeff Garzik via_do_set_mode(ap, adev, adev->pio_mode, tclock[mode], set_ast, udma[mode]); 304669a5db4SJeff Garzik } 305669a5db4SJeff Garzik 306669a5db4SJeff Garzik static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) 307669a5db4SJeff Garzik { 308669a5db4SJeff Garzik const struct via_isa_bridge *config = ap->host->private_data; 309669a5db4SJeff Garzik int set_ast = (config->flags & VIA_BAD_AST) ? 0 : 1; 310669a5db4SJeff Garzik int mode = config->flags & VIA_UDMA; 311669a5db4SJeff Garzik static u8 tclock[5] = { 1, 1, 2, 3, 4 }; 312669a5db4SJeff Garzik static u8 udma[5] = { 0, 33, 66, 100, 133 }; 313669a5db4SJeff Garzik 314669a5db4SJeff Garzik via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); 315669a5db4SJeff Garzik } 316669a5db4SJeff Garzik 317669a5db4SJeff Garzik static struct scsi_host_template via_sht = { 318669a5db4SJeff Garzik .module = THIS_MODULE, 319669a5db4SJeff Garzik .name = DRV_NAME, 320669a5db4SJeff Garzik .ioctl = ata_scsi_ioctl, 321669a5db4SJeff Garzik .queuecommand = ata_scsi_queuecmd, 322669a5db4SJeff Garzik .can_queue = ATA_DEF_QUEUE, 323669a5db4SJeff Garzik .this_id = ATA_SHT_THIS_ID, 324669a5db4SJeff Garzik .sg_tablesize = LIBATA_MAX_PRD, 325669a5db4SJeff Garzik .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 326669a5db4SJeff Garzik .emulated = ATA_SHT_EMULATED, 327669a5db4SJeff Garzik .use_clustering = ATA_SHT_USE_CLUSTERING, 328669a5db4SJeff Garzik .proc_name = DRV_NAME, 329669a5db4SJeff Garzik .dma_boundary = ATA_DMA_BOUNDARY, 330669a5db4SJeff Garzik .slave_configure = ata_scsi_slave_config, 331afdfe899STejun Heo .slave_destroy = ata_scsi_slave_destroy, 332669a5db4SJeff Garzik .bios_param = ata_std_bios_param, 333669a5db4SJeff Garzik }; 334669a5db4SJeff Garzik 335669a5db4SJeff Garzik static struct ata_port_operations via_port_ops = { 336669a5db4SJeff Garzik .port_disable = ata_port_disable, 337669a5db4SJeff Garzik .set_piomode = via_set_piomode, 338669a5db4SJeff Garzik .set_dmamode = via_set_dmamode, 339669a5db4SJeff Garzik .mode_filter = ata_pci_default_filter, 340669a5db4SJeff Garzik 341669a5db4SJeff Garzik .tf_load = ata_tf_load, 342669a5db4SJeff Garzik .tf_read = ata_tf_read, 343669a5db4SJeff Garzik .check_status = ata_check_status, 344669a5db4SJeff Garzik .exec_command = ata_exec_command, 345669a5db4SJeff Garzik .dev_select = ata_std_dev_select, 346669a5db4SJeff Garzik 347669a5db4SJeff Garzik .freeze = ata_bmdma_freeze, 348669a5db4SJeff Garzik .thaw = ata_bmdma_thaw, 349669a5db4SJeff Garzik .error_handler = via_error_handler, 350669a5db4SJeff Garzik .post_internal_cmd = ata_bmdma_post_internal_cmd, 35197cb81c3SAlan Cox .cable_detect = via_cable_detect, 352669a5db4SJeff Garzik 353669a5db4SJeff Garzik .bmdma_setup = ata_bmdma_setup, 354669a5db4SJeff Garzik .bmdma_start = ata_bmdma_start, 355669a5db4SJeff Garzik .bmdma_stop = ata_bmdma_stop, 356669a5db4SJeff Garzik .bmdma_status = ata_bmdma_status, 357669a5db4SJeff Garzik 358669a5db4SJeff Garzik .qc_prep = ata_qc_prep, 359669a5db4SJeff Garzik .qc_issue = ata_qc_issue_prot, 360bda30288SJeff Garzik 3610d5ff566STejun Heo .data_xfer = ata_data_xfer, 362669a5db4SJeff Garzik 363669a5db4SJeff Garzik .irq_handler = ata_interrupt, 364669a5db4SJeff Garzik .irq_clear = ata_bmdma_irq_clear, 365246ce3b6SAkira Iguchi .irq_on = ata_irq_on, 366246ce3b6SAkira Iguchi .irq_ack = ata_irq_ack, 367669a5db4SJeff Garzik 368669a5db4SJeff Garzik .port_start = ata_port_start, 369669a5db4SJeff Garzik }; 370669a5db4SJeff Garzik 371669a5db4SJeff Garzik static struct ata_port_operations via_port_ops_noirq = { 372669a5db4SJeff Garzik .port_disable = ata_port_disable, 373669a5db4SJeff Garzik .set_piomode = via_set_piomode, 374669a5db4SJeff Garzik .set_dmamode = via_set_dmamode, 375669a5db4SJeff Garzik .mode_filter = ata_pci_default_filter, 376669a5db4SJeff Garzik 377669a5db4SJeff Garzik .tf_load = ata_tf_load, 378669a5db4SJeff Garzik .tf_read = ata_tf_read, 379669a5db4SJeff Garzik .check_status = ata_check_status, 380669a5db4SJeff Garzik .exec_command = ata_exec_command, 381669a5db4SJeff Garzik .dev_select = ata_std_dev_select, 382669a5db4SJeff Garzik 383669a5db4SJeff Garzik .freeze = ata_bmdma_freeze, 384669a5db4SJeff Garzik .thaw = ata_bmdma_thaw, 385669a5db4SJeff Garzik .error_handler = via_error_handler, 386669a5db4SJeff Garzik .post_internal_cmd = ata_bmdma_post_internal_cmd, 38797cb81c3SAlan Cox .cable_detect = via_cable_detect, 388669a5db4SJeff Garzik 389669a5db4SJeff Garzik .bmdma_setup = ata_bmdma_setup, 390669a5db4SJeff Garzik .bmdma_start = ata_bmdma_start, 391669a5db4SJeff Garzik .bmdma_stop = ata_bmdma_stop, 392669a5db4SJeff Garzik .bmdma_status = ata_bmdma_status, 393669a5db4SJeff Garzik 394669a5db4SJeff Garzik .qc_prep = ata_qc_prep, 395669a5db4SJeff Garzik .qc_issue = ata_qc_issue_prot, 396bda30288SJeff Garzik 3970d5ff566STejun Heo .data_xfer = ata_data_xfer_noirq, 398669a5db4SJeff Garzik 399669a5db4SJeff Garzik .irq_handler = ata_interrupt, 400669a5db4SJeff Garzik .irq_clear = ata_bmdma_irq_clear, 401246ce3b6SAkira Iguchi .irq_on = ata_irq_on, 402246ce3b6SAkira Iguchi .irq_ack = ata_irq_ack, 403669a5db4SJeff Garzik 404669a5db4SJeff Garzik .port_start = ata_port_start, 405669a5db4SJeff Garzik }; 406669a5db4SJeff Garzik 407669a5db4SJeff Garzik /** 408627d2d32SAlan * via_config_fifo - set up the FIFO 409627d2d32SAlan * @pdev: PCI device 410627d2d32SAlan * @flags: configuration flags 411627d2d32SAlan * 412627d2d32SAlan * Set the FIFO properties for this device if neccessary. Used both on 413627d2d32SAlan * set up and on and the resume path 414627d2d32SAlan */ 415627d2d32SAlan 416627d2d32SAlan static void via_config_fifo(struct pci_dev *pdev, unsigned int flags) 417627d2d32SAlan { 418627d2d32SAlan u8 enable; 419627d2d32SAlan 420627d2d32SAlan /* 0x40 low bits indicate enabled channels */ 421627d2d32SAlan pci_read_config_byte(pdev, 0x40 , &enable); 422627d2d32SAlan enable &= 3; 423627d2d32SAlan 424627d2d32SAlan if (flags & VIA_SET_FIFO) { 42573720861SAndrew Morton static const u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; 426627d2d32SAlan u8 fifo; 427627d2d32SAlan 428627d2d32SAlan pci_read_config_byte(pdev, 0x43, &fifo); 429627d2d32SAlan 430627d2d32SAlan /* Clear PREQ# until DDACK# for errata */ 431627d2d32SAlan if (flags & VIA_BAD_PREQ) 432627d2d32SAlan fifo &= 0x7F; 433627d2d32SAlan else 434627d2d32SAlan fifo &= 0x9f; 435627d2d32SAlan /* Turn on FIFO for enabled channels */ 436627d2d32SAlan fifo |= fifo_setting[enable]; 437627d2d32SAlan pci_write_config_byte(pdev, 0x43, fifo); 438627d2d32SAlan } 439627d2d32SAlan } 440627d2d32SAlan 441627d2d32SAlan /** 442669a5db4SJeff Garzik * via_init_one - discovery callback 443627d2d32SAlan * @pdev: PCI device 444669a5db4SJeff Garzik * @id: PCI table info 445669a5db4SJeff Garzik * 446669a5db4SJeff Garzik * A VIA IDE interface has been discovered. Figure out what revision 447669a5db4SJeff Garzik * and perform configuration work before handing it to the ATA layer 448669a5db4SJeff Garzik */ 449669a5db4SJeff Garzik 450669a5db4SJeff Garzik static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 451669a5db4SJeff Garzik { 452669a5db4SJeff Garzik /* Early VIA without UDMA support */ 4531626aeb8STejun Heo static const struct ata_port_info via_mwdma_info = { 454669a5db4SJeff Garzik .sht = &via_sht, 4553d3cca37STejun Heo .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, 456669a5db4SJeff Garzik .pio_mask = 0x1f, 457669a5db4SJeff Garzik .mwdma_mask = 0x07, 458669a5db4SJeff Garzik .port_ops = &via_port_ops 459669a5db4SJeff Garzik }; 460669a5db4SJeff Garzik /* Ditto with IRQ masking required */ 4611626aeb8STejun Heo static const struct ata_port_info via_mwdma_info_borked = { 462669a5db4SJeff Garzik .sht = &via_sht, 4633d3cca37STejun Heo .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, 464669a5db4SJeff Garzik .pio_mask = 0x1f, 465669a5db4SJeff Garzik .mwdma_mask = 0x07, 466669a5db4SJeff Garzik .port_ops = &via_port_ops_noirq, 467669a5db4SJeff Garzik }; 468669a5db4SJeff Garzik /* VIA UDMA 33 devices (and borked 66) */ 4691626aeb8STejun Heo static const struct ata_port_info via_udma33_info = { 470669a5db4SJeff Garzik .sht = &via_sht, 4713d3cca37STejun Heo .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, 472669a5db4SJeff Garzik .pio_mask = 0x1f, 473669a5db4SJeff Garzik .mwdma_mask = 0x07, 474669a5db4SJeff Garzik .udma_mask = 0x7, 475669a5db4SJeff Garzik .port_ops = &via_port_ops 476669a5db4SJeff Garzik }; 477669a5db4SJeff Garzik /* VIA UDMA 66 devices */ 4781626aeb8STejun Heo static const struct ata_port_info via_udma66_info = { 479669a5db4SJeff Garzik .sht = &via_sht, 4803d3cca37STejun Heo .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, 481669a5db4SJeff Garzik .pio_mask = 0x1f, 482669a5db4SJeff Garzik .mwdma_mask = 0x07, 483669a5db4SJeff Garzik .udma_mask = 0x1f, 484669a5db4SJeff Garzik .port_ops = &via_port_ops 485669a5db4SJeff Garzik }; 486669a5db4SJeff Garzik /* VIA UDMA 100 devices */ 4871626aeb8STejun Heo static const struct ata_port_info via_udma100_info = { 488669a5db4SJeff Garzik .sht = &via_sht, 4893d3cca37STejun Heo .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, 490669a5db4SJeff Garzik .pio_mask = 0x1f, 491669a5db4SJeff Garzik .mwdma_mask = 0x07, 492669a5db4SJeff Garzik .udma_mask = 0x3f, 493669a5db4SJeff Garzik .port_ops = &via_port_ops 494669a5db4SJeff Garzik }; 495669a5db4SJeff Garzik /* UDMA133 with bad AST (All current 133) */ 4961626aeb8STejun Heo static const struct ata_port_info via_udma133_info = { 497669a5db4SJeff Garzik .sht = &via_sht, 4983d3cca37STejun Heo .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, 499669a5db4SJeff Garzik .pio_mask = 0x1f, 500669a5db4SJeff Garzik .mwdma_mask = 0x07, 501669a5db4SJeff Garzik .udma_mask = 0x7f, /* FIXME: should check north bridge */ 502669a5db4SJeff Garzik .port_ops = &via_port_ops 503669a5db4SJeff Garzik }; 5041626aeb8STejun Heo struct ata_port_info type; 5051626aeb8STejun Heo const struct ata_port_info *ppi[] = { &type, NULL }; 506669a5db4SJeff Garzik struct pci_dev *isa = NULL; 507669a5db4SJeff Garzik const struct via_isa_bridge *config; 508669a5db4SJeff Garzik static int printed_version; 509669a5db4SJeff Garzik u8 t; 510669a5db4SJeff Garzik u8 enable; 511669a5db4SJeff Garzik u32 timing; 512669a5db4SJeff Garzik 513669a5db4SJeff Garzik if (!printed_version++) 514669a5db4SJeff Garzik dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 515669a5db4SJeff Garzik 516669a5db4SJeff Garzik /* To find out how the IDE will behave and what features we 517669a5db4SJeff Garzik actually have to look at the bridge not the IDE controller */ 518669a5db4SJeff Garzik for (config = via_isa_bridges; config->id; config++) 519669a5db4SJeff Garzik if ((isa = pci_get_device(PCI_VENDOR_ID_VIA + 520669a5db4SJeff Garzik !!(config->flags & VIA_BAD_ID), 521669a5db4SJeff Garzik config->id, NULL))) { 522669a5db4SJeff Garzik 523669a5db4SJeff Garzik pci_read_config_byte(isa, PCI_REVISION_ID, &t); 524669a5db4SJeff Garzik if (t >= config->rev_min && 525669a5db4SJeff Garzik t <= config->rev_max) 526669a5db4SJeff Garzik break; 527669a5db4SJeff Garzik pci_dev_put(isa); 528669a5db4SJeff Garzik } 529669a5db4SJeff Garzik 530669a5db4SJeff Garzik if (!config->id) { 531669a5db4SJeff Garzik printk(KERN_WARNING "via: Unknown VIA SouthBridge, disabling.\n"); 532669a5db4SJeff Garzik return -ENODEV; 533669a5db4SJeff Garzik } 534669a5db4SJeff Garzik pci_dev_put(isa); 535669a5db4SJeff Garzik 536669a5db4SJeff Garzik /* 0x40 low bits indicate enabled channels */ 537669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x40 , &enable); 538669a5db4SJeff Garzik enable &= 3; 539669a5db4SJeff Garzik if (enable == 0) { 540669a5db4SJeff Garzik return -ENODEV; 541669a5db4SJeff Garzik } 542669a5db4SJeff Garzik 543669a5db4SJeff Garzik /* Initialise the FIFO for the enabled channels. */ 544627d2d32SAlan via_config_fifo(pdev, config->flags); 545669a5db4SJeff Garzik 546669a5db4SJeff Garzik /* Clock set up */ 547669a5db4SJeff Garzik switch(config->flags & VIA_UDMA) { 548669a5db4SJeff Garzik case VIA_UDMA_NONE: 549669a5db4SJeff Garzik if (config->flags & VIA_NO_UNMASK) 5501626aeb8STejun Heo type = via_mwdma_info_borked; 551669a5db4SJeff Garzik else 5521626aeb8STejun Heo type = via_mwdma_info; 553669a5db4SJeff Garzik break; 554669a5db4SJeff Garzik case VIA_UDMA_33: 5551626aeb8STejun Heo type = via_udma33_info; 556669a5db4SJeff Garzik break; 557669a5db4SJeff Garzik case VIA_UDMA_66: 5581626aeb8STejun Heo type = via_udma66_info; 559669a5db4SJeff Garzik /* The 66 MHz devices require we enable the clock */ 560669a5db4SJeff Garzik pci_read_config_dword(pdev, 0x50, &timing); 561669a5db4SJeff Garzik timing |= 0x80008; 562669a5db4SJeff Garzik pci_write_config_dword(pdev, 0x50, timing); 563669a5db4SJeff Garzik break; 564669a5db4SJeff Garzik case VIA_UDMA_100: 5651626aeb8STejun Heo type = via_udma100_info; 566669a5db4SJeff Garzik break; 567669a5db4SJeff Garzik case VIA_UDMA_133: 5681626aeb8STejun Heo type = via_udma133_info; 569669a5db4SJeff Garzik break; 570669a5db4SJeff Garzik default: 571669a5db4SJeff Garzik WARN_ON(1); 572669a5db4SJeff Garzik return -ENODEV; 573669a5db4SJeff Garzik } 574669a5db4SJeff Garzik 575669a5db4SJeff Garzik if (config->flags & VIA_BAD_CLK66) { 576669a5db4SJeff Garzik /* Disable the 66MHz clock on problem devices */ 577669a5db4SJeff Garzik pci_read_config_dword(pdev, 0x50, &timing); 578669a5db4SJeff Garzik timing &= ~0x80008; 579669a5db4SJeff Garzik pci_write_config_dword(pdev, 0x50, timing); 580669a5db4SJeff Garzik } 581669a5db4SJeff Garzik 582669a5db4SJeff Garzik /* We have established the device type, now fire it up */ 5831626aeb8STejun Heo type.private_data = (void *)config; 584669a5db4SJeff Garzik 5851626aeb8STejun Heo return ata_pci_init_one(pdev, ppi); 586669a5db4SJeff Garzik } 587669a5db4SJeff Garzik 588438ac6d5STejun Heo #ifdef CONFIG_PM 589627d2d32SAlan /** 590627d2d32SAlan * via_reinit_one - reinit after resume 591627d2d32SAlan * @pdev; PCI device 592627d2d32SAlan * 593627d2d32SAlan * Called when the VIA PATA device is resumed. We must then 594627d2d32SAlan * reconfigure the fifo and other setup we may have altered. In 595627d2d32SAlan * addition the kernel needs to have the resume methods on PCI 596627d2d32SAlan * quirk supported. 597627d2d32SAlan */ 598627d2d32SAlan 599627d2d32SAlan static int via_reinit_one(struct pci_dev *pdev) 600627d2d32SAlan { 601627d2d32SAlan u32 timing; 602627d2d32SAlan struct ata_host *host = dev_get_drvdata(&pdev->dev); 603627d2d32SAlan const struct via_isa_bridge *config = host->private_data; 604627d2d32SAlan 605627d2d32SAlan via_config_fifo(pdev, config->flags); 606627d2d32SAlan 607627d2d32SAlan if ((config->flags & VIA_UDMA) == VIA_UDMA_66) { 608627d2d32SAlan /* The 66 MHz devices require we enable the clock */ 609627d2d32SAlan pci_read_config_dword(pdev, 0x50, &timing); 610627d2d32SAlan timing |= 0x80008; 611627d2d32SAlan pci_write_config_dword(pdev, 0x50, timing); 612627d2d32SAlan } 613627d2d32SAlan if (config->flags & VIA_BAD_CLK66) { 614627d2d32SAlan /* Disable the 66MHz clock on problem devices */ 615627d2d32SAlan pci_read_config_dword(pdev, 0x50, &timing); 616627d2d32SAlan timing &= ~0x80008; 617627d2d32SAlan pci_write_config_dword(pdev, 0x50, timing); 618627d2d32SAlan } 619627d2d32SAlan return ata_pci_device_resume(pdev); 620627d2d32SAlan } 621438ac6d5STejun Heo #endif 622627d2d32SAlan 623669a5db4SJeff Garzik static const struct pci_device_id via[] = { 6242d2744fcSJeff Garzik { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), }, 6252d2744fcSJeff Garzik { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), }, 6262d2744fcSJeff Garzik { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), }, 6272d2744fcSJeff Garzik { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), }, 6282d2744fcSJeff Garzik 6292d2744fcSJeff Garzik { }, 630669a5db4SJeff Garzik }; 631669a5db4SJeff Garzik 632669a5db4SJeff Garzik static struct pci_driver via_pci_driver = { 633669a5db4SJeff Garzik .name = DRV_NAME, 634669a5db4SJeff Garzik .id_table = via, 635669a5db4SJeff Garzik .probe = via_init_one, 636627d2d32SAlan .remove = ata_pci_remove_one, 637438ac6d5STejun Heo #ifdef CONFIG_PM 638627d2d32SAlan .suspend = ata_pci_device_suspend, 639627d2d32SAlan .resume = via_reinit_one, 640438ac6d5STejun Heo #endif 641669a5db4SJeff Garzik }; 642669a5db4SJeff Garzik 643669a5db4SJeff Garzik static int __init via_init(void) 644669a5db4SJeff Garzik { 645669a5db4SJeff Garzik return pci_register_driver(&via_pci_driver); 646669a5db4SJeff Garzik } 647669a5db4SJeff Garzik 648669a5db4SJeff Garzik static void __exit via_exit(void) 649669a5db4SJeff Garzik { 650669a5db4SJeff Garzik pci_unregister_driver(&via_pci_driver); 651669a5db4SJeff Garzik } 652669a5db4SJeff Garzik 653669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox"); 654669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for VIA PATA"); 655669a5db4SJeff Garzik MODULE_LICENSE("GPL"); 656669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, via); 657669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION); 658669a5db4SJeff Garzik 659669a5db4SJeff Garzik module_init(via_init); 660669a5db4SJeff Garzik module_exit(via_exit); 661