Blame view
drivers/ata/pata_efar.c
8.01 KB
09c434b8a treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
669a5db41 [libata] Add a bu... |
2 3 4 |
/* * pata_efar.c - EFAR PIIX clone controller driver * |
ab7716300 ata: Switch all m... |
5 |
* (C) 2005 Red Hat |
73e2e3d0e pata_efar: fix se... |
6 |
* (C) 2009-2010 Bartlomiej Zolnierkiewicz |
669a5db41 [libata] Add a bu... |
7 8 9 10 11 12 13 14 15 16 17 |
* * Some parts based on ata_piix.c by Jeff Garzik and others. * * The EFAR is a PIIX4 clone with UDMA66 support. Unlike the later * Intel ICH controllers the EFAR widened the UDMA mode register bits * and doesn't require the funky clock selection. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> |
669a5db41 [libata] Add a bu... |
18 19 20 21 22 23 24 25 |
#include <linux/blkdev.h> #include <linux/delay.h> #include <linux/device.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #include <linux/ata.h> #define DRV_NAME "pata_efar" |
5f33b3bcd pata_efar: fix PI... |
26 |
#define DRV_VERSION "0.4.5" |
669a5db41 [libata] Add a bu... |
27 28 |
/** |
6bfed3fb0 pata_efar: suppor... |
29 |
* efar_pre_reset - Enable bits |
cc0680a58 libata-link: link... |
30 |
* @link: ATA link |
d4b2bab4f libata: add deadl... |
31 |
* @deadline: deadline jiffies for the operation |
669a5db41 [libata] Add a bu... |
32 33 34 35 |
* * Perform cable detection for the EFAR ATA interface. This is * different to the PIIX arrangement */ |
cc0680a58 libata-link: link... |
36 |
static int efar_pre_reset(struct ata_link *link, unsigned long deadline) |
669a5db41 [libata] Add a bu... |
37 38 39 40 41 |
{ static const struct pci_bits efar_enable_bits[] = { { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ }; |
cc0680a58 libata-link: link... |
42 |
struct ata_port *ap = link->ap; |
669a5db41 [libata] Add a bu... |
43 |
struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
669a5db41 [libata] Add a bu... |
44 |
|
c961922b7 [PATCH] libata-eh... |
45 46 |
if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no])) return -ENOENT; |
9363c3825 libata: rename SF... |
47 |
return ata_sff_prereset(link, deadline); |
669a5db41 [libata] Add a bu... |
48 49 50 |
} /** |
6bfed3fb0 pata_efar: suppor... |
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
* efar_cable_detect - check for 40/80 pin * @ap: Port * * Perform cable detection for the EFAR ATA interface. This is * different to the PIIX arrangement */ static int efar_cable_detect(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 tmp; pci_read_config_byte(pdev, 0x47, &tmp); if (tmp & (2 >> ap->port_no)) return ATA_CBL_PATA40; return ATA_CBL_PATA80; } |
303f1a76a [libata] pata_efa... |
68 |
static DEFINE_SPINLOCK(efar_lock); |
6bfed3fb0 pata_efar: suppor... |
69 |
/** |
669a5db41 [libata] Add a bu... |
70 71 |
* efar_set_piomode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring |
a0da19149 pata_efar: fix re... |
72 |
* @adev: Device to program |
669a5db41 [libata] Add a bu... |
73 74 75 76 77 78 79 80 81 82 83 |
* * Set PIO mode for device, in host controller PCI config space. * * LOCKING: * None (inherited from caller). */ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) { unsigned int pio = adev->pio_mode - XFER_PIO_0; struct pci_dev *dev = to_pci_dev(ap->host->dev); |
a0da19149 pata_efar: fix re... |
84 |
unsigned int master_port = ap->port_no ? 0x42 : 0x40; |
303f1a76a [libata] pata_efa... |
85 |
unsigned long flags; |
a0da19149 pata_efar: fix re... |
86 |
u16 master_data; |
303f1a76a [libata] pata_efa... |
87 |
u8 udma_enable; |
669a5db41 [libata] Add a bu... |
88 89 90 91 92 93 94 95 96 97 98 99 100 |
int control = 0; /* * See Intel Document 298600-004 for the timing programing rules * for PIIX/ICH. The EFAR is a clone so very similar */ static const /* ISP RTC */ u8 timings[][2] = { { 0, 0 }, { 0, 0 }, { 1, 0 }, { 2, 1 }, { 2, 3 }, }; |
5f33b3bcd pata_efar: fix PI... |
101 102 |
if (pio > 1) control |= 1; /* TIME */ |
669a5db41 [libata] Add a bu... |
103 |
if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ |
5f33b3bcd pata_efar: fix PI... |
104 105 |
control |= 2; /* IE */ /* Intel specifies that the prefetch/posting is for disk only */ |
669a5db41 [libata] Add a bu... |
106 |
if (adev->class == ATA_DEV_ATA) |
5f33b3bcd pata_efar: fix PI... |
107 |
control |= 4; /* PPE */ |
669a5db41 [libata] Add a bu... |
108 |
|
303f1a76a [libata] pata_efa... |
109 |
spin_lock_irqsave(&efar_lock, flags); |
a0da19149 pata_efar: fix re... |
110 |
pci_read_config_word(dev, master_port, &master_data); |
669a5db41 [libata] Add a bu... |
111 |
|
5f33b3bcd pata_efar: fix PI... |
112 |
/* Set PPE, IE, and TIME as appropriate */ |
669a5db41 [libata] Add a bu... |
113 |
if (adev->devno == 0) { |
a0da19149 pata_efar: fix re... |
114 115 116 |
master_data &= 0xCCF0; master_data |= control; master_data |= (timings[pio][0] << 12) | |
669a5db41 [libata] Add a bu... |
117 118 119 120 |
(timings[pio][1] << 8); } else { int shift = 4 * ap->port_no; u8 slave_data; |
a0da19149 pata_efar: fix re... |
121 122 |
master_data &= 0xFF0F; master_data |= (control << 4); |
669a5db41 [libata] Add a bu... |
123 |
|
1967b7ff7 drivers/ata/: Spe... |
124 |
/* Slave timing in separate register */ |
669a5db41 [libata] Add a bu... |
125 |
pci_read_config_byte(dev, 0x44, &slave_data); |
f79ff9264 pata_efar: fix wr... |
126 |
slave_data &= ap->port_no ? 0x0F : 0xF0; |
669a5db41 [libata] Add a bu... |
127 128 129 |
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift; pci_write_config_byte(dev, 0x44, slave_data); } |
a0da19149 pata_efar: fix re... |
130 131 |
master_data |= 0x4000; /* Ensure SITRE is set */ pci_write_config_word(dev, master_port, master_data); |
303f1a76a [libata] pata_efa... |
132 133 134 135 136 |
pci_read_config_byte(dev, 0x48, &udma_enable); udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); pci_write_config_byte(dev, 0x48, udma_enable); spin_unlock_irqrestore(&efar_lock, flags); |
669a5db41 [libata] Add a bu... |
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
} /** * efar_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: Device to program * * Set UDMA/MWDMA mode for device, in host controller PCI config space. * * LOCKING: * None (inherited from caller). */ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) { struct pci_dev *dev = to_pci_dev(ap->host->dev); u8 master_port = ap->port_no ? 0x42 : 0x40; u16 master_data; u8 speed = adev->dma_mode; int devid = adev->devno + 2 * ap->port_no; |
303f1a76a [libata] pata_efa... |
157 |
unsigned long flags; |
669a5db41 [libata] Add a bu... |
158 159 160 161 162 163 164 165 |
u8 udma_enable; static const /* ISP RTC */ u8 timings[][2] = { { 0, 0 }, { 0, 0 }, { 1, 0 }, { 2, 1 }, { 2, 3 }, }; |
303f1a76a [libata] pata_efa... |
166 |
spin_lock_irqsave(&efar_lock, flags); |
669a5db41 [libata] Add a bu... |
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
pci_read_config_word(dev, master_port, &master_data); pci_read_config_byte(dev, 0x48, &udma_enable); if (speed >= XFER_UDMA_0) { unsigned int udma = adev->dma_mode - XFER_UDMA_0; u16 udma_timing; udma_enable |= (1 << devid); /* Load the UDMA mode number */ pci_read_config_word(dev, 0x4A, &udma_timing); udma_timing &= ~(7 << (4 * devid)); udma_timing |= udma << (4 * devid); pci_write_config_word(dev, 0x4A, udma_timing); } else { /* * MWDMA is driven by the PIO timings. We must also enable * IORDY unconditionally along with TIME1. PPE has already * been set when the PIO timing was set. */ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; unsigned int control; u8 slave_data; const unsigned int needed_pio[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 }; int pio = needed_pio[mwdma] - XFER_PIO_0; control = 3; /* IORDY|TIME1 */ /* If the drive MWDMA is faster than it can do PIO then we must force PIO into PIO0 */ if (adev->pio_mode < needed_pio[mwdma]) /* Enable DMA timing only */ control |= 8; /* PIO cycles in PIO0 */ if (adev->devno) { /* Slave */ master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ master_data |= control << 4; pci_read_config_byte(dev, 0x44, &slave_data); |
dd221f9ce pata_efar: fix wr... |
208 |
slave_data &= ap->port_no ? 0x0F : 0xF0; |
669a5db41 [libata] Add a bu... |
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
/* Load the matching timing */ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); pci_write_config_byte(dev, 0x44, slave_data); } else { /* Master */ master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY and master timing bits */ master_data |= control; master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); } udma_enable &= ~(1 << devid); pci_write_config_word(dev, master_port, master_data); } pci_write_config_byte(dev, 0x48, udma_enable); |
303f1a76a [libata] pata_efa... |
224 |
spin_unlock_irqrestore(&efar_lock, flags); |
669a5db41 [libata] Add a bu... |
225 226 227 |
} static struct scsi_host_template efar_sht = { |
68d1d07b5 libata: implement... |
228 |
ATA_BMDMA_SHT(DRV_NAME), |
669a5db41 [libata] Add a bu... |
229 |
}; |
029cfd6b7 libata: implement... |
230 231 232 |
static struct ata_port_operations efar_ops = { .inherits = &ata_bmdma_port_ops, .cable_detect = efar_cable_detect, |
669a5db41 [libata] Add a bu... |
233 234 |
.set_piomode = efar_set_piomode, .set_dmamode = efar_set_dmamode, |
a1efdaba2 libata: make rese... |
235 |
.prereset = efar_pre_reset, |
669a5db41 [libata] Add a bu... |
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
}; /** * efar_init_one - Register EFAR ATA PCI device with kernel services * @pdev: PCI device to register * @ent: Entry in efar_pci_tbl matching with @pdev * * Called from kernel PCI layer. * * LOCKING: * Inherited from PCI layer (may sleep). * * RETURNS: * Zero on success, or -ERRNO value. */ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { |
1626aeb88 libata: clean up ... |
255 |
static const struct ata_port_info info = { |
1d2808fd3 [libata] PATA dri... |
256 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982 [libata] convert ... |
257 |
.pio_mask = ATA_PIO4, |
82563232c [libata] MWDMA0 i... |
258 |
.mwdma_mask = ATA_MWDMA12_ONLY, |
b2a034cf1 pata_efar: fix *d... |
259 |
.udma_mask = ATA_UDMA4, |
669a5db41 [libata] Add a bu... |
260 261 |
.port_ops = &efar_ops, }; |
73e2e3d0e pata_efar: fix se... |
262 |
const struct ata_port_info *ppi[] = { &info, &info }; |
669a5db41 [libata] Add a bu... |
263 |
|
06296a1e6 ata: Add and use ... |
264 |
ata_print_version_once(&pdev->dev, DRV_VERSION); |
669a5db41 [libata] Add a bu... |
265 |
|
1c5afdf7a libata-sff: separ... |
266 267 |
return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL, ATA_HOST_PARALLEL_SCAN); |
669a5db41 [libata] Add a bu... |
268 269 270 |
} static const struct pci_device_id efar_pci_tbl[] = { |
2d2744fc8 [libata] PCI ID t... |
271 |
{ PCI_VDEVICE(EFAR, 0x9130), }, |
669a5db41 [libata] Add a bu... |
272 273 274 275 276 277 278 279 |
{ } /* terminate list */ }; static struct pci_driver efar_pci_driver = { .name = DRV_NAME, .id_table = efar_pci_tbl, .probe = efar_init_one, .remove = ata_pci_remove_one, |
58eb8cd56 ata: use CONFIG_P... |
280 |
#ifdef CONFIG_PM_SLEEP |
30ced0f0d [PATCH] PATA liba... |
281 282 |
.suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, |
438ac6d5e libata: add missi... |
283 |
#endif |
669a5db41 [libata] Add a bu... |
284 |
}; |
2fc75da0c ata: use module_p... |
285 |
module_pci_driver(efar_pci_driver); |
669a5db41 [libata] Add a bu... |
286 287 288 289 290 291 |
MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("SCSI low-level driver for EFAR PIIX clones"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, efar_pci_tbl); MODULE_VERSION(DRV_VERSION); |