1 /* jazz_esp.c: ESP front-end for MIPS JAZZ systems. 2 * 3 * Copyright (C) 2007 Thomas Bogend�rfer (tsbogend@alpha.frankende) 4 */ 5 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> 13 14 #include <asm/irq.h> 15 #include <asm/io.h> 16 #include <asm/dma.h> 17 18 #include <asm/jazz.h> 19 #include <asm/jazzdma.h> 20 21 #include <scsi/scsi_host.h> 22 23 #include "esp_scsi.h" 24 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" 29 30 static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg) 31 { 32 *(volatile u8 *)(esp->regs + reg) = val; 33 } 34 35 static u8 jazz_esp_read8(struct esp *esp, unsigned long reg) 36 { 37 return *(volatile u8 *)(esp->regs + reg); 38 } 39 40 static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf, 41 size_t sz, int dir) 42 { 43 return dma_map_single(esp->dev, buf, sz, dir); 44 } 45 46 static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg, 47 int num_sg, int dir) 48 { 49 return dma_map_sg(esp->dev, sg, num_sg, dir); 50 } 51 52 static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr, 53 size_t sz, int dir) 54 { 55 dma_unmap_single(esp->dev, addr, sz, dir); 56 } 57 58 static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, 59 int num_sg, int dir) 60 { 61 dma_unmap_sg(esp->dev, sg, num_sg, dir); 62 } 63 64 static int jazz_esp_irq_pending(struct esp *esp) 65 { 66 if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) 67 return 1; 68 return 0; 69 } 70 71 static void jazz_esp_reset_dma(struct esp *esp) 72 { 73 vdma_disable ((int)esp->dma_regs); 74 } 75 76 static void jazz_esp_dma_drain(struct esp *esp) 77 { 78 /* nothing to do */ 79 } 80 81 static void jazz_esp_dma_invalidate(struct esp *esp) 82 { 83 vdma_disable ((int)esp->dma_regs); 84 } 85 86 static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, 87 u32 dma_count, int write, u8 cmd) 88 { 89 BUG_ON(!(cmd & ESP_CMD_DMA)); 90 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); 94 if (write) 95 vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ); 96 else 97 vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE); 98 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); 102 103 scsi_esp_cmd(esp, cmd); 104 } 105 106 static int jazz_esp_dma_error(struct esp *esp) 107 { 108 u32 enable = vdma_get_enable((int)esp->dma_regs); 109 110 if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR)) 111 return 1; 112 113 return 0; 114 } 115 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, 129 }; 130 131 static int __devinit esp_jazz_probe(struct platform_device *dev) 132 { 133 struct scsi_host_template *tpnt = &scsi_esp_template; 134 struct Scsi_Host *host; 135 struct esp *esp; 136 struct resource *res; 137 int err; 138 139 host = scsi_host_alloc(tpnt, sizeof(struct esp)); 140 141 err = -ENOMEM; 142 if (!host) 143 goto fail; 144 145 host->max_id = 8; 146 esp = shost_priv(host); 147 148 esp->host = host; 149 esp->dev = dev; 150 esp->ops = &jazz_esp_ops; 151 152 res = platform_get_resource(dev, IORESOURCE_MEM, 0); 153 if (!res) 154 goto fail_unlink; 155 156 esp->regs = (void __iomem *)res->start; 157 if (!esp->regs) 158 goto fail_unlink; 159 160 res = platform_get_resource(dev, IORESOURCE_MEM, 1); 161 if (!res) 162 goto fail_unlink; 163 164 esp->dma_regs = (void __iomem *)res->start; 165 166 esp->command_block = dma_alloc_coherent(esp->dev, 16, 167 &esp->command_block_dma, 168 GFP_KERNEL); 169 if (!esp->command_block) 170 goto fail_unmap_regs; 171 172 host->irq = platform_get_irq(dev, 0); 173 err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); 174 if (err < 0) 175 goto fail_unmap_command_block; 176 177 esp->scsi_id = 7; 178 esp->host->this_id = esp->scsi_id; 179 esp->scsi_id_mask = (1 << esp->scsi_id); 180 esp->cfreq = 40000000; 181 182 dev_set_drvdata(&dev->dev, esp); 183 184 err = scsi_esp_register(esp, &dev->dev); 185 if (err) 186 goto fail_free_irq; 187 188 return 0; 189 190 fail_free_irq: 191 free_irq(host->irq, esp); 192 fail_unmap_command_block: 193 dma_free_coherent(esp->dev, 16, 194 esp->command_block, 195 esp->command_block_dma); 196 fail_unmap_regs: 197 fail_unlink: 198 scsi_host_put(host); 199 fail: 200 return err; 201 } 202 203 static int __devexit esp_jazz_remove(struct platform_device *dev) 204 { 205 struct esp *esp = dev_get_drvdata(&dev->dev); 206 unsigned int irq = esp->host->irq; 207 208 scsi_esp_unregister(esp); 209 210 free_irq(irq, esp); 211 dma_free_coherent(esp->dev, 16, 212 esp->command_block, 213 esp->command_block_dma); 214 215 scsi_host_put(esp->host); 216 217 return 0; 218 } 219 220 static struct platform_driver esp_jazz_driver = { 221 .probe = esp_jazz_probe, 222 .remove = __devexit_p(esp_jazz_remove), 223 .driver = { 224 .name = "jazz_esp", 225 }, 226 }; 227 228 static int __init jazz_esp_init(void) 229 { 230 return platform_driver_register(&esp_jazz_driver); 231 } 232 233 static void __exit jazz_esp_exit(void) 234 { 235 platform_driver_unregister(&esp_jazz_driver); 236 } 237 238 MODULE_DESCRIPTION("JAZZ ESP SCSI driver"); 239 MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)"); 240 MODULE_LICENSE("GPL"); 241 MODULE_VERSION(DRV_VERSION); 242 243 module_init(jazz_esp_init); 244 module_exit(jazz_esp_exit); 245