Skip to content

Commit 9ab27d1

Browse files
bzolnierhtejun
authored andcommitted
ata: add Amiga Gayle PATA controller driver
Add Amiga Gayle PATA controller driver. It enables libata support for the on-board IDE interfaces on some Amiga models (A600, A1200, A4000 and A4000T) and also for IDE interfaces on the Zorro expansion bus (M-Tech E-Matrix 530 expansion card). Thanks to John Paul Adrian Glaubitz and Michael Schmitz for help with testing the driver. Tested-by: John Paul Adrian Glaubitz <[email protected]> Cc: Michael Schmitz <[email protected]> Cc: Geert Uytterhoeven <[email protected]> Cc: Philippe Ombredanne <[email protected]> Cc: Andy Shevchenko <[email protected]> Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent e587873 commit 9ab27d1

File tree

3 files changed

+232
-0
lines changed

3 files changed

+232
-0
lines changed

drivers/ata/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,18 @@ config PATA_FALCON
963963

964964
If unsure, say N.
965965

966+
config PATA_GAYLE
967+
tristate "Amiga Gayle PATA support"
968+
depends on M68K && AMIGA
969+
help
970+
This option enables support for the on-board IDE
971+
interfaces on some Amiga models (A600, A1200,
972+
A4000 and A4000T) and also for IDE interfaces on
973+
the Zorro expansion bus (M-Tech E-Matrix 530
974+
expansion card).
975+
976+
If unsure, say N.
977+
966978
config PATA_ISAPNP
967979
tristate "ISA Plug and Play PATA support"
968980
depends on ISAPNP

drivers/ata/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
9898
# SFF PIO only
9999
obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o
100100
obj-$(CONFIG_PATA_FALCON) += pata_falcon.o
101+
obj-$(CONFIG_PATA_GAYLE) += pata_gayle.o
101102
obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o
102103
obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
103104
obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o

