Blame view

drivers/pcmcia/at91_cf.c 9.97 KB
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * at91_cf.c -- AT91 CompactFlash controller driver
   *
   * Copyright (C) 2005 David Brownell
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
14
15
16
17
  #include <linux/platform_device.h>
  #include <linux/errno.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
18
  #include <linux/slab.h>
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
19
20
  
  #include <pcmcia/ss.h>
a09e64fbc   Russell King   [ARM] Move includ...
21
  #include <mach/hardware.h>
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
22
23
  #include <asm/io.h>
  #include <asm/sizes.h>
4c1fc445c   David Brownell   at91_cf: use gene...
24
  #include <asm/gpio.h>
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
25

a09e64fbc   Russell King   [ARM] Move includ...
26
27
  #include <mach/board.h>
  #include <mach/at91rm9200_mc.h>
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
28

2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
29
30
31
32
  /*
   * A0..A10 work in each range; A23 indicates I/O space;  A25 is CFRNW;
   * some other bit in {A24,A22..A11} is nREG to flag memory access
   * (vs attributes).  So more than 2KB/region would just be waste.
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
33
   * Note: These are offsets from the physical base address.
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
34
   */
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
35
36
37
  #define	CF_ATTR_PHYS	(0)
  #define	CF_IO_PHYS	(1 << 23)
  #define	CF_MEM_PHYS	(0x017ff800)
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
38
39
40
41
42
43
44
45
46
47
48
49
  
  /*--------------------------------------------------------------------------*/
  
  static const char driver_name[] = "at91_cf";
  
  struct at91_cf_socket {
  	struct pcmcia_socket	socket;
  
  	unsigned		present:1;
  
  	struct platform_device	*pdev;
  	struct at91_cf_data	*board;
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
50
51
  
  	unsigned long		phys_baseaddr;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
52
  };
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
53
54
  static inline int at91_cf_present(struct at91_cf_socket *cf)
  {
4c1fc445c   David Brownell   at91_cf: use gene...
55
  	return !gpio_get_value(cf->board->det_pin);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
56
57
58
59
60
61
62
63
  }
  
  /*--------------------------------------------------------------------------*/
  
  static int at91_cf_ss_init(struct pcmcia_socket *s)
  {
  	return 0;
  }
7d12e780e   David Howells   IRQ: Maintain reg...
64
  static irqreturn_t at91_cf_irq(int irq, void *_cf)
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
65
  {
c7bec5aba   Jeff Garzik   Various drivers' ...
66
  	struct at91_cf_socket *cf = _cf;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
67
68
69
70
71
72
73
  
  	if (irq == cf->board->det_pin) {
  		unsigned present = at91_cf_present(cf);
  
  		/* kick pccard as needed */
  		if (present != cf->present) {
  			cf->present = present;
2c5362007   David Brownell   Fix AT91RM9200 bu...
74
75
76
  			pr_debug("%s: card %s
  ", driver_name,
  					present ? "present" : "gone");
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  			pcmcia_parse_events(&cf->socket, SS_DETECT);
  		}
  	}
  
  	return IRQ_HANDLED;
  }
  
  static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
  {
  	struct at91_cf_socket	*cf;
  
  	if (!sp)
  		return -EINVAL;
  
  	cf = container_of(s, struct at91_cf_socket, socket);
2c5362007   David Brownell   Fix AT91RM9200 bu...
92
  	/* NOTE: CF is always 3VCARD */
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
93
94
95
96
97
  	if (at91_cf_present(cf)) {
  		int rdy	= cf->board->irq_pin;	/* RDY/nIRQ */
  		int vcc	= cf->board->vcc_pin;
  
  		*sp = SS_DETECT | SS_3VCARD;
4c1fc445c   David Brownell   at91_cf: use gene...
98
  		if (!rdy || gpio_get_value(rdy))
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
99
  			*sp |= SS_READY;
4c1fc445c   David Brownell   at91_cf: use gene...
100
  		if (!vcc || gpio_get_value(vcc))
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
101
102
103
104
105
106
  			*sp |= SS_POWERON;
  	} else
  		*sp = 0;
  
  	return 0;
  }
2c5362007   David Brownell   Fix AT91RM9200 bu...
107
108
  static int
  at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
