Blame view

drivers/ata/pata_hpt3x3.c 7.46 KB
669a5db41   Jeff Garzik   [libata] Add a bu...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   *	pata_hpt3x3		-	HPT3x3 driver
   *	(c) Copyright 2005-2006 Red Hat
   *
   *	Was pata_hpt34x but the naming was confusing as it supported the
   *	343 and 363 so it has been renamed.
   *
   *	Based on:
   *	linux/drivers/ide/pci/hpt34x.c		Version 0.40	Sept 10, 2002
   *	Copyright (C) 1998-2000	Andre Hedrick <andre@linux-ide.org>
   *
   *	May be copied or modified under the terms of the GNU General Public
   *	License
   */
85cd7251b   Jeff Garzik   [libata #pata-dri...
15

669a5db41   Jeff Garzik   [libata] Add a bu...
16
17
18
19
20
21
22
23
24
25
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <scsi/scsi_host.h>
  #include <linux/libata.h>
  
  #define DRV_NAME	"pata_hpt3x3"
978ff6db2   Alan Cox   pata_hpt3x3: Work...
26
  #define DRV_VERSION	"0.6.1"
669a5db41   Jeff Garzik   [libata] Add a bu...
27

669a5db41   Jeff Garzik   [libata] Add a bu...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  /**
   *	hpt3x3_set_piomode		-	PIO setup
   *	@ap: ATA interface
   *	@adev: device on the interface
   *
   *	Set our PIO requirements. This is fairly simple on the HPT3x3 as
   *	all we have to do is clear the MWDMA and UDMA bits then load the
   *	mode number.
   */
  
  static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	u32 r1, r2;
  	int dn = 2 * ap->port_no + adev->devno;
  
  	pci_read_config_dword(pdev, 0x44, &r1);
  	pci_read_config_dword(pdev, 0x48, &r2);
  	/* Load the PIO timing number */
  	r1 &= ~(7 << (3 * dn));
  	r1 |= (adev->pio_mode - XFER_PIO_0) << (3 * dn);
  	r2 &= ~(0x11 << dn);	/* Clear MWDMA and UDMA bits */
  
  	pci_write_config_dword(pdev, 0x44, r1);
  	pci_write_config_dword(pdev, 0x48, r2);
  }
790956e7b   Jeff Garzik   pata_hpt3x3: fix ...
54
  #if defined(CONFIG_PATA_HPT3X3_DMA)
669a5db41   Jeff Garzik   [libata] Add a bu...
55
56
57
58
59
60
61
  /**
   *	hpt3x3_set_dmamode		-	DMA timing setup
   *	@ap: ATA interface
   *	@adev: Device being configured
   *
   *	Set up the channel for MWDMA or UDMA modes. Much the same as with
   *	PIO, load the mode number and then set MWDMA or UDMA flag.
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
62
63
64
   *
   *	0x44 : bit 0-2 master mode, 3-5 slave mode, etc
   *	0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc
669a5db41   Jeff Garzik   [libata] Add a bu...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
   */
  
  static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
  {
  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
  	u32 r1, r2;
  	int dn = 2 * ap->port_no + adev->devno;
  	int mode_num = adev->dma_mode & 0x0F;
  
  	pci_read_config_dword(pdev, 0x44, &r1);
  	pci_read_config_dword(pdev, 0x48, &r2);
  	/* Load the timing number */
  	r1 &= ~(7 << (3 * dn));
  	r1 |= (mode_num << (3 * dn));
  	r2 &= ~(0x11 << dn);	/* Clear MWDMA and UDMA bits */
  
  	if (adev->dma_mode >= XFER_UDMA_0)
978ff6db2   Alan Cox   pata_hpt3x3: Work...
82
  		r2 |= (0x01 << dn);	/* Ultra mode */
669a5db41   Jeff Garzik   [libata] Add a bu...
83
  	else
978ff6db2   Alan Cox   pata_hpt3x3: Work...
84
  		r2 |= (0x10 << dn);	/* MWDMA */
669a5db41   Jeff Garzik   [libata] Add a bu...
85
86
87
88
  
  	pci_write_config_dword(pdev, 0x44, r1);
  	pci_write_config_dword(pdev, 0x48, r2);
  }
978ff6db2   Alan Cox   pata_hpt3x3: Work...
89
90
91
92
93
94
95
96
  
  /**
   *	hpt3x3_freeze		-	DMA workaround
   *	@ap: port to freeze
   *
   *	When freezing an HPT3x3 we must stop any pending DMA before
   *	writing to the control register or the chip will hang
   */
b63d39532   Jeff Garzik   [libata] pata_hpt...
97
  static void hpt3x3_freeze(struct ata_port *ap)
