root/drivers/usb/misc/emi62.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. emi62_writememory
  2. emi62_set_reset
  3. emi62_load_firmware
  4. emi62_probe
  5. emi62_disconnect

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* 
   3  * Emagic EMI 2|6 usb audio interface firmware loader.
   4  * Copyright (C) 2002
   5  *      Tapio Laxström (tapio.laxstrom@iptime.fi)
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/errno.h>
   9 #include <linux/slab.h>
  10 #include <linux/module.h>
  11 #include <linux/usb.h>
  12 #include <linux/delay.h>
  13 #include <linux/firmware.h>
  14 #include <linux/ihex.h>
  15 
  16 /* include firmware (variables)*/
  17 
  18 /* FIXME: This is quick and dirty solution! */
  19 #define SPDIF   /* if you want SPDIF comment next line */
  20 //#undef SPDIF  /* if you want MIDI uncomment this line */ 
  21 
  22 #ifdef SPDIF
  23 #define FIRMWARE_FW "emi62/spdif.fw"
  24 #else
  25 #define FIRMWARE_FW "emi62/midi.fw"
  26 #endif
  27 
  28 #define EMI62_VENDOR_ID                 0x086a  /* Emagic Soft-und Hardware GmBH */
  29 #define EMI62_PRODUCT_ID                0x0110  /* EMI 6|2m without firmware */
  30 
  31 #define ANCHOR_LOAD_INTERNAL    0xA0    /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
  32 #define ANCHOR_LOAD_EXTERNAL    0xA3    /* This command is not implemented in the core. Requires firmware */
  33 #define ANCHOR_LOAD_FPGA        0xA5    /* This command is not implemented in the core. Requires firmware. Emagic extension */
  34 #define MAX_INTERNAL_ADDRESS    0x1B3F  /* This is the highest internal RAM address for the AN2131Q */
  35 #define CPUCS_REG               0x7F92  /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */ 
  36 #define INTERNAL_RAM(address)   (address <= MAX_INTERNAL_ADDRESS)
  37 
  38 static int emi62_writememory(struct usb_device *dev, int address,
  39                              const unsigned char *data, int length,
  40                              __u8 bRequest);
  41 static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
  42 static int emi62_load_firmware (struct usb_device *dev);
  43 static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
  44 static void emi62_disconnect(struct usb_interface *intf);
  45 
  46 /* thanks to drivers/usb/serial/keyspan_pda.c code */
  47 static int emi62_writememory(struct usb_device *dev, int address,
  48                              const unsigned char *data, int length,
  49                              __u8 request)
  50 {
  51         int result;
  52         unsigned char *buffer =  kmemdup(data, length, GFP_KERNEL);
  53 
  54         if (!buffer) {
  55                 dev_err(&dev->dev, "kmalloc(%d) failed.\n", length);
  56                 return -ENOMEM;
  57         }
  58         /* Note: usb_control_msg returns negative value on error or length of the
  59          *               data that was written! */
  60         result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
  61         kfree (buffer);
  62         return result;
  63 }
  64 
  65 /* thanks to drivers/usb/serial/keyspan_pda.c code */
  66 static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
  67 {
  68         int response;
  69         dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit);
  70         
  71         response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
  72         if (response < 0)
  73                 dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit);
  74         return response;
  75 }
  76 
  77 #define FW_LOAD_SIZE            1023
  78 
  79 static int emi62_load_firmware (struct usb_device *dev)
  80 {
  81         const struct firmware *loader_fw = NULL;
  82         const struct firmware *bitstream_fw = NULL;
  83         const struct firmware *firmware_fw = NULL;
  84         const struct ihex_binrec *rec;
  85         int err = -ENOMEM;
  86         int i;
  87         __u32 addr;     /* Address to write */
  88         __u8 *buf;
  89 
  90         dev_dbg(&dev->dev, "load_firmware\n");
  91         buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
  92         if (!buf)
  93                 goto wraperr;
  94 
  95         err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev);
  96         if (err)
  97                 goto nofw;
  98 
  99         err = request_ihex_firmware(&bitstream_fw, "emi62/bitstream.fw",
 100                                     &dev->dev);
 101         if (err)
 102                 goto nofw;
 103 
 104         err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev);
 105         if (err) {
 106         nofw:
 107                 goto wraperr;
 108         }
 109 
 110         /* Assert reset (stop the CPU in the EMI) */
 111         err = emi62_set_reset(dev,1);
 112         if (err < 0)
 113                 goto wraperr;
 114 
 115         rec = (const struct ihex_binrec *)loader_fw->data;
 116 
 117         /* 1. We need to put the loader for the FPGA into the EZ-USB */
 118         while (rec) {
 119                 err = emi62_writememory(dev, be32_to_cpu(rec->addr),
 120                                         rec->data, be16_to_cpu(rec->len),
 121                                         ANCHOR_LOAD_INTERNAL);
 122                 if (err < 0)
 123                         goto wraperr;
 124                 rec = ihex_next_binrec(rec);
 125         }
 126 
 127         /* De-assert reset (let the CPU run) */
 128         err = emi62_set_reset(dev,0);
 129         if (err < 0)
 130                 goto wraperr;
 131         msleep(250);    /* let device settle */
 132 
 133         /* 2. We upload the FPGA firmware into the EMI
 134          * Note: collect up to 1023 (yes!) bytes and send them with
 135          * a single request. This is _much_ faster! */
 136         rec = (const struct ihex_binrec *)bitstream_fw->data;
 137         do {
 138                 i = 0;
 139                 addr = be32_to_cpu(rec->addr);
 140 
 141                 /* intel hex records are terminated with type 0 element */
 142                 while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) {
 143                         memcpy(buf + i, rec->data, be16_to_cpu(rec->len));
 144                         i += be16_to_cpu(rec->len);
 145                         rec = ihex_next_binrec(rec);
 146                 }
 147                 err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
 148                 if (err < 0)
 149                         goto wraperr;
 150         } while (rec);
 151 
 152         /* Assert reset (stop the CPU in the EMI) */
 153         err = emi62_set_reset(dev,1);
 154         if (err < 0)
 155                 goto wraperr;
 156 
 157         /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
 158         for (rec = (const struct ihex_binrec *)loader_fw->data;
 159              rec; rec = ihex_next_binrec(rec)) {
 160                 err = emi62_writememory(dev, be32_to_cpu(rec->addr),
 161                                         rec->data, be16_to_cpu(rec->len),
 162                                         ANCHOR_LOAD_INTERNAL);
 163                 if (err < 0)
 164                         goto wraperr;
 165         }
 166 
 167         /* De-assert reset (let the CPU run) */
 168         err = emi62_set_reset(dev,0);
 169         if (err < 0)
 170                 goto wraperr;
 171         msleep(250);    /* let device settle */
 172 
 173         /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
 174 
 175         for (rec = (const struct ihex_binrec *)firmware_fw->data;
 176              rec; rec = ihex_next_binrec(rec)) {
 177                 if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) {
 178                         err = emi62_writememory(dev, be32_to_cpu(rec->addr),
 179                                                 rec->data, be16_to_cpu(rec->len),
 180                                                 ANCHOR_LOAD_EXTERNAL);
 181                         if (err < 0)
 182                                 goto wraperr;
 183                 }
 184         }
 185 
 186         /* Assert reset (stop the CPU in the EMI) */
 187         err = emi62_set_reset(dev,1);
 188         if (err < 0)
 189                 goto wraperr;
 190 
 191         for (rec = (const struct ihex_binrec *)firmware_fw->data;
 192              rec; rec = ihex_next_binrec(rec)) {
 193                 if (INTERNAL_RAM(be32_to_cpu(rec->addr))) {
 194                         err = emi62_writememory(dev, be32_to_cpu(rec->addr),
 195                                                 rec->data, be16_to_cpu(rec->len),
 196                                                 ANCHOR_LOAD_EXTERNAL);
 197                         if (err < 0)
 198                                 goto wraperr;
 199                 }
 200         }
 201 
 202         /* De-assert reset (let the CPU run) */
 203         err = emi62_set_reset(dev,0);
 204         if (err < 0)
 205                 goto wraperr;
 206         msleep(250);    /* let device settle */
 207 
 208         release_firmware(loader_fw);
 209         release_firmware(bitstream_fw);
 210         release_firmware(firmware_fw);
 211 
 212         kfree(buf);
 213 
 214         /* return 1 to fail the driver inialization
 215          * and give real driver change to load */
 216         return 1;
 217 
 218 wraperr:
 219         if (err < 0)
 220                 dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
 221                         __func__, err);
 222         release_firmware(loader_fw);
 223         release_firmware(bitstream_fw);
 224         release_firmware(firmware_fw);
 225 
 226         kfree(buf);
 227         dev_err(&dev->dev, "Error\n");
 228         return err;
 229 }
 230 
 231 static const struct usb_device_id id_table[] = {
 232         { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },
 233         { }                                             /* Terminating entry */
 234 };
 235 
 236 MODULE_DEVICE_TABLE (usb, id_table);
 237 
 238 static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id)
 239 {
 240         struct usb_device *dev = interface_to_usbdev(intf);
 241         dev_dbg(&intf->dev, "emi62_probe\n");
 242 
 243         dev_info(&intf->dev, "%s start\n", __func__);
 244 
 245         emi62_load_firmware(dev);
 246 
 247         /* do not return the driver context, let real audio driver do that */
 248         return -EIO;
 249 }
 250 
 251 static void emi62_disconnect(struct usb_interface *intf)
 252 {
 253 }
 254 
 255 static struct usb_driver emi62_driver = {
 256         .name           = "emi62 - firmware loader",
 257         .probe          = emi62_probe,
 258         .disconnect     = emi62_disconnect,
 259         .id_table       = id_table,
 260 };
 261 
 262 module_usb_driver(emi62_driver);
 263 
 264 MODULE_AUTHOR("Tapio Laxström");
 265 MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader.");
 266 MODULE_LICENSE("GPL");
 267 
 268 MODULE_FIRMWARE("emi62/loader.fw");
 269 MODULE_FIRMWARE("emi62/bitstream.fw");
 270 MODULE_FIRMWARE(FIRMWARE_FW);
 271 /* vi:ai:syntax=c:sw=8:ts=8:tw=80
 272  */

/* [<][>][^][v][top][bottom][index][help] */