Blame view

drivers/ata/pata_efar.c 7.97 KB
669a5db41   Jeff Garzik   [libata] Add a bu...
1
2
3
  /*
   *    pata_efar.c - EFAR PIIX clone controller driver
   *
ab7716300   Alan Cox   ata: Switch all m...
4
   *	(C) 2005 Red Hat
73e2e3d0e   Bartlomiej Zolnierkiewicz   pata_efar: fix se...
5
   *	(C) 2009-2010 Bartlomiej Zolnierkiewicz
669a5db41   Jeff Garzik   [libata] Add a bu...
6
7
8
9
10
11
12
13
14
15
16
   *
   *    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   Jeff Garzik   [libata] Add a bu...
17
18
19
20
21
22
23
24
  #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   Sergei Shtylyov   pata_efar: fix PI...
25
  #define DRV_VERSION	"0.4.5"
669a5db41   Jeff Garzik   [libata] Add a bu...
26
27
  
  /**
6bfed3fb0   Alan Cox   pata_efar: suppor...
28
   *	efar_pre_reset	-	Enable bits
cc0680a58   Tejun Heo   libata-link: link...
29
   *	@link: ATA link
d4b2bab4f   Tejun Heo   libata: add deadl...
30
   *	@deadline: deadline jiffies for the operation
669a5db41   Jeff Garzik   [libata] Add a bu...
31
32
33
34
   *
   *	Perform cable detection for the EFAR ATA interface. This is
   *	different to the PIIX arrangement
   */
cc0680a58   Tejun Heo   libata-link: link...
35
  static int efar_pre_reset(struct ata_link *link, unsigned long deadline)
669a5db41   Jeff Garzik   [libata] Add a bu...
36
37
38
39
40
  {
  	static const struct pci_bits efar_enable_bits[] = {
  		{ 0x41U, 1U, 0x80UL, 0x80UL },	/* port 0 */
  		{ 0x43U, 1U, 0x80UL, 0x80UL },	/* port 1 */
  	};
cc0680a58   Tejun Heo   libata-link: link...
41
  	struct ata_port *ap = link->ap;
669a5db41   Jeff Garzik   [libata] Add a bu...
42
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
669a5db41   Jeff Garzik   [libata] Add a bu...
43

c961922b7   Alan Cox   [PATCH] libata-eh...
44
45
  	if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
  		return -ENOENT;
9363c3825   Tejun Heo   libata: rename SF...
46
  	return ata_sff_prereset(link, deadline);
669a5db41   Jeff Garzik   [libata] Add a bu...
47
48
49
  }
  
  /**
6bfed3fb0   Alan Cox   pata_efar: suppor...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
   *	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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
67
  static DEFINE_SPINLOCK(efar_lock);
6bfed3fb0   Alan Cox   pata_efar: suppor...
68
  /**
669a5db41   Jeff Garzik   [libata] Add a bu...
69
70
   *	efar_set_piomode - Initialize host controller PATA PIO timings
   *	@ap: Port whose timings we are configuring
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
71
   *	@adev: Device to program
669a5db41   Jeff Garzik   [libata] Add a bu...
72
73
74
75
76
77
78
79
80
81
82
   *
   *	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   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
83
  	unsigned int master_port = ap->port_no ? 0x42 : 0x40;
303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
84
  	unsigned long flags;
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
85
  	u16 master_data;
303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
86
  	u8 udma_enable;
669a5db41   Jeff Garzik   [libata] Add a bu...
87
88
89
90
91
92
93
94
95
96
97
98
99
  	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   Sergei Shtylyov   pata_efar: fix PI...
100
101
  	if (pio > 1)
  		control |= 1;	/* TIME */
669a5db41   Jeff Garzik   [libata] Add a bu...
102
  	if (ata_pio_need_iordy(adev))	/* PIO 3/4 require IORDY */
5f33b3bcd   Sergei Shtylyov   pata_efar: fix PI...
103
104
  		control |= 2;	/* IE */
  	/* Intel specifies that the prefetch/posting is for disk only */
669a5db41   Jeff Garzik   [libata] Add a bu...
105
  	if (adev->class == ATA_DEV_ATA)
5f33b3bcd   Sergei Shtylyov   pata_efar: fix PI...
106
  		control |= 4;	/* PPE */
669a5db41   Jeff Garzik   [libata] Add a bu...
107

303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
108
  	spin_lock_irqsave(&efar_lock, flags);
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
109
  	pci_read_config_word(dev, master_port, &master_data);
669a5db41   Jeff Garzik   [libata] Add a bu...
110

5f33b3bcd   Sergei Shtylyov   pata_efar: fix PI...
111
  	/* Set PPE, IE, and TIME as appropriate */
