static int emi26_load_firmware (struct usb_device *dev) { const struct firmware *loader_fw = NULL; const struct firmware *bitstream_fw = NULL; const struct firmware *firmware_fw = NULL; const struct ihex_binrec *rec; int err; int i; __u32 addr; __u8 *buf; buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); if (!buf) { dev_err(&dev->dev, "%s - error loading firmware: error = %d\n", __func__, -ENOMEM); err = -ENOMEM; goto wraperr; } err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); if (err) goto nofw; err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw", &dev->dev); if (err) goto nofw; err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw", &dev->dev); if (err) { nofw: dev_err(&dev->dev, "%s - request_firmware() failed\n", __func__); goto wraperr; } err = emi26_set_reset(dev,1); if (err < 0) { dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", __func__, err); goto wraperr; } rec = (const struct ihex_binrec *)loader_fw->data; while (rec) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } rec = ihex_next_binrec(rec); } err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } msleep(250); rec = (const struct ihex_binrec *)bitstream_fw->data; do { i = 0; addr = be32_to_cpu(rec->addr); while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) { memcpy(buf + i, rec->data, be16_to_cpu(rec->len)); i += be16_to_cpu(rec->len); rec = ihex_next_binrec(rec); } err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } } while (rec); err = emi26_set_reset(dev,1); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } for (rec = (const struct ihex_binrec *)loader_fw->data; rec; rec = ihex_next_binrec(rec)) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } } msleep(250); err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } } } err = emi26_set_reset(dev,1); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { if (INTERNAL_RAM(be32_to_cpu(rec->addr))) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } } } err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } msleep(250); err = 1; wraperr: release_firmware(loader_fw); release_firmware(bitstream_fw); release_firmware(firmware_fw); kfree(buf); return err; }
int mga_warp_install_microcode(drm_mga_private_t *dev_priv) { unsigned char *vcbase = dev_priv->warp->handle; unsigned long pcbase = dev_priv->warp->offset; const char *firmware_name; struct platform_device *pdev; const struct firmware *fw = NULL; const struct ihex_binrec *rec; unsigned int size; int n_pipes, where; int rc = 0; switch (dev_priv->chipset) { case MGA_CARD_TYPE_G400: case MGA_CARD_TYPE_G550: firmware_name = FIRMWARE_G400; n_pipes = MGA_MAX_G400_PIPES; break; case MGA_CARD_TYPE_G200: firmware_name = FIRMWARE_G200; n_pipes = MGA_MAX_G200_PIPES; break; default: return -EINVAL; } pdev = platform_device_register_simple("mga_warp", 0, NULL, 0); if (IS_ERR(pdev)) { DRM_ERROR("mga: Failed to register microcode\n"); return PTR_ERR(pdev); } rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev); platform_device_unregister(pdev); if (rc) { DRM_ERROR("mga: Failed to load microcode \"%s\"\n", firmware_name); return rc; } size = 0; where = 0; for (rec = (const struct ihex_binrec *)fw->data; rec; rec = ihex_next_binrec(rec)) { size += WARP_UCODE_SIZE(be16_to_cpu(rec->len)); where++; } if (where != n_pipes) { DRM_ERROR("mga: Invalid microcode \"%s\"\n", firmware_name); rc = -EINVAL; goto out; } size = PAGE_ALIGN(size); DRM_DEBUG("MGA ucode size = %d bytes\n", size); if (size > dev_priv->warp->size) { DRM_ERROR("microcode too large! (%u > %lu)\n", size, dev_priv->warp->size); rc = -ENOMEM; goto out; } memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); where = 0; for (rec = (const struct ihex_binrec *)fw->data; rec; rec = ihex_next_binrec(rec)) { unsigned int src_size, dst_size; DRM_DEBUG(" pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase); dev_priv->warp_pipe_phys[where] = pcbase; src_size = be16_to_cpu(rec->len); dst_size = WARP_UCODE_SIZE(src_size); memcpy(vcbase, rec->data, src_size); pcbase += dst_size; vcbase += dst_size; where++; } out: release_firmware(fw); return rc; }
int read_fwfile(const struct ihex_binrec *record) { int i; int rcnt = 0; u16 *tmpinfo; u16 *ptr16; u32 *ptr32, len, addr; pr_debug("Reading fw file ...\n"); while (record) { rcnt++; len = be16_to_cpu(record->len); addr = be32_to_cpu(record->addr); ptr32 = (u32 *) record->data; ptr16 = (u16 *) record->data; switch (addr) { case S3ADDR_START: startaddr = *ptr32; pr_debug(" S7 start addr, record=%d " " addr=0x%08x\n", rcnt, startaddr); break; case S3ADDR_PLUG: s3plug[ns3plug].itemcode = *ptr32; s3plug[ns3plug].addr = *(ptr32 + 1); s3plug[ns3plug].len = *(ptr32 + 2); pr_debug(" S3 plugrec, record=%d " "itemcode=0x%08x addr=0x%08x len=%d\n", rcnt, s3plug[ns3plug].itemcode, s3plug[ns3plug].addr, s3plug[ns3plug].len); ns3plug++; if (ns3plug == S3PLUG_MAX) { printk(KERN_ERR "S3 plugrec limit reached - aborting\n"); return 1; } break; case S3ADDR_CRC: s3crc[ns3crc].addr = *ptr32; s3crc[ns3crc].len = *(ptr32 + 1); s3crc[ns3crc].dowrite = *(ptr32 + 2); pr_debug(" S3 crcrec, record=%d " "addr=0x%08x len=%d write=0x%08x\n", rcnt, s3crc[ns3crc].addr, s3crc[ns3crc].len, s3crc[ns3crc].dowrite); ns3crc++; if (ns3crc == S3CRC_MAX) { printk(KERN_ERR "S3 crcrec limit reached - aborting\n"); return 1; } break; case S3ADDR_INFO: s3info[ns3info].len = *ptr16; s3info[ns3info].type = *(ptr16 + 1); pr_debug(" S3 inforec, record=%d " "len=0x%04x type=0x%04x\n", rcnt, s3info[ns3info].len, s3info[ns3info].type); if (((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info)) { printk(KERN_ERR " S3 inforec length too long - aborting\n"); return 1; } tmpinfo = (u16 *)&(s3info[ns3info].info.version); pr_debug(" info="); for (i = 0; i < s3info[ns3info].len - 1; i++) { tmpinfo[i] = *(ptr16 + 2 + i); pr_debug("%04x ", tmpinfo[i]); } pr_debug("\n"); ns3info++; if (ns3info == S3INFO_MAX) { printk(KERN_ERR "S3 inforec limit reached - aborting\n"); return 1; } break; default: s3data[ns3data].addr = addr; s3data[ns3data].len = len; s3data[ns3data].data = (uint8_t *) record->data; ns3data++; if (ns3data == S3DATA_MAX) { printk(KERN_ERR "S3 datarec limit reached - aborting\n"); return 1; } break; } record = ihex_next_binrec(record); } return 0; }
/* steps to download the firmware to the WhiteHEAT device: - hold the reset (by writing to the reset bit of the CPUCS register) - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD - release the reset (by writing to the CPUCS register) - download the WH.HEX file for all addresses greater than 0x1b3f using VENDOR_REQUEST-ANCHOR_EXTERNAL_RAM_LOAD - hold the reset - download the WH.HEX file for all addresses less than 0x1b40 using VENDOR_REQUEST_ANCHOR_LOAD - release the reset - device renumerated itself and comes up as new device id with all firmware download completed. */ static int whiteheat_firmware_download(struct usb_serial *serial, const struct usb_device_id *id) { int response, ret = -ENOENT; const struct firmware *loader_fw = NULL, *firmware_fw = NULL; const struct ihex_binrec *record; if (request_ihex_firmware(&firmware_fw, "whiteheat.fw", &serial->dev->dev)) { dev_err(&serial->dev->dev, "%s - request \"whiteheat.fw\" failed\n", __func__); goto out; } if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw", &serial->dev->dev)) { dev_err(&serial->dev->dev, "%s - request \"whiteheat_loader.fw\" failed\n", __func__); goto out; } ret = 0; response = ezusb_set_reset (serial, 1); record = (const struct ihex_binrec *)loader_fw->data; while (record) { response = ezusb_writememory (serial, be32_to_cpu(record->addr), (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { dev_err(&serial->dev->dev, "%s - ezusb_writememory " "failed for loader (%d %04X %p %d)\n", __func__, response, be32_to_cpu(record->addr), record->data, be16_to_cpu(record->len)); break; } record = ihex_next_binrec(record); } response = ezusb_set_reset(serial, 0); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) record = ihex_next_binrec(record); while (record) { response = ezusb_writememory (serial, be32_to_cpu(record->addr), (unsigned char *)record->data, be16_to_cpu(record->len), 0xa3); if (response < 0) { dev_err(&serial->dev->dev, "%s - ezusb_writememory " "failed for first firmware step " "(%d %04X %p %d)\n", __func__, response, be32_to_cpu(record->addr), record->data, be16_to_cpu(record->len)); break; } ++record; } response = ezusb_set_reset(serial, 1); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) { response = ezusb_writememory (serial, be32_to_cpu(record->addr), (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { dev_err(&serial->dev->dev, "%s - ezusb_writememory " "failed for second firmware step " "(%d %04X %p %d)\n", __func__, response, be32_to_cpu(record->addr), record->data, be16_to_cpu(record->len)); break; } ++record; } ret = 0; response = ezusb_set_reset (serial, 0); out: release_firmware(loader_fw); release_firmware(firmware_fw); return ret; }
static int emi26_load_firmware (struct usb_device *dev) { const struct firmware *loader_fw = NULL; const struct firmware *bitstream_fw = NULL; const struct firmware *firmware_fw = NULL; const struct ihex_binrec *rec; int err = -ENOMEM; int i; __u32 addr; /* Address to write */ __u8 *buf; buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); if (!buf) goto wraperr; err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); if (err) goto nofw; err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw", &dev->dev); if (err) goto nofw; err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw", &dev->dev); if (err) { nofw: dev_err(&dev->dev, "%s - request_firmware() failed\n", __func__); goto wraperr; } /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); if (err < 0) goto wraperr; rec = (const struct ihex_binrec *)loader_fw->data; /* 1. We need to put the loader for the FPGA into the EZ-USB */ while (rec) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); if (err < 0) goto wraperr; rec = ihex_next_binrec(rec); } /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); if (err < 0) goto wraperr; msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI * Note: collect up to 1023 (yes!) bytes and send them with * a single request. This is _much_ faster! */ rec = (const struct ihex_binrec *)bitstream_fw->data; do { i = 0; addr = be32_to_cpu(rec->addr); /* intel hex records are terminated with type 0 element */ while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) { memcpy(buf + i, rec->data, be16_to_cpu(rec->len)); i += be16_to_cpu(rec->len); rec = ihex_next_binrec(rec); } err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); if (err < 0) goto wraperr; } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); if (err < 0) goto wraperr; /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ for (rec = (const struct ihex_binrec *)loader_fw->data; rec; rec = ihex_next_binrec(rec)) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); if (err < 0) goto wraperr; } msleep(250); /* let device settle */ /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); if (err < 0) goto wraperr; /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); if (err < 0) goto wraperr; } } /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); if (err < 0) goto wraperr; for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { if (INTERNAL_RAM(be32_to_cpu(rec->addr))) { err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); if (err < 0) goto wraperr; } } /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); if (err < 0) goto wraperr; msleep(250); /* let device settle */ /* return 1 to fail the driver inialization * and give real driver change to load */ err = 1; wraperr: if (err < 0) dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", __func__, err); release_firmware(loader_fw); release_firmware(bitstream_fw); release_firmware(firmware_fw); kfree(buf); return err; }