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 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 static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) 84 { 85 if (unlikely(use_msr)) { 86 u32 dummy __maybe_unused; 87 88 rdmsr(MSR_IDE_CFG + reg, *val, dummy); 89 return 0; 90 } 91 92 return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); 93 } 94 95 static int cs5536_write(struct pci_dev *pdev, int reg, int val) 96 { 97 if (unlikely(use_msr)) { 98 wrmsr(MSR_IDE_CFG + reg, val, 0); 99 return 0; 100 } 101 102 return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); 103 } 104 105 static void cs5536_program_dtc(struct ata_device *adev, u8 tim) 106 { 107 struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev); 108 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 109 u32 dtc; 110 111 cs5536_read(pdev, DTC, &dtc); 112 dtc &= ~(IDE_DRV_MASK << dshift); 113 dtc |= tim << dshift; 114 cs5536_write(pdev, DTC, dtc); 115 } 116 117 /** 118 * cs5536_cable_detect - detect cable type 119 * @ap: Port to detect on 120 * 121 * Perform cable detection for ATA66 capable cable. 122 * 123 * Returns a cable type. 124 */ 125 126 static int cs5536_cable_detect(struct ata_port *ap) 127 { 128 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 129 u32 cfg; 130 131 cs5536_read(pdev, CFG, &cfg); 132 133 if (cfg & IDE_CFG_CABLE) 134 return ATA_CBL_PATA80; 135 else 136 return ATA_CBL_PATA40; 137 } 138 139 /** 140 * cs5536_set_piomode - PIO setup 141 * @ap: ATA interface 142 * @adev: device on the interface 143 */ 144 145 static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) 146 { 147 static const u8 drv_timings[5] = { 148 0x98, 0x55, 0x32, 0x21, 0x20, 149 }; 150 151 static const u8 addr_timings[5] = { 152 0x2, 0x1, 0x0, 0x0, 0x0, 153 }; 154 155 static const u8 cmd_timings[5] = { 156 0x99, 0x92, 0x90, 0x22, 0x20, 157 }; 158 159 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 160 struct ata_device *pair = ata_dev_pair(adev); 161 int mode = adev->pio_mode - XFER_PIO_0; 162 int cmdmode = mode; 163 int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; 164 u32 cast; 165 166 if (pair) 167 cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); 168 169 cs5536_program_dtc(adev, drv_timings[mode]); 170 171 cs5536_read(pdev, CAST, &cast); 172 173 cast &= ~(IDE_CAST_DRV_MASK << cshift); 174 cast |= addr_timings[mode] << cshift; 175 176 cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); 177 cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; 178 179 cs5536_write(pdev, CAST, cast); 180 } 181 182 /** 183 * cs5536_set_dmamode - DMA timing setup 184 * @ap: ATA interface 185 * @adev: Device being configured 186 * 187 */ 188 189 static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) 190 { 191 static const u8 udma_timings[6] = { 192 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 193 }; 194 195 static const u8 mwdma_timings[3] = { 196 0x67, 0x21, 0x20, 197 }; 198 199 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 200 u32 etc; 201 int mode = adev->dma_mode; 202 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 203 204 cs5536_read(pdev, ETC, &etc); 205 206 if (mode >= XFER_UDMA_0) { 207 etc &= ~(IDE_DRV_MASK << dshift); 208 etc |= udma_timings[mode - XFER_UDMA_0] << dshift; 209 } else { /* MWDMA */ 210 etc &= ~(IDE_ETC_UDMA_MASK << dshift); 211 cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]); 212 } 213 214 cs5536_write(pdev, ETC, etc); 215 } 216 217 static struct scsi_host_template cs5536_sht = { 218 ATA_BMDMA_SHT(DRV_NAME), 219 }; 220 221 static struct ata_port_operations cs5536_port_ops = { 222 .inherits = &ata_bmdma32_port_ops, 223 .cable_detect = cs5536_cable_detect, 224 .set_piomode = cs5536_set_piomode, 225 .set_dmamode = cs5536_set_dmamode, 226 }; 227 228 /** 229 * cs5536_init_one 230 * @dev: PCI device 231 * @id: Entry in match table 232 * 233 */ 234 235 static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) 236 { 237 static const struct ata_port_info info = { 238 .flags = ATA_FLAG_SLAVE_POSS, 239 .pio_mask = ATA_PIO4, 240 .mwdma_mask = ATA_MWDMA2, 241 .udma_mask = ATA_UDMA5, 242 .port_ops = &cs5536_port_ops, 243 }; 244 245 const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; 246 u32 cfg; 247 248 if (use_msr) 249 printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n"); 250 251 cs5536_read(dev, CFG, &cfg); 252 253 if ((cfg & IDE_CFG_CHANEN) == 0) { 254 printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); 255 return -ENODEV; 256 } 257 258 return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0); 259 } 260 261 static const struct pci_device_id cs5536[] = { 262 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, 263 { }, 264 }; 265 266 static struct pci_driver cs5536_pci_driver = { 267 .name = DRV_NAME, 268 .id_table = cs5536, 269 .probe = cs5536_init_one, 270 .remove = ata_pci_remove_one, 271 #ifdef CONFIG_PM 272 .suspend = ata_pci_device_suspend, 273 .resume = ata_pci_device_resume, 274 #endif 275 }; 276 277 module_pci_driver(cs5536_pci_driver); 278 279 MODULE_AUTHOR("Martin K. Petersen"); 280 MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); 281 MODULE_LICENSE("GPL"); 282 MODULE_DEVICE_TABLE(pci, cs5536); 283 MODULE_VERSION(DRV_VERSION); 284