Blame view

drivers/ata/pata_ixp4xx_cf.c 5.38 KB
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
1
2
  /*
   * ixp4xx PATA/Compact Flash driver
5d4c51f6b   Alessandro Zummo   [libata] pata_ixp...
3
   * Copyright (C) 2006-07 Tower Technologies
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
4
5
6
7
8
   * Author: Alessandro Zummo <a.zummo@towertech.it>
   *
   * An ATA driver to handle a Compact Flash connected
   * to the ixp4xx expansion bus in TrueIDE mode. The CF
   * must have it chip selects connected to two CS lines
5d4c51f6b   Alessandro Zummo   [libata] pata_ixp...
9
10
11
   * on the ixp4xx. In the irq is not available, you might
   * want to modify both this driver and libata to run in
   * polling mode.
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/libata.h>
  #include <linux/irq.h>
  #include <linux/platform_device.h>
  #include <scsi/scsi_host.h>
  
  #define DRV_NAME	"pata_ixp4xx_cf"
5d4c51f6b   Alessandro Zummo   [libata] pata_ixp...
27
  #define DRV_VERSION	"0.2"
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
28

0260731f0   Tejun Heo   libata-link: link...
29
  static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
30
  {
f58229f80   Tejun Heo   libata-link: impl...
31
  	struct ata_device *dev;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
32

1eca4365b   Tejun Heo   libata: beef up i...
33
  	ata_for_each_dev(dev, link, ENABLED) {
a9a79dfec   Joe Perches   ata: Convert ata_...
34
35
  		ata_dev_info(dev, "configured for PIO0
  ");
1eca4365b   Tejun Heo   libata: beef up i...
36
37
38
39
  		dev->pio_mode = XFER_PIO_0;
  		dev->xfer_mode = XFER_PIO_0;
  		dev->xfer_shift = ATA_SHIFT_PIO;
  		dev->flags |= ATA_DFLAG_PIO;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
40
  	}
b229a7b0a   Alan Cox   libata: set_mode,...
41
  	return 0;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
42
  }
55dba3120   Tejun Heo   libata: update ->...
43
44
  static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
  				unsigned char *buf, unsigned int buflen, int rw)
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
45
46
47
48
  {
  	unsigned int i;
  	unsigned int words = buflen >> 1;
  	u16 *buf16 = (u16 *) buf;
55dba3120   Tejun Heo   libata: update ->...
49
  	struct ata_port *ap = dev->link->ap;
59f998802   Jeff Garzik   [libata] drivers:...
50
  	void __iomem *mmio = ap->ioaddr.data_addr;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
51
52
53
54
55
56
57
58
59
  	struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
  
  	/* set the expansion bus in 16bit mode and restore
  	 * 8 bit mode after the transaction.
  	 */
  	*data->cs0_cfg &= ~(0x01);
  	udelay(100);
  
  	/* Transfer multiple of 2 bytes */
55dba3120   Tejun Heo   libata: update ->...
60
  	if (rw == READ)
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
61
62
  		for (i = 0; i < words; i++)
  			buf16[i] = readw(mmio);
55dba3120   Tejun Heo   libata: update ->...
63
64
65
  	else
  		for (i = 0; i < words; i++)
  			writew(buf16[i], mmio);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
66
67
68
69
70
  
  	/* Transfer trailing 1 byte, if any. */
  	if (unlikely(buflen & 0x01)) {
  		u16 align_buf[1] = { 0 };
  		unsigned char *trailing_buf = buf + buflen - 1;
55dba3120   Tejun Heo   libata: update ->...
71
  		if (rw == READ) {
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
72
73
  			align_buf[0] = readw(mmio);
  			memcpy(trailing_buf, align_buf, 1);
55dba3120   Tejun Heo   libata: update ->...
74
75
76
  		} else {
  			memcpy(align_buf, trailing_buf, 1);
  			writew(align_buf[0], mmio);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
77
  		}
55dba3120   Tejun Heo   libata: update ->...
78
  		words++;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
79
80
81
82
  	}
  
  	udelay(100);
  	*data->cs0_cfg |= 0x01;
55dba3120   Tejun Heo   libata: update ->...
83
84
  
  	return words << 1;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
85
  }
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
86
  static struct scsi_host_template ixp4xx_sht = {
68d1d07b5   Tejun Heo   libata: implement...
87
  	ATA_PIO_SHT(DRV_NAME),
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
88
89
90
  };
  
  static struct ata_port_operations ixp4xx_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
91
  	.inherits		= &ata_sff_port_ops,
5682ed33a   Tejun Heo   libata: rename SF...
92
  	.sff_data_xfer		= ixp4xx_mmio_data_xfer,
5d4c51f6b   Alessandro Zummo   [libata] pata_ixp...
93
  	.cable_detect		= ata_cable_40wire,
029cfd6b7   Tejun Heo   libata: implement...
94
  	.set_mode		= ixp4xx_set_mode,
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
95
  };