978ff6db2   Alan Cox   pata_hpt3x3: Work...
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  {
  	void __iomem *mmio = ap->ioaddr.bmdma_addr;
  
  	iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ ATA_DMA_START,
  			mmio + ATA_DMA_CMD);
  	ata_sff_dma_pause(ap);
  	ata_sff_freeze(ap);
  }
  
  /**
   *	hpt3x3_bmdma_setup	-	DMA workaround
   *	@qc: Queued command
   *
   *	When issuing BMDMA we must clean up the error/active bits in
   *	software on this device
   */
  
  static void hpt3x3_bmdma_setup(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	u8 r = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
  	r |= ATA_DMA_INTR | ATA_DMA_ERR;
  	iowrite8(r, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
  	return ata_bmdma_setup(qc);
  }
669a5db41   Jeff Garzik   [libata] Add a bu...
123

66e7da4e3   Alan Cox   pata_hpt3x3: majo...
124
125
126
127
128
129
130
131
132
133
134
  /**
   *	hpt3x3_atapi_dma	-	ATAPI DMA check
   *	@qc: Queued command
   *
   *	Just say no - we don't do ATAPI DMA
   */
  
  static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
  {
  	return 1;
  }
978ff6db2   Alan Cox   pata_hpt3x3: Work...
135
  #endif /* CONFIG_PATA_HPT3X3_DMA */
669a5db41   Jeff Garzik   [libata] Add a bu...
136
  static struct scsi_host_template hpt3x3_sht = {
68d1d07b5   Tejun Heo   libata: implement...
137
  	ATA_BMDMA_SHT(DRV_NAME),
669a5db41   Jeff Garzik   [libata] Add a bu...
138
139
140
  };
  
  static struct ata_port_operations hpt3x3_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
141
  	.inherits	= &ata_bmdma_port_ops,
029cfd6b7   Tejun Heo   libata: implement...
142
  	.cable_detect	= ata_cable_40wire,
669a5db41   Jeff Garzik   [libata] Add a bu...
143
  	.set_piomode	= hpt3x3_set_piomode,
790956e7b   Jeff Garzik   pata_hpt3x3: fix ...
144
145
  #if defined(CONFIG_PATA_HPT3X3_DMA)
  	.set_dmamode	= hpt3x3_set_dmamode,
978ff6db2   Alan Cox   pata_hpt3x3: Work...
146
147
148
  	.bmdma_setup	= hpt3x3_bmdma_setup,
  	.check_atapi_dma= hpt3x3_atapi_dma,
  	.freeze		= hpt3x3_freeze,
790956e7b   Jeff Garzik   pata_hpt3x3: fix ...
149
  #endif
978ff6db2   Alan Cox   pata_hpt3x3: Work...
150
  	
669a5db41   Jeff Garzik   [libata] Add a bu...
151
152
153
  };
  
  /**
aff0df059   Alan Cox   [PATCH] pata_hpt3...
154
155
156
157
158
   *	hpt3x3_init_chipset	-	chip setup
   *	@dev: PCI device
   *
   *	Perform the setup required at boot and on resume.
   */
f20b16ff7   Jeff Garzik   [libata] trim tra...
159

aff0df059   Alan Cox   [PATCH] pata_hpt3...
160
161
162
163
164
165
166
167
168
169
170
171
  static void hpt3x3_init_chipset(struct pci_dev *dev)
  {
  	u16 cmd;
  	/* Initialize the board */
  	pci_write_config_word(dev, 0x80, 0x00);
  	/* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */
  	pci_read_config_word(dev, PCI_COMMAND, &cmd);
  	if (cmd & PCI_COMMAND_MEMORY)
  		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
  	else
  		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
  }
aff0df059   Alan Cox   [PATCH] pata_hpt3...
172
  /**
669a5db41   Jeff Garzik   [libata] Add a bu...
173
   *	hpt3x3_init_one		-	Initialise an HPT343/363
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
174
   *	@pdev: PCI device
669a5db41   Jeff Garzik   [libata] Add a bu...
175
176
   *	@id: Entry in match table
   *
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
177
   *	Perform basic initialisation. We set the device up so we access all
3ad2f3fbb   Daniel Mack   tree-wide: Assort...
178
   *	ports via BAR4. This is necessary to work around errata.
669a5db41   Jeff Garzik   [libata] Add a bu...
179
   */
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
180
  static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
