1 /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
3 * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
6 #include <linux/kernel.h>
8 #include <linux/types.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/interrupt.h>
12 #include <linux/platform_device.h>
13 #include <linux/dma-mapping.h>
20 #include <asm/jazzdma.h>
22 #include <scsi/scsi_host.h>
26 #define DRV_MODULE_NAME "jazz_esp"
27 #define PFX DRV_MODULE_NAME ": "
28 #define DRV_VERSION "1.000"
29 #define DRV_MODULE_RELDATE "May 19, 2007"
31 static void jazz_esp_write8(struct esp
*esp
, u8 val
, unsigned long reg
)
33 *(volatile u8
*)(esp
->regs
+ reg
) = val
;
36 static u8
jazz_esp_read8(struct esp
*esp
, unsigned long reg
)
38 return *(volatile u8
*)(esp
->regs
+ reg
);
41 static int jazz_esp_irq_pending(struct esp
*esp
)
43 if (jazz_esp_read8(esp
, ESP_STATUS
) & ESP_STAT_INTR
)
48 static void jazz_esp_reset_dma(struct esp
*esp
)
50 vdma_disable ((int)esp
->dma_regs
);
53 static void jazz_esp_dma_drain(struct esp
*esp
)
58 static void jazz_esp_dma_invalidate(struct esp
*esp
)
60 vdma_disable ((int)esp
->dma_regs
);
63 static void jazz_esp_send_dma_cmd(struct esp
*esp
, u32 addr
, u32 esp_count
,
64 u32 dma_count
, int write
, u8 cmd
)
66 BUG_ON(!(cmd
& ESP_CMD_DMA
));
68 jazz_esp_write8(esp
, (esp_count
>> 0) & 0xff, ESP_TCLOW
);
69 jazz_esp_write8(esp
, (esp_count
>> 8) & 0xff, ESP_TCMED
);
70 vdma_disable ((int)esp
->dma_regs
);
72 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_READ
);
74 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_WRITE
);
76 vdma_set_addr ((int)esp
->dma_regs
, addr
);
77 vdma_set_count ((int)esp
->dma_regs
, dma_count
);
78 vdma_enable ((int)esp
->dma_regs
);
80 scsi_esp_cmd(esp
, cmd
);
83 static int jazz_esp_dma_error(struct esp
*esp
)
85 u32 enable
= vdma_get_enable((int)esp
->dma_regs
);
87 if (enable
& (R4030_MEM_INTR
|R4030_ADDR_INTR
))
93 static const struct esp_driver_ops jazz_esp_ops
= {
94 .esp_write8
= jazz_esp_write8
,
95 .esp_read8
= jazz_esp_read8
,
96 .irq_pending
= jazz_esp_irq_pending
,
97 .reset_dma
= jazz_esp_reset_dma
,
98 .dma_drain
= jazz_esp_dma_drain
,
99 .dma_invalidate
= jazz_esp_dma_invalidate
,
100 .send_dma_cmd
= jazz_esp_send_dma_cmd
,
101 .dma_error
= jazz_esp_dma_error
,
104 static int esp_jazz_probe(struct platform_device
*dev
)
106 struct scsi_host_template
*tpnt
= &scsi_esp_template
;
107 struct Scsi_Host
*host
;
109 struct resource
*res
;
112 host
= scsi_host_alloc(tpnt
, sizeof(struct esp
));
119 esp
= shost_priv(host
);
122 esp
->dev
= &dev
->dev
;
123 esp
->ops
= &jazz_esp_ops
;
125 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
129 esp
->regs
= (void __iomem
*)res
->start
;
133 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
137 esp
->dma_regs
= (void __iomem
*)res
->start
;
139 esp
->command_block
= dma_alloc_coherent(esp
->dev
, 16,
140 &esp
->command_block_dma
,
142 if (!esp
->command_block
)
143 goto fail_unmap_regs
;
145 host
->irq
= platform_get_irq(dev
, 0);
146 err
= request_irq(host
->irq
, scsi_esp_intr
, IRQF_SHARED
, "ESP", esp
);
148 goto fail_unmap_command_block
;
151 esp
->host
->this_id
= esp
->scsi_id
;
152 esp
->scsi_id_mask
= (1 << esp
->scsi_id
);
153 esp
->cfreq
= 40000000;
155 dev_set_drvdata(&dev
->dev
, esp
);
157 err
= scsi_esp_register(esp
);
164 free_irq(host
->irq
, esp
);
165 fail_unmap_command_block
:
166 dma_free_coherent(esp
->dev
, 16,
168 esp
->command_block_dma
);
176 static int esp_jazz_remove(struct platform_device
*dev
)
178 struct esp
*esp
= dev_get_drvdata(&dev
->dev
);
179 unsigned int irq
= esp
->host
->irq
;
181 scsi_esp_unregister(esp
);
184 dma_free_coherent(esp
->dev
, 16,
186 esp
->command_block_dma
);
188 scsi_host_put(esp
->host
);
193 /* work with hotplug and coldplug */
194 MODULE_ALIAS("platform:jazz_esp");
196 static struct platform_driver esp_jazz_driver
= {
197 .probe
= esp_jazz_probe
,
198 .remove
= esp_jazz_remove
,
204 static int __init
jazz_esp_init(void)
206 return platform_driver_register(&esp_jazz_driver
);
209 static void __exit
jazz_esp_exit(void)
211 platform_driver_unregister(&esp_jazz_driver
);
214 MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
215 MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
216 MODULE_LICENSE("GPL");
217 MODULE_VERSION(DRV_VERSION
);
219 module_init(jazz_esp_init
);
220 module_exit(jazz_esp_exit
);