Blame view

drivers/ide/cy82c693.c 6.29 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
   *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
   *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
0ab3d8b32   Bartlomiej Zolnierkiewicz   cy82c693: fix PCI...
5
   *  Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
   *
   * CYPRESS CY82C693 chipset IDE controller
   *
   * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/pci.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
  #include <linux/ide.h>
  #include <linux/init.h>
  
  #include <asm/io.h>
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
18
  #define DRV_NAME "cy82c693"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   *	NOTE: the value for busmaster timeout is tricky and I got it by
   *	trial and error!  By using a to low value will cause DMA timeouts
   *	and drop IDE performance, and by using a to high value will cause
   *	audio playback to scatter.
   *	If you know a better value or how to calc it, please let me know.
   */
  
  /* twice the value written in cy82c693ub datasheet */
  #define BUSMASTER_TIMEOUT	0x50
  /*
   * the value above was tested on my machine and it seems to work okay
   */
  
  /* here are the offset definitions for the registers */
  #define CY82_IDE_CMDREG		0x04
  #define CY82_IDE_ADDRSETUP	0x48
  #define CY82_IDE_MASTER_IOR	0x4C
  #define CY82_IDE_MASTER_IOW	0x4D
  #define CY82_IDE_SLAVE_IOR	0x4E
  #define CY82_IDE_SLAVE_IOW	0x4F
  #define CY82_IDE_MASTER_8BIT	0x50
  #define CY82_IDE_SLAVE_8BIT	0x51
  
  #define CY82_INDEX_PORT		0x22
  #define CY82_DATA_PORT		0x23
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
  #define CY82_INDEX_CHANNEL0	0x30
  #define CY82_INDEX_CHANNEL1	0x31
  #define CY82_INDEX_TIMEOUT	0x32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
  /*
   * set DMA mode a specific channel for CY82C693
   */
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
51
  static void cy82c693_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  {
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
53
  	const u8 mode = drive->dma_mode;
8704de8f2   Bartlomiej Zolnierkiewicz   cy82c693: add ->s...
54
  	u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

8704de8f2   Bartlomiej Zolnierkiewicz   cy82c693: add ->s...
56
  	index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

8704de8f2   Bartlomiej Zolnierkiewicz   cy82c693: add ->s...
58
  	data = (mode & 3) | (single << 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59

0ecdca26e   Bartlomiej Zolnierkiewicz   ide: use PIO/MMIO...
60
61
  	outb(index, CY82_INDEX_PORT);
  	outb(data, CY82_DATA_PORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

175f354b7   Paolo Ciarrocchi   IDE: Coding Style...
63
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  	 * note: below we set the value for Bus Master IDE TimeOut Register
25985edce   Lucas De Marchi   Fix common misspe...
65
  	 * I'm not absolutely sure what this does, but it solved my problem
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
  	 * with IDE DMA and sound, so I now can play sound and work with
  	 * my IDE driver at the same time :-)
  	 *
  	 * If you know the correct (best) value for this register please
  	 * let me know - ASK
  	 */
  
  	data = BUSMASTER_TIMEOUT;
0ecdca26e   Bartlomiej Zolnierkiewicz   ide: use PIO/MMIO...
74
75
  	outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
  	outb(data, CY82_DATA_PORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  }
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
77
  static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
79
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
80
81
  	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
  	const unsigned long T = 1000000 / bus_speed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  	unsigned int addrCtrl;
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
83
84
  	struct ide_timing t;
  	u8 time_16, time_8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  
  	/* select primary or secondary channel */
0ab3d8b32   Bartlomiej Zolnierkiewicz   cy82c693: fix PCI...
87
  	if (drive->dn > 1) {  /* drive is on the secondary channel */
652aa1629   Alan Cox   [PATCH] IDE: more...
88
  		dev = pci_get_slot(dev->bus, dev->devfn+1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
95
96
  		if (!dev) {
  			printk(KERN_ERR "%s: tune_drive: "
  				"Cannot find secondary interface!
  ",
  				drive->name);
  			return;
  		}
  	}
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
97
  	ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
98
99
100
101
102
  
  	time_16 = clamp_val(t.recover - 1, 0, 15) |
  		  (clamp_val(t.active - 1, 0, 15) << 4);
  	time_8 = clamp_val(t.act8b - 1, 0, 15) |
  		 (clamp_val(t.rec8b - 1, 0, 15) << 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
  
  	/* now let's write  the clocks registers */
123995b97   Bartlomiej Zolnierkiewicz   ide: use 'drive->...
105
  	if ((drive->dn & 1) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
  		/*
  		 * set master drive
  		 * address setup control register
  		 * is 32 bit !!!
175f354b7   Paolo Ciarrocchi   IDE: Coding Style...
110
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
175f354b7   Paolo Ciarrocchi   IDE: Coding Style...
112

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  		addrCtrl &= (~0xF);
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
114
  		addrCtrl |= clamp_val(t.setup - 1, 0, 15);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
  		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
  
  		/* now let's set the remaining registers */
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
118
119
120
  		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, time_16);
  		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, time_16);
  		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, time_8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
  	} else {
  		/*
  		 * set slave drive
  		 * address setup control register
  		 * is 32 bit !!!
175f354b7   Paolo Ciarrocchi   IDE: Coding Style...
126
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
  		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
  
  		addrCtrl &= (~0xF0);
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
130
  		addrCtrl |= (clamp_val(t.setup - 1, 0, 15) << 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
  
  		/* now let's set the remaining registers */
4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
134
135
136
  		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, time_16);
  		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
  		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
175f354b7   Paolo Ciarrocchi   IDE: Coding Style...
137
  	}
0ab3d8b32   Bartlomiej Zolnierkiewicz   cy82c693: fix PCI...
138
  	if (drive->dn > 1)
0302899e1   Julia Lawall   drivers/ide/cy82c...
139
  		pci_dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
141
  static void init_iops_cy82c693(ide_hwif_t *hwif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  {
f32d26ae2   Bartlomiej Zolnierkiewicz   cy82c693: fix bui...
143
  	static ide_hwif_t *primary;
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
144
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
f32d26ae2   Bartlomiej Zolnierkiewicz   cy82c693: fix bui...
145

36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
146
  	if (PCI_FUNC(dev->devfn) == 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
  		primary = hwif;
  	else {
  		hwif->mate = primary;
  		hwif->channel = 1;
  	}
  }
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
153
154
155
156
  static const struct ide_port_ops cy82c693_port_ops = {
  	.set_pio_mode		= cy82c693_set_pio_mode,
  	.set_dma_mode		= cy82c693_set_dma_mode,
  };
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
157
  static const struct ide_port_info cy82c693_chipset = {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
158
  	.name		= DRV_NAME,
7b77d864a   Bartlomiej Zolnierkiewicz   ide: remove ide_p...
159
  	.init_iops	= init_iops_cy82c693,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
160
  	.port_ops	= &cy82c693_port_ops,
951784b66   Bartlomiej Zolnierkiewicz   ide: remove IDE_H...
161
  	.host_flags	= IDE_HFLAG_SINGLE,
4099d1432   Bartlomiej Zolnierkiewicz   ide: add PIO masks
162
  	.pio_mask	= ATA_PIO4,
8704de8f2   Bartlomiej Zolnierkiewicz   cy82c693: add ->s...
163
164
  	.swdma_mask	= ATA_SWDMA2,
  	.mwdma_mask	= ATA_MWDMA2,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  };
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
166
167
  static int cy82c693_init_one(struct pci_dev *dev,
  			     const struct pci_device_id *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
173
  	struct pci_dev *dev2;
  	int ret = -ENODEV;
  
  	/* CY82C693 is more than only a IDE controller.
  	   Function 1 is primary IDE channel, function 2 - secondary. */
175f354b7   Paolo Ciarrocchi   IDE: Coding Style...
174
  	if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  	    PCI_FUNC(dev->devfn) == 1) {
652aa1629   Alan Cox   [PATCH] IDE: more...
176
  		dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
177
  		ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
cd68841b8   Bartlomiej Zolnierkiewicz   cy82c693: add ->r...
178
179
  		if (ret)
  			pci_dev_put(dev2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
  	}
  	return ret;
  }
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
183
  static void cy82c693_remove(struct pci_dev *dev)
cd68841b8   Bartlomiej Zolnierkiewicz   cy82c693: add ->r...
184
185
186
187
188
189
190
  {
  	struct ide_host *host = pci_get_drvdata(dev);
  	struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
  
  	ide_pci_remove(dev);
  	pci_dev_put(dev2);
  }
9cbcc5e3c   Bartlomiej Zolnierkiewicz   ide: use PCI_VDEV...
191
192
  static const struct pci_device_id cy82c693_pci_tbl[] = {
  	{ PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
  	{ 0, },
  };
  MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
196
  static struct pci_driver cy82c693_pci_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
  	.name		= "Cypress_IDE",
  	.id_table	= cy82c693_pci_tbl,
  	.probe		= cy82c693_init_one,
fe31edc8a   Greg Kroah-Hartman   Drivers: ide: rem...
200
  	.remove		= cy82c693_remove,
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
201
202
  	.suspend	= ide_pci_suspend,
  	.resume		= ide_pci_resume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  };
82ab1eece   Bartlomiej Zolnierkiewicz   ide: add missing ...
204
  static int __init cy82c693_ide_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
206
  	return ide_pci_register_driver(&cy82c693_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  }
cd68841b8   Bartlomiej Zolnierkiewicz   cy82c693: add ->r...
208
209
  static void __exit cy82c693_ide_exit(void)
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
210
  	pci_unregister_driver(&cy82c693_pci_driver);
cd68841b8   Bartlomiej Zolnierkiewicz   cy82c693: add ->r...
211
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  module_init(cy82c693_ide_init);
cd68841b8   Bartlomiej Zolnierkiewicz   cy82c693: add ->r...
213
  module_exit(cy82c693_ide_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

4d6b32894   Bartlomiej Zolnierkiewicz   cy82c693: fix PIO...
215
  MODULE_AUTHOR("Andreas Krebs, Andre Hedrick, Bartlomiej Zolnierkiewicz");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
  MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
  MODULE_LICENSE("GPL");