109
110
111
112
113
114
115
116
117
  {
  	struct at91_cf_socket	*cf;
  
  	cf = container_of(sock, struct at91_cf_socket, socket);
  
  	/* switch Vcc if needed and possible */
  	if (cf->board->vcc_pin) {
  		switch (s->Vcc) {
  			case 0:
4c1fc445c   David Brownell   at91_cf: use gene...
118
  				gpio_set_value(cf->board->vcc_pin, 0);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
119
120
  				break;
  			case 33:
4c1fc445c   David Brownell   at91_cf: use gene...
121
  				gpio_set_value(cf->board->vcc_pin, 1);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
122
123
124
125
126
127
128
  				break;
  			default:
  				return -EINVAL;
  		}
  	}
  
  	/* toggle reset if needed */
4c1fc445c   David Brownell   at91_cf: use gene...
129
  	gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  
  	pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x
  ",
  		driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
  
  	return 0;
  }
  
  static int at91_cf_ss_suspend(struct pcmcia_socket *s)
  {
  	return at91_cf_set_socket(s, &dead_socket);
  }
  
  /* we already mapped the I/O region */
  static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
  {
  	struct at91_cf_socket	*cf;
  	u32			csr;
  
  	cf = container_of(s, struct at91_cf_socket, socket);
  	io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ);
  
  	/*
  	 * Use 16 bit accesses unless/until we need 8-bit i/o space.
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
154
  	 */
