Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cs5530.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2000 Andre Hedrick <[email protected]>
3  * Copyright (C) 2000 Mark Lord <[email protected]>
4  * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
5  *
6  * May be copied or modified under the terms of the GNU General Public License
7  *
8  * Development of this chipset driver was funded
9  * by the nice folks at National Semiconductor.
10  *
11  * Documentation:
12  * CS5530 documentation available from National Semiconductor.
13  */
14 
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/kernel.h>
18 #include <linux/pci.h>
19 #include <linux/init.h>
20 #include <linux/ide.h>
21 
22 #include <asm/io.h>
23 
24 #define DRV_NAME "cs5530"
25 
26 /*
27  * Here are the standard PIO mode 0-4 timings for each "format".
28  * Format-0 uses fast data reg timings, with slower command reg timings.
29  * Format-1 uses fast timings for all registers, but won't work with all drives.
30  */
31 static unsigned int cs5530_pio_timings[2][5] = {
32  {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
33  {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}
34 };
35 
36 /*
37  * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
38  */
39 #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
40 #define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
41 
53 static void cs5530_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
54 {
55  unsigned long basereg = CS5530_BASEREG(hwif);
56  unsigned int format = (inl(basereg + 4) >> 31) & 1;
57  const u8 pio = drive->pio_mode - XFER_PIO_0;
58 
59  outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
60 }
61 
81 static u8 cs5530_udma_filter(ide_drive_t *drive)
82 {
83  ide_hwif_t *hwif = drive->hwif;
84  ide_drive_t *mate = ide_get_pair_dev(drive);
85  u16 *mateid;
86  u8 mask = hwif->ultra_mask;
87 
88  if (mate == NULL)
89  goto out;
90  mateid = mate->id;
91 
92  if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) {
93  if ((mateid[ATA_ID_FIELD_VALID] & 4) &&
94  (mateid[ATA_ID_UDMA_MODES] & 7))
95  goto out;
96  if (mateid[ATA_ID_MWDMA_MODES] & 7)
97  mask = 0;
98  }
99 out:
100  return mask;
101 }
102 
103 static void cs5530_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
104 {
105  unsigned long basereg;
106  unsigned int reg, timings = 0;
107 
108  switch (drive->dma_mode) {
109  case XFER_UDMA_0: timings = 0x00921250; break;
110  case XFER_UDMA_1: timings = 0x00911140; break;
111  case XFER_UDMA_2: timings = 0x00911030; break;
112  case XFER_MW_DMA_0: timings = 0x00077771; break;
113  case XFER_MW_DMA_1: timings = 0x00012121; break;
114  case XFER_MW_DMA_2: timings = 0x00002020; break;
115  }
116  basereg = CS5530_BASEREG(hwif);
117  reg = inl(basereg + 4); /* get drive0 config register */
118  timings |= reg & 0x80000000; /* preserve PIO format bit */
119  if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */
120  outl(timings, basereg + 4); /* write drive0 config register */
121  } else {
122  if (timings & 0x00100000)
123  reg |= 0x00100000; /* enable UDMA timings for both drives */
124  else
125  reg &= ~0x00100000; /* disable UDMA timings for both drives */
126  outl(reg, basereg + 4); /* write drive0 config register */
127  outl(timings, basereg + 12); /* write drive1 config register */
128  }
129 }
130 
138 static int init_chipset_cs5530(struct pci_dev *dev)
139 {
140  struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
141 
142  if (pci_resource_start(dev, 4) == 0)
143  return -EFAULT;
144 
145  dev = NULL;
146  while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
147  switch (dev->device) {
149  master_0 = pci_dev_get(dev);
150  break;
152  cs5530_0 = pci_dev_get(dev);
153  break;
154  }
155  }
156  if (!master_0) {
157  printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
158  goto out;
159  }
160  if (!cs5530_0) {
161  printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
162  goto out;
163  }
164 
165  /*
166  * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
167  * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
168  */
169 
170  pci_set_master(cs5530_0);
171  pci_try_set_mwi(cs5530_0);
172 
173  /*
174  * Set PCI CacheLineSize to 16-bytes:
175  * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
176  */
177 
178  pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
179 
180  /*
181  * Disable trapping of UDMA register accesses (Win98 hack):
182  * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
183  */
184 
185  pci_write_config_word(cs5530_0, 0xd0, 0x5006);
186 
187  /*
188  * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
189  * The other settings are what is necessary to get the register
190  * into a sane state for IDE DMA operation.
191  */
192 
193  pci_write_config_byte(master_0, 0x40, 0x1e);
194 
195  /*
196  * Set max PCI burst size (16-bytes seems to work best):
197  * 16bytes: set bit-1 at 0x41 (reg value of 0x16)
198  * all others: clear bit-1 at 0x41, and do:
199  * 128bytes: OR 0x00 at 0x41
200  * 256bytes: OR 0x04 at 0x41
201  * 512bytes: OR 0x08 at 0x41
202  * 1024bytes: OR 0x0c at 0x41
203  */
204 
205  pci_write_config_byte(master_0, 0x41, 0x14);
206 
207  /*
208  * These settings are necessary to get the chip
209  * into a sane state for IDE DMA operation.
210  */
211 
212  pci_write_config_byte(master_0, 0x42, 0x00);
213  pci_write_config_byte(master_0, 0x43, 0xc1);
214 
215 out:
216  pci_dev_put(master_0);
217  pci_dev_put(cs5530_0);
218  return 0;
219 }
220 
229 static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
230 {
231  unsigned long basereg;
232  u32 d0_timings;
233 
234  basereg = CS5530_BASEREG(hwif);
235  d0_timings = inl(basereg + 0);
236  if (CS5530_BAD_PIO(d0_timings))
237  outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
238  if (CS5530_BAD_PIO(inl(basereg + 8)))
239  outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
240 }
241 
242 static const struct ide_port_ops cs5530_port_ops = {
243  .set_pio_mode = cs5530_set_pio_mode,
244  .set_dma_mode = cs5530_set_dma_mode,
245  .udma_filter = cs5530_udma_filter,
246 };
247 
248 static const struct ide_port_info cs5530_chipset __devinitconst = {
249  .name = DRV_NAME,
250  .init_chipset = init_chipset_cs5530,
251  .init_hwif = init_hwif_cs5530,
252  .port_ops = &cs5530_port_ops,
253  .host_flags = IDE_HFLAG_SERIALIZE |
255  .pio_mask = ATA_PIO4,
256  .mwdma_mask = ATA_MWDMA2,
257  .udma_mask = ATA_UDMA2,
258 };
259 
260 static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
261 {
262  return ide_pci_init_one(dev, &cs5530_chipset, NULL);
263 }
264 
265 static const struct pci_device_id cs5530_pci_tbl[] = {
267  { 0, },
268 };
269 MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
270 
271 static struct pci_driver cs5530_pci_driver = {
272  .name = "CS5530 IDE",
273  .id_table = cs5530_pci_tbl,
274  .probe = cs5530_init_one,
275  .remove = ide_pci_remove,
276  .suspend = ide_pci_suspend,
277  .resume = ide_pci_resume,
278 };
279 
280 static int __init cs5530_ide_init(void)
281 {
282  return ide_pci_register_driver(&cs5530_pci_driver);
283 }
284 
285 static void __exit cs5530_ide_exit(void)
286 {
287  pci_unregister_driver(&cs5530_pci_driver);
288 }
289 
290 module_init(cs5530_ide_init);
291 module_exit(cs5530_ide_exit);
292 
293 MODULE_AUTHOR("Mark Lord");
294 MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
295 MODULE_LICENSE("GPL");