Blame view
drivers/ata/pata_cs5520.c
7.36 KB
3e0a4e858 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
669a5db41 [libata] Add a bu... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * IDE tuning and bus mastering support for the CS5510/CS5520 * chipsets * * The CS5510/CS5520 are slightly unusual devices. Unlike the * typical IDE controllers they do bus mastering with the drive in * PIO mode and smarter silicon. * * The practical upshot of this is that we must always tune the * drive for the right PIO mode. We must also ignore all the blacklists * and the drive bus mastering DMA information. Also to confuse matters * further we can do DMA on PIO only drives. * * DMA on the 5510 also requires we disable_hlt() during DMA on early * revisions. * * *** This driver is strictly experimental *** * * (c) Copyright Red Hat Inc 2002 * |
669a5db41 [libata] Add a bu... |
22 |
* Documentation: |
25985edce Fix common misspe... |
23 |
* Not publicly available. |
669a5db41 [libata] Add a bu... |
24 25 26 27 |
*/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> |
669a5db41 [libata] Add a bu... |
28 29 30 31 32 33 |
#include <linux/blkdev.h> #include <linux/delay.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #define DRV_NAME "pata_cs5520" |
2a3103ce4 [libata] Bump dri... |
34 |
#define DRV_VERSION "0.6.6" |
669a5db41 [libata] Add a bu... |
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
struct pio_clocks { int address; int assert; int recovery; }; static const struct pio_clocks cs5520_pio_clocks[]={ {3, 6, 11}, {2, 5, 6}, {1, 4, 3}, {1, 3, 2}, {1, 2, 1} }; /** * cs5520_set_timings - program PIO timings * @ap: ATA port * @adev: ATA device * * Program the PIO mode timings for the controller according to the pio * clocking table. */ static void cs5520_set_timings(struct ata_port *ap, struct ata_device *adev, int pio) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); int slave = adev->devno; pio -= XFER_PIO_0; /* Channel command timing */ pci_write_config_byte(pdev, 0x62 + ap->port_no, (cs5520_pio_clocks[pio].recovery << 4) | (cs5520_pio_clocks[pio].assert)); /* FIXME: should these use address ? */ /* Read command timing */ pci_write_config_byte(pdev, 0x64 + 4*ap->port_no + slave, (cs5520_pio_clocks[pio].recovery << 4) | (cs5520_pio_clocks[pio].assert)); /* Write command timing */ pci_write_config_byte(pdev, 0x66 + 4*ap->port_no + slave, (cs5520_pio_clocks[pio].recovery << 4) | (cs5520_pio_clocks[pio].assert)); } /** |
669a5db41 [libata] Add a bu... |
83 84 85 86 87 |
* cs5520_set_piomode - program PIO timings * @ap: ATA port * @adev: ATA device * * Program the PIO mode timings for the controller according to the pio |
940a68de5 pata_cs5520: remo... |
88 |
* clocking table. |
669a5db41 [libata] Add a bu... |
89 90 91 92 93 94 |
*/ static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev) { cs5520_set_timings(ap, adev, adev->pio_mode); } |
669a5db41 [libata] Add a bu... |
95 |
static struct scsi_host_template cs5520_sht = { |
68d1d07b5 libata: implement... |
96 |
ATA_BMDMA_SHT(DRV_NAME), |
d26fc9551 libata: Support c... |
97 |
.sg_tablesize = LIBATA_DUMB_MAX_PRD, |
669a5db41 [libata] Add a bu... |
98 99 100 |
}; static struct ata_port_operations cs5520_port_ops = { |
029cfd6b7 libata: implement... |
101 |
.inherits = &ata_bmdma_port_ops, |
f47451c45 libata-sff: ata_s... |
102 |
.qc_prep = ata_bmdma_dumb_qc_prep, |
029cfd6b7 libata: implement... |
103 |
.cable_detect = ata_cable_40wire, |
669a5db41 [libata] Add a bu... |
104 |
.set_piomode = cs5520_set_piomode, |
669a5db41 [libata] Add a bu... |
105 |
}; |
0ec249146 Drivers: ata: rem... |
106 |
static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
669a5db41 [libata] Add a bu... |
107 |
{ |
cbcdd8759 libata: implement... |
108 109 |
static const unsigned int cmd_port[] = { 0x1F0, 0x170 }; static const unsigned int ctl_port[] = { 0x3F6, 0x376 }; |
5d728824e libata: convert t... |
110 111 |
struct ata_port_info pi = { .flags = ATA_FLAG_SLAVE_POSS, |
14bdef982 [libata] convert ... |
112 |
.pio_mask = ATA_PIO4, |
5d728824e libata: convert t... |
113 114 115 |
.port_ops = &cs5520_port_ops, }; const struct ata_port_info *ppi[2]; |
669a5db41 [libata] Add a bu... |
116 |
u8 pcicfg; |
4ca4e4396 libata annotation... |
117 |
void __iomem *iomap[5]; |
5d728824e libata: convert t... |
118 119 120 |
struct ata_host *host; struct ata_ioports *ioaddr; int i, rc; |
669a5db41 [libata] Add a bu... |
121 |
|
f08048e94 libata: PCI devic... |
122 123 124 |
rc = pcim_enable_device(pdev); if (rc) return rc; |
669a5db41 [libata] Add a bu... |
125 |
/* IDE port enable bits */ |
5d728824e libata: convert t... |
126 |
pci_read_config_byte(pdev, 0x60, &pcicfg); |
669a5db41 [libata] Add a bu... |
127 128 129 130 |
/* Check if the ATA ports are enabled */ if ((pcicfg & 3) == 0) return -ENODEV; |
5d728824e libata: convert t... |
131 132 133 134 135 |
ppi[0] = ppi[1] = &ata_dummy_port_info; if (pcicfg & 1) ppi[0] = π if (pcicfg & 2) ppi[1] = π |
669a5db41 [libata] Add a bu... |
136 |
if ((pcicfg & 0x40) == 0) { |
a44fec1fc ata: Convert dev_... |
137 138 |
dev_warn(&pdev->dev, "DMA mode disabled. Enabling. "); |
5d728824e libata: convert t... |
139 |
pci_write_config_byte(pdev, 0x60, pcicfg | 0x40); |
669a5db41 [libata] Add a bu... |
140 |
} |
5d728824e libata: convert t... |
141 142 143 144 145 |
pi.mwdma_mask = id->driver_data; host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); if (!host) return -ENOMEM; |
669a5db41 [libata] Add a bu... |
146 |
/* Perform set up for DMA */ |
094839164 PCI: Remove users... |
147 |
if (pci_enable_device_io(pdev)) { |
669a5db41 [libata] Add a bu... |
148 149 150 151 |
printk(KERN_ERR DRV_NAME ": unable to configure BAR2. "); return -ENODEV; } |
5d728824e libata: convert t... |
152 |
|
b5e555561 libata: switch re... |
153 |
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { |
669a5db41 [libata] Add a bu... |
154 155 156 157 |
printk(KERN_ERR DRV_NAME ": unable to configure DMA mask. "); return -ENODEV; } |
669a5db41 [libata] Add a bu... |
158 |
|
5d728824e libata: convert t... |
159 |
/* Map IO ports and initialize host accordingly */ |
cbcdd8759 libata: implement... |
160 161 162 163 |
iomap[0] = devm_ioport_map(&pdev->dev, cmd_port[0], 8); iomap[1] = devm_ioport_map(&pdev->dev, ctl_port[0], 1); iomap[2] = devm_ioport_map(&pdev->dev, cmd_port[1], 8); iomap[3] = devm_ioport_map(&pdev->dev, ctl_port[1], 1); |
5d728824e libata: convert t... |
164 |
iomap[4] = pcim_iomap(pdev, 2, 0); |
0d5ff5667 libata: convert t... |
165 166 167 |
if (!iomap[0] || !iomap[1] || !iomap[2] || !iomap[3] || !iomap[4]) return -ENOMEM; |
5d728824e libata: convert t... |
168 169 170 171 172 |
ioaddr = &host->ports[0]->ioaddr; ioaddr->cmd_addr = iomap[0]; ioaddr->ctl_addr = iomap[1]; ioaddr->altstatus_addr = iomap[1]; ioaddr->bmdma_addr = iomap[4]; |
9363c3825 libata: rename SF... |
173 |
ata_sff_std_ports(ioaddr); |
5d728824e libata: convert t... |
174 |
|
cbcdd8759 libata: implement... |
175 176 177 |
ata_port_desc(host->ports[0], "cmd 0x%x ctl 0x%x", cmd_port[0], ctl_port[0]); ata_port_pbar_desc(host->ports[0], 4, 0, "bmdma"); |
5d728824e libata: convert t... |
178 179 180 181 182 |
ioaddr = &host->ports[1]->ioaddr; ioaddr->cmd_addr = iomap[2]; ioaddr->ctl_addr = iomap[3]; ioaddr->altstatus_addr = iomap[3]; ioaddr->bmdma_addr = iomap[4] + 8; |
9363c3825 libata: rename SF... |
183 |
ata_sff_std_ports(ioaddr); |
5d728824e libata: convert t... |
184 |
|
cbcdd8759 libata: implement... |
185 186 187 |
ata_port_desc(host->ports[1], "cmd 0x%x ctl 0x%x", cmd_port[1], ctl_port[1]); ata_port_pbar_desc(host->ports[1], 4, 8, "bmdma"); |
5d728824e libata: convert t... |
188 189 190 191 192 193 194 195 |
/* activate the host */ pci_set_master(pdev); rc = ata_host_start(host); if (rc) return rc; for (i = 0; i < 2; i++) { static const int irq[] = { 14, 15 }; |
8c6b065b7 pata_cs5520: Fix ... |
196 |
struct ata_port *ap = host->ports[i]; |
5d728824e libata: convert t... |
197 198 199 200 201 |
if (ata_port_is_dummy(ap)) continue; rc = devm_request_irq(&pdev->dev, irq[ap->port_no], |
c3b288942 libata-sff: separ... |
202 |
ata_bmdma_interrupt, 0, DRV_NAME, host); |
5d728824e libata: convert t... |
203 204 |
if (rc) return rc; |
4031826b3 libata: fix assig... |
205 |
|
cbcdd8759 libata: implement... |
206 |
ata_port_desc(ap, "irq %d", irq[i]); |
5d728824e libata: convert t... |
207 208 209 |
} return ata_host_register(host, &cs5520_sht); |
669a5db41 [libata] Add a bu... |
210 |
} |
58eb8cd56 ata: use CONFIG_P... |
211 |
#ifdef CONFIG_PM_SLEEP |
8501120f1 [PATCH] pata_cs55... |
212 213 214 215 216 217 218 |
/** * cs5520_reinit_one - device resume * @pdev: PCI device * * Do any reconfiguration work needed by a resume from RAM. We need * to restore DMA mode support on BIOSen which disabled it */ |
f20b16ff7 [libata] trim tra... |
219 |
|
8501120f1 [PATCH] pata_cs55... |
220 221 |
static int cs5520_reinit_one(struct pci_dev *pdev) { |
0a86e1c85 ata: use pci_get_... |
222 |
struct ata_host *host = pci_get_drvdata(pdev); |
8501120f1 [PATCH] pata_cs55... |
223 |
u8 pcicfg; |
f08048e94 libata: PCI devic... |
224 225 226 227 228 |
int rc; rc = ata_pci_device_do_resume(pdev); if (rc) return rc; |
8501120f1 [PATCH] pata_cs55... |
229 230 231 |
pci_read_config_byte(pdev, 0x60, &pcicfg); if ((pcicfg & 0x40) == 0) pci_write_config_byte(pdev, 0x60, pcicfg | 0x40); |
f08048e94 libata: PCI devic... |
232 233 234 |
ata_host_resume(host); return 0; |
8501120f1 [PATCH] pata_cs55... |
235 |
} |
aa6de4942 pata_cs5520: susp... |
236 237 238 239 240 241 242 243 244 245 246 247 248 |
/** * cs5520_pci_device_suspend - device suspend * @pdev: PCI device * * We have to cut and waste bits from the standard method because * the 5520 is a bit odd and not just a pure ATA device. As a result * we must not disable it. The needed code is short and this avoids * chip specific mess in the core code. */ static int cs5520_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) { |
0a86e1c85 ata: use pci_get_... |
249 |
struct ata_host *host = pci_get_drvdata(pdev); |
aa6de4942 pata_cs5520: susp... |
250 251 252 253 254 255 256 257 258 |
int rc = 0; rc = ata_host_suspend(host, mesg); if (rc) return rc; pci_save_state(pdev); return 0; } |
58eb8cd56 ata: use CONFIG_P... |
259 |
#endif /* CONFIG_PM_SLEEP */ |
a84471fe2 [libata] Trim tra... |
260 |
|
669a5db41 [libata] Add a bu... |
261 262 |
/* For now keep DMA off. We can set it for all but A rev CS5510 once the core ATA code can handle it */ |
2d2744fc8 [libata] PCI ID t... |
263 264 265 266 267 |
static const struct pci_device_id pata_cs5520[] = { { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), }, { }, |
669a5db41 [libata] Add a bu... |
268 269 270 271 272 273 |
}; static struct pci_driver cs5520_pci_driver = { .name = DRV_NAME, .id_table = pata_cs5520, .probe = cs5520_init_one, |
2855568b1 [libata] struct p... |
274 |
.remove = ata_pci_remove_one, |
58eb8cd56 ata: use CONFIG_P... |
275 |
#ifdef CONFIG_PM_SLEEP |
aa6de4942 pata_cs5520: susp... |
276 |
.suspend = cs5520_pci_device_suspend, |
8501120f1 [PATCH] pata_cs55... |
277 |
.resume = cs5520_reinit_one, |
438ac6d5e libata: add missi... |
278 |
#endif |
669a5db41 [libata] Add a bu... |
279 |
}; |
2fc75da0c ata: use module_p... |
280 |
module_pci_driver(cs5520_pci_driver); |
669a5db41 [libata] Add a bu... |
281 282 283 284 285 286 |
MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for Cyrix CS5510/5520"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, pata_cs5520); MODULE_VERSION(DRV_VERSION); |