1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer 4 * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator 5 * Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz 6 * 7 * CYPRESS CY82C693 chipset IDE controller 8 * 9 * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. 10 */ 11 12#include <linux/module.h> 13#include <linux/types.h> 14#include <linux/pci.h> 15#include <linux/ide.h> 16#include <linux/init.h> 17 18#include <asm/io.h> 19 20#define DRV_NAME "cy82c693" 21 22/* 23 * NOTE: the value for busmaster timeout is tricky and I got it by 24 * trial and error! By using a to low value will cause DMA timeouts 25 * and drop IDE performance, and by using a to high value will cause 26 * audio playback to scatter. 27 * If you know a better value or how to calc it, please let me know. 28 */ 29 30/* twice the value written in cy82c693ub datasheet */ 31#define BUSMASTER_TIMEOUT 0x50 32/* 33 * the value above was tested on my machine and it seems to work okay 34 */ 35 36/* here are the offset definitions for the registers */ 37#define CY82_IDE_CMDREG 0x04 38#define CY82_IDE_ADDRSETUP 0x48 39#define CY82_IDE_MASTER_IOR 0x4C 40#define CY82_IDE_MASTER_IOW 0x4D 41#define CY82_IDE_SLAVE_IOR 0x4E 42#define CY82_IDE_SLAVE_IOW 0x4F 43#define CY82_IDE_MASTER_8BIT 0x50 44#define CY82_IDE_SLAVE_8BIT 0x51 45 46#define CY82_INDEX_PORT 0x22 47#define CY82_DATA_PORT 0x23 48 49#define CY82_INDEX_CHANNEL0 0x30 50#define CY82_INDEX_CHANNEL1 0x31 51#define CY82_INDEX_TIMEOUT 0x32 52 53/* 54 * set DMA mode a specific channel for CY82C693 55 */ 56 57static void cy82c693_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) 58{ 59 const u8 mode = drive->dma_mode; 60 u8 single = (mode & 0x10) >> 4, index = 0, data = 0; 61 62 index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0; 63 64 data = (mode & 3) | (single << 2); 65 66 outb(index, CY82_INDEX_PORT); 67 outb(data, CY82_DATA_PORT); 68 69 /* 70 * note: below we set the value for Bus Master IDE TimeOut Register 71 * I'm not absolutely sure what this does, but it solved my problem 72 * with IDE DMA and sound, so I now can play sound and work with 73 * my IDE driver at the same time :-) 74 * 75 * If you know the correct (best) value for this register please 76 * let me know - ASK 77 */ 78 79 data = BUSMASTER_TIMEOUT; 80 outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); 81 outb(data, CY82_DATA_PORT); 82} 83 84static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 85{ 86 struct pci_dev *dev = to_pci_dev(hwif->dev); 87 int bus_speed = ide_pci_clk ? ide_pci_clk : 33; 88 const unsigned long T = 1000000 / bus_speed; 89 unsigned int addrCtrl; 90 struct ide_timing t; 91 u8 time_16, time_8; 92 93 /* select primary or secondary channel */ 94 if (drive->dn > 1) { /* drive is on the secondary channel */ 95 dev = pci_get_slot(dev->bus, dev->devfn+1); 96 if (!dev) { 97 printk(KERN_ERR "%s: tune_drive: " 98 "Cannot find secondary interface!\n", 99 drive->name); 100 return; 101 } 102 } 103 104 ide_timing_compute(drive, drive->pio_mode, &t, T, 1); 105 106 time_16 = clamp_val(t.recover - 1, 0, 15) | 107 (clamp_val(t.active - 1, 0, 15) << 4); 108 time_8 = clamp_val(t.act8b - 1, 0, 15) | 109 (clamp_val(t.rec8b - 1, 0, 15) << 4); 110 111 /* now let's write the clocks registers */ 112 if ((drive->dn & 1) == 0) { 113 /* 114 * set master drive 115 * address setup control register 116 * is 32 bit !!! 117 */ 118 pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); 119 120 addrCtrl &= (~0xF); 121 addrCtrl |= clamp_val(t.setup - 1, 0, 15); 122 pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); 123 124 /* now let's set the remaining registers */ 125 pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, time_16); 126 pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, time_16); 127 pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, time_8); 128 } else { 129 /* 130 * set slave drive 131 * address setup control register 132 * is 32 bit !!! 133 */ 134 pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); 135 136 addrCtrl &= (~0xF0); 137 addrCtrl |= (clamp_val(t.setup - 1, 0, 15) << 4); 138 pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); 139 140 /* now let's set the remaining registers */ 141 pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, time_16); 142 pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16); 143 pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8); 144 } 145 if (drive->dn > 1) 146 pci_dev_put(dev); 147} 148 149static void init_iops_cy82c693(ide_hwif_t *hwif) 150{ 151 static ide_hwif_t *primary; 152 struct pci_dev *dev = to_pci_dev(hwif->dev); 153 154 if (PCI_FUNC(dev->devfn) == 1) 155 primary = hwif; 156 else { 157 hwif->mate = primary; 158 hwif->channel = 1; 159 } 160} 161 162static const struct ide_port_ops cy82c693_port_ops = { 163 .set_pio_mode = cy82c693_set_pio_mode, 164 .set_dma_mode = cy82c693_set_dma_mode, 165}; 166 167static const struct ide_port_info cy82c693_chipset = { 168 .name = DRV_NAME, 169 .init_iops = init_iops_cy82c693, 170 .port_ops = &cy82c693_port_ops, 171 .host_flags = IDE_HFLAG_SINGLE, 172 .pio_mask = ATA_PIO4, 173 .swdma_mask = ATA_SWDMA2, 174 .mwdma_mask = ATA_MWDMA2, 175}; 176 177static int cy82c693_init_one(struct pci_dev *dev, 178 const struct pci_device_id *id) 179{ 180 struct pci_dev *dev2; 181 int ret = -ENODEV; 182 183 /* CY82C693 is more than only a IDE controller. 184 Function 1 is primary IDE channel, function 2 - secondary. */ 185 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && 186 PCI_FUNC(dev->devfn) == 1) { 187 dev2 = pci_get_slot(dev->bus, dev->devfn + 1); 188 ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL); 189 if (ret) 190 pci_dev_put(dev2); 191 } 192 return ret; 193} 194 195static void cy82c693_remove(struct pci_dev *dev) 196{ 197 struct ide_host *host = pci_get_drvdata(dev); 198 struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; 199 200 ide_pci_remove(dev); 201 pci_dev_put(dev2); 202} 203 204static const struct pci_device_id cy82c693_pci_tbl[] = { 205 { PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 }, 206 { 0, }, 207}; 208MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); 209 210static struct pci_driver cy82c693_pci_driver = { 211 .name = "Cypress_IDE", 212 .id_table = cy82c693_pci_tbl, 213 .probe = cy82c693_init_one, 214 .remove = cy82c693_remove, 215 .suspend = ide_pci_suspend, 216 .resume = ide_pci_resume, 217}; 218 219static int __init cy82c693_ide_init(void) 220{ 221 return ide_pci_register_driver(&cy82c693_pci_driver); 222} 223 224static void __exit cy82c693_ide_exit(void) 225{ 226 pci_unregister_driver(&cy82c693_pci_driver); 227} 228 229module_init(cy82c693_ide_init); 230module_exit(cy82c693_ide_exit); 231 232MODULE_AUTHOR("Andreas Krebs, Andre Hedrick, Bartlomiej Zolnierkiewicz"); 233MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE"); 234MODULE_LICENSE("GPL"); 235