drivers/ata/pata_gayle.c

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Amiga Gayle PATA controller driver
5+
*
6+
* Copyright (c) 2018 Samsung Electronics Co., Ltd.
7+
* http://www.samsung.com
8+
*
9+
* Based on gayle.c:
10+
*
11+
* Created 12 Jul 1997 by Geert Uytterhoeven
12+
*/
13+
14+
#include <linux/ata.h>
15+
#include <linux/blkdev.h>
16+
#include <linux/delay.h>
17+
#include <linux/interrupt.h>
18+
#include <linux/kernel.h>
19+
#include <linux/libata.h>
20+
#include <linux/mm.h>
21+
#include <linux/module.h>
22+
#include <linux/platform_device.h>
23+
#include <linux/zorro.h>
24+
#include <scsi/scsi_cmnd.h>
25+
#include <scsi/scsi_host.h>
26+
27+
#include <asm/amigahw.h>
28+
#include <asm/amigaints.h>
29+
#include <asm/amigayle.h>
30+
#include <asm/ide.h>
31+
#include <asm/setup.h>
32+
33+
#define DRV_NAME "pata_gayle"
34+
#define DRV_VERSION "0.1.0"
35+
36+
#define GAYLE_CONTROL 0x101a
37+
38+
static struct scsi_host_template pata_gayle_sht = {
39+
ATA_PIO_SHT(DRV_NAME),
40+
};
41+
42+
/* FIXME: is this needed? */
43+
static unsigned int pata_gayle_data_xfer(struct ata_queued_cmd *qc,
44+
unsigned char *buf,
45+
unsigned int buflen, int rw)
46+
{
47+
struct ata_device *dev = qc->dev;
48+
struct ata_port *ap = dev->link->ap;
49+
void __iomem *data_addr = ap->ioaddr.data_addr;
50+
unsigned int words = buflen >> 1;
51+
52+
/* Transfer multiple of 2 bytes */
53+
if (rw == READ)
54+
raw_insw((u16 *)data_addr, (u16 *)buf, words);
55+
else
56+
raw_outsw((u16 *)data_addr, (u16 *)buf, words);
57+
58+
/* Transfer trailing byte, if any. */
59+
if (unlikely(buflen & 0x01)) {
60+
unsigned char pad[2] = { };
61+
62+
/* Point buf to the tail of buffer */
63+
buf += buflen - 1;
64+
65+
if (rw == READ) {
66+
raw_insw((u16 *)data_addr, (u16 *)pad, 1);
67+
*buf = pad[0];
68+
} else {
69+
pad[0] = *buf;
70+
raw_outsw((u16 *)data_addr, (u16 *)pad, 1);
71+
}
72+
words++;
73+
}
74+
75+
return words << 1;
76+
}
77+
78+
/*
79+
* Provide our own set_mode() as we don't want to change anything that has
80+
* already been configured..
81+
*/
82+
static int pata_gayle_set_mode(struct ata_link *link,
83+
struct ata_device **unused)
84+
{
85+
struct ata_device *dev;
86+
87+
ata_for_each_dev(dev, link, ENABLED) {
88+
/* We don't really care */
89+
dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
90+
dev->xfer_shift = ATA_SHIFT_PIO;
91+
dev->flags |= ATA_DFLAG_PIO;
92+
ata_dev_info(dev, "configured for PIO\n");
93+
}
94+
return 0;
95+
}
96+
97+
static bool pata_gayle_irq_check(struct ata_port *ap)
98+
{
99+
u8 ch;
100+
101+
ch = z_readb((unsigned long)ap->private_data);
102+
103+
return !!(ch & GAYLE_IRQ_IDE);
104+
}
105+
106+
static void pata_gayle_irq_clear(struct ata_port *ap)
107+
{
108+
(void)z_readb((unsigned long)ap->ioaddr.status_addr);
109+
z_writeb(0x7c, (unsigned long)ap->private_data);
110+
}
111+
112+
static struct ata_port_operations pata_gayle_a1200_ops = {
113+
.inherits = &ata_sff_port_ops,
114+
.sff_data_xfer = pata_gayle_data_xfer,
115+
.sff_irq_check = pata_gayle_irq_check,
116+
.sff_irq_clear = pata_gayle_irq_clear,
117+
.cable_detect = ata_cable_unknown,
118+
.set_mode = pata_gayle_set_mode,
119+
};
120+
121+
static struct ata_port_operations pata_gayle_a4000_ops = {
122+
.inherits = &ata_sff_port_ops,
123+
.sff_data_xfer = pata_gayle_data_xfer,
124+
.cable_detect = ata_cable_unknown,
125+
.set_mode = pata_gayle_set_mode,
126+
};
127+
128+
static int __init pata_gayle_init_one(struct platform_device *pdev)
129+
{
130+
struct resource *res;
131+
struct gayle_ide_platform_data *pdata;
132+
struct ata_host *host;
133+
struct ata_port *ap;
134+
void __iomem *base;
135+
int ret;
136+
137+
pdata = dev_get_platdata(&pdev->dev);
138+
139+
dev_info(&pdev->dev, "Amiga Gayle IDE controller (A%u style)\n",
140+
pdata->explicit_ack ? 1200 : 4000);
141+
142+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
143+
if (!res)
144+
return -ENODEV;
145+
146+
if (!devm_request_mem_region(&pdev->dev, res->start,
147+
resource_size(res), DRV_NAME)) {
148+
pr_err(DRV_NAME ": resources busy\n");
149+
return -EBUSY;
150+
}
151+
152+
/* allocate host */
153+
host = ata_host_alloc(&pdev->dev, 1);
154+
if (!host)
155+
return -ENOMEM;
156+
157+
ap = host->ports[0];
158+
159+
if (pdata->explicit_ack)
160+
ap->ops = &pata_gayle_a1200_ops;
161+
else
162+
ap->ops = &pata_gayle_a4000_ops;
163+
164+
ap->pio_mask = ATA_PIO4;
165+
ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
166+
167+
base = ZTWO_VADDR(pdata->base);
168+
ap->ioaddr.data_addr = base;
169+
ap->ioaddr.error_addr = base + 2 + 1 * 4;
170+
ap->ioaddr.feature_addr = base + 2 + 1 * 4;
171+
ap->ioaddr.nsect_addr = base + 2 + 2 * 4;
172+
ap->ioaddr.lbal_addr = base + 2 + 3 * 4;
173+
ap->ioaddr.lbam_addr = base + 2 + 4 * 4;
174+
ap->ioaddr.lbah_addr = base + 2 + 5 * 4;
175+
ap->ioaddr.device_addr = base + 2 + 6 * 4;
176+
ap->ioaddr.status_addr = base + 2 + 7 * 4;
177+
ap->ioaddr.command_addr = base + 2 + 7 * 4;
178+
179+
ap->ioaddr.altstatus_addr = base + GAYLE_CONTROL;
180+
ap->ioaddr.ctl_addr = base + GAYLE_CONTROL;
181+
182+
ap->private_data = (void *)ZTWO_VADDR(pdata->irqport);
183+
184+
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", pdata->base,
185+
pdata->base + GAYLE_CONTROL);
186+
187+
ret = ata_host_activate(host, IRQ_AMIGA_PORTS, ata_sff_interrupt,
188+
IRQF_SHARED, &pata_gayle_sht);
189+
if (ret)
190+
return ret;
191+
192+
platform_set_drvdata(pdev, host);
193+
194+
return 0;
195+
}
196+
197+
static int __exit pata_gayle_remove_one(struct platform_device *pdev)
198+
{
199+
struct ata_host *host = platform_get_drvdata(pdev);
200+
201+
ata_host_detach(host);
202+
203+
return 0;
204+
}
205+
206+
static struct platform_driver pata_gayle_driver = {
207+
.remove = __exit_p(pata_gayle_remove_one),
208+
.driver = {
209+
.name = "amiga-gayle-ide",
210+
},
211+
};
212+
213+
module_platform_driver_probe(pata_gayle_driver, pata_gayle_init_one);
214+
215+
MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
216+
MODULE_DESCRIPTION("low-level driver for Amiga Gayle PATA");
217+
MODULE_LICENSE("GPL v2");
218+
MODULE_ALIAS("platform:amiga-gayle-ide");
219+
MODULE_VERSION(DRV_VERSION);

0 commit comments

Comments
 (0)