Blame view

drivers/scsi/jazz_esp.c 5.43 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
   *
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
  #include <linux/types.h>
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
7
8
9
10
11
  #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
12
13
  
  #include <asm/irq.h>
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
14
15
  #include <asm/io.h>
  #include <asm/dma.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
  #include <asm/jazz.h>
  #include <asm/jazzdma.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

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

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

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
23
24
25
26
  #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
27

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
28
  static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
30
  	*(volatile u8 *)(esp->regs + reg) = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
32
  static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
34
  	return *(volatile u8 *)(esp->regs + reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
36
37
  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
38
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
39
  	return dma_map_single(esp->dev, buf, sz, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
41
42
  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
43
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
44
  	return dma_map_sg(esp->dev, sg, num_sg, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
46
47
  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
48
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
49
  	dma_unmap_single(esp->dev, addr, sz, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
51
52
  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
53
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
54
  	dma_unmap_sg(esp->dev, sg, num_sg, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
56
  static int jazz_esp_irq_pending(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
58
59
60
  	if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
  		return 1;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
62
  static void jazz_esp_reset_dma(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
64
  	vdma_disable ((int)esp->dma_regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
66
  static void jazz_esp_dma_drain(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
68
  	/* nothing to do */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
70
  static void jazz_esp_dma_invalidate(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
72
  	vdma_disable ((int)esp->dma_regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
74
75
  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
76
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  	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
92
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
93
  static int jazz_esp_dma_error(struct esp *esp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
95
96
97
98
99
100
  	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
101
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  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
118
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
119
120
121
122
123
124
125
126
127
128
129
130
131
  	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...
132
  	esp = shost_priv(host);
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
133
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
  
  	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
187
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
188
  static int __devexit esp_jazz_remove(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
190
191
192
193
194
195
196
197
198
199
200
201
202
  	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
203
  }
ecc1241e8   Kay Sievers   [SCSI] jazz_esp, ...
204
205
  /* work with hotplug and coldplug */
  MODULE_ALIAS("platform:jazz_esp");
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
206
207
208
209
210
  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, ...
211
  		.owner	= THIS_MODULE,
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
212
213
  	},
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
215
  static int __init jazz_esp_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  {
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
217
  	return platform_driver_register(&esp_jazz_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
219
220
221
  static void __exit jazz_esp_exit(void)
  {
  	platform_driver_unregister(&esp_jazz_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  }
352e921f0   Thomas Bogendoerfer   [SCSI] jazz_esp: ...
223
224
225
226
227
228
229
  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);