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 unsigned int channel;
69 unsigned int enabled;
70 void __iomem *irq_port;
71 void __iomem *ioc_base;
72 unsigned int sel;
73 unsigned int type;
74 struct ide_host *host;
75};
76
77#define ICS_TYPE_A3IN 0
78#define ICS_TYPE_A3USER 1
79#define ICS_TYPE_V6 3
80#define ICS_TYPE_V5 15
81#define ICS_TYPE_NOTYPE ((unsigned int)-1)
82
83
84
85
86
87static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
88{
89 struct icside_state *state = ec->irq_data;
90
91 writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
92}
93
94
95
96
97static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
98{
99 struct icside_state *state = ec->irq_data;
100
101 readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
102}
103
104static const expansioncard_ops_t icside_ops_arcin_v5 = {
105 .irqenable = icside_irqenable_arcin_v5,
106 .irqdisable = icside_irqdisable_arcin_v5,
107};
108
109
110
111
112
113
114static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
115{
116 struct icside_state *state = ec->irq_data;
117 void __iomem *base = state->irq_port;
118
119 state->enabled = 1;
120
121 switch (state->channel) {
122 case 0:
123 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
124 readb(base + ICS_ARCIN_V6_INTROFFSET_2);
125 break;
126 case 1:
127 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
128 readb(base + ICS_ARCIN_V6_INTROFFSET_1);
129 break;
130 }
131}
132
133
134
135
136static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
137{
138 struct icside_state *state = ec->irq_data;
139
140 state->enabled = 0;
141
142 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
143 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
144}
145
146
147
148
149static int icside_irqpending_arcin_v6(struct expansion_card *ec)
150{
151 struct icside_state *state = ec->irq_data;
152
153 return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
154 readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
155}
156
157static const expansioncard_ops_t icside_ops_arcin_v6 = {
158 .irqenable = icside_irqenable_arcin_v6,
159 .irqdisable = icside_irqdisable_arcin_v6,
160 .irqpending = icside_irqpending_arcin_v6,
161};
162
163
164
165
166
167static void icside_maskproc(ide_drive_t *drive, int mask)
168{
169 ide_hwif_t *hwif = HWIF(drive);
170 struct expansion_card *ec = ECARD_DEV(hwif->dev);
171 struct icside_state *state = ecard_get_drvdata(ec);
172 unsigned long flags;
173
174 local_irq_save(flags);
175
176 state->channel = hwif->channel;
177
178 if (state->enabled && !mask) {
179 switch (hwif->channel) {
180 case 0:
181 writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
182 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
183 break;
184 case 1:
185 writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
186 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
187 break;
188 }
189 } else {
190 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
191 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
192 }
193
194 local_irq_restore(flags);
195}
196
197static const struct ide_port_ops icside_v6_no_dma_port_ops = {
198 .maskproc = icside_maskproc,
199};
200
201#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
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
237static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
238{
239 int cycle_time, use_dma_info = 0;
240
241 switch (xfer_mode) {
242 case XFER_MW_DMA_2:
243 cycle_time = 250;
244 use_dma_info = 1;
245 break;
246
247 case XFER_MW_DMA_1:
248 cycle_time = 250;
249 use_dma_info = 1;
250 break;
251
252 case XFER_MW_DMA_0:
253 cycle_time = 480;
254 break;
255
256 case XFER_SW_DMA_2:
257 case XFER_SW_DMA_1:
258 case XFER_SW_DMA_0:
259 cycle_time = 480;
260 break;
261 }
262
263
264
265
266
267 if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
268 cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
269
270 drive->drive_data = cycle_time;
271
272 printk("%s: %s selected (peak %dMB/s)\n", drive->name,
273 ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
274}
275
276static const struct ide_port_ops icside_v6_port_ops = {
277 .set_dma_mode = icside_set_dma_mode,
278 .maskproc = icside_maskproc,
279};
280
281static void icside_dma_host_set(ide_drive_t *drive, int on)
282{
283}
284
285static int icside_dma_end(ide_drive_t *drive)
286{
287 ide_hwif_t *hwif = HWIF(drive);
288 struct expansion_card *ec = ECARD_DEV(hwif->dev);
289
290 drive->waiting_for_dma = 0;
291
292 disable_dma(ec->dma);
293
294
295 ide_destroy_dmatable(drive);
296
297 return get_dma_residue(ec->dma) != 0;
298}
299
300static void icside_dma_start(ide_drive_t *drive)
301{
302 ide_hwif_t *hwif = HWIF(drive);
303 struct expansion_card *ec = ECARD_DEV(hwif->dev);
304
305
306 BUG_ON(dma_channel_active(ec->dma));
307 enable_dma(ec->dma);
308}
309
310static int icside_dma_setup(ide_drive_t *drive)
311{
312 ide_hwif_t *hwif = HWIF(drive);
313 struct expansion_card *ec = ECARD_DEV(hwif->dev);
314 struct icside_state *state = ecard_get_drvdata(ec);
315 struct request *rq = hwif->hwgroup->rq;
316 unsigned int dma_mode;
317
318 if (rq_data_dir(rq))
319 dma_mode = DMA_MODE_WRITE;
320 else
321 dma_mode = DMA_MODE_READ;
322
323
324
325
326 BUG_ON(dma_channel_active(ec->dma));
327
328 hwif->sg_nents = ide_build_sglist(drive, rq);
329
330
331
332
333 icside_maskproc(drive, 0);
334
335
336
337
338 writeb(state->sel | hwif->channel, state->ioc_base);
339
340
341
342
343 set_dma_speed(ec->dma, drive->drive_data);
344
345
346
347
348
349 set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
350 set_dma_mode(ec->dma, dma_mode);
351
352 drive->waiting_for_dma = 1;
353
354 return 0;
355}
356
357static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
358{
359
360 ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL);
361}
362
363static int icside_dma_test_irq(ide_drive_t *drive)
364{
365 ide_hwif_t *hwif = HWIF(drive);
366 struct expansion_card *ec = ECARD_DEV(hwif->dev);
367 struct icside_state *state = ecard_get_drvdata(ec);
368
369 return readb(state->irq_port +
370 (hwif->channel ?
371 ICS_ARCIN_V6_INTRSTAT_2 :
372 ICS_ARCIN_V6_INTRSTAT_1)) & 1;
373}
374
375static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
376{
377 hwif->dmatable_cpu = NULL;
378 hwif->dmatable_dma = 0;
379
380 return 0;
381}
382
383static const struct ide_dma_ops icside_v6_dma_ops = {
384 .dma_host_set = icside_dma_host_set,
385 .dma_setup = icside_dma_setup,
386 .dma_exec_cmd = icside_dma_exec_cmd,
387 .dma_start = icside_dma_start,
388 .dma_end = icside_dma_end,
389 .dma_test_irq = icside_dma_test_irq,
390 .dma_timeout = ide_dma_timeout,
391 .dma_lost_irq = ide_dma_lost_irq,
392};
393#else
394#define icside_v6_dma_ops NULL
395#endif
396
397static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
398{
399 return -EOPNOTSUPP;
400}
401
402static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
403 struct cardinfo *info, struct expansion_card *ec)
404{
405 unsigned long port = (unsigned long)base + info->dataoffset;
406
407 hw->io_ports.data_addr = port;
408 hw->io_ports.error_addr = port + (1 << info->stepping);
409 hw->io_ports.nsect_addr = port + (2 << info->stepping);
410 hw->io_ports.lbal_addr = port + (3 << info->stepping);
411 hw->io_ports.lbam_addr = port + (4 << info->stepping);
412 hw->io_ports.lbah_addr = port + (5 << info->stepping);
413 hw->io_ports.device_addr = port + (6 << info->stepping);
414 hw->io_ports.status_addr = port + (7 << info->stepping);
415 hw->io_ports.ctl_addr = (unsigned long)base + info->ctrloffset;
416
417 hw->irq = ec->irq;
418 hw->dev = &ec->dev;
419 hw->chipset = ide_acorn;
420}
421
422static int __devinit
423icside_register_v5(struct icside_state *state, struct expansion_card *ec)
424{
425 void __iomem *base;
426 struct ide_host *host;
427 hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
428 int ret;
429
430 base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
431 if (!base)
432 return -ENOMEM;
433
434 state->irq_port = base;
435
436 ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
437 ec->irqmask = 1;
438
439 ecard_setirq(ec, &icside_ops_arcin_v5, state);
440
441
442
443
444 icside_irqdisable_arcin_v5(ec, 0);
445
446 icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
447
448 host = ide_host_alloc(NULL, hws);
449 if (host == NULL)
450 return -ENODEV;
451
452 state->host = host;
453
454 ecard_set_drvdata(ec, state);
455
456 ret = ide_host_register(host, NULL, hws);
457 if (ret)
458 goto err_free;
459
460 return 0;
461err_free:
462 ide_host_free(host);
463 ecard_set_drvdata(ec, NULL);
464 return ret;
465}
466
467static const struct ide_port_info icside_v6_port_info __initdata = {
468 .init_dma = icside_dma_off_init,
469 .port_ops = &icside_v6_no_dma_port_ops,
470 .dma_ops = &icside_v6_dma_ops,
471 .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
472 .mwdma_mask = ATA_MWDMA2,
473 .swdma_mask = ATA_SWDMA2,
474};
475
476static int __devinit
477icside_register_v6(struct icside_state *state, struct expansion_card *ec)
478{
479 void __iomem *ioc_base, *easi_base;
480 struct ide_host *host;
481 unsigned int sel = 0;
482 int ret;
483 hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
484 struct ide_port_info d = icside_v6_port_info;
485
486 ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
487 if (!ioc_base) {
488 ret = -ENOMEM;
489 goto out;
490 }
491
492 easi_base = ioc_base;
493
494 if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
495 easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
496 if (!easi_base) {
497 ret = -ENOMEM;
498 goto out;
499 }
500
501
502
503
504 sel = 1 << 5;
505 }
506
507 writeb(sel, ioc_base);
508
509 ecard_setirq(ec, &icside_ops_arcin_v6, state);
510
511 state->irq_port = easi_base;
512 state->ioc_base = ioc_base;
513 state->sel = sel;
514
515
516
517
518 icside_irqdisable_arcin_v6(ec, 0);
519
520 icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
521 icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
522
523 host = ide_host_alloc(&d, hws);
524 if (host == NULL)
525 return -ENODEV;
526
527 state->host = host;
528
529 ecard_set_drvdata(ec, state);
530
531 if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
532 d.init_dma = icside_dma_init;
533 d.port_ops = &icside_v6_port_ops;
534 d.dma_ops = NULL;
535 }
536
537 ret = ide_host_register(host, NULL, hws);
538 if (ret)
539 goto err_free;
540
541 return 0;
542err_free:
543 ide_host_free(host);
544 if (d.dma_ops)
545 free_dma(ec->dma);
546 ecard_set_drvdata(ec, NULL);
547out:
548 return ret;
549}
550
551static int __devinit
552icside_probe(struct expansion_card *ec, const struct ecard_id *id)
553{
554 struct icside_state *state;
555 void __iomem *idmem;
556 int ret;
557
558 ret = ecard_request_resources(ec);
559 if (ret)
560 goto out;
561
562 state = kzalloc(sizeof(struct icside_state), GFP_KERNEL);
563 if (!state) {
564 ret = -ENOMEM;
565 goto release;
566 }
567
568 state->type = ICS_TYPE_NOTYPE;
569
570 idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
571 if (idmem) {
572 unsigned int type;
573
574 type = readb(idmem + ICS_IDENT_OFFSET) & 1;
575 type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
576 type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
577 type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
578 ecardm_iounmap(ec, idmem);
579
580 state->type = type;
581 }
582
583 switch (state->type) {
584 case ICS_TYPE_A3IN:
585 dev_warn(&ec->dev, "A3IN unsupported\n");
586 ret = -ENODEV;
587 break;
588
589 case ICS_TYPE_A3USER:
590 dev_warn(&ec->dev, "A3USER unsupported\n");
591 ret = -ENODEV;
592 break;
593
594 case ICS_TYPE_V5:
595 ret = icside_register_v5(state, ec);
596 break;
597
598 case ICS_TYPE_V6:
599 ret = icside_register_v6(state, ec);
600 break;
601
602 default:
603 dev_warn(&ec->dev, "unknown interface type\n");
604 ret = -ENODEV;
605 break;
606 }
607
608 if (ret == 0)
609 goto out;
610
611 kfree(state);
612 release:
613 ecard_release_resources(ec);
614 out:
615 return ret;
616}
617
618static void __devexit icside_remove(struct expansion_card *ec)
619{
620 struct icside_state *state = ecard_get_drvdata(ec);
621
622 switch (state->type) {
623 case ICS_TYPE_V5:
624
625
626
627 icside_irqdisable_arcin_v5(ec, 0);
628 break;
629
630 case ICS_TYPE_V6:
631
632 if (ec->dma != NO_DMA)
633 free_dma(ec->dma);
634
635
636 icside_irqdisable_arcin_v6(ec, 0);
637
638
639 writeb(0, state->ioc_base);
640 break;
641 }
642
643 ecard_set_drvdata(ec, NULL);
644
645 kfree(state);
646 ecard_release_resources(ec);
647}
648
649static void icside_shutdown(struct expansion_card *ec)
650{
651 struct icside_state *state = ecard_get_drvdata(ec);
652 unsigned long flags;
653
654
655
656
657
658
659 local_irq_save(flags);
660 ec->ops->irqdisable(ec, 0);
661 local_irq_restore(flags);
662
663
664
665
666
667
668 if (state->ioc_base)
669 writeb(0, state->ioc_base);
670}
671
672static const struct ecard_id icside_ids[] = {
673 { MANU_ICS, PROD_ICS_IDE },
674 { MANU_ICS2, PROD_ICS2_IDE },
675 { 0xffff, 0xffff }
676};
677
678static struct ecard_driver icside_driver = {
679 .probe = icside_probe,
680 .remove = __devexit_p(icside_remove),
681 .shutdown = icside_shutdown,
682 .id_table = icside_ids,
683 .drv = {
684 .name = "icside",
685 },
686};
687
688static int __init icside_init(void)
689{
690 return ecard_register_driver(&icside_driver);
691}
692
693static void __exit icside_exit(void)
694{
695 ecard_remove_driver(&icside_driver);
696}
697
698MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
699MODULE_LICENSE("GPL");
700MODULE_DESCRIPTION("ICS IDE driver");
701
702module_init(icside_init);
703module_exit(icside_exit);
704