^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) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/mvme147hw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "scsi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "wd33c93.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "mvme147.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static irqreturn_t mvme147_intr(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct Scsi_Host *instance = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (irq == MVME147_IRQ_SCSI_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) wd33c93_intr(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) m147_pcc->dma_intr = 0x89; /* Ack and enable ints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct Scsi_Host *instance = cmd->device->host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct WD33C93_hostdata *hdata = shost_priv(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned char flags = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned long addr = virt_to_bus(cmd->SCp.ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* setup dma direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!dir_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) flags |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* remember direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) hdata->dma_dir = dir_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (dir_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* invalidate any cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cache_clear(addr, cmd->SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* push any dirty cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) cache_push(addr, cmd->SCp.this_residual);
^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) /* start DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) m147_pcc->dma_bcr = cmd->SCp.this_residual | (1 << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) m147_pcc->dma_dadr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) m147_pcc->dma_cntrl = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* return success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) m147_pcc->dma_cntrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct scsi_host_template mvme147_host_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .proc_name = "MVME147",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .name = "MVME147 built-in SCSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .queuecommand = wd33c93_queuecommand,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .eh_abort_handler = wd33c93_abort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .eh_host_reset_handler = wd33c93_host_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .show_info = wd33c93_show_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .write_info = wd33c93_write_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .can_queue = CAN_QUEUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .this_id = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .sg_tablesize = SG_ALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .cmd_per_lun = CMD_PER_LUN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct Scsi_Host *mvme147_shost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int __init mvme147_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) wd33c93_regs regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct WD33C93_hostdata *hdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!MACH_IS_MVME147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) mvme147_shost = scsi_host_alloc(&mvme147_host_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) sizeof(struct WD33C93_hostdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!mvme147_shost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mvme147_shost->base = 0xfffe4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) mvme147_shost->irq = MVME147_IRQ_SCSI_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) regs.SASR = (volatile unsigned char *)0xfffe4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) regs.SCMD = (volatile unsigned char *)0xfffe4001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) hdata = shost_priv(mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) hdata->no_sync = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) hdata->fast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) hdata->dma_mode = CTRL_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) wd33c93_init(mvme147_shost, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) error = request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "MVME147 SCSI PORT", mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) goto err_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) error = request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "MVME147 SCSI DMA", mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #if 0 /* Disabled; causes problems booting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) m147_pcc->scsi_interrupt = 0x00; /* Negate SCSI bus reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) udelay(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) m147_pcc->scsi_interrupt = 0x40; /* Clear bus reset interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) m147_pcc->scsi_interrupt = 0x09; /* Enable interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) m147_pcc->dma_intr = 0x89; /* Ack and enable ints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) error = scsi_add_host(mvme147_shost, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) scsi_scan_host(mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) err_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) err_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) scsi_host_put(mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static void __exit mvme147_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) scsi_remove_host(mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* XXX Make sure DMA is stopped! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) free_irq(MVME147_IRQ_SCSI_DMA, mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) scsi_host_put(mvme147_shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) module_init(mvme147_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) module_exit(mvme147_exit);