40a0017eb   Andrew Victor   [PATCH] pcmcia: a...
155
  	csr = at91_sys_read(AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
156
157
158
159
160
161
162
163
164
165
166
  
  	/*
  	 * NOTE: this CF controller ignores IOIS16, so we can't really do
  	 * MAP_AUTOSZ.  The 16bit mode allows single byte access on either
  	 * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many
  	 * purposes (and handles ide-cs).
  	 *
  	 * The 8bit mode is needed for odd byte access on D0-D7.  It seems
  	 * some cards only like that way to get at the odd byte, despite
  	 * CF 3.0 spec table 35 also giving the D8-D15 option.
  	 */
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
167
  	if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) {
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
168
169
170
171
172
173
174
175
  		csr |= AT91_SMC_DBW_8;
  		pr_debug("%s: 8bit i/o bus
  ", driver_name);
  	} else {
  		csr |= AT91_SMC_DBW_16;
  		pr_debug("%s: 16bit i/o bus
  ", driver_name);
  	}
40a0017eb   Andrew Victor   [PATCH] pcmcia: a...
176
  	at91_sys_write(AT91_SMC_CSR(cf->board->chipselect), csr);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
177
178
179
180
181
182
183
184
  
  	io->start = cf->socket.io_offset;
  	io->stop = io->start + SZ_2K - 1;
  
  	return 0;
  }
  
  /* pcmcia layer maps/unmaps mem regions */
2c5362007   David Brownell   Fix AT91RM9200 bu...
185
186
  static int
  at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
187
188
189
190
191
192
193
  {
  	struct at91_cf_socket	*cf;
  
  	if (map->card_start)
  		return -EINVAL;
  
  	cf = container_of(s, struct at91_cf_socket, socket);
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
194
  	map->flags &= (MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
195
  	if (map->flags & MAP_ATTRIB)
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
196
  		map->static_start = cf->phys_baseaddr + CF_ATTR_PHYS;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
197
  	else
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
198
  		map->static_start = cf->phys_baseaddr + CF_MEM_PHYS;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  
  	return 0;
  }
  
  static struct pccard_operations at91_cf_ops = {
  	.init			= at91_cf_ss_init,
  	.suspend		= at91_cf_ss_suspend,
  	.get_status		= at91_cf_get_status,
  	.set_socket		= at91_cf_set_socket,
  	.set_io_map		= at91_cf_set_io_map,
  	.set_mem_map		= at91_cf_set_mem_map,
  };
  
  /*--------------------------------------------------------------------------*/
0db6095d4   David Brownell   [PATCH] pcmcia: a...
213
  static int __init at91_cf_probe(struct platform_device *pdev)
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
214
215
  {
  	struct at91_cf_socket	*cf;
0db6095d4   David Brownell   [PATCH] pcmcia: a...
216
  	struct at91_cf_data	*board = pdev->dev.platform_data;
2c5362007   David Brownell   Fix AT91RM9200 bu...
217
  	struct resource		*io;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
218
219
220
221
  	int			status;
  
  	if (!board || !board->det_pin || !board->rst_pin)
  		return -ENODEV;
2c5362007   David Brownell   Fix AT91RM9200 bu...
222
223
224
  	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!io)
  		return -ENODEV;
cd8612808   Robert P. J. Day   [PATCH] Fix numer...
225
  	cf = kzalloc(sizeof *cf, GFP_KERNEL);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
226
227
228
229
230
  	if (!cf)
  		return -ENOMEM;
  
  	cf->board = board;
  	cf->pdev = pdev;
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
231
  	cf->phys_baseaddr = io->start;
0db6095d4   David Brownell   [PATCH] pcmcia: a...
232
  	platform_set_drvdata(pdev, cf);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
233

2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
234
  	/* must be a GPIO; ergo must trigger on both edges */
4c1fc445c   David Brownell   at91_cf: use gene...
235
  	status = gpio_request(board->det_pin, "cf_det");
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
236
237
  	if (status < 0)
  		goto fail0;
4c1fc445c   David Brownell   at91_cf: use gene...
238
239
240
  	status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
  	if (status < 0)
  		goto fail00;
0db6095d4   David Brownell   [PATCH] pcmcia: a...
241
  	device_init_wakeup(&pdev->dev, 1);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
242

4c1fc445c   David Brownell   at91_cf: use gene...
243
244
245
246
247
248
249
250
251
  	status = gpio_request(board->rst_pin, "cf_rst");
  	if (status < 0)
  		goto fail0a;
  
  	if (board->vcc_pin) {
  		status = gpio_request(board->vcc_pin, "cf_vcc");
  		if (status < 0)
  			goto fail0b;
  	}
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
252
253
254
255
256
257
258
  	/*
  	 * The card driver will request this irq later as needed.
  	 * but it causes lots of "irqNN: nobody cared" messages
  	 * unless we report that we handle everything (sigh).
  	 * (Note:  DK board doesn't wire the IRQ pin...)
  	 */
  	if (board->irq_pin) {
4c1fc445c   David Brownell   at91_cf: use gene...
259
260
261
  		status = gpio_request(board->irq_pin, "cf_irq");
  		if (status < 0)
  			goto fail0c;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
262
  		status = request_irq(board->irq_pin, at91_cf_irq,
dace14537   Thomas Gleixner   [PATCH] irq-flags...
263
  				IRQF_SHARED, driver_name, cf);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
264
  		if (status < 0)
4c1fc445c   David Brownell   at91_cf: use gene...
265
  			goto fail0d;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
266
  		cf->socket.pci_irq = board->irq_pin;
2c5362007   David Brownell   Fix AT91RM9200 bu...
267
  	} else
9130addad   Yinghai Lu   drivers/pcmcia: u...
268
  		cf->socket.pci_irq = nr_irqs + 1;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
269
270
  
  	/* pcmcia layer only remaps "real" memory not iospace */
4c1fc445c   David Brownell   at91_cf: use gene...
271
272
  	cf->socket.io_offset = (unsigned long)
  			ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
273
274
  	if (!cf->socket.io_offset) {
  		status = -ENXIO;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
275
  		goto fail1;
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
276
  	}
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
277

40a0017eb   Andrew Victor   [PATCH] pcmcia: a...
278
  	/* reserve chip-select regions */
28f65c11f   Joe Perches   treewide: Convert...
279
  	if (!request_mem_region(io->start, resource_size(io), driver_name)) {
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
280
  		status = -ENXIO;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
281
  		goto fail1;
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
282
  	}
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
283
284
285
286
287
288
  
  	pr_info("%s: irqs det #%d, io #%d
  ", driver_name,
  		board->det_pin, board->irq_pin);
  
  	cf->socket.owner = THIS_MODULE;
e4a3c3f09   Alexey Dobriyan   pcmcia: some clas...
289
  	cf->socket.dev.parent = &pdev->dev;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
290
291
292
293
294
  	cf->socket.ops = &at91_cf_ops;
  	cf->socket.resource_ops = &pccard_static_ops;
  	cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
  				| SS_CAP_MEM_ALIGN;
  	cf->socket.map_size = SZ_2K;
2c5362007   David Brownell   Fix AT91RM9200 bu...
295
  	cf->socket.io[0].res = io;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
296
297
298
299
300
301
302
303
  
  	status = pcmcia_register_socket(&cf->socket);
  	if (status < 0)
  		goto fail2;
  
  	return 0;
  
  fail2:
28f65c11f   Joe Perches   treewide: Convert...
304
  	release_mem_region(io->start, resource_size(io));
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
305
  fail1:
3efa9970b   Amol Lad   [PATCH] ioremap b...
306
307
  	if (cf->socket.io_offset)
  		iounmap((void __iomem *) cf->socket.io_offset);
4c1fc445c   David Brownell   at91_cf: use gene...
308
  	if (board->irq_pin) {
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
309
  		free_irq(board->irq_pin, cf);
4c1fc445c   David Brownell   at91_cf: use gene...
310
311
312
313
314
315
316
317
  fail0d:
  		gpio_free(board->irq_pin);
  	}
  fail0c:
  	if (board->vcc_pin)
  		gpio_free(board->vcc_pin);
  fail0b:
  	gpio_free(board->rst_pin);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
318
  fail0a:
1fbece150   David Brownell   [PATCH] pcmcia: a...
319
  	device_init_wakeup(&pdev->dev, 0);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
320
  	free_irq(board->det_pin, cf);
4c1fc445c   David Brownell   at91_cf: use gene...
321
322
  fail00:
  	gpio_free(board->det_pin);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
323
  fail0:
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
324
325
326
  	kfree(cf);
  	return status;
  }
0db6095d4   David Brownell   [PATCH] pcmcia: a...
327
  static int __exit at91_cf_remove(struct platform_device *pdev)
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
328
  {
0db6095d4   David Brownell   [PATCH] pcmcia: a...
329
330
  	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
  	struct at91_cf_data	*board = cf->board;
2c5362007   David Brownell   Fix AT91RM9200 bu...
331
  	struct resource		*io = cf->socket.io[0].res;
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
332
333
  
  	pcmcia_unregister_socket(&cf->socket);
28f65c11f   Joe Perches   treewide: Convert...
334
  	release_mem_region(io->start, resource_size(io));
4c1fc445c   David Brownell   at91_cf: use gene...
335
336
  	iounmap((void __iomem *) cf->socket.io_offset);
  	if (board->irq_pin) {
0db6095d4   David Brownell   [PATCH] pcmcia: a...
337
  		free_irq(board->irq_pin, cf);
4c1fc445c   David Brownell   at91_cf: use gene...
338
339
340
341
342
  		gpio_free(board->irq_pin);
  	}
  	if (board->vcc_pin)
  		gpio_free(board->vcc_pin);
  	gpio_free(board->rst_pin);
0db6095d4   David Brownell   [PATCH] pcmcia: a...
343
  	device_init_wakeup(&pdev->dev, 0);
ebe5cfb3b   Andrew Victor   [PATCH] pcmcia: a...
344
  	free_irq(board->det_pin, cf);
4c1fc445c   David Brownell   at91_cf: use gene...
345
  	gpio_free(board->det_pin);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
346
347
348
  	kfree(cf);
  	return 0;
  }
0db6095d4   David Brownell   [PATCH] pcmcia: a...
349
350
351
352
353
354
  #ifdef	CONFIG_PM
  
  static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
  {
  	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
  	struct at91_cf_data	*board = cf->board;
1fbece150   David Brownell   [PATCH] pcmcia: a...
355
  	if (device_may_wakeup(&pdev->dev)) {
0db6095d4   David Brownell   [PATCH] pcmcia: a...
356
  		enable_irq_wake(board->det_pin);
1fbece150   David Brownell   [PATCH] pcmcia: a...
357
358
  		if (board->irq_pin)
  			enable_irq_wake(board->irq_pin);
0db6095d4   David Brownell   [PATCH] pcmcia: a...
359
  	}
0db6095d4   David Brownell   [PATCH] pcmcia: a...
360
361
362
363
364
  	return 0;
  }
  
  static int at91_cf_resume(struct platform_device *pdev)
  {
9af20376e   Marc Pignat   at91: fix enable/...
365
366
367
368
369
370
371
372
  	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
  	struct at91_cf_data	*board = cf->board;
  
  	if (device_may_wakeup(&pdev->dev)) {
  		disable_irq_wake(board->det_pin);
  		if (board->irq_pin)
  			disable_irq_wake(board->irq_pin);
  	}
0db6095d4   David Brownell   [PATCH] pcmcia: a...
373
374
375
376
377
378
379
380
381
382
383
384
385
  	return 0;
  }
  
  #else
  #define	at91_cf_suspend		NULL
  #define	at91_cf_resume		NULL
  #endif
  
  static struct platform_driver at91_cf_driver = {
  	.driver = {
  		.name		= (char *) driver_name,
  		.owner		= THIS_MODULE,
  	},
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
386
  	.remove		= __exit_p(at91_cf_remove),
0db6095d4   David Brownell   [PATCH] pcmcia: a...
387
388
  	.suspend	= at91_cf_suspend,
  	.resume		= at91_cf_resume,
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
389
390
391
392
393
394
  };
  
  /*--------------------------------------------------------------------------*/
  
  static int __init at91_cf_init(void)
  {
02c83595b   David Brownell   at91_cf, minor fix
395
  	return platform_driver_probe(&at91_cf_driver, at91_cf_probe);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
396
397
398
399
400
  }
  module_init(at91_cf_init);
  
  static void __exit at91_cf_exit(void)
  {
0db6095d4   David Brownell   [PATCH] pcmcia: a...
401
  	platform_driver_unregister(&at91_cf_driver);
2c1f3b7a3   Andrew Victor   [PATCH] pcmcia: A...
402
403
404
405
406
407
  }
  module_exit(at91_cf_exit);
  
  MODULE_DESCRIPTION("AT91 Compact Flash Driver");
  MODULE_AUTHOR("David Brownell");
  MODULE_LICENSE("GPL");
12c2c019e   Kay Sievers   pcmcia: fix platf...
408
  MODULE_ALIAS("platform:at91_cf");