1cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller/* sun_esp.c: ESP front-end for Sparc SBUS systems.
2cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller *
3334ae614772b1147435dce9be3911f9040dff0d9David S. Miller * Copyright (C) 2007, 2008 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>
1027ac792ca0b0a1e7e65f20342260650516c95864Andrea Righi#include <linux/mm.h>
11cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <linux/init.h>
12738f2b7b813913e651f39387d007dd961755dee2David S. Miller#include <linux/dma-mapping.h>
1305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller#include <linux/of.h>
1405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller#include <linux/of_device.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
16cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
17cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/irq.h>
18cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/io.h>
19cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <asm/dma.h>
20cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
21cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include <scsi/scsi_host.h>
22cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
23cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#include "esp_scsi.h"
24cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
25cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define DRV_MODULE_NAME		"sun_esp"
26cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define PFX DRV_MODULE_NAME	": "
2705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller#define DRV_VERSION		"1.100"
2805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller#define DRV_MODULE_RELDATE	"August 27, 2008"
29cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
30cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define dma_read32(REG) \
31cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_readl(esp->dma_regs + (REG))
32cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller#define dma_write32(VAL, REG) \
33cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_writel((VAL), esp->dma_regs + (REG))
34cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
35334ae614772b1147435dce9be3911f9040dff0d9David S. Miller/* DVMA chip revisions */
36334ae614772b1147435dce9be3911f9040dff0d9David S. Millerenum dvma_rev {
37334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmarev0,
38334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmaesc1,
39334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmarev1,
40334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmarev2,
41334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmarev3,
42334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmarevplus,
43334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	dvmahme
44334ae614772b1147435dce9be3911f9040dff0d9David S. Miller};
45cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
46334ae614772b1147435dce9be3911f9040dff0d9David S. Millerstatic int __devinit esp_sbus_setup_dma(struct esp *esp,
472dc11581376829303b98eadb2de253bee065a56aGrant Likely					struct platform_device *dma_of)
48334ae614772b1147435dce9be3911f9040dff0d9David S. Miller{
49334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	esp->dma = dma_of;
50cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
51334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	esp->dma_regs = of_ioremap(&dma_of->resource[0], 0,
52334ae614772b1147435dce9be3911f9040dff0d9David S. Miller				   resource_size(&dma_of->resource[0]),
53334ae614772b1147435dce9be3911f9040dff0d9David S. Miller				   "espdma");
54334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (!esp->dma_regs)
55334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		return -ENOMEM;
56cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
57334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) {
58334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERS0:
59334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarev0;
60334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
61334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_ESCV1:
62334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmaesc1;
63334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
64334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERS1:
65334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarev1;
66334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
67334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERS2:
68334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarev2;
69334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
70334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERHME:
71334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmahme;
72334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
73334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERSPLUS:
74334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarevplus;
75334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
76cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
77cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
78cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
79cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
80cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
81cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
82cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
83cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
842dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
85cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct resource *res;
86cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
87cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* On HME, two reg sets exist, first is DVMA,
88cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 * second is ESP registers.
89cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 */
90cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (hme)
9105bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		res = &op->resource[1];
92cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	else
9305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		res = &op->resource[0];
94cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
9505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp->regs = of_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
96cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!esp->regs)
97cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return -ENOMEM;
98cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
99cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
100cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
101cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
102cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_map_command_block(struct esp *esp)
103cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1042dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
105cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
10605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp->command_block = dma_alloc_coherent(&op->dev, 16,
107738f2b7b813913e651f39387d007dd961755dee2David S. Miller						&esp->command_block_dma,
108738f2b7b813913e651f39387d007dd961755dee2David S. Miller						GFP_ATOMIC);
109cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!esp->command_block)
110cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return -ENOMEM;
111cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
112cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
113cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
114cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __devinit esp_sbus_register_irq(struct esp *esp)
115cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
116cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct Scsi_Host *host = esp->host;
1172dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
118cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1191636f8ac2b08410df4766449f7c86b912443cd99Grant Likely	host->irq = op->archdata.irqs[0];
120cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
121cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
122cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1232dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
124cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1252dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
12605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct device_node *dp;
127cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
12861c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
129cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff);
130cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (esp->scsi_id != 0xff)
131cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto done;
132cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
133cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", 0xff);
134cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (esp->scsi_id != 0xff)
135cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto done;
136cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
13761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	esp->scsi_id = of_getintprop_default(espdma->dev.of_node,
138cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					     "scsi-initiator-id", 7);
139cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
140cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerdone:
141cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->host->this_id = esp->scsi_id;
142cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->scsi_id_mask = (1 << esp->scsi_id);
143cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
144cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
145cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_get_differential(struct esp *esp)
146cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1472dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
14805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct device_node *dp;
149cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
15061c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
151cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (of_find_property(dp, "differential", NULL))
152cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->flags |= ESP_FLAG_DIFFERENTIAL;
153cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	else
154cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
155cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
156cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
157cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __devinit esp_get_clock_params(struct esp *esp)
158cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1592dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
16005bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct device_node *bus_dp, *dp;
161cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int fmhz;
162cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
16361c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
16405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	bus_dp = dp->parent;
165cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
166cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	fmhz = of_getintprop_default(dp, "clock-frequency", 0);
167cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (fmhz == 0)
16805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		fmhz = of_getintprop_default(bus_dp, "clock-frequency", 0);
169cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
170cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->cfreq = fmhz;
171cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
172cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1732dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
174cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
17561c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *dma_dp = dma_of->dev.of_node;
1762dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
177334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	struct device_node *dp;
178334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	u8 bursts, val;
179cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
18061c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
181cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	bursts = of_getintprop_default(dp, "burst-sizes", 0xff);
182334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
183334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (val != 0xff)
184334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		bursts &= val;
185cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
18605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	val = of_getintprop_default(dma_dp->parent, "burst-sizes", 0xff);
18705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	if (val != 0xff)
18805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		bursts &= val;
189cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
190cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (bursts == 0xff ||
191cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	    (bursts & DMA_BURST16) == 0 ||
192cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	    (bursts & DMA_BURST32) == 0)
193cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		bursts = (DMA_BURST32 - 1);
194cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
195cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->bursts = bursts;
196cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
197cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1982dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
199cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
20005bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp_get_scsi_id(esp, espdma);
201cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_get_differential(esp);
202cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_get_clock_params(esp);
203cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_get_bursts(esp, espdma);
204cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
205cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
206cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_write8(struct esp *esp, u8 val, unsigned long reg)
207cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
208cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_writeb(val, esp->regs + (reg * 4UL));
209cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
210cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
211cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic u8 sbus_esp_read8(struct esp *esp, unsigned long reg)
212cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
213cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return sbus_readb(esp->regs + (reg * 4UL));
214cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
215cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
216cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf,
217cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				      size_t sz, int dir)
218cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2192dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2207a715f46012f3552294154978aed59cba9804928David S. Miller
22105bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	return dma_map_single(&op->dev, buf, sz, dir);
222cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
223cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
224cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg,
225cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				  int num_sg, int dir)
226cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2272dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2287a715f46012f3552294154978aed59cba9804928David S. Miller
22905bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	return dma_map_sg(&op->dev, sg, num_sg, dir);
230cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
231cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
232cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr,
233cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				  size_t sz, int dir)
234cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2352dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2367a715f46012f3552294154978aed59cba9804928David S. Miller
23705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_unmap_single(&op->dev, addr, sz, dir);
238cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
239cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
240cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
241cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			      int num_sg, int dir)
242cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2432dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2447a715f46012f3552294154978aed59cba9804928David S. Miller
24505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_unmap_sg(&op->dev, sg, num_sg, dir);
246cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
247cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
248cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_irq_pending(struct esp *esp)
249cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
250cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
251cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return 1;
252cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
253cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
254cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
255cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_reset_dma(struct esp *esp)
256cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
257cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int can_do_burst16, can_do_burst32, can_do_burst64;
258cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int can_do_sbus64, lim;
2592dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op;
260cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 val;
261cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
262cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
263cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
264cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_burst64 = 0;
265cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_sbus64 = 0;
26605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	op = esp->dev;
26763237eeb5ac92d618a0a6055f4b1f65c5d14682bDavid S. Miller	if (sbus_can_dma_64bit())
268cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		can_do_sbus64 = 1;
26963237eeb5ac92d618a0a6055f4b1f65c5d14682bDavid S. Miller	if (sbus_can_burst64())
270cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
271cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
272cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Put the DVMA into a known state. */
273334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev != dvmahme) {
274cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val = dma_read32(DMA_CSR);
275cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val | DMA_RST_SCSI, DMA_CSR);
276cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
277cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
278334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	switch (esp->dmarev) {
279cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmahme:
280cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(DMA_RESET_FAS366, DMA_CSR);
281cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(DMA_RST_SCSI, DMA_CSR);
282cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
283cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS |
284cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					DMA_SCSI_DISAB | DMA_INT_ENAB);
285cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
286cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE |
287cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					  DMA_BRST_SZ);
288cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
289cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (can_do_burst64)
290cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			esp->prev_hme_dmacsr |= DMA_BRST64;
291cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		else if (can_do_burst32)
292cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			esp->prev_hme_dmacsr |= DMA_BRST32;
293cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
294cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (can_do_sbus64) {
295cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
29605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller			sbus_set_sbus64(&op->dev, esp->bursts);
297cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
298cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
299cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		lim = 1000;
300cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		while (dma_read32(DMA_CSR) & DMA_PEND_READ) {
301cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			if (--lim == 0) {
302cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ "
303cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				       "will not clear!\n",
304cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				       esp->host->unique_id);
305cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				break;
306cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			}
307cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			udelay(1);
308cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
309cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
310cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_CSR);
311cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
312cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
313cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_ADDR);
314cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
315cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
316cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmarev2:
317cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (esp->rev != ESP100) {
318cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val = dma_read32(DMA_CSR);
319cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			dma_write32(val | DMA_3CLKS, DMA_CSR);
320cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
321cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
322cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
323cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmarev3:
324cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val = dma_read32(DMA_CSR);
325cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~DMA_3CLKS;
326cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val |= DMA_2CLKS;
327cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (can_do_burst32) {
328cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val &= ~DMA_BRST_SZ;
329cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val |= DMA_BRST32;
330cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
331cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
332cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
333cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
334cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmaesc1:
335cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val = dma_read32(DMA_CSR);
336cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val |= DMA_ADD_ENABLE;
337cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~DMA_BCNT_ENAB;
338cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (!can_do_burst32 && can_do_burst16) {
339cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val |= DMA_ESC_BURST;
340cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		} else {
341cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val &= ~(DMA_ESC_BURST);
342cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
343cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
344cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
345cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
346cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	default:
347cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
348cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
349cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
350cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Enable interrupts.  */
351cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	val = dma_read32(DMA_CSR);
352cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	dma_write32(val | DMA_INT_ENAB, DMA_CSR);
353cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
354cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
355cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_dma_drain(struct esp *esp)
356cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
357cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 csr;
358cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int lim;
359cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
360334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev == dvmahme)
361cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return;
362cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
363cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	csr = dma_read32(DMA_CSR);
364cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!(csr & DMA_FIFO_ISDRAIN))
365cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return;
366cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
367334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1)
368cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
369cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
370cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	lim = 1000;
371cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) {
372cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (--lim == 0) {
373cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n",
374cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			       esp->host->unique_id);
375cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			break;
376cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
377cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		udelay(1);
378cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
379cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
380cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
381cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_dma_invalidate(struct esp *esp)
382cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
383334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev == dvmahme) {
384cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(DMA_RST_SCSI, DMA_CSR);
385cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
386cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
387cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					 (DMA_PARITY_OFF | DMA_2CLKS |
388cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					  DMA_SCSI_DISAB | DMA_INT_ENAB)) &
389cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					~(DMA_ST_WRITE | DMA_ENABLE));
390cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
391cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_CSR);
392cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
393cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
394cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		/* This is necessary to avoid having the SCSI channel
395cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		 * engine lock up on us.
396cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		 */
397cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_ADDR);
398cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	} else {
399cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		u32 val;
400cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		int lim;
401cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
402cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		lim = 1000;
403cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) {
404cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			if (--lim == 0) {
405cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				printk(KERN_ALERT PFX "esp%d: DMA will not "
406cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				       "invalidate!\n", esp->host->unique_id);
407cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				break;
408cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			}
409cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			udelay(1);
410cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
411cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
412cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
413cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val |= DMA_FIFO_INV;
414cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
415cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~DMA_FIFO_INV;
416cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
417cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
418cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
419cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
420cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
421cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				  u32 dma_count, int write, u8 cmd)
422cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
423cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 csr;
424cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
425cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	BUG_ON(!(cmd & ESP_CMD_DMA));
426cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
427cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
428cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
429cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (esp->rev == FASHME) {
430cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO);
431cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		sbus_esp_write8(esp, 0, FAS_RHI);
432cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
433cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		scsi_esp_cmd(esp, cmd);
434cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
435cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr = esp->prev_hme_dmacsr;
436cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr |= DMA_SCSI_DISAB | 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		esp->prev_hme_dmacsr = csr;
442cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
443cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(dma_count, DMA_COUNT);
444cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(addr, DMA_ADDR);
445cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(csr, DMA_CSR);
446cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	} else {
447cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr = dma_read32(DMA_CSR);
448cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr |= DMA_ENABLE;
449cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (write)
450cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			csr |= DMA_ST_WRITE;
451cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		else
452cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			csr &= ~DMA_ST_WRITE;
453cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(csr, DMA_CSR);
454334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		if (esp->dmarev == dvmaesc1) {
455cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			u32 end = PAGE_ALIGN(addr + dma_count + 16U);
456cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			dma_write32(end - addr, DMA_COUNT);
457cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
458cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(addr, DMA_ADDR);
459cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
460cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		scsi_esp_cmd(esp, cmd);
461cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
462cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
463cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
464cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
465cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_dma_error(struct esp *esp)
466cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
467cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 csr = dma_read32(DMA_CSR);
468cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
469cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (csr & DMA_HNDL_ERROR)
470cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return 1;
471cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
472cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
473cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
474cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
475cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic const struct esp_driver_ops sbus_esp_ops = {
476cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.esp_write8	=	sbus_esp_write8,
477cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.esp_read8	=	sbus_esp_read8,
478cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.map_single	=	sbus_esp_map_single,
479cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.map_sg		=	sbus_esp_map_sg,
480cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.unmap_single	=	sbus_esp_unmap_single,
481cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.unmap_sg	=	sbus_esp_unmap_sg,
482cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.irq_pending	=	sbus_esp_irq_pending,
483cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.reset_dma	=	sbus_esp_reset_dma,
484cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.dma_drain	=	sbus_esp_dma_drain,
485cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.dma_invalidate	=	sbus_esp_dma_invalidate,
486cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.send_dma_cmd	=	sbus_esp_send_dma_cmd,
487cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.dma_error	=	sbus_esp_dma_error,
488cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller};
489cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
4902dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devinit esp_sbus_probe_one(struct platform_device *op,
4912dc11581376829303b98eadb2de253bee065a56aGrant Likely					struct platform_device *espdma,
492cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					int hme)
493cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
494cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct scsi_host_template *tpnt = &scsi_esp_template;
495cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct Scsi_Host *host;
496cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct esp *esp;
497cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int err;
498cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
499cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	host = scsi_host_alloc(tpnt, sizeof(struct esp));
500cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
501cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = -ENOMEM;
502cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!host)
503cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail;
504cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
505cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	host->max_id = (hme ? 16 : 8);
5062b14ec787869707843a14164a3ba91930a076031Christoph Hellwig	esp = shost_priv(host);
507cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
508cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->host = host;
50905bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp->dev = op;
510cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->ops = &sbus_esp_ops;
511cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
512cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (hme)
513cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->flags |= ESP_FLAG_WIDE_CAPABLE;
514cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
515334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	err = esp_sbus_setup_dma(esp, espdma);
516cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
517cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unlink;
518cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
519cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = esp_sbus_map_regs(esp, hme);
520cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
521cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unlink;
522cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
523cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = esp_sbus_map_command_block(esp);
524cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
525cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unmap_regs;
526cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
527cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = esp_sbus_register_irq(esp);
528cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
529cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unmap_command_block;
530cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
531cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_sbus_get_props(esp, espdma);
532cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
533cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Before we try to touch the ESP chip, ESC1 dma can
534cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 * come up with the reset bit set, so make sure that
535cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 * is clear first.
536cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 */
537334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev == dvmaesc1) {
538cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		u32 val = dma_read32(DMA_CSR);
539cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
540cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
541cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
542cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
54305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dev_set_drvdata(&op->dev, esp);
544cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
54505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	err = scsi_esp_register(esp, &op->dev);
546cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err)
547cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_free_irq;
548cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
549cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
550cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
551cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_free_irq:
552cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	free_irq(host->irq, esp);
553cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unmap_command_block:
55405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_free_coherent(&op->dev, 16,
555738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block,
556738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block_dma);
557cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unmap_regs:
55805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	of_iounmap(&op->resource[(hme ? 1 : 0)], esp->regs, SBUS_ESP_REG_SIZE);
559cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unlink:
560cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	scsi_host_put(host);
561cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail:
562cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return err;
563cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
564cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
5654ebb24f707187196937607c60810d42f7112d7aaGrant Likelystatic int __devinit esp_sbus_probe(struct platform_device *op)
566cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
567334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	struct device_node *dma_node = NULL;
56861c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *dp = op->dev.of_node;
5692dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *dma_of = NULL;
570cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int hme = 0;
571cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
572cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (dp->parent &&
573cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	    (!strcmp(dp->parent->name, "espdma") ||
574cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	     !strcmp(dp->parent->name, "dma")))
575334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		dma_node = dp->parent;
576cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	else if (!strcmp(dp->name, "SUNW,fas")) {
57761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely		dma_node = op->dev.of_node;
578cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		hme = 1;
579cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
580334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (dma_node)
581334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		dma_of = of_find_device_by_node(dma_node);
582334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (!dma_of)
583334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		return -ENODEV;
584cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
58505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	return esp_sbus_probe_one(op, dma_of, hme);
586cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
587cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
5882dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit esp_sbus_remove(struct platform_device *op)
589cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
59005bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct esp *esp = dev_get_drvdata(&op->dev);
5912dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *dma_of = esp->dma;
592cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	unsigned int irq = esp->host->irq;
59305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	bool is_hme;
594cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 val;
595cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
596cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	scsi_esp_unregister(esp);
597cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
598cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Disable interrupts.  */
599cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	val = dma_read32(DMA_CSR);
600cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
601cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
602cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	free_irq(irq, esp);
60305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller
60405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	is_hme = (esp->dmarev == dvmahme);
60505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller
60605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_free_coherent(&op->dev, 16,
607738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block,
608738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block_dma);
60905bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	of_iounmap(&op->resource[(is_hme ? 1 : 0)], esp->regs,
61005bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		   SBUS_ESP_REG_SIZE);
611334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	of_iounmap(&dma_of->resource[0], esp->dma_regs,
612334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		   resource_size(&dma_of->resource[0]));
613cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
614cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	scsi_host_put(esp->host);
615cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
61605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dev_set_drvdata(&op->dev, NULL);
61705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller
618cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
619cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
620cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
621fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id esp_match[] = {
622cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{
623cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		.name = "SUNW,esp",
624cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	},
625cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{
626cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		.name = "SUNW,fas",
627cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	},
628cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{
629cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		.name = "esp",
630cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	},
631cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{},
632cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller};
633cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_DEVICE_TABLE(of, esp_match);
634cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
6354ebb24f707187196937607c60810d42f7112d7aaGrant Likelystatic struct platform_driver esp_sbus_driver = {
6364018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
6374018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "esp",
6384018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
6394018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = esp_match,
6404018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
641cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.probe		= esp_sbus_probe,
642cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.remove		= __devexit_p(esp_sbus_remove),
643cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller};
644cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
645cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __init sunesp_init(void)
646cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
6474ebb24f707187196937607c60810d42f7112d7aaGrant Likely	return platform_driver_register(&esp_sbus_driver);
648cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
649cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
650cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __exit sunesp_exit(void)
651cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
6524ebb24f707187196937607c60810d42f7112d7aaGrant Likely	platform_driver_unregister(&esp_sbus_driver);
653cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
654cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
655cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_DESCRIPTION("Sun ESP SCSI driver");
656cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
657cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_LICENSE("GPL");
658cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_VERSION(DRV_VERSION);
659cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
660cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millermodule_init(sunesp_init);
661cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millermodule_exit(sunesp_exit);
662