Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.30-rc6 357 lines 10 kB view raw
1/* 2 * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer 3 * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator 4 * 5 * CYPRESS CY82C693 chipset IDE controller 6 * 7 * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. 8 * Writing the driver was quite simple, since most of the job is 9 * done by the generic pci-ide support. 10 * The hard part was finding the CY82C693's datasheet on Cypress's 11 * web page :-(. But Altavista solved this problem :-). 12 * 13 * 14 * Notes: 15 * - I recently got a 16.8G IBM DTTA, so I was able to test it with 16 * a large and fast disk - the results look great, so I'd say the 17 * driver is working fine :-) 18 * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA 19 * - this is my first linux driver, so there's probably a lot of room 20 * for optimizations and bug fixing, so feel free to do it. 21 * - if using PIO mode it's a good idea to set the PIO mode and 22 * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda 23 * - I had some problems with my IBM DHEA with PIO modes < 2 24 * (lost interrupts) ????? 25 * - first tests with DMA look okay, they seem to work, but there is a 26 * problem with sound - the BusMaster IDE TimeOut should fixed this 27 * 28 * Ancient History: 29 * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 30 * ASK@1999-01-23: v0.33 made a few minor code clean ups 31 * removed DMA clock speed setting by default 32 * added boot message 33 * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut 34 * added support to set DMA Controller Clock Speed 35 * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes 36 * on some drives. 37 * ASK@1998-10-29: v0.3 added support to set DMA modes 38 * ASK@1998-10-28: v0.2 added support to set PIO modes 39 * ASK@1998-10-27: v0.1 first version - chipset detection 40 * 41 */ 42 43#include <linux/module.h> 44#include <linux/types.h> 45#include <linux/pci.h> 46#include <linux/ide.h> 47#include <linux/init.h> 48 49#include <asm/io.h> 50 51#define DRV_NAME "cy82c693" 52 53/* 54 * The following are used to debug the driver. 55 */ 56#define CY82C693_DEBUG_INFO 0 57 58/* 59 * NOTE: the value for busmaster timeout is tricky and I got it by 60 * trial and error! By using a to low value will cause DMA timeouts 61 * and drop IDE performance, and by using a to high value will cause 62 * audio playback to scatter. 63 * If you know a better value or how to calc it, please let me know. 64 */ 65 66/* twice the value written in cy82c693ub datasheet */ 67#define BUSMASTER_TIMEOUT 0x50 68/* 69 * the value above was tested on my machine and it seems to work okay 70 */ 71 72/* here are the offset definitions for the registers */ 73#define CY82_IDE_CMDREG 0x04 74#define CY82_IDE_ADDRSETUP 0x48 75#define CY82_IDE_MASTER_IOR 0x4C 76#define CY82_IDE_MASTER_IOW 0x4D 77#define CY82_IDE_SLAVE_IOR 0x4E 78#define CY82_IDE_SLAVE_IOW 0x4F 79#define CY82_IDE_MASTER_8BIT 0x50 80#define CY82_IDE_SLAVE_8BIT 0x51 81 82#define CY82_INDEX_PORT 0x22 83#define CY82_DATA_PORT 0x23 84 85#define CY82_INDEX_CHANNEL0 0x30 86#define CY82_INDEX_CHANNEL1 0x31 87#define CY82_INDEX_TIMEOUT 0x32 88 89/* the min and max PCI bus speed in MHz - from datasheet */ 90#define CY82C963_MIN_BUS_SPEED 25 91#define CY82C963_MAX_BUS_SPEED 33 92 93/* the struct for the PIO mode timings */ 94typedef struct pio_clocks_s { 95 u8 address_time; /* Address setup (clocks) */ 96 u8 time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ 97 u8 time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ 98 u8 time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ 99} pio_clocks_t; 100 101/* 102 * calc clocks using bus_speed 103 * returns (rounded up) time in bus clocks for time in ns 104 */ 105static int calc_clk(int time, int bus_speed) 106{ 107 int clocks; 108 109 clocks = (time*bus_speed+999)/1000 - 1; 110 111 if (clocks < 0) 112 clocks = 0; 113 114 if (clocks > 0x0F) 115 clocks = 0x0F; 116 117 return clocks; 118} 119 120/* 121 * compute the values for the clock registers for PIO 122 * mode and pci_clk [MHz] speed 123 * 124 * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used 125 * for mode 3 and 4 drives 8 and 16-bit timings are the same 126 * 127 */ 128static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) 129{ 130 struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); 131 int clk1, clk2; 132 int bus_speed = ide_pci_clk ? ide_pci_clk : 33; 133 134 /* we don't check against CY82C693's min and max speed, 135 * so you can play with the idebus=xx parameter 136 */ 137 138 /* let's calc the address setup time clocks */ 139 p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed); 140 141 /* let's calc the active and recovery time clocks */ 142 clk1 = calc_clk(t->active, bus_speed); 143 144 /* calc recovery timing */ 145 clk2 = t->cycle - t->active - t->setup; 146 147 clk2 = calc_clk(clk2, bus_speed); 148 149 clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ 150 151 /* note: we use the same values for 16bit IOR and IOW 152 * those are all the same, since I don't have other 153 * timings than those from ide-lib.c 154 */ 155 156 p_pclk->time_16r = (u8)clk1; 157 p_pclk->time_16w = (u8)clk1; 158 159 /* what are good values for 8bit ?? */ 160 p_pclk->time_8 = (u8)clk1; 161} 162 163/* 164 * set DMA mode a specific channel for CY82C693 165 */ 166 167static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) 168{ 169 ide_hwif_t *hwif = drive->hwif; 170 u8 single = (mode & 0x10) >> 4, index = 0, data = 0; 171 172 index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0; 173 174 data = (mode & 3) | (single << 2); 175 176 outb(index, CY82_INDEX_PORT); 177 outb(data, CY82_DATA_PORT); 178 179#if CY82C693_DEBUG_INFO 180 printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", 181 drive->name, hwif->channel, drive->dn & 1, mode & 3, single); 182#endif /* CY82C693_DEBUG_INFO */ 183 184 /* 185 * note: below we set the value for Bus Master IDE TimeOut Register 186 * I'm not absolutly sure what this does, but it solved my problem 187 * with IDE DMA and sound, so I now can play sound and work with 188 * my IDE driver at the same time :-) 189 * 190 * If you know the correct (best) value for this register please 191 * let me know - ASK 192 */ 193 194 data = BUSMASTER_TIMEOUT; 195 outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); 196 outb(data, CY82_DATA_PORT); 197 198#if CY82C693_DEBUG_INFO 199 printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", 200 drive->name, data); 201#endif /* CY82C693_DEBUG_INFO */ 202} 203 204static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) 205{ 206 ide_hwif_t *hwif = drive->hwif; 207 struct pci_dev *dev = to_pci_dev(hwif->dev); 208 pio_clocks_t pclk; 209 unsigned int addrCtrl; 210 211 /* select primary or secondary channel */ 212 if (hwif->index > 0) { /* drive is on the secondary channel */ 213 dev = pci_get_slot(dev->bus, dev->devfn+1); 214 if (!dev) { 215 printk(KERN_ERR "%s: tune_drive: " 216 "Cannot find secondary interface!\n", 217 drive->name); 218 return; 219 } 220 } 221 222 /* let's calc the values for this PIO mode */ 223 compute_clocks(pio, &pclk); 224 225 /* now let's write the clocks registers */ 226 if ((drive->dn & 1) == 0) { 227 /* 228 * set master drive 229 * address setup control register 230 * is 32 bit !!! 231 */ 232 pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); 233 234 addrCtrl &= (~0xF); 235 addrCtrl |= (unsigned int)pclk.address_time; 236 pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); 237 238 /* now let's set the remaining registers */ 239 pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r); 240 pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); 241 pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); 242 243 addrCtrl &= 0xF; 244 } else { 245 /* 246 * set slave drive 247 * address setup control register 248 * is 32 bit !!! 249 */ 250 pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); 251 252 addrCtrl &= (~0xF0); 253 addrCtrl |= ((unsigned int)pclk.address_time<<4); 254 pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); 255 256 /* now let's set the remaining registers */ 257 pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r); 258 pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w); 259 pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8); 260 261 addrCtrl >>= 4; 262 addrCtrl &= 0xF; 263 } 264 265#if CY82C693_DEBUG_INFO 266 printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " 267 "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", 268 drive->name, hwif->channel, drive->dn & 1, 269 addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); 270#endif /* CY82C693_DEBUG_INFO */ 271} 272 273static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) 274{ 275 static ide_hwif_t *primary; 276 struct pci_dev *dev = to_pci_dev(hwif->dev); 277 278 if (PCI_FUNC(dev->devfn) == 1) 279 primary = hwif; 280 else { 281 hwif->mate = primary; 282 hwif->channel = 1; 283 } 284} 285 286static const struct ide_port_ops cy82c693_port_ops = { 287 .set_pio_mode = cy82c693_set_pio_mode, 288 .set_dma_mode = cy82c693_set_dma_mode, 289}; 290 291static const struct ide_port_info cy82c693_chipset __devinitdata = { 292 .name = DRV_NAME, 293 .init_iops = init_iops_cy82c693, 294 .port_ops = &cy82c693_port_ops, 295 .host_flags = IDE_HFLAG_SINGLE, 296 .pio_mask = ATA_PIO4, 297 .swdma_mask = ATA_SWDMA2, 298 .mwdma_mask = ATA_MWDMA2, 299}; 300 301static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id) 302{ 303 struct pci_dev *dev2; 304 int ret = -ENODEV; 305 306 /* CY82C693 is more than only a IDE controller. 307 Function 1 is primary IDE channel, function 2 - secondary. */ 308 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && 309 PCI_FUNC(dev->devfn) == 1) { 310 dev2 = pci_get_slot(dev->bus, dev->devfn + 1); 311 ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL); 312 if (ret) 313 pci_dev_put(dev2); 314 } 315 return ret; 316} 317 318static void __devexit cy82c693_remove(struct pci_dev *dev) 319{ 320 struct ide_host *host = pci_get_drvdata(dev); 321 struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; 322 323 ide_pci_remove(dev); 324 pci_dev_put(dev2); 325} 326 327static const struct pci_device_id cy82c693_pci_tbl[] = { 328 { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 }, 329 { 0, }, 330}; 331MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); 332 333static struct pci_driver cy82c693_pci_driver = { 334 .name = "Cypress_IDE", 335 .id_table = cy82c693_pci_tbl, 336 .probe = cy82c693_init_one, 337 .remove = __devexit_p(cy82c693_remove), 338 .suspend = ide_pci_suspend, 339 .resume = ide_pci_resume, 340}; 341 342static int __init cy82c693_ide_init(void) 343{ 344 return ide_pci_register_driver(&cy82c693_pci_driver); 345} 346 347static void __exit cy82c693_ide_exit(void) 348{ 349 pci_unregister_driver(&cy82c693_pci_driver); 350} 351 352module_init(cy82c693_ide_init); 353module_exit(cy82c693_ide_exit); 354 355MODULE_AUTHOR("Andreas Krebs, Andre Hedrick"); 356MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE"); 357MODULE_LICENSE("GPL");