1 /* 2 * pata_cs5536.c - CS5536 PATA for new ATA layer 3 * (C) 2007 Martin K. Petersen <mkp@mkp.net> 4 * (C) 2011 Bartlomiej Zolnierkiewicz 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 * Documentation: 20 * Available from AMD web site. 21 * 22 * The IDE timing registers for the CS5536 live in the Geode Machine 23 * Specific Register file and not PCI config space. Most BIOSes 24 * virtualize the PCI registers so the chip looks like a standard IDE 25 * controller. Unfortunately not all implementations get this right. 26 * In particular some have problems with unaligned accesses to the 27 * virtualized PCI registers. This driver always does full dword 28 * writes to work around the issue. Also, in case of a bad BIOS this 29 * driver can be loaded with the "msr=1" parameter which forces using 30 * the Machine Specific Registers to configure the device. 31 */ 32 33 #include <linux/kernel.h> 34 #include <linux/module.h> 35 #include <linux/pci.h> 36 #include <linux/init.h> 37 #include <linux/blkdev.h> 38 #include <linux/delay.h> 39 #include <linux/libata.h> 40 #include <scsi/scsi_host.h> 41 #include <linux/dmi.h> 42 43 #ifdef CONFIG_X86_32 44 #include <asm/msr.h> 45 static int use_msr; 46 module_param_named(msr, use_msr, int, 0644); 47 MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); 48 #else 49 #undef rdmsr /* avoid accidental MSR usage on, e.g. x86-64 */ 50 #undef wrmsr 51 #define rdmsr(x, y, z) do { } while (0) 52 #define wrmsr(x, y, z) do { } while (0) 53 #define use_msr 0 54 #endif 55 56 #define DRV_NAME "pata_cs5536" 57 #define DRV_VERSION "0.0.8" 58 59 enum { 60 MSR_IDE_CFG = 0x51300010, 61 PCI_IDE_CFG = 0x40, 62 63 CFG = 0, 64 DTC = 2, 65 CAST = 3, 66 ETC = 4, 67 68 IDE_CFG_CHANEN = (1 << 1), 69 IDE_CFG_CABLE = (1 << 17) | (1 << 16), 70 71 IDE_D0_SHIFT = 24, 72 IDE_D1_SHIFT = 16, 73 IDE_DRV_MASK = 0xff, 74 75 IDE_CAST_D0_SHIFT = 6, 76 IDE_CAST_D1_SHIFT = 4, 77 IDE_CAST_DRV_MASK = 0x3, 78 IDE_CAST_CMD_MASK = 0xff, 79 IDE_CAST_CMD_SHIFT = 24, 80 81 IDE_ETC_UDMA_MASK = 0xc0, 82 }; 83 84 /* Some Bachmann OT200 devices have a non working UDMA support due a 85 * missing resistor. 86 */ 87 static const struct dmi_system_id udma_quirk_dmi_table[] = { 88 { 89 .ident = "Bachmann electronic OT200", 90 .matches = { 91 DMI_MATCH(DMI_SYS_VENDOR, "Bachmann electronic"), 92 DMI_MATCH(DMI_PRODUCT_NAME, "OT200"), 93 DMI_MATCH(DMI_PRODUCT_VERSION, "1") 94 }, 95 }, 96 { } 97 }; 98 99 static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) 100 { 101 if (unlikely(use_msr)) { 102 u32 dummy __maybe_unused; 103 104 rdmsr(MSR_IDE_CFG + reg, *val, dummy); 105 return 0; 106 } 107 108 return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); 109 } 110 111 static int cs5536_write(struct pci_dev *pdev, int reg, int val) 112 { 113 if (unlikely(use_msr)) { 114 wrmsr(MSR_IDE_CFG + reg, val, 0); 115 return 0; 116 } 117 118 return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); 119 } 120 121 static void cs5536_program_dtc(struct ata_device *adev, u8 tim) 122 { 123 struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev); 124 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 125 u32 dtc; 126 127 cs5536_read(pdev, DTC, &dtc); 128 dtc &= ~(IDE_DRV_MASK << dshift); 129 dtc |= tim << dshift; 130 cs5536_write(pdev, DTC, dtc); 131 } 132 133 /** 134 * cs5536_cable_detect - detect cable type 135 * @ap: Port to detect on 136 * 137 * Perform cable detection for ATA66 capable cable. 138 * 139 * Returns a cable type. 140 */ 141 142 static int cs5536_cable_detect(struct ata_port *ap) 143 { 144 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 145 u32 cfg; 146 147 cs5536_read(pdev, CFG, &cfg); 148 149 if (cfg & IDE_CFG_CABLE) 150 return ATA_CBL_PATA80; 151 else 152 return ATA_CBL_PATA40; 153 } 154 155 /** 156 * cs5536_set_piomode - PIO setup 157 * @ap: ATA interface 158 * @adev: device on the interface 159 */ 160 161 static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) 162 { 163 static const u8 drv_timings[5] = { 164 0x98, 0x55, 0x32, 0x21, 0x20, 165 }; 166 167 static const u8 addr_timings[5] = { 168 0x2, 0x1, 0x0, 0x0, 0x0, 169 }; 170 171 static const u8 cmd_timings[5] = { 172 0x99, 0x92, 0x90, 0x22, 0x20, 173 }; 174 175 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 176 struct ata_device *pair = ata_dev_pair(adev); 177 int mode = adev->pio_mode - XFER_PIO_0; 178 int cmdmode = mode; 179 int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; 180 u32 cast; 181 182 if (pair) 183 cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); 184 185 cs5536_program_dtc(adev, drv_timings[mode]); 186 187 cs5536_read(pdev, CAST, &cast); 188 189 cast &= ~(IDE_CAST_DRV_MASK << cshift); 190 cast |= addr_timings[mode] << cshift; 191 192 cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); 193 cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; 194 195 cs5536_write(pdev, CAST, cast); 196 } 197 198 /** 199 * cs5536_set_dmamode - DMA timing setup 200 * @ap: ATA interface 201 * @adev: Device being configured 202 * 203 */ 204 205 static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) 206 { 207 static const u8 udma_timings[6] = { 208 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 209 }; 210 211 static const u8 mwdma_timings[3] = { 212 0x67, 0x21, 0x20, 213 }; 214 215 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 216 u32 etc; 217 int mode = adev->dma_mode; 218 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 219 220 cs5536_read(pdev, ETC, &etc); 221 222 if (mode >= XFER_UDMA_0) { 223 etc &= ~(IDE_DRV_MASK << dshift); 224 etc |= udma_timings[mode - XFER_UDMA_0] << dshift; 225 } else { /* MWDMA */ 226 etc &= ~(IDE_ETC_UDMA_MASK << dshift); 227 cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]); 228 } 229 230 cs5536_write(pdev, ETC, etc); 231 } 232 233 static struct scsi_host_template cs5536_sht = { 234 ATA_BMDMA_SHT(DRV_NAME), 235 }; 236 237 static struct ata_port_operations cs5536_port_ops = { 238 .inherits = &ata_bmdma32_port_ops, 239 .cable_detect = cs5536_cable_detect, 240 .set_piomode = cs5536_set_piomode, 241 .set_dmamode = cs5536_set_dmamode, 242 }; 243 244 /** 245 * cs5536_init_one 246 * @dev: PCI device 247 * @id: Entry in match table 248 * 249 */ 250 251 static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) 252 { 253 static const struct ata_port_info info = { 254 .flags = ATA_FLAG_SLAVE_POSS, 255 .pio_mask = ATA_PIO4, 256 .mwdma_mask = ATA_MWDMA2, 257 .udma_mask = ATA_UDMA5, 258 .port_ops = &cs5536_port_ops, 259 }; 260 261 static const struct ata_port_info no_udma_info = { 262 .flags = ATA_FLAG_SLAVE_POSS, 263 .pio_mask = ATA_PIO4, 264 .port_ops = &cs5536_port_ops, 265 }; 266 267 268 const struct ata_port_info *ppi[2]; 269 u32 cfg; 270 271 if (dmi_check_system(udma_quirk_dmi_table)) 272 ppi[0] = &no_udma_info; 273 else 274 ppi[0] = &info; 275 276 ppi[1] = &ata_dummy_port_info; 277 278 if (use_msr) 279 printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n"); 280 281 cs5536_read(dev, CFG, &cfg); 282 283 if ((cfg & IDE_CFG_CHANEN) == 0) { 284 printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); 285 return -ENODEV; 286 } 287 288 return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0); 289 } 290 291 static const struct pci_device_id cs5536[] = { 292 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, 293 { }, 294 }; 295 296 static struct pci_driver cs5536_pci_driver = { 297 .name = DRV_NAME, 298 .id_table = cs5536, 299 .probe = cs5536_init_one, 300 .remove = ata_pci_remove_one, 301 #ifdef CONFIG_PM 302 .suspend = ata_pci_device_suspend, 303 .resume = ata_pci_device_resume, 304 #endif 305 }; 306 307 module_pci_driver(cs5536_pci_driver); 308 309 MODULE_AUTHOR("Martin K. Petersen"); 310 MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); 311 MODULE_LICENSE("GPL"); 312 MODULE_DEVICE_TABLE(pci, cs5536); 313 MODULE_VERSION(DRV_VERSION); 314