Blame view

drivers/ata/pata_platform.c 7.04 KB
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
1
2
3
  /*
   * Generic platform device PATA driver
   *
f7fc0ceb4   Paul Mundt   libata: pata_plat...
4
   * Copyright (C) 2006 - 2007  Paul Mundt
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
5
6
7
   *
   * Based on pata_pcmcia:
   *
ab7716300   Alan Cox   ata: Switch all m...
8
   *   Copyright 2005-2006 Red Hat Inc, all rights reserved.
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
9
10
11
12
13
14
15
16
17
18
19
20
21
   *
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <scsi/scsi_host.h>
  #include <linux/ata.h>
  #include <linux/libata.h>
  #include <linux/platform_device.h>
0a87e3e92   Jeff Garzik   Rename: linux/pat...
22
  #include <linux/ata_platform.h>
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
23
24
  
  #define DRV_NAME "pata_platform"
f7fc0ceb4   Paul Mundt   libata: pata_plat...
25
  #define DRV_VERSION "1.2"
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
26
27
28
29
30
31
32
  
  static int pio_mask = 1;
  
  /*
   * Provide our own set_mode() as we don't want to change anything that has
   * already been configured..
   */
0260731f0   Tejun Heo   libata-link: link...
33
  static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unused)
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
34
  {
f58229f80   Tejun Heo   libata-link: impl...
35
  	struct ata_device *dev;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
36

1eca4365b   Tejun Heo   libata: beef up i...
37
38
39
40
41
  	ata_for_each_dev(dev, link, ENABLED) {
  		/* We don't really care */
  		dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
  		dev->xfer_shift = ATA_SHIFT_PIO;
  		dev->flags |= ATA_DFLAG_PIO;
a9a79dfec   Joe Perches   ata: Convert ata_...
42
43
  		ata_dev_info(dev, "configured for PIO
  ");
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
44
  	}
161c888b0   Al Viro   [PATCH] pata_plat...
45
  	return 0;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
46
  }
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
47
  static struct scsi_host_template pata_platform_sht = {
68d1d07b5   Tejun Heo   libata: implement...
48
  	ATA_PIO_SHT(DRV_NAME),
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
49
50
51
  };
  
  static struct ata_port_operations pata_platform_port_ops = {
029cfd6b7   Tejun Heo   libata: implement...
52
  	.inherits		= &ata_sff_port_ops,
5682ed33a   Tejun Heo   libata: rename SF...
53
  	.sff_data_xfer		= ata_sff_data_xfer_noirq,
029cfd6b7   Tejun Heo   libata: implement...
54
55
  	.cable_detect		= ata_cable_unknown,
  	.set_mode		= pata_platform_set_mode,
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
56
57
58
  };
  
  static void pata_platform_setup_port(struct ata_ioports *ioaddr,
cf03613e9   Anton Vorontsov   libata: pata_plat...
59
  				     unsigned int shift)
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
60
  {
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
61
  	/* Fixup the port shift for platforms that need it */
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
62
63
64
65
66
67
68
69
70
71
72
73
74
  	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << shift);
  	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << shift);
  	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
  	ioaddr->nsect_addr	= ioaddr->cmd_addr + (ATA_REG_NSECT   << shift);
  	ioaddr->lbal_addr	= ioaddr->cmd_addr + (ATA_REG_LBAL    << shift);
  	ioaddr->lbam_addr	= ioaddr->cmd_addr + (ATA_REG_LBAM    << shift);
  	ioaddr->lbah_addr	= ioaddr->cmd_addr + (ATA_REG_LBAH    << shift);
  	ioaddr->device_addr	= ioaddr->cmd_addr + (ATA_REG_DEVICE  << shift);
  	ioaddr->status_addr	= ioaddr->cmd_addr + (ATA_REG_STATUS  << shift);
  	ioaddr->command_addr	= ioaddr->cmd_addr + (ATA_REG_CMD     << shift);
  }
  
  /**
cf03613e9   Anton Vorontsov   libata: pata_plat...
75
76
77
78
79
80
81
   *	__pata_platform_probe		-	attach a platform interface
   *	@dev: device
   *	@io_res: Resource representing I/O base
   *	@ctl_res: Resource representing CTL base
   *	@irq_res: Resource representing IRQ and its flags
   *	@ioport_shift: I/O port shift
   *	@__pio_mask: PIO mask
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
82
83
84
85
   *
   *	Register a platform bus IDE interface. Such interfaces are PIO and we
   *	assume do not support IRQ sharing.
   *
f7fc0ceb4   Paul Mundt   libata: pata_plat...
86
   *	Platform devices are expected to contain at least 2 resources per port:
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
87
88
89
   *
   *		- I/O Base (IORESOURCE_IO or IORESOURCE_MEM)
   *		- CTL Base (IORESOURCE_IO or IORESOURCE_MEM)
f7fc0ceb4   Paul Mundt   libata: pata_plat...
90
91
92
   *
   *	and optionally:
   *
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
93
94
95
96
97
   *		- IRQ	   (IORESOURCE_IRQ)
   *
   *	If the base resources are both mem types, the ioremap() is handled
   *	here. For IORESOURCE_IO, it's assumed that there's no remapping
   *	necessary.
f7fc0ceb4   Paul Mundt   libata: pata_plat...
98
99
   *
   *	If no IRQ resource is present, PIO polling mode is used instead.
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
100
   */
