109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
273b6a2beSRussell King #include <linux/kernel.h>
373b6a2beSRussell King #include <linux/module.h>
473b6a2beSRussell King #include <linux/init.h>
573b6a2beSRussell King #include <linux/blkdev.h>
65a0e3ad6STejun Heo #include <linux/gfp.h>
773b6a2beSRussell King #include <scsi/scsi_host.h>
873b6a2beSRussell King #include <linux/ata.h>
973b6a2beSRussell King #include <linux/libata.h>
1073b6a2beSRussell King
1173b6a2beSRussell King #include <asm/dma.h>
1273b6a2beSRussell King #include <asm/ecard.h>
1373b6a2beSRussell King
1473b6a2beSRussell King #define DRV_NAME "pata_icside"
1573b6a2beSRussell King
1673b6a2beSRussell King #define ICS_IDENT_OFFSET 0x2280
1773b6a2beSRussell King
1873b6a2beSRussell King #define ICS_ARCIN_V5_INTRSTAT 0x0000
1973b6a2beSRussell King #define ICS_ARCIN_V5_INTROFFSET 0x0004
2073b6a2beSRussell King
2173b6a2beSRussell King #define ICS_ARCIN_V6_INTROFFSET_1 0x2200
2273b6a2beSRussell King #define ICS_ARCIN_V6_INTRSTAT_1 0x2290
2373b6a2beSRussell King #define ICS_ARCIN_V6_INTROFFSET_2 0x3200
2473b6a2beSRussell King #define ICS_ARCIN_V6_INTRSTAT_2 0x3290
2573b6a2beSRussell King
2673b6a2beSRussell King struct portinfo {
2773b6a2beSRussell King unsigned int dataoffset;
2873b6a2beSRussell King unsigned int ctrloffset;
2973b6a2beSRussell King unsigned int stepping;
3073b6a2beSRussell King };
3173b6a2beSRussell King
3273b6a2beSRussell King static const struct portinfo pata_icside_portinfo_v5 = {
3373b6a2beSRussell King .dataoffset = 0x2800,
3473b6a2beSRussell King .ctrloffset = 0x2b80,
3573b6a2beSRussell King .stepping = 6,
3673b6a2beSRussell King };
3773b6a2beSRussell King
3873b6a2beSRussell King static const struct portinfo pata_icside_portinfo_v6_1 = {
3973b6a2beSRussell King .dataoffset = 0x2000,
4073b6a2beSRussell King .ctrloffset = 0x2380,
4173b6a2beSRussell King .stepping = 6,
4273b6a2beSRussell King };
4373b6a2beSRussell King
4473b6a2beSRussell King static const struct portinfo pata_icside_portinfo_v6_2 = {
4573b6a2beSRussell King .dataoffset = 0x3000,
4673b6a2beSRussell King .ctrloffset = 0x3380,
4773b6a2beSRussell King .stepping = 6,
4873b6a2beSRussell King };
4973b6a2beSRussell King
5073b6a2beSRussell King struct pata_icside_state {
5173b6a2beSRussell King void __iomem *irq_port;
5273b6a2beSRussell King void __iomem *ioc_base;
5373b6a2beSRussell King unsigned int type;
5473b6a2beSRussell King unsigned int dma;
5573b6a2beSRussell King struct {
5673b6a2beSRussell King u8 port_sel;
5773b6a2beSRussell King u8 disabled;
5873b6a2beSRussell King unsigned int speed[ATA_MAX_DEVICES];
5973b6a2beSRussell King } port[2];
6073b6a2beSRussell King };
6173b6a2beSRussell King
62f95637d2SRussell King struct pata_icside_info {
63f95637d2SRussell King struct pata_icside_state *state;
64f95637d2SRussell King struct expansion_card *ec;
65f95637d2SRussell King void __iomem *base;
66f95637d2SRussell King void __iomem *irqaddr;
67f95637d2SRussell King unsigned int irqmask;
68f95637d2SRussell King const expansioncard_ops_t *irqops;
69f95637d2SRussell King unsigned int mwdma_mask;
70f95637d2SRussell King unsigned int nr_ports;
71f95637d2SRussell King const struct portinfo *port[2];
72cbcdd875STejun Heo unsigned long raw_base;
73cbcdd875STejun Heo unsigned long raw_ioc_base;
74f95637d2SRussell King };
75f95637d2SRussell King
7673b6a2beSRussell King #define ICS_TYPE_A3IN 0
7773b6a2beSRussell King #define ICS_TYPE_A3USER 1
7873b6a2beSRussell King #define ICS_TYPE_V6 3
7973b6a2beSRussell King #define ICS_TYPE_V5 15
8073b6a2beSRussell King #define ICS_TYPE_NOTYPE ((unsigned int)-1)
8173b6a2beSRussell King
8273b6a2beSRussell King /* ---------------- Version 5 PCB Support Functions --------------------- */
8373b6a2beSRussell King /* Prototype: pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
8473b6a2beSRussell King * Purpose : enable interrupts from card
8573b6a2beSRussell King */
pata_icside_irqenable_arcin_v5(struct expansion_card * ec,int irqnr)8673b6a2beSRussell King static void pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
8773b6a2beSRussell King {
8873b6a2beSRussell King struct pata_icside_state *state = ec->irq_data;
8973b6a2beSRussell King
9073b6a2beSRussell King writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
9173b6a2beSRussell King }
9273b6a2beSRussell King
9373b6a2beSRussell King /* Prototype: pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
9473b6a2beSRussell King * Purpose : disable interrupts from card
9573b6a2beSRussell King */
pata_icside_irqdisable_arcin_v5(struct expansion_card * ec,int irqnr)9673b6a2beSRussell King static void pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
9773b6a2beSRussell King {
9873b6a2beSRussell King struct pata_icside_state *state = ec->irq_data;
9973b6a2beSRussell King
10073b6a2beSRussell King readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
10173b6a2beSRussell King }
10273b6a2beSRussell King
10373b6a2beSRussell King static const expansioncard_ops_t pata_icside_ops_arcin_v5 = {
10473b6a2beSRussell King .irqenable = pata_icside_irqenable_arcin_v5,
10573b6a2beSRussell King .irqdisable = pata_icside_irqdisable_arcin_v5,
10673b6a2beSRussell King };
10773b6a2beSRussell King
10873b6a2beSRussell King
10973b6a2beSRussell King /* ---------------- Version 6 PCB Support Functions --------------------- */
11073b6a2beSRussell King /* Prototype: pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
11173b6a2beSRussell King * Purpose : enable interrupts from card
11273b6a2beSRussell King */
pata_icside_irqenable_arcin_v6(struct expansion_card * ec,int irqnr)11373b6a2beSRussell King static void pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
11473b6a2beSRussell King {
11573b6a2beSRussell King struct pata_icside_state *state = ec->irq_data;
11673b6a2beSRussell King void __iomem *base = state->irq_port;
11773b6a2beSRussell King
11873b6a2beSRussell King if (!state->port[0].disabled)
11973b6a2beSRussell King writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
12073b6a2beSRussell King if (!state->port[1].disabled)
12173b6a2beSRussell King writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
12273b6a2beSRussell King }
12373b6a2beSRussell King
12473b6a2beSRussell King /* Prototype: pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
12573b6a2beSRussell King * Purpose : disable interrupts from card
12673b6a2beSRussell King */
pata_icside_irqdisable_arcin_v6(struct expansion_card * ec,int irqnr)12773b6a2beSRussell King static void pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
12873b6a2beSRussell King {
12973b6a2beSRussell King struct pata_icside_state *state = ec->irq_data;
13073b6a2beSRussell King
13173b6a2beSRussell King readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
13273b6a2beSRussell King readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
13373b6a2beSRussell King }
13473b6a2beSRussell King
13573b6a2beSRussell King /* Prototype: pata_icside_irqprobe(struct expansion_card *ec)
13673b6a2beSRussell King * Purpose : detect an active interrupt from card
13773b6a2beSRussell King */
pata_icside_irqpending_arcin_v6(struct expansion_card * ec)13873b6a2beSRussell King static int pata_icside_irqpending_arcin_v6(struct expansion_card *ec)
13973b6a2beSRussell King {
14073b6a2beSRussell King struct pata_icside_state *state = ec->irq_data;
14173b6a2beSRussell King
14273b6a2beSRussell King return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
14373b6a2beSRussell King readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
14473b6a2beSRussell King }
14573b6a2beSRussell King
14673b6a2beSRussell King static const expansioncard_ops_t pata_icside_ops_arcin_v6 = {
14773b6a2beSRussell King .irqenable = pata_icside_irqenable_arcin_v6,
14873b6a2beSRussell King .irqdisable = pata_icside_irqdisable_arcin_v6,
14973b6a2beSRussell King .irqpending = pata_icside_irqpending_arcin_v6,
15073b6a2beSRussell King };
15173b6a2beSRussell King
15273b6a2beSRussell King
15373b6a2beSRussell King /*
15473b6a2beSRussell King * SG-DMA support.
15573b6a2beSRussell King *
15673b6a2beSRussell King * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
15773b6a2beSRussell King * There is only one DMA controller per card, which means that only
15873b6a2beSRussell King * one drive can be accessed at one time. NOTE! We do not enforce that
15973b6a2beSRussell King * here, but we rely on the main IDE driver spotting that both
16073b6a2beSRussell King * interfaces use the same IRQ, which should guarantee this.
16173b6a2beSRussell King */
16273b6a2beSRussell King
16373b6a2beSRussell King /*
16473b6a2beSRussell King * Configure the IOMD to give the appropriate timings for the transfer
16573b6a2beSRussell King * mode being requested. We take the advice of the ATA standards, and
16673b6a2beSRussell King * calculate the cycle time based on the transfer mode, and the EIDE
16773b6a2beSRussell King * MW DMA specs that the drive provides in the IDENTIFY command.
16873b6a2beSRussell King *
16973b6a2beSRussell King * We have the following IOMD DMA modes to choose from:
17073b6a2beSRussell King *
17173b6a2beSRussell King * Type Active Recovery Cycle
17273b6a2beSRussell King * A 250 (250) 312 (550) 562 (800)
17373b6a2beSRussell King * B 187 (200) 250 (550) 437 (750)
17473b6a2beSRussell King * C 125 (125) 125 (375) 250 (500)
17573b6a2beSRussell King * D 62 (50) 125 (375) 187 (425)
17673b6a2beSRussell King *
17773b6a2beSRussell King * (figures in brackets are actual measured timings on DIOR/DIOW)
17873b6a2beSRussell King *
17973b6a2beSRussell King * However, we also need to take care of the read/write active and
18073b6a2beSRussell King * recovery timings:
18173b6a2beSRussell King *
18273b6a2beSRussell King * Read Write
18373b6a2beSRussell King * Mode Active -- Recovery -- Cycle IOMD type
18473b6a2beSRussell King * MW0 215 50 215 480 A
18573b6a2beSRussell King * MW1 80 50 50 150 C
18673b6a2beSRussell King * MW2 70 25 25 120 C
18773b6a2beSRussell King */
pata_icside_set_dmamode(struct ata_port * ap,struct ata_device * adev)18873b6a2beSRussell King static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev)
18973b6a2beSRussell King {
19073b6a2beSRussell King struct pata_icside_state *state = ap->host->private_data;
19173b6a2beSRussell King struct ata_timing t;
19273b6a2beSRussell King unsigned int cycle;
19373b6a2beSRussell King char iomd_type;
19473b6a2beSRussell King
19573b6a2beSRussell King /*
19673b6a2beSRussell King * DMA is based on a 16MHz clock
19773b6a2beSRussell King */
19873b6a2beSRussell King if (ata_timing_compute(adev, adev->dma_mode, &t, 1000, 1))
19973b6a2beSRussell King return;
20073b6a2beSRussell King
20173b6a2beSRussell King /*
20273b6a2beSRussell King * Choose the IOMD cycle timing which ensure that the interface
20373b6a2beSRussell King * satisfies the measured active, recovery and cycle times.
20473b6a2beSRussell King */
205e53d76e6SJoe Perches if (t.active <= 50 && t.recover <= 375 && t.cycle <= 425) {
206e53d76e6SJoe Perches iomd_type = 'D';
207e53d76e6SJoe Perches cycle = 187;
208e53d76e6SJoe Perches } else if (t.active <= 125 && t.recover <= 375 && t.cycle <= 500) {
209e53d76e6SJoe Perches iomd_type = 'C';
210e53d76e6SJoe Perches cycle = 250;
211e53d76e6SJoe Perches } else if (t.active <= 200 && t.recover <= 550 && t.cycle <= 750) {
212e53d76e6SJoe Perches iomd_type = 'B';
213e53d76e6SJoe Perches cycle = 437;
214e53d76e6SJoe Perches } else {
215e53d76e6SJoe Perches iomd_type = 'A';
216e53d76e6SJoe Perches cycle = 562;
217e53d76e6SJoe Perches }
21873b6a2beSRussell King
219a9a79dfeSJoe Perches ata_dev_info(adev, "timings: act %dns rec %dns cyc %dns (%c)\n",
22073b6a2beSRussell King t.active, t.recover, t.cycle, iomd_type);
22173b6a2beSRussell King
22273b6a2beSRussell King state->port[ap->port_no].speed[adev->devno] = cycle;
22373b6a2beSRussell King }
22473b6a2beSRussell King
pata_icside_bmdma_setup(struct ata_queued_cmd * qc)22573b6a2beSRussell King static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
22673b6a2beSRussell King {
22773b6a2beSRussell King struct ata_port *ap = qc->ap;
22873b6a2beSRussell King struct pata_icside_state *state = ap->host->private_data;
22973b6a2beSRussell King unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
23073b6a2beSRussell King
23173b6a2beSRussell King /*
23273b6a2beSRussell King * We are simplex; BUG if we try to fiddle with DMA
23373b6a2beSRussell King * while it's active.
23473b6a2beSRussell King */
23573b6a2beSRussell King BUG_ON(dma_channel_active(state->dma));
23673b6a2beSRussell King
23773b6a2beSRussell King /*
23873b6a2beSRussell King * Route the DMA signals to the correct interface
23973b6a2beSRussell King */
24073b6a2beSRussell King writeb(state->port[ap->port_no].port_sel, state->ioc_base);
24173b6a2beSRussell King
24273b6a2beSRussell King set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]);
243f6718653SRussell King set_dma_sg(state->dma, qc->sg, qc->n_elem);
24473b6a2beSRussell King set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
24573b6a2beSRussell King
24673b6a2beSRussell King /* issue r/w command */
2475682ed33STejun Heo ap->ops->sff_exec_command(ap, &qc->tf);
24873b6a2beSRussell King }
24973b6a2beSRussell King
pata_icside_bmdma_start(struct ata_queued_cmd * qc)25073b6a2beSRussell King static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
25173b6a2beSRussell King {
25273b6a2beSRussell King struct ata_port *ap = qc->ap;
25373b6a2beSRussell King struct pata_icside_state *state = ap->host->private_data;
25473b6a2beSRussell King
25573b6a2beSRussell King BUG_ON(dma_channel_active(state->dma));
25673b6a2beSRussell King enable_dma(state->dma);
25773b6a2beSRussell King }
25873b6a2beSRussell King
pata_icside_bmdma_stop(struct ata_queued_cmd * qc)25973b6a2beSRussell King static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
26073b6a2beSRussell King {
26173b6a2beSRussell King struct ata_port *ap = qc->ap;
26273b6a2beSRussell King struct pata_icside_state *state = ap->host->private_data;
26373b6a2beSRussell King
26473b6a2beSRussell King disable_dma(state->dma);
26573b6a2beSRussell King
26673b6a2beSRussell King /* see ata_bmdma_stop */
267a57c1badSAlan Cox ata_sff_dma_pause(ap);
26873b6a2beSRussell King }
26973b6a2beSRussell King
pata_icside_bmdma_status(struct ata_port * ap)27073b6a2beSRussell King static u8 pata_icside_bmdma_status(struct ata_port *ap)
27173b6a2beSRussell King {
27273b6a2beSRussell King struct pata_icside_state *state = ap->host->private_data;
27373b6a2beSRussell King void __iomem *irq_port;
27473b6a2beSRussell King
27573b6a2beSRussell King irq_port = state->irq_port + (ap->port_no ? ICS_ARCIN_V6_INTRSTAT_2 :
27673b6a2beSRussell King ICS_ARCIN_V6_INTRSTAT_1);
27773b6a2beSRussell King
27873b6a2beSRussell King return readb(irq_port) & 1 ? ATA_DMA_INTR : 0;
27973b6a2beSRussell King }
28073b6a2beSRussell King
icside_dma_init(struct pata_icside_info * info)281f95637d2SRussell King static int icside_dma_init(struct pata_icside_info *info)
28273b6a2beSRussell King {
283f95637d2SRussell King struct pata_icside_state *state = info->state;
284f95637d2SRussell King struct expansion_card *ec = info->ec;
28573b6a2beSRussell King int i;
28673b6a2beSRussell King
28773b6a2beSRussell King for (i = 0; i < ATA_MAX_DEVICES; i++) {
28873b6a2beSRussell King state->port[0].speed[i] = 480;
28973b6a2beSRussell King state->port[1].speed[i] = 480;
29073b6a2beSRussell King }
29173b6a2beSRussell King
29273b6a2beSRussell King if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
29373b6a2beSRussell King state->dma = ec->dma;
29414bdef98SErik Inge Bolsø info->mwdma_mask = ATA_MWDMA2;
29573b6a2beSRussell King }
29673b6a2beSRussell King
29773b6a2beSRussell King return 0;
29873b6a2beSRussell King }
29973b6a2beSRussell King
30073b6a2beSRussell King
301*25df73d9SBart Van Assche static const struct scsi_host_template pata_icside_sht = {
30268d1d07bSTejun Heo ATA_BASE_SHT(DRV_NAME),
30365e8617fSMing Lin .sg_tablesize = SG_MAX_SEGMENTS,
3045369bea7SRussell King .dma_boundary = IOMD_DMA_BOUNDARY,
30573b6a2beSRussell King };
30673b6a2beSRussell King
pata_icside_postreset(struct ata_link * link,unsigned int * classes)307c15fcafeSAl Viro static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
30873b6a2beSRussell King {
309c15fcafeSAl Viro struct ata_port *ap = link->ap;
31073b6a2beSRussell King struct pata_icside_state *state = ap->host->private_data;
31173b6a2beSRussell King
312eba84481SRussell King if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
3139363c382STejun Heo return ata_sff_postreset(link, classes);
31473b6a2beSRussell King
31573b6a2beSRussell King state->port[ap->port_no].disabled = 1;
31673b6a2beSRussell King
31773b6a2beSRussell King if (state->type == ICS_TYPE_V6) {
31873b6a2beSRussell King /*
31973b6a2beSRussell King * Disable interrupts from this port, otherwise we
32073b6a2beSRussell King * receive spurious interrupts from the floating
32173b6a2beSRussell King * interrupt line.
32273b6a2beSRussell King */
32373b6a2beSRussell King void __iomem *irq_port = state->irq_port +
32473b6a2beSRussell King (ap->port_no ? ICS_ARCIN_V6_INTROFFSET_2 : ICS_ARCIN_V6_INTROFFSET_1);
32573b6a2beSRussell King readb(irq_port);
32673b6a2beSRussell King }
32773b6a2beSRussell King }
32873b6a2beSRussell King
32973b6a2beSRussell King static struct ata_port_operations pata_icside_port_ops = {
3308930ff25STejun Heo .inherits = &ata_bmdma_port_ops,
33173b6a2beSRussell King /* no need to build any PRD tables for DMA */
33273b6a2beSRussell King .qc_prep = ata_noop_qc_prep,
33323ebda2fSSebastian Andrzej Siewior .sff_data_xfer = ata_sff_data_xfer32,
334029cfd6bSTejun Heo .bmdma_setup = pata_icside_bmdma_setup,
335029cfd6bSTejun Heo .bmdma_start = pata_icside_bmdma_start,
33673b6a2beSRussell King .bmdma_stop = pata_icside_bmdma_stop,
33773b6a2beSRussell King .bmdma_status = pata_icside_bmdma_status,
338029cfd6bSTejun Heo
339029cfd6bSTejun Heo .cable_detect = ata_cable_40wire,
340029cfd6bSTejun Heo .set_dmamode = pata_icside_set_dmamode,
341a1efdabaSTejun Heo .postreset = pata_icside_postreset,
3428930ff25STejun Heo
343c7087652STejun Heo .port_start = ATA_OP_NULL, /* don't need PRD table */
34473b6a2beSRussell King };
34573b6a2beSRussell King
pata_icside_setup_ioaddr(struct ata_port * ap,void __iomem * base,struct pata_icside_info * info,const struct portinfo * port)3460ec24914SGreg Kroah-Hartman static void pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
347c15fcafeSAl Viro struct pata_icside_info *info,
348c15fcafeSAl Viro const struct portinfo *port)
34973b6a2beSRussell King {
350cbcdd875STejun Heo struct ata_ioports *ioaddr = &ap->ioaddr;
351c15fcafeSAl Viro void __iomem *cmd = base + port->dataoffset;
35273b6a2beSRussell King
35373b6a2beSRussell King ioaddr->cmd_addr = cmd;
354c15fcafeSAl Viro ioaddr->data_addr = cmd + (ATA_REG_DATA << port->stepping);
355c15fcafeSAl Viro ioaddr->error_addr = cmd + (ATA_REG_ERR << port->stepping);
356c15fcafeSAl Viro ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << port->stepping);
357c15fcafeSAl Viro ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << port->stepping);
358c15fcafeSAl Viro ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << port->stepping);
359c15fcafeSAl Viro ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << port->stepping);
360c15fcafeSAl Viro ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << port->stepping);
361c15fcafeSAl Viro ioaddr->device_addr = cmd + (ATA_REG_DEVICE << port->stepping);
362c15fcafeSAl Viro ioaddr->status_addr = cmd + (ATA_REG_STATUS << port->stepping);
363c15fcafeSAl Viro ioaddr->command_addr = cmd + (ATA_REG_CMD << port->stepping);
36473b6a2beSRussell King
365c15fcafeSAl Viro ioaddr->ctl_addr = base + port->ctrloffset;
36673b6a2beSRussell King ioaddr->altstatus_addr = ioaddr->ctl_addr;
367cbcdd875STejun Heo
368cbcdd875STejun Heo ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
369c15fcafeSAl Viro info->raw_base + port->dataoffset,
370c15fcafeSAl Viro info->raw_base + port->ctrloffset);
371cbcdd875STejun Heo
372cbcdd875STejun Heo if (info->raw_ioc_base)
373cbcdd875STejun Heo ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base);
37473b6a2beSRussell King }
37573b6a2beSRussell King
pata_icside_register_v5(struct pata_icside_info * info)3760ec24914SGreg Kroah-Hartman static int pata_icside_register_v5(struct pata_icside_info *info)
37773b6a2beSRussell King {
378f95637d2SRussell King struct pata_icside_state *state = info->state;
37973b6a2beSRussell King void __iomem *base;
38073b6a2beSRussell King
38110bdaaa0SRussell King base = ecardm_iomap(info->ec, ECARD_RES_MEMC, 0, 0);
38273b6a2beSRussell King if (!base)
38373b6a2beSRussell King return -ENOMEM;
38473b6a2beSRussell King
38573b6a2beSRussell King state->irq_port = base;
38673b6a2beSRussell King
387f95637d2SRussell King info->base = base;
388f95637d2SRussell King info->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
389f95637d2SRussell King info->irqmask = 1;
390f95637d2SRussell King info->irqops = &pata_icside_ops_arcin_v5;
391f95637d2SRussell King info->nr_ports = 1;
392f95637d2SRussell King info->port[0] = &pata_icside_portinfo_v5;
39373b6a2beSRussell King
394c15fcafeSAl Viro info->raw_base = ecard_resource_start(info->ec, ECARD_RES_MEMC);
395cbcdd875STejun Heo
39673b6a2beSRussell King return 0;
39773b6a2beSRussell King }
39873b6a2beSRussell King
pata_icside_register_v6(struct pata_icside_info * info)3990ec24914SGreg Kroah-Hartman static int pata_icside_register_v6(struct pata_icside_info *info)
40073b6a2beSRussell King {
401f95637d2SRussell King struct pata_icside_state *state = info->state;
402f95637d2SRussell King struct expansion_card *ec = info->ec;
40373b6a2beSRussell King void __iomem *ioc_base, *easi_base;
40473b6a2beSRussell King unsigned int sel = 0;
40573b6a2beSRussell King
40610bdaaa0SRussell King ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
40710bdaaa0SRussell King if (!ioc_base)
40810bdaaa0SRussell King return -ENOMEM;
40973b6a2beSRussell King
41073b6a2beSRussell King easi_base = ioc_base;
41173b6a2beSRussell King
41273b6a2beSRussell King if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
41310bdaaa0SRussell King easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
41410bdaaa0SRussell King if (!easi_base)
41510bdaaa0SRussell King return -ENOMEM;
41673b6a2beSRussell King
41773b6a2beSRussell King /*
41873b6a2beSRussell King * Enable access to the EASI region.
41973b6a2beSRussell King */
42073b6a2beSRussell King sel = 1 << 5;
42173b6a2beSRussell King }
42273b6a2beSRussell King
42373b6a2beSRussell King writeb(sel, ioc_base);
42473b6a2beSRussell King
42573b6a2beSRussell King state->irq_port = easi_base;
42673b6a2beSRussell King state->ioc_base = ioc_base;
42773b6a2beSRussell King state->port[0].port_sel = sel;
42873b6a2beSRussell King state->port[1].port_sel = sel | 1;
42973b6a2beSRussell King
430f95637d2SRussell King info->base = easi_base;
431f95637d2SRussell King info->irqops = &pata_icside_ops_arcin_v6;
432f95637d2SRussell King info->nr_ports = 2;
433f95637d2SRussell King info->port[0] = &pata_icside_portinfo_v6_1;
434f95637d2SRussell King info->port[1] = &pata_icside_portinfo_v6_2;
43573b6a2beSRussell King
436cbcdd875STejun Heo info->raw_base = ecard_resource_start(ec, ECARD_RES_EASI);
437cbcdd875STejun Heo info->raw_ioc_base = ecard_resource_start(ec, ECARD_RES_IOCFAST);
438cbcdd875STejun Heo
439f95637d2SRussell King return icside_dma_init(info);
440f95637d2SRussell King }
441f95637d2SRussell King
pata_icside_add_ports(struct pata_icside_info * info)4420ec24914SGreg Kroah-Hartman static int pata_icside_add_ports(struct pata_icside_info *info)
443f95637d2SRussell King {
444f95637d2SRussell King struct expansion_card *ec = info->ec;
445f95637d2SRussell King struct ata_host *host;
446f95637d2SRussell King int i;
447f95637d2SRussell King
448f95637d2SRussell King if (info->irqaddr) {
449f95637d2SRussell King ec->irqaddr = info->irqaddr;
450f95637d2SRussell King ec->irqmask = info->irqmask;
451f95637d2SRussell King }
452f95637d2SRussell King if (info->irqops)
453f95637d2SRussell King ecard_setirq(ec, info->irqops, info->state);
454f95637d2SRussell King
455f95637d2SRussell King /*
456f95637d2SRussell King * Be on the safe side - disable interrupts
457f95637d2SRussell King */
458f95637d2SRussell King ec->ops->irqdisable(ec, ec->irq);
459f95637d2SRussell King
460f95637d2SRussell King host = ata_host_alloc(&ec->dev, info->nr_ports);
461f95637d2SRussell King if (!host)
462f95637d2SRussell King return -ENOMEM;
463f95637d2SRussell King
464f95637d2SRussell King host->private_data = info->state;
465f95637d2SRussell King host->flags = ATA_HOST_SIMPLEX;
466f95637d2SRussell King
467f95637d2SRussell King for (i = 0; i < info->nr_ports; i++) {
468f95637d2SRussell King struct ata_port *ap = host->ports[i];
469f95637d2SRussell King
47014bdef98SErik Inge Bolsø ap->pio_mask = ATA_PIO4;
471f95637d2SRussell King ap->mwdma_mask = info->mwdma_mask;
4721d2808fdSJeff Garzik ap->flags |= ATA_FLAG_SLAVE_POSS;
473f95637d2SRussell King ap->ops = &pata_icside_port_ops;
474f95637d2SRussell King
475c15fcafeSAl Viro pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
476f95637d2SRussell King }
477f95637d2SRussell King
478c3b28894STejun Heo return ata_host_activate(host, ec->irq, ata_bmdma_interrupt, 0,
479f95637d2SRussell King &pata_icside_sht);
48073b6a2beSRussell King }
48173b6a2beSRussell King
pata_icside_probe(struct expansion_card * ec,const struct ecard_id * id)4820ec24914SGreg Kroah-Hartman static int pata_icside_probe(struct expansion_card *ec,
4830ec24914SGreg Kroah-Hartman const struct ecard_id *id)
48473b6a2beSRussell King {
48573b6a2beSRussell King struct pata_icside_state *state;
486f95637d2SRussell King struct pata_icside_info info;
48773b6a2beSRussell King void __iomem *idmem;
48873b6a2beSRussell King int ret;
48973b6a2beSRussell King
49073b6a2beSRussell King ret = ecard_request_resources(ec);
49173b6a2beSRussell King if (ret)
49273b6a2beSRussell King goto out;
49373b6a2beSRussell King
494f95637d2SRussell King state = devm_kzalloc(&ec->dev, sizeof(*state), GFP_KERNEL);
49573b6a2beSRussell King if (!state) {
49673b6a2beSRussell King ret = -ENOMEM;
49773b6a2beSRussell King goto release;
49873b6a2beSRussell King }
49973b6a2beSRussell King
50073b6a2beSRussell King state->type = ICS_TYPE_NOTYPE;
50173b6a2beSRussell King state->dma = NO_DMA;
50273b6a2beSRussell King
50310bdaaa0SRussell King idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
50473b6a2beSRussell King if (idmem) {
50573b6a2beSRussell King unsigned int type;
50673b6a2beSRussell King
50773b6a2beSRussell King type = readb(idmem + ICS_IDENT_OFFSET) & 1;
50873b6a2beSRussell King type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
50973b6a2beSRussell King type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
51073b6a2beSRussell King type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
51110bdaaa0SRussell King ecardm_iounmap(ec, idmem);
51273b6a2beSRussell King
51373b6a2beSRussell King state->type = type;
51473b6a2beSRussell King }
51573b6a2beSRussell King
516f95637d2SRussell King memset(&info, 0, sizeof(info));
517f95637d2SRussell King info.state = state;
518f95637d2SRussell King info.ec = ec;
51973b6a2beSRussell King
52073b6a2beSRussell King switch (state->type) {
52173b6a2beSRussell King case ICS_TYPE_A3IN:
52273b6a2beSRussell King dev_warn(&ec->dev, "A3IN unsupported\n");
52373b6a2beSRussell King ret = -ENODEV;
52473b6a2beSRussell King break;
52573b6a2beSRussell King
52673b6a2beSRussell King case ICS_TYPE_A3USER:
52773b6a2beSRussell King dev_warn(&ec->dev, "A3USER unsupported\n");
52873b6a2beSRussell King ret = -ENODEV;
52973b6a2beSRussell King break;
53073b6a2beSRussell King
53173b6a2beSRussell King case ICS_TYPE_V5:
532f95637d2SRussell King ret = pata_icside_register_v5(&info);
53373b6a2beSRussell King break;
53473b6a2beSRussell King
53573b6a2beSRussell King case ICS_TYPE_V6:
536f95637d2SRussell King ret = pata_icside_register_v6(&info);
53773b6a2beSRussell King break;
53873b6a2beSRussell King
53973b6a2beSRussell King default:
54073b6a2beSRussell King dev_warn(&ec->dev, "unknown interface type\n");
54173b6a2beSRussell King ret = -ENODEV;
54273b6a2beSRussell King break;
54373b6a2beSRussell King }
54473b6a2beSRussell King
54573b6a2beSRussell King if (ret == 0)
546f95637d2SRussell King ret = pata_icside_add_ports(&info);
54773b6a2beSRussell King
54873b6a2beSRussell King if (ret == 0)
54973b6a2beSRussell King goto out;
55073b6a2beSRussell King
55173b6a2beSRussell King release:
55273b6a2beSRussell King ecard_release_resources(ec);
55373b6a2beSRussell King out:
55473b6a2beSRussell King return ret;
55573b6a2beSRussell King }
55673b6a2beSRussell King
pata_icside_shutdown(struct expansion_card * ec)55773b6a2beSRussell King static void pata_icside_shutdown(struct expansion_card *ec)
55873b6a2beSRussell King {
55973b6a2beSRussell King struct ata_host *host = ecard_get_drvdata(ec);
56073b6a2beSRussell King unsigned long flags;
56173b6a2beSRussell King
56273b6a2beSRussell King /*
56373b6a2beSRussell King * Disable interrupts from this card. We need to do
56473b6a2beSRussell King * this before disabling EASI since we may be accessing
56573b6a2beSRussell King * this register via that region.
56673b6a2beSRussell King */
56773b6a2beSRussell King local_irq_save(flags);
56873b6a2beSRussell King ec->ops->irqdisable(ec, ec->irq);
56973b6a2beSRussell King local_irq_restore(flags);
57073b6a2beSRussell King
57173b6a2beSRussell King /*
57273b6a2beSRussell King * Reset the ROM pointer so that we can read the ROM
57373b6a2beSRussell King * after a soft reboot. This also disables access to
57473b6a2beSRussell King * the IDE taskfile via the EASI region.
57573b6a2beSRussell King */
57673b6a2beSRussell King if (host) {
57773b6a2beSRussell King struct pata_icside_state *state = host->private_data;
57873b6a2beSRussell King if (state->ioc_base)
57973b6a2beSRussell King writeb(0, state->ioc_base);
58073b6a2beSRussell King }
58173b6a2beSRussell King }
58273b6a2beSRussell King
pata_icside_remove(struct expansion_card * ec)5830ec24914SGreg Kroah-Hartman static void pata_icside_remove(struct expansion_card *ec)
58473b6a2beSRussell King {
58573b6a2beSRussell King struct ata_host *host = ecard_get_drvdata(ec);
58673b6a2beSRussell King struct pata_icside_state *state = host->private_data;
58773b6a2beSRussell King
58873b6a2beSRussell King ata_host_detach(host);
58973b6a2beSRussell King
59073b6a2beSRussell King pata_icside_shutdown(ec);
59173b6a2beSRussell King
59273b6a2beSRussell King /*
59373b6a2beSRussell King * don't NULL out the drvdata - devres/libata wants it
59473b6a2beSRussell King * to free the ata_host structure.
59573b6a2beSRussell King */
59673b6a2beSRussell King if (state->dma != NO_DMA)
59773b6a2beSRussell King free_dma(state->dma);
59873b6a2beSRussell King
59973b6a2beSRussell King ecard_release_resources(ec);
60073b6a2beSRussell King }
60173b6a2beSRussell King
60273b6a2beSRussell King static const struct ecard_id pata_icside_ids[] = {
60373b6a2beSRussell King { MANU_ICS, PROD_ICS_IDE },
60473b6a2beSRussell King { MANU_ICS2, PROD_ICS2_IDE },
60573b6a2beSRussell King { 0xffff, 0xffff }
60673b6a2beSRussell King };
60773b6a2beSRussell King
60873b6a2beSRussell King static struct ecard_driver pata_icside_driver = {
60973b6a2beSRussell King .probe = pata_icside_probe,
6100ec24914SGreg Kroah-Hartman .remove = pata_icside_remove,
61173b6a2beSRussell King .shutdown = pata_icside_shutdown,
61273b6a2beSRussell King .id_table = pata_icside_ids,
61373b6a2beSRussell King .drv = {
61473b6a2beSRussell King .name = DRV_NAME,
61573b6a2beSRussell King },
61673b6a2beSRussell King };
61773b6a2beSRussell King
pata_icside_init(void)61873b6a2beSRussell King static int __init pata_icside_init(void)
61973b6a2beSRussell King {
62073b6a2beSRussell King return ecard_register_driver(&pata_icside_driver);
62173b6a2beSRussell King }
62273b6a2beSRussell King
pata_icside_exit(void)62373b6a2beSRussell King static void __exit pata_icside_exit(void)
62473b6a2beSRussell King {
62573b6a2beSRussell King ecard_remove_driver(&pata_icside_driver);
62673b6a2beSRussell King }
62773b6a2beSRussell King
62873b6a2beSRussell King MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
62973b6a2beSRussell King MODULE_LICENSE("GPL");
63073b6a2beSRussell King MODULE_DESCRIPTION("ICS PATA driver");
63173b6a2beSRussell King
63273b6a2beSRussell King module_init(pata_icside_init);
63373b6a2beSRussell King module_exit(pata_icside_exit);
634