11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 1996-2004 Russell King.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please note that this platform does not support 32-bit IDE IO.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dma-mapping.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/scatterlist.h>
18ba5b55d0498bd56b9d60d85c5f654cd7b291e9c8Al Viro#include <linux/io.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ecard.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2367717e224181527987cce800fa2ddb5c8c1e9315Bartlomiej Zolnierkiewicz#define DRV_NAME "icside"
2467717e224181527987cce800fa2ddb5c8c1e9315Bartlomiej Zolnierkiewicz
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_IDENT_OFFSET		0x2280
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V5_INTRSTAT		0x0000
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V5_INTROFFSET		0x0004
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V5_IDEOFFSET		0x2800
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V5_IDEALTOFFSET	0x2b80
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V5_IDESTEPPING	6
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_IDEOFFSET_1	0x2000
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_INTROFFSET_1	0x2200
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_INTRSTAT_1		0x2290
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_IDEALTOFFSET_1	0x2380
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_IDEOFFSET_2	0x3000
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_INTROFFSET_2	0x3200
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_INTRSTAT_2		0x3290
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_IDEALTOFFSET_2	0x3380
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_ARCIN_V6_IDESTEPPING	6
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cardinfo {
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int dataoffset;
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ctrloffset;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int stepping;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct cardinfo icside_cardinfo_v5 = {
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dataoffset	= ICS_ARCIN_V5_IDEOFFSET,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ctrloffset	= ICS_ARCIN_V5_IDEALTOFFSET,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stepping	= ICS_ARCIN_V5_IDESTEPPING,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct cardinfo icside_cardinfo_v6_1 = {
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dataoffset	= ICS_ARCIN_V6_IDEOFFSET_1,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ctrloffset	= ICS_ARCIN_V6_IDEALTOFFSET_1,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stepping	= ICS_ARCIN_V6_IDESTEPPING,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct cardinfo icside_cardinfo_v6_2 = {
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dataoffset	= ICS_ARCIN_V6_IDEOFFSET_2,
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ctrloffset	= ICS_ARCIN_V6_IDEALTOFFSET_2,
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stepping	= ICS_ARCIN_V6_IDESTEPPING,
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct icside_state {
68f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	unsigned int channel;
69f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	unsigned int enabled;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *irq_port;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ioc_base;
7226839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	unsigned int sel;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int type;
7448c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	struct ide_host *host;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_TYPE_A3IN	0
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_TYPE_A3USER	1
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_TYPE_V6	3
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_TYPE_V5	15
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ICS_TYPE_NOTYPE	((unsigned int)-1)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---------------- Version 5 PCB Support Functions --------------------- */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose  : enable interrupts from card
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ec->irq_data;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose  : disable interrupts from card
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ec->irq_data;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const expansioncard_ops_t icside_ops_arcin_v5 = {
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irqenable	= icside_irqenable_arcin_v5,
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irqdisable	= icside_irqdisable_arcin_v5,
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---------------- Version 6 PCB Support Functions --------------------- */
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose  : enable interrupts from card
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ec->irq_data;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base = state->irq_port;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	state->enabled = 1;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	switch (state->channel) {
122f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	case 0:
123f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
124f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		readb(base + ICS_ARCIN_V6_INTROFFSET_2);
125f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		break;
126f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	case 1:
127f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
128f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		readb(base + ICS_ARCIN_V6_INTROFFSET_1);
129f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		break;
130f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	}
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose  : disable interrupts from card
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ec->irq_data;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
140f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	state->enabled = 0;
141f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Prototype: icside_irqprobe(struct expansion_card *ec)
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Purpose  : detect an active interrupt from card
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int icside_irqpending_arcin_v6(struct expansion_card *ec)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ec->irq_data;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const expansioncard_ops_t icside_ops_arcin_v6 = {
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irqenable	= icside_irqenable_arcin_v6,
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irqdisable	= icside_irqdisable_arcin_v6,
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irqpending	= icside_irqpending_arcin_v6,
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
163f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz/*
164f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz * Handle routing of interrupts.  This is called before
165f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz * we write the command to the drive.
166f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz */
167f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewiczstatic void icside_maskproc(ide_drive_t *drive, int mask)
168f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz{
169f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	ide_hwif_t *hwif = drive->hwif;
170f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	struct expansion_card *ec = ECARD_DEV(hwif->dev);
171f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	struct icside_state *state = ecard_get_drvdata(ec);
172f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	unsigned long flags;
173f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
174f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	local_irq_save(flags);
175f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
176f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	state->channel = hwif->channel;
177f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
178f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	if (state->enabled && !mask) {
179f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		switch (hwif->channel) {
180f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		case 0:
181f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz			writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
182f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz			readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
183f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz			break;
184f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		case 1:
185f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz			writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
186f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz			readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
187f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz			break;
188f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		}
189f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	} else {
190f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
191f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz		readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
192f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	}
193f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
194f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	local_irq_restore(flags);
195f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz}
196f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
197f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewiczstatic const struct ide_port_ops icside_v6_no_dma_port_ops = {
198f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	.maskproc		= icside_maskproc,
199f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz};
200f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SG-DMA support.
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is only one DMA controller per card, which means that only
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one drive can be accessed at one time.  NOTE! We do not enforce that
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * here, but we rely on the main IDE driver spotting that both
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interfaces use the same IRQ, which should guarantee this.
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configure the IOMD to give the appropriate timings for the transfer
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mode being requested.  We take the advice of the ATA standards, and
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * calculate the cycle time based on the transfer mode, and the EIDE
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MW DMA specs that the drive provides in the IDENTIFY command.
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have the following IOMD DMA modes to choose from:
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Type	Active		Recovery	Cycle
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	A	250 (250)	312 (550)	562 (800)
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	B	187		250		437
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	C	125 (125)	125 (375)	250 (500)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	D	62		125		187
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (figures in brackets are actual measured timings)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * However, we also need to take care of the read/write active and
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * recovery timings:
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			Read	Write
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  	Mode	Active	-- Recovery --	Cycle	IOMD type
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	MW0	215	50	215	480	A
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	MW1	80	50	50	150	C
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	MW2	70	25	25	120	C
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2378776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewiczstatic void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2395bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos	unsigned long cycle_time;
2405bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos	int use_dma_info = 0;
2418776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz	const u8 xfer_mode = drive->dma_mode;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (xfer_mode) {
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case XFER_MW_DMA_2:
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cycle_time = 250;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		use_dma_info = 1;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case XFER_MW_DMA_1:
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cycle_time = 250;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		use_dma_info = 1;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case XFER_MW_DMA_0:
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cycle_time = 480;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case XFER_SW_DMA_2:
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case XFER_SW_DMA_1:
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case XFER_SW_DMA_0:
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cycle_time = 480;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * take care to note the values in the ID...
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2694dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz	if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
2704dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz		cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2725bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos	ide_set_drivedata(drive, (void *)cycle_time);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s: %s selected (peak %dMB/s)\n", drive->name,
2755bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos		ide_xfer_verbose(xfer_mode),
2765bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos		2000 / (unsigned long)ide_get_drivedata(drive));
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
279ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops icside_v6_port_ops = {
280ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_dma_mode		= icside_set_dma_mode,
281f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	.maskproc		= icside_maskproc,
282ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz};
283ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz
28415ce926ada545cb078711bd9a18c083c93fa01d7Bartlomiej Zolnierkiewiczstatic void icside_dma_host_set(ide_drive_t *drive, int on)
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int icside_dma_end(ide_drive_t *drive)
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
290898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif = drive->hwif;
291f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	struct expansion_card *ec = ECARD_DEV(hwif->dev);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
293f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	disable_dma(ec->dma);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
295f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	return get_dma_residue(ec->dma) != 0;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void icside_dma_start(ide_drive_t *drive)
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
300898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif = drive->hwif;
301f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	struct expansion_card *ec = ECARD_DEV(hwif->dev);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We can not enable DMA on both channels simultaneously. */
304f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	BUG_ON(dma_channel_active(ec->dma));
305f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	enable_dma(ec->dma);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3082298169418f43ba5e0919762a4bab95a1227872aBartlomiej Zolnierkiewiczstatic int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
310898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif = drive->hwif;
311f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	struct expansion_card *ec = ECARD_DEV(hwif->dev);
31226839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	struct icside_state *state = ecard_get_drvdata(ec);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int dma_mode;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3152298169418f43ba5e0919762a4bab95a1227872aBartlomiej Zolnierkiewicz	if (cmd->tf_flags & IDE_TFLAG_WRITE)
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_mode = DMA_MODE_WRITE;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_mode = DMA_MODE_READ;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We can not enable DMA on both channels.
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
323f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	BUG_ON(dma_channel_active(ec->dma));
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
326f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	 * Ensure that we have the right interrupt routed.
327f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	 */
328f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	icside_maskproc(drive, 0);
329f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz
330f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	/*
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Route the DMA signals to the correct interface.
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
33326839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	writeb(state->sel | hwif->channel, state->ioc_base);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Select the correct timing for this drive.
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3385bfb151f1f565e6082304a30e8c81dfb6ed0b0c8Joao Ramos	set_dma_speed(ec->dma, (unsigned long)ide_get_drivedata(drive));
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Tell the DMA engine about the SG table and
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * data direction.
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3442298169418f43ba5e0919762a4bab95a1227872aBartlomiej Zolnierkiewicz	set_dma_sg(ec->dma, hwif->sg_table, cmd->sg_nents);
345f8341c1c19730f1869f2f12e30fe56ff4afb4189Bartlomiej Zolnierkiewicz	set_dma_mode(ec->dma, dma_mode);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int icside_dma_test_irq(ide_drive_t *drive)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
352898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif = drive->hwif;
35326839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	struct expansion_card *ec = ECARD_DEV(hwif->dev);
35426839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	struct icside_state *state = ecard_get_drvdata(ec);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return readb(state->irq_port +
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (hwif->channel ?
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ICS_ARCIN_V6_INTRSTAT_2 :
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ICS_ARCIN_V6_INTRSTAT_1)) & 1;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36291432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewiczstatic int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->dmatable_cpu	= NULL;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->dmatable_dma	= 0;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36791432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz	return 0;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3695e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz
370f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewiczstatic const struct ide_dma_ops icside_v6_dma_ops = {
3715e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_host_set		= icside_dma_host_set,
3725e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_setup		= icside_dma_setup,
3735e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_start		= icside_dma_start,
3745e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_end		= icside_dma_end,
3755e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_test_irq		= icside_dma_test_irq,
376de23ec9ca82357e6d337a2263befb1a65cf19c83Bartlomiej Zolnierkiewicz	.dma_lost_irq		= ide_dma_lost_irq,
3775e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz};
3785e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz#else
3795e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz#define icside_v6_dma_ops NULL
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38291432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewiczstatic int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
38391432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz{
38491432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz	return -EOPNOTSUPP;
38591432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz}
38691432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz
3879f36d31437922354d104a2db407f397e79e4027eBartlomiej Zolnierkiewiczstatic void icside_setup_ports(struct ide_hw *hw, void __iomem *base,
388b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz			       struct cardinfo *info, struct expansion_card *ec)
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long port = (unsigned long)base + info->dataoffset;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
392b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.data_addr	 = port;
393b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.error_addr	 = port + (1 << info->stepping);
394b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.nsect_addr	 = port + (2 << info->stepping);
395b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.lbal_addr	 = port + (3 << info->stepping);
396b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.lbam_addr	 = port + (4 << info->stepping);
397b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.lbah_addr	 = port + (5 << info->stepping);
398b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.device_addr = port + (6 << info->stepping);
399b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.status_addr = port + (7 << info->stepping);
400b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->io_ports.ctl_addr	 = (unsigned long)base + info->ctrloffset;
401b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz
402b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->irq = ec->irq;
403b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	hw->dev = &ec->dev;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40633050ec7a2b83bc048b2322c79af25df6fdcb879Bartlomiej Zolnierkiewiczstatic const struct ide_port_info icside_v5_port_info = {
40733050ec7a2b83bc048b2322c79af25df6fdcb879Bartlomiej Zolnierkiewicz	.host_flags		= IDE_HFLAG_NO_DMA,
40829e52cf793ded6bece50de50e738596f94f07d9fBartlomiej Zolnierkiewicz	.chipset		= ide_acorn,
40933050ec7a2b83bc048b2322c79af25df6fdcb879Bartlomiej Zolnierkiewicz};
41033050ec7a2b83bc048b2322c79af25df6fdcb879Bartlomiej Zolnierkiewicz
411d16d7667f9c211e8d9b7e2365cc3d3a83fc6a8e2Al Virostatic int __devinit
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsicside_register_v5(struct icside_state *state, struct expansion_card *ec)
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base;
41548c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	struct ide_host *host;
4169f36d31437922354d104a2db407f397e79e4027eBartlomiej Zolnierkiewicz	struct ide_hw hw, *hws[] = { &hw };
4178a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	int ret;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41910bdaaa0fad620145cf10e2b573266b2d80b44deRussell King	base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!base)
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->irq_port = base;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ec->irqmask  = 1;
427c7b87f3d5037a35b5c7bb916ffc826be3fcb208dRussell King
428c7b87f3d5037a35b5c7bb916ffc826be3fcb208dRussell King	ecard_setirq(ec, &icside_ops_arcin_v5, state);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Be on the safe side - disable interrupts
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	icside_irqdisable_arcin_v5(ec, 0);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
435b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
436b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz
437dca3983059a4481e4ae97bbf0ac4b4c21429e1a5Bartlomiej Zolnierkiewicz	host = ide_host_alloc(&icside_v5_port_info, hws, 1);
43848c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	if (host == NULL)
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44148c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	state->host = host;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44326839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	ecard_set_drvdata(ec, state);
44426839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz
44533050ec7a2b83bc048b2322c79af25df6fdcb879Bartlomiej Zolnierkiewicz	ret = ide_host_register(host, &icside_v5_port_info, hws);
4468a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	if (ret)
4478a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz		goto err_free;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4508a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewiczerr_free:
4518a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	ide_host_free(host);
4528a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	ecard_set_drvdata(ec, NULL);
4538a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	return ret;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
456c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewiczstatic const struct ide_port_info icside_v6_port_info __initdata = {
45791432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz	.init_dma		= icside_dma_off_init,
458f75d4a238770d83d3a0475ce7f34e3fa37de161eBartlomiej Zolnierkiewicz	.port_ops		= &icside_v6_no_dma_port_ops,
4595e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_ops		= &icside_v6_dma_ops,
460c5dd43ec65c1e1e378df043d517d40ed70a32cbeBartlomiej Zolnierkiewicz	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
461c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz	.mwdma_mask		= ATA_MWDMA2,
462c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz	.swdma_mask		= ATA_SWDMA2,
46329e52cf793ded6bece50de50e738596f94f07d9fBartlomiej Zolnierkiewicz	.chipset		= ide_acorn,
464c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz};
465c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz
466d16d7667f9c211e8d9b7e2365cc3d3a83fc6a8e2Al Virostatic int __devinit
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsicside_register_v6(struct icside_state *state, struct expansion_card *ec)
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *ioc_base, *easi_base;
47048c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	struct ide_host *host;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int sel = 0;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
4739f36d31437922354d104a2db407f397e79e4027eBartlomiej Zolnierkiewicz	struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] };
474c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz	struct ide_port_info d = icside_v6_port_info;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47610bdaaa0fad620145cf10e2b573266b2d80b44deRussell King	ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!ioc_base) {
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	easi_base = ioc_base;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
48510bdaaa0fad620145cf10e2b573266b2d80b44deRussell King		easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!easi_base) {
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -ENOMEM;
48810bdaaa0fad620145cf10e2b573266b2d80b44deRussell King			goto out;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Enable access to the EASI region.
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sel = 1 << 5;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writeb(sel, ioc_base);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
499c7b87f3d5037a35b5c7bb916ffc826be3fcb208dRussell King	ecard_setirq(ec, &icside_ops_arcin_v6, state);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->irq_port   = easi_base;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->ioc_base   = ioc_base;
50326839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	state->sel	  = sel;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Be on the safe side - disable interrupts
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	icside_irqdisable_arcin_v6(ec, 0);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
510b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
511b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz	icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
512b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz
513dca3983059a4481e4ae97bbf0ac4b4c21429e1a5Bartlomiej Zolnierkiewicz	host = ide_host_alloc(&d, hws, 2);
51448c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	if (host == NULL)
515b25afdf1336237fb0e4021eb35744e577e19bd14Bartlomiej Zolnierkiewicz		return -ENODEV;
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51748c3c1072651922ed153bcf0a33ea82cf20df390Bartlomiej Zolnierkiewicz	state->host = host;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51926839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	ecard_set_drvdata(ec, state);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52167717e224181527987cce800fa2ddb5c8c1e9315Bartlomiej Zolnierkiewicz	if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
52291432f48094db32579776bd0a9d8432b16dc0a09Bartlomiej Zolnierkiewicz		d.init_dma = icside_dma_init;
5239c391bae6a65bd39962877ad7dc000b600757bbeAl Viro		d.port_ops = &icside_v6_port_ops;
524acc8dbe7f44f1bab6fcf21f2d5efb32ea92e19fdBartlomiej Zolnierkiewicz	} else
5255e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz		d.dma_ops = NULL;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
527d224b6269e4731a82f648bb0281ea1a4d8b3311dBartlomiej Zolnierkiewicz	ret = ide_host_register(host, &d, hws);
5288a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	if (ret)
5298a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz		goto err_free;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5328a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewiczerr_free:
5338a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	ide_host_free(host);
5348a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	if (d.dma_ops)
5358a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz		free_dma(ec->dma);
5368a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewicz	ecard_set_drvdata(ec, NULL);
5378a69580e1ea9516caada5eed202afd39546e9809Bartlomiej Zolnierkiewiczout:
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsicside_probe(struct expansion_card *ec, const struct ecard_id *id)
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *idmem;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = ecard_request_resources(ec);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret)
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
552cc60d8baa35c995bf8c40a9730b894993ddb43b9Mariusz Kozlowski	state = kzalloc(sizeof(struct icside_state), GFP_KERNEL);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!state) {
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto release;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->type	= ICS_TYPE_NOTYPE;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56010bdaaa0fad620145cf10e2b573266b2d80b44deRussell King	idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (idmem) {
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int type;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type = readb(idmem + ICS_IDENT_OFFSET) & 1;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
56810bdaaa0fad620145cf10e2b573266b2d80b44deRussell King		ecardm_iounmap(ec, idmem);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		state->type = type;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (state->type) {
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ICS_TYPE_A3IN:
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_warn(&ec->dev, "A3IN unsupported\n");
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENODEV;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ICS_TYPE_A3USER:
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_warn(&ec->dev, "A3USER unsupported\n");
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENODEV;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ICS_TYPE_V5:
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = icside_register_v5(state, ec);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ICS_TYPE_V6:
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = icside_register_v6(state, ec);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_warn(&ec->dev, "unknown interface type\n");
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENODEV;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59826839f09ca2d0f4239e546cd912bc9f4694f3c5eBartlomiej Zolnierkiewicz	if (ret == 0)
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(state);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release:
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ecard_release_resources(ec);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit icside_remove(struct expansion_card *ec)
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ecard_get_drvdata(ec);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (state->type) {
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ICS_TYPE_V5:
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* FIXME: tell IDE to stop using the interface */
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable interrupts */
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		icside_irqdisable_arcin_v5(ec, 0);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ICS_TYPE_V6:
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* FIXME: tell IDE to stop using the interface */
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ec->dma != NO_DMA)
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free_dma(ec->dma);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable interrupts */
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		icside_irqdisable_arcin_v6(ec, 0);
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Reset the ROM pointer/EASI selection */
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(0, state->ioc_base);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ecard_set_drvdata(ec, NULL);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(state);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ecard_release_resources(ec);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void icside_shutdown(struct expansion_card *ec)
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct icside_state *state = ecard_get_drvdata(ec);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Disable interrupts from this card.  We need to do
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * this before disabling EASI since we may be accessing
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * this register via that region.
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_save(flags);
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ec->ops->irqdisable(ec, 0);
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_restore(flags);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Reset the ROM pointer so that we can read the ROM
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * after a soft reboot.  This also disables access to
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the IDE taskfile via the EASI region.
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (state->ioc_base)
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writeb(0, state->ioc_base);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct ecard_id icside_ids[] = {
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ MANU_ICS,  PROD_ICS_IDE  },
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ MANU_ICS2, PROD_ICS2_IDE },
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0xffff, 0xffff }
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct ecard_driver icside_driver = {
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= icside_probe,
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= __devexit_p(icside_remove),
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.shutdown	= icside_shutdown,
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= icside_ids,
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drv = {
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "icside",
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init icside_init(void)
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ecard_register_driver(&icside_driver);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6831137fb670465b6b5d15b9db7d01707a5833ee3aeAl Virostatic void __exit icside_exit(void)
6848e27cb1135de4cc69bf358209f91e1f7ba81eca1Bartlomiej Zolnierkiewicz{
6851137fb670465b6b5d15b9db7d01707a5833ee3aeAl Viro	ecard_remove_driver(&icside_driver);
6868e27cb1135de4cc69bf358209f91e1f7ba81eca1Bartlomiej Zolnierkiewicz}
6878e27cb1135de4cc69bf358209f91e1f7ba81eca1Bartlomiej Zolnierkiewicz
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ICS IDE driver");
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(icside_init);
6938e27cb1135de4cc69bf358209f91e1f7ba81eca1Bartlomiej Zolnierkiewiczmodule_exit(icside_exit);
694