diff options
Diffstat (limited to 'drivers/usb/misc/emi62.c')
-rw-r--r-- | drivers/usb/misc/emi62.c | 130 |
1 files changed, 73 insertions, 57 deletions
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 1a2b79ac5e10..20886c21e739 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c | |||
@@ -16,15 +16,8 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/usb.h> | 17 | #include <linux/usb.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | 19 | #include <linux/firmware.h> | |
20 | #define MAX_INTEL_HEX_RECORD_LENGTH 16 | 20 | #include <linux/ihex.h> |
21 | typedef struct _INTEL_HEX_RECORD | ||
22 | { | ||
23 | __u32 length; | ||
24 | __u32 address; | ||
25 | __u32 type; | ||
26 | __u8 data[MAX_INTEL_HEX_RECORD_LENGTH]; | ||
27 | } INTEL_HEX_RECORD, *PINTEL_HEX_RECORD; | ||
28 | 21 | ||
29 | /* include firmware (variables)*/ | 22 | /* include firmware (variables)*/ |
30 | 23 | ||
@@ -33,9 +26,9 @@ typedef struct _INTEL_HEX_RECORD | |||
33 | //#undef SPDIF /* if you want MIDI uncomment this line */ | 26 | //#undef SPDIF /* if you want MIDI uncomment this line */ |
34 | 27 | ||
35 | #ifdef SPDIF | 28 | #ifdef SPDIF |
36 | # include "emi62_fw_s.h" /* spdif fw */ | 29 | #define FIRMWARE_FW "emi62/spdif.fw" |
37 | #else | 30 | #else |
38 | # include "emi62_fw_m.h" /* midi fw */ | 31 | #define FIRMWARE_FW "emi62/midi.fw" |
39 | #endif | 32 | #endif |
40 | 33 | ||
41 | #define EMI62_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */ | 34 | #define EMI62_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */ |
@@ -48,7 +41,9 @@ typedef struct _INTEL_HEX_RECORD | |||
48 | #define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ | 41 | #define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ |
49 | #define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS) | 42 | #define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS) |
50 | 43 | ||
51 | static int emi62_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest); | 44 | static int emi62_writememory(struct usb_device *dev, int address, |
45 | const unsigned char *data, int length, | ||
46 | __u8 bRequest); | ||
52 | static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); | 47 | static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); |
53 | static int emi62_load_firmware (struct usb_device *dev); | 48 | static int emi62_load_firmware (struct usb_device *dev); |
54 | static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); | 49 | static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); |
@@ -58,7 +53,9 @@ static void __exit emi62_exit (void); | |||
58 | 53 | ||
59 | 54 | ||
60 | /* thanks to drivers/usb/serial/keyspan_pda.c code */ | 55 | /* thanks to drivers/usb/serial/keyspan_pda.c code */ |
61 | static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) | 56 | static int emi62_writememory(struct usb_device *dev, int address, |
57 | const unsigned char *data, int length, | ||
58 | __u8 request) | ||
62 | { | 59 | { |
63 | int result; | 60 | int result; |
64 | unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); | 61 | unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); |
@@ -91,9 +88,12 @@ static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit) | |||
91 | 88 | ||
92 | static int emi62_load_firmware (struct usb_device *dev) | 89 | static int emi62_load_firmware (struct usb_device *dev) |
93 | { | 90 | { |
91 | const struct firmware *loader_fw = NULL; | ||
92 | const struct firmware *bitstream_fw = NULL; | ||
93 | const struct firmware *firmware_fw = NULL; | ||
94 | const struct ihex_binrec *rec; | ||
94 | int err; | 95 | int err; |
95 | int i; | 96 | int i; |
96 | int pos = 0; /* Position in hex record */ | ||
97 | __u32 addr; /* Address to write */ | 97 | __u32 addr; /* Address to write */ |
98 | __u8 *buf; | 98 | __u8 *buf; |
99 | 99 | ||
@@ -105,6 +105,22 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
105 | goto wraperr; | 105 | goto wraperr; |
106 | } | 106 | } |
107 | 107 | ||
108 | err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev); | ||
109 | if (err) | ||
110 | goto nofw; | ||
111 | |||
112 | err = request_ihex_firmware(&bitstream_fw, "emi62/bitstream.fw", | ||
113 | &dev->dev); | ||
114 | if (err) | ||
115 | goto nofw; | ||
116 | |||
117 | err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev); | ||
118 | if (err) { | ||
119 | nofw: | ||
120 | err( "%s - request_firmware() failed", __func__); | ||
121 | goto wraperr; | ||
122 | } | ||
123 | |||
108 | /* Assert reset (stop the CPU in the EMI) */ | 124 | /* Assert reset (stop the CPU in the EMI) */ |
109 | err = emi62_set_reset(dev,1); | 125 | err = emi62_set_reset(dev,1); |
110 | if (err < 0) { | 126 | if (err < 0) { |
@@ -112,13 +128,18 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
112 | goto wraperr; | 128 | goto wraperr; |
113 | } | 129 | } |
114 | 130 | ||
131 | rec = (const struct ihex_binrec *)loader_fw->data; | ||
132 | |||
115 | /* 1. We need to put the loader for the FPGA into the EZ-USB */ | 133 | /* 1. We need to put the loader for the FPGA into the EZ-USB */ |
116 | for (i=0; g_emi62_loader[i].type == 0; i++) { | 134 | while (rec) { |
117 | err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL); | 135 | err = emi62_writememory(dev, be32_to_cpu(rec->addr), |
136 | rec->data, be16_to_cpu(rec->len), | ||
137 | ANCHOR_LOAD_INTERNAL); | ||
118 | if (err < 0) { | 138 | if (err < 0) { |
119 | err("%s - error loading firmware: error = %d", __func__, err); | 139 | err("%s - error loading firmware: error = %d", __func__, err); |
120 | goto wraperr; | 140 | goto wraperr; |
121 | } | 141 | } |
142 | rec = ihex_next_binrec(rec); | ||
122 | } | 143 | } |
123 | 144 | ||
124 | /* De-assert reset (let the CPU run) */ | 145 | /* De-assert reset (let the CPU run) */ |
@@ -132,15 +153,16 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
132 | /* 2. We upload the FPGA firmware into the EMI | 153 | /* 2. We upload the FPGA firmware into the EMI |
133 | * Note: collect up to 1023 (yes!) bytes and send them with | 154 | * Note: collect up to 1023 (yes!) bytes and send them with |
134 | * a single request. This is _much_ faster! */ | 155 | * a single request. This is _much_ faster! */ |
156 | rec = (const struct ihex_binrec *)bitstream_fw->data; | ||
135 | do { | 157 | do { |
136 | i = 0; | 158 | i = 0; |
137 | addr = g_emi62bs[pos].address; | 159 | addr = be32_to_cpu(rec->addr); |
138 | 160 | ||
139 | /* intel hex records are terminated with type 0 element */ | 161 | /* intel hex records are terminated with type 0 element */ |
140 | while ((g_emi62bs[pos].type == 0) && (i + g_emi62bs[pos].length < FW_LOAD_SIZE)) { | 162 | while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) { |
141 | memcpy(buf + i, g_emi62bs[pos].data, g_emi62bs[pos].length); | 163 | memcpy(buf + i, rec->data, be16_to_cpu(rec->len)); |
142 | i += g_emi62bs[pos].length; | 164 | i += be16_to_cpu(rec->len); |
143 | pos++; | 165 | rec = ihex_next_binrec(rec); |
144 | } | 166 | } |
145 | err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); | 167 | err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); |
146 | if (err < 0) { | 168 | if (err < 0) { |
@@ -157,8 +179,11 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
157 | } | 179 | } |
158 | 180 | ||
159 | /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ | 181 | /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ |
160 | for (i=0; g_emi62_loader[i].type == 0; i++) { | 182 | for (rec = (const struct ihex_binrec *)loader_fw->data; |
161 | err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL); | 183 | rec; rec = ihex_next_binrec(rec)) { |
184 | err = emi62_writememory(dev, be32_to_cpu(rec->addr), | ||
185 | rec->data, be16_to_cpu(rec->len), | ||
186 | ANCHOR_LOAD_INTERNAL); | ||
162 | if (err < 0) { | 187 | if (err < 0) { |
163 | err("%s - error loading firmware: error = %d", __func__, err); | 188 | err("%s - error loading firmware: error = %d", __func__, err); |
164 | goto wraperr; | 189 | goto wraperr; |
@@ -175,29 +200,19 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
175 | 200 | ||
176 | /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ | 201 | /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ |
177 | 202 | ||
178 | /* FIXME: quick and dirty ifdefs */ | 203 | for (rec = (const struct ihex_binrec *)firmware_fw->data; |
179 | #ifdef SPDIF | 204 | rec; rec = ihex_next_binrec(rec)) { |
180 | for (i=0; g_HexSpdifFw62[i].type == 0; i++) { | 205 | if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) { |
181 | if (!INTERNAL_RAM(g_HexSpdifFw62[i].address)) { | 206 | err = emi62_writememory(dev, be32_to_cpu(rec->addr), |
182 | err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_EXTERNAL); | 207 | rec->data, be16_to_cpu(rec->len), |
208 | ANCHOR_LOAD_EXTERNAL); | ||
183 | if (err < 0) { | 209 | if (err < 0) { |
184 | err("%s - error loading firmware: error = %d", __func__, err); | 210 | err("%s - error loading firmware: error = %d", __func__, err); |
185 | goto wraperr; | 211 | goto wraperr; |
186 | } | 212 | } |
187 | } | 213 | } |
188 | } | 214 | } |
189 | #else /* MIDI */ | 215 | |
190 | for (i=0; g_HexMidiFw62[i].type == 0; i++) { | ||
191 | if (!INTERNAL_RAM(g_HexMidiFw62[i].address)) { | ||
192 | err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_EXTERNAL); | ||
193 | if (err < 0) { | ||
194 | err("%s - error loading firmware: error = %d\n", __func__, err); | ||
195 | goto wraperr; | ||
196 | return err; | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | #endif | ||
201 | /* Assert reset (stop the CPU in the EMI) */ | 216 | /* Assert reset (stop the CPU in the EMI) */ |
202 | err = emi62_set_reset(dev,1); | 217 | err = emi62_set_reset(dev,1); |
203 | if (err < 0) { | 218 | if (err < 0) { |
@@ -205,29 +220,19 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
205 | goto wraperr; | 220 | goto wraperr; |
206 | } | 221 | } |
207 | 222 | ||
208 | /* FIXME: quick and dirty ifdefs */ | 223 | for (rec = (const struct ihex_binrec *)firmware_fw->data; |
209 | #ifdef SPDIF | 224 | rec; rec = ihex_next_binrec(rec)) { |
210 | for (i=0; g_HexSpdifFw62[i].type == 0; i++) { | 225 | if (INTERNAL_RAM(be32_to_cpu(rec->addr))) { |
211 | if (INTERNAL_RAM(g_HexSpdifFw62[i].address)) { | 226 | err = emi62_writememory(dev, be32_to_cpu(rec->addr), |
212 | err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_INTERNAL); | 227 | rec->data, be16_to_cpu(rec->len), |
228 | ANCHOR_LOAD_EXTERNAL); | ||
213 | if (err < 0) { | 229 | if (err < 0) { |
214 | err("%s - error loading firmware: error = %d", __func__, err); | 230 | err("%s - error loading firmware: error = %d", __func__, err); |
215 | goto wraperr; | 231 | goto wraperr; |
216 | } | 232 | } |
217 | } | 233 | } |
218 | } | 234 | } |
219 | #else /* MIDI */ | 235 | |
220 | for (i=0; g_HexMidiFw62[i].type == 0; i++) { | ||
221 | if (INTERNAL_RAM(g_HexMidiFw62[i].address)) { | ||
222 | err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_INTERNAL); | ||
223 | if (err < 0) { | ||
224 | err("%s - error loading firmware: error = %d\n", __func__, err); | ||
225 | goto wraperr; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | #endif | ||
230 | |||
231 | /* De-assert reset (let the CPU run) */ | 236 | /* De-assert reset (let the CPU run) */ |
232 | err = emi62_set_reset(dev,0); | 237 | err = emi62_set_reset(dev,0); |
233 | if (err < 0) { | 238 | if (err < 0) { |
@@ -236,6 +241,10 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
236 | } | 241 | } |
237 | msleep(250); /* let device settle */ | 242 | msleep(250); /* let device settle */ |
238 | 243 | ||
244 | release_firmware(loader_fw); | ||
245 | release_firmware(bitstream_fw); | ||
246 | release_firmware(firmware_fw); | ||
247 | |||
239 | kfree(buf); | 248 | kfree(buf); |
240 | 249 | ||
241 | /* return 1 to fail the driver inialization | 250 | /* return 1 to fail the driver inialization |
@@ -243,6 +252,10 @@ static int emi62_load_firmware (struct usb_device *dev) | |||
243 | return 1; | 252 | return 1; |
244 | 253 | ||
245 | wraperr: | 254 | wraperr: |
255 | release_firmware(loader_fw); | ||
256 | release_firmware(bitstream_fw); | ||
257 | release_firmware(firmware_fw); | ||
258 | |||
246 | kfree(buf); | 259 | kfree(buf); |
247 | dev_err(&dev->dev, "Error\n"); | 260 | dev_err(&dev->dev, "Error\n"); |
248 | return err; | 261 | return err; |
@@ -300,5 +313,8 @@ MODULE_AUTHOR("Tapio Laxström"); | |||
300 | MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader."); | 313 | MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader."); |
301 | MODULE_LICENSE("GPL"); | 314 | MODULE_LICENSE("GPL"); |
302 | 315 | ||
316 | MODULE_FIRMWARE("emi62/loader.fw"); | ||
317 | MODULE_FIRMWARE("emi62/bitstream.fw"); | ||
318 | MODULE_FIRMWARE(FIRMWARE_FW); | ||
303 | /* vi:ai:syntax=c:sw=8:ts=8:tw=80 | 319 | /* vi:ai:syntax=c:sw=8:ts=8:tw=80 |
304 | */ | 320 | */ |