cf03613e9   Anton Vorontsov   libata: pata_plat...
101
102
103
104
105
106
  int __devinit __pata_platform_probe(struct device *dev,
  				    struct resource *io_res,
  				    struct resource *ctl_res,
  				    struct resource *irq_res,
  				    unsigned int ioport_shift,
  				    int __pio_mask)
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
107
  {
5d728824e   Tejun Heo   libata: convert t...
108
109
  	struct ata_host *host;
  	struct ata_port *ap;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
110
  	unsigned int mmio;
cf03613e9   Anton Vorontsov   libata: pata_plat...
111
112
  	int irq = 0;
  	int irq_flags = 0;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
113
114
115
116
117
118
119
120
  
  	/*
  	 * Check for MMIO
  	 */
  	mmio = (( io_res->flags == IORESOURCE_MEM) &&
  		(ctl_res->flags == IORESOURCE_MEM));
  
  	/*
f7fc0ceb4   Paul Mundt   libata: pata_plat...
121
122
  	 * And the IRQ
  	 */
cf03613e9   Anton Vorontsov   libata: pata_plat...
123
124
125
126
  	if (irq_res && irq_res->start > 0) {
  		irq = irq_res->start;
  		irq_flags = irq_res->flags;
  	}
f7fc0ceb4   Paul Mundt   libata: pata_plat...
127
128
  
  	/*
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
129
130
  	 * Now that that's out of the way, wire up the port..
  	 */
cf03613e9   Anton Vorontsov   libata: pata_plat...
131
  	host = ata_host_alloc(dev, 1);
5d728824e   Tejun Heo   libata: convert t...
132
133
134
135
136
  	if (!host)
  		return -ENOMEM;
  	ap = host->ports[0];
  
  	ap->ops = &pata_platform_port_ops;
cf03613e9   Anton Vorontsov   libata: pata_plat...
137
  	ap->pio_mask = __pio_mask;
5d728824e   Tejun Heo   libata: convert t...
138
  	ap->flags |= ATA_FLAG_SLAVE_POSS;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
139
140
  
  	/*
f7fc0ceb4   Paul Mundt   libata: pata_plat...
141
142
143
144
145
146
147
148
  	 * Use polling mode if there's no IRQ
  	 */
  	if (!irq) {
  		ap->flags |= ATA_FLAG_PIO_POLLING;
  		ata_port_desc(ap, "no IRQ, using PIO polling");
  	}
  
  	/*
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
149
150
151
  	 * Handle the MMIO case
  	 */
  	if (mmio) {
cf03613e9   Anton Vorontsov   libata: pata_plat...
152
  		ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start,
041b5eac2   Julia Lawall   drivers/ata: use ...
153
  				resource_size(io_res));
cf03613e9   Anton Vorontsov   libata: pata_plat...
154
  		ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start,
041b5eac2   Julia Lawall   drivers/ata: use ...
155
  				resource_size(ctl_res));
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
156
  	} else {
cf03613e9   Anton Vorontsov   libata: pata_plat...
157
  		ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start,
041b5eac2   Julia Lawall   drivers/ata: use ...
158
  				resource_size(io_res));
cf03613e9   Anton Vorontsov   libata: pata_plat...
159
  		ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start,
041b5eac2   Julia Lawall   drivers/ata: use ...
160
  				resource_size(ctl_res));
