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/blkdev.h> 37 #include <linux/delay.h> 38 #include <linux/libata.h> 39 #include <scsi/scsi_host.h> 40 #include <linux/dmi.h> 41 42 #ifdef CONFIG_X86_32 43 #include <asm/msr.h> 44 static int use_msr; 45 module_param_named(msr, use_msr, int, 0644); 46 MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); 47 #else 48 #undef rdmsr /* avoid accidental MSR usage on, e.g. x86-64 */ 49 #undef wrmsr 50 #define rdmsr(x, y, z) do { } while (0) 51 #define wrmsr(x, y, z) do { } while (0) 52 #define use_msr 0 53 #endif 54 55 #define DRV_NAME "pata_cs5536" 56 #define DRV_VERSION "0.0.8" 57 58 enum { 59 MSR_IDE_CFG = 0x51300010, 60 PCI_IDE_CFG = 0x40, 61 62 CFG = 0, 63 DTC = 2, 64 CAST = 3, 65 ETC = 4, 66 67 IDE_CFG_CHANEN = (1 << 1), 68 IDE_CFG_CABLE = (1 << 17) | (1 << 16), 69 70 IDE_D0_SHIFT = 24, 71 IDE_D1_SHIFT = 16, 72 IDE_DRV_MASK = 0xff, 73 74 IDE_CAST_D0_SHIFT = 6, 75 IDE_CAST_D1_SHIFT = 4, 76 IDE_CAST_DRV_MASK = 0x3, 77 IDE_CAST_CMD_MASK = 0xff, 78 IDE_CAST_CMD_SHIFT = 24, 79 80 IDE_ETC_UDMA_MASK = 0xc0, 81 }; 82 83 /* Some Bachmann OT200 devices have a non working UDMA support due a 84 * missing resistor. 85 */ 86 static const struct dmi_system_id udma_quirk_dmi_table[] = { 87 { 88 .ident = "Bachmann electronic OT200", 89 .matches = { 90 DMI_MATCH(DMI_SYS_VENDOR, "Bachmann electronic"), 91 DMI_MATCH(DMI_PRODUCT_NAME, "OT200"), 92 DMI_MATCH(DMI_PRODUCT_VERSION, "1") 93 }, 94 }, 95 { } 96 }; 97 98 static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) 99 { 100 if (unlikely(use_msr)) { 101 u32 dummy __maybe_unused; 102 103 rdmsr(MSR_IDE_CFG + reg, *val, dummy); 104 return 0; 105 } 106 107 return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); 108 } 109 110 static int cs5536_write(struct pci_dev *pdev, int reg, int val) 111 { 112 if (unlikely(use_msr)) { 113 wrmsr(MSR_IDE_CFG + reg, val, 0); 114 return 0; 115 } 116 117 return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); 118 } 119 120 static void cs5536_program_dtc(struct ata_device *adev, u8 tim) 121 { 122 struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev); 123 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 124 u32 dtc; 125 126 cs5536_read(pdev, DTC, &dtc); 127 dtc &= ~(IDE_DRV_MASK << dshift); 128 dtc |= tim << dshift; 129 cs5536_write(pdev, DTC, dtc); 130 } 131 132 /** 133 * cs5536_cable_detect - detect cable type 134 * @ap: Port to detect on 135 * 136 * Perform cable detection for ATA66 capable cable. 137 * 138 * Returns a cable type. 139 */ 140 141 static int cs5536_cable_detect(struct ata_port *ap) 142 { 143 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 144 u32 cfg; 145 146 cs5536_read(pdev, CFG, &cfg); 147 148 if (cfg & IDE_CFG_CABLE) 149 return ATA_CBL_PATA80; 150 else 151 return ATA_CBL_PATA40; 152 } 153 154 /** 155 * cs5536_set_piomode - PIO setup 156 * @ap: ATA interface 157 * @adev: device on the interface 158 */ 159 160 static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) 161 { 162 static const u8 drv_timings[5] = { 163 0x98, 0x55, 0x32, 0x21, 0x20, 164 }; 165 166 static const u8 addr_timings[5] = { 167 0x2, 0x1, 0x0, 0x0, 0x0, 168 }; 169 170 static const u8 cmd_timings[5] = { 171 0x99, 0x92, 0x90, 0x22, 0x20, 172 }; 173 174 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 175 struct ata_device *pair = ata_dev_pair(adev); 176 int mode = adev->pio_mode - XFER_PIO_0; 177 int cmdmode = mode; 178 int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; 179 u32 cast; 180 181 if (pair) 182 cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); 183 184 cs5536_program_dtc(adev, drv_timings[mode]); 185 186 cs5536_read(pdev, CAST, &cast); 187 188 cast &= ~(IDE_CAST_DRV_MASK << cshift); 189 cast |= addr_timings[mode] << cshift; 190 191 cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); 192 cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; 193 194 cs5536_write(pdev, CAST, cast); 195 } 196 197 /** 198 * cs5536_set_dmamode - DMA timing setup 199 * @ap: ATA interface 200 * @adev: Device being configured 201 * 202 */ 203 204 static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) 205 { 206 static const u8 udma_timings[6] = { 207 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 208 }; 209 210 static const u8 mwdma_timings[3] = { 211 0x67, 0x21, 0x20, 212 }; 213 214 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 215 u32 etc; 216 int mode = adev->dma_mode; 217 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 218 219 cs5536_read(pdev, ETC, &etc); 220 221 if (mode >= XFER_UDMA_0) { 222 etc &= ~(IDE_DRV_MASK << dshift); 223 etc |= udma_timings[mode - XFER_UDMA_0] << dshift; 224 } else { /* MWDMA */ 225 etc &= ~(IDE_ETC_UDMA_MASK << dshift); 226 cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]); 227 } 228 229 cs5536_write(pdev, ETC, etc); 230 } 231 232 static struct scsi_host_template cs5536_sht = { 233 ATA_BMDMA_SHT(DRV_NAME), 234 }; 235 236 static struct ata_port_operations cs5536_port_ops = { 237 .inherits = &ata_bmdma32_port_ops, 238 .cable_detect = cs5536_cable_detect, 239 .set_piomode = cs5536_set_piomode, 240 .set_dmamode = cs5536_set_dmamode, 241 }; 242 243 /** 244 * cs5536_init_one 245 * @dev: PCI device 246 * @id: Entry in match table 247 * 248 */ 249 250 static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) 251 { 252 static const struct ata_port_info info = { 253 .flags = ATA_FLAG_SLAVE_POSS, 254 .pio_mask = ATA_PIO4, 255 .mwdma_mask = ATA_MWDMA2, 256 .udma_mask = ATA_UDMA5, 257 .port_ops = &cs5536_port_ops, 258 }; 259 260 static const struct ata_port_info no_udma_info = { 261 .flags = ATA_FLAG_SLAVE_POSS, 262 .pio_mask = ATA_PIO4, 263 .port_ops = &cs5536_port_ops, 264 }; 265 266 267 const struct ata_port_info *ppi[2]; 268 u32 cfg; 269 270 if (dmi_check_system(udma_quirk_dmi_table)) 271 ppi[0] = &no_udma_info; 272 else 273 ppi[0] = &info; 274 275 ppi[1] = &ata_dummy_port_info; 276 277 if (use_msr) 278 printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n"); 279 280 cs5536_read(dev, CFG, &cfg); 281 282 if ((cfg & IDE_CFG_CHANEN) == 0) { 283 printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); 284 return -ENODEV; 285 } 286 287 return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0); 288 } 289 290 static const struct pci_device_id cs5536[] = { 291 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, 292 { }, 293 }; 294 295 static struct pci_driver cs5536_pci_driver = { 296 .name = DRV_NAME, 297 .id_table = cs5536, 298 .probe = cs5536_init_one, 299 .remove = ata_pci_remove_one, 300 #ifdef CONFIG_PM_SLEEP 301 .suspend = ata_pci_device_suspend, 302 .resume = ata_pci_device_resume, 303 #endif 304 }; 305 306 module_pci_driver(cs5536_pci_driver); 307 308 MODULE_AUTHOR("Martin K. Petersen"); 309 MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); 310 MODULE_LICENSE("GPL"); 311 MODULE_DEVICE_TABLE(pci, cs5536); 312 MODULE_VERSION(DRV_VERSION); 313