Blame view

drivers/ata/pata_efar.c 8.01 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
669a5db41   Jeff Garzik   [libata] Add a bu...
2
3
4
  /*
   *    pata_efar.c - EFAR PIIX clone controller driver
   *
ab7716300   Alan Cox   ata: Switch all m...
5
   *	(C) 2005 Red Hat
73e2e3d0e   Bartlomiej Zolnierkiewicz   pata_efar: fix se...
6
   *	(C) 2009-2010 Bartlomiej Zolnierkiewicz
669a5db41   Jeff Garzik   [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   Jeff Garzik   [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   Sergei Shtylyov   pata_efar: fix PI...
26
  #define DRV_VERSION	"0.4.5"
669a5db41   Jeff Garzik   [libata] Add a bu...
27
28
  
  /**
6bfed3fb0   Alan Cox   pata_efar: suppor...
29
   *	efar_pre_reset	-	Enable bits
cc0680a58   Tejun Heo   libata-link: link...
30
   *	@link: ATA link
d4b2bab4f   Tejun Heo   libata: add deadl...
31
   *	@deadline: deadline jiffies for the operation
669a5db41   Jeff Garzik   [libata] Add a bu...
32
33
34
35
   *
   *	Perform cable detection for the EFAR ATA interface. This is
   *	different to the PIIX arrangement
   */
cc0680a58   Tejun Heo   libata-link: link...
36
  static int efar_pre_reset(struct ata_link *link, unsigned long deadline)
669a5db41   Jeff Garzik   [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   Tejun Heo   libata-link: link...
42
  	struct ata_port *ap = link->ap;
669a5db41   Jeff Garzik   [libata] Add a bu...
43
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
669a5db41   Jeff Garzik   [libata] Add a bu...
44

c961922b7   Alan Cox   [PATCH] libata-eh...
45
46
  	if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
  		return -ENOENT;
9363c3825   Tejun Heo   libata: rename SF...
47
  	return ata_sff_prereset(link, deadline);
669a5db41   Jeff Garzik   [libata] Add a bu...
48
49
50
  }
  
  /**
6bfed3fb0   Alan Cox   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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
68
  static DEFINE_SPINLOCK(efar_lock);
6bfed3fb0   Alan Cox   pata_efar: suppor...
69
  /**
669a5db41   Jeff Garzik   [libata] Add a bu...
70
71
   *	efar_set_piomode - Initialize host controller PATA PIO timings
   *	@ap: Port whose timings we are configuring
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
72
   *	@adev: Device to program
669a5db41   Jeff Garzik   [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   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
84
  	unsigned int master_port = ap->port_no ? 0x42 : 0x40;
303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
85
  	unsigned long flags;
a0da19149   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
86
  	u16 master_data;
303f1a76a   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
87
  	u8 udma_enable;
669a5db41   Jeff Garzik   [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   Sergei Shtylyov   pata_efar: fix PI...
101
102
  	if (pio > 1)
  		control |= 1;	/* TIME */
669a5db41   Jeff Garzik   [libata] Add a bu...
103
  	if (ata_pio_need_iordy(adev))	/* PIO 3/4 require IORDY */
5f33b3bcd   Sergei Shtylyov   pata_efar: fix PI...
104
105
  		control |= 2;	/* IE */
  	/* Intel specifies that the prefetch/posting is for disk only */
669a5db41   Jeff Garzik   [libata] Add a bu...
106
  	if (adev->class == ATA_DEV_ATA)
5f33b3bcd   Sergei Shtylyov   pata_efar: fix PI...
107
  		control |= 4;	/* PPE */
669a5db41   Jeff Garzik   [libata] Add a bu...
108

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

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

1967b7ff7   Joe Perches   drivers/ata/: Spe...
124
  		/* Slave timing in separate register */
669a5db41   Jeff Garzik   [libata] Add a bu...
125
  		pci_read_config_byte(dev, 0x44, &slave_data);
f79ff9264   Bartlomiej Zolnierkiewicz   pata_efar: fix wr...
126
  		slave_data &= ap->port_no ? 0x0F : 0xF0;
669a5db41   Jeff Garzik   [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   Bartlomiej Zolnierkiewicz   pata_efar: fix re...
130
131
  	master_data |= 0x4000;	/* Ensure SITRE is set */
  	pci_write_config_word(dev, master_port, master_data);
303f1a76a   Bartlomiej Zolnierkiewicz   [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   Jeff Garzik   [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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
157
  	unsigned long flags;
669a5db41   Jeff Garzik   [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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
166
  	spin_lock_irqsave(&efar_lock, flags);
669a5db41   Jeff Garzik   [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   Bartlomiej Zolnierkiewicz   pata_efar: fix wr...
208
  			slave_data &= ap->port_no ? 0x0F : 0xF0;
669a5db41   Jeff Garzik   [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   Bartlomiej Zolnierkiewicz   [libata] pata_efa...
224
  	spin_unlock_irqrestore(&efar_lock, flags);
669a5db41   Jeff Garzik   [libata] Add a bu...
225
226
227
  }
  
  static struct scsi_host_template efar_sht = {
68d1d07b5   Tejun Heo   libata: implement...
228
  	ATA_BMDMA_SHT(DRV_NAME),
669a5db41   Jeff Garzik   [libata] Add a bu...
229
  };
029cfd6b7   Tejun Heo   libata: implement...
230
231
232
  static struct ata_port_operations efar_ops = {
  	.inherits		= &ata_bmdma_port_ops,
  	.cable_detect		= efar_cable_detect,
669a5db41   Jeff Garzik   [libata] Add a bu...
233
234
  	.set_piomode		= efar_set_piomode,
  	.set_dmamode		= efar_set_dmamode,
a1efdaba2   Tejun Heo   libata: make rese...
235
  	.prereset		= efar_pre_reset,
669a5db41   Jeff Garzik   [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   Tejun Heo   libata: clean up ...
255
  	static const struct ata_port_info info = {
1d2808fd3   Jeff Garzik   [libata] PATA dri...
256
  		.flags		= ATA_FLAG_SLAVE_POSS,
14bdef982   Erik Inge Bolsø   [libata] convert ...
257
  		.pio_mask	= ATA_PIO4,
82563232c   Bartlomiej Zolnierkiewicz   [libata] MWDMA0 i...
258
  		.mwdma_mask	= ATA_MWDMA12_ONLY,
b2a034cf1   Erik Inge Bolsø   pata_efar: fix *d...
259
  		.udma_mask 	= ATA_UDMA4,
669a5db41   Jeff Garzik   [libata] Add a bu...
260
261
  		.port_ops	= &efar_ops,
  	};
73e2e3d0e   Bartlomiej Zolnierkiewicz   pata_efar: fix se...
262
  	const struct ata_port_info *ppi[] = { &info, &info };
669a5db41   Jeff Garzik   [libata] Add a bu...
263

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

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