mac_esp.c (11818B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* mac_esp.c: ESP front-end for Macintosh Quadra systems. 3 * 4 * Adapted from jazz_esp.c and the old mac_esp.c. 5 * 6 * The pseudo DMA algorithm is based on the one used in NetBSD. 7 * See sys/arch/mac68k/obio/esp.c for some background information. 8 * 9 * Copyright (C) 2007-2008 Finn Thain 10 */ 11 12#include <linux/kernel.h> 13#include <linux/types.h> 14#include <linux/module.h> 15#include <linux/init.h> 16#include <linux/interrupt.h> 17#include <linux/platform_device.h> 18#include <linux/dma-mapping.h> 19#include <linux/scatterlist.h> 20#include <linux/delay.h> 21#include <linux/io.h> 22#include <linux/nubus.h> 23#include <linux/slab.h> 24 25#include <asm/irq.h> 26#include <asm/dma.h> 27#include <asm/macints.h> 28#include <asm/macintosh.h> 29#include <asm/mac_via.h> 30 31#include <scsi/scsi_host.h> 32 33#include "esp_scsi.h" 34 35#define DRV_MODULE_NAME "mac_esp" 36#define PFX DRV_MODULE_NAME ": " 37#define DRV_VERSION "1.000" 38#define DRV_MODULE_RELDATE "Sept 15, 2007" 39 40#define MAC_ESP_IO_BASE 0x50F00000 41#define MAC_ESP_REGS_QUADRA (MAC_ESP_IO_BASE + 0x10000) 42#define MAC_ESP_REGS_QUADRA2 (MAC_ESP_IO_BASE + 0xF000) 43#define MAC_ESP_REGS_QUADRA3 (MAC_ESP_IO_BASE + 0x18000) 44#define MAC_ESP_REGS_SPACING 0x402 45#define MAC_ESP_PDMA_REG 0xF9800024 46#define MAC_ESP_PDMA_REG_SPACING 0x4 47#define MAC_ESP_PDMA_IO_OFFSET 0x100 48 49#define esp_read8(REG) mac_esp_read8(esp, REG) 50#define esp_write8(VAL, REG) mac_esp_write8(esp, VAL, REG) 51 52struct mac_esp_priv { 53 struct esp *esp; 54 void __iomem *pdma_regs; 55 void __iomem *pdma_io; 56}; 57static struct esp *esp_chips[2]; 58static DEFINE_SPINLOCK(esp_chips_lock); 59 60#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ 61 dev_get_drvdata((esp)->dev)) 62 63static inline void mac_esp_write8(struct esp *esp, u8 val, unsigned long reg) 64{ 65 nubus_writeb(val, esp->regs + reg * 16); 66} 67 68static inline u8 mac_esp_read8(struct esp *esp, unsigned long reg) 69{ 70 return nubus_readb(esp->regs + reg * 16); 71} 72 73static void mac_esp_reset_dma(struct esp *esp) 74{ 75 /* Nothing to do. */ 76} 77 78static void mac_esp_dma_drain(struct esp *esp) 79{ 80 /* Nothing to do. */ 81} 82 83static void mac_esp_dma_invalidate(struct esp *esp) 84{ 85 /* Nothing to do. */ 86} 87 88static int mac_esp_dma_error(struct esp *esp) 89{ 90 return esp->send_cmd_error; 91} 92 93static inline int mac_esp_wait_for_empty_fifo(struct esp *esp) 94{ 95 int i = 500000; 96 97 do { 98 if (!(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES)) 99 return 0; 100 101 if (esp_read8(ESP_STATUS) & ESP_STAT_INTR) 102 return 1; 103 104 udelay(2); 105 } while (--i); 106 107 printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n", 108 esp_read8(ESP_STATUS)); 109 esp->send_cmd_error = 1; 110 return 1; 111} 112 113static inline int mac_esp_wait_for_dreq(struct esp *esp) 114{ 115 struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); 116 int i = 500000; 117 118 do { 119 if (mep->pdma_regs == NULL) { 120 if (via2_scsi_drq_pending()) 121 return 0; 122 } else { 123 if (nubus_readl(mep->pdma_regs) & 0x200) 124 return 0; 125 } 126 127 if (esp_read8(ESP_STATUS) & ESP_STAT_INTR) 128 return 1; 129 130 udelay(2); 131 } while (--i); 132 133 printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n", 134 esp_read8(ESP_STATUS)); 135 esp->send_cmd_error = 1; 136 return 1; 137} 138 139#define MAC_ESP_PDMA_LOOP(operands) \ 140 asm volatile ( \ 141 " tstw %1 \n" \ 142 " jbeq 20f \n" \ 143 "1: movew " operands " \n" \ 144 "2: movew " operands " \n" \ 145 "3: movew " operands " \n" \ 146 "4: movew " operands " \n" \ 147 "5: movew " operands " \n" \ 148 "6: movew " operands " \n" \ 149 "7: movew " operands " \n" \ 150 "8: movew " operands " \n" \ 151 "9: movew " operands " \n" \ 152 "10: movew " operands " \n" \ 153 "11: movew " operands " \n" \ 154 "12: movew " operands " \n" \ 155 "13: movew " operands " \n" \ 156 "14: movew " operands " \n" \ 157 "15: movew " operands " \n" \ 158 "16: movew " operands " \n" \ 159 " subqw #1,%1 \n" \ 160 " jbne 1b \n" \ 161 "20: tstw %2 \n" \ 162 " jbeq 30f \n" \ 163 "21: movew " operands " \n" \ 164 " subqw #1,%2 \n" \ 165 " jbne 21b \n" \ 166 "30: tstw %3 \n" \ 167 " jbeq 40f \n" \ 168 "31: moveb " operands " \n" \ 169 "32: nop \n" \ 170 "40: \n" \ 171 " \n" \ 172 " .section __ex_table,\"a\" \n" \ 173 " .align 4 \n" \ 174 " .long 1b,40b \n" \ 175 " .long 2b,40b \n" \ 176 " .long 3b,40b \n" \ 177 " .long 4b,40b \n" \ 178 " .long 5b,40b \n" \ 179 " .long 6b,40b \n" \ 180 " .long 7b,40b \n" \ 181 " .long 8b,40b \n" \ 182 " .long 9b,40b \n" \ 183 " .long 10b,40b \n" \ 184 " .long 11b,40b \n" \ 185 " .long 12b,40b \n" \ 186 " .long 13b,40b \n" \ 187 " .long 14b,40b \n" \ 188 " .long 15b,40b \n" \ 189 " .long 16b,40b \n" \ 190 " .long 21b,40b \n" \ 191 " .long 31b,40b \n" \ 192 " .long 32b,40b \n" \ 193 " .previous \n" \ 194 : "+a" (addr), "+r" (count32), "+r" (count2) \ 195 : "g" (count1), "a" (mep->pdma_io)) 196 197static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count, 198 u32 dma_count, int write, u8 cmd) 199{ 200 struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); 201 202 esp->send_cmd_error = 0; 203 204 if (!write) 205 scsi_esp_cmd(esp, ESP_CMD_FLUSH); 206 207 esp_write8((esp_count >> 0) & 0xFF, ESP_TCLOW); 208 esp_write8((esp_count >> 8) & 0xFF, ESP_TCMED); 209 210 scsi_esp_cmd(esp, cmd); 211 212 do { 213 unsigned int count32 = esp_count >> 5; 214 unsigned int count2 = (esp_count & 0x1F) >> 1; 215 unsigned int count1 = esp_count & 1; 216 unsigned int start_addr = addr; 217 218 if (mac_esp_wait_for_dreq(esp)) 219 break; 220 221 if (write) { 222 MAC_ESP_PDMA_LOOP("%4@,%0@+"); 223 224 esp_count -= addr - start_addr; 225 } else { 226 unsigned int n; 227 228 MAC_ESP_PDMA_LOOP("%0@+,%4@"); 229 230 if (mac_esp_wait_for_empty_fifo(esp)) 231 break; 232 233 n = (esp_read8(ESP_TCMED) << 8) + esp_read8(ESP_TCLOW); 234 addr = start_addr + esp_count - n; 235 esp_count = n; 236 } 237 } while (esp_count); 238} 239 240static int mac_esp_irq_pending(struct esp *esp) 241{ 242 if (esp_read8(ESP_STATUS) & ESP_STAT_INTR) 243 return 1; 244 return 0; 245} 246 247static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len) 248{ 249 return dma_len > 0xFFFF ? 0xFFFF : dma_len; 250} 251 252static irqreturn_t mac_scsi_esp_intr(int irq, void *dev_id) 253{ 254 int got_intr; 255 256 /* 257 * This is an edge triggered IRQ, so we have to be careful to 258 * avoid missing a transition when it is shared by two ESP devices. 259 */ 260 261 do { 262 got_intr = 0; 263 if (esp_chips[0] && 264 (mac_esp_read8(esp_chips[0], ESP_STATUS) & ESP_STAT_INTR)) { 265 (void)scsi_esp_intr(irq, esp_chips[0]); 266 got_intr = 1; 267 } 268 if (esp_chips[1] && 269 (mac_esp_read8(esp_chips[1], ESP_STATUS) & ESP_STAT_INTR)) { 270 (void)scsi_esp_intr(irq, esp_chips[1]); 271 got_intr = 1; 272 } 273 } while (got_intr); 274 275 return IRQ_HANDLED; 276} 277 278static struct esp_driver_ops mac_esp_ops = { 279 .esp_write8 = mac_esp_write8, 280 .esp_read8 = mac_esp_read8, 281 .irq_pending = mac_esp_irq_pending, 282 .dma_length_limit = mac_esp_dma_length_limit, 283 .reset_dma = mac_esp_reset_dma, 284 .dma_drain = mac_esp_dma_drain, 285 .dma_invalidate = mac_esp_dma_invalidate, 286 .send_dma_cmd = mac_esp_send_pdma_cmd, 287 .dma_error = mac_esp_dma_error, 288}; 289 290static int esp_mac_probe(struct platform_device *dev) 291{ 292 struct scsi_host_template *tpnt = &scsi_esp_template; 293 struct Scsi_Host *host; 294 struct esp *esp; 295 int err; 296 struct mac_esp_priv *mep; 297 298 if (!MACH_IS_MAC) 299 return -ENODEV; 300 301 if (dev->id > 1) 302 return -ENODEV; 303 304 host = scsi_host_alloc(tpnt, sizeof(struct esp)); 305 306 err = -ENOMEM; 307 if (!host) 308 goto fail; 309 310 host->max_id = 8; 311 host->dma_boundary = PAGE_SIZE - 1; 312 esp = shost_priv(host); 313 314 esp->host = host; 315 esp->dev = &dev->dev; 316 317 esp->command_block = kzalloc(16, GFP_KERNEL); 318 if (!esp->command_block) 319 goto fail_unlink; 320 esp->command_block_dma = (dma_addr_t)esp->command_block; 321 322 esp->scsi_id = 7; 323 host->this_id = esp->scsi_id; 324 esp->scsi_id_mask = 1 << esp->scsi_id; 325 326 mep = kzalloc(sizeof(struct mac_esp_priv), GFP_KERNEL); 327 if (!mep) 328 goto fail_free_command_block; 329 mep->esp = esp; 330 platform_set_drvdata(dev, mep); 331 332 switch (macintosh_config->scsi_type) { 333 case MAC_SCSI_QUADRA: 334 esp->cfreq = 16500000; 335 esp->regs = (void __iomem *)MAC_ESP_REGS_QUADRA; 336 mep->pdma_io = esp->regs + MAC_ESP_PDMA_IO_OFFSET; 337 mep->pdma_regs = NULL; 338 break; 339 case MAC_SCSI_QUADRA2: 340 esp->cfreq = 25000000; 341 esp->regs = (void __iomem *)(MAC_ESP_REGS_QUADRA2 + 342 dev->id * MAC_ESP_REGS_SPACING); 343 mep->pdma_io = esp->regs + MAC_ESP_PDMA_IO_OFFSET; 344 mep->pdma_regs = (void __iomem *)(MAC_ESP_PDMA_REG + 345 dev->id * MAC_ESP_PDMA_REG_SPACING); 346 nubus_writel(0x1d1, mep->pdma_regs); 347 break; 348 case MAC_SCSI_QUADRA3: 349 /* These quadras have a real DMA controller (the PSC) but we 350 * don't know how to drive it so we must use PIO instead. 351 */ 352 esp->cfreq = 25000000; 353 esp->regs = (void __iomem *)MAC_ESP_REGS_QUADRA3; 354 mep->pdma_io = NULL; 355 mep->pdma_regs = NULL; 356 break; 357 } 358 esp->fifo_reg = esp->regs + ESP_FDATA * 16; 359 360 esp->ops = &mac_esp_ops; 361 esp->flags = ESP_FLAG_NO_DMA_MAP; 362 if (mep->pdma_io == NULL) { 363 printk(KERN_INFO PFX "using PIO for controller %d\n", dev->id); 364 esp_write8(0, ESP_TCLOW); 365 esp_write8(0, ESP_TCMED); 366 esp->flags |= ESP_FLAG_DISABLE_SYNC; 367 mac_esp_ops.send_dma_cmd = esp_send_pio_cmd; 368 } else { 369 printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id); 370 } 371 372 host->irq = IRQ_MAC_SCSI; 373 374 /* The request_irq() call is intended to succeed for the first device 375 * and fail for the second device. 376 */ 377 err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL); 378 spin_lock(&esp_chips_lock); 379 if (err < 0 && esp_chips[!dev->id] == NULL) { 380 spin_unlock(&esp_chips_lock); 381 goto fail_free_priv; 382 } 383 esp_chips[dev->id] = esp; 384 spin_unlock(&esp_chips_lock); 385 386 err = scsi_esp_register(esp); 387 if (err) 388 goto fail_free_irq; 389 390 return 0; 391 392fail_free_irq: 393 spin_lock(&esp_chips_lock); 394 esp_chips[dev->id] = NULL; 395 if (esp_chips[!dev->id] == NULL) { 396 spin_unlock(&esp_chips_lock); 397 free_irq(host->irq, NULL); 398 } else 399 spin_unlock(&esp_chips_lock); 400fail_free_priv: 401 kfree(mep); 402fail_free_command_block: 403 kfree(esp->command_block); 404fail_unlink: 405 scsi_host_put(host); 406fail: 407 return err; 408} 409 410static int esp_mac_remove(struct platform_device *dev) 411{ 412 struct mac_esp_priv *mep = platform_get_drvdata(dev); 413 struct esp *esp = mep->esp; 414 unsigned int irq = esp->host->irq; 415 416 scsi_esp_unregister(esp); 417 418 spin_lock(&esp_chips_lock); 419 esp_chips[dev->id] = NULL; 420 if (esp_chips[!dev->id] == NULL) { 421 spin_unlock(&esp_chips_lock); 422 free_irq(irq, NULL); 423 } else 424 spin_unlock(&esp_chips_lock); 425 426 kfree(mep); 427 428 kfree(esp->command_block); 429 430 scsi_host_put(esp->host); 431 432 return 0; 433} 434 435static struct platform_driver esp_mac_driver = { 436 .probe = esp_mac_probe, 437 .remove = esp_mac_remove, 438 .driver = { 439 .name = DRV_MODULE_NAME, 440 }, 441}; 442module_platform_driver(esp_mac_driver); 443 444MODULE_DESCRIPTION("Mac ESP SCSI driver"); 445MODULE_AUTHOR("Finn Thain"); 446MODULE_LICENSE("GPL v2"); 447MODULE_VERSION(DRV_VERSION); 448MODULE_ALIAS("platform:" DRV_MODULE_NAME);