^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^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/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/jazz.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/jazzdma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "esp_scsi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DRV_MODULE_NAME "jazz_esp"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PFX DRV_MODULE_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DRV_VERSION "1.000"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DRV_MODULE_RELDATE "May 19, 2007"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *(volatile u8 *)(esp->regs + reg) = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return *(volatile u8 *)(esp->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int jazz_esp_irq_pending(struct esp *esp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void jazz_esp_reset_dma(struct esp *esp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) vdma_disable ((int)esp->dma_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void jazz_esp_dma_drain(struct esp *esp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void jazz_esp_dma_invalidate(struct esp *esp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) vdma_disable ((int)esp->dma_regs);
^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) static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 dma_count, int write, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) BUG_ON(!(cmd & ESP_CMD_DMA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) vdma_disable ((int)esp->dma_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) vdma_set_addr ((int)esp->dma_regs, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) vdma_set_count ((int)esp->dma_regs, dma_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) vdma_enable ((int)esp->dma_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) scsi_esp_cmd(esp, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int jazz_esp_dma_error(struct esp *esp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u32 enable = vdma_get_enable((int)esp->dma_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static const struct esp_driver_ops jazz_esp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .esp_write8 = jazz_esp_write8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .esp_read8 = jazz_esp_read8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .irq_pending = jazz_esp_irq_pending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .reset_dma = jazz_esp_reset_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .dma_drain = jazz_esp_dma_drain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .dma_invalidate = jazz_esp_dma_invalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .send_dma_cmd = jazz_esp_send_dma_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .dma_error = jazz_esp_dma_error,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int esp_jazz_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct scsi_host_template *tpnt = &scsi_esp_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct Scsi_Host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct esp *esp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) host = scsi_host_alloc(tpnt, sizeof(struct esp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) host->max_id = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) esp = shost_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) esp->host = host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) esp->dev = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) esp->ops = &jazz_esp_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) res = platform_get_resource(dev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) goto fail_unlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) esp->regs = (void __iomem *)res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!esp->regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto fail_unlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) res = platform_get_resource(dev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto fail_unlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) esp->dma_regs = (void __iomem *)res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) esp->command_block = dma_alloc_coherent(esp->dev, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) &esp->command_block_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!esp->command_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto fail_unmap_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) host->irq = err = platform_get_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto fail_unmap_command_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) goto fail_unmap_command_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) esp->scsi_id = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) esp->host->this_id = esp->scsi_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) esp->scsi_id_mask = (1 << esp->scsi_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) esp->cfreq = 40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dev_set_drvdata(&dev->dev, esp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) err = scsi_esp_register(esp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) goto fail_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) fail_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) free_irq(host->irq, esp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fail_unmap_command_block:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dma_free_coherent(esp->dev, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) esp->command_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) esp->command_block_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) fail_unmap_regs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fail_unlink:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) scsi_host_put(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int esp_jazz_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct esp *esp = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned int irq = esp->host->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) scsi_esp_unregister(esp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) free_irq(irq, esp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dma_free_coherent(esp->dev, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) esp->command_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) esp->command_block_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) scsi_host_put(esp->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* work with hotplug and coldplug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) MODULE_ALIAS("platform:jazz_esp");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static struct platform_driver esp_jazz_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .probe = esp_jazz_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .remove = esp_jazz_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .name = "jazz_esp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) module_platform_driver(esp_jazz_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) MODULE_VERSION(DRV_VERSION);