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 dma_addr_t
jazz_esp_map_single(struct esp
*esp
, void *buf
,
44 return dma_map_single(esp
->dev
, buf
, sz
, dir
);
47 static int jazz_esp_map_sg(struct esp
*esp
, struct scatterlist
*sg
,
50 return dma_map_sg(esp
->dev
, sg
, num_sg
, dir
);
53 static void jazz_esp_unmap_single(struct esp
*esp
, dma_addr_t addr
,
56 dma_unmap_single(esp
->dev
, addr
, sz
, dir
);
59 static void jazz_esp_unmap_sg(struct esp
*esp
, struct scatterlist
*sg
,
62 dma_unmap_sg(esp
->dev
, sg
, num_sg
, dir
);
65 static int jazz_esp_irq_pending(struct esp
*esp
)
67 if (jazz_esp_read8(esp
, ESP_STATUS
) & ESP_STAT_INTR
)
72 static void jazz_esp_reset_dma(struct esp
*esp
)
74 vdma_disable ((int)esp
->dma_regs
);
77 static void jazz_esp_dma_drain(struct esp
*esp
)
82 static void jazz_esp_dma_invalidate(struct esp
*esp
)
84 vdma_disable ((int)esp
->dma_regs
);
87 static void jazz_esp_send_dma_cmd(struct esp
*esp
, u32 addr
, u32 esp_count
,
88 u32 dma_count
, int write
, u8 cmd
)
90 BUG_ON(!(cmd
& ESP_CMD_DMA
));
92 jazz_esp_write8(esp
, (esp_count
>> 0) & 0xff, ESP_TCLOW
);
93 jazz_esp_write8(esp
, (esp_count
>> 8) & 0xff, ESP_TCMED
);
94 vdma_disable ((int)esp
->dma_regs
);
96 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_READ
);
98 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_WRITE
);
100 vdma_set_addr ((int)esp
->dma_regs
, addr
);
101 vdma_set_count ((int)esp
->dma_regs
, dma_count
);
102 vdma_enable ((int)esp
->dma_regs
);
104 scsi_esp_cmd(esp
, cmd
);
107 static int jazz_esp_dma_error(struct esp
*esp
)
109 u32 enable
= vdma_get_enable((int)esp
->dma_regs
);
111 if (enable
& (R4030_MEM_INTR
|R4030_ADDR_INTR
))
117 static const struct esp_driver_ops jazz_esp_ops
= {
118 .esp_write8
= jazz_esp_write8
,
119 .esp_read8
= jazz_esp_read8
,
120 .map_single
= jazz_esp_map_single
,
121 .map_sg
= jazz_esp_map_sg
,
122 .unmap_single
= jazz_esp_unmap_single
,
123 .unmap_sg
= jazz_esp_unmap_sg
,
124 .irq_pending
= jazz_esp_irq_pending
,
125 .reset_dma
= jazz_esp_reset_dma
,
126 .dma_drain
= jazz_esp_dma_drain
,
127 .dma_invalidate
= jazz_esp_dma_invalidate
,
128 .send_dma_cmd
= jazz_esp_send_dma_cmd
,
129 .dma_error
= jazz_esp_dma_error
,
132 static int __devinit
esp_jazz_probe(struct platform_device
*dev
)
134 struct scsi_host_template
*tpnt
= &scsi_esp_template
;
135 struct Scsi_Host
*host
;
137 struct resource
*res
;
140 host
= scsi_host_alloc(tpnt
, sizeof(struct esp
));
147 esp
= shost_priv(host
);
151 esp
->ops
= &jazz_esp_ops
;
153 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
157 esp
->regs
= (void __iomem
*)res
->start
;
161 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
165 esp
->dma_regs
= (void __iomem
*)res
->start
;
167 esp
->command_block
= dma_alloc_coherent(esp
->dev
, 16,
168 &esp
->command_block_dma
,
170 if (!esp
->command_block
)
171 goto fail_unmap_regs
;
173 host
->irq
= platform_get_irq(dev
, 0);
174 err
= request_irq(host
->irq
, scsi_esp_intr
, IRQF_SHARED
, "ESP", esp
);
176 goto fail_unmap_command_block
;
179 esp
->host
->this_id
= esp
->scsi_id
;
180 esp
->scsi_id_mask
= (1 << esp
->scsi_id
);
181 esp
->cfreq
= 40000000;
183 dev_set_drvdata(&dev
->dev
, esp
);
185 err
= scsi_esp_register(esp
, &dev
->dev
);
192 free_irq(host
->irq
, esp
);
193 fail_unmap_command_block
:
194 dma_free_coherent(esp
->dev
, 16,
196 esp
->command_block_dma
);
204 static int __devexit
esp_jazz_remove(struct platform_device
*dev
)
206 struct esp
*esp
= dev_get_drvdata(&dev
->dev
);
207 unsigned int irq
= esp
->host
->irq
;
209 scsi_esp_unregister(esp
);
212 dma_free_coherent(esp
->dev
, 16,
214 esp
->command_block_dma
);
216 scsi_host_put(esp
->host
);
221 /* work with hotplug and coldplug */
222 MODULE_ALIAS("platform:jazz_esp");
224 static struct platform_driver esp_jazz_driver
= {
225 .probe
= esp_jazz_probe
,
226 .remove
= __devexit_p(esp_jazz_remove
),
229 .owner
= THIS_MODULE
,
233 static int __init
jazz_esp_init(void)
235 return platform_driver_register(&esp_jazz_driver
);
238 static void __exit
jazz_esp_exit(void)
240 platform_driver_unregister(&esp_jazz_driver
);
243 MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
244 MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
245 MODULE_LICENSE("GPL");
246 MODULE_VERSION(DRV_VERSION
);
248 module_init(jazz_esp_init
);
249 module_exit(jazz_esp_exit
);