1 /* 2 * pata-cs5530.c - CS5530 PATA for new ATA layer 3 * (C) 2005 Red Hat Inc 4 * 5 * based upon cs5530.c by Mark Lord. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 * Loosely based on the piix & svwks drivers. 21 * 22 * Documentation: 23 * Available from AMD web site. 24 */ 25 26 #include <linux/kernel.h> 27 #include <linux/module.h> 28 #include <linux/pci.h> 29 #include <linux/blkdev.h> 30 #include <linux/delay.h> 31 #include <scsi/scsi_host.h> 32 #include <linux/libata.h> 33 #include <linux/dmi.h> 34 35 #define DRV_NAME "pata_cs5530" 36 #define DRV_VERSION "0.7.4" 37 38 static void __iomem *cs5530_port_base(struct ata_port *ap) 39 { 40 unsigned long bmdma = (unsigned long)ap->ioaddr.bmdma_addr; 41 42 return (void __iomem *)((bmdma & ~0x0F) + 0x20 + 0x10 * ap->port_no); 43 } 44 45 /** 46 * cs5530_set_piomode - PIO setup 47 * @ap: ATA interface 48 * @adev: device on the interface 49 * 50 * Set our PIO requirements. This is fairly simple on the CS5530 51 * chips. 52 */ 53 54 static void cs5530_set_piomode(struct ata_port *ap, struct ata_device *adev) 55 { 56 static const unsigned int cs5530_pio_timings[2][5] = { 57 {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, 58 {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010} 59 }; 60 void __iomem *base = cs5530_port_base(ap); 61 u32 tuning; 62 int format; 63 64 /* Find out which table to use */ 65 tuning = ioread32(base + 0x04); 66 format = (tuning & 0x80000000UL) ? 1 : 0; 67 68 /* Now load the right timing register */ 69 if (adev->devno) 70 base += 0x08; 71 72 iowrite32(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base); 73 } 74 75 /** 76 * cs5530_set_dmamode - DMA timing setup 77 * @ap: ATA interface 78 * @adev: Device being configured 79 * 80 * We cannot mix MWDMA and UDMA without reloading timings each switch 81 * master to slave. We track the last DMA setup in order to minimise 82 * reloads. 83 */ 84 85 static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev) 86 { 87 void __iomem *base = cs5530_port_base(ap); 88 u32 tuning, timing = 0; 89 u8 reg; 90 91 /* Find out which table to use */ 92 tuning = ioread32(base + 0x04); 93 94 switch(adev->dma_mode) { 95 case XFER_UDMA_0: 96 timing = 0x00921250;break; 97 case XFER_UDMA_1: 98 timing = 0x00911140;break; 99 case XFER_UDMA_2: 100 timing = 0x00911030;break; 101 case XFER_MW_DMA_0: 102 timing = 0x00077771;break; 103 case XFER_MW_DMA_1: 104 timing = 0x00012121;break; 105 case XFER_MW_DMA_2: 106 timing = 0x00002020;break; 107 default: 108 BUG(); 109 } 110 /* Merge in the PIO format bit */ 111 timing |= (tuning & 0x80000000UL); 112 if (adev->devno == 0) /* Master */ 113 iowrite32(timing, base + 0x04); 114 else { 115 if (timing & 0x00100000) 116 tuning |= 0x00100000; /* UDMA for both */ 117 else 118 tuning &= ~0x00100000; /* MWDMA for both */ 119 iowrite32(tuning, base + 0x04); 120 iowrite32(timing, base + 0x0C); 121 } 122 123 /* Set the DMA capable bit in the BMDMA area */ 124 reg = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); 125 reg |= (1 << (5 + adev->devno)); 126 iowrite8(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); 127 128 /* Remember the last DMA setup we did */ 129 130 ap->private_data = adev; 131 } 132 133 /** 134 * cs5530_qc_issue - command issue 135 * @qc: command pending 136 * 137 * Called when the libata layer is about to issue a command. We wrap 138 * this interface so that we can load the correct ATA timings if 139 * necessary. Specifically we have a problem that there is only 140 * one MWDMA/UDMA bit. 141 */ 142 143 static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc) 144 { 145 struct ata_port *ap = qc->ap; 146 struct ata_device *adev = qc->dev; 147 struct ata_device *prev = ap->private_data; 148 149 /* See if the DMA settings could be wrong */ 150 if (ata_dma_enabled(adev) && adev != prev && prev != NULL) { 151 /* Maybe, but do the channels match MWDMA/UDMA ? */ 152 if ((ata_using_udma(adev) && !ata_using_udma(prev)) || 153 (ata_using_udma(prev) && !ata_using_udma(adev))) 154 /* Switch the mode bits */ 155 cs5530_set_dmamode(ap, adev); 156 } 157 158 return ata_bmdma_qc_issue(qc); 159 } 160 161 static struct scsi_host_template cs5530_sht = { 162 ATA_BMDMA_SHT(DRV_NAME), 163 .sg_tablesize = LIBATA_DUMB_MAX_PRD, 164 }; 165 166 static struct ata_port_operations cs5530_port_ops = { 167 .inherits = &ata_bmdma_port_ops, 168 169 .qc_prep = ata_bmdma_dumb_qc_prep, 170 .qc_issue = cs5530_qc_issue, 171 172 .cable_detect = ata_cable_40wire, 173 .set_piomode = cs5530_set_piomode, 174 .set_dmamode = cs5530_set_dmamode, 175 }; 176 177 static const struct dmi_system_id palmax_dmi_table[] = { 178 { 179 .ident = "Palmax PD1100", 180 .matches = { 181 DMI_MATCH(DMI_SYS_VENDOR, "Cyrix"), 182 DMI_MATCH(DMI_PRODUCT_NAME, "Caddis"), 183 }, 184 }, 185 { } 186 }; 187 188 static int cs5530_is_palmax(void) 189 { 190 if (dmi_check_system(palmax_dmi_table)) { 191 printk(KERN_INFO "Palmax PD1100: Disabling DMA on docking port.\n"); 192 return 1; 193 } 194 return 0; 195 } 196 197 198 /** 199 * cs5530_init_chip - Chipset init 200 * 201 * Perform the chip initialisation work that is shared between both 202 * setup and resume paths 203 */ 204 205 static int cs5530_init_chip(void) 206 { 207 struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL; 208 209 while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { 210 switch (dev->device) { 211 case PCI_DEVICE_ID_CYRIX_PCI_MASTER: 212 master_0 = pci_dev_get(dev); 213 break; 214 case PCI_DEVICE_ID_CYRIX_5530_LEGACY: 215 cs5530_0 = pci_dev_get(dev); 216 break; 217 } 218 } 219 if (!master_0) { 220 printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n"); 221 goto fail_put; 222 } 223 if (!cs5530_0) { 224 printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n"); 225 goto fail_put; 226 } 227 228 pci_set_master(cs5530_0); 229 pci_try_set_mwi(cs5530_0); 230 231 /* 232 * Set PCI CacheLineSize to 16-bytes: 233 * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 234 * 235 * Note: This value is constant because the 5530 is only a Geode companion 236 */ 237 238 pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); 239 240 /* 241 * Disable trapping of UDMA register accesses (Win98 hack): 242 * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 243 */ 244 245 pci_write_config_word(cs5530_0, 0xd0, 0x5006); 246 247 /* 248 * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: 249 * The other settings are what is necessary to get the register 250 * into a sane state for IDE DMA operation. 251 */ 252 253 pci_write_config_byte(master_0, 0x40, 0x1e); 254 255 /* 256 * Set max PCI burst size (16-bytes seems to work best): 257 * 16bytes: set bit-1 at 0x41 (reg value of 0x16) 258 * all others: clear bit-1 at 0x41, and do: 259 * 128bytes: OR 0x00 at 0x41 260 * 256bytes: OR 0x04 at 0x41 261 * 512bytes: OR 0x08 at 0x41 262 * 1024bytes: OR 0x0c at 0x41 263 */ 264 265 pci_write_config_byte(master_0, 0x41, 0x14); 266 267 /* 268 * These settings are necessary to get the chip 269 * into a sane state for IDE DMA operation. 270 */ 271 272 pci_write_config_byte(master_0, 0x42, 0x00); 273 pci_write_config_byte(master_0, 0x43, 0xc1); 274 275 pci_dev_put(master_0); 276 pci_dev_put(cs5530_0); 277 return 0; 278 fail_put: 279 pci_dev_put(master_0); 280 pci_dev_put(cs5530_0); 281 return -ENODEV; 282 } 283 284 /** 285 * cs5530_init_one - Initialise a CS5530 286 * @dev: PCI device 287 * @id: Entry in match table 288 * 289 * Install a driver for the newly found CS5530 companion chip. Most of 290 * this is just housekeeping. We have to set the chip up correctly and 291 * turn off various bits of emulation magic. 292 */ 293 294 static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 295 { 296 static const struct ata_port_info info = { 297 .flags = ATA_FLAG_SLAVE_POSS, 298 .pio_mask = ATA_PIO4, 299 .mwdma_mask = ATA_MWDMA2, 300 .udma_mask = ATA_UDMA2, 301 .port_ops = &cs5530_port_ops 302 }; 303 /* The docking connector doesn't do UDMA, and it seems not MWDMA */ 304 static const struct ata_port_info info_palmax_secondary = { 305 .flags = ATA_FLAG_SLAVE_POSS, 306 .pio_mask = ATA_PIO4, 307 .port_ops = &cs5530_port_ops 308 }; 309 const struct ata_port_info *ppi[] = { &info, NULL }; 310 int rc; 311 312 rc = pcim_enable_device(pdev); 313 if (rc) 314 return rc; 315 316 /* Chip initialisation */ 317 if (cs5530_init_chip()) 318 return -ENODEV; 319 320 if (cs5530_is_palmax()) 321 ppi[1] = &info_palmax_secondary; 322 323 /* Now kick off ATA set up */ 324 return ata_pci_bmdma_init_one(pdev, ppi, &cs5530_sht, NULL, 0); 325 } 326 327 #ifdef CONFIG_PM_SLEEP 328 static int cs5530_reinit_one(struct pci_dev *pdev) 329 { 330 struct ata_host *host = pci_get_drvdata(pdev); 331 int rc; 332 333 rc = ata_pci_device_do_resume(pdev); 334 if (rc) 335 return rc; 336 337 /* If we fail on resume we are doomed */ 338 if (cs5530_init_chip()) 339 return -EIO; 340 341 ata_host_resume(host); 342 return 0; 343 } 344 #endif /* CONFIG_PM_SLEEP */ 345 346 static const struct pci_device_id cs5530[] = { 347 { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, 348 349 { }, 350 }; 351 352 static struct pci_driver cs5530_pci_driver = { 353 .name = DRV_NAME, 354 .id_table = cs5530, 355 .probe = cs5530_init_one, 356 .remove = ata_pci_remove_one, 357 #ifdef CONFIG_PM_SLEEP 358 .suspend = ata_pci_device_suspend, 359 .resume = cs5530_reinit_one, 360 #endif 361 }; 362 363 module_pci_driver(cs5530_pci_driver); 364 365 MODULE_AUTHOR("Alan Cox"); 366 MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530"); 367 MODULE_LICENSE("GPL"); 368 MODULE_DEVICE_TABLE(pci, cs5530); 369 MODULE_VERSION(DRV_VERSION); 370