669a5db41   Jeff Garzik   [libata] Add a bu...
181
  {
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
182
  	static int printed_version;
1626aeb88   Tejun Heo   libata: clean up ...
183
  	static const struct ata_port_info info = {
1d2808fd3   Jeff Garzik   [libata] PATA dri...
184
  		.flags = ATA_FLAG_SLAVE_POSS,
14bdef982   Erik Inge Bolsø   [libata] convert ...
185
  		.pio_mask = ATA_PIO4,
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
186
187
  #if defined(CONFIG_PATA_HPT3X3_DMA)
  		/* Further debug needed */
14bdef982   Erik Inge Bolsø   [libata] convert ...
188
189
  		.mwdma_mask = ATA_MWDMA2,
  		.udma_mask = ATA_UDMA2,
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
190
  #endif
669a5db41   Jeff Garzik   [libata] Add a bu...
191
192
  		.port_ops = &hpt3x3_port_ops
  	};
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
193
194
195
  	/* Register offsets of taskfiles in BAR4 area */
  	static const u8 offset_cmd[2] = { 0x20, 0x28 };
  	static const u8 offset_ctl[2] = { 0x36, 0x3E };
1626aeb88   Tejun Heo   libata: clean up ...
196
  	const struct ata_port_info *ppi[] = { &info, NULL };
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  	struct ata_host *host;
  	int i, rc;
  	void __iomem *base;
  
  	hpt3x3_init_chipset(pdev);
  
  	if (!printed_version++)
  		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "
  ");
  
  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
  	if (!host)
  		return -ENOMEM;
  	/* acquire resources and fill host */
  	rc = pcim_enable_device(pdev);
  	if (rc)
  		return rc;
  
  	/* Everything is relative to BAR4 if we set up this way */
  	rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
  	if (rc == -EBUSY)
  		pcim_pin_device(pdev);
  	if (rc)
  		return rc;
  	host->iomap = pcim_iomap_table(pdev);
  	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
  	if (rc)
  		return rc;
  	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
  	if (rc)
  		return rc;
  
  	base = host->iomap[4];	/* Bus mastering base */
  
  	for (i = 0; i < host->n_ports; i++) {
cbcdd8759   Tejun Heo   libata: implement...
232
233
  		struct ata_port *ap = host->ports[i];
  		struct ata_ioports *ioaddr = &ap->ioaddr;
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
234
235
236
237
238
  
  		ioaddr->cmd_addr = base + offset_cmd[i];
  		ioaddr->altstatus_addr =
  		ioaddr->ctl_addr = base + offset_ctl[i];
  		ioaddr->scr_addr = NULL;
9363c3825   Tejun Heo   libata: rename SF...
239
  		ata_sff_std_ports(ioaddr);
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
240
  		ioaddr->bmdma_addr = base + 8 * i;
cbcdd8759   Tejun Heo   libata: implement...
241
242
243
  
  		ata_port_pbar_desc(ap, 4, -1, "ioport");
  		ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
66e7da4e3   Alan Cox   pata_hpt3x3: majo...
244
245
  	}
  	pci_set_master(pdev);
c3b288942   Tejun Heo   libata-sff: separ...
246
  	return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
9363c3825   Tejun Heo   libata: rename SF...
247
  				 IRQF_SHARED, &hpt3x3_sht);
669a5db41   Jeff Garzik   [libata] Add a bu...
248
  }
438ac6d5e   Tejun Heo   libata: add missi...
249
  #ifdef CONFIG_PM
aff0df059   Alan Cox   [PATCH] pata_hpt3...
250
251
  static int hpt3x3_reinit_one(struct pci_dev *dev)
  {
391504446   Bartlomiej Zolnierkiewicz   pata_hpt3x3: Powe...
252
253
254
255
256
257
  	struct ata_host *host = dev_get_drvdata(&dev->dev);
  	int rc;
  
  	rc = ata_pci_device_do_resume(dev);
  	if (rc)
  		return rc;
aff0df059   Alan Cox   [PATCH] pata_hpt3...
258
  	hpt3x3_init_chipset(dev);
391504446   Bartlomiej Zolnierkiewicz   pata_hpt3x3: Powe...
259
260
261
  
  	ata_host_resume(host);
  	return 0;
aff0df059   Alan Cox   [PATCH] pata_hpt3...
262
  }
438ac6d5e   Tejun Heo   libata: add missi...
263
  #endif
aff0df059   Alan Cox   [PATCH] pata_hpt3...
264

2d2744fc8   Jeff Garzik   [libata] PCI ID t...
265
266
267
268
  static const struct pci_device_id hpt3x3[] = {
  	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), },
  
  	{ },
669a5db41   Jeff Garzik   [libata] Add a bu...
269
270
271
  };
  
  static struct pci_driver hpt3x3_pci_driver = {
2d2744fc8   Jeff Garzik   [libata] PCI ID t...
272
  	.name 		= DRV_NAME,
669a5db41   Jeff Garzik   [libata] Add a bu...
273
274
  	.id_table	= hpt3x3,
  	.probe 		= hpt3x3_init_one,
aff0df059   Alan Cox   [PATCH] pata_hpt3...
275
  	.remove		= ata_pci_remove_one,
438ac6d5e   Tejun Heo   libata: add missi...
276
  #ifdef CONFIG_PM
aff0df059   Alan Cox   [PATCH] pata_hpt3...
277
278
  	.suspend	= ata_pci_device_suspend,
  	.resume		= hpt3x3_reinit_one,
438ac6d5e   Tejun Heo   libata: add missi...
279
  #endif
669a5db41   Jeff Garzik   [libata] Add a bu...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  };
  
  static int __init hpt3x3_init(void)
  {
  	return pci_register_driver(&hpt3x3_pci_driver);
  }
  
  
  static void __exit hpt3x3_exit(void)
  {
  	pci_unregister_driver(&hpt3x3_pci_driver);
  }
  
  
  MODULE_AUTHOR("Alan Cox");
  MODULE_DESCRIPTION("low-level driver for the Highpoint HPT343/363");
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(pci, hpt3x3);
  MODULE_VERSION(DRV_VERSION);
  
  module_init(hpt3x3_init);
b63d39532   Jeff Garzik   [libata] pata_hpt...
301
  module_exit(hpt3x3_exit);