0d5ff5667   Tejun Heo   libata: convert t...
161
  	}
5d728824e   Tejun Heo   libata: convert t...
162
  	if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
cf03613e9   Anton Vorontsov   libata: pata_plat...
163
164
  		dev_err(dev, "failed to map IO/CTL base
  ");
0d5ff5667   Tejun Heo   libata: convert t...
165
  		return -ENOMEM;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
166
  	}
5d728824e   Tejun Heo   libata: convert t...
167
  	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
168

cf03613e9   Anton Vorontsov   libata: pata_plat...
169
  	pata_platform_setup_port(&ap->ioaddr, ioport_shift);
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
170

cbcdd8759   Tejun Heo   libata: implement...
171
172
173
  	ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
  		      (unsigned long long)io_res->start,
  		      (unsigned long long)ctl_res->start);
5d728824e   Tejun Heo   libata: convert t...
174
  	/* activate */
9363c3825   Tejun Heo   libata: rename SF...
175
  	return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
cf03613e9   Anton Vorontsov   libata: pata_plat...
176
  				 irq_flags, &pata_platform_sht);
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
177
  }
cf03613e9   Anton Vorontsov   libata: pata_plat...
178
  EXPORT_SYMBOL_GPL(__pata_platform_probe);
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
179
180
  
  /**
cf03613e9   Anton Vorontsov   libata: pata_plat...
181
182
   *	__pata_platform_remove		-	unplug a platform interface
   *	@dev: device
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
183
184
185
186
   *
   *	A platform bus ATA device has been unplugged. Perform the needed
   *	cleanup. Also called on module unload for any active devices.
   */
78a7ba47f   Sonic Zhang   pata_platform: __...
187
  int __pata_platform_remove(struct device *dev)
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
188
  {
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
189
  	struct ata_host *host = dev_get_drvdata(dev);
1a68ff13c   Tejun Heo   pata_platform: fi...
190
  	ata_host_detach(host);
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
191
192
193
  
  	return 0;
  }
cf03613e9   Anton Vorontsov   libata: pata_plat...
194
195
196
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  EXPORT_SYMBOL_GPL(__pata_platform_remove);
  
  static int __devinit pata_platform_probe(struct platform_device *pdev)
  {
  	struct resource *io_res;
  	struct resource *ctl_res;
  	struct resource *irq_res;
  	struct pata_platform_info *pp_info = pdev->dev.platform_data;
  
  	/*
  	 * Simple resource validation ..
  	 */
  	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
  		dev_err(&pdev->dev, "invalid number of resources
  ");
  		return -EINVAL;
  	}
  
  	/*
  	 * Get the I/O base first
  	 */
  	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	if (io_res == NULL) {
  		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  		if (unlikely(io_res == NULL))
  			return -EINVAL;
  	}
  
  	/*
  	 * Then the CTL base
  	 */
  	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
  	if (ctl_res == NULL) {
  		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  		if (unlikely(ctl_res == NULL))
  			return -EINVAL;
  	}
  
  	/*
  	 * And the IRQ
  	 */
  	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  	if (irq_res)
  		irq_res->flags = pp_info ? pp_info->irq_flags : 0;
  
  	return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res,
  				     pp_info ? pp_info->ioport_shift : 0,
  				     pio_mask);
  }
  
  static int __devexit pata_platform_remove(struct platform_device *pdev)
  {
  	return __pata_platform_remove(&pdev->dev);
  }
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
248
249
250
251
252
253
254
255
256
  
  static struct platform_driver pata_platform_driver = {
  	.probe		= pata_platform_probe,
  	.remove		= __devexit_p(pata_platform_remove),
  	.driver = {
  		.name		= DRV_NAME,
  		.owner		= THIS_MODULE,
  	},
  };
99c8ea3e5   Axel Lin   SATA/PATA: conver...
257
  module_platform_driver(pata_platform_driver);
a20c9e820   Paul Mundt   [PATCH] ata: Gene...
258
259
260
261
262
263
264
  
  module_param(pio_mask, int, 0);
  
  MODULE_AUTHOR("Paul Mundt");
  MODULE_DESCRIPTION("low-level driver for platform device ATA");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);
458622fcd   Kay Sievers   ATA/IDE: fix plat...
265
  MODULE_ALIAS("platform:" DRV_NAME);