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 | */ |
