1669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 2669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * pata-legacy.c - Legacy port PATA/SATA controller driver. 3ab77163008c596aad9624ceab190d840c0143fa8Alan Cox * Copyright 2005/2006 Red Hat, all rights reserved. 4669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 5669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This program is free software; you can redistribute it and/or modify 6669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * it under the terms of the GNU General Public License as published by 7669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * the Free Software Foundation; either version 2, or (at your option) 8669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * any later version. 9669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 10669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This program is distributed in the hope that it will be useful, 11669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 12669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * GNU General Public License for more details. 14669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * You should have received a copy of the GNU General Public License 16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * along with this program; see the file COPYING. If not, write to 17669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * An ATA driver for the legacy ATA ports. 20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Data Sources: 22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Opti 82C465/82C611 support: Data sheets at opti-inc.com 23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * HT6560 series: 24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Promise 20230/20620: 25669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * http://www.ryston.cz/petr/vlb/pdc20230b.html 26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * http://www.ryston.cz/petr/vlb/pdc20230c.html 27669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * http://www.ryston.cz/petr/vlb/pdc20630.html 289c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * QDI65x0: 299c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * http://www.ryston.cz/petr/vlb/qd6500.html 309c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * http://www.ryston.cz/petr/vlb/qd6580.html 319c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * 329c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * QDI65x0 probe code based on drivers/ide/legacy/qd65xx.c 339c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by 349c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * Samuel Thibault <samuel.thibault@ens-lyon.org> 35669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Unsupported but docs exist: 37669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Appian/Adaptec AIC25VL01/Cirrus Logic PD7220 38669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 39669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This driver handles legacy (that is "ISA/VLB side") IDE ports found 40669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * on PC class systems. There are three hybrid devices that are exceptions 41669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * The Cyrix 5510/5520 where a pre SFF ATA device is on the bridge and 42669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * the MPIIX where the tuning is PCI side but the IDE is "ISA side". 43669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 44669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Specific support is included for the ht6560a/ht6560b/opti82c611a/ 459c7e0d22c524afc76f82b942d12da00766ac9101Bartlomiej Zolnierkiewicz * opti82c465mv/promise 20230c/20630/qdi65x0/winbond83759A 46669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 476d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz * Support for the Winbond 83759A when operating in advanced mode. 486d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz * Multichip mode is not currently supported. 496d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz * 50669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Use the autospeed and pio_mask options with: 51669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Appian ADI/2 aka CLPD7220 or AIC25VL01. 52669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Use the jumpers, autospeed and set pio_mask to the mode on the jumpers with 53669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Goldstar GM82C711, PIC-1288A-125, UMC 82C871F, Winbond W83759, 54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Winbond W83759A, Promise PDC20230-B 55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * For now use autospeed and pio_mask as above with the W83759A. This may 57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * change. 58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 6145bc955bb1324a46c9539550cc615994e6d0a43dJames Bottomley#include <linux/async.h> 62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h> 63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h> 64669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h> 65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h> 66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h> 67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h> 68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h> 69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/ata.h> 70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h> 71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/platform_device.h> 72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME "pata_legacy" 74b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox#define DRV_VERSION "0.6.5" 75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define NR_HOST 6 77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 78defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int all; 79defc9cd826e4a99f550504a744f9407b518828aeAlan Coxmodule_param(all, int, 0444); 80defc9cd826e4a99f550504a744f9407b518828aeAlan CoxMODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)"); 81669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 82defc9cd826e4a99f550504a744f9407b518828aeAlan Coxenum controller { 83defc9cd826e4a99f550504a744f9407b518828aeAlan Cox BIOS = 0, 84defc9cd826e4a99f550504a744f9407b518828aeAlan Cox SNOOP = 1, 85defc9cd826e4a99f550504a744f9407b518828aeAlan Cox PDC20230 = 2, 86defc9cd826e4a99f550504a744f9407b518828aeAlan Cox HT6560A = 3, 87defc9cd826e4a99f550504a744f9407b518828aeAlan Cox HT6560B = 4, 88defc9cd826e4a99f550504a744f9407b518828aeAlan Cox OPTI611A = 5, 89defc9cd826e4a99f550504a744f9407b518828aeAlan Cox OPTI46X = 6, 90defc9cd826e4a99f550504a744f9407b518828aeAlan Cox QDI6500 = 7, 91defc9cd826e4a99f550504a744f9407b518828aeAlan Cox QDI6580 = 8, 92defc9cd826e4a99f550504a744f9407b518828aeAlan Cox QDI6580DP = 9, /* Dual channel mode is different */ 93b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox W83759A = 10, 94defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 95defc9cd826e4a99f550504a744f9407b518828aeAlan Cox UNKNOWN = -1 96defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 97defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 988c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewiczstruct legacy_data { 998c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz unsigned long timing; 1008c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz u8 clock[2]; 1018c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz u8 last; 1028c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz int fast; 1038c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz enum controller type; 1048c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz struct platform_device *platform_dev; 1058c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz}; 106defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 107defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstruct legacy_probe { 108defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned char *name; 109defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned long port; 110defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned int irq; 111defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned int slot; 112defc9cd826e4a99f550504a744f9407b518828aeAlan Cox enum controller type; 113defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned long private; 114defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 115defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 116defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstruct legacy_controller { 117defc9cd826e4a99f550504a744f9407b518828aeAlan Cox const char *name; 118defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_port_operations *ops; 119defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned int pio_mask; 120defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned int flags; 121e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox unsigned int pflags; 122b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox int (*setup)(struct platform_device *, struct legacy_probe *probe, 123b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox struct legacy_data *data); 124defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 125defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 126defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; 127defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 128defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct legacy_probe probe_list[NR_HOST]; 129669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct legacy_data legacy_data[NR_HOST]; 130669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_host *legacy_host[NR_HOST]; 131669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int nr_legacy_host; 132669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 133669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 134defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int probe_all; /* Set to check all ISA port ranges */ 135defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int ht6560a; /* HT 6560A on primary 1, second 2, both 3 */ 136defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int ht6560b; /* HT 6560A on primary 1, second 2, both 3 */ 137defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int opti82c611a; /* Opti82c611A on primary 1, sec 2, both 3 */ 138defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int opti82c46x; /* Opti 82c465MV present(pri/sec autodetect) */ 139defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int autospeed; /* Chip present which snoops speed changes */ 14014bdef982caeda19afe34010482867c18217c641Erik Inge Bolsøstatic int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */ 141f834e49f1a09414e9618ff0c9cd83c2114032bb6Alan Coxstatic int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */ 142669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1430dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz/* Set to probe QDI controllers */ 1440dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz#ifdef CONFIG_PATA_QDI_MODULE 1450dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewiczstatic int qdi = 1; 1460dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz#else 1470dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewiczstatic int qdi; 1480dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz#endif 1490dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej Zolnierkiewicz 150f60215a1302f03ad435f8365c0dd85bdb022cac3Tejun Heo#ifdef CONFIG_PATA_WINBOND_VLB_MODULE 1516d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewiczstatic int winbond = 1; /* Set to probe Winbond controllers, 1526d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz give I/O port if non standard */ 1536d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz#else 1546d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewiczstatic int winbond; /* Set to probe Winbond controllers, 1556d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz give I/O port if non standard */ 1566d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz#endif 1576d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewicz 158669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/** 159defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * legacy_probe_add - Add interface to probe list 160defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @port: Controller port 161defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @irq: IRQ number 162defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @type: Controller type 163defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @private: Controller specific info 164defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * 165defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * Add an entry into the probe list for ATA controllers. This is used 166defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * to add the default ISA slots and then to build up the table 167defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * further according to other ISA/VLB/Weird device scans 168defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * 169defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * An I/O port list is used to keep ordering stable and sane, as we 170defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * don't have any good way to talk about ordering otherwise 171defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */ 172defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 173defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic int legacy_probe_add(unsigned long port, unsigned int irq, 174defc9cd826e4a99f550504a744f9407b518828aeAlan Cox enum controller type, unsigned long private) 175defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 176defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct legacy_probe *lp = &probe_list[0]; 177defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int i; 178defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct legacy_probe *free = NULL; 179defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 180defc9cd826e4a99f550504a744f9407b518828aeAlan Cox for (i = 0; i < NR_HOST; i++) { 181defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (lp->port == 0 && free == NULL) 182defc9cd826e4a99f550504a744f9407b518828aeAlan Cox free = lp; 183defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Matching port, or the correct slot for ordering */ 184defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (lp->port == port || legacy_port[i] == port) { 185defc9cd826e4a99f550504a744f9407b518828aeAlan Cox free = lp; 186defc9cd826e4a99f550504a744f9407b518828aeAlan Cox break; 187defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 188defc9cd826e4a99f550504a744f9407b518828aeAlan Cox lp++; 189defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 190defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (free == NULL) { 191defc9cd826e4a99f550504a744f9407b518828aeAlan Cox printk(KERN_ERR "pata_legacy: Too many interfaces.\n"); 192defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return -1; 193defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 194defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Fill in the entry for later probing */ 195defc9cd826e4a99f550504a744f9407b518828aeAlan Cox free->port = port; 196defc9cd826e4a99f550504a744f9407b518828aeAlan Cox free->irq = irq; 197defc9cd826e4a99f550504a744f9407b518828aeAlan Cox free->type = type; 198defc9cd826e4a99f550504a744f9407b518828aeAlan Cox free->private = private; 199defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return 0; 200defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 201defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 202defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 203defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/** 204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * legacy_set_mode - mode setting 2050260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo * @link: IDE link 206b229a7b0aed808f2ef6a5e9dbf78b0f17cefb4d0Alan Cox * @unused: Device that failed when error is returned 207669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 208669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Use a non standard set_mode function. We don't want to be tuned. 209669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 210669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * The BIOS configured everything. Our job is not to fiddle. Just use 211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * whatever PIO the hardware is using and leave it at that. When we 212669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * get some kind of nice user driven API for control then we can 213669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * expand on this as per hdparm in the base kernel. 214669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 215669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 2160260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heostatic int legacy_set_mode(struct ata_link *link, struct ata_device **unused) 217669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 218f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo struct ata_device *dev; 219669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 2201eca4365be25c540650693e941bc06a66cf38f94Tejun Heo ata_for_each_dev(dev, link, ENABLED) { 221a9a79dfec239568bdbf778242f8fcd10bcc5b9e2Joe Perches ata_dev_info(dev, "configured for PIO\n"); 2221eca4365be25c540650693e941bc06a66cf38f94Tejun Heo dev->pio_mode = XFER_PIO_0; 2231eca4365be25c540650693e941bc06a66cf38f94Tejun Heo dev->xfer_mode = XFER_PIO_0; 2241eca4365be25c540650693e941bc06a66cf38f94Tejun Heo dev->xfer_shift = ATA_SHIFT_PIO; 2251eca4365be25c540650693e941bc06a66cf38f94Tejun Heo dev->flags |= ATA_DFLAG_PIO; 226669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 227b229a7b0aed808f2ef6a5e9dbf78b0f17cefb4d0Alan Cox return 0; 228669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 229669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 230669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct scsi_host_template legacy_sht = { 23168d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo ATA_PIO_SHT(DRV_NAME), 232669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 233669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 234029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heostatic const struct ata_port_operations legacy_base_port_ops = { 235029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &ata_sff_port_ops, 236029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .cable_detect = ata_cable_40wire, 237029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo}; 238029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo 239669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 240669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * These ops are used if the user indicates the hardware 241669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * snoops the commands to decide on the mode and handles the 242669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * mode selection "magically" itself. Several legacy controllers 243669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * do this. The mode range can be set if it is not 0x1F by setting 244669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * pio_mask as well. 245669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 246669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 247669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations simple_port_ops = { 248029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 2495682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = ata_sff_data_xfer_noirq, 250669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 251669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations legacy_port_ops = { 253029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 2545682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = ata_sff_data_xfer_noirq, 255029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .set_mode = legacy_set_mode, 256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 257669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 258669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Promise 20230C and 20620 support 260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 261defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * This controller supports PIO0 to PIO2. We set PIO timings 262defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * conservatively to allow for 50MHz Vesa Local Bus. The 20620 DMA 263defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * support is weird being DMA to controller and PIO'd to the host 264defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * and not supported. 265669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) 268669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int tries = 5; 270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int pio = adev->pio_mode - XFER_PIO_0; 271669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 rt; 272669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik unsigned long flags; 27385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik 274669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Safe as UP only. Force I/Os to occur together */ 27585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik 276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_save(flags); 27785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik 278669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Unlock the control interface */ 279defc9cd826e4a99f550504a744f9407b518828aeAlan Cox do { 280669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F5); 281669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(inb(0x1F2) | 0x80, 0x1F2); 282669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 283669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3F6); 284669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3F6); 285669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 286669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 287669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 288defc9cd826e4a99f550504a744f9407b518828aeAlan Cox while ((inb(0x1F2) & 0x80) && --tries); 289669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 290669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_restore(flags); 29185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik 292669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(inb(0x1F4) & 0x07, 0x1F4); 293669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 294669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rt = inb(0x1F3); 295669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rt &= 0x07 << (3 * adev->devno); 296669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (pio) 297669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rt |= (1 + 3 * pio) << (3 * adev->devno); 298669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 299669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik udelay(100); 300669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(inb(0x1F2) | 0x01, 0x1F2); 301669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik udelay(100); 302669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F5); 303669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 304669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 305669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 30655dba3120fbcbea6800f9a18503d25f73212a347Tejun Heostatic unsigned int pdc_data_xfer_vlb(struct ata_device *dev, 307defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned char *buf, unsigned int buflen, int rw) 308669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 309c55af1f5abf606118b32e3ce9c3b1bbce5236e7eAlan Cox int slop = buflen & 3; 31016e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu struct ata_port *ap = dev->link->ap; 31116e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu 312c55af1f5abf606118b32e3ce9c3b1bbce5236e7eAlan Cox /* 32bit I/O capable *and* we need to write a whole number of dwords */ 313e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3) 314e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox && (ap->pflags & ATA_PFLAG_PIO32)) { 31555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo unsigned long flags; 31655dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo 317669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_save(flags); 318669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 319669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Perform the 32bit I/O synchronization sequence */ 3200d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread8(ap->ioaddr.nsect_addr); 3210d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread8(ap->ioaddr.nsect_addr); 3220d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread8(ap->ioaddr.nsect_addr); 323669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 324669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Now the data */ 32555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo if (rw == READ) 3260d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); 32755dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo else 32855dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); 329669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (unlikely(slop)) { 3316ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison __le32 pad; 33255dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo if (rw == READ) { 333b50e56d81e0df964e9b28001d792021b109cf4f1Al Viro pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); 334669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik memcpy(buf + buflen - slop, &pad, slop); 33555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo } else { 33655dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo memcpy(&pad, buf + buflen - slop, slop); 33755dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); 338669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 33955dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo buflen += 4 - slop; 340669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 341669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_restore(flags); 34255dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo } else 3439363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo buflen = ata_sff_data_xfer_noirq(dev, buf, buflen, rw); 34455dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo 34555dba3120fbcbea6800f9a18503d25f73212a347Tejun Heo return buflen; 346669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 347669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 348669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations pdc20230_port_ops = { 349029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 350669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik .set_piomode = pdc20230_set_piomode, 3515682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = pdc_data_xfer_vlb, 352669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 353669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 354669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 355669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Holtek 6560A support 356669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 357defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * This controller supports PIO0 to PIO2 (no IORDY even though higher 358defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * timings can be loaded). 359669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 360669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 361669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev) 362669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 363669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 active, recover; 364669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_timing t; 365669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 366669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Get the timing data in cycles. For now play safe at 50Mhz */ 367669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); 368669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 36907633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = clamp_val(t.active, 2, 15); 37007633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison recover = clamp_val(t.recover, 4, 15); 371669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 372669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 373669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 374669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 375669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 376669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 3770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(recover << 4 | active, ap->ioaddr.device_addr); 3780d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread8(ap->ioaddr.status_addr); 379669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 380669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 381669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations ht6560a_port_ops = { 382029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 383669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik .set_piomode = ht6560a_set_piomode, 384669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 385669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 386669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 387669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Holtek 6560B support 388669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 389defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO 390defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * setting unless we see an ATAPI device in which case we force it off. 391669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 392669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * FIXME: need to implement 2nd channel support. 393669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 394669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 395669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev) 396669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 397669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 active, recover; 398669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_timing t; 399669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 400669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Get the timing data in cycles. For now play safe at 50Mhz */ 401669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); 402669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 40307633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = clamp_val(t.active, 2, 15); 4049716387311c790de381214c03e7f1b72b91a8189Sergei Shtylyov recover = clamp_val(t.recover, 2, 16) & 0x0F; 405669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 406669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 407669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 408669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 409669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3E6); 410669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 4110d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(recover << 4 | active, ap->ioaddr.device_addr); 412669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 413669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (adev->class != ATA_DEV_ATA) { 414669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 rconf = inb(0x3E6); 415669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (rconf & 0x24) { 416defc9cd826e4a99f550504a744f9407b518828aeAlan Cox rconf &= ~0x24; 417669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(rconf, 0x3E6); 418669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 419669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 4200d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread8(ap->ioaddr.status_addr); 421669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 422669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 423669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations ht6560b_port_ops = { 424029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 425669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik .set_piomode = ht6560b_set_piomode, 426669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 427669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 428669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 429669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Opti core chipset helpers 430669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 43185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik 432669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/** 433669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * opti_syscfg - read OPTI chipset configuration 434669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * @reg: Configuration register to read 435669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 436669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Returns the value of an OPTI system board configuration register. 437669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 438669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 439669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic u8 opti_syscfg(u8 reg) 440669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 441669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik unsigned long flags; 442669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 r; 44385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik 444669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Uniprocessor chipset and must force cycles adjancent */ 445669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_save(flags); 446669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(reg, 0x22); 447669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik r = inb(0x24); 448669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_restore(flags); 449669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return r; 450669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 451669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 452669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 453669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Opti 82C611A 454669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 455669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This controller supports PIO0 to PIO3. 456669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 457669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 458defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic void opti82c611a_set_piomode(struct ata_port *ap, 459defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_device *adev) 460669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 461669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 active, recover, setup; 462669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_timing t; 463669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_device *pair = ata_dev_pair(adev); 464669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int clock; 465669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int khz[4] = { 50000, 40000, 33000, 25000 }; 466669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 rc; 467669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 468669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Enter configuration mode */ 4690d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread16(ap->ioaddr.error_addr); 4700d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread16(ap->ioaddr.error_addr); 4710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(3, ap->ioaddr.nsect_addr); 472669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 473669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Read VLB clock strapping */ 4740d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo clock = 1000000000 / khz[ioread8(ap->ioaddr.lbah_addr) & 0x03]; 475669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 476669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Get the timing data in cycles */ 477669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000); 478669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 479669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Setup timing is shared */ 480669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (pair) { 481669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_timing tp; 482669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000); 483669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 484669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); 485669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 486669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 48707633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = clamp_val(t.active, 2, 17) - 2; 48807633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison recover = clamp_val(t.recover, 1, 16) - 1; 48907633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison setup = clamp_val(t.setup, 1, 4) - 1; 490669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 491669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Select the right timing bank for write timing */ 4920d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = ioread8(ap->ioaddr.lbal_addr); 493669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc &= 0x7F; 494669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= (adev->devno << 7); 4950d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(rc, ap->ioaddr.lbal_addr); 496669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 497669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Write the timings */ 4980d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(active << 4 | recover, ap->ioaddr.error_addr); 499669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 500669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Select the right bank for read timings, also 501669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik load the shared timings for address */ 5020d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = ioread8(ap->ioaddr.device_addr); 503669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc &= 0xC0; 504669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= adev->devno; /* Index select */ 505669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= (setup << 4) | 0x04; 5060d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(rc, ap->ioaddr.device_addr); 507669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 508669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Load the read timings */ 5090d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(active << 4 | recover, ap->ioaddr.data_addr); 510669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 511669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Ensure the timing register mode is right */ 5120d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = ioread8(ap->ioaddr.lbal_addr); 513669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc &= 0x73; 514669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= 0x84; 5150d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(rc, ap->ioaddr.lbal_addr); 516669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 517669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Exit command mode */ 5180d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(0x83, ap->ioaddr.nsect_addr); 519669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 520669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 521669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 522669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations opti82c611a_port_ops = { 523029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 524669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik .set_piomode = opti82c611a_set_piomode, 525669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 526669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 527669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* 528669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Opti 82C465MV 529669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 530669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This controller supports PIO0 to PIO3. Unlike the 611A the MVB 531669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * version is dual channel but doesn't have a lot of unique registers. 532669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 533669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 534669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev) 535669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 536669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 active, recover, setup; 537669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_timing t; 538669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_device *pair = ata_dev_pair(adev); 539669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int clock; 540669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int khz[4] = { 50000, 40000, 33000, 25000 }; 541669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 rc; 542669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u8 sysclk; 543669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 544669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Get the clock */ 545669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik sysclk = opti_syscfg(0xAC) & 0xC0; /* BIOS set */ 546669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 547669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Enter configuration mode */ 5480d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread16(ap->ioaddr.error_addr); 5490d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo ioread16(ap->ioaddr.error_addr); 5500d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(3, ap->ioaddr.nsect_addr); 551669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 552669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Read VLB clock strapping */ 553669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik clock = 1000000000 / khz[sysclk]; 554669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 555669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Get the timing data in cycles */ 556669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000); 557669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 558669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Setup timing is shared */ 559669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (pair) { 560669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_timing tp; 561669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000); 562669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 563669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); 564669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 565669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 56607633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = clamp_val(t.active, 2, 17) - 2; 56707633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison recover = clamp_val(t.recover, 1, 16) - 1; 56807633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison setup = clamp_val(t.setup, 1, 4) - 1; 569669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 570669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Select the right timing bank for write timing */ 5710d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = ioread8(ap->ioaddr.lbal_addr); 572669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc &= 0x7F; 573669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= (adev->devno << 7); 5740d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(rc, ap->ioaddr.lbal_addr); 575669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 576669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Write the timings */ 5770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(active << 4 | recover, ap->ioaddr.error_addr); 578669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 579669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Select the right bank for read timings, also 580669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik load the shared timings for address */ 5810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = ioread8(ap->ioaddr.device_addr); 582669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc &= 0xC0; 583669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= adev->devno; /* Index select */ 584669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= (setup << 4) | 0x04; 5850d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(rc, ap->ioaddr.device_addr); 586669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 587669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Load the read timings */ 5880d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(active << 4 | recover, ap->ioaddr.data_addr); 589669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 590669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Ensure the timing register mode is right */ 5910d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = ioread8(ap->ioaddr.lbal_addr); 592669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc &= 0x73; 593669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik rc |= 0x84; 5940d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(rc, ap->ioaddr.lbal_addr); 595669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 596669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Exit command mode */ 5970d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo iowrite8(0x83, ap->ioaddr.nsect_addr); 598669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 599669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* We need to know this for quad device on the MVB */ 600669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ap->host->private_data = ap; 601669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 602669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 603669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/** 6049363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo * opt82c465mv_qc_issue - command issue 605669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * @qc: command pending 606669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 607669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Called when the libata layer is about to issue a command. We wrap 608669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * this interface so that we can load the correct ATA timings. The 609669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * MVB has a single set of timing registers and these are shared 610669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * across channels. As there are two registers we really ought to 611669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * track the last two used values as a sort of register window. For 612669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * now we just reload on a channel switch. On the single channel 613669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * setup this condition never fires so we do nothing extra. 614669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 615669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * FIXME: dual channel needs ->serialize support 616669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 617669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 6189363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heostatic unsigned int opti82c46x_qc_issue(struct ata_queued_cmd *qc) 619669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 620669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_port *ap = qc->ap; 621669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct ata_device *adev = qc->dev; 622669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 623669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* If timings are set and for the wrong channel (2nd test is 624669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik due to a libata shortcoming and will eventually go I hope) */ 625669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (ap->host->private_data != ap->host 626669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik && ap->host->private_data != NULL) 627669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik opti82c46x_set_piomode(ap, adev); 628669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 6299363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo return ata_sff_qc_issue(qc); 630669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 631669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 632669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations opti82c46x_port_ops = { 633029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 634669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik .set_piomode = opti82c46x_set_piomode, 6359363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo .qc_issue = opti82c46x_qc_issue, 636669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}; 637669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 638669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/** 6398c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz * qdi65x0_set_piomode - PIO setup for QDI65x0 640defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @ap: Port 641defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @adev: Device 642669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 6438c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz * In single channel mode the 6580 has one clock per device and we can 6448c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz * avoid the requirement to clock switch. We also have to load the timing 6458c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz * into the right clock according to whether we are master or slave. 6468c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz * 647defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * In dual channel mode the 6580 has one clock per channel and we have 6489363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo * to software clockswitch in qc_issue. 649669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 650669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 6518c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewiczstatic void qdi65x0_set_piomode(struct ata_port *ap, struct ata_device *adev) 652669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 653defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_timing t; 654cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison struct legacy_data *ld_qdi = ap->host->private_data; 655defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int active, recovery; 656defc9cd826e4a99f550504a744f9407b518828aeAlan Cox u8 timing; 657669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 658defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Get the timing data in cycles */ 659defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); 660defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 661cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison if (ld_qdi->fast) { 66207633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = 8 - clamp_val(t.active, 1, 8); 66307633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison recovery = 18 - clamp_val(t.recover, 3, 18); 664defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } else { 66507633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = 9 - clamp_val(t.active, 2, 9); 66607633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison recovery = 15 - clamp_val(t.recover, 0, 15); 667defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 668defc9cd826e4a99f550504a744f9407b518828aeAlan Cox timing = (recovery << 4) | active | 0x08; 669cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison ld_qdi->clock[adev->devno] = timing; 670669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 6718c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz if (ld_qdi->type == QDI6580) 6728c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz outb(timing, ld_qdi->timing + 2 * adev->devno); 6738c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz else 6748c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz outb(timing, ld_qdi->timing + 2 * ap->port_no); 675defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 676defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Clear the FIFO */ 6778c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz if (ld_qdi->type != QDI6500 && adev->class != ATA_DEV_ATA) 6786809e7301fba4f9fa446ead5167faed115690fc4Bartlomiej Zolnierkiewicz outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3); 679defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 680defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 681defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/** 6829363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo * qdi_qc_issue - command issue 683defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @qc: command pending 684defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * 685defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * Called when the libata layer is about to issue a command. We wrap 686defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * this interface so that we can load the correct ATA timings. 687defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */ 688defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 6899363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heostatic unsigned int qdi_qc_issue(struct ata_queued_cmd *qc) 690defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 691defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_port *ap = qc->ap; 692defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_device *adev = qc->dev; 693cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison struct legacy_data *ld_qdi = ap->host->private_data; 694defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 695cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison if (ld_qdi->clock[adev->devno] != ld_qdi->last) { 696defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (adev->pio_mode) { 697cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison ld_qdi->last = ld_qdi->clock[adev->devno]; 698cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison outb(ld_qdi->clock[adev->devno], ld_qdi->timing + 699defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 2 * ap->port_no); 700defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 701669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 7029363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo return ata_sff_qc_issue(qc); 703defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 704669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 705b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf, 706defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned int buflen, int rw) 707defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 708defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_port *ap = adev->link->ap; 709defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int slop = buflen & 3; 710669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 711e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3) 712e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox && (ap->pflags & ATA_PFLAG_PIO32)) { 713defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (rw == WRITE) 714defc9cd826e4a99f550504a744f9407b518828aeAlan Cox iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); 715defc9cd826e4a99f550504a744f9407b518828aeAlan Cox else 716defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); 717669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 718defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (unlikely(slop)) { 7196ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison __le32 pad; 720defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (rw == WRITE) { 721defc9cd826e4a99f550504a744f9407b518828aeAlan Cox memcpy(&pad, buf + buflen - slop, slop); 7226ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); 723defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } else { 7246ad67403da47e833d9e418caf7f28295c9472e11Harvey Harrison pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); 725defc9cd826e4a99f550504a744f9407b518828aeAlan Cox memcpy(buf + buflen - slop, &pad, slop); 726defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 727defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 728defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return (buflen + 3) & ~3; 729defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } else 7309363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo return ata_sff_data_xfer(adev, buf, buflen, rw); 731defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 732defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 733b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic int qdi_port(struct platform_device *dev, 734b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox struct legacy_probe *lp, struct legacy_data *ld) 735b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{ 736b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (devm_request_region(&dev->dev, lp->private, 4, "qdi") == NULL) 737b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox return -EBUSY; 738b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox ld->timing = lp->private; 739b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox return 0; 740b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox} 741b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 742defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct ata_port_operations qdi6500_port_ops = { 743029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 7448c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz .set_piomode = qdi65x0_set_piomode, 7459363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo .qc_issue = qdi_qc_issue, 7465682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = vlb32_data_xfer, 747defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 748defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 749defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct ata_port_operations qdi6580_port_ops = { 750029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 7518c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz .set_piomode = qdi65x0_set_piomode, 7525682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = vlb32_data_xfer, 753defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 754defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 755defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct ata_port_operations qdi6580dp_port_ops = { 756029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 7578c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz .set_piomode = qdi65x0_set_piomode, 75843c7d17ee7e03433c57dc4ce457d34110108455aBartlomiej Zolnierkiewicz .qc_issue = qdi_qc_issue, 7595682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = vlb32_data_xfer, 760defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 761defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 762b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic DEFINE_SPINLOCK(winbond_lock); 763b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 764b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic void winbond_writecfg(unsigned long port, u8 reg, u8 val) 765b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{ 766b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox unsigned long flags; 767b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox spin_lock_irqsave(&winbond_lock, flags); 768b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox outb(reg, port + 0x01); 769b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox outb(val, port + 0x02); 770b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox spin_unlock_irqrestore(&winbond_lock, flags); 771b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox} 772b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 773b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic u8 winbond_readcfg(unsigned long port, u8 reg) 774b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{ 775b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox u8 val; 776b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 777b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox unsigned long flags; 778b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox spin_lock_irqsave(&winbond_lock, flags); 779b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox outb(reg, port + 0x01); 780b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox val = inb(port + 0x02); 781b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox spin_unlock_irqrestore(&winbond_lock, flags); 782b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 783b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox return val; 784b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox} 785b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 786b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) 787b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{ 788b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox struct ata_timing t; 789cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison struct legacy_data *ld_winbond = ap->host->private_data; 790b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox int active, recovery; 791b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox u8 reg; 792b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2); 793b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 794cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison reg = winbond_readcfg(ld_winbond->timing, 0x81); 795b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 796b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox /* Get the timing data in cycles */ 797b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (reg & 0x40) /* Fast VLB bus, assume 50MHz */ 798b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); 799b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox else 800b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); 801b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 80207633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison active = (clamp_val(t.active, 3, 17) - 1) & 0x0F; 80307633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison recovery = (clamp_val(t.recover, 1, 15) + 1) & 0x0F; 804b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox timing = (active << 4) | recovery; 805cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison winbond_writecfg(ld_winbond->timing, timing, reg); 806b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 807b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox /* Load the setup timing */ 808b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 809b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg = 0x35; 810b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (adev->class != ATA_DEV_ATA) 811b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg |= 0x08; /* FIFO off */ 812b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (!ata_pio_need_iordy(adev)) 813b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg |= 0x02; /* IORDY off */ 81407633b5d0723ce2ec31262e1096dcf61311bf078Harvey Harrison reg |= (clamp_val(t.setup, 0, 3) << 6); 815cb616dd5bb6ddadf3e0607696b18055065ce4c3dHarvey Harrison winbond_writecfg(ld_winbond->timing, timing + 1, reg); 816b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox} 817b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 818b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic int winbond_port(struct platform_device *dev, 819b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox struct legacy_probe *lp, struct legacy_data *ld) 820b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox{ 821b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (devm_request_region(&dev->dev, lp->private, 4, "winbond") == NULL) 822b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox return -EBUSY; 823b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox ld->timing = lp->private; 824b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox return 0; 825b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox} 826b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 827b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic struct ata_port_operations winbond_port_ops = { 828029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &legacy_base_port_ops, 829b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox .set_piomode = winbond_set_piomode, 8305682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo .sff_data_xfer = vlb32_data_xfer, 831b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox}; 832b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 833defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic struct legacy_controller controllers[] = { 834b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"BIOS", &legacy_port_ops, ATA_PIO4, 835e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox ATA_FLAG_NO_IORDY, 0, NULL }, 836b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"Snooping", &simple_port_ops, ATA_PIO4, 837e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox 0, 0, NULL }, 838b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"PDC20230", &pdc20230_port_ops, ATA_PIO2, 839e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox ATA_FLAG_NO_IORDY, 84016e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, NULL }, 841b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"HT6560A", &ht6560a_port_ops, ATA_PIO2, 842e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox ATA_FLAG_NO_IORDY, 0, NULL }, 843b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"HT6560B", &ht6560b_port_ops, ATA_PIO4, 844e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox ATA_FLAG_NO_IORDY, 0, NULL }, 845b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"OPTI82C611A", &opti82c611a_port_ops, ATA_PIO3, 846e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox 0, 0, NULL }, 847b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"OPTI82C46X", &opti82c46x_port_ops, ATA_PIO3, 848e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox 0, 0, NULL }, 849b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"QDI6500", &qdi6500_port_ops, ATA_PIO2, 850e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox ATA_FLAG_NO_IORDY, 85116e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port }, 852b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"QDI6580", &qdi6580_port_ops, ATA_PIO4, 85316e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port }, 854b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"QDI6580DP", &qdi6580dp_port_ops, ATA_PIO4, 85516e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port }, 856b2f104bba39e16f48b7e0ac6447cc167c54505b8Bartlomiej Zolnierkiewicz {"W83759A", &winbond_port_ops, ATA_PIO4, 85716e6aeca9e86fb0effb847c1687c9b2cc8e3fb4cZhenwen Xu 0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, 858e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox winbond_port } 859defc9cd826e4a99f550504a744f9407b518828aeAlan Cox}; 860defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 861defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/** 862defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * probe_chip_type - Discover controller 863defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @probe: Probe entry to check 864defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * 865defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * Probe an ATA port and identify the type of controller. We don't 866defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * check if the controller appears to be driveless at this point. 867defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */ 868defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 869b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic __init int probe_chip_type(struct legacy_probe *probe) 870defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 871defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int mask = 1 << probe->slot; 872defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 873b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (winbond && (probe->port == 0x1F0 || probe->port == 0x170)) { 874b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox u8 reg = winbond_readcfg(winbond, 0x81); 875b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg |= 0x80; /* jumpered mode off */ 876b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox winbond_writecfg(winbond, 0x81, reg); 877b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg = winbond_readcfg(winbond, 0x83); 878b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg |= 0xF0; /* local control */ 879b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox winbond_writecfg(winbond, 0x83, reg); 880b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg = winbond_readcfg(winbond, 0x85); 881b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg |= 0xF0; /* programmable timing */ 882b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox winbond_writecfg(winbond, 0x85, reg); 883b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 884b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox reg = winbond_readcfg(winbond, 0x81); 885b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 886b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (reg & mask) 887b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox return W83759A; 888b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox } 889defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (probe->port == 0x1F0) { 890defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned long flags; 891defc9cd826e4a99f550504a744f9407b518828aeAlan Cox local_irq_save(flags); 892669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Probes */ 893669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(inb(0x1F2) | 0x80, 0x1F2); 894defc9cd826e4a99f550504a744f9407b518828aeAlan Cox inb(0x1F5); 895669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 896669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3F6); 897669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x3F6); 898669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 899669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 900669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 901669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if ((inb(0x1F2) & 0x80) == 0) { 902669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* PDC20230c or 20630 ? */ 903defc9cd826e4a99f550504a744f9407b518828aeAlan Cox printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller" 904defc9cd826e4a99f550504a744f9407b518828aeAlan Cox " detected.\n"); 905669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik udelay(100); 906669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F5); 907defc9cd826e4a99f550504a744f9407b518828aeAlan Cox local_irq_restore(flags); 908defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return PDC20230; 909669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } else { 910669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik outb(0x55, 0x1F2); 911669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 912669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik inb(0x1F2); 913defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (inb(0x1F2) == 0x00) 914defc9cd826e4a99f550504a744f9407b518828aeAlan Cox printk(KERN_INFO "PDC20230-B VLB ATA " 915defc9cd826e4a99f550504a744f9407b518828aeAlan Cox "controller detected.\n"); 916defc9cd826e4a99f550504a744f9407b518828aeAlan Cox local_irq_restore(flags); 917defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return BIOS; 918669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 919669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik local_irq_restore(flags); 920669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 921669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 922defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (ht6560a & mask) 923defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return HT6560A; 924defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (ht6560b & mask) 925defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return HT6560B; 926defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (opti82c611a & mask) 927defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return OPTI611A; 928defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (opti82c46x & mask) 929defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return OPTI46X; 930defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (autospeed & mask) 931defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return SNOOP; 932defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return BIOS; 933defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 934defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 935defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 936defc9cd826e4a99f550504a744f9407b518828aeAlan Cox/** 937defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * legacy_init_one - attach a legacy interface 938defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * @pl: probe record 939defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * 940defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * Register an ISA bus IDE interface. Such interfaces are PIO and we 941defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * assume do not support IRQ sharing. 942defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */ 943defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 944defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init int legacy_init_one(struct legacy_probe *probe) 945defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 946defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct legacy_controller *controller = &controllers[probe->type]; 947defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int pio_modes = controller->pio_mask; 948defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned long io = probe->port; 949defc9cd826e4a99f550504a744f9407b518828aeAlan Cox u32 mask = (1 << probe->slot); 950defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_port_operations *ops = controller->ops; 951defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct legacy_data *ld = &legacy_data[probe->slot]; 952defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_host *host = NULL; 953defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_port *ap; 954defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct platform_device *pdev; 955defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct ata_device *dev; 956defc9cd826e4a99f550504a744f9407b518828aeAlan Cox void __iomem *io_addr, *ctrl_addr; 957defc9cd826e4a99f550504a744f9407b518828aeAlan Cox u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY; 958defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int ret; 959defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 960defc9cd826e4a99f550504a744f9407b518828aeAlan Cox iordy |= controller->flags; 961defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 962defc9cd826e4a99f550504a744f9407b518828aeAlan Cox pdev = platform_device_register_simple(DRV_NAME, probe->slot, NULL, 0); 963defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (IS_ERR(pdev)) 964defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return PTR_ERR(pdev); 965669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 966defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ret = -EBUSY; 967defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL || 968defc9cd826e4a99f550504a744f9407b518828aeAlan Cox devm_request_region(&pdev->dev, io + 0x0206, 1, 969defc9cd826e4a99f550504a744f9407b518828aeAlan Cox "pata_legacy") == NULL) 970defc9cd826e4a99f550504a744f9407b518828aeAlan Cox goto fail; 971f834e49f1a09414e9618ff0c9cd83c2114032bb6Alan Cox 9725d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ret = -ENOMEM; 973defc9cd826e4a99f550504a744f9407b518828aeAlan Cox io_addr = devm_ioport_map(&pdev->dev, io, 8); 974defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1); 975defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (!io_addr || !ctrl_addr) 976defc9cd826e4a99f550504a744f9407b518828aeAlan Cox goto fail; 9778c7e8f947f8068b01f798def52318f97e1338ee1Bartlomiej Zolnierkiewicz ld->type = probe->type; 978defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (controller->setup) 979b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (controller->setup(pdev, probe, ld) < 0) 980defc9cd826e4a99f550504a744f9407b518828aeAlan Cox goto fail; 9815d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo host = ata_host_alloc(&pdev->dev, 1); 9825d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo if (!host) 9835d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo goto fail; 9845d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap = host->ports[0]; 9855d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo 9865d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap->ops = ops; 9875d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap->pio_mask = pio_modes; 9885d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap->flags |= ATA_FLAG_SLAVE_POSS | iordy; 989e3cf95dd6d352954b663d2934110d6e30af2406dAlan Cox ap->pflags |= controller->pflags; 9905d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap->ioaddr.cmd_addr = io_addr; 9915d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap->ioaddr.altstatus_addr = ctrl_addr; 9925d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo ap->ioaddr.ctl_addr = ctrl_addr; 9939363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_std_ports(&ap->ioaddr); 994b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox ap->host->private_data = ld; 9955d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo 996defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206); 997cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 9989363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ret = ata_host_activate(host, probe->irq, ata_sff_interrupt, 0, 9999363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo &legacy_sht); 10005d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo if (ret) 1001669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik goto fail; 100245bc955bb1324a46c9539550cc615994e6d0a43dJames Bottomley async_synchronize_full(); 1003669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ld->platform_dev = pdev; 1004669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1005defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Nothing found means we drop the port as its probably not there */ 1006defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1007defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ret = -ENODEV; 10081eca4365be25c540650693e941bc06a66cf38f94Tejun Heo ata_for_each_dev(dev, &ap->link, ALL) { 1009defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (!ata_dev_absent(dev)) { 1010defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_host[probe->slot] = host; 1011defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ld->platform_dev = pdev; 1012defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return 0; 1013defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1014defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 101520cbf5f8c0fe3df2ddbde1f334993b4dda18a651Tejun Heo ata_host_detach(host); 1016669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikfail: 1017669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik platform_device_unregister(pdev); 1018669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return ret; 1019669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 1020669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1021669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/** 1022669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * legacy_check_special_cases - ATA special cases 1023669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * @p: PCI device to check 1024669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * @master: set this if we find an ATA master 1025669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * @master: set this if we find an ATA secondary 1026669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 1027defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * A small number of vendors implemented early PCI ATA interfaces 1028defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * on bridge logic without the ATA interface being PCI visible. 1029defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * Where we have a matching PCI driver we must skip the relevant 1030defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * device here. If we don't know about it then the legacy driver 1031defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * is the right driver anyway. 1032669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 1033669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1034b832548773b0cd98216534caa31b9ed7607c4e76Alan Coxstatic void __init legacy_check_special_cases(struct pci_dev *p, int *primary, 1035defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int *secondary) 1036669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 1037669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */ 1038669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (p->vendor == 0x1078 && p->device == 0x0000) { 1039669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *primary = *secondary = 1; 1040669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return; 1041669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1042669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Cyrix CS5520 pre SFF MWDMA ATA on the bridge */ 1043669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (p->vendor == 0x1078 && p->device == 0x0002) { 1044669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *primary = *secondary = 1; 1045669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return; 1046669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1047669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Intel MPIIX - PIO ATA on non PCI side of bridge */ 1048669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (p->vendor == 0x8086 && p->device == 0x1234) { 1049669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik u16 r; 1050669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik pci_read_config_word(p, 0x6C, &r); 1051defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (r & 0x8000) { 1052defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* ATA port enabled */ 1053669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (r & 0x4000) 1054669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *secondary = 1; 1055669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik else 1056669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *primary = 1; 1057669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1058669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return; 1059669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1060669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 1061669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1062defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init void probe_opti_vlb(void) 1063defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 1064defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* If an OPTI 82C46X is present find out where the channels are */ 1065defc9cd826e4a99f550504a744f9407b518828aeAlan Cox static const char *optis[4] = { 1066defc9cd826e4a99f550504a744f9407b518828aeAlan Cox "3/463MV", "5MV", 1067defc9cd826e4a99f550504a744f9407b518828aeAlan Cox "5MVA", "5MVB" 1068defc9cd826e4a99f550504a744f9407b518828aeAlan Cox }; 1069defc9cd826e4a99f550504a744f9407b518828aeAlan Cox u8 chans = 1; 1070defc9cd826e4a99f550504a744f9407b518828aeAlan Cox u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6; 1071defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1072defc9cd826e4a99f550504a744f9407b518828aeAlan Cox opti82c46x = 3; /* Assume master and slave first */ 1073defc9cd826e4a99f550504a744f9407b518828aeAlan Cox printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", 1074defc9cd826e4a99f550504a744f9407b518828aeAlan Cox optis[ctrl]); 1075defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (ctrl == 3) 1076defc9cd826e4a99f550504a744f9407b518828aeAlan Cox chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1; 1077defc9cd826e4a99f550504a744f9407b518828aeAlan Cox ctrl = opti_syscfg(0xAC); 1078defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Check enabled and this port is the 465MV port. On the 1079defc9cd826e4a99f550504a744f9407b518828aeAlan Cox MVB we may have two channels */ 1080defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (ctrl & 8) { 1081defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (chans == 2) { 1082defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1F0, 14, OPTI46X, 0); 1083defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x170, 15, OPTI46X, 0); 1084defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1085defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (ctrl & 4) 1086defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x170, 15, OPTI46X, 0); 1087defc9cd826e4a99f550504a744f9407b518828aeAlan Cox else 1088defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1F0, 14, OPTI46X, 0); 1089defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } else 1090defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1F0, 14, OPTI46X, 0); 1091defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 1092defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1093defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init void qdi65_identify_port(u8 r, u8 res, unsigned long port) 1094defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 1095defc9cd826e4a99f550504a744f9407b518828aeAlan Cox static const unsigned long ide_port[2] = { 0x170, 0x1F0 }; 1096defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Check card type */ 1097defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if ((r & 0xF0) == 0xC0) { 1098defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* QD6500: single channel */ 1099b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (r & 8) 1100defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Disabled ? */ 1101defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return; 1102defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01), 1103defc9cd826e4a99f550504a744f9407b518828aeAlan Cox QDI6500, port); 1104defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1105defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) { 1106defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* QD6580: dual channel */ 1107defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (!request_region(port + 2 , 2, "pata_qdi")) { 1108defc9cd826e4a99f550504a744f9407b518828aeAlan Cox release_region(port, 2); 1109defc9cd826e4a99f550504a744f9407b518828aeAlan Cox return; 1110defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1111defc9cd826e4a99f550504a744f9407b518828aeAlan Cox res = inb(port + 3); 1112defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Single channel mode ? */ 1113defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (res & 1) 1114defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01), 1115defc9cd826e4a99f550504a744f9407b518828aeAlan Cox QDI6580, port); 1116defc9cd826e4a99f550504a744f9407b518828aeAlan Cox else { /* Dual channel mode */ 1117defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1F0, 14, QDI6580DP, port); 1118defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* port + 0x02, r & 0x04 */ 1119defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x170, 15, QDI6580DP, port + 2); 1120defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1121b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox release_region(port + 2, 2); 1122defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1123defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 1124defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1125defc9cd826e4a99f550504a744f9407b518828aeAlan Coxstatic __init void probe_qdi_vlb(void) 1126defc9cd826e4a99f550504a744f9407b518828aeAlan Cox{ 1127defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned long flags; 1128defc9cd826e4a99f550504a744f9407b518828aeAlan Cox static const unsigned long qd_port[2] = { 0x30, 0xB0 }; 1129defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int i; 1130defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1131defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* 1132defc9cd826e4a99f550504a744f9407b518828aeAlan Cox * Check each possible QD65xx base address 1133defc9cd826e4a99f550504a744f9407b518828aeAlan Cox */ 1134defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1135defc9cd826e4a99f550504a744f9407b518828aeAlan Cox for (i = 0; i < 2; i++) { 1136defc9cd826e4a99f550504a744f9407b518828aeAlan Cox unsigned long port = qd_port[i]; 1137defc9cd826e4a99f550504a744f9407b518828aeAlan Cox u8 r, res; 1138defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1139defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1140defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (request_region(port, 2, "pata_qdi")) { 1141defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Check for a card */ 1142defc9cd826e4a99f550504a744f9407b518828aeAlan Cox local_irq_save(flags); 1143defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* I have no h/w that needs this delay but it 1144defc9cd826e4a99f550504a744f9407b518828aeAlan Cox is present in the historic code */ 1145defc9cd826e4a99f550504a744f9407b518828aeAlan Cox r = inb(port); 1146defc9cd826e4a99f550504a744f9407b518828aeAlan Cox udelay(1); 1147defc9cd826e4a99f550504a744f9407b518828aeAlan Cox outb(0x19, port); 1148defc9cd826e4a99f550504a744f9407b518828aeAlan Cox udelay(1); 1149defc9cd826e4a99f550504a744f9407b518828aeAlan Cox res = inb(port); 1150defc9cd826e4a99f550504a744f9407b518828aeAlan Cox udelay(1); 1151defc9cd826e4a99f550504a744f9407b518828aeAlan Cox outb(r, port); 1152defc9cd826e4a99f550504a744f9407b518828aeAlan Cox udelay(1); 1153defc9cd826e4a99f550504a744f9407b518828aeAlan Cox local_irq_restore(flags); 1154defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1155defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Fail */ 1156defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (res == 0x19) { 1157defc9cd826e4a99f550504a744f9407b518828aeAlan Cox release_region(port, 2); 1158defc9cd826e4a99f550504a744f9407b518828aeAlan Cox continue; 1159defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1160defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Passes the presence test */ 1161defc9cd826e4a99f550504a744f9407b518828aeAlan Cox r = inb(port + 1); 1162defc9cd826e4a99f550504a744f9407b518828aeAlan Cox udelay(1); 1163defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Check port agrees with port set */ 1164b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if ((r & 2) >> 1 == i) 1165b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox qdi65_identify_port(r, res, port); 1166b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox release_region(port, 2); 1167defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1168defc9cd826e4a99f550504a744f9407b518828aeAlan Cox } 1169defc9cd826e4a99f550504a744f9407b518828aeAlan Cox} 1170669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1171669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/** 1172669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * legacy_init - attach legacy interfaces 1173669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * 1174669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Attach legacy IDE interfaces by scanning the usual IRQ/port suspects. 1175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Right now we do not scan the ide0 and ide1 address but should do so 1176669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * for non PCI systems or systems with no PCI IDE legacy mode devices. 1177669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * If you fix that note there are special cases to consider like VLB 1178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * drivers and CS5510/20. 1179669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */ 1180669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1181669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic __init int legacy_init(void) 1182669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 1183669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int i; 1184669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int ct = 0; 1185669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int primary = 0; 1186669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int secondary = 0; 1187defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int pci_present = 0; 1188defc9cd826e4a99f550504a744f9407b518828aeAlan Cox struct legacy_probe *pl = &probe_list[0]; 1189defc9cd826e4a99f550504a744f9407b518828aeAlan Cox int slot = 0; 1190669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1191669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct pci_dev *p = NULL; 1192669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1193669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik for_each_pci_dev(p) { 1194669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int r; 1195defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* Check for any overlap of the system ATA mappings. Native 1196defc9cd826e4a99f550504a744f9407b518828aeAlan Cox mode controllers stuck on these addresses or some devices 1197defc9cd826e4a99f550504a744f9407b518828aeAlan Cox in 'raid' mode won't be found by the storage class test */ 1198669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik for (r = 0; r < 6; r++) { 1199669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (pci_resource_start(p, r) == 0x1f0) 1200669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik primary = 1; 1201669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (pci_resource_start(p, r) == 0x170) 1202669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik secondary = 1; 1203669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik /* Check for special cases */ 1205669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik legacy_check_special_cases(p, &primary, &secondary); 1206669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1207defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* If PCI bus is present then don't probe for tertiary 1208defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy ports */ 1209defc9cd826e4a99f550504a744f9407b518828aeAlan Cox pci_present = 1; 1210669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1212b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox if (winbond == 1) 1213b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox winbond = 0x130; /* Default port, alt is 1B0 */ 1214b832548773b0cd98216534caa31b9ed7607c4e76Alan Cox 1215defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (primary == 0 || all) 1216defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1F0, 14, UNKNOWN, 0); 1217defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (secondary == 0 || all) 1218defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x170, 15, UNKNOWN, 0); 1219defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1220defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (probe_all || !pci_present) { 1221defc9cd826e4a99f550504a744f9407b518828aeAlan Cox /* ISA/VLB extra ports */ 1222defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1E8, 11, UNKNOWN, 0); 1223defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x168, 10, UNKNOWN, 0); 1224defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x1E0, 8, UNKNOWN, 0); 1225defc9cd826e4a99f550504a744f9407b518828aeAlan Cox legacy_probe_add(0x160, 12, UNKNOWN, 0); 1226669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1227669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1228defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (opti82c46x) 1229defc9cd826e4a99f550504a744f9407b518828aeAlan Cox probe_opti_vlb(); 1230defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (qdi) 1231defc9cd826e4a99f550504a744f9407b518828aeAlan Cox probe_qdi_vlb(); 1232defc9cd826e4a99f550504a744f9407b518828aeAlan Cox 1233defc9cd826e4a99f550504a744f9407b518828aeAlan Cox for (i = 0; i < NR_HOST; i++, pl++) { 1234defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (pl->port == 0) 1235669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik continue; 1236defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (pl->type == UNKNOWN) 1237defc9cd826e4a99f550504a744f9407b518828aeAlan Cox pl->type = probe_chip_type(pl); 1238defc9cd826e4a99f550504a744f9407b518828aeAlan Cox pl->slot = slot++; 1239defc9cd826e4a99f550504a744f9407b518828aeAlan Cox if (legacy_init_one(pl) == 0) 1240669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik ct++; 1241669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1242669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik if (ct != 0) 1243669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return 0; 1244669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik return -ENODEV; 1245669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 1246669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1247669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic __exit void legacy_exit(void) 1248669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{ 1249669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik int i; 1250669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1251669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik for (i = 0; i < nr_legacy_host; i++) { 1252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik struct legacy_data *ld = &legacy_data[i]; 125324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo ata_host_detach(legacy_host[i]); 1254669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik platform_device_unregister(ld->platform_dev); 1255669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik } 1256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik} 1257669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1258669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox"); 1259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for legacy ATA"); 1260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL"); 1261669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION); 12620dcd0a76370a526d4bc844d82d54c717eb40e042Bartlomiej ZolnierkiewiczMODULE_ALIAS("pata_qdi"); 12636d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej ZolnierkiewiczMODULE_ALIAS("pata_winbond"); 1264669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1265669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(probe_all, int, 0); 1266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(autospeed, int, 0); 1267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(ht6560a, int, 0); 1268669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(ht6560b, int, 0); 1269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(opti82c611a, int, 0); 1270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(opti82c46x, int, 0); 1271defc9cd826e4a99f550504a744f9407b518828aeAlan Coxmodule_param(qdi, int, 0); 12726d981b9a91be29c0deae5ac794a4fe885027032fBartlomiej Zolnierkiewiczmodule_param(winbond, int, 0); 1273669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_param(pio_mask, int, 0); 1274f834e49f1a09414e9618ff0c9cd83c2114032bb6Alan Coxmodule_param(iordy_mask, int, 0); 1275669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik 1276669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_init(legacy_init); 1277669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_exit(legacy_exit); 1278