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