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>
7 #include <linux/types.h>
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/platform_device.h>
12 #include <linux/dma-mapping.h>
19 #include <asm/jazzdma.h>
21 #include <scsi/scsi_host.h>
25 #define DRV_MODULE_NAME "jazz_esp"
26 #define PFX DRV_MODULE_NAME ": "
27 #define DRV_VERSION "1.000"
28 #define DRV_MODULE_RELDATE "May 19, 2007"
30 static void jazz_esp_write8(struct esp
*esp
, u8 val
, unsigned long reg
)
32 *(volatile u8
*)(esp
->regs
+ reg
) = val
;
35 static u8
jazz_esp_read8(struct esp
*esp
, unsigned long reg
)
37 return *(volatile u8
*)(esp
->regs
+ reg
);
40 static dma_addr_t
jazz_esp_map_single(struct esp
*esp
, void *buf
,
43 return dma_map_single(esp
->dev
, buf
, sz
, dir
);
46 static int jazz_esp_map_sg(struct esp
*esp
, struct scatterlist
*sg
,
49 return dma_map_sg(esp
->dev
, sg
, num_sg
, dir
);
52 static void jazz_esp_unmap_single(struct esp
*esp
, dma_addr_t addr
,
55 dma_unmap_single(esp
->dev
, addr
, sz
, dir
);
58 static void jazz_esp_unmap_sg(struct esp
*esp
, struct scatterlist
*sg
,
61 dma_unmap_sg(esp
->dev
, sg
, num_sg
, dir
);
64 static int jazz_esp_irq_pending(struct esp
*esp
)
66 if (jazz_esp_read8(esp
, ESP_STATUS
) & ESP_STAT_INTR
)
71 static void jazz_esp_reset_dma(struct esp
*esp
)
73 vdma_disable ((int)esp
->dma_regs
);
76 static void jazz_esp_dma_drain(struct esp
*esp
)
81 static void jazz_esp_dma_invalidate(struct esp
*esp
)
83 vdma_disable ((int)esp
->dma_regs
);
86 static void jazz_esp_send_dma_cmd(struct esp
*esp
, u32 addr
, u32 esp_count
,
87 u32 dma_count
, int write
, u8 cmd
)
89 BUG_ON(!(cmd
& ESP_CMD_DMA
));
91 jazz_esp_write8(esp
, (esp_count
>> 0) & 0xff, ESP_TCLOW
);
92 jazz_esp_write8(esp
, (esp_count
>> 8) & 0xff, ESP_TCMED
);
93 vdma_disable ((int)esp
->dma_regs
);
95 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_READ
);
97 vdma_set_mode ((int)esp
->dma_regs
, DMA_MODE_WRITE
);
99 vdma_set_addr ((int)esp
->dma_regs
, addr
);
100 vdma_set_count ((int)esp
->dma_regs
, dma_count
);
101 vdma_enable ((int)esp
->dma_regs
);
103 scsi_esp_cmd(esp
, cmd
);
106 static int jazz_esp_dma_error(struct esp
*esp
)
108 u32 enable
= vdma_get_enable((int)esp
->dma_regs
);
110 if (enable
& (R4030_MEM_INTR
|R4030_ADDR_INTR
))
116 static const struct esp_driver_ops jazz_esp_ops
= {
117 .esp_write8
= jazz_esp_write8
,
118 .esp_read8
= jazz_esp_read8
,
119 .map_single
= jazz_esp_map_single
,
120 .map_sg
= jazz_esp_map_sg
,
121 .unmap_single
= jazz_esp_unmap_single
,
122 .unmap_sg
= jazz_esp_unmap_sg
,
123 .irq_pending
= jazz_esp_irq_pending
,
124 .reset_dma
= jazz_esp_reset_dma
,
125 .dma_drain
= jazz_esp_dma_drain
,
126 .dma_invalidate
= jazz_esp_dma_invalidate
,
127 .send_dma_cmd
= jazz_esp_send_dma_cmd
,
128 .dma_error
= jazz_esp_dma_error
,
131 static int __devinit
esp_jazz_probe(struct platform_device
*dev
)
133 struct scsi_host_template
*tpnt
= &scsi_esp_template
;
134 struct Scsi_Host
*host
;
136 struct resource
*res
;
139 host
= scsi_host_alloc(tpnt
, sizeof(struct esp
));
146 esp
= shost_priv(host
);
150 esp
->ops
= &jazz_esp_ops
;
152 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
156 esp
->regs
= (void __iomem
*)res
->start
;
160 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
164 esp
->dma_regs
= (void __iomem
*)res
->start
;
166 esp
->command_block
= dma_alloc_coherent(esp
->dev
, 16,
167 &esp
->command_block_dma
,
169 if (!esp
->command_block
)
170 goto fail_unmap_regs
;
172 host
->irq
= platform_get_irq(dev
, 0);
173 err
= request_irq(host
->irq
, scsi_esp_intr
, IRQF_SHARED
, "ESP", esp
);
175 goto fail_unmap_command_block
;
178 esp
->host
->this_id
= esp
->scsi_id
;
179 esp
->scsi_id_mask
= (1 << esp
->scsi_id
);
180 esp
->cfreq
= 40000000;
182 dev_set_drvdata(&dev
->dev
, esp
);
184 err
= scsi_esp_register(esp
, &dev
->dev
);
191 free_irq(host
->irq
, esp
);
192 fail_unmap_command_block
:
193 dma_free_coherent(esp
->dev
, 16,
195 esp
->command_block_dma
);
203 static int __devexit
esp_jazz_remove(struct platform_device
*dev
)
205 struct esp
*esp
= dev_get_drvdata(&dev
->dev
);
206 unsigned int irq
= esp
->host
->irq
;
208 scsi_esp_unregister(esp
);
211 dma_free_coherent(esp
->dev
, 16,
213 esp
->command_block_dma
);
215 scsi_host_put(esp
->host
);
220 /* work with hotplug and coldplug */
221 MODULE_ALIAS("platform:jazz_esp");
223 static struct platform_driver esp_jazz_driver
= {
224 .probe
= esp_jazz_probe
,
225 .remove
= __devexit_p(esp_jazz_remove
),
228 .owner
= THIS_MODULE
,
232 static int __init
jazz_esp_init(void)
234 return platform_driver_register(&esp_jazz_driver
);
237 static void __exit
jazz_esp_exit(void)
239 platform_driver_unregister(&esp_jazz_driver
);
242 MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
243 MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
244 MODULE_LICENSE("GPL");
245 MODULE_VERSION(DRV_VERSION
);
247 module_init(jazz_esp_init
);
248 module_exit(jazz_esp_exit
);