aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2007-03-06 05:38:11 -0500
committerJeff Garzik <jeff@garzik.org>2007-04-28 14:15:55 -0400
commitb2248dac07cf057e4af3ec970e7d36a09f44fac8 (patch)
tree4a9dbabfcf18981ec433475852016c0d5943bd15 /drivers
parentbe0d18dff5fae83845801929f297977c10ab99ad (diff)
pata_cmd640: CMD640 PCI support
Support for the PCI CMD640 (not VLB) Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/Kconfig10
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/pata_cmd640.c298
3 files changed, 309 insertions, 0 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 7bdbe5a914d0..1410907d1ed2 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -209,6 +209,16 @@ config PATA_ATIIXP
209 209
210 If unsure, say N. 210 If unsure, say N.
211 211
212config PATA_CMD640_PCI
213 tristate "CMD640 PCI PATA support (Very Experimental)"
214 depends on PCI && EXPERIMENTAL
215 help
216 This option enables support for the CMD640 PCI IDE
217 interface chip. Only the primary channel is currently
218 supported.
219
220 If unsure, say N.
221
212config PATA_CMD64X 222config PATA_CMD64X
213 tristate "CMD64x PATA support (Very Experimental)" 223 tristate "CMD64x PATA support (Very Experimental)"
214 depends on PCI&& EXPERIMENTAL 224 depends on PCI&& EXPERIMENTAL
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 13d7397e0008..b7055e302650 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_PATA_ALI) += pata_ali.o
22obj-$(CONFIG_PATA_AMD) += pata_amd.o 22obj-$(CONFIG_PATA_AMD) += pata_amd.o
23obj-$(CONFIG_PATA_ARTOP) += pata_artop.o 23obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
24obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o 24obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
25obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o
25obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o 26obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
26obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o 27obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
27obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o 28obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
new file mode 100644
index 000000000000..4d01d4692412
--- /dev/null
+++ b/drivers/ata/pata_cmd640.c
@@ -0,0 +1,298 @@
1/*
2 * pata_cmd640.c - CMD640 PCI PATA for new ATA layer
3 * (C) 2007 Red Hat Inc
4 * Alan Cox <alan@redhat.com>
5 *
6 * Based upon
7 * linux/drivers/ide/pci/cmd640.c Version 1.02 Sep 01, 1996
8 *
9 * Copyright (C) 1995-1996 Linus Torvalds & authors (see driver)
10 *
11 * This drives only the PCI version of the controller. If you have a
12 * VLB one then we have enough docs to support it but you can write
13 * your own code.
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/pci.h>
19#include <linux/init.h>
20#include <linux/blkdev.h>
21#include <linux/delay.h>
22#include <scsi/scsi_host.h>
23#include <linux/libata.h>
24
25#define DRV_NAME "pata_cmd640"
26#define DRV_VERSION "0.0.3"
27
28struct cmd640_reg {
29 int last;
30 u8 reg58[ATA_MAX_DEVICES];
31};
32
33enum {
34 CFR = 0x50,
35 CNTRL = 0x51,
36 CMDTIM = 0x52,
37 ARTIM0 = 0x53,
38 DRWTIM0 = 0x54,
39 ARTIM23 = 0x57,
40 DRWTIM23 = 0x58,
41 BRST = 0x59
42};
43
44/**
45 * cmd640_set_piomode - set initial PIO mode data
46 * @adev: ATA device
47 *
48 * Called to do the PIO mode setup.
49 */
50
51static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
52{
53 struct cmd640_reg *timing = ap->private_data;
54 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
55 struct ata_timing t;
56 const unsigned long T = 1000000 / 33;
57 const u8 setup_data[] = { 0x40, 0x40, 0x40, 0x80, 0x00 };
58 u8 reg;
59 int arttim = ARTIM0 + 2 * adev->devno;
60 struct ata_device *pair = ata_dev_pair(adev);
61
62 if (ata_timing_compute(adev, adev->pio_mode, &t, T, 0) < 0) {
63 printk(KERN_ERR DRV_NAME ": mode computation failed.\n");
64 return;
65 }
66
67 /* The second channel has shared timings and the setup timing is
68 messy to switch to merge it for worst case */
69 if (ap->port_no && pair) {
70 struct ata_timing p;
71 ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
72 ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP);
73 }
74
75 /* Make the timings fit */
76 if (t.recover > 16) {
77 t.active += t.recover - 16;
78 t.recover = 16;
79 }
80 if (t.active > 16)
81 t.active = 16;
82
83 /* Now convert the clocks into values we can actually stuff into
84 the chip */
85
86 if (t.recover > 1)
87 t.recover--; /* 640B only */
88 else
89 t.recover = 15;
90
91 if (t.setup > 4)
92 t.setup = 0xC0;
93 else
94 t.setup = setup_data[t.setup];
95
96 if (ap->port_no == 0) {
97 t.active &= 0x0F; /* 0 = 16 */
98
99 /* Load setup timing */
100 pci_read_config_byte(pdev, arttim, &reg);
101 reg &= 0x3F;
102 reg |= t.setup;
103 pci_write_config_byte(pdev, arttim, reg);
104
105 /* Load active/recovery */
106 pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
107 } else {
108 /* Save the shared timings for channel, they will be loaded
109 by qc_issue_prot. Reloading the setup time is expensive
110 so we keep a merged one loaded */
111 pci_read_config_byte(pdev, ARTIM23, &reg);
112 reg &= 0x3F;
113 reg |= t.setup;
114 pci_write_config_byte(pdev, ARTIM23, reg);
115 timing->reg58[adev->devno] = (t.active << 4) | t.recover;
116 }
117}
118
119
120/**
121 * cmd640_qc_issue_prot - command preparation hook
122 * @qc: Command to be issued
123 *
124 * Channel 1 has shared timings. We must reprogram the
125 * clock each drive 2/3 switch we do.
126 */
127
128static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
129{
130 struct ata_port *ap = qc->ap;
131 struct ata_device *adev = qc->dev;
132 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
133 struct cmd640_reg *timing = ap->private_data;
134
135 if (ap->port_no != 0 && adev->devno != timing->last) {
136 pci_write_config_byte(pdev, DRWTIM23, timing->reg58[adev->devno]);
137 timing->last = adev->devno;
138 }
139 return ata_qc_issue_prot(qc);
140}
141
142/**
143 * cmd640_port_start - port setup
144 * @ap: ATA port being set up
145 *
146 * The CMD640 needs to maintain private data structures so we
147 * allocate space here.
148 */
149
150static int cmd640_port_start(struct ata_port *ap)
151{
152 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
153 struct cmd640_reg *timing;
154
155 int ret = ata_port_start(ap);
156 if (ret < 0)
157 return ret;
158
159 timing = devm_kzalloc(&pdev->dev, sizeof(struct cmd640_reg), GFP_KERNEL);
160 if (timing == NULL)
161 return -ENOMEM;
162 timing->last = -1; /* Force a load */
163 ap->private_data = timing;
164 return ret;
165}
166
167static struct scsi_host_template cmd640_sht = {
168 .module = THIS_MODULE,
169 .name = DRV_NAME,
170 .ioctl = ata_scsi_ioctl,
171 .queuecommand = ata_scsi_queuecmd,
172 .can_queue = ATA_DEF_QUEUE,
173 .this_id = ATA_SHT_THIS_ID,
174 .sg_tablesize = LIBATA_MAX_PRD,
175 .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
176 .emulated = ATA_SHT_EMULATED,
177 .use_clustering = ATA_SHT_USE_CLUSTERING,
178 .proc_name = DRV_NAME,
179 .dma_boundary = ATA_DMA_BOUNDARY,
180 .slave_configure = ata_scsi_slave_config,
181 .slave_destroy = ata_scsi_slave_destroy,
182 .bios_param = ata_std_bios_param,
183 .resume = ata_scsi_device_resume,
184 .suspend = ata_scsi_device_suspend,
185};
186
187static struct ata_port_operations cmd640_port_ops = {
188 .port_disable = ata_port_disable,
189 .set_piomode = cmd640_set_piomode,
190 .mode_filter = ata_pci_default_filter,
191 .tf_load = ata_tf_load,
192 .tf_read = ata_tf_read,
193 .check_status = ata_check_status,
194 .exec_command = ata_exec_command,
195 .dev_select = ata_std_dev_select,
196
197 .freeze = ata_bmdma_freeze,
198 .thaw = ata_bmdma_thaw,
199 .error_handler = ata_bmdma_error_handler,
200 .post_internal_cmd = ata_bmdma_post_internal_cmd,
201 .cable_detect = ata_cable_40wire,
202
203 .bmdma_setup = ata_bmdma_setup,
204 .bmdma_start = ata_bmdma_start,
205 .bmdma_stop = ata_bmdma_stop,
206 .bmdma_status = ata_bmdma_status,
207
208 .qc_prep = ata_qc_prep,
209 .qc_issue = cmd640_qc_issue_prot,
210
211 /* In theory this is not needed once we kill the prefetcher */
212 .data_xfer = ata_data_xfer_noirq,
213
214 .irq_handler = ata_interrupt,
215 .irq_clear = ata_bmdma_irq_clear,
216 .irq_on = ata_irq_on,
217 .irq_ack = ata_irq_ack,
218
219 .port_start = cmd640_port_start,
220};
221
222static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
223{
224 u8 r;
225 u8 ctrl;
226
227 static struct ata_port_info info = {
228 .sht = &cmd640_sht,
229 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
230 .pio_mask = 0x1f,
231 .port_ops = &cmd640_port_ops
232 };
233
234 static struct ata_port_info *port_info[2] = { &info, &info };
235
236 /* CMD640 detected, commiserations */
237 pci_write_config_byte(pdev, 0x5C, 0x00);
238 /* Get version info */
239 pci_read_config_byte(pdev, CFR, &r);
240 /* PIO0 command cycles */
241 pci_write_config_byte(pdev, CMDTIM, 0);
242 /* 512 byte bursts (sector) */
243 pci_write_config_byte(pdev, BRST, 0x40);
244 /*
245 * A reporter a long time ago
246 * Had problems with the data fifo
247 * So don't run the risk
248 * Of putting crap on the disk
249 * For its better just to go slow
250 */
251 /* Do channel 0 */
252 pci_read_config_byte(pdev, CNTRL, &ctrl);
253 pci_write_config_byte(pdev, CNTRL, ctrl | 0xC0);
254 /* Ditto for channel 1 */
255 pci_read_config_byte(pdev, ARTIM23, &ctrl);
256 ctrl |= 0x0C;
257 pci_write_config_byte(pdev, ARTIM23, ctrl);
258
259 return ata_pci_init_one(pdev, port_info, 2);
260}
261
262static int cmd640_reinit_one(struct pci_dev *pdev)
263{
264 return ata_pci_device_resume(pdev);
265}
266
267static const struct pci_device_id cmd640[] = {
268 { PCI_VDEVICE(CMD, 0x640), 0 },
269 { },
270};
271
272static struct pci_driver cmd640_pci_driver = {
273 .name = DRV_NAME,
274 .id_table = cmd640,
275 .probe = cmd640_init_one,
276 .remove = ata_pci_remove_one,
277 .suspend = ata_pci_device_suspend,
278 .resume = cmd640_reinit_one,
279};
280
281static int __init cmd640_init(void)
282{
283 return pci_register_driver(&cmd640_pci_driver);
284}
285
286static void __exit cmd640_exit(void)
287{
288 pci_unregister_driver(&cmd640_pci_driver);
289}
290
291MODULE_AUTHOR("Alan Cox");
292MODULE_DESCRIPTION("low-level driver for CMD640 PATA controllers");
293MODULE_LICENSE("GPL");
294MODULE_DEVICE_TABLE(pci, cmd640);
295MODULE_VERSION(DRV_VERSION);
296
297module_init(cmd640_init);
298module_exit(cmd640_exit);