af1837480   Rod Whitby   pata_ixp4xx_cf: f...
96
  static void ixp4xx_setup_port(struct ata_port *ap,
cbcdd8759   Tejun Heo   libata: implement...
97
98
  			      struct ixp4xx_pata_data *data,
  			      unsigned long raw_cs0, unsigned long raw_cs1)
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
99
  {
af1837480   Rod Whitby   pata_ixp4xx_cf: f...
100
  	struct ata_ioports *ioaddr = &ap->ioaddr;
cbcdd8759   Tejun Heo   libata: implement...
101
102
  	unsigned long raw_cmd = raw_cs0;
  	unsigned long raw_ctl = raw_cs1 + 0x06;
0d5ff5667   Tejun Heo   libata: convert t...
103
104
105
  	ioaddr->cmd_addr	= data->cs0;
  	ioaddr->altstatus_addr	= data->cs1 + 0x06;
  	ioaddr->ctl_addr	= data->cs1 + 0x06;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
106

9363c3825   Tejun Heo   libata: rename SF...
107
  	ata_sff_std_ports(ioaddr);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
108
109
110
111
112
113
  
  #ifndef __ARMEB__
  
  	/* adjust the addresses to handle the address swizzling of the
  	 * ixp4xx in little endian mode.
  	 */
0d5ff5667   Tejun Heo   libata: convert t...
114
115
116
117
118
119
120
121
122
123
124
125
126
  	*(unsigned long *)&ioaddr->data_addr		^= 0x02;
  	*(unsigned long *)&ioaddr->cmd_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->altstatus_addr	^= 0x03;
  	*(unsigned long *)&ioaddr->ctl_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->error_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->feature_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->nsect_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->lbal_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->lbam_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->lbah_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->device_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->status_addr		^= 0x03;
  	*(unsigned long *)&ioaddr->command_addr		^= 0x03;
cbcdd8759   Tejun Heo   libata: implement...
127
128
129
  
  	raw_cmd ^= 0x03;
  	raw_ctl ^= 0x03;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
130
  #endif
cbcdd8759   Tejun Heo   libata: implement...
131
132
  
  	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", raw_cmd, raw_ctl);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
133
  }
0ec249146   Greg Kroah-Hartman   Drivers: ata: rem...
134
  static int ixp4xx_pata_probe(struct platform_device *pdev)
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
135
  {
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
136
137
  	unsigned int irq;
  	struct resource *cs0, *cs1;
5d728824e   Tejun Heo   libata: convert t...
138
139
  	struct ata_host *host;
  	struct ata_port *ap;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
140
141
142
143
144
145
146
  	struct ixp4xx_pata_data *data = pdev->dev.platform_data;
  
  	cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  
  	if (!cs0 || !cs1)
  		return -EINVAL;
5d728824e   Tejun Heo   libata: convert t...
147
148
149
150
151
152
  	/* allocate host */
  	host = ata_host_alloc(&pdev->dev, 1);
  	if (!host)
  		return -ENOMEM;
  
  	/* acquire resources and fill host */
284901a90   Yang Hongyang   dma-mapping: repl...
153
  	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
154

24dc5f33e   Tejun Heo   libata: update li...
155
156
  	data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
  	data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
157

991bf528f   Scott Thompson   drivers/ata/pata_...
158
159
  	if (!data->cs0 || !data->cs1)
  		return -ENOMEM;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
160
161
  	irq = platform_get_irq(pdev, 0);
  	if (irq)
dced35aeb   Thomas Gleixner   drivers: Final ir...
162
  		irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
163
164
165
166
  
  	/* Setup expansion bus chip selects */
  	*data->cs0_cfg = data->cs0_bits;
  	*data->cs1_cfg = data->cs1_bits;
5d728824e   Tejun Heo   libata: convert t...
167
  	ap = host->ports[0];
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
168

5d728824e   Tejun Heo   libata: convert t...
169
  	ap->ops	= &ixp4xx_port_ops;
14bdef982   Erik Inge Bolsø   [libata] convert ...
170
  	ap->pio_mask = ATA_PIO4;
9cbe056f6   Sergei Shtylyov   libata: remove AT...
171
  	ap->flags |= ATA_FLAG_NO_ATAPI;
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
172

cbcdd8759   Tejun Heo   libata: implement...
173
  	ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
174

06296a1e6   Joe Perches   ata: Add and use ...
175
  	ata_print_version_once(&pdev->dev, DRV_VERSION);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
176

5d728824e   Tejun Heo   libata: convert t...
177
  	/* activate host */
9363c3825   Tejun Heo   libata: rename SF...
178
  	return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
179
  }
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
180
181
182
183
184
185
  static struct platform_driver ixp4xx_pata_platform_driver = {
  	.driver	 = {
  		.name   = DRV_NAME,
  		.owner  = THIS_MODULE,
  	},
  	.probe		= ixp4xx_pata_probe,
58d0ff2f0   Brian Norris   pata_ixp4xx_cf: u...
186
  	.remove		= ata_platform_remove_one,
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
187
  };
99c8ea3e5   Axel Lin   SATA/PATA: conver...
188
  module_platform_driver(ixp4xx_pata_platform_driver);
0df0d0a0e   Alessandro Zummo   [libata] ARM: add...
189
190
191
192
193
  
  MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
  MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);
458622fcd   Kay Sievers   ATA/IDE: fix plat...
194
  MODULE_ALIAS("platform:" DRV_NAME);