1 // SPDX-License-Identifier: GPL-2.0-only
2 /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
4 * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
7 #include <linux/kernel.h>
9 #include <linux/types.h>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/dma-mapping.h>
21 #include <asm/jazzdma.h>
23 #include <scsi/scsi_host.h>
27 #define DRV_MODULE_NAME "jazz_esp"
28 #define PFX DRV_MODULE_NAME ": "
29 #define DRV_VERSION "1.000"
30 #define DRV_MODULE_RELDATE "May 19, 2007"
32 static void jazz_esp_write8(struct esp
*esp
, u8 val
, unsigned long reg
)
34 *(volatile u8
*)(esp
->regs
+ reg
) = val
;
37 static u8
jazz_esp_read8(struct esp
*esp
, unsigned long reg
)
39 return *(volatile u8
*)(esp
->regs
+ reg
);
42 static int jazz_esp_irq_pending(struct esp
*esp
)
44 if (jazz_esp_read8(esp
, ESP_STATUS
) & ESP_STAT_INTR
)
49 static void jazz_esp_reset_dma(struct esp
*esp
)
51 vdma_disable ((int)esp
->dma_regs
);
54 static void jazz_esp_dma_drain(struct esp
*esp
)
59 static void jazz_esp_dma_invalidate(struct esp
*esp
)
61 vdma_disable ((int)esp
->dma_regs
);
64 static void jazz_esp_send_dma_cmd(struct esp
*esp
, u32 addr
, u32 esp_count
,
65 u32 dma_count
, int write
, u8 cmd
)
67 BUG_ON(!(cmd
& ESP_CMD_DMA
));
69 jazz_esp_write8(esp
, (esp_count
>> 0) & 0xff, ESP_TCLOW
);
70 jazz_esp_write8(esp
, (esp_count
>> 8) & 0xff, ESP_TCMED
);
71 vdma_disable ((int)esp
->dma_regs
);
73 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_READ
);
75 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_WRITE
);
77 vdma_set_addr ((int)esp
->dma_regs
, addr
);
78 vdma_set_count ((int)esp
->dma_regs
, dma_count
);
79 vdma_enable ((int)esp
->dma_regs
);
81 scsi_esp_cmd(esp
, cmd
);
84 static int jazz_esp_dma_error(struct esp
*esp
)
86 u32 enable
= vdma_get_enable((int)esp
->dma_regs
);
88 if (enable
& (R4030_MEM_INTR
|R4030_ADDR_INTR
))
94 static const struct esp_driver_ops jazz_esp_ops
= {
95 .esp_write8
= jazz_esp_write8
,
96 .esp_read8
= jazz_esp_read8
,
97 .irq_pending
= jazz_esp_irq_pending
,
98 .reset_dma
= jazz_esp_reset_dma
,
99 .dma_drain
= jazz_esp_dma_drain
,
100 .dma_invalidate
= jazz_esp_dma_invalidate
,
101 .send_dma_cmd
= jazz_esp_send_dma_cmd
,
102 .dma_error
= jazz_esp_dma_error
,
105 static int esp_jazz_probe(struct platform_device
*dev
)
107 struct scsi_host_template
*tpnt
= &scsi_esp_template
;
108 struct Scsi_Host
*host
;
110 struct resource
*res
;
113 host
= scsi_host_alloc(tpnt
, sizeof(struct esp
));
120 esp
= shost_priv(host
);
123 esp
->dev
= &dev
->dev
;
124 esp
->ops
= &jazz_esp_ops
;
126 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
130 esp
->regs
= (void __iomem
*)res
->start
;
134 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
138 esp
->dma_regs
= (void __iomem
*)res
->start
;
140 esp
->command_block
= dma_alloc_coherent(esp
->dev
, 16,
141 &esp
->command_block_dma
,
143 if (!esp
->command_block
)
144 goto fail_unmap_regs
;
146 host
->irq
= platform_get_irq(dev
, 0);
147 err
= request_irq(host
->irq
, scsi_esp_intr
, IRQF_SHARED
, "ESP", esp
);
149 goto fail_unmap_command_block
;
152 esp
->host
->this_id
= esp
->scsi_id
;
153 esp
->scsi_id_mask
= (1 << esp
->scsi_id
);
154 esp
->cfreq
= 40000000;
156 dev_set_drvdata(&dev
->dev
, esp
);
158 err
= scsi_esp_register(esp
);
165 free_irq(host
->irq
, esp
);
166 fail_unmap_command_block
:
167 dma_free_coherent(esp
->dev
, 16,
169 esp
->command_block_dma
);
177 static int esp_jazz_remove(struct platform_device
*dev
)
179 struct esp
*esp
= dev_get_drvdata(&dev
->dev
);
180 unsigned int irq
= esp
->host
->irq
;
182 scsi_esp_unregister(esp
);
185 dma_free_coherent(esp
->dev
, 16,
187 esp
->command_block_dma
);
189 scsi_host_put(esp
->host
);
194 /* work with hotplug and coldplug */
195 MODULE_ALIAS("platform:jazz_esp");
197 static struct platform_driver esp_jazz_driver
= {
198 .probe
= esp_jazz_probe
,
199 .remove
= esp_jazz_remove
,
204 module_platform_driver(esp_jazz_driver
);
206 MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
207 MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
208 MODULE_LICENSE("GPL");
209 MODULE_VERSION(DRV_VERSION
);