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
466f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_setup_dma(struct esp *esp, struct platform_device *dma_of)
47334ae614772b1147435dce9be3911f9040dff0d9David S. Miller{
48334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	esp->dma = dma_of;
49cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
50334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	esp->dma_regs = of_ioremap(&dma_of->resource[0], 0,
51334ae614772b1147435dce9be3911f9040dff0d9David S. Miller				   resource_size(&dma_of->resource[0]),
52334ae614772b1147435dce9be3911f9040dff0d9David S. Miller				   "espdma");
53334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (!esp->dma_regs)
54334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		return -ENOMEM;
55cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
56334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) {
57334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERS0:
58334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarev0;
59334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
60334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_ESCV1:
61334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmaesc1;
62334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
63334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERS1:
64334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarev1;
65334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
66334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERS2:
67334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarev2;
68334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
69334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERHME:
70334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmahme;
71334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
72334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	case DMA_VERSPLUS:
73334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		esp->dmarev = dvmarevplus;
74334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		break;
75cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
76cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
77cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
78cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
79cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
80cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
816f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_map_regs(struct esp *esp, int hme)
82cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
832dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
84cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct resource *res;
85cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
86cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* On HME, two reg sets exist, first is DVMA,
87cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 * second is ESP registers.
88cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 */
89cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (hme)
9005bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		res = &op->resource[1];
91cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	else
9205bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		res = &op->resource[0];
93cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
9405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp->regs = of_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
95cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!esp->regs)
96cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return -ENOMEM;
97cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
98cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
99cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
100cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1016f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_map_command_block(struct esp *esp)
102cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1032dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
104cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
10505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp->command_block = dma_alloc_coherent(&op->dev, 16,
106738f2b7b813913e651f39387d007dd961755dee2David S. Miller						&esp->command_block_dma,
107738f2b7b813913e651f39387d007dd961755dee2David S. Miller						GFP_ATOMIC);
108cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!esp->command_block)
109cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return -ENOMEM;
110cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
111cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
112cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1136f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_register_irq(struct esp *esp)
114cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
115cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct Scsi_Host *host = esp->host;
1162dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
117cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1181636f8ac2b08410df4766449f7c86b912443cd99Grant Likely	host->irq = op->archdata.irqs[0];
119cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
120cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
121cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1226f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic void esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
123cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1242dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
12505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct device_node *dp;
126cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
12761c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
128cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff);
129cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (esp->scsi_id != 0xff)
130cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto done;
131cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
132cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", 0xff);
133cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (esp->scsi_id != 0xff)
134cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto done;
135cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
13661c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	esp->scsi_id = of_getintprop_default(espdma->dev.of_node,
137cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					     "scsi-initiator-id", 7);
138cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
139cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerdone:
140cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->host->this_id = esp->scsi_id;
141cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->scsi_id_mask = (1 << esp->scsi_id);
142cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
143cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1446f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic void esp_get_differential(struct esp *esp)
145cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1462dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
14705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct device_node *dp;
148cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
14961c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
150cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (of_find_property(dp, "differential", NULL))
151cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->flags |= ESP_FLAG_DIFFERENTIAL;
152cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	else
153cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
154cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
155cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1566f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic void esp_get_clock_params(struct esp *esp)
157cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
1582dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
15905bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct device_node *bus_dp, *dp;
160cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int fmhz;
161cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
16261c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
16305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	bus_dp = dp->parent;
164cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
165cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	fmhz = of_getintprop_default(dp, "clock-frequency", 0);
166cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (fmhz == 0)
16705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		fmhz = of_getintprop_default(bus_dp, "clock-frequency", 0);
168cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
169cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->cfreq = fmhz;
170cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
171cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1726f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic void esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
173cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
17461c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *dma_dp = dma_of->dev.of_node;
1752dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
176334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	struct device_node *dp;
177334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	u8 bursts, val;
178cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
17961c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	dp = op->dev.of_node;
180cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	bursts = of_getintprop_default(dp, "burst-sizes", 0xff);
181334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
182334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (val != 0xff)
183334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		bursts &= val;
184cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
18505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	val = of_getintprop_default(dma_dp->parent, "burst-sizes", 0xff);
18605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	if (val != 0xff)
18705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		bursts &= val;
188cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
189cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (bursts == 0xff ||
190cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	    (bursts & DMA_BURST16) == 0 ||
191cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	    (bursts & DMA_BURST32) == 0)
192cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		bursts = (DMA_BURST32 - 1);
193cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
194cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->bursts = bursts;
195cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
196cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
1976f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic void esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
198cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
19905bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp_get_scsi_id(esp, espdma);
200cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_get_differential(esp);
201cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_get_clock_params(esp);
202cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_get_bursts(esp, espdma);
203cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
204cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
205cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_write8(struct esp *esp, u8 val, unsigned long reg)
206cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
207cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_writeb(val, esp->regs + (reg * 4UL));
208cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
209cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
210cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic u8 sbus_esp_read8(struct esp *esp, unsigned long reg)
211cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
212cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return sbus_readb(esp->regs + (reg * 4UL));
213cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
214cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
215cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf,
216cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				      size_t sz, int dir)
217cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2182dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2197a715f46012f3552294154978aed59cba9804928David S. Miller
22005bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	return dma_map_single(&op->dev, buf, sz, dir);
221cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
222cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
223cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg,
224cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				  int num_sg, int dir)
225cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2262dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2277a715f46012f3552294154978aed59cba9804928David S. Miller
22805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	return dma_map_sg(&op->dev, sg, num_sg, dir);
229cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
230cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
231cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr,
232cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				  size_t sz, int dir)
233cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2342dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2357a715f46012f3552294154978aed59cba9804928David S. Miller
23605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_unmap_single(&op->dev, addr, sz, dir);
237cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
238cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
239cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
240cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			      int num_sg, int dir)
241cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
2422dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op = esp->dev;
2437a715f46012f3552294154978aed59cba9804928David S. Miller
24405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_unmap_sg(&op->dev, sg, num_sg, dir);
245cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
246cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
247cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_irq_pending(struct esp *esp)
248cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
249cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
250cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return 1;
251cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
252cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
253cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
254cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_reset_dma(struct esp *esp)
255cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
256cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int can_do_burst16, can_do_burst32, can_do_burst64;
257cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int can_do_sbus64, lim;
2582dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *op;
259cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 val;
260cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
261cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
262cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
263cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_burst64 = 0;
264cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	can_do_sbus64 = 0;
26505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	op = esp->dev;
26663237eeb5ac92d618a0a6055f4b1f65c5d14682bDavid S. Miller	if (sbus_can_dma_64bit())
267cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		can_do_sbus64 = 1;
26863237eeb5ac92d618a0a6055f4b1f65c5d14682bDavid S. Miller	if (sbus_can_burst64())
269cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
270cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
271cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Put the DVMA into a known state. */
272334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev != dvmahme) {
273cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val = dma_read32(DMA_CSR);
274cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val | DMA_RST_SCSI, DMA_CSR);
275cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
276cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
277334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	switch (esp->dmarev) {
278cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmahme:
279cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(DMA_RESET_FAS366, DMA_CSR);
280cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(DMA_RST_SCSI, DMA_CSR);
281cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
282cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS |
283cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					DMA_SCSI_DISAB | DMA_INT_ENAB);
284cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
285cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE |
286cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					  DMA_BRST_SZ);
287cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
288cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (can_do_burst64)
289cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			esp->prev_hme_dmacsr |= DMA_BRST64;
290cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		else if (can_do_burst32)
291cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			esp->prev_hme_dmacsr |= DMA_BRST32;
292cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
293cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (can_do_sbus64) {
294cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
29505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller			sbus_set_sbus64(&op->dev, esp->bursts);
296cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
297cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
298cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		lim = 1000;
299cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		while (dma_read32(DMA_CSR) & DMA_PEND_READ) {
300cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			if (--lim == 0) {
301cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ "
302cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				       "will not clear!\n",
303cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				       esp->host->unique_id);
304cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				break;
305cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			}
306cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			udelay(1);
307cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
308cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
309cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_CSR);
310cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
311cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
312cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_ADDR);
313cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
314cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
315cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmarev2:
316cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (esp->rev != ESP100) {
317cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val = dma_read32(DMA_CSR);
318cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			dma_write32(val | DMA_3CLKS, DMA_CSR);
319cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
320cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
321cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
322cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmarev3:
323cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val = dma_read32(DMA_CSR);
324cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~DMA_3CLKS;
325cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val |= DMA_2CLKS;
326cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (can_do_burst32) {
327cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val &= ~DMA_BRST_SZ;
328cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val |= DMA_BRST32;
329cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
330cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
331cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
332cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
333cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	case dvmaesc1:
334cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val = dma_read32(DMA_CSR);
335cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val |= DMA_ADD_ENABLE;
336cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~DMA_BCNT_ENAB;
337cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (!can_do_burst32 && can_do_burst16) {
338cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val |= DMA_ESC_BURST;
339cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		} else {
340cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			val &= ~(DMA_ESC_BURST);
341cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
342cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
343cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
344cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
345cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	default:
346cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		break;
347cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
348cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
349cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Enable interrupts.  */
350cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	val = dma_read32(DMA_CSR);
351cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	dma_write32(val | DMA_INT_ENAB, DMA_CSR);
352cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
353cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
354cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_dma_drain(struct esp *esp)
355cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
356cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 csr;
357cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int lim;
358cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
359334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev == dvmahme)
360cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return;
361cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
362cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	csr = dma_read32(DMA_CSR);
363cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!(csr & DMA_FIFO_ISDRAIN))
364cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return;
365cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
366334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1)
367cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
368cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
369cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	lim = 1000;
370cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) {
371cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (--lim == 0) {
372cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n",
373cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			       esp->host->unique_id);
374cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			break;
375cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
376cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		udelay(1);
377cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
378cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
379cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
380cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_dma_invalidate(struct esp *esp)
381cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
382334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev == dvmahme) {
383cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(DMA_RST_SCSI, DMA_CSR);
384cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
385cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
386cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					 (DMA_PARITY_OFF | DMA_2CLKS |
387cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					  DMA_SCSI_DISAB | DMA_INT_ENAB)) &
388cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller					~(DMA_ST_WRITE | DMA_ENABLE));
389cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
390cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_CSR);
391cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
392cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
393cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		/* This is necessary to avoid having the SCSI channel
394cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		 * engine lock up on us.
395cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		 */
396cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(0, DMA_ADDR);
397cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	} else {
398cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		u32 val;
399cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		int lim;
400cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
401cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		lim = 1000;
402cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) {
403cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			if (--lim == 0) {
404cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				printk(KERN_ALERT PFX "esp%d: DMA will not "
405cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				       "invalidate!\n", esp->host->unique_id);
406cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				break;
407cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			}
408cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			udelay(1);
409cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
410cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
411cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
412cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val |= DMA_FIFO_INV;
413cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
414cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		val &= ~DMA_FIFO_INV;
415cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val, DMA_CSR);
416cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
417cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
418cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
419cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
420cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller				  u32 dma_count, int write, u8 cmd)
421cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
422cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 csr;
423cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
424cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	BUG_ON(!(cmd & ESP_CMD_DMA));
425cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
426cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
427cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
428cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (esp->rev == FASHME) {
429cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO);
430cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		sbus_esp_write8(esp, 0, FAS_RHI);
431cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
432cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		scsi_esp_cmd(esp, cmd);
433cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
434cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr = esp->prev_hme_dmacsr;
435cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr |= DMA_SCSI_DISAB | DMA_ENABLE;
436cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (write)
437cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			csr |= DMA_ST_WRITE;
438cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		else
439cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			csr &= ~DMA_ST_WRITE;
440cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->prev_hme_dmacsr = csr;
441cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
442cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(dma_count, DMA_COUNT);
443cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(addr, DMA_ADDR);
444cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(csr, DMA_CSR);
445cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	} else {
446cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr = dma_read32(DMA_CSR);
447cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		csr |= DMA_ENABLE;
448cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		if (write)
449cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			csr |= DMA_ST_WRITE;
450cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		else
451cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			csr &= ~DMA_ST_WRITE;
452cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(csr, DMA_CSR);
453334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		if (esp->dmarev == dvmaesc1) {
454cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			u32 end = PAGE_ALIGN(addr + dma_count + 16U);
455cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller			dma_write32(end - addr, DMA_COUNT);
456cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		}
457cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(addr, DMA_ADDR);
458cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
459cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		scsi_esp_cmd(esp, cmd);
460cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
461cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
462cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
463cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
464cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int sbus_esp_dma_error(struct esp *esp)
465cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
466cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 csr = dma_read32(DMA_CSR);
467cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
468cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (csr & DMA_HNDL_ERROR)
469cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		return 1;
470cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
471cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
472cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
473cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
474cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic const struct esp_driver_ops sbus_esp_ops = {
475cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.esp_write8	=	sbus_esp_write8,
476cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.esp_read8	=	sbus_esp_read8,
477cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.map_single	=	sbus_esp_map_single,
478cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.map_sg		=	sbus_esp_map_sg,
479cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.unmap_single	=	sbus_esp_unmap_single,
480cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.unmap_sg	=	sbus_esp_unmap_sg,
481cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.irq_pending	=	sbus_esp_irq_pending,
482cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.reset_dma	=	sbus_esp_reset_dma,
483cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.dma_drain	=	sbus_esp_dma_drain,
484cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.dma_invalidate	=	sbus_esp_dma_invalidate,
485cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.send_dma_cmd	=	sbus_esp_send_dma_cmd,
486cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.dma_error	=	sbus_esp_dma_error,
487cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller};
488cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
4896f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_probe_one(struct platform_device *op,
4906f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartman			      struct platform_device *espdma, int hme)
491cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
492cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct scsi_host_template *tpnt = &scsi_esp_template;
493cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct Scsi_Host *host;
494cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	struct esp *esp;
495cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int err;
496cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
497cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	host = scsi_host_alloc(tpnt, sizeof(struct esp));
498cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
499cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = -ENOMEM;
500cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (!host)
501cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail;
502cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
503cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	host->max_id = (hme ? 16 : 8);
5042b14ec787869707843a14164a3ba91930a076031Christoph Hellwig	esp = shost_priv(host);
505cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
506cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->host = host;
50705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	esp->dev = op;
508cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp->ops = &sbus_esp_ops;
509cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
510cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (hme)
511cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		esp->flags |= ESP_FLAG_WIDE_CAPABLE;
512cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
513334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	err = esp_sbus_setup_dma(esp, espdma);
514cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
515cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unlink;
516cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
517cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = esp_sbus_map_regs(esp, hme);
518cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
519cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unlink;
520cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
521cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = esp_sbus_map_command_block(esp);
522cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
523cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unmap_regs;
524cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
525cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	err = esp_sbus_register_irq(esp);
526cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err < 0)
527cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_unmap_command_block;
528cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
529cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	esp_sbus_get_props(esp, espdma);
530cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
531cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Before we try to touch the ESP chip, ESC1 dma can
532cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 * come up with the reset bit set, so make sure that
533cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 * is clear first.
534cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	 */
535334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (esp->dmarev == dvmaesc1) {
536cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		u32 val = dma_read32(DMA_CSR);
537cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
538cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
539cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
540cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
54105bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dev_set_drvdata(&op->dev, esp);
542cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
54305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	err = scsi_esp_register(esp, &op->dev);
544cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (err)
545cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		goto fail_free_irq;
546cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
547cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
548cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
549cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_free_irq:
550cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	free_irq(host->irq, esp);
551cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unmap_command_block:
55205bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_free_coherent(&op->dev, 16,
553738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block,
554738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block_dma);
555cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unmap_regs:
55605bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	of_iounmap(&op->resource[(hme ? 1 : 0)], esp->regs, SBUS_ESP_REG_SIZE);
557cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail_unlink:
558cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	scsi_host_put(host);
559cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerfail:
560cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return err;
561cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
562cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
5636f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_probe(struct platform_device *op)
564cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
565334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	struct device_node *dma_node = NULL;
56661c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *dp = op->dev.of_node;
5672dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *dma_of = NULL;
568cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	int hme = 0;
569cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
570cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	if (dp->parent &&
571cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	    (!strcmp(dp->parent->name, "espdma") ||
572cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	     !strcmp(dp->parent->name, "dma")))
573334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		dma_node = dp->parent;
574cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	else if (!strcmp(dp->name, "SUNW,fas")) {
57561c7a080a5a061c976988fd4b844dfb468dda255Grant Likely		dma_node = op->dev.of_node;
576cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		hme = 1;
577cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	}
578334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (dma_node)
579334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		dma_of = of_find_device_by_node(dma_node);
580334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	if (!dma_of)
581334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		return -ENODEV;
582cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
58305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	return esp_sbus_probe_one(op, dma_of, hme);
584cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
585cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
5866f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int esp_sbus_remove(struct platform_device *op)
587cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
58805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	struct esp *esp = dev_get_drvdata(&op->dev);
5892dc11581376829303b98eadb2de253bee065a56aGrant Likely	struct platform_device *dma_of = esp->dma;
590cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	unsigned int irq = esp->host->irq;
59105bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	bool is_hme;
592cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	u32 val;
593cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
594cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	scsi_esp_unregister(esp);
595cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
596cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	/* Disable interrupts.  */
597cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	val = dma_read32(DMA_CSR);
598cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
599cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
600cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	free_irq(irq, esp);
60105bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller
60205bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	is_hme = (esp->dmarev == dvmahme);
60305bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller
60405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dma_free_coherent(&op->dev, 16,
605738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block,
606738f2b7b813913e651f39387d007dd961755dee2David S. Miller			  esp->command_block_dma);
60705bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	of_iounmap(&op->resource[(is_hme ? 1 : 0)], esp->regs,
60805bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller		   SBUS_ESP_REG_SIZE);
609334ae614772b1147435dce9be3911f9040dff0d9David S. Miller	of_iounmap(&dma_of->resource[0], esp->dma_regs,
610334ae614772b1147435dce9be3911f9040dff0d9David S. Miller		   resource_size(&dma_of->resource[0]));
611cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
612cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	scsi_host_put(esp->host);
613cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
61405bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller	dev_set_drvdata(&op->dev, NULL);
61505bb5e93f2ef3f14e0c5a7e9281d07e7a7e4233dDavid S. Miller
616cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	return 0;
617cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
618cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
619fd098316ef533e8441576f020ead4beab93154ceDavid S. Millerstatic const struct of_device_id esp_match[] = {
620cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{
621cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		.name = "SUNW,esp",
622cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	},
623cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{
624cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		.name = "SUNW,fas",
625cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	},
626cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{
627cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller		.name = "esp",
628cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	},
629cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	{},
630cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller};
631cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_DEVICE_TABLE(of, esp_match);
632cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
6334ebb24f707187196937607c60810d42f7112d7aaGrant Likelystatic struct platform_driver esp_sbus_driver = {
6344018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
6354018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "esp",
6364018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
6374018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = esp_match,
6384018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	},
639cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller	.probe		= esp_sbus_probe,
6406f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartman	.remove		= esp_sbus_remove,
641cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller};
642cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
643cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic int __init sunesp_init(void)
644cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
6454ebb24f707187196937607c60810d42f7112d7aaGrant Likely	return platform_driver_register(&esp_sbus_driver);
646cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
647cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
648cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millerstatic void __exit sunesp_exit(void)
649cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller{
6504ebb24f707187196937607c60810d42f7112d7aaGrant Likely	platform_driver_unregister(&esp_sbus_driver);
651cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller}
652cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
653cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_DESCRIPTION("Sun ESP SCSI driver");
654cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
655cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_LICENSE("GPL");
656cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. MillerMODULE_VERSION(DRV_VERSION);
657cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Miller
658cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millermodule_init(sunesp_init);
659cd9ad58d4061494e7fdd70ded7bcf2418daf356aDavid S. Millermodule_exit(sunesp_exit);
660