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