1 /* 2 * EZ-USB specific functions used by some of the USB to Serial drivers. 3 * 4 * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License version 8 * 2 as published by the Free Software Foundation. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/slab.h> 14 #include <linux/module.h> 15 #include <linux/usb.h> 16 #include <linux/firmware.h> 17 #include <linux/ihex.h> 18 19 struct ezusb_fx_type { 20 /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ 21 unsigned short cpucs_reg; 22 unsigned short max_internal_adress; 23 }; 24 25 struct ezusb_fx_type ezusb_fx1 = { 26 .cpucs_reg = 0x7F92, 27 .max_internal_adress = 0x1B3F, 28 }; 29 30 struct ezusb_fx_type ezusb_fx2 = { 31 .cpucs_reg = 0xE600, 32 .max_internal_adress = 0x3FFF, 33 }; 34 35 /* Commands for writing to memory */ 36 #define WRITE_INT_RAM 0xA0 37 #define WRITE_EXT_RAM 0xA3 38 39 int ezusb_writememory(struct usb_device *dev, int address, 40 unsigned char *data, int length, __u8 request) 41 { 42 int result; 43 unsigned char *transfer_buffer; 44 45 if (!dev) 46 return -ENODEV; 47 48 transfer_buffer = kmemdup(data, length, GFP_KERNEL); 49 if (!transfer_buffer) { 50 dev_err(&dev->dev, "%s - kmalloc(%d) failed.\n", 51 __func__, length); 52 return -ENOMEM; 53 } 54 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, 55 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 56 address, 0, transfer_buffer, length, 3000); 57 58 kfree(transfer_buffer); 59 return result; 60 } 61 EXPORT_SYMBOL_GPL(ezusb_writememory); 62 63 int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, 64 unsigned char reset_bit) 65 { 66 int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM); 67 if (response < 0) 68 dev_err(&dev->dev, "%s-%d failed: %d\n", 69 __func__, reset_bit, response); 70 return response; 71 } 72 73 int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit) 74 { 75 return ezusb_set_reset(dev, ezusb_fx1.cpucs_reg, reset_bit); 76 } 77 EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); 78 79 int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) 80 { 81 return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); 82 } 83 EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); 84 85 static int ezusb_ihex_firmware_download(struct usb_device *dev, 86 struct ezusb_fx_type fx, 87 const char *firmware_path) 88 { 89 int ret = -ENOENT; 90 const struct firmware *firmware = NULL; 91 const struct ihex_binrec *record; 92 93 if (request_ihex_firmware(&firmware, firmware_path, 94 &dev->dev)) { 95 dev_err(&dev->dev, 96 "%s - request \"%s\" failed\n", 97 __func__, firmware_path); 98 goto out; 99 } 100 101 ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); 102 if (ret < 0) 103 goto out; 104 105 record = (const struct ihex_binrec *)firmware->data; 106 for (; record; record = ihex_next_binrec(record)) { 107 if (be32_to_cpu(record->addr) > fx.max_internal_adress) { 108 ret = ezusb_writememory(dev, be32_to_cpu(record->addr), 109 (unsigned char *)record->data, 110 be16_to_cpu(record->len), WRITE_EXT_RAM); 111 if (ret < 0) { 112 dev_err(&dev->dev, "%s - ezusb_writememory " 113 "failed writing internal memory " 114 "(%d %04X %p %d)\n", __func__, ret, 115 be32_to_cpu(record->addr), record->data, 116 be16_to_cpu(record->len)); 117 goto out; 118 } 119 } 120 } 121 122 ret = ezusb_set_reset(dev, fx.cpucs_reg, 1); 123 if (ret < 0) 124 goto out; 125 record = (const struct ihex_binrec *)firmware->data; 126 for (; record; record = ihex_next_binrec(record)) { 127 if (be32_to_cpu(record->addr) <= fx.max_internal_adress) { 128 ret = ezusb_writememory(dev, be32_to_cpu(record->addr), 129 (unsigned char *)record->data, 130 be16_to_cpu(record->len), WRITE_INT_RAM); 131 if (ret < 0) { 132 dev_err(&dev->dev, "%s - ezusb_writememory " 133 "failed writing external memory " 134 "(%d %04X %p %d)\n", __func__, ret, 135 be32_to_cpu(record->addr), record->data, 136 be16_to_cpu(record->len)); 137 goto out; 138 } 139 } 140 } 141 ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); 142 out: 143 release_firmware(firmware); 144 return ret; 145 } 146 147 int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, 148 const char *firmware_path) 149 { 150 return ezusb_ihex_firmware_download(dev, ezusb_fx1, firmware_path); 151 } 152 EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); 153 154 int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, 155 const char *firmware_path) 156 { 157 return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path); 158 } 159 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); 160 161