11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Emagic EMI 2|6 usb audio interface firmware loader. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 496de0e252cedffad61b3cb5e05662c591898e69aJan Engelhardt * Tapio Laxström (tapio.laxstrom@iptime.fi) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License, as published by 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation, version 2. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 1516c23f7d88cbcce491f9370b2846fad66e8ef319Monty#include <linux/delay.h> 16b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse#include <linux/firmware.h> 17b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse#include <linux/ihex.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* include firmware (variables)*/ 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FIXME: This is quick and dirty solution! */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SPDIF /* if you want SPDIF comment next line */ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//#undef SPDIF /* if you want MIDI uncomment this line */ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SPDIF 26b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse#define FIRMWARE_FW "emi62/spdif.fw" 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 28b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse#define FIRMWARE_FW "emi62/midi.fw" 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EMI62_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EMI62_PRODUCT_ID 0x0110 /* EMI 6|2m without firmware */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ANCHOR_LOAD_INTERNAL 0xA0 /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ANCHOR_LOAD_EXTERNAL 0xA3 /* This command is not implemented in the core. Requires firmware */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ANCHOR_LOAD_FPGA 0xA5 /* This command is not implemented in the core. Requires firmware. Emagic extension */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_INTERNAL_ADDRESS 0x1B3F /* This is the highest internal RAM address for the AN2131Q */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CPUCS_REG 0x7F92 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INTERNAL_RAM(address) (address <= MAX_INTERNAL_ADDRESS) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhousestatic int emi62_writememory(struct usb_device *dev, int address, 42b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse const unsigned char *data, int length, 43b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse __u8 bRequest); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emi62_load_firmware (struct usb_device *dev); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void emi62_disconnect(struct usb_interface *intf); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* thanks to drivers/usb/serial/keyspan_pda.c code */ 50b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhousestatic int emi62_writememory(struct usb_device *dev, int address, 51b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse const unsigned char *data, int length, 52b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse __u8 request) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 555d7efe5b3768bf53df9b87380ea68baacf11f933Eric Sesterhenn unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!buffer) { 58e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman dev_err(&dev->dev, "kmalloc(%d) failed.\n", length); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: usb_control_msg returns negative value on error or length of the 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data that was written! */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (buffer); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* thanks to drivers/usb/serial/keyspan_pda.c code */ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int response; 721b29a375fb0b79a11a2d18e7bf5f6da422a35025Greg Kroah-Hartman dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0); 75e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (response < 0) 76e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return response; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FW_LOAD_SIZE 1023 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emi62_load_firmware (struct usb_device *dev) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 84b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse const struct firmware *loader_fw = NULL; 85b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse const struct firmware *bitstream_fw = NULL; 86b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse const struct firmware *firmware_fw = NULL; 87b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse const struct ihex_binrec *rec; 88e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman int err = -ENOMEM; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u32 addr; /* Address to write */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 *buf; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&dev->dev, "load_firmware\n"); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); 95e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (!buf) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 98b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev); 99b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse if (err) 100b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse goto nofw; 101b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 102b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = request_ihex_firmware(&bitstream_fw, "emi62/bitstream.fw", 103b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse &dev->dev); 104b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse if (err) 105b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse goto nofw; 106b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 107b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev); 108b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse if (err) { 109b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse nofw: 110b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse goto wraperr; 111b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse } 112b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Assert reset (stop the CPU in the EMI) */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_set_reset(dev,1); 115e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 118b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec = (const struct ihex_binrec *)loader_fw->data; 119b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1. We need to put the loader for the FPGA into the EZ-USB */ 121b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse while (rec) { 122b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = emi62_writememory(dev, be32_to_cpu(rec->addr), 123b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec->data, be16_to_cpu(rec->len), 124b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse ANCHOR_LOAD_INTERNAL); 125e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 127b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec = ihex_next_binrec(rec); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* De-assert reset (let the CPU run) */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_set_reset(dev,0); 132e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1335919a43bbc649f4770b8b5db33f43136c7ff3153Oliver Neukum goto wraperr; 13416c23f7d88cbcce491f9370b2846fad66e8ef319Monty msleep(250); /* let device settle */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2. We upload the FPGA firmware into the EMI 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: collect up to 1023 (yes!) bytes and send them with 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a single request. This is _much_ faster! */ 139b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec = (const struct ihex_binrec *)bitstream_fw->data; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 142b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse addr = be32_to_cpu(rec->addr); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* intel hex records are terminated with type 0 element */ 145b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) { 146b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse memcpy(buf + i, rec->data, be16_to_cpu(rec->len)); 147b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse i += be16_to_cpu(rec->len); 148b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec = ihex_next_binrec(rec); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); 151e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 153ac06c06770bb8761b1f1f9bdf2f5420fa6d3e9faClemens Ladisch } while (rec); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Assert reset (stop the CPU in the EMI) */ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_set_reset(dev,1); 157e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ 161b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse for (rec = (const struct ihex_binrec *)loader_fw->data; 162b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec; rec = ihex_next_binrec(rec)) { 163b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = emi62_writememory(dev, be32_to_cpu(rec->addr), 164b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec->data, be16_to_cpu(rec->len), 165b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse ANCHOR_LOAD_INTERNAL); 166e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* De-assert reset (let the CPU run) */ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_set_reset(dev,0); 172e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 17416c23f7d88cbcce491f9370b2846fad66e8ef319Monty msleep(250); /* let device settle */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 178b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse for (rec = (const struct ihex_binrec *)firmware_fw->data; 179b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec; rec = ihex_next_binrec(rec)) { 180b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) { 181b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = emi62_writememory(dev, be32_to_cpu(rec->addr), 182b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec->data, be16_to_cpu(rec->len), 183b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse ANCHOR_LOAD_EXTERNAL); 184e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 188b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Assert reset (stop the CPU in the EMI) */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_set_reset(dev,1); 191e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 194b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse for (rec = (const struct ihex_binrec *)firmware_fw->data; 195b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec; rec = ihex_next_binrec(rec)) { 196b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse if (INTERNAL_RAM(be32_to_cpu(rec->addr))) { 197b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse err = emi62_writememory(dev, be32_to_cpu(rec->addr), 198b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse rec->data, be16_to_cpu(rec->len), 199b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse ANCHOR_LOAD_EXTERNAL); 200e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 204b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* De-assert reset (let the CPU run) */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = emi62_set_reset(dev,0); 207e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wraperr; 20916c23f7d88cbcce491f9370b2846fad66e8ef319Monty msleep(250); /* let device settle */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse release_firmware(loader_fw); 212b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse release_firmware(bitstream_fw); 213b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse release_firmware(firmware_fw); 214b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(buf); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* return 1 to fail the driver inialization 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and give real driver change to load */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswraperr: 222e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman if (err < 0) 223e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", 224e9a527dae346c0ad56410c3794ba5ec535c66bccGreg Kroah-Hartman __func__, err); 225b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse release_firmware(loader_fw); 226b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse release_firmware(bitstream_fw); 227b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse release_firmware(firmware_fw); 228b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David Woodhouse 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(buf); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&dev->dev, "Error\n"); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23483957df21dd94655d2b026e0944a69ff37b83988Greg Kroah-Hartmanstatic const struct usb_device_id id_table[] = { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* Terminating entry */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE (usb, id_table); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_device *dev = interface_to_usbdev(intf); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&intf->dev, "emi62_probe\n"); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461b29a375fb0b79a11a2d18e7bf5f6da422a35025Greg Kroah-Hartman dev_info(&intf->dev, "%s start\n", __func__); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds emi62_load_firmware(dev); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do not return the driver context, let real audio driver do that */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void emi62_disconnect(struct usb_interface *intf) 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_driver emi62_driver = { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "emi62 - firmware loader", 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = emi62_probe, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .disconnect = emi62_disconnect, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = id_table, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26565db43054065790a75291b0834657445fea2cf56Greg Kroah-Hartmanmodule_usb_driver(emi62_driver); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26796de0e252cedffad61b3cb5e05662c591898e69aJan EngelhardtMODULE_AUTHOR("Tapio Laxström"); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader."); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David WoodhouseMODULE_FIRMWARE("emi62/loader.fw"); 272b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David WoodhouseMODULE_FIRMWARE("emi62/bitstream.fw"); 273b8e24bfabb03527d1c876fcaf24cccb05e1cbc65David WoodhouseMODULE_FIRMWARE(FIRMWARE_FW); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* vi:ai:syntax=c:sw=8:ts=8:tw=80 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 276