Blame view

drivers/scsi/jazz_esp.c 5.45 KB
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
1
  /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *
d36b69107   Al Viro   misc latin1 to ut...
3
   * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
6
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
  #include <linux/types.h>
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
8
9
10
11
12
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/platform_device.h>
  #include <linux/dma-mapping.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
  
  #include <asm/irq.h>
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
15
16
  #include <asm/io.h>
  #include <asm/dma.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
  #include <asm/jazz.h>
  #include <asm/jazzdma.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
20
  #include <scsi/scsi_host.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
22
  #include "esp_scsi.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
24
25
26
27
  #define DRV_MODULE_NAME		"jazz_esp"
  #define PFX DRV_MODULE_NAME	": "
  #define DRV_VERSION		"1.000"
  #define DRV_MODULE_RELDATE	"May 19, 2007"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
29
  static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
31
  	*(volatile u8 *)(esp->regs + reg) = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
33
  static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
35
  	return *(volatile u8 *)(esp->regs + reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
37
38
  static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf,
  				      size_t sz, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
40
  	return dma_map_single(esp->dev, buf, sz, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
42
43
  static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg,
  				  int num_sg, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
45
  	return dma_map_sg(esp->dev, sg, num_sg, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
47
48
  static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr,
  				  size_t sz, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
50
  	dma_unmap_single(esp->dev, addr, sz, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
52
53
  static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
  			      int num_sg, int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
55
  	dma_unmap_sg(esp->dev, sg, num_sg, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
57
  static int jazz_esp_irq_pending(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
59
60
61
  	if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
  		return 1;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
63
  static void jazz_esp_reset_dma(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
65
  	vdma_disable ((int)esp->dma_regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
67
  static void jazz_esp_dma_drain(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
69
  	/* nothing to do */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
71
  static void jazz_esp_dma_invalidate(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
73
  	vdma_disable ((int)esp->dma_regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
75
76
  static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
  				  u32 dma_count, int write, u8 cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  	BUG_ON(!(cmd & ESP_CMD_DMA));
  
  	jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
  	jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
  	vdma_disable ((int)esp->dma_regs);
  	if (write)
  		vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);
  	else
  		vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);
  
  	vdma_set_addr ((int)esp->dma_regs, addr);
  	vdma_set_count ((int)esp->dma_regs, dma_count);
  	vdma_enable ((int)esp->dma_regs);
  
  	scsi_esp_cmd(esp, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
94
  static int jazz_esp_dma_error(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
96
97
98
99
100
101
  	u32 enable = vdma_get_enable((int)esp->dma_regs);
  
  	if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))
  		return 1;
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  static const struct esp_driver_ops jazz_esp_ops = {
  	.esp_write8	=	jazz_esp_write8,
  	.esp_read8	=	jazz_esp_read8,
  	.map_single	=	jazz_esp_map_single,
  	.map_sg		=	jazz_esp_map_sg,
  	.unmap_single	=	jazz_esp_unmap_single,
  	.unmap_sg	=	jazz_esp_unmap_sg,
  	.irq_pending	=	jazz_esp_irq_pending,
  	.reset_dma	=	jazz_esp_reset_dma,
  	.dma_drain	=	jazz_esp_dma_drain,
  	.dma_invalidate	=	jazz_esp_dma_invalidate,
  	.send_dma_cmd	=	jazz_esp_send_dma_cmd,
  	.dma_error	=	jazz_esp_dma_error,
  };
  
  static int __devinit esp_jazz_probe(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
120
121
122
123
124
125
126
127
128
129
130
131
132
  	struct scsi_host_template *tpnt = &scsi_esp_template;
  	struct Scsi_Host *host;
  	struct esp *esp;
  	struct resource *res;
  	int err;
  
  	host = scsi_host_alloc(tpnt, sizeof(struct esp));
  
  	err = -ENOMEM;
  	if (!host)
  		goto fail;
  
  	host->max_id = 8;
2b14ec787   Christoph Hellwig   [SCSI] esp: use s...
133
  	esp = shost_priv(host);
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  
  	esp->host = host;
  	esp->dev = dev;
  	esp->ops = &jazz_esp_ops;
  
  	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
  	if (!res)
  		goto fail_unlink;
  
  	esp->regs = (void __iomem *)res->start;
  	if (!esp->regs)
  		goto fail_unlink;
  
  	res = platform_get_resource(dev, IORESOURCE_MEM, 1);
  	if (!res)
  		goto fail_unlink;
  
  	esp->dma_regs = (void __iomem *)res->start;
  
  	esp->command_block = dma_alloc_coherent(esp->dev, 16,
  						&esp->command_block_dma,
  						GFP_KERNEL);
  	if (!esp->command_block)
  		goto fail_unmap_regs;
  
  	host->irq = platform_get_irq(dev, 0);
  	err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
  	if (err < 0)
  		goto fail_unmap_command_block;
  
  	esp->scsi_id = 7;
  	esp->host->this_id = esp->scsi_id;
  	esp->scsi_id_mask = (1 << esp->scsi_id);
  	esp->cfreq = 40000000;
  
  	dev_set_drvdata(&dev->dev, esp);
  
  	err = scsi_esp_register(esp, &dev->dev);
  	if (err)
  		goto fail_free_irq;
  
  	return 0;
  
  fail_free_irq:
  	free_irq(host->irq, esp);
  fail_unmap_command_block:
  	dma_free_coherent(esp->dev, 16,
  			  esp->command_block,
  			  esp->command_block_dma);
  fail_unmap_regs:
  fail_unlink:
  	scsi_host_put(host);
  fail:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
189
  static int __devexit esp_jazz_remove(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
191
192
193
194
195
196
197
198
199
200
201
202
203
  	struct esp *esp = dev_get_drvdata(&dev->dev);
  	unsigned int irq = esp->host->irq;
  
  	scsi_esp_unregister(esp);
  
  	free_irq(irq, esp);
  	dma_free_coherent(esp->dev, 16,
  			  esp->command_block,
  			  esp->command_block_dma);
  
  	scsi_host_put(esp->host);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  }
ecc1241e8   Kay Sievers   [SCSI] jazz_esp, ...
205
206
  /* work with hotplug and coldplug */
  MODULE_ALIAS("platform:jazz_esp");
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
207
208
209
210
211
  static struct platform_driver esp_jazz_driver = {
  	.probe		= esp_jazz_probe,
  	.remove		= __devexit_p(esp_jazz_remove),
  	.driver	= {
  		.name	= "jazz_esp",
ecc1241e8   Kay Sievers   [SCSI] jazz_esp, ...
212
  		.owner	= THIS_MODULE,
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
213
214
  	},
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
216
  static int __init jazz_esp_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
218
  	return platform_driver_register(&esp_jazz_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
220
221
222
  static void __exit jazz_esp_exit(void)
  {
  	platform_driver_unregister(&esp_jazz_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
224
225
226
227
228
229
230
  MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
  MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);
  
  module_init(jazz_esp_init);
  module_exit(jazz_esp_exit);