^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Buddha, Catweasel and X-Surf PATA controller driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2018 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * http://www.samsung.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on buddha.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/ata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/libata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/zorro.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <scsi/scsi_cmnd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/amigahw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/amigaints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/ide.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DRV_NAME "pata_buddha"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DRV_VERSION "0.1.1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BUDDHA_BASE1 0x800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define BUDDHA_BASE2 0xa00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define BUDDHA_BASE3 0xc00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define XSURF_BASE1 0xb000 /* 2.5" interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define XSURF_BASE2 0xd000 /* 3.5" interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define BUDDHA_CONTROL 0x11a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define BUDDHA_IRQ 0xf00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define XSURF_IRQ 0x7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) BOARD_BUDDHA = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) BOARD_CATWEASEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) BOARD_XSURF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static unsigned int buddha_bases[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static unsigned int xsurf_bases[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) XSURF_BASE1, XSURF_BASE2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static struct scsi_host_template pata_buddha_sht = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ATA_PIO_SHT(DRV_NAME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* FIXME: is this needed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static unsigned int pata_buddha_data_xfer(struct ata_queued_cmd *qc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned int buflen, int rw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct ata_device *dev = qc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct ata_port *ap = dev->link->ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void __iomem *data_addr = ap->ioaddr.data_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int words = buflen >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Transfer multiple of 2 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (rw == READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) raw_insw((u16 *)data_addr, (u16 *)buf, words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) raw_outsw((u16 *)data_addr, (u16 *)buf, words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Transfer trailing byte, if any. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (unlikely(buflen & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned char pad[2] = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Point buf to the tail of buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) buf += buflen - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (rw == READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) raw_insw((u16 *)data_addr, (u16 *)pad, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *buf = pad[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pad[0] = *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) raw_outsw((u16 *)data_addr, (u16 *)pad, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) words++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return words << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Provide our own set_mode() as we don't want to change anything that has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * already been configured..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int pata_buddha_set_mode(struct ata_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct ata_device **unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct ata_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ata_for_each_dev(dev, link, ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* We don't really care */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dev->xfer_shift = ATA_SHIFT_PIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev->flags |= ATA_DFLAG_PIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ata_dev_info(dev, "configured for PIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static bool pata_buddha_irq_check(struct ata_port *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u8 ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ch = z_readb((unsigned long)ap->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return !!(ch & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static void pata_xsurf_irq_clear(struct ata_port *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) z_writeb(0, (unsigned long)ap->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static struct ata_port_operations pata_buddha_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .inherits = &ata_sff_port_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .sff_data_xfer = pata_buddha_data_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .sff_irq_check = pata_buddha_irq_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .cable_detect = ata_cable_unknown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .set_mode = pata_buddha_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct ata_port_operations pata_xsurf_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .inherits = &ata_sff_port_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .sff_data_xfer = pata_buddha_data_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .sff_irq_check = pata_buddha_irq_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .sff_irq_clear = pata_xsurf_irq_clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .cable_detect = ata_cable_unknown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .set_mode = pata_buddha_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int pata_buddha_probe(struct zorro_dev *z,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) const struct zorro_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static const char * const board_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) "Buddha", "Catweasel", "X-Surf"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct ata_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) void __iomem *buddha_board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int type = ent->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned int nr_ports = (type == BOARD_CATWEASEL) ? 3 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void *old_drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dev_info(&z->dev, "%s IDE controller\n", board_name[type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) board = z->resource.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (type != BOARD_XSURF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!devm_request_mem_region(&z->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) board + BUDDHA_BASE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 0x800, DRV_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (!devm_request_mem_region(&z->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) board + XSURF_BASE1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 0x1000, DRV_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!devm_request_mem_region(&z->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) board + XSURF_BASE2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 0x1000, DRV_NAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Workaround for X-Surf: Save drvdata in case zorro8390 has set it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (type == BOARD_XSURF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) old_drvdata = dev_get_drvdata(&z->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* allocate host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) host = ata_host_alloc(&z->dev, nr_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (type == BOARD_XSURF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_set_drvdata(&z->dev, old_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) buddha_board = ZTWO_VADDR(board);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* enable the board IRQ on Buddha/Catweasel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (type != BOARD_XSURF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) z_writeb(0, buddha_board + BUDDHA_IRQ_MR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) for (i = 0; i < nr_ports; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct ata_port *ap = host->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) void __iomem *base, *irqport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned long ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (type != BOARD_XSURF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ap->ops = &pata_buddha_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) base = buddha_board + buddha_bases[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ctl = BUDDHA_CONTROL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) irqport = buddha_board + BUDDHA_IRQ + i * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ap->ops = &pata_xsurf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) base = buddha_board + xsurf_bases[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* X-Surf has no CS1* (Control/AltStat) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) irqport = buddha_board + XSURF_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ap->pio_mask = ATA_PIO4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ap->ioaddr.data_addr = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ap->ioaddr.error_addr = base + 2 + 1 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ap->ioaddr.feature_addr = base + 2 + 1 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ap->ioaddr.nsect_addr = base + 2 + 2 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ap->ioaddr.lbal_addr = base + 2 + 3 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ap->ioaddr.lbam_addr = base + 2 + 4 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ap->ioaddr.lbah_addr = base + 2 + 5 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ap->ioaddr.device_addr = base + 2 + 6 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ap->ioaddr.status_addr = base + 2 + 7 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ap->ioaddr.command_addr = base + 2 + 7 * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ctl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ap->ioaddr.altstatus_addr = base + ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ap->ioaddr.ctl_addr = base + ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ap->private_data = (void *)irqport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", board,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ctl ? board + buddha_bases[i] + ctl : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ata_host_activate(host, IRQ_AMIGA_PORTS, ata_sff_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) IRQF_SHARED, &pata_buddha_sht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static void pata_buddha_remove(struct zorro_dev *z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct ata_host *host = dev_get_drvdata(&z->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ata_host_detach(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static const struct zorro_device_id pata_buddha_zorro_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA, BOARD_BUDDHA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL, BOARD_CATWEASEL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) MODULE_DEVICE_TABLE(zorro, pata_buddha_zorro_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct zorro_driver pata_buddha_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .name = "pata_buddha",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .id_table = pata_buddha_zorro_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .probe = pata_buddha_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .remove = pata_buddha_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * We cannot have a modalias for X-Surf boards, as it competes with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * zorro8390 network driver. As a stopgap measure until we have proper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * MFD support for this board, we manually attach to it late after Zorro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * has enumerated its boards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int __init pata_buddha_late_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct zorro_dev *z = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* Auto-bind to regular boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) zorro_register_driver(&pata_buddha_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Manually bind to all X-Surf boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) while ((z = zorro_find_device(ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, z))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static struct zorro_device_id xsurf_ent = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, BOARD_XSURF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) pata_buddha_probe(z, &xsurf_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) late_initcall(pata_buddha_late_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) MODULE_DESCRIPTION("low-level driver for Buddha/Catweasel/X-Surf PATA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) MODULE_VERSION(DRV_VERSION);