669a5db41   Jeff Garzik   [libata] Add a bu...
112
  	if (adev->devno == 0) {
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
113
114
115
  		master_data &= 0xCCF0;
  		master_data |= control;
  		master_data |= (timings[pio][0] << 12) |
669a5db41   Jeff Garzik   [libata] Add a bu...
116
117
118
119
  			(timings[pio][1] << 8);
  	} else {
  		int shift = 4 * ap->port_no;
  		u8 slave_data;
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
120
121
  		master_data &= 0xFF0F;
  		master_data |= (control << 4);
669a5db41   Jeff Garzik   [libata] Add a bu...
122

1967b7ff7   Joe Perches   drivers/ata/: Spe...
123
  		/* Slave timing in separate register */
669a5db41   Jeff Garzik   [libata] Add a bu...
124
  		pci_read_config_byte(dev, 0x44, &slave_data);
f79ff9264   Bartlomiej Zolnierkiewicz   pata_efar: fix wr...
125
  		slave_data &= ap->port_no ? 0x0F : 0xF0;
669a5db41   Jeff Garzik   [libata] Add a bu...
126
127
128
  		slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift;
  		pci_write_config_byte(dev, 0x44, slave_data);
  	}
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
129
130
  	master_data |= 0x4000;	/* Ensure SITRE is set */
  	pci_write_config_word(dev, master_port, master_data);
303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
131
132
133
134
135
  
  	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   Jeff Garzik   [libata] Add a bu...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  }
  
  /**
   *	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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
156
  	unsigned long flags;
669a5db41   Jeff Garzik   [libata] Add a bu...
157
158
159
160
161
162
163
164
  	u8 udma_enable;
  
  	static const	 /* ISP  RTC */
  	u8 timings[][2]	= { { 0, 0 },
  			    { 0, 0 },
  			    { 1, 0 },
  			    { 2, 1 },
  			    { 2, 3 }, };
303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
165
  	spin_lock_irqsave(&efar_lock, flags);
669a5db41   Jeff Garzik   [libata] Add a bu...
166
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
  	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   Bartlomiej Zolnierkiewicz   pata_efar: fix wr...
207
  			slave_data &= ap->port_no ? 0x0F : 0xF0;
669a5db41   Jeff Garzik   [libata] Add a bu...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  			/* 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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
223
  	spin_unlock_irqrestore(&efar_lock, flags);
669a5db41   Jeff Garzik   [libata] Add a bu...
224
225
226
  }
  
  static struct scsi_host_template efar_sht = {
68d1d07b5   Tejun Heo   libata: implement...
227
  	ATA_BMDMA_SHT(DRV_NAME),
669a5db41   Jeff Garzik   [libata] Add a bu...
228
  };
029cfd6b7   Tejun Heo   libata: implement...
229
230
231
  static struct ata_port_operations efar_ops = {
  	.inherits		= &ata_bmdma_port_ops,
  	.cable_detect		= efar_cable_detect,
669a5db41   Jeff Garzik   [libata] Add a bu...
232
233
  	.set_piomode		= efar_set_piomode,
  	.set_dmamode		= efar_set_dmamode,
a1efdaba2   Tejun Heo   libata: make rese...
234
  	.prereset		= efar_pre_reset,
669a5db41   Jeff Garzik   [libata] Add a bu...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  };
  
  
  /**
   *	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   Tejun Heo   libata: clean up ...
254
  	static const struct ata_port_info info = {
1d2808fd3   Jeff Garzik   [libata] PATA dri...
255
  		.flags		= ATA_FLAG_SLAVE_POSS,
14bdef982   Erik Inge Bolsø   [libata] convert ...
256
  		.pio_mask	= ATA_PIO4,
82563232c   Bartlomiej Zolnierkiewicz   [libata] MWDMA0 i...
257
  		.mwdma_mask	= ATA_MWDMA12_ONLY,
b2a034cf1   Erik Inge Bolsø   pata_efar: fix *d...
258
  		.udma_mask 	= ATA_UDMA4,
669a5db41   Jeff Garzik   [libata] Add a bu...
259
260
  		.port_ops	= &efar_ops,
  	};
73e2e3d0e   Bartlomiej Zolnierkiewicz   pata_efar: fix se...
261
  	const struct ata_port_info *ppi[] = { &info, &info };
669a5db41   Jeff Garzik   [libata] Add a bu...
262

06296a1e6   Joe Perches   ata: Add and use ...
263
  	ata_print_version_once(&pdev->dev, DRV_VERSION);
669a5db41   Jeff Garzik   [libata] Add a bu...
264

1c5afdf7a   Tejun Heo   libata-sff: separ...
265
266
  	return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL,
  				      ATA_HOST_PARALLEL_SCAN);
669a5db41   Jeff Garzik   [libata] Add a bu...
267
268
269
  }
  
  static const struct pci_device_id efar_pci_tbl[] = {
2d2744fc8   Jeff Garzik   [libata] PCI ID t...
270
  	{ PCI_VDEVICE(EFAR, 0x9130), },
669a5db41   Jeff Garzik   [libata] Add a bu...
271
272
273
274
275
276
277
278
  	{ }	/* 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   Bartlomiej Zolnierkiewicz   ata: use CONFIG_P...
279
  #ifdef CONFIG_PM_SLEEP
30ced0f0d   Alan Cox   [PATCH] PATA liba...
280
281
  	.suspend		= ata_pci_device_suspend,
  	.resume			= ata_pci_device_resume,
438ac6d5e   Tejun Heo   libata: add missi...
282
  #endif
669a5db41   Jeff Garzik   [libata] Add a bu...
283
  };
2fc75da0c   Axel Lin   ata: use module_p...
284
  module_pci_driver(efar_pci_driver);
669a5db41   Jeff Garzik   [libata] Add a bu...
285
286
287
288
289
290
  
  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);