diff options
Diffstat (limited to 'drivers/usb/misc/emi26.c')
-rw-r--r-- | drivers/usb/misc/emi26.c | 96 |
1 files changed, 66 insertions, 30 deletions
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 4b9dc81b8453..4b994a0cd272 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c | |||
@@ -16,18 +16,8 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.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 | |||
29 | /* include firmware (variables) */ | ||
30 | #include "emi26_fw.h" | ||
31 | 21 | ||
32 | #define EMI26_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */ | 22 | #define EMI26_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */ |
33 | #define EMI26_PRODUCT_ID 0x0100 /* EMI 2|6 without firmware */ | 23 | #define EMI26_PRODUCT_ID 0x0100 /* EMI 2|6 without firmware */ |
@@ -40,7 +30,9 @@ typedef struct _INTEL_HEX_RECORD | |||
40 | #define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ | 30 | #define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ |
41 | #define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS) | 31 | #define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS) |
42 | 32 | ||
43 | static int emi26_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest); | 33 | static int emi26_writememory( struct usb_device *dev, int address, |
34 | const unsigned char *data, int length, | ||
35 | __u8 bRequest); | ||
44 | static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit); | 36 | static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit); |
45 | static int emi26_load_firmware (struct usb_device *dev); | 37 | static int emi26_load_firmware (struct usb_device *dev); |
46 | static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id); | 38 | static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id); |
@@ -50,7 +42,9 @@ static void __exit emi26_exit (void); | |||
50 | 42 | ||
51 | 43 | ||
52 | /* thanks to drivers/usb/serial/keyspan_pda.c code */ | 44 | /* thanks to drivers/usb/serial/keyspan_pda.c code */ |
53 | static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) | 45 | static int emi26_writememory (struct usb_device *dev, int address, |
46 | const unsigned char *data, int length, | ||
47 | __u8 request) | ||
54 | { | 48 | { |
55 | int result; | 49 | int result; |
56 | unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); | 50 | unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); |
@@ -83,9 +77,12 @@ static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit) | |||
83 | 77 | ||
84 | static int emi26_load_firmware (struct usb_device *dev) | 78 | static int emi26_load_firmware (struct usb_device *dev) |
85 | { | 79 | { |
80 | const struct firmware *loader_fw = NULL; | ||
81 | const struct firmware *bitstream_fw = NULL; | ||
82 | const struct firmware *firmware_fw = NULL; | ||
83 | const struct ihex_binrec *rec; | ||
86 | int err; | 84 | int err; |
87 | int i; | 85 | int i; |
88 | int pos = 0; /* Position in hex record */ | ||
89 | __u32 addr; /* Address to write */ | 86 | __u32 addr; /* Address to write */ |
90 | __u8 *buf; | 87 | __u8 *buf; |
91 | 88 | ||
@@ -96,6 +93,23 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
96 | goto wraperr; | 93 | goto wraperr; |
97 | } | 94 | } |
98 | 95 | ||
96 | err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); | ||
97 | if (err) | ||
98 | goto nofw; | ||
99 | |||
100 | err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw", | ||
101 | &dev->dev); | ||
102 | if (err) | ||
103 | goto nofw; | ||
104 | |||
105 | err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw", | ||
106 | &dev->dev); | ||
107 | if (err) { | ||
108 | nofw: | ||
109 | err( "%s - request_firmware() failed", __func__); | ||
110 | goto wraperr; | ||
111 | } | ||
112 | |||
99 | /* Assert reset (stop the CPU in the EMI) */ | 113 | /* Assert reset (stop the CPU in the EMI) */ |
100 | err = emi26_set_reset(dev,1); | 114 | err = emi26_set_reset(dev,1); |
101 | if (err < 0) { | 115 | if (err < 0) { |
@@ -103,13 +117,17 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
103 | goto wraperr; | 117 | goto wraperr; |
104 | } | 118 | } |
105 | 119 | ||
120 | rec = (const struct ihex_binrec *)loader_fw->data; | ||
106 | /* 1. We need to put the loader for the FPGA into the EZ-USB */ | 121 | /* 1. We need to put the loader for the FPGA into the EZ-USB */ |
107 | for (i=0; g_Loader[i].type == 0; i++) { | 122 | while (rec) { |
108 | err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL); | 123 | err = emi26_writememory(dev, be32_to_cpu(rec->addr), |
124 | rec->data, be16_to_cpu(rec->len), | ||
125 | ANCHOR_LOAD_INTERNAL); | ||
109 | if (err < 0) { | 126 | if (err < 0) { |
110 | err("%s - error loading firmware: error = %d", __func__, err); | 127 | err("%s - error loading firmware: error = %d", __func__, err); |
111 | goto wraperr; | 128 | goto wraperr; |
112 | } | 129 | } |
130 | rec = ihex_next_binrec(rec); | ||
113 | } | 131 | } |
114 | 132 | ||
115 | /* De-assert reset (let the CPU run) */ | 133 | /* De-assert reset (let the CPU run) */ |
@@ -123,15 +141,16 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
123 | /* 2. We upload the FPGA firmware into the EMI | 141 | /* 2. We upload the FPGA firmware into the EMI |
124 | * Note: collect up to 1023 (yes!) bytes and send them with | 142 | * Note: collect up to 1023 (yes!) bytes and send them with |
125 | * a single request. This is _much_ faster! */ | 143 | * a single request. This is _much_ faster! */ |
144 | rec = (const struct ihex_binrec *)bitstream_fw->data; | ||
126 | do { | 145 | do { |
127 | i = 0; | 146 | i = 0; |
128 | addr = g_bitstream[pos].address; | 147 | addr = be32_to_cpu(rec->addr); |
129 | 148 | ||
130 | /* intel hex records are terminated with type 0 element */ | 149 | /* intel hex records are terminated with type 0 element */ |
131 | while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < FW_LOAD_SIZE)) { | 150 | while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) { |
132 | memcpy(buf + i, g_bitstream[pos].data, g_bitstream[pos].length); | 151 | memcpy(buf + i, rec->data, be16_to_cpu(rec->len)); |
133 | i += g_bitstream[pos].length; | 152 | i += be16_to_cpu(rec->len); |
134 | pos++; | 153 | rec = ihex_next_binrec(rec); |
135 | } | 154 | } |
136 | err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); | 155 | err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); |
137 | if (err < 0) { | 156 | if (err < 0) { |
@@ -148,8 +167,11 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
148 | } | 167 | } |
149 | 168 | ||
150 | /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ | 169 | /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ |
151 | for (i=0; g_Loader[i].type == 0; i++) { | 170 | for (rec = (const struct ihex_binrec *)loader_fw->data; |
152 | err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL); | 171 | rec; rec = ihex_next_binrec(rec)) { |
172 | err = emi26_writememory(dev, be32_to_cpu(rec->addr), | ||
173 | rec->data, be16_to_cpu(rec->len), | ||
174 | ANCHOR_LOAD_INTERNAL); | ||
153 | if (err < 0) { | 175 | if (err < 0) { |
154 | err("%s - error loading firmware: error = %d", __func__, err); | 176 | err("%s - error loading firmware: error = %d", __func__, err); |
155 | goto wraperr; | 177 | goto wraperr; |
@@ -165,9 +187,13 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
165 | } | 187 | } |
166 | 188 | ||
167 | /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ | 189 | /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ |
168 | for (i=0; g_Firmware[i].type == 0; i++) { | 190 | |
169 | if (!INTERNAL_RAM(g_Firmware[i].address)) { | 191 | for (rec = (const struct ihex_binrec *)firmware_fw->data; |
170 | err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL); | 192 | rec; rec = ihex_next_binrec(rec)) { |
193 | if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) { | ||
194 | err = emi26_writememory(dev, be32_to_cpu(rec->addr), | ||
195 | rec->data, be16_to_cpu(rec->len), | ||
196 | ANCHOR_LOAD_EXTERNAL); | ||
171 | if (err < 0) { | 197 | if (err < 0) { |
172 | err("%s - error loading firmware: error = %d", __func__, err); | 198 | err("%s - error loading firmware: error = %d", __func__, err); |
173 | goto wraperr; | 199 | goto wraperr; |
@@ -182,9 +208,12 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
182 | goto wraperr; | 208 | goto wraperr; |
183 | } | 209 | } |
184 | 210 | ||
185 | for (i=0; g_Firmware[i].type == 0; i++) { | 211 | for (rec = (const struct ihex_binrec *)firmware_fw->data; |
186 | if (INTERNAL_RAM(g_Firmware[i].address)) { | 212 | rec; rec = ihex_next_binrec(rec)) { |
187 | err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL); | 213 | if (INTERNAL_RAM(be32_to_cpu(rec->addr))) { |
214 | err = emi26_writememory(dev, be32_to_cpu(rec->addr), | ||
215 | rec->data, be16_to_cpu(rec->len), | ||
216 | ANCHOR_LOAD_INTERNAL); | ||
188 | if (err < 0) { | 217 | if (err < 0) { |
189 | err("%s - error loading firmware: error = %d", __func__, err); | 218 | err("%s - error loading firmware: error = %d", __func__, err); |
190 | goto wraperr; | 219 | goto wraperr; |
@@ -205,6 +234,10 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
205 | err = 1; | 234 | err = 1; |
206 | 235 | ||
207 | wraperr: | 236 | wraperr: |
237 | release_firmware(loader_fw); | ||
238 | release_firmware(bitstream_fw); | ||
239 | release_firmware(firmware_fw); | ||
240 | |||
208 | kfree(buf); | 241 | kfree(buf); |
209 | return err; | 242 | return err; |
210 | } | 243 | } |
@@ -257,5 +290,8 @@ MODULE_AUTHOR("Tapio Laxström"); | |||
257 | MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader."); | 290 | MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader."); |
258 | MODULE_LICENSE("GPL"); | 291 | MODULE_LICENSE("GPL"); |
259 | 292 | ||
293 | MODULE_FIRMWARE("emi26/loader.fw"); | ||
294 | MODULE_FIRMWARE("emi26/bitstream.fw"); | ||
295 | MODULE_FIRMWARE("emi26/firmware.fw"); | ||
260 | /* vi:ai:syntax=c:sw=8:ts=8:tw=80 | 296 | /* vi:ai:syntax=c:sw=8:ts=8:tw=80 |
261 | */ | 297 | */ |