1669a5db4SJeff Garzik /*
2669a5db4SJeff Garzik * pata_ali.c - ALI 15x3 PATA for new ATA layer
3669a5db4SJeff Garzik * (C) 2005 Red Hat Inc
4669a5db4SJeff Garzik *
5669a5db4SJeff Garzik * based in part upon
6669a5db4SJeff Garzik * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02
7669a5db4SJeff Garzik *
8669a5db4SJeff Garzik * Copyright (C) 1998-2000 Michel Aubry, Maintainer
9669a5db4SJeff Garzik * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
10669a5db4SJeff Garzik * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
11669a5db4SJeff Garzik *
12669a5db4SJeff Garzik * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org)
13669a5db4SJeff Garzik * May be copied or modified under the terms of the GNU General Public License
14669a5db4SJeff Garzik * Copyright (C) 2002 Alan Cox <alan@redhat.com>
15669a5db4SJeff Garzik * ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
16669a5db4SJeff Garzik *
17669a5db4SJeff Garzik * Documentation
18669a5db4SJeff Garzik * Chipset documentation available under NDA only
19669a5db4SJeff Garzik *
20669a5db4SJeff Garzik * TODO/CHECK
21669a5db4SJeff Garzik * Cannot have ATAPI on both master & slave for rev < c2 (???) but
221b2c357cSAlan Cox * otherwise should do atapi DMA (For now for old we do PIO only for
231b2c357cSAlan Cox * ATAPI)
241b2c357cSAlan Cox * Review Sunblade workaround.
25669a5db4SJeff Garzik */
26669a5db4SJeff Garzik
27669a5db4SJeff Garzik #include <linux/kernel.h>
28669a5db4SJeff Garzik #include <linux/module.h>
29669a5db4SJeff Garzik #include <linux/pci.h>
30669a5db4SJeff Garzik #include <linux/init.h>
31669a5db4SJeff Garzik #include <linux/blkdev.h>
32669a5db4SJeff Garzik #include <linux/delay.h>
33669a5db4SJeff Garzik #include <scsi/scsi_host.h>
34669a5db4SJeff Garzik #include <linux/libata.h>
35669a5db4SJeff Garzik #include <linux/dmi.h>
36669a5db4SJeff Garzik
37669a5db4SJeff Garzik #define DRV_NAME "pata_ali"
38fc80902fSAlan Cox #define DRV_VERSION "0.7.8"
39669a5db4SJeff Garzik
4049737f26SJason Wang static int ali_atapi_dma;
418243e636STejun Heo module_param_named(atapi_dma, ali_atapi_dma, int, 0644);
428243e636STejun Heo MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)");
438243e636STejun Heo
44bc42b24eSAndrew Morton static struct pci_dev *ali_isa_bridge;
451b2c357cSAlan Cox
46669a5db4SJeff Garzik /*
47669a5db4SJeff Garzik * Cable special cases
48669a5db4SJeff Garzik */
49669a5db4SJeff Garzik
501855256cSJeff Garzik static const struct dmi_system_id cable_dmi_table[] = {
51669a5db4SJeff Garzik {
52669a5db4SJeff Garzik .ident = "HP Pavilion N5430",
53669a5db4SJeff Garzik .matches = {
54669a5db4SJeff Garzik DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
555c8d5201SAlan Cox DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
56669a5db4SJeff Garzik },
57669a5db4SJeff Garzik },
5803e6f489SDaniel Exner {
59802872e7SBartlomiej Zolnierkiewicz .ident = "Toshiba Satellite S1800-814",
6003e6f489SDaniel Exner .matches = {
6103e6f489SDaniel Exner DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
6203e6f489SDaniel Exner DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
6303e6f489SDaniel Exner },
6403e6f489SDaniel Exner },
65669a5db4SJeff Garzik { }
66669a5db4SJeff Garzik };
67669a5db4SJeff Garzik
ali_cable_override(struct pci_dev * pdev)68669a5db4SJeff Garzik static int ali_cable_override(struct pci_dev *pdev)
69669a5db4SJeff Garzik {
70669a5db4SJeff Garzik /* Fujitsu P2000 */
71669a5db4SJeff Garzik if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
72669a5db4SJeff Garzik return 1;
738f59a13aSAlan Cox /* Mitac 8317 (Winbook-A) and relatives */
748f59a13aSAlan Cox if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
758f59a13aSAlan Cox return 1;
76669a5db4SJeff Garzik /* Systems by DMI */
77669a5db4SJeff Garzik if (dmi_check_system(cable_dmi_table))
78669a5db4SJeff Garzik return 1;
79669a5db4SJeff Garzik return 0;
80669a5db4SJeff Garzik }
81669a5db4SJeff Garzik
82669a5db4SJeff Garzik /**
83669a5db4SJeff Garzik * ali_c2_cable_detect - cable detection
84669a5db4SJeff Garzik * @ap: ATA port
85669a5db4SJeff Garzik *
86669a5db4SJeff Garzik * Perform cable detection for C2 and later revisions
87669a5db4SJeff Garzik */
88669a5db4SJeff Garzik
ali_c2_cable_detect(struct ata_port * ap)89669a5db4SJeff Garzik static int ali_c2_cable_detect(struct ata_port *ap)
90669a5db4SJeff Garzik {
91669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev);
92669a5db4SJeff Garzik u8 ata66;
93669a5db4SJeff Garzik
94669a5db4SJeff Garzik /* Certain laptops use short but suitable cables and don't
95669a5db4SJeff Garzik implement the detect logic */
96669a5db4SJeff Garzik
97669a5db4SJeff Garzik if (ali_cable_override(pdev))
98fc085150SAlan Cox return ATA_CBL_PATA40_SHORT;
99669a5db4SJeff Garzik
100669a5db4SJeff Garzik /* Host view cable detect 0x4A bit 0 primary bit 1 secondary
101669a5db4SJeff Garzik Bit set for 40 pin */
102669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x4A, &ata66);
103669a5db4SJeff Garzik if (ata66 & (1 << ap->port_no))
104669a5db4SJeff Garzik return ATA_CBL_PATA40;
105669a5db4SJeff Garzik else
106669a5db4SJeff Garzik return ATA_CBL_PATA80;
107669a5db4SJeff Garzik }
108669a5db4SJeff Garzik
109669a5db4SJeff Garzik /**
110669a5db4SJeff Garzik * ali_20_filter - filter for earlier ALI DMA
111325fe208SLee Jones * @adev: ATA device
112764e3bc4SLee Jones * @mask: received mask to manipulate and pass back
113669a5db4SJeff Garzik *
114669a5db4SJeff Garzik * Ensure that we do not do DMA on CD devices. We may be able to
115669a5db4SJeff Garzik * fix that later on. Also ensure we do not do UDMA on WDC drives
116669a5db4SJeff Garzik */
117669a5db4SJeff Garzik
ali_20_filter(struct ata_device * adev,unsigned int mask)118f0a6d77bSSergey Shtylyov static unsigned int ali_20_filter(struct ata_device *adev, unsigned int mask)
119669a5db4SJeff Garzik {
1208bfa79fcSTejun Heo char model_num[ATA_ID_PROD_LEN + 1];
121669a5db4SJeff Garzik /* No DMA on anything but a disk for now */
122669a5db4SJeff Garzik if (adev->class != ATA_DEV_ATA)
123669a5db4SJeff Garzik mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
1248bfa79fcSTejun Heo ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
125669a5db4SJeff Garzik if (strstr(model_num, "WDC"))
126237fe888SColin Ian King mask &= ~ATA_MASK_UDMA;
127c7087652STejun Heo return mask;
128669a5db4SJeff Garzik }
129669a5db4SJeff Garzik
130669a5db4SJeff Garzik /**
131669a5db4SJeff Garzik * ali_fifo_control - FIFO manager
132669a5db4SJeff Garzik * @ap: ALi channel to control
133669a5db4SJeff Garzik * @adev: device for FIFO control
134669a5db4SJeff Garzik * @on: 0 for off 1 for on
135669a5db4SJeff Garzik *
136669a5db4SJeff Garzik * Enable or disable the FIFO on a given device. Because of the way the
137669a5db4SJeff Garzik * ALi FIFO works it provides a boost on ATA disk but can be confused by
138669a5db4SJeff Garzik * ATAPI and we must therefore manage it.
139669a5db4SJeff Garzik */
140669a5db4SJeff Garzik
ali_fifo_control(struct ata_port * ap,struct ata_device * adev,int on)141669a5db4SJeff Garzik static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on)
142669a5db4SJeff Garzik {
143669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev);
144669a5db4SJeff Garzik int pio_fifo = 0x54 + ap->port_no;
145669a5db4SJeff Garzik u8 fifo;
146669a5db4SJeff Garzik int shift = 4 * adev->devno;
147669a5db4SJeff Garzik
148669a5db4SJeff Garzik /* ATA - FIFO on set nibble to 0x05, ATAPI - FIFO off, set nibble to
149669a5db4SJeff Garzik 0x00. Not all the docs agree but the behaviour we now use is the
150669a5db4SJeff Garzik one stated in the BIOS Programming Guide */
151669a5db4SJeff Garzik
152669a5db4SJeff Garzik pci_read_config_byte(pdev, pio_fifo, &fifo);
153669a5db4SJeff Garzik fifo &= ~(0x0F << shift);
154669a5db4SJeff Garzik fifo |= (on << shift);
155669a5db4SJeff Garzik pci_write_config_byte(pdev, pio_fifo, fifo);
156669a5db4SJeff Garzik }
157669a5db4SJeff Garzik
158669a5db4SJeff Garzik /**
159669a5db4SJeff Garzik * ali_program_modes - load mode registers
160669a5db4SJeff Garzik * @ap: ALi channel to load
161669a5db4SJeff Garzik * @adev: Device the timing is for
162d8b3d8cfSBartlomiej Zolnierkiewicz * @t: timing data
163669a5db4SJeff Garzik * @ultra: UDMA timing or zero for off
164669a5db4SJeff Garzik *
165669a5db4SJeff Garzik * Loads the timing registers for cmd/data and disable UDMA if
166669a5db4SJeff Garzik * ultra is zero. If ultra is set then load and enable the UDMA
167669a5db4SJeff Garzik * timing but do not touch the command/data timing.
168669a5db4SJeff Garzik */
169669a5db4SJeff Garzik
ali_program_modes(struct ata_port * ap,struct ata_device * adev,struct ata_timing * t,u8 ultra)170669a5db4SJeff Garzik static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, struct ata_timing *t, u8 ultra)
171669a5db4SJeff Garzik {
172669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev);
173669a5db4SJeff Garzik int cas = 0x58 + 4 * ap->port_no; /* Command timing */
174669a5db4SJeff Garzik int cbt = 0x59 + 4 * ap->port_no; /* Command timing */
175669a5db4SJeff Garzik int drwt = 0x5A + 4 * ap->port_no + adev->devno; /* R/W timing */
176669a5db4SJeff Garzik int udmat = 0x56 + ap->port_no; /* UDMA timing */
177669a5db4SJeff Garzik int shift = 4 * adev->devno;
178669a5db4SJeff Garzik u8 udma;
179669a5db4SJeff Garzik
180669a5db4SJeff Garzik if (t != NULL) {
18107633b5dSHarvey Harrison t->setup = clamp_val(t->setup, 1, 8) & 7;
18207633b5dSHarvey Harrison t->act8b = clamp_val(t->act8b, 1, 8) & 7;
18307633b5dSHarvey Harrison t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
18407633b5dSHarvey Harrison t->active = clamp_val(t->active, 1, 8) & 7;
18507633b5dSHarvey Harrison t->recover = clamp_val(t->recover, 1, 16) & 15;
186669a5db4SJeff Garzik
187669a5db4SJeff Garzik pci_write_config_byte(pdev, cas, t->setup);
188669a5db4SJeff Garzik pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b);
189669a5db4SJeff Garzik pci_write_config_byte(pdev, drwt, (t->active << 4) | t->recover);
190669a5db4SJeff Garzik }
191669a5db4SJeff Garzik
192669a5db4SJeff Garzik /* Set up the UDMA enable */
193669a5db4SJeff Garzik pci_read_config_byte(pdev, udmat, &udma);
194669a5db4SJeff Garzik udma &= ~(0x0F << shift);
195669a5db4SJeff Garzik udma |= ultra << shift;
196669a5db4SJeff Garzik pci_write_config_byte(pdev, udmat, udma);
197669a5db4SJeff Garzik }
198669a5db4SJeff Garzik
199669a5db4SJeff Garzik /**
200669a5db4SJeff Garzik * ali_set_piomode - set initial PIO mode data
201669a5db4SJeff Garzik * @ap: ATA interface
202669a5db4SJeff Garzik * @adev: ATA device
203669a5db4SJeff Garzik *
204d8b3d8cfSBartlomiej Zolnierkiewicz * Program the ALi registers for PIO mode.
205669a5db4SJeff Garzik */
206669a5db4SJeff Garzik
ali_set_piomode(struct ata_port * ap,struct ata_device * adev)207669a5db4SJeff Garzik static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev)
208669a5db4SJeff Garzik {
209669a5db4SJeff Garzik struct ata_device *pair = ata_dev_pair(adev);
210669a5db4SJeff Garzik struct ata_timing t;
211669a5db4SJeff Garzik unsigned long T = 1000000000 / 33333; /* PCI clock based */
212669a5db4SJeff Garzik
213669a5db4SJeff Garzik ata_timing_compute(adev, adev->pio_mode, &t, T, 1);
214669a5db4SJeff Garzik if (pair) {
215669a5db4SJeff Garzik struct ata_timing p;
216669a5db4SJeff Garzik ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
217669a5db4SJeff Garzik ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
21847b32049SReimar Döffinger if (ata_dma_enabled(pair)) {
219669a5db4SJeff Garzik ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
220669a5db4SJeff Garzik ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
221669a5db4SJeff Garzik }
222669a5db4SJeff Garzik }
223669a5db4SJeff Garzik
224669a5db4SJeff Garzik /* PIO FIFO is only permitted on ATA disk */
225669a5db4SJeff Garzik if (adev->class != ATA_DEV_ATA)
226669a5db4SJeff Garzik ali_fifo_control(ap, adev, 0x00);
227669a5db4SJeff Garzik ali_program_modes(ap, adev, &t, 0);
228669a5db4SJeff Garzik if (adev->class == ATA_DEV_ATA)
229669a5db4SJeff Garzik ali_fifo_control(ap, adev, 0x05);
230669a5db4SJeff Garzik
231669a5db4SJeff Garzik }
232669a5db4SJeff Garzik
233669a5db4SJeff Garzik /**
234669a5db4SJeff Garzik * ali_set_dmamode - set initial DMA mode data
235669a5db4SJeff Garzik * @ap: ATA interface
236669a5db4SJeff Garzik * @adev: ATA device
237669a5db4SJeff Garzik *
238d8b3d8cfSBartlomiej Zolnierkiewicz * Program the ALi registers for DMA mode.
239669a5db4SJeff Garzik */
240669a5db4SJeff Garzik
ali_set_dmamode(struct ata_port * ap,struct ata_device * adev)241669a5db4SJeff Garzik static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
242669a5db4SJeff Garzik {
243669a5db4SJeff Garzik static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
244669a5db4SJeff Garzik struct ata_device *pair = ata_dev_pair(adev);
245669a5db4SJeff Garzik struct ata_timing t;
246669a5db4SJeff Garzik unsigned long T = 1000000000 / 33333; /* PCI clock based */
247669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev);
248669a5db4SJeff Garzik
249669a5db4SJeff Garzik
250669a5db4SJeff Garzik if (adev->class == ATA_DEV_ATA)
251669a5db4SJeff Garzik ali_fifo_control(ap, adev, 0x08);
252669a5db4SJeff Garzik
253669a5db4SJeff Garzik if (adev->dma_mode >= XFER_UDMA_0) {
254669a5db4SJeff Garzik ali_program_modes(ap, adev, NULL, udma_timing[adev->dma_mode - XFER_UDMA_0]);
255669a5db4SJeff Garzik if (adev->dma_mode >= XFER_UDMA_3) {
256669a5db4SJeff Garzik u8 reg4b;
257669a5db4SJeff Garzik pci_read_config_byte(pdev, 0x4B, ®4b);
258669a5db4SJeff Garzik reg4b |= 1;
259669a5db4SJeff Garzik pci_write_config_byte(pdev, 0x4B, reg4b);
260669a5db4SJeff Garzik }
261669a5db4SJeff Garzik } else {
262669a5db4SJeff Garzik ata_timing_compute(adev, adev->dma_mode, &t, T, 1);
263669a5db4SJeff Garzik if (pair) {
264669a5db4SJeff Garzik struct ata_timing p;
265669a5db4SJeff Garzik ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
266669a5db4SJeff Garzik ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
26747b32049SReimar Döffinger if (ata_dma_enabled(pair)) {
268669a5db4SJeff Garzik ata_timing_compute(pair, pair->dma_mode, &p, T, 1);
269669a5db4SJeff Garzik ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT);
270669a5db4SJeff Garzik }
271669a5db4SJeff Garzik }
272669a5db4SJeff Garzik ali_program_modes(ap, adev, &t, 0);
273669a5db4SJeff Garzik }
274669a5db4SJeff Garzik }
275669a5db4SJeff Garzik
276669a5db4SJeff Garzik /**
2778243e636STejun Heo * ali_warn_atapi_dma - Warn about ATAPI DMA disablement
2788243e636STejun Heo * @adev: Device
2798243e636STejun Heo *
2808243e636STejun Heo * Whine about ATAPI DMA disablement if @adev is an ATAPI device.
2818243e636STejun Heo * Can be used as ->dev_config.
2828243e636STejun Heo */
2838243e636STejun Heo
ali_warn_atapi_dma(struct ata_device * adev)2848243e636STejun Heo static void ali_warn_atapi_dma(struct ata_device *adev)
2858243e636STejun Heo {
2868243e636STejun Heo struct ata_eh_context *ehc = &adev->link->eh_context;
2878243e636STejun Heo int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
2888243e636STejun Heo
2898243e636STejun Heo if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
290a9a79dfeSJoe Perches ata_dev_warn(adev,
291c21c8066SDirk Hohndel "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n");
292a9a79dfeSJoe Perches ata_dev_warn(adev,
2938243e636STejun Heo "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
2948243e636STejun Heo }
2958243e636STejun Heo }
2968243e636STejun Heo
2978243e636STejun Heo /**
298669a5db4SJeff Garzik * ali_lock_sectors - Keep older devices to 255 sector mode
299669a5db4SJeff Garzik * @adev: Device
300669a5db4SJeff Garzik *
301669a5db4SJeff Garzik * Called during the bus probe for each device that is found. We use
302669a5db4SJeff Garzik * this call to lock the sector count of the device to 255 or less on
303669a5db4SJeff Garzik * older ALi controllers. If we didn't do this then large I/O's would
304669a5db4SJeff Garzik * require LBA48 commands which the older ALi requires are issued by
305669a5db4SJeff Garzik * slower PIO methods
306669a5db4SJeff Garzik */
307669a5db4SJeff Garzik
ali_lock_sectors(struct ata_device * adev)308cd0d3bbcSAlan static void ali_lock_sectors(struct ata_device *adev)
309669a5db4SJeff Garzik {
310669a5db4SJeff Garzik adev->max_sectors = 255;
3118243e636STejun Heo ali_warn_atapi_dma(adev);
312669a5db4SJeff Garzik }
313669a5db4SJeff Garzik
314498222f3SAlan Cox /**
315498222f3SAlan Cox * ali_check_atapi_dma - DMA check for most ALi controllers
316325fe208SLee Jones * @qc: Command to complete
317498222f3SAlan Cox *
318498222f3SAlan Cox * Called to decide whether commands should be sent by DMA or PIO
319498222f3SAlan Cox */
320498222f3SAlan Cox
ali_check_atapi_dma(struct ata_queued_cmd * qc)321498222f3SAlan Cox static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
322498222f3SAlan Cox {
3238243e636STejun Heo if (!ali_atapi_dma) {
3248243e636STejun Heo /* FIXME: pata_ali can't do ATAPI DMA reliably but the
3258243e636STejun Heo * IDE alim15x3 driver can. I tried lots of things
3268243e636STejun Heo * but couldn't find what the actual difference was.
3278243e636STejun Heo * If you got an idea, please write it to
3288243e636STejun Heo * linux-ide@vger.kernel.org and cc htejun@gmail.com.
3298243e636STejun Heo *
3308243e636STejun Heo * Disable ATAPI DMA for now.
3318243e636STejun Heo */
3328243e636STejun Heo return -EOPNOTSUPP;
3338243e636STejun Heo }
3348243e636STejun Heo
335498222f3SAlan Cox /* If its not a media command, its not worth it */
3364a38e733STejun Heo if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC)
337498222f3SAlan Cox return -EOPNOTSUPP;
338498222f3SAlan Cox return 0;
339498222f3SAlan Cox }
340498222f3SAlan Cox
ali_c2_c3_postreset(struct ata_link * link,unsigned int * classes)341fc80902fSAlan Cox static void ali_c2_c3_postreset(struct ata_link *link, unsigned int *classes)
342fc80902fSAlan Cox {
343fc80902fSAlan Cox u8 r;
344fc80902fSAlan Cox int port_bit = 4 << link->ap->port_no;
345fc80902fSAlan Cox
346fc80902fSAlan Cox /* If our bridge is an ALI 1533 then do the extra work */
347bc42b24eSAndrew Morton if (ali_isa_bridge) {
348fc80902fSAlan Cox /* Tristate and re-enable the bus signals */
349bc42b24eSAndrew Morton pci_read_config_byte(ali_isa_bridge, 0x58, &r);
350fc80902fSAlan Cox r &= ~port_bit;
351bc42b24eSAndrew Morton pci_write_config_byte(ali_isa_bridge, 0x58, r);
352fc80902fSAlan Cox r |= port_bit;
353bc42b24eSAndrew Morton pci_write_config_byte(ali_isa_bridge, 0x58, r);
354fc80902fSAlan Cox }
355fc80902fSAlan Cox ata_sff_postreset(link, classes);
356fc80902fSAlan Cox }
357fc80902fSAlan Cox
358*25df73d9SBart Van Assche static const struct scsi_host_template ali_sht = {
35968d1d07bSTejun Heo ATA_BMDMA_SHT(DRV_NAME),
360669a5db4SJeff Garzik };
361669a5db4SJeff Garzik
362669a5db4SJeff Garzik /*
363669a5db4SJeff Garzik * Port operations for PIO only ALi
364669a5db4SJeff Garzik */
365669a5db4SJeff Garzik
366669a5db4SJeff Garzik static struct ata_port_operations ali_early_port_ops = {
367029cfd6bSTejun Heo .inherits = &ata_sff_port_ops,
368b723d144SAlan Cox .cable_detect = ata_cable_40wire,
369029cfd6bSTejun Heo .set_piomode = ali_set_piomode,
370871af121SAlan Cox .sff_data_xfer = ata_sff_data_xfer32,
371029cfd6bSTejun Heo };
372669a5db4SJeff Garzik
373029cfd6bSTejun Heo static const struct ata_port_operations ali_dma_base_ops = {
374871af121SAlan Cox .inherits = &ata_bmdma32_port_ops,
375029cfd6bSTejun Heo .set_piomode = ali_set_piomode,
376029cfd6bSTejun Heo .set_dmamode = ali_set_dmamode,
377669a5db4SJeff Garzik };
378669a5db4SJeff Garzik
379669a5db4SJeff Garzik /*
380669a5db4SJeff Garzik * Port operations for DMA capable ALi without cable
381669a5db4SJeff Garzik * detect
382669a5db4SJeff Garzik */
383669a5db4SJeff Garzik static struct ata_port_operations ali_20_port_ops = {
384029cfd6bSTejun Heo .inherits = &ali_dma_base_ops,
385b723d144SAlan Cox .cable_detect = ata_cable_40wire,
386029cfd6bSTejun Heo .mode_filter = ali_20_filter,
387029cfd6bSTejun Heo .check_atapi_dma = ali_check_atapi_dma,
388029cfd6bSTejun Heo .dev_config = ali_lock_sectors,
389669a5db4SJeff Garzik };
390669a5db4SJeff Garzik
391669a5db4SJeff Garzik /*
392669a5db4SJeff Garzik * Port operations for DMA capable ALi with cable detect
393669a5db4SJeff Garzik */
394669a5db4SJeff Garzik static struct ata_port_operations ali_c2_port_ops = {
395029cfd6bSTejun Heo .inherits = &ali_dma_base_ops,
396498222f3SAlan Cox .check_atapi_dma = ali_check_atapi_dma,
397b723d144SAlan Cox .cable_detect = ali_c2_cable_detect,
398029cfd6bSTejun Heo .dev_config = ali_lock_sectors,
399fc80902fSAlan Cox .postreset = ali_c2_c3_postreset,
400fc80902fSAlan Cox };
401fc80902fSAlan Cox
402fc80902fSAlan Cox /*
403fc80902fSAlan Cox * Port operations for DMA capable ALi with cable detect
404fc80902fSAlan Cox */
405fc80902fSAlan Cox static struct ata_port_operations ali_c4_port_ops = {
406fc80902fSAlan Cox .inherits = &ali_dma_base_ops,
407fc80902fSAlan Cox .check_atapi_dma = ali_check_atapi_dma,
408fc80902fSAlan Cox .cable_detect = ali_c2_cable_detect,
409fc80902fSAlan Cox .dev_config = ali_lock_sectors,
410669a5db4SJeff Garzik };
411669a5db4SJeff Garzik
412669a5db4SJeff Garzik /*
413669a5db4SJeff Garzik * Port operations for DMA capable ALi with cable detect and LBA48
414669a5db4SJeff Garzik */
415669a5db4SJeff Garzik static struct ata_port_operations ali_c5_port_ops = {
416029cfd6bSTejun Heo .inherits = &ali_dma_base_ops,
417498222f3SAlan Cox .check_atapi_dma = ali_check_atapi_dma,
4188243e636STejun Heo .dev_config = ali_warn_atapi_dma,
419b723d144SAlan Cox .cable_detect = ali_c2_cable_detect,
420669a5db4SJeff Garzik };
421669a5db4SJeff Garzik
42234d8dfb1SAlan
42334d8dfb1SAlan /**
42434d8dfb1SAlan * ali_init_chipset - chip setup function
42534d8dfb1SAlan * @pdev: PCI device of ATA controller
42634d8dfb1SAlan *
42734d8dfb1SAlan * Perform the setup on the device that must be done both at boot
42834d8dfb1SAlan * and at resume time.
42934d8dfb1SAlan */
43034d8dfb1SAlan
ali_init_chipset(struct pci_dev * pdev)43134d8dfb1SAlan static void ali_init_chipset(struct pci_dev *pdev)
43234d8dfb1SAlan {
43344c10138SAuke Kok u8 tmp;
4341b2c357cSAlan Cox struct pci_dev *north;
43534d8dfb1SAlan
43634d8dfb1SAlan /*
43734d8dfb1SAlan * The chipset revision selects the driver operations and
43834d8dfb1SAlan * mode data.
43934d8dfb1SAlan */
44034d8dfb1SAlan
4411b2c357cSAlan Cox if (pdev->revision <= 0x20) {
4421b2c357cSAlan Cox pci_read_config_byte(pdev, 0x53, &tmp);
4431b2c357cSAlan Cox tmp |= 0x03;
4441b2c357cSAlan Cox pci_write_config_byte(pdev, 0x53, tmp);
4451b2c357cSAlan Cox } else {
4461b2c357cSAlan Cox pci_read_config_byte(pdev, 0x4a, &tmp);
4471b2c357cSAlan Cox pci_write_config_byte(pdev, 0x4a, tmp | 0x20);
44834d8dfb1SAlan pci_read_config_byte(pdev, 0x4B, &tmp);
4491b2c357cSAlan Cox if (pdev->revision < 0xC2)
4501b2c357cSAlan Cox /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
45134d8dfb1SAlan /* Clear CD-ROM DMA write bit */
45234d8dfb1SAlan tmp &= 0x7F;
4531b2c357cSAlan Cox /* Cable and UDMA */
454d6250a03SAlan Cox if (pdev->revision >= 0xc2)
455d6250a03SAlan Cox tmp |= 0x01;
456d6250a03SAlan Cox pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
4571b2c357cSAlan Cox /*
4581b2c357cSAlan Cox * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
4591b2c357cSAlan Cox * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
4601b2c357cSAlan Cox * via 0x54/55.
4611b2c357cSAlan Cox */
4621b2c357cSAlan Cox pci_read_config_byte(pdev, 0x53, &tmp);
4631b2c357cSAlan Cox if (pdev->revision >= 0xc7)
4641b2c357cSAlan Cox tmp |= 0x03;
4651b2c357cSAlan Cox else
4661b2c357cSAlan Cox tmp |= 0x01; /* CD_ROM enable for DMA */
4671b2c357cSAlan Cox pci_write_config_byte(pdev, 0x53, tmp);
46834d8dfb1SAlan }
46978a6b8d8SSinan Kaya north = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 0,
47078a6b8d8SSinan Kaya PCI_DEVFN(0, 0));
471bc42b24eSAndrew Morton if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) {
47234d8dfb1SAlan /* Configure the ALi bridge logic. For non ALi rely on BIOS.
47334d8dfb1SAlan Set the south bridge enable bit */
474bc42b24eSAndrew Morton pci_read_config_byte(ali_isa_bridge, 0x79, &tmp);
47544c10138SAuke Kok if (pdev->revision == 0xC2)
476bc42b24eSAndrew Morton pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04);
47744c10138SAuke Kok else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
478bc42b24eSAndrew Morton pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
47934d8dfb1SAlan }
48034d8dfb1SAlan pci_dev_put(north);
4819363c382STejun Heo ata_pci_bmdma_clear_simplex(pdev);
48234d8dfb1SAlan }
483669a5db4SJeff Garzik /**
484669a5db4SJeff Garzik * ali_init_one - discovery callback
485669a5db4SJeff Garzik * @pdev: PCI device ID
486669a5db4SJeff Garzik * @id: PCI table info
487669a5db4SJeff Garzik *
488669a5db4SJeff Garzik * An ALi IDE interface has been discovered. Figure out what revision
489669a5db4SJeff Garzik * and perform configuration work before handing it to the ATA layer
490669a5db4SJeff Garzik */
491669a5db4SJeff Garzik
ali_init_one(struct pci_dev * pdev,const struct pci_device_id * id)492669a5db4SJeff Garzik static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
493669a5db4SJeff Garzik {
4941626aeb8STejun Heo static const struct ata_port_info info_early = {
4951d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS,
49614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
497669a5db4SJeff Garzik .port_ops = &ali_early_port_ops
498669a5db4SJeff Garzik };
499669a5db4SJeff Garzik /* Revision 0x20 added DMA */
5001626aeb8STejun Heo static const struct ata_port_info info_20 = {
501a3cb900cSAlan Cox .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
502a3cb900cSAlan Cox ATA_FLAG_IGN_SIMPLEX,
50314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
50414bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2,
505669a5db4SJeff Garzik .port_ops = &ali_20_port_ops
506669a5db4SJeff Garzik };
507669a5db4SJeff Garzik /* Revision 0x20 with support logic added UDMA */
5081626aeb8STejun Heo static const struct ata_port_info info_20_udma = {
509a3cb900cSAlan Cox .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
510a3cb900cSAlan Cox ATA_FLAG_IGN_SIMPLEX,
51114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
51214bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2,
51314bdef98SErik Inge Bolsø .udma_mask = ATA_UDMA2,
514669a5db4SJeff Garzik .port_ops = &ali_20_port_ops
515669a5db4SJeff Garzik };
516669a5db4SJeff Garzik /* Revision 0xC2 adds UDMA66 */
5171626aeb8STejun Heo static const struct ata_port_info info_c2 = {
518a3cb900cSAlan Cox .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
519a3cb900cSAlan Cox ATA_FLAG_IGN_SIMPLEX,
52014bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
52114bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2,
522bf6263a8SJeff Garzik .udma_mask = ATA_UDMA4,
523669a5db4SJeff Garzik .port_ops = &ali_c2_port_ops
524669a5db4SJeff Garzik };
525ee581502SChuck Ebbert /* Revision 0xC3 is UDMA66 for now */
5261626aeb8STejun Heo static const struct ata_port_info info_c3 = {
527a3cb900cSAlan Cox .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
528a3cb900cSAlan Cox ATA_FLAG_IGN_SIMPLEX,
52914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
53014bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2,
531bf6263a8SJeff Garzik .udma_mask = ATA_UDMA4,
532669a5db4SJeff Garzik .port_ops = &ali_c2_port_ops
533669a5db4SJeff Garzik };
534ee581502SChuck Ebbert /* Revision 0xC4 is UDMA100 */
5351626aeb8STejun Heo static const struct ata_port_info info_c4 = {
536a3cb900cSAlan Cox .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
537a3cb900cSAlan Cox ATA_FLAG_IGN_SIMPLEX,
53814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
53914bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2,
540bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5,
541fc80902fSAlan Cox .port_ops = &ali_c4_port_ops
542669a5db4SJeff Garzik };
543669a5db4SJeff Garzik /* Revision 0xC5 is UDMA133 with LBA48 DMA */
5441626aeb8STejun Heo static const struct ata_port_info info_c5 = {
545a3cb900cSAlan Cox .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_IGN_SIMPLEX,
54614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
54714bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2,
548bf6263a8SJeff Garzik .udma_mask = ATA_UDMA6,
549669a5db4SJeff Garzik .port_ops = &ali_c5_port_ops
550669a5db4SJeff Garzik };
551669a5db4SJeff Garzik
5521626aeb8STejun Heo const struct ata_port_info *ppi[] = { NULL, NULL };
55344c10138SAuke Kok u8 tmp;
554f08048e9STejun Heo int rc;
555f08048e9STejun Heo
556f08048e9STejun Heo rc = pcim_enable_device(pdev);
557f08048e9STejun Heo if (rc)
558f08048e9STejun Heo return rc;
559669a5db4SJeff Garzik
560669a5db4SJeff Garzik /*
561669a5db4SJeff Garzik * The chipset revision selects the driver operations and
562669a5db4SJeff Garzik * mode data.
563669a5db4SJeff Garzik */
564669a5db4SJeff Garzik
56544c10138SAuke Kok if (pdev->revision < 0x20) {
5661626aeb8STejun Heo ppi[0] = &info_early;
56744c10138SAuke Kok } else if (pdev->revision < 0xC2) {
5681626aeb8STejun Heo ppi[0] = &info_20;
56944c10138SAuke Kok } else if (pdev->revision == 0xC2) {
5701626aeb8STejun Heo ppi[0] = &info_c2;
57144c10138SAuke Kok } else if (pdev->revision == 0xC3) {
5721626aeb8STejun Heo ppi[0] = &info_c3;
57344c10138SAuke Kok } else if (pdev->revision == 0xC4) {
5741626aeb8STejun Heo ppi[0] = &info_c4;
575669a5db4SJeff Garzik } else
5761626aeb8STejun Heo ppi[0] = &info_c5;
577669a5db4SJeff Garzik
57834d8dfb1SAlan ali_init_chipset(pdev);
579669a5db4SJeff Garzik
580bc42b24eSAndrew Morton if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
581669a5db4SJeff Garzik /* Are we paired with a UDMA capable chip */
582bc42b24eSAndrew Morton pci_read_config_byte(ali_isa_bridge, 0x5E, &tmp);
583669a5db4SJeff Garzik if ((tmp & 0x1E) == 0x12)
5841626aeb8STejun Heo ppi[0] = &info_20_udma;
58534d8dfb1SAlan }
586e8389f0cSBen Dooks
5871c5afdf7STejun Heo if (!ppi[0]->mwdma_mask && !ppi[0]->udma_mask)
58816ea0fc9SAlan Cox return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
5891c5afdf7STejun Heo else
5901c5afdf7STejun Heo return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0);
591669a5db4SJeff Garzik }
592669a5db4SJeff Garzik
59358eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
ali_reinit_one(struct pci_dev * pdev)59434d8dfb1SAlan static int ali_reinit_one(struct pci_dev *pdev)
59534d8dfb1SAlan {
5960a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev);
597f08048e9STejun Heo int rc;
598f08048e9STejun Heo
599f08048e9STejun Heo rc = ata_pci_device_do_resume(pdev);
600f08048e9STejun Heo if (rc)
601f08048e9STejun Heo return rc;
60234d8dfb1SAlan ali_init_chipset(pdev);
603f08048e9STejun Heo ata_host_resume(host);
604f08048e9STejun Heo return 0;
60534d8dfb1SAlan }
606438ac6d5STejun Heo #endif
60734d8dfb1SAlan
6082d2744fcSJeff Garzik static const struct pci_device_id ali[] = {
6092d2744fcSJeff Garzik { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
6102d2744fcSJeff Garzik { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), },
6112d2744fcSJeff Garzik
6122d2744fcSJeff Garzik { },
613669a5db4SJeff Garzik };
614669a5db4SJeff Garzik
615669a5db4SJeff Garzik static struct pci_driver ali_pci_driver = {
616669a5db4SJeff Garzik .name = DRV_NAME,
617669a5db4SJeff Garzik .id_table = ali,
618669a5db4SJeff Garzik .probe = ali_init_one,
61934d8dfb1SAlan .remove = ata_pci_remove_one,
62058eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
62134d8dfb1SAlan .suspend = ata_pci_device_suspend,
62234d8dfb1SAlan .resume = ali_reinit_one,
623438ac6d5STejun Heo #endif
624669a5db4SJeff Garzik };
625669a5db4SJeff Garzik
ali_init(void)626669a5db4SJeff Garzik static int __init ali_init(void)
627669a5db4SJeff Garzik {
6281b2c357cSAlan Cox int ret;
629bc42b24eSAndrew Morton ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
6301b2c357cSAlan Cox
6311b2c357cSAlan Cox ret = pci_register_driver(&ali_pci_driver);
6321b2c357cSAlan Cox if (ret < 0)
633bc42b24eSAndrew Morton pci_dev_put(ali_isa_bridge);
6341b2c357cSAlan Cox return ret;
635669a5db4SJeff Garzik }
636669a5db4SJeff Garzik
637669a5db4SJeff Garzik
ali_exit(void)638669a5db4SJeff Garzik static void __exit ali_exit(void)
639669a5db4SJeff Garzik {
640669a5db4SJeff Garzik pci_unregister_driver(&ali_pci_driver);
641bc42b24eSAndrew Morton pci_dev_put(ali_isa_bridge);
642669a5db4SJeff Garzik }
643669a5db4SJeff Garzik
644669a5db4SJeff Garzik
645669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox");
646669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for ALi PATA");
647669a5db4SJeff Garzik MODULE_LICENSE("GPL");
648669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, ali);
649669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION);
650669a5db4SJeff Garzik
651669a5db4SJeff Garzik module_init(ali_init);
652669a5db4SJeff Garzik module_exit(ali_exit);
653