sun_esp.c revision 6025dfe5b2598056cd763a2b10ca7e7faffb2e16
1cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller/* sun_esp.c: ESP front-end for Sparc SBUS systems. 2cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * 3cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * Copyright (C) 2007 David S. Miller (davem@davemloft.net) 4cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller */ 5cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 6cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <linux/kernel.h> 7cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <linux/types.h> 86025dfe5b2598056cd763a2b10ca7e7faffb2e16David S. Miller#include <linux/delay.h> 9cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <linux/module.h> 10cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <linux/init.h> 11cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 12cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/irq.h> 13cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/io.h> 14cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/dma.h> 15cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 16cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/sbus.h> 17cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 18cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <scsi/scsi_host.h> 19cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 20cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include "esp_scsi.h" 21cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 22cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define DRV_MODULE_NAME "sun_esp" 23cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define PFX DRV_MODULE_NAME ": " 24cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define DRV_VERSION "1.000" 25cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define DRV_MODULE_RELDATE "April 19, 2007" 26cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 27cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define dma_read32(REG) \ 28cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_readl(esp->dma_regs + (REG)) 29cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define dma_write32(VAL, REG) \ 30cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_writel((VAL), esp->dma_regs + (REG)) 31cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 32cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sdev) 33cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 34cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 35cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dma *dma; 36cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 37cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dma_sdev != NULL) { 38cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller for_each_dvma(dma) { 39cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dma->sdev == dma_sdev) 40cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 41cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 42cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } else { 43cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller for_each_dvma(dma) { 44cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dma->sdev == NULL) 45cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 46cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 47cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* If bus + slot are the same and it has the 48cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * correct OBP name, it's ours. 49cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller */ 50cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (sdev->bus == dma->sdev->bus && 51cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sdev->slot == dma->sdev->slot && 52cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller (!strcmp(dma->sdev->prom_name, "dma") || 53cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller !strcmp(dma->sdev->prom_name, "espdma"))) 54cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 55cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 56cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 57cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 58cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dma == NULL) { 59cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller printk(KERN_ERR PFX "[%s] Cannot find dma.\n", 60cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sdev->ofdev.node->full_name); 61cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return -ENODEV; 62cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 63cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->dma = dma; 64cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->dma_regs = dma->regs; 65cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 66cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 67cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 68cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 69cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 70cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_map_regs(struct esp *esp, int hme) 71cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 72cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 73cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct resource *res; 74cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 75cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* On HME, two reg sets exist, first is DVMA, 76cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * second is ESP registers. 77cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller */ 78cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (hme) 79cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller res = &sdev->resource[1]; 80cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller else 81cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller res = &sdev->resource[0]; 82cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 83cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->regs = sbus_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP"); 84cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (!esp->regs) 85cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return -ENOMEM; 86cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 87cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 88cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 89cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 90cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_map_command_block(struct esp *esp) 91cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 92cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 93cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 94cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->command_block = sbus_alloc_consistent(sdev, 16, 95cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller &esp->command_block_dma); 96cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (!esp->command_block) 97cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return -ENOMEM; 98cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 99cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 100cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 101cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_register_irq(struct esp *esp) 102cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 103cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct Scsi_Host *host = esp->host; 104cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 105cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 106cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller host->irq = sdev->irqs[0]; 107cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); 108cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 109cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 110cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_get_scsi_id(struct esp *esp) 111cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 112cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 113cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *dp = sdev->ofdev.node; 114cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 115cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff); 116cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->scsi_id != 0xff) 117cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto done; 118cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 119cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", 0xff); 120cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->scsi_id != 0xff) 121cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto done; 122cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 123cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (!sdev->bus) { 124cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* SUN4 */ 125cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->scsi_id = 7; 126cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto done; 127cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 128cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 129cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->scsi_id = of_getintprop_default(sdev->bus->ofdev.node, 130cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller "scsi-initiator-id", 7); 131cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 132cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerdone: 133cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->host->this_id = esp->scsi_id; 134cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->scsi_id_mask = (1 << esp->scsi_id); 135cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 136cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 137cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_get_differential(struct esp *esp) 138cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 139cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 140cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *dp = sdev->ofdev.node; 141cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 142cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (of_find_property(dp, "differential", NULL)) 143cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->flags |= ESP_FLAG_DIFFERENTIAL; 144cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller else 145cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->flags &= ~ESP_FLAG_DIFFERENTIAL; 146cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 147cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 148cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_get_clock_params(struct esp *esp) 149cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 150cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 151cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *dp = sdev->ofdev.node; 152cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *bus_dp; 153cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int fmhz; 154cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 155cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller bus_dp = NULL; 156cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (sdev != NULL && sdev->bus != NULL) 157cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller bus_dp = sdev->bus->ofdev.node; 158cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 159cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller fmhz = of_getintprop_default(dp, "clock-frequency", 0); 160cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (fmhz == 0) 161cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller fmhz = (!bus_dp) ? 0 : 162cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller of_getintprop_default(bus_dp, "clock-frequency", 0); 163cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 164cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->cfreq = fmhz; 165cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 166cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 167cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) 168cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 169cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = esp->dev; 170cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *dp = sdev->ofdev.node; 171cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u8 bursts; 172cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 173cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller bursts = of_getintprop_default(dp, "burst-sizes", 0xff); 174cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dma) { 175cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *dma_dp = dma->ofdev.node; 176cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u8 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); 177cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (val != 0xff) 178cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller bursts &= val; 179cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 180cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 181cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (sdev->bus) { 182cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u8 val = of_getintprop_default(sdev->bus->ofdev.node, 183cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller "burst-sizes", 0xff); 184cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (val != 0xff) 185cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller bursts &= val; 186cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 187cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 188cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (bursts == 0xff || 189cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller (bursts & DMA_BURST16) == 0 || 190cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller (bursts & DMA_BURST32) == 0) 191cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller bursts = (DMA_BURST32 - 1); 192cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 193cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->bursts = bursts; 194cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 195cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 196cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_sbus_get_props(struct esp *esp, struct sbus_dev *espdma) 197cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 198cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp_get_scsi_id(esp); 199cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp_get_differential(esp); 200cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp_get_clock_params(esp); 201cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp_get_bursts(esp, espdma); 202cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 203cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 204cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_write8(struct esp *esp, u8 val, unsigned long reg) 205cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 206cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_writeb(val, esp->regs + (reg * 4UL)); 207cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 208cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 209cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic u8 sbus_esp_read8(struct esp *esp, unsigned long reg) 210cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 211cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return sbus_readb(esp->regs + (reg * 4UL)); 212cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 213cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 214cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, 215cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller size_t sz, int dir) 216cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 217cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return sbus_map_single(esp->dev, buf, sz, dir); 218cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 219cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 220cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, 221cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int num_sg, int dir) 222cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 223cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return sbus_map_sg(esp->dev, sg, num_sg, dir); 224cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 225cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 226cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, 227cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller size_t sz, int dir) 228cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 229cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_unmap_single(esp->dev, addr, sz, dir); 230cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 231cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 232cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, 233cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int num_sg, int dir) 234cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 235cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_unmap_sg(esp->dev, sg, num_sg, dir); 236cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 237cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 238cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_irq_pending(struct esp *esp) 239cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 240cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)) 241cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 1; 242cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 243cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 244cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 245cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_reset_dma(struct esp *esp) 246cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 247cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int can_do_burst16, can_do_burst32, can_do_burst64; 248cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int can_do_sbus64, lim; 249cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 val; 250cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 251cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; 252cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; 253cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller can_do_burst64 = 0; 254cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller can_do_sbus64 = 0; 255cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (sbus_can_dma_64bit(esp->dev)) 256cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller can_do_sbus64 = 1; 257cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (sbus_can_burst64(esp->sdev)) 258cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; 259cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 260cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* Put the DVMA into a known state. */ 261cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->dma->revision != dvmahme) { 262cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val = dma_read32(DMA_CSR); 263cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val | DMA_RST_SCSI, DMA_CSR); 264cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); 265cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 266cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller switch (esp->dma->revision) { 267cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller case dvmahme: 268cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(DMA_RESET_FAS366, DMA_CSR); 269cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(DMA_RST_SCSI, DMA_CSR); 270cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 271cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS | 272cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller DMA_SCSI_DISAB | DMA_INT_ENAB); 273cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 274cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE | 275cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller DMA_BRST_SZ); 276cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 277cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (can_do_burst64) 278cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr |= DMA_BRST64; 279cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller else if (can_do_burst32) 280cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr |= DMA_BRST32; 281cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 282cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (can_do_sbus64) { 283cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; 284cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_set_sbus64(esp->dev, esp->bursts); 285cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 286cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 287cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller lim = 1000; 288cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller while (dma_read32(DMA_CSR) & DMA_PEND_READ) { 289cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (--lim == 0) { 290cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ " 291cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller "will not clear!\n", 292cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->host->unique_id); 293cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 294cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 295cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller udelay(1); 296cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 297cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 298cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(0, DMA_CSR); 299cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(esp->prev_hme_dmacsr, DMA_CSR); 300cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 301cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(0, DMA_ADDR); 302cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 303cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 304cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller case dvmarev2: 305cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->rev != ESP100) { 306cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val = dma_read32(DMA_CSR); 307cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val | DMA_3CLKS, DMA_CSR); 308cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 309cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 310cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 311cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller case dvmarev3: 312cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val = dma_read32(DMA_CSR); 313cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val &= ~DMA_3CLKS; 314cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val |= DMA_2CLKS; 315cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (can_do_burst32) { 316cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val &= ~DMA_BRST_SZ; 317cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val |= DMA_BRST32; 318cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 319cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val, DMA_CSR); 320cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 321cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 322cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller case dvmaesc1: 323cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val = dma_read32(DMA_CSR); 324cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val |= DMA_ADD_ENABLE; 325cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val &= ~DMA_BCNT_ENAB; 326cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (!can_do_burst32 && can_do_burst16) { 327cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val |= DMA_ESC_BURST; 328cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } else { 329cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val &= ~(DMA_ESC_BURST); 330cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 331cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val, DMA_CSR); 332cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 333cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 334cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller default: 335cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 336cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 337cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 338cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* Enable interrupts. */ 339cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val = dma_read32(DMA_CSR); 340cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val | DMA_INT_ENAB, DMA_CSR); 341cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 342cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 343cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_dma_drain(struct esp *esp) 344cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 345cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 csr; 346cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int lim; 347cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 348cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->dma->revision == dvmahme) 349cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return; 350cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 351cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr = dma_read32(DMA_CSR); 352cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (!(csr & DMA_FIFO_ISDRAIN)) 353cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return; 354cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 355cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->dma->revision != dvmarev3 && esp->dma->revision != dvmaesc1) 356cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); 357cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 358cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller lim = 1000; 359cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) { 360cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (--lim == 0) { 361cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n", 362cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->host->unique_id); 363cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 364cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 365cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller udelay(1); 366cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 367cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 368cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 369cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_dma_invalidate(struct esp *esp) 370cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 371cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->dma->revision == dvmahme) { 372cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(DMA_RST_SCSI, DMA_CSR); 373cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 374cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | 375cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller (DMA_PARITY_OFF | DMA_2CLKS | 376cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller DMA_SCSI_DISAB | DMA_INT_ENAB)) & 377cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller ~(DMA_ST_WRITE | DMA_ENABLE)); 378cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 379cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(0, DMA_CSR); 380cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(esp->prev_hme_dmacsr, DMA_CSR); 381cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 382cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* This is necessary to avoid having the SCSI channel 383cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * engine lock up on us. 384cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller */ 385cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(0, DMA_ADDR); 386cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } else { 387cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 val; 388cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int lim; 389cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 390cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller lim = 1000; 391cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) { 392cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (--lim == 0) { 393cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller printk(KERN_ALERT PFX "esp%d: DMA will not " 394cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller "invalidate!\n", esp->host->unique_id); 395cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller break; 396cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 397cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller udelay(1); 398cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 399cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 400cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB); 401cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val |= DMA_FIFO_INV; 402cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val, DMA_CSR); 403cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val &= ~DMA_FIFO_INV; 404cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val, DMA_CSR); 405cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 406cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 407cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 408cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, 409cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 dma_count, int write, u8 cmd) 410cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 411cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 csr; 412cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 413cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller BUG_ON(!(cmd & ESP_CMD_DMA)); 414cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 415cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 416cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 417cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->rev == FASHME) { 418cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO); 419cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_esp_write8(esp, 0, FAS_RHI); 420cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 421cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller scsi_esp_cmd(esp, cmd); 422cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 423cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr = esp->prev_hme_dmacsr; 424cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr |= DMA_SCSI_DISAB | DMA_ENABLE; 425cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (write) 426cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr |= DMA_ST_WRITE; 427cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller else 428cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr &= ~DMA_ST_WRITE; 429cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->prev_hme_dmacsr = csr; 430cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 431cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(dma_count, DMA_COUNT); 432cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(addr, DMA_ADDR); 433cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(csr, DMA_CSR); 434cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } else { 435cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr = dma_read32(DMA_CSR); 436cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr |= DMA_ENABLE; 437cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (write) 438cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr |= DMA_ST_WRITE; 439cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller else 440cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller csr &= ~DMA_ST_WRITE; 441cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(csr, DMA_CSR); 442cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->dma->revision == dvmaesc1) { 443cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 end = PAGE_ALIGN(addr + dma_count + 16U); 444cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(end - addr, DMA_COUNT); 445cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 446cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(addr, DMA_ADDR); 447cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 448cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller scsi_esp_cmd(esp, cmd); 449cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 450cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 451cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 452cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 453cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_dma_error(struct esp *esp) 454cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 455cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 csr = dma_read32(DMA_CSR); 456cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 457cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (csr & DMA_HNDL_ERROR) 458cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 1; 459cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 460cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 461cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 462cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 463cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic const struct esp_driver_ops sbus_esp_ops = { 464cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .esp_write8 = sbus_esp_write8, 465cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .esp_read8 = sbus_esp_read8, 466cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .map_single = sbus_esp_map_single, 467cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .map_sg = sbus_esp_map_sg, 468cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .unmap_single = sbus_esp_unmap_single, 469cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .unmap_sg = sbus_esp_unmap_sg, 470cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .irq_pending = sbus_esp_irq_pending, 471cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .reset_dma = sbus_esp_reset_dma, 472cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .dma_drain = sbus_esp_dma_drain, 473cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .dma_invalidate = sbus_esp_dma_invalidate, 474cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .send_dma_cmd = sbus_esp_send_dma_cmd, 475cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .dma_error = sbus_esp_dma_error, 476cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}; 477cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 478cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_probe_one(struct device *dev, 479cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *esp_dev, 480cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *espdma, 481cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_bus *sbus, 482cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int hme) 483cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 484cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct scsi_host_template *tpnt = &scsi_esp_template; 485cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct Scsi_Host *host; 486cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct esp *esp; 487cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int err; 488cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 489cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller host = scsi_host_alloc(tpnt, sizeof(struct esp)); 490cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 491cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller err = -ENOMEM; 492cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (!host) 493cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto fail; 494cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 495cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller host->max_id = (hme ? 16 : 8); 496cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp = host_to_esp(host); 497cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 498cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->host = host; 499cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->dev = esp_dev; 500cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->ops = &sbus_esp_ops; 501cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 502cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (hme) 503cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->flags |= ESP_FLAG_WIDE_CAPABLE; 504cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 505cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller err = esp_sbus_find_dma(esp, espdma); 506cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (err < 0) 507cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto fail_unlink; 508cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 509cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller err = esp_sbus_map_regs(esp, hme); 510cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (err < 0) 511cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto fail_unlink; 512cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 513cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller err = esp_sbus_map_command_block(esp); 514cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (err < 0) 515cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto fail_unmap_regs; 516cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 517cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller err = esp_sbus_register_irq(esp); 518cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (err < 0) 519cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto fail_unmap_command_block; 520cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 521cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp_sbus_get_props(esp, espdma); 522cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 523cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* Before we try to touch the ESP chip, ESC1 dma can 524cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * come up with the reset bit set, so make sure that 525cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller * is clear first. 526cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller */ 527cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (esp->dma->revision == dvmaesc1) { 528cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 val = dma_read32(DMA_CSR); 529cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 530cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); 531cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 532cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 533cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dev_set_drvdata(&esp_dev->ofdev.dev, esp); 534cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 535cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller err = scsi_esp_register(esp, dev); 536cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (err) 537cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller goto fail_free_irq; 538cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 539cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 540cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 541cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_free_irq: 542cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller free_irq(host->irq, esp); 543cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unmap_command_block: 544cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_free_consistent(esp->dev, 16, 545cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->command_block, 546cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->command_block_dma); 547cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unmap_regs: 548cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); 549cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unlink: 550cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller scsi_host_put(host); 551cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail: 552cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return err; 553cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 554cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 555cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) 556cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 557cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *sdev = to_sbus_device(&dev->dev); 558cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct device_node *dp = dev->node; 559cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct sbus_dev *dma_sdev = NULL; 560cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller int hme = 0; 561cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 562cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller if (dp->parent && 563cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller (!strcmp(dp->parent->name, "espdma") || 564cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller !strcmp(dp->parent->name, "dma"))) 565cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_sdev = sdev->parent; 566cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller else if (!strcmp(dp->name, "SUNW,fas")) { 567cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_sdev = sdev; 568cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller hme = 1; 569cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller } 570cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 571cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return esp_sbus_probe_one(&dev->dev, sdev, dma_sdev, 572cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sdev->bus, hme); 573cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 574cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 575cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devexit esp_sbus_remove(struct of_device *dev) 576cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 577cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller struct esp *esp = dev_get_drvdata(&dev->dev); 578cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller unsigned int irq = esp->host->irq; 579cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller u32 val; 580cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 581cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller scsi_esp_unregister(esp); 582cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 583cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller /* Disable interrupts. */ 584cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller val = dma_read32(DMA_CSR); 585cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); 586cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 587cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller free_irq(irq, esp); 588cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_free_consistent(esp->dev, 16, 589cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->command_block, 590cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller esp->command_block_dma); 591cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); 592cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 593cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller scsi_host_put(esp->host); 594cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 595cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return 0; 596cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 597cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 598cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic struct of_device_id esp_match[] = { 599cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller { 600cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .name = "SUNW,esp", 601cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller }, 602cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller { 603cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .name = "SUNW,fas", 604cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller }, 605cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller { 606cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .name = "esp", 607cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller }, 608cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller {}, 609cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}; 610cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_DEVICE_TABLE(of, esp_match); 611cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 612cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic struct of_platform_driver esp_sbus_driver = { 613cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .name = "esp", 614cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .match_table = esp_match, 615cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .probe = esp_sbus_probe, 616cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller .remove = __devexit_p(esp_sbus_remove), 617cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}; 618cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 619cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __init sunesp_init(void) 620cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 621cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller return of_register_driver(&esp_sbus_driver, &sbus_bus_type); 622cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 623cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 624cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __exit sunesp_exit(void) 625cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{ 626cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller of_unregister_driver(&esp_sbus_driver); 627cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller} 628cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 629cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_DESCRIPTION("Sun ESP SCSI driver"); 630cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); 631cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_LICENSE("GPL"); 632cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_VERSION(DRV_VERSION); 633cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller 634cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millermodule_init(sunesp_init); 635cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millermodule_exit(sunesp_exit); 636