1
2
3
4
5
6
7#include <linux/string.h>
8#include <linux/module.h>
9#include <linux/ioport.h>
10#include <linux/slab.h>
11#include <linux/blkdev.h>
12#include <linux/errno.h>
13#include <linux/ide.h>
14#include <linux/dma-mapping.h>
15#include <linux/device.h>
16#include <linux/init.h>
17#include <linux/scatterlist.h>
18#include <linux/io.h>
19
20#include <asm/dma.h>
21#include <asm/ecard.h>
22
23#define DRV_NAME "icside"
24
25#define ICS_IDENT_OFFSET 0x2280
26
27#define ICS_ARCIN_V5_INTRSTAT 0x0000
28#define ICS_ARCIN_V5_INTROFFSET 0x0004
29#define ICS_ARCIN_V5_IDEOFFSET 0x2800
30#define ICS_ARCIN_V5_IDEALTOFFSET 0x2b80
31#define ICS_ARCIN_V5_IDESTEPPING 6
32
33#define ICS_ARCIN_V6_IDEOFFSET_1 0x2000
34#define ICS_ARCIN_V6_INTROFFSET_1 0x2200
35#define ICS_ARCIN_V6_INTRSTAT_1 0x2290
36#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x2380
37#define ICS_ARCIN_V6_IDEOFFSET_2 0x3000
38#define ICS_ARCIN_V6_INTROFFSET_2 0x3200
39#define ICS_ARCIN_V6_INTRSTAT_2 0x3290
40#define ICS_ARCIN_V6_IDEALTOFFSET_2 0x3380
41#define ICS_ARCIN_V6_IDESTEPPING 6
42
43struct cardinfo {
44 unsigned int dataoffset;
45 unsigned int ctrloffset;
46 unsigned int stepping;
47};
48
49static struct cardinfo icside_cardinfo_v5 = {
50 .dataoffset = ICS_ARCIN_V5_IDEOFFSET,
51 .ctrloffset = ICS_ARCIN_V5_IDEALTOFFSET,
52 .stepping = ICS_ARCIN_V5_IDESTEPPING,
53};
54
55static struct cardinfo icside_cardinfo_v6_1 = {
56 .dataoffset = ICS_ARCIN_V6_IDEOFFSET_1,
57 .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_1,
58 .stepping = ICS_ARCIN_V6_IDESTEPPING,
59};
60
61static struct cardinfo icside_cardinfo_v6_2 = {
62 .dataoffset = ICS_ARCIN_V6_IDEOFFSET_2,
63 .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_2,
64 .stepping = ICS_ARCIN_V6_IDESTEPPING,
65};
66
67struct icside_state {
68 void __iomem *irq_port;
69 void __iomem *ioc_base;
70 unsigned int sel;
71 unsigned int type;
72 struct ide_host *host;
73};
74
75#define ICS_TYPE_A3IN 0
76#define ICS_TYPE_A3USER 1
77#define ICS_TYPE_V6 3
78#define ICS_TYPE_V5 15
79#define ICS_TYPE_NOTYPE ((unsigned int)-1)
80
81
82
83
84
85static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
86{
87 struct icside_state *state = ec->irq_data;
88
89 writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
90}
91
92
93
94
95static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
96{
97 struct icside_state *state = ec->irq_data;
98
99 readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
100}
101
102static const expansioncard_ops_t icside_ops_arcin_v5 = {
103 .irqenable = icside_irqenable_arcin_v5,
104 .irqdisable = icside_irqdisable_arcin_v5,
105};
106
107
108
109
110
111
112static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
113{
114 struct icside_state *state = ec->irq_data;
115 void __iomem *base = state->irq_port;
116
117 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
118 readb(base + ICS_ARCIN_V6_INTROFFSET_2);
119
120 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
121 readb(base + ICS_ARCIN_V6_INTROFFSET_1);
122}
123
124
125
126
127static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
128{
129 struct icside_state *state = ec->irq_data;
130
131 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
132 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
133}
134
135
136
137
138static int icside_irqpending_arcin_v6(struct expansion_card *ec)
139{
140 struct icside_state *state = ec->irq_data;
141
142 return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
143 readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
144}
145
146static const expansioncard_ops_t icside_ops_arcin_v6 = {
147 .irqenable = icside_irqenable_arcin_v6,
148 .irqdisable = icside_irqdisable_arcin_v6,
149 .irqpending = icside_irqpending_arcin_v6,
150};
151
152#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
189{
190 unsigned long cycle_time;
191 int use_dma_info = 0;
192
193 switch (xfer_mode) {
194 case XFER_MW_DMA_2:
195 cycle_time = 250;
196 use_dma_info = 1;
197 break;
198
199 case XFER_MW_DMA_1:
200 cycle_time = 250;
201 use_dma_info = 1;
202 break;
203
204 case XFER_MW_DMA_0:
205 cycle_time = 480;
206 break;
207
208 case XFER_SW_DMA_2:
209 case XFER_SW_DMA_1:
210 case XFER_SW_DMA_0:
211 cycle_time = 480;
212 break;
213 }
214
215
216
217
218
219 if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
220 cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
221
222 ide_set_drivedata(drive, (void *)cycle_time);
223
224 printk("%s: %s selected (peak %dMB/s)\n", drive->name,
225 ide_xfer_verbose(xfer_mode),
226 2000 / (unsigned long)ide_get_drivedata(drive));
227}
228
229static const struct ide_port_ops icside_v6_port_ops = {
230 .set_dma_mode = icside_set_dma_mode,
231};
232
233static void icside_dma_host_set(ide_drive_t *drive, int on)
234{
235}
236
237static int icside_dma_end(ide_drive_t *drive)
238{
239 ide_hwif_t *hwif = drive->hwif;
240 struct expansion_card *ec = ECARD_DEV(hwif->dev);
241
242 disable_dma(ec->dma);
243
244 return get_dma_residue(ec->dma) != 0;
245}
246
247static void icside_dma_start(ide_drive_t *drive)
248{
249 ide_hwif_t *hwif = drive->hwif;
250 struct expansion_card *ec = ECARD_DEV(hwif->dev);
251
252
253 BUG_ON(dma_channel_active(ec->dma));
254 enable_dma(ec->dma);
255}
256
257static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
258{
259 ide_hwif_t *hwif = drive->hwif;
260 struct expansion_card *ec = ECARD_DEV(hwif->dev);
261 struct icside_state *state = ecard_get_drvdata(ec);
262 unsigned int dma_mode;
263
264 if (cmd->tf_flags & IDE_TFLAG_WRITE)
265 dma_mode = DMA_MODE_WRITE;
266 else
267 dma_mode = DMA_MODE_READ;
268
269
270
271
272 BUG_ON(dma_channel_active(ec->dma));
273
274
275
276
277 writeb(state->sel | hwif->channel, state->ioc_base);
278
279
280
281
282 set_dma_speed(ec->dma, (unsigned long)ide_get_drivedata(drive));
283
284
285
286
287
288 set_dma_sg(ec->dma, hwif->sg_table, cmd->sg_nents);
289 set_dma_mode(ec->dma, dma_mode);
290
291 return 0;
292}
293
294static int icside_dma_test_irq(ide_drive_t *drive)
295{
296 ide_hwif_t *hwif = drive->hwif;
297 struct expansion_card *ec = ECARD_DEV(hwif->dev);
298 struct icside_state *state = ecard_get_drvdata(ec);
299
300 return readb(state->irq_port +
301 (hwif->channel ?
302 ICS_ARCIN_V6_INTRSTAT_2 :
303 ICS_ARCIN_V6_INTRSTAT_1)) & 1;
304}
305
306static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
307{
308 hwif->dmatable_cpu = NULL;
309 hwif->dmatable_dma = 0;
310
311 return 0;
312}
313
314static const struct ide_dma_ops icside_v6_dma_ops = {
315 .dma_host_set = icside_dma_host_set,
316 .dma_setup = icside_dma_setup,
317 .dma_start = icside_dma_start,
318 .dma_end = icside_dma_end,
319 .dma_test_irq = icside_dma_test_irq,
320 .dma_lost_irq = ide_dma_lost_irq,
321};
322#else
323#define icside_v6_dma_ops NULL
324#endif
325
326static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
327{
328 return -EOPNOTSUPP;
329}
330
331static void icside_setup_ports(struct ide_hw *hw, void __iomem *base,
332 struct cardinfo *info, struct expansion_card *ec)
333{
334 unsigned long port = (unsigned long)base + info->dataoffset;
335
336 hw->io_ports.data_addr = port;
337 hw->io_ports.error_addr = port + (1 << info->stepping);
338 hw->io_ports.nsect_addr = port + (2 << info->stepping);
339 hw->io_ports.lbal_addr = port + (3 << info->stepping);
340 hw->io_ports.lbam_addr = port + (4 << info->stepping);
341 hw->io_ports.lbah_addr = port + (5 << info->stepping);
342 hw->io_ports.device_addr = port + (6 << info->stepping);
343 hw->io_ports.status_addr = port + (7 << info->stepping);
344 hw->io_ports.ctl_addr = (unsigned long)base + info->ctrloffset;
345
346 hw->irq = ec->irq;
347 hw->dev = &ec->dev;
348}
349
350static const struct ide_port_info icside_v5_port_info = {
351 .host_flags = IDE_HFLAG_NO_DMA,
352 .chipset = ide_acorn,
353};
354
355static int __devinit
356icside_register_v5(struct icside_state *state, struct expansion_card *ec)
357{
358 void __iomem *base;
359 struct ide_host *host;
360 struct ide_hw hw, *hws[] = { &hw };
361 int ret;
362
363 base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
364 if (!base)
365 return -ENOMEM;
366
367 state->irq_port = base;
368
369 ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
370 ec->irqmask = 1;
371
372 ecard_setirq(ec, &icside_ops_arcin_v5, state);
373
374
375
376
377 icside_irqdisable_arcin_v5(ec, 0);
378
379 icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
380
381 host = ide_host_alloc(&icside_v5_port_info, hws, 1);
382 if (host == NULL)
383 return -ENODEV;
384
385 state->host = host;
386
387 ecard_set_drvdata(ec, state);
388
389 ret = ide_host_register(host, &icside_v5_port_info, hws);
390 if (ret)
391 goto err_free;
392
393 return 0;
394err_free:
395 ide_host_free(host);
396 ecard_set_drvdata(ec, NULL);
397 return ret;
398}
399
400static const struct ide_port_info icside_v6_port_info __initdata = {
401 .init_dma = icside_dma_off_init,
402 .dma_ops = &icside_v6_dma_ops,
403 .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
404 .mwdma_mask = ATA_MWDMA2,
405 .swdma_mask = ATA_SWDMA2,
406 .chipset = ide_acorn,
407};
408
409static int __devinit
410icside_register_v6(struct icside_state *state, struct expansion_card *ec)
411{
412 void __iomem *ioc_base, *easi_base;
413 struct ide_host *host;
414 unsigned int sel = 0;
415 int ret;
416 struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] };
417 struct ide_port_info d = icside_v6_port_info;
418
419 ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
420 if (!ioc_base) {
421 ret = -ENOMEM;
422 goto out;
423 }
424
425 easi_base = ioc_base;
426
427 if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
428 easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
429 if (!easi_base) {
430 ret = -ENOMEM;
431 goto out;
432 }
433
434
435
436
437 sel = 1 << 5;
438 }
439
440 writeb(sel, ioc_base);
441
442 ecard_setirq(ec, &icside_ops_arcin_v6, state);
443
444 state->irq_port = easi_base;
445 state->ioc_base = ioc_base;
446 state->sel = sel;
447
448
449
450
451 icside_irqdisable_arcin_v6(ec, 0);
452
453 icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
454 icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
455
456 host = ide_host_alloc(&d, hws, 2);
457 if (host == NULL)
458 return -ENODEV;
459
460 state->host = host;
461
462 ecard_set_drvdata(ec, state);
463
464 if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
465 d.init_dma = icside_dma_init;
466 d.port_ops = &icside_v6_port_ops;
467 d.dma_ops = NULL;
468 }
469
470 ret = ide_host_register(host, &d, hws);
471 if (ret)
472 goto err_free;
473
474 return 0;
475err_free:
476 ide_host_free(host);
477 if (d.dma_ops)
478 free_dma(ec->dma);
479 ecard_set_drvdata(ec, NULL);
480out:
481 return ret;
482}
483
484static int __devinit
485icside_probe(struct expansion_card *ec, const struct ecard_id *id)
486{
487 struct icside_state *state;
488 void __iomem *idmem;
489 int ret;
490
491 ret = ecard_request_resources(ec);
492 if (ret)
493 goto out;
494
495 state = kzalloc(sizeof(struct icside_state), GFP_KERNEL);
496 if (!state) {
497 ret = -ENOMEM;
498 goto release;
499 }
500
501 state->type = ICS_TYPE_NOTYPE;
502
503 idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
504 if (idmem) {
505 unsigned int type;
506
507 type = readb(idmem + ICS_IDENT_OFFSET) & 1;
508 type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
509 type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
510 type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
511 ecardm_iounmap(ec, idmem);
512
513 state->type = type;
514 }
515
516 switch (state->type) {
517 case ICS_TYPE_A3IN:
518 dev_warn(&ec->dev, "A3IN unsupported\n");
519 ret = -ENODEV;
520 break;
521
522 case ICS_TYPE_A3USER:
523 dev_warn(&ec->dev, "A3USER unsupported\n");
524 ret = -ENODEV;
525 break;
526
527 case ICS_TYPE_V5:
528 ret = icside_register_v5(state, ec);
529 break;
530
531 case ICS_TYPE_V6:
532 ret = icside_register_v6(state, ec);
533 break;
534
535 default:
536 dev_warn(&ec->dev, "unknown interface type\n");
537 ret = -ENODEV;
538 break;
539 }
540
541 if (ret == 0)
542 goto out;
543
544 kfree(state);
545 release:
546 ecard_release_resources(ec);
547 out:
548 return ret;
549}
550
551static void __devexit icside_remove(struct expansion_card *ec)
552{
553 struct icside_state *state = ecard_get_drvdata(ec);
554
555 switch (state->type) {
556 case ICS_TYPE_V5:
557
558
559
560 icside_irqdisable_arcin_v5(ec, 0);
561 break;
562
563 case ICS_TYPE_V6:
564
565 if (ec->dma != NO_DMA)
566 free_dma(ec->dma);
567
568
569 icside_irqdisable_arcin_v6(ec, 0);
570
571
572 writeb(0, state->ioc_base);
573 break;
574 }
575
576 ecard_set_drvdata(ec, NULL);
577
578 kfree(state);
579 ecard_release_resources(ec);
580}
581
582static void icside_shutdown(struct expansion_card *ec)
583{
584 struct icside_state *state = ecard_get_drvdata(ec);
585 unsigned long flags;
586
587
588
589
590
591
592 local_irq_save(flags);
593 ec->ops->irqdisable(ec, 0);
594 local_irq_restore(flags);
595
596
597
598
599
600
601 if (state->ioc_base)
602 writeb(0, state->ioc_base);
603}
604
605static const struct ecard_id icside_ids[] = {
606 { MANU_ICS, PROD_ICS_IDE },
607 { MANU_ICS2, PROD_ICS2_IDE },
608 { 0xffff, 0xffff }
609};
610
611static struct ecard_driver icside_driver = {
612 .probe = icside_probe,
613 .remove = __devexit_p(icside_remove),
614 .shutdown = icside_shutdown,
615 .id_table = icside_ids,
616 .drv = {
617 .name = "icside",
618 },
619};
620
621static int __init icside_init(void)
622{
623 return ecard_register_driver(&icside_driver);
624}
625
626static void __exit icside_exit(void)
627{
628 ecard_remove_driver(&icside_driver);
629}
630
631MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
632MODULE_LICENSE("GPL");
633MODULE_DESCRIPTION("ICS IDE driver");
634
635module_init(icside_init);
636module_exit(icside_exit);
637