Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* mac_esp.c: ESP front-end for Macintosh Quadra systems.
0003  *
0004  * Adapted from jazz_esp.c and the old mac_esp.c.
0005  *
0006  * The pseudo DMA algorithm is based on the one used in NetBSD.
0007  * See sys/arch/mac68k/obio/esp.c for some background information.
0008  *
0009  * Copyright (C) 2007-2008 Finn Thain
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/types.h>
0014 #include <linux/module.h>
0015 #include <linux/init.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/dma-mapping.h>
0019 #include <linux/scatterlist.h>
0020 #include <linux/delay.h>
0021 #include <linux/io.h>
0022 #include <linux/nubus.h>
0023 #include <linux/slab.h>
0024 
0025 #include <asm/irq.h>
0026 #include <asm/dma.h>
0027 #include <asm/macints.h>
0028 #include <asm/macintosh.h>
0029 #include <asm/mac_via.h>
0030 
0031 #include <scsi/scsi_host.h>
0032 
0033 #include "esp_scsi.h"
0034 
0035 #define DRV_MODULE_NAME     "mac_esp"
0036 #define PFX                 DRV_MODULE_NAME ": "
0037 #define DRV_VERSION         "1.000"
0038 #define DRV_MODULE_RELDATE  "Sept 15, 2007"
0039 
0040 #define MAC_ESP_IO_BASE          0x50F00000
0041 #define MAC_ESP_REGS_QUADRA      (MAC_ESP_IO_BASE + 0x10000)
0042 #define MAC_ESP_REGS_QUADRA2     (MAC_ESP_IO_BASE + 0xF000)
0043 #define MAC_ESP_REGS_QUADRA3     (MAC_ESP_IO_BASE + 0x18000)
0044 #define MAC_ESP_REGS_SPACING     0x402
0045 #define MAC_ESP_PDMA_REG         0xF9800024
0046 #define MAC_ESP_PDMA_REG_SPACING 0x4
0047 #define MAC_ESP_PDMA_IO_OFFSET   0x100
0048 
0049 #define esp_read8(REG)      mac_esp_read8(esp, REG)
0050 #define esp_write8(VAL, REG)    mac_esp_write8(esp, VAL, REG)
0051 
0052 struct mac_esp_priv {
0053     struct esp *esp;
0054     void __iomem *pdma_regs;
0055     void __iomem *pdma_io;
0056 };
0057 static struct esp *esp_chips[2];
0058 static DEFINE_SPINLOCK(esp_chips_lock);
0059 
0060 #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
0061                    dev_get_drvdata((esp)->dev))
0062 
0063 static inline void mac_esp_write8(struct esp *esp, u8 val, unsigned long reg)
0064 {
0065     nubus_writeb(val, esp->regs + reg * 16);
0066 }
0067 
0068 static inline u8 mac_esp_read8(struct esp *esp, unsigned long reg)
0069 {
0070     return nubus_readb(esp->regs + reg * 16);
0071 }
0072 
0073 static void mac_esp_reset_dma(struct esp *esp)
0074 {
0075     /* Nothing to do. */
0076 }
0077 
0078 static void mac_esp_dma_drain(struct esp *esp)
0079 {
0080     /* Nothing to do. */
0081 }
0082 
0083 static void mac_esp_dma_invalidate(struct esp *esp)
0084 {
0085     /* Nothing to do. */
0086 }
0087 
0088 static int mac_esp_dma_error(struct esp *esp)
0089 {
0090     return esp->send_cmd_error;
0091 }
0092 
0093 static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
0094 {
0095     int i = 500000;
0096 
0097     do {
0098         if (!(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES))
0099             return 0;
0100 
0101         if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
0102             return 1;
0103 
0104         udelay(2);
0105     } while (--i);
0106 
0107     printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n",
0108            esp_read8(ESP_STATUS));
0109     esp->send_cmd_error = 1;
0110     return 1;
0111 }
0112 
0113 static inline int mac_esp_wait_for_dreq(struct esp *esp)
0114 {
0115     struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
0116     int i = 500000;
0117 
0118     do {
0119         if (mep->pdma_regs == NULL) {
0120             if (via2_scsi_drq_pending())
0121                 return 0;
0122         } else {
0123             if (nubus_readl(mep->pdma_regs) & 0x200)
0124                 return 0;
0125         }
0126 
0127         if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
0128             return 1;
0129 
0130         udelay(2);
0131     } while (--i);
0132 
0133     printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n",
0134            esp_read8(ESP_STATUS));
0135     esp->send_cmd_error = 1;
0136     return 1;
0137 }
0138 
0139 #define MAC_ESP_PDMA_LOOP(operands) \
0140     asm volatile ( \
0141          "       tstw %1                   \n" \
0142          "       jbeq 20f                  \n" \
0143          "1:     movew " operands "        \n" \
0144          "2:     movew " operands "        \n" \
0145          "3:     movew " operands "        \n" \
0146          "4:     movew " operands "        \n" \
0147          "5:     movew " operands "        \n" \
0148          "6:     movew " operands "        \n" \
0149          "7:     movew " operands "        \n" \
0150          "8:     movew " operands "        \n" \
0151          "9:     movew " operands "        \n" \
0152          "10:    movew " operands "        \n" \
0153          "11:    movew " operands "        \n" \
0154          "12:    movew " operands "        \n" \
0155          "13:    movew " operands "        \n" \
0156          "14:    movew " operands "        \n" \
0157          "15:    movew " operands "        \n" \
0158          "16:    movew " operands "        \n" \
0159          "       subqw #1,%1               \n" \
0160          "       jbne 1b                   \n" \
0161          "20:    tstw %2                   \n" \
0162          "       jbeq 30f                  \n" \
0163          "21:    movew " operands "        \n" \
0164          "       subqw #1,%2               \n" \
0165          "       jbne 21b                  \n" \
0166          "30:    tstw %3                   \n" \
0167          "       jbeq 40f                  \n" \
0168          "31:    moveb " operands "        \n" \
0169          "32:    nop                       \n" \
0170          "40:                              \n" \
0171          "                                 \n" \
0172          "       .section __ex_table,\"a\" \n" \
0173          "       .align  4                 \n" \
0174          "       .long   1b,40b            \n" \
0175          "       .long   2b,40b            \n" \
0176          "       .long   3b,40b            \n" \
0177          "       .long   4b,40b            \n" \
0178          "       .long   5b,40b            \n" \
0179          "       .long   6b,40b            \n" \
0180          "       .long   7b,40b            \n" \
0181          "       .long   8b,40b            \n" \
0182          "       .long   9b,40b            \n" \
0183          "       .long  10b,40b            \n" \
0184          "       .long  11b,40b            \n" \
0185          "       .long  12b,40b            \n" \
0186          "       .long  13b,40b            \n" \
0187          "       .long  14b,40b            \n" \
0188          "       .long  15b,40b            \n" \
0189          "       .long  16b,40b            \n" \
0190          "       .long  21b,40b            \n" \
0191          "       .long  31b,40b            \n" \
0192          "       .long  32b,40b            \n" \
0193          "       .previous                 \n" \
0194          : "+a" (addr), "+r" (count32), "+r" (count2) \
0195          : "g" (count1), "a" (mep->pdma_io))
0196 
0197 static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
0198                   u32 dma_count, int write, u8 cmd)
0199 {
0200     struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
0201 
0202     esp->send_cmd_error = 0;
0203 
0204     if (!write)
0205         scsi_esp_cmd(esp, ESP_CMD_FLUSH);
0206 
0207     esp_write8((esp_count >> 0) & 0xFF, ESP_TCLOW);
0208     esp_write8((esp_count >> 8) & 0xFF, ESP_TCMED);
0209 
0210     scsi_esp_cmd(esp, cmd);
0211 
0212     do {
0213         unsigned int count32 = esp_count >> 5;
0214         unsigned int count2 = (esp_count & 0x1F) >> 1;
0215         unsigned int count1 = esp_count & 1;
0216         unsigned int start_addr = addr;
0217 
0218         if (mac_esp_wait_for_dreq(esp))
0219             break;
0220 
0221         if (write) {
0222             MAC_ESP_PDMA_LOOP("%4@,%0@+");
0223 
0224             esp_count -= addr - start_addr;
0225         } else {
0226             unsigned int n;
0227 
0228             MAC_ESP_PDMA_LOOP("%0@+,%4@");
0229 
0230             if (mac_esp_wait_for_empty_fifo(esp))
0231                 break;
0232 
0233             n = (esp_read8(ESP_TCMED) << 8) + esp_read8(ESP_TCLOW);
0234             addr = start_addr + esp_count - n;
0235             esp_count = n;
0236         }
0237     } while (esp_count);
0238 }
0239 
0240 static int mac_esp_irq_pending(struct esp *esp)
0241 {
0242     if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
0243         return 1;
0244     return 0;
0245 }
0246 
0247 static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
0248 {
0249     return dma_len > 0xFFFF ? 0xFFFF : dma_len;
0250 }
0251 
0252 static irqreturn_t mac_scsi_esp_intr(int irq, void *dev_id)
0253 {
0254     int got_intr;
0255 
0256     /*
0257      * This is an edge triggered IRQ, so we have to be careful to
0258      * avoid missing a transition when it is shared by two ESP devices.
0259      */
0260 
0261     do {
0262         got_intr = 0;
0263         if (esp_chips[0] &&
0264             (mac_esp_read8(esp_chips[0], ESP_STATUS) & ESP_STAT_INTR)) {
0265             (void)scsi_esp_intr(irq, esp_chips[0]);
0266             got_intr = 1;
0267         }
0268         if (esp_chips[1] &&
0269             (mac_esp_read8(esp_chips[1], ESP_STATUS) & ESP_STAT_INTR)) {
0270             (void)scsi_esp_intr(irq, esp_chips[1]);
0271             got_intr = 1;
0272         }
0273     } while (got_intr);
0274 
0275     return IRQ_HANDLED;
0276 }
0277 
0278 static struct esp_driver_ops mac_esp_ops = {
0279     .esp_write8       = mac_esp_write8,
0280     .esp_read8        = mac_esp_read8,
0281     .irq_pending      = mac_esp_irq_pending,
0282     .dma_length_limit = mac_esp_dma_length_limit,
0283     .reset_dma        = mac_esp_reset_dma,
0284     .dma_drain        = mac_esp_dma_drain,
0285     .dma_invalidate   = mac_esp_dma_invalidate,
0286     .send_dma_cmd     = mac_esp_send_pdma_cmd,
0287     .dma_error        = mac_esp_dma_error,
0288 };
0289 
0290 static int esp_mac_probe(struct platform_device *dev)
0291 {
0292     struct scsi_host_template *tpnt = &scsi_esp_template;
0293     struct Scsi_Host *host;
0294     struct esp *esp;
0295     int err;
0296     struct mac_esp_priv *mep;
0297 
0298     if (!MACH_IS_MAC)
0299         return -ENODEV;
0300 
0301     if (dev->id > 1)
0302         return -ENODEV;
0303 
0304     host = scsi_host_alloc(tpnt, sizeof(struct esp));
0305 
0306     err = -ENOMEM;
0307     if (!host)
0308         goto fail;
0309 
0310     host->max_id = 8;
0311     host->dma_boundary = PAGE_SIZE - 1;
0312     esp = shost_priv(host);
0313 
0314     esp->host = host;
0315     esp->dev = &dev->dev;
0316 
0317     esp->command_block = kzalloc(16, GFP_KERNEL);
0318     if (!esp->command_block)
0319         goto fail_unlink;
0320     esp->command_block_dma = (dma_addr_t)esp->command_block;
0321 
0322     esp->scsi_id = 7;
0323     host->this_id = esp->scsi_id;
0324     esp->scsi_id_mask = 1 << esp->scsi_id;
0325 
0326     mep = kzalloc(sizeof(struct mac_esp_priv), GFP_KERNEL);
0327     if (!mep)
0328         goto fail_free_command_block;
0329     mep->esp = esp;
0330     platform_set_drvdata(dev, mep);
0331 
0332     switch (macintosh_config->scsi_type) {
0333     case MAC_SCSI_QUADRA:
0334         esp->cfreq     = 16500000;
0335         esp->regs      = (void __iomem *)MAC_ESP_REGS_QUADRA;
0336         mep->pdma_io   = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
0337         mep->pdma_regs = NULL;
0338         break;
0339     case MAC_SCSI_QUADRA2:
0340         esp->cfreq     = 25000000;
0341         esp->regs      = (void __iomem *)(MAC_ESP_REGS_QUADRA2 +
0342                  dev->id * MAC_ESP_REGS_SPACING);
0343         mep->pdma_io   = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
0344         mep->pdma_regs = (void __iomem *)(MAC_ESP_PDMA_REG +
0345                  dev->id * MAC_ESP_PDMA_REG_SPACING);
0346         nubus_writel(0x1d1, mep->pdma_regs);
0347         break;
0348     case MAC_SCSI_QUADRA3:
0349         /* These quadras have a real DMA controller (the PSC) but we
0350          * don't know how to drive it so we must use PIO instead.
0351          */
0352         esp->cfreq     = 25000000;
0353         esp->regs      = (void __iomem *)MAC_ESP_REGS_QUADRA3;
0354         mep->pdma_io   = NULL;
0355         mep->pdma_regs = NULL;
0356         break;
0357     }
0358     esp->fifo_reg = esp->regs + ESP_FDATA * 16;
0359 
0360     esp->ops = &mac_esp_ops;
0361     esp->flags = ESP_FLAG_NO_DMA_MAP;
0362     if (mep->pdma_io == NULL) {
0363         printk(KERN_INFO PFX "using PIO for controller %d\n", dev->id);
0364         esp_write8(0, ESP_TCLOW);
0365         esp_write8(0, ESP_TCMED);
0366         esp->flags |= ESP_FLAG_DISABLE_SYNC;
0367         mac_esp_ops.send_dma_cmd = esp_send_pio_cmd;
0368     } else {
0369         printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id);
0370     }
0371 
0372     host->irq = IRQ_MAC_SCSI;
0373 
0374     /* The request_irq() call is intended to succeed for the first device
0375      * and fail for the second device.
0376      */
0377     err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
0378     spin_lock(&esp_chips_lock);
0379     if (err < 0 && esp_chips[!dev->id] == NULL) {
0380         spin_unlock(&esp_chips_lock);
0381         goto fail_free_priv;
0382     }
0383     esp_chips[dev->id] = esp;
0384     spin_unlock(&esp_chips_lock);
0385 
0386     err = scsi_esp_register(esp);
0387     if (err)
0388         goto fail_free_irq;
0389 
0390     return 0;
0391 
0392 fail_free_irq:
0393     spin_lock(&esp_chips_lock);
0394     esp_chips[dev->id] = NULL;
0395     if (esp_chips[!dev->id] == NULL) {
0396         spin_unlock(&esp_chips_lock);
0397         free_irq(host->irq, NULL);
0398     } else
0399         spin_unlock(&esp_chips_lock);
0400 fail_free_priv:
0401     kfree(mep);
0402 fail_free_command_block:
0403     kfree(esp->command_block);
0404 fail_unlink:
0405     scsi_host_put(host);
0406 fail:
0407     return err;
0408 }
0409 
0410 static int esp_mac_remove(struct platform_device *dev)
0411 {
0412     struct mac_esp_priv *mep = platform_get_drvdata(dev);
0413     struct esp *esp = mep->esp;
0414     unsigned int irq = esp->host->irq;
0415 
0416     scsi_esp_unregister(esp);
0417 
0418     spin_lock(&esp_chips_lock);
0419     esp_chips[dev->id] = NULL;
0420     if (esp_chips[!dev->id] == NULL) {
0421         spin_unlock(&esp_chips_lock);
0422         free_irq(irq, NULL);
0423     } else
0424         spin_unlock(&esp_chips_lock);
0425 
0426     kfree(mep);
0427 
0428     kfree(esp->command_block);
0429 
0430     scsi_host_put(esp->host);
0431 
0432     return 0;
0433 }
0434 
0435 static struct platform_driver esp_mac_driver = {
0436     .probe    = esp_mac_probe,
0437     .remove   = esp_mac_remove,
0438     .driver   = {
0439         .name   = DRV_MODULE_NAME,
0440     },
0441 };
0442 module_platform_driver(esp_mac_driver);
0443 
0444 MODULE_DESCRIPTION("Mac ESP SCSI driver");
0445 MODULE_AUTHOR("Finn Thain");
0446 MODULE_LICENSE("GPL v2");
0447 MODULE_VERSION(DRV_VERSION);
0448 MODULE_ALIAS("platform:" DRV_MODULE_NAME);