Kelley Nielsen | 89a03d3 | 2013-10-14 14:21:30 -0700 | [diff] [blame] | 1 | /* |
| 2 | * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. |
| 3 | * |
| 4 | * This file is part of Express Card USB Driver |
| 5 | */ |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 6 | |
| 7 | #include <linux/init.h> |
| 8 | #include <linux/kernel.h> |
| 9 | #include <linux/module.h> |
| 10 | #include <linux/netdevice.h> |
| 11 | #include <linux/etherdevice.h> |
| 12 | #include <linux/usb.h> |
| 13 | #include <linux/vmalloc.h> |
| 14 | #include "ft1000_usb.h" |
| 15 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 16 | |
| 17 | #define DWNLD_HANDSHAKE_LOC 0x02 |
| 18 | #define DWNLD_TYPE_LOC 0x04 |
| 19 | #define DWNLD_SIZE_MSW_LOC 0x06 |
| 20 | #define DWNLD_SIZE_LSW_LOC 0x08 |
| 21 | #define DWNLD_PS_HDR_LOC 0x0A |
| 22 | |
| 23 | #define MAX_DSP_WAIT_LOOPS 40 |
| 24 | #define DSP_WAIT_SLEEP_TIME 1000 /* 1 millisecond */ |
| 25 | #define DSP_WAIT_DISPATCH_LVL 50 /* 50 usec */ |
| 26 | |
| 27 | #define HANDSHAKE_TIMEOUT_VALUE 0xF1F1 |
| 28 | #define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */ |
| 29 | #define HANDSHAKE_RESET_VALUE_USB 0xFE7E /* When DSP requests startover */ |
| 30 | #define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */ |
| 31 | #define HANDSHAKE_DSP_BL_READY_USB 0xFE7E /* At start DSP writes this when bootloader ready */ |
| 32 | #define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */ |
| 33 | #define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */ |
| 34 | |
| 35 | #define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */ |
| 36 | #define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */ |
| 37 | |
| 38 | #define REQUEST_CODE_LENGTH 0x0000 |
| 39 | #define REQUEST_RUN_ADDRESS 0x0001 |
| 40 | #define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */ |
| 41 | #define REQUEST_DONE_BL 0x0003 |
| 42 | #define REQUEST_DONE_CL 0x0004 |
| 43 | #define REQUEST_VERSION_INFO 0x0005 |
| 44 | #define REQUEST_CODE_BY_VERSION 0x0006 |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 45 | #define REQUEST_MAILBOX_DATA 0x0007 |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 46 | #define REQUEST_FILE_CHECKSUM 0x0008 |
| 47 | |
| 48 | #define STATE_START_DWNLD 0x01 |
| 49 | #define STATE_BOOT_DWNLD 0x02 |
| 50 | #define STATE_CODE_DWNLD 0x03 |
| 51 | #define STATE_DONE_DWNLD 0x04 |
| 52 | #define STATE_SECTION_PROV 0x05 |
| 53 | #define STATE_DONE_PROV 0x06 |
| 54 | #define STATE_DONE_FILE 0x07 |
| 55 | |
| 56 | #define MAX_LENGTH 0x7f0 |
| 57 | |
| 58 | // Temporary download mechanism for Magnemite |
| 59 | #define DWNLD_MAG_TYPE_LOC 0x00 |
| 60 | #define DWNLD_MAG_LEN_LOC 0x01 |
| 61 | #define DWNLD_MAG_ADDR_LOC 0x02 |
| 62 | #define DWNLD_MAG_CHKSUM_LOC 0x03 |
| 63 | #define DWNLD_MAG_VAL_LOC 0x04 |
| 64 | |
| 65 | #define HANDSHAKE_MAG_DSP_BL_READY 0xFEFE0000 /* At start DSP writes this when bootloader ready */ |
| 66 | #define HANDSHAKE_MAG_DSP_ENTRY 0x01000000 /* Dsp writes this to request for entry address */ |
| 67 | #define HANDSHAKE_MAG_DSP_DATA 0x02000000 /* Dsp writes this to request for data block */ |
| 68 | #define HANDSHAKE_MAG_DSP_DONE 0x03000000 /* Dsp writes this to indicate download done */ |
| 69 | |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 70 | #define HANDSHAKE_MAG_DRV_READY 0xFFFF0000 /* Driver writes this to indicate ready to download */ |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 71 | #define HANDSHAKE_MAG_DRV_DATA 0x02FECDAB /* Driver writes this to indicate data available to DSP */ |
| 72 | #define HANDSHAKE_MAG_DRV_ENTRY 0x01FECDAB /* Driver writes this to indicate entry point to DSP */ |
| 73 | |
| 74 | #define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1 |
| 75 | |
| 76 | |
| 77 | // New Magnemite downloader |
| 78 | #define DWNLD_MAG1_HANDSHAKE_LOC 0x00 |
| 79 | #define DWNLD_MAG1_TYPE_LOC 0x01 |
| 80 | #define DWNLD_MAG1_SIZE_LOC 0x02 |
| 81 | #define DWNLD_MAG1_PS_HDR_LOC 0x03 |
| 82 | |
Marek Belisko | 13da8f0 | 2010-10-12 10:26:43 +0200 | [diff] [blame] | 83 | struct dsp_file_hdr { |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 84 | long version_id; // Version ID of this image format. |
| 85 | long package_id; // Package ID of code release. |
| 86 | long build_date; // Date/time stamp when file was built. |
| 87 | long commands_offset; // Offset to attached commands in Pseudo Hdr format. |
| 88 | long loader_offset; // Offset to bootloader code. |
| 89 | long loader_code_address; // Start address of bootloader. |
| 90 | long loader_code_end; // Where bootloader code ends. |
| 91 | long loader_code_size; |
| 92 | long version_data_offset; // Offset were scrambled version data begins. |
| 93 | long version_data_size; // Size, in words, of scrambled version data. |
| 94 | long nDspImages; // Number of DSP images in file. |
Marek Belisko | 13da8f0 | 2010-10-12 10:26:43 +0200 | [diff] [blame] | 95 | }; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 96 | |
Marek Belisko | 13da8f0 | 2010-10-12 10:26:43 +0200 | [diff] [blame] | 97 | #pragma pack(1) |
| 98 | struct dsp_image_info { |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 99 | long coff_date; // Date/time when DSP Coff image was built. |
| 100 | long begin_offset; // Offset in file where image begins. |
| 101 | long end_offset; // Offset in file where image begins. |
| 102 | long run_address; // On chip Start address of DSP code. |
| 103 | long image_size; // Size of image. |
| 104 | long version; // Embedded version # of DSP code. |
| 105 | unsigned short checksum; // DSP File checksum |
| 106 | unsigned short pad1; |
Marek Belisko | 13da8f0 | 2010-10-12 10:26:43 +0200 | [diff] [blame] | 107 | }; |
| 108 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 109 | |
Kelley Nielsen | de7a0cc | 2013-10-12 12:16:33 -0700 | [diff] [blame] | 110 | /* checks if the doorbell register is cleared */ |
Kelley Nielsen | e072241 | 2013-10-11 23:08:28 -0700 | [diff] [blame] | 111 | static u32 check_usb_db(struct ft1000_usb *ft1000dev) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 112 | { |
Marek Belisko | c5d680c | 2011-02-03 11:07:40 +0100 | [diff] [blame] | 113 | int loopcnt; |
| 114 | u16 temp; |
| 115 | u32 status; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 116 | |
Marek Belisko | c5d680c | 2011-02-03 11:07:40 +0100 | [diff] [blame] | 117 | loopcnt = 0; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 118 | |
Marek Belisko | c5d680c | 2011-02-03 11:07:40 +0100 | [diff] [blame] | 119 | while (loopcnt < 10) { |
| 120 | status = ft1000_read_register(ft1000dev, &temp, |
| 121 | FT1000_REG_DOORBELL); |
| 122 | DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n", |
| 123 | temp); |
| 124 | if (temp & 0x0080) { |
| 125 | DEBUG("FT1000:Got checkusb doorbell\n"); |
| 126 | status = ft1000_write_register(ft1000dev, 0x0080, |
| 127 | FT1000_REG_DOORBELL); |
| 128 | status = ft1000_write_register(ft1000dev, 0x0100, |
| 129 | FT1000_REG_DOORBELL); |
| 130 | status = ft1000_write_register(ft1000dev, 0x8000, |
| 131 | FT1000_REG_DOORBELL); |
| 132 | break; |
| 133 | } else { |
| 134 | loopcnt++; |
| 135 | msleep(10); |
| 136 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 137 | |
Marek Belisko | c5d680c | 2011-02-03 11:07:40 +0100 | [diff] [blame] | 138 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 139 | |
Marek Belisko | c5d680c | 2011-02-03 11:07:40 +0100 | [diff] [blame] | 140 | loopcnt = 0; |
| 141 | while (loopcnt < 20) { |
| 142 | status = ft1000_read_register(ft1000dev, &temp, |
| 143 | FT1000_REG_DOORBELL); |
| 144 | DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp); |
| 145 | if (temp & 0x8000) { |
| 146 | loopcnt++; |
| 147 | msleep(10); |
| 148 | } else { |
| 149 | DEBUG("check_usb_db: door bell is cleared, return 0\n"); |
| 150 | return 0; |
| 151 | } |
| 152 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 153 | |
Marek Belisko | c5d680c | 2011-02-03 11:07:40 +0100 | [diff] [blame] | 154 | return HANDSHAKE_MAG_TIMEOUT_VALUE; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 155 | } |
| 156 | |
Kelley Nielsen | 135a9ea | 2013-10-13 18:52:46 -0700 | [diff] [blame] | 157 | /* gets the handshake and compares it with the expected value */ |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 158 | static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 159 | { |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 160 | u16 handshake; |
| 161 | int loopcnt; |
| 162 | u32 status = 0; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 163 | |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 164 | loopcnt = 0; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 165 | |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 166 | while (loopcnt < 100) { |
| 167 | /* Need to clear downloader doorbell if Hartley ASIC */ |
| 168 | status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_RX, |
| 169 | FT1000_REG_DOORBELL); |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 170 | if (ft1000dev->fcodeldr) { |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 171 | DEBUG(" get_handshake: fcodeldr is %d\n", |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 172 | ft1000dev->fcodeldr); |
| 173 | ft1000dev->fcodeldr = 0; |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 174 | status = check_usb_db(ft1000dev); |
| 175 | if (status != STATUS_SUCCESS) { |
| 176 | DEBUG("get_handshake: check_usb_db failed\n"); |
| 177 | status = STATUS_FAILURE; |
| 178 | break; |
| 179 | } |
| 180 | status = ft1000_write_register(ft1000dev, |
| 181 | FT1000_DB_DNLD_RX, |
| 182 | FT1000_REG_DOORBELL); |
| 183 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 184 | |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 185 | status = ft1000_read_dpram16(ft1000dev, |
| 186 | DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1); |
| 187 | handshake = ntohs(handshake); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 188 | |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 189 | if (status) |
| 190 | return HANDSHAKE_TIMEOUT_VALUE; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 191 | |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 192 | if ((handshake == expected_value) || |
| 193 | (handshake == HANDSHAKE_RESET_VALUE_USB)) { |
| 194 | return handshake; |
| 195 | } else { |
| 196 | loopcnt++; |
| 197 | msleep(10); |
| 198 | } |
| 199 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 200 | |
Marek Belisko | d7a7318 | 2011-02-03 11:07:49 +0100 | [diff] [blame] | 201 | return HANDSHAKE_TIMEOUT_VALUE; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 202 | } |
| 203 | |
Kelley Nielsen | fafa4dc | 2013-10-14 14:40:01 -0700 | [diff] [blame] | 204 | /* write the handshake value to the handshake location */ |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 205 | static void put_handshake(struct ft1000_usb *ft1000dev,u16 handshake_value) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 206 | { |
Marek Belisko | a8d4d19 | 2011-02-03 11:07:41 +0100 | [diff] [blame] | 207 | u32 tempx; |
| 208 | u16 tempword; |
| 209 | u32 status; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 210 | |
Marek Belisko | a8d4d19 | 2011-02-03 11:07:41 +0100 | [diff] [blame] | 211 | tempx = (u32)handshake_value; |
| 212 | tempx = ntohl(tempx); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 213 | |
Marek Belisko | a8d4d19 | 2011-02-03 11:07:41 +0100 | [diff] [blame] | 214 | tempword = (u16)(tempx & 0xffff); |
| 215 | status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, |
| 216 | tempword, 0); |
| 217 | tempword = (u16)(tempx >> 16); |
| 218 | status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, |
| 219 | tempword, 1); |
| 220 | status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, |
| 221 | FT1000_REG_DOORBELL); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 222 | } |
| 223 | |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 224 | static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 225 | { |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 226 | u16 handshake; |
| 227 | int loopcnt; |
| 228 | u16 temp; |
| 229 | u32 status = 0; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 230 | |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 231 | loopcnt = 0; |
| 232 | handshake = 0; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 233 | |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 234 | while (loopcnt < 100) { |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 235 | if (ft1000dev->usbboot == 2) { |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 236 | status = ft1000_read_dpram32(ft1000dev, 0, |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 237 | (u8 *)&(ft1000dev->tempbuf[0]), 64); |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 238 | for (temp = 0; temp < 16; temp++) { |
| 239 | DEBUG("tempbuf %d = 0x%x\n", temp, |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 240 | ft1000dev->tempbuf[temp]); |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 241 | } |
| 242 | status = ft1000_read_dpram16(ft1000dev, |
| 243 | DWNLD_MAG1_HANDSHAKE_LOC, |
| 244 | (u8 *)&handshake, 1); |
| 245 | DEBUG("handshake from read_dpram16 = 0x%x\n", |
| 246 | handshake); |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 247 | if (ft1000dev->dspalive == ft1000dev->tempbuf[6]) { |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 248 | handshake = 0; |
| 249 | } else { |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 250 | handshake = ft1000dev->tempbuf[1]; |
| 251 | ft1000dev->dspalive = |
| 252 | ft1000dev->tempbuf[6]; |
Marek Belisko | 5865a18 | 2011-02-03 11:07:42 +0100 | [diff] [blame] | 253 | } |
| 254 | } else { |
| 255 | status = ft1000_read_dpram16(ft1000dev, |
| 256 | DWNLD_MAG1_HANDSHAKE_LOC, |
| 257 | (u8 *)&handshake, 1); |
| 258 | } |
| 259 | |
| 260 | loopcnt++; |
| 261 | msleep(10); |
| 262 | handshake = ntohs(handshake); |
| 263 | if ((handshake == expected_value) || |
| 264 | (handshake == HANDSHAKE_RESET_VALUE_USB)) |
| 265 | return handshake; |
| 266 | } |
| 267 | |
| 268 | return HANDSHAKE_TIMEOUT_VALUE; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 269 | } |
| 270 | |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 271 | static void put_handshake_usb(struct ft1000_usb *ft1000dev,u16 handshake_value) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 272 | { |
Marek Belisko | 5acc539 | 2011-02-03 11:07:43 +0100 | [diff] [blame] | 273 | int i; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 274 | |
| 275 | for (i=0; i<1000; i++); |
| 276 | } |
| 277 | |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 278 | static u16 get_request_type(struct ft1000_usb *ft1000dev) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 279 | { |
Marek Belisko | 9b43f37 | 2011-02-03 11:07:44 +0100 | [diff] [blame] | 280 | u16 request_type; |
| 281 | u32 status; |
| 282 | u16 tempword; |
| 283 | u32 tempx; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 284 | |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 285 | if (ft1000dev->bootmode == 1) { |
Marek Belisko | 9b43f37 | 2011-02-03 11:07:44 +0100 | [diff] [blame] | 286 | status = fix_ft1000_read_dpram32(ft1000dev, |
| 287 | DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx); |
| 288 | tempx = ntohl(tempx); |
| 289 | } else { |
| 290 | tempx = 0; |
| 291 | status = ft1000_read_dpram16(ft1000dev, |
| 292 | DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1); |
| 293 | tempx |= (tempword << 16); |
| 294 | tempx = ntohl(tempx); |
| 295 | } |
| 296 | request_type = (u16)tempx; |
Marek Belisko | 6e2c2dc | 2010-10-14 11:41:00 +0200 | [diff] [blame] | 297 | |
Marek Belisko | 9b43f37 | 2011-02-03 11:07:44 +0100 | [diff] [blame] | 298 | return request_type; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 299 | } |
| 300 | |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 301 | static u16 get_request_type_usb(struct ft1000_usb *ft1000dev) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 302 | { |
Marek Belisko | c3ed5d2 | 2011-02-03 11:07:45 +0100 | [diff] [blame] | 303 | u16 request_type; |
| 304 | u32 status; |
| 305 | u16 tempword; |
| 306 | u32 tempx; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 307 | |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 308 | if (ft1000dev->bootmode == 1) { |
Marek Belisko | c3ed5d2 | 2011-02-03 11:07:45 +0100 | [diff] [blame] | 309 | status = fix_ft1000_read_dpram32(ft1000dev, |
| 310 | DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx); |
| 311 | tempx = ntohl(tempx); |
| 312 | } else { |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 313 | if (ft1000dev->usbboot == 2) { |
| 314 | tempx = ft1000dev->tempbuf[2]; |
| 315 | tempword = ft1000dev->tempbuf[3]; |
Marek Belisko | c3ed5d2 | 2011-02-03 11:07:45 +0100 | [diff] [blame] | 316 | } else { |
| 317 | tempx = 0; |
| 318 | status = ft1000_read_dpram16(ft1000dev, |
| 319 | DWNLD_MAG1_TYPE_LOC, |
| 320 | (u8 *)&tempword, 1); |
| 321 | } |
| 322 | tempx |= (tempword << 16); |
| 323 | tempx = ntohl(tempx); |
| 324 | } |
| 325 | request_type = (u16)tempx; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 326 | |
Marek Belisko | c3ed5d2 | 2011-02-03 11:07:45 +0100 | [diff] [blame] | 327 | return request_type; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 328 | } |
| 329 | |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 330 | static long get_request_value(struct ft1000_usb *ft1000dev) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 331 | { |
Marek Belisko | 114a06a | 2011-02-03 11:07:46 +0100 | [diff] [blame] | 332 | u32 value; |
| 333 | u16 tempword; |
| 334 | u32 status; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 335 | |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 336 | if (ft1000dev->bootmode == 1) { |
Marek Belisko | 114a06a | 2011-02-03 11:07:46 +0100 | [diff] [blame] | 337 | status = fix_ft1000_read_dpram32(ft1000dev, |
| 338 | DWNLD_MAG1_SIZE_LOC, (u8 *)&value); |
| 339 | value = ntohl(value); |
| 340 | } else { |
| 341 | status = ft1000_read_dpram16(ft1000dev, |
| 342 | DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0); |
| 343 | value = tempword; |
| 344 | status = ft1000_read_dpram16(ft1000dev, |
| 345 | DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1); |
| 346 | value |= (tempword << 16); |
| 347 | value = ntohl(value); |
| 348 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 349 | |
Marek Belisko | 114a06a | 2011-02-03 11:07:46 +0100 | [diff] [blame] | 350 | return value; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 351 | } |
| 352 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 353 | |
Kelley Nielsen | 9e80d03 | 2013-10-15 14:05:09 -0700 | [diff] [blame] | 354 | /* writes a value to DWNLD_MAG1_SIZE_LOC */ |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 355 | static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 356 | { |
Marek Belisko | cc4f65b | 2011-02-03 11:07:47 +0100 | [diff] [blame] | 357 | u32 tempx; |
| 358 | u32 status; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 359 | |
Marek Belisko | cc4f65b | 2011-02-03 11:07:47 +0100 | [diff] [blame] | 360 | tempx = ntohl(lvalue); |
| 361 | status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, |
| 362 | (u8 *)&tempx); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | |
| 366 | |
Kelley Nielsen | b30f4e2 | 2013-10-15 14:05:41 -0700 | [diff] [blame] | 367 | /* returns the checksum of the pseudo header */ |
Marek Belisko | fc549a0 | 2010-11-03 11:19:50 +0100 | [diff] [blame] | 368 | static u16 hdr_checksum(struct pseudo_hdr *pHdr) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 369 | { |
Marek Belisko | 78395f6 | 2011-02-03 11:07:48 +0100 | [diff] [blame] | 370 | u16 *usPtr = (u16 *)pHdr; |
| 371 | u16 chksum; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 372 | |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 373 | |
Marek Belisko | 78395f6 | 2011-02-03 11:07:48 +0100 | [diff] [blame] | 374 | chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^ |
| 375 | usPtr[4]) ^ usPtr[5]) ^ usPtr[6]); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 376 | |
Marek Belisko | 78395f6 | 2011-02-03 11:07:48 +0100 | [diff] [blame] | 377 | return chksum; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 378 | } |
| 379 | |
Marek Belisko | e7af078 | 2011-02-03 11:07:53 +0100 | [diff] [blame] | 380 | static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset) |
| 381 | { |
| 382 | int i; |
| 383 | |
| 384 | for (i = 0; i < len; i++) { |
| 385 | if (buff_w[i] != buff_r[i + offset]) |
| 386 | return -1; |
| 387 | } |
| 388 | |
| 389 | return 0; |
| 390 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 391 | |
Kelley Nielsen | 69f7be1 | 2013-10-15 14:06:12 -0700 | [diff] [blame] | 392 | /* writes a block of DSP image to DPRAM |
| 393 | * Parameters: struct ft1000_usb - device structure |
| 394 | * u16 **pUsFile - DSP image file pointer in u16 |
| 395 | * u8 **pUcFile - DSP image file pointer in u8 |
| 396 | * long word_length - length of the buffer to be written to DPRAM |
| 397 | */ |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 398 | static u32 write_blk (struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 399 | { |
Marek Belisko | 84b7801 | 2010-11-03 11:19:52 +0100 | [diff] [blame] | 400 | u32 Status = STATUS_SUCCESS; |
Marek Belisko | fc549a0 | 2010-11-03 11:19:50 +0100 | [diff] [blame] | 401 | u16 dpram; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 402 | int loopcnt, i, j; |
Marek Belisko | fc549a0 | 2010-11-03 11:19:50 +0100 | [diff] [blame] | 403 | u16 tempword; |
| 404 | u16 tempbuffer[64]; |
| 405 | u16 resultbuffer[64]; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 406 | |
| 407 | //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length); |
Marek Belisko | fc549a0 | 2010-11-03 11:19:50 +0100 | [diff] [blame] | 408 | dpram = (u16)DWNLD_MAG1_PS_HDR_LOC; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 409 | tempword = *(*pUsFile); |
| 410 | (*pUsFile)++; |
| 411 | Status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0); |
| 412 | tempword = *(*pUsFile); |
| 413 | (*pUsFile)++; |
| 414 | Status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1); |
| 415 | |
| 416 | *pUcFile = *pUcFile + 4; |
| 417 | word_length--; |
Marek Belisko | fc549a0 | 2010-11-03 11:19:50 +0100 | [diff] [blame] | 418 | tempword = (u16)word_length; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 419 | word_length = (word_length / 16) + 1; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 420 | for (; word_length > 0; word_length--) /* In words */ |
| 421 | { |
| 422 | loopcnt = 0; |
| 423 | |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 424 | for (i=0; i<32; i++) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 425 | { |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 426 | if (tempword != 0) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 427 | { |
| 428 | tempbuffer[i++] = *(*pUsFile); |
| 429 | (*pUsFile)++; |
| 430 | tempbuffer[i] = *(*pUsFile); |
| 431 | (*pUsFile)++; |
| 432 | *pUcFile = *pUcFile + 4; |
| 433 | loopcnt++; |
| 434 | tempword--; |
| 435 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 436 | else |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 437 | { |
| 438 | tempbuffer[i++] = 0; |
| 439 | tempbuffer[i] = 0; |
| 440 | } |
| 441 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 442 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 443 | //DEBUG("write_blk: loopcnt is %d\n", loopcnt); |
| 444 | //DEBUG("write_blk: bootmode = %d\n", bootmode); |
| 445 | //DEBUG("write_blk: dpram = %x\n", dpram); |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 446 | if (ft1000dev->bootmode == 0) |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 447 | { |
| 448 | if (dpram >= 0x3F4) |
Marek Belisko | e2cb7da | 2010-11-03 11:19:47 +0100 | [diff] [blame] | 449 | Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 8); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 450 | else |
Marek Belisko | e2cb7da | 2010-11-03 11:19:47 +0100 | [diff] [blame] | 451 | Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 452 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 453 | else |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 454 | { |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 455 | for (j=0; j<10; j++) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 456 | { |
Marek Belisko | e2cb7da | 2010-11-03 11:19:47 +0100 | [diff] [blame] | 457 | Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 458 | if (Status == STATUS_SUCCESS) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 459 | { |
| 460 | // Work around for ASIC bit stuffing problem. |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 461 | if ( (tempbuffer[31] & 0xfe00) == 0xfe00) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 462 | { |
Marek Belisko | e2cb7da | 2010-11-03 11:19:47 +0100 | [diff] [blame] | 463 | Status = ft1000_write_dpram32(ft1000dev, dpram+12, (u8 *)&tempbuffer[24], 64); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 464 | } |
| 465 | // Let's check the data written |
Marek Belisko | e2cb7da | 2010-11-03 11:19:47 +0100 | [diff] [blame] | 466 | Status = ft1000_read_dpram32 (ft1000dev, dpram, (u8 *)&resultbuffer[0], 64); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 467 | if ( (tempbuffer[31] & 0xfe00) == 0xfe00) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 468 | { |
Marek Belisko | e7af078 | 2011-02-03 11:07:53 +0100 | [diff] [blame] | 469 | if (check_buffers(tempbuffer, resultbuffer, 28, 0)) { |
| 470 | DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n"); |
| 471 | msleep(10); |
| 472 | Status = STATUS_FAILURE; |
| 473 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 474 | } |
Marek Belisko | e2cb7da | 2010-11-03 11:19:47 +0100 | [diff] [blame] | 475 | Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (u8 *)&resultbuffer[0], 64); |
Marek Belisko | e7af078 | 2011-02-03 11:07:53 +0100 | [diff] [blame] | 476 | |
| 477 | if (check_buffers(tempbuffer, resultbuffer, 16, 24)) { |
| 478 | DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n"); |
| 479 | msleep(10); |
| 480 | Status = STATUS_FAILURE; |
| 481 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 482 | } |
Marek Belisko | e7af078 | 2011-02-03 11:07:53 +0100 | [diff] [blame] | 483 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 484 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 485 | else |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 486 | { |
Marek Belisko | e7af078 | 2011-02-03 11:07:53 +0100 | [diff] [blame] | 487 | if (check_buffers(tempbuffer, resultbuffer, 32, 0)) { |
| 488 | DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n"); |
| 489 | msleep(10); |
| 490 | Status = STATUS_FAILURE; |
| 491 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 492 | } |
Marek Belisko | e7af078 | 2011-02-03 11:07:53 +0100 | [diff] [blame] | 493 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 494 | } |
| 495 | |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 496 | if (Status == STATUS_SUCCESS) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 497 | break; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 498 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 499 | } |
| 500 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 501 | |
| 502 | if (Status != STATUS_SUCCESS) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 503 | { |
| 504 | DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]); |
| 505 | break; |
| 506 | } |
| 507 | |
| 508 | } |
| 509 | dpram = dpram + loopcnt; |
| 510 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 511 | |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 512 | return Status; |
| 513 | } |
| 514 | |
| 515 | static void usb_dnld_complete (struct urb *urb) |
| 516 | { |
| 517 | //DEBUG("****** usb_dnld_complete\n"); |
| 518 | } |
| 519 | |
Kelley Nielsen | 456ae7e | 2013-10-15 14:06:41 -0700 | [diff] [blame] | 520 | /* writes a block of DSP image to DPRAM |
| 521 | * Parameters: struct ft1000_usb - device structure |
| 522 | * u16 **pUsFile - DSP image file pointer in u16 |
| 523 | * u8 **pUcFile - DSP image file pointer in u8 |
| 524 | * long word_length - length of the buffer to be written to DPRAM |
| 525 | */ |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 526 | static u32 write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile, |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 527 | u8 **pUcFile, long word_length) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 528 | { |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 529 | u32 Status = STATUS_SUCCESS; |
| 530 | int byte_length; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 531 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 532 | byte_length = word_length * 4; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 533 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 534 | if (byte_length && ((byte_length % 64) == 0)) |
| 535 | byte_length += 4; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 536 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 537 | if (byte_length < 64) |
| 538 | byte_length = 68; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 539 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 540 | usb_init_urb(ft1000dev->tx_urb); |
| 541 | memcpy(ft1000dev->tx_buf, *pUcFile, byte_length); |
| 542 | usb_fill_bulk_urb(ft1000dev->tx_urb, |
| 543 | ft1000dev->dev, |
| 544 | usb_sndbulkpipe(ft1000dev->dev, |
| 545 | ft1000dev->bulk_out_endpointAddr), |
| 546 | ft1000dev->tx_buf, byte_length, usb_dnld_complete, |
| 547 | (void *)ft1000dev); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 548 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 549 | usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 550 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 551 | *pUsFile = *pUsFile + (word_length << 1); |
| 552 | *pUcFile = *pUcFile + (word_length << 2); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 553 | |
Marek Belisko | 857af45 | 2011-02-03 11:07:50 +0100 | [diff] [blame] | 554 | return Status; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 555 | } |
| 556 | |
Kelley Nielsen | eb3836c | 2013-10-27 16:40:39 -0700 | [diff] [blame^] | 557 | static int scram_start_dwnld(struct ft1000_usb *ft1000dev, u16 *hshake, |
| 558 | u32 *state) |
| 559 | { |
| 560 | int status = STATUS_SUCCESS; |
| 561 | |
| 562 | DEBUG("FT1000:STATE_START_DWNLD\n"); |
| 563 | if (ft1000dev->usbboot) |
| 564 | *hshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY); |
| 565 | else |
| 566 | *hshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY); |
| 567 | if (*hshake == HANDSHAKE_DSP_BL_READY) { |
| 568 | DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n"); |
| 569 | put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY); |
| 570 | } else { |
| 571 | DEBUG("FT1000:download:Download error: Handshake failed\n"); |
| 572 | status = STATUS_FAILURE; |
| 573 | } |
| 574 | *state = STATE_BOOT_DWNLD; |
| 575 | return status; |
| 576 | } |
| 577 | |
Kelley Nielsen | 4b31e1f | 2013-10-15 14:07:09 -0700 | [diff] [blame] | 578 | /* Scramble downloader for Harley based ASIC via USB interface */ |
Ondrej Zary | dedbc93 | 2012-12-02 18:51:40 +0100 | [diff] [blame] | 579 | u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 580 | u32 FileLength) |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 581 | { |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 582 | u16 status = STATUS_SUCCESS; |
| 583 | u32 state; |
| 584 | u16 handshake; |
Marek Belisko | 0ce72ea | 2010-12-14 14:02:54 +0100 | [diff] [blame] | 585 | struct pseudo_hdr *pseudo_header; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 586 | u16 pseudo_header_len; |
| 587 | long word_length; |
| 588 | u16 request; |
| 589 | u16 temp; |
| 590 | u16 tempword; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 591 | |
Marek Belisko | 0ce72ea | 2010-12-14 14:02:54 +0100 | [diff] [blame] | 592 | struct dsp_file_hdr *file_hdr; |
| 593 | struct dsp_image_info *dsp_img_info = NULL; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 594 | long requested_version; |
| 595 | bool correct_version; |
Marek Belisko | 0ce72ea | 2010-12-14 14:02:54 +0100 | [diff] [blame] | 596 | struct drv_msg *mailbox_data; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 597 | u16 *data = NULL; |
| 598 | u16 *s_file = NULL; |
| 599 | u8 *c_file = NULL; |
| 600 | u8 *boot_end = NULL, *code_end = NULL; |
| 601 | int image; |
| 602 | long loader_code_address, loader_code_size = 0; |
| 603 | long run_address = 0, run_size = 0; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 604 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 605 | u32 templong; |
| 606 | u32 image_chksum = 0; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 607 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 608 | u16 dpram = 0; |
| 609 | u8 *pbuffer; |
Marek Belisko | e27d96d | 2010-10-15 14:13:01 +0200 | [diff] [blame] | 610 | struct prov_record *pprov_record; |
Marek Belisko | 1a88a06 | 2010-10-16 22:37:27 +0200 | [diff] [blame] | 611 | struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 612 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 613 | DEBUG("Entered scram_dnldr...\n"); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 614 | |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 615 | ft1000dev->fcodeldr = 0; |
| 616 | ft1000dev->usbboot = 0; |
| 617 | ft1000dev->dspalive = 0xffff; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 618 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 619 | // |
| 620 | // Get version id of file, at first 4 bytes of file, for newer files. |
| 621 | // |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 622 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 623 | state = STATE_START_DWNLD; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 624 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 625 | file_hdr = (struct dsp_file_hdr *)pFileStart; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 626 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 627 | ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 628 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 629 | s_file = (u16 *) (pFileStart + file_hdr->loader_offset); |
| 630 | c_file = (u8 *) (pFileStart + file_hdr->loader_offset); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 631 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 632 | boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 633 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 634 | loader_code_address = file_hdr->loader_code_address; |
| 635 | loader_code_size = file_hdr->loader_code_size; |
Rashika Kheria | 36f955bf06 | 2013-10-27 19:50:45 +0530 | [diff] [blame] | 636 | correct_version = false; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 637 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 638 | while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) { |
| 639 | switch (state) { |
| 640 | case STATE_START_DWNLD: |
Kelley Nielsen | eb3836c | 2013-10-27 16:40:39 -0700 | [diff] [blame^] | 641 | status = scram_start_dwnld(ft1000dev, &handshake, |
| 642 | &state); |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 643 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 644 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 645 | case STATE_BOOT_DWNLD: |
| 646 | DEBUG("FT1000:STATE_BOOT_DWNLD\n"); |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 647 | ft1000dev->bootmode = 1; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 648 | handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST); |
| 649 | if (handshake == HANDSHAKE_REQUEST) { |
| 650 | /* |
| 651 | * Get type associated with the request. |
| 652 | */ |
| 653 | request = get_request_type(ft1000dev); |
| 654 | switch (request) { |
| 655 | case REQUEST_RUN_ADDRESS: |
| 656 | DEBUG("FT1000:REQUEST_RUN_ADDRESS\n"); |
| 657 | put_request_value(ft1000dev, |
| 658 | loader_code_address); |
| 659 | break; |
| 660 | case REQUEST_CODE_LENGTH: |
| 661 | DEBUG("FT1000:REQUEST_CODE_LENGTH\n"); |
| 662 | put_request_value(ft1000dev, |
| 663 | loader_code_size); |
| 664 | break; |
| 665 | case REQUEST_DONE_BL: |
| 666 | DEBUG("FT1000:REQUEST_DONE_BL\n"); |
| 667 | /* Reposition ptrs to beginning of code section */ |
| 668 | s_file = (u16 *) (boot_end); |
| 669 | c_file = (u8 *) (boot_end); |
| 670 | //DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file); |
| 671 | //DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file); |
| 672 | state = STATE_CODE_DWNLD; |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 673 | ft1000dev->fcodeldr = 1; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 674 | break; |
| 675 | case REQUEST_CODE_SEGMENT: |
| 676 | //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n"); |
| 677 | word_length = |
| 678 | get_request_value(ft1000dev); |
| 679 | //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length); |
| 680 | //NdisMSleep (100); |
| 681 | if (word_length > MAX_LENGTH) { |
| 682 | DEBUG |
| 683 | ("FT1000:download:Download error: Max length exceeded\n"); |
| 684 | status = STATUS_FAILURE; |
| 685 | break; |
| 686 | } |
| 687 | if ((word_length * 2 + c_file) > |
| 688 | boot_end) { |
| 689 | /* |
| 690 | * Error, beyond boot code range. |
| 691 | */ |
| 692 | DEBUG |
Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 693 | ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 694 | (int)word_length); |
| 695 | status = STATUS_FAILURE; |
| 696 | break; |
| 697 | } |
| 698 | /* |
| 699 | * Position ASIC DPRAM auto-increment pointer. |
| 700 | */ |
| 701 | dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 702 | if (word_length & 0x1) |
| 703 | word_length++; |
| 704 | word_length = word_length / 2; |
| 705 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 706 | status = |
| 707 | write_blk(ft1000dev, &s_file, |
| 708 | &c_file, word_length); |
| 709 | //DEBUG("write_blk returned %d\n", status); |
| 710 | break; |
| 711 | default: |
| 712 | DEBUG |
| 713 | ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n", |
| 714 | request); |
| 715 | status = STATUS_FAILURE; |
| 716 | break; |
| 717 | } |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 718 | if (ft1000dev->usbboot) |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 719 | put_handshake_usb(ft1000dev, |
| 720 | HANDSHAKE_RESPONSE); |
| 721 | else |
| 722 | put_handshake(ft1000dev, |
| 723 | HANDSHAKE_RESPONSE); |
| 724 | } else { |
| 725 | DEBUG |
| 726 | ("FT1000:download:Download error: Handshake failed\n"); |
| 727 | status = STATUS_FAILURE; |
| 728 | } |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 729 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 730 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 731 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 732 | case STATE_CODE_DWNLD: |
| 733 | //DEBUG("FT1000:STATE_CODE_DWNLD\n"); |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 734 | ft1000dev->bootmode = 0; |
| 735 | if (ft1000dev->usbboot) |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 736 | handshake = |
| 737 | get_handshake_usb(ft1000dev, |
| 738 | HANDSHAKE_REQUEST); |
| 739 | else |
| 740 | handshake = |
| 741 | get_handshake(ft1000dev, HANDSHAKE_REQUEST); |
| 742 | if (handshake == HANDSHAKE_REQUEST) { |
| 743 | /* |
| 744 | * Get type associated with the request. |
| 745 | */ |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 746 | if (ft1000dev->usbboot) |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 747 | request = |
| 748 | get_request_type_usb(ft1000dev); |
| 749 | else |
| 750 | request = get_request_type(ft1000dev); |
| 751 | switch (request) { |
| 752 | case REQUEST_FILE_CHECKSUM: |
| 753 | DEBUG |
| 754 | ("FT1000:download:image_chksum = 0x%8x\n", |
| 755 | image_chksum); |
| 756 | put_request_value(ft1000dev, |
| 757 | image_chksum); |
| 758 | break; |
| 759 | case REQUEST_RUN_ADDRESS: |
| 760 | DEBUG |
| 761 | ("FT1000:download: REQUEST_RUN_ADDRESS\n"); |
| 762 | if (correct_version) { |
| 763 | DEBUG |
| 764 | ("FT1000:download:run_address = 0x%8x\n", |
| 765 | (int)run_address); |
| 766 | put_request_value(ft1000dev, |
| 767 | run_address); |
| 768 | } else { |
| 769 | DEBUG |
| 770 | ("FT1000:download:Download error: Got Run address request before image offset request.\n"); |
| 771 | status = STATUS_FAILURE; |
| 772 | break; |
| 773 | } |
| 774 | break; |
| 775 | case REQUEST_CODE_LENGTH: |
| 776 | DEBUG |
| 777 | ("FT1000:download:REQUEST_CODE_LENGTH\n"); |
| 778 | if (correct_version) { |
| 779 | DEBUG |
| 780 | ("FT1000:download:run_size = 0x%8x\n", |
| 781 | (int)run_size); |
| 782 | put_request_value(ft1000dev, |
| 783 | run_size); |
| 784 | } else { |
| 785 | DEBUG |
| 786 | ("FT1000:download:Download error: Got Size request before image offset request.\n"); |
| 787 | status = STATUS_FAILURE; |
| 788 | break; |
| 789 | } |
| 790 | break; |
| 791 | case REQUEST_DONE_CL: |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 792 | ft1000dev->usbboot = 3; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 793 | /* Reposition ptrs to beginning of provisioning section */ |
| 794 | s_file = |
| 795 | (u16 *) (pFileStart + |
| 796 | file_hdr->commands_offset); |
| 797 | c_file = |
| 798 | (u8 *) (pFileStart + |
| 799 | file_hdr->commands_offset); |
| 800 | state = STATE_DONE_DWNLD; |
| 801 | break; |
| 802 | case REQUEST_CODE_SEGMENT: |
| 803 | //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n"); |
| 804 | if (!correct_version) { |
| 805 | DEBUG |
| 806 | ("FT1000:download:Download error: Got Code Segment request before image offset request.\n"); |
| 807 | status = STATUS_FAILURE; |
| 808 | break; |
| 809 | } |
Marek Belisko | 165d290 | 2011-02-03 11:07:39 +0100 | [diff] [blame] | 810 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 811 | word_length = |
| 812 | get_request_value(ft1000dev); |
| 813 | //DEBUG("FT1000:download:word_length = %d\n", (int)word_length); |
| 814 | if (word_length > MAX_LENGTH) { |
| 815 | DEBUG |
| 816 | ("FT1000:download:Download error: Max length exceeded\n"); |
| 817 | status = STATUS_FAILURE; |
| 818 | break; |
| 819 | } |
| 820 | if ((word_length * 2 + c_file) > |
| 821 | code_end) { |
| 822 | /* |
| 823 | * Error, beyond boot code range. |
| 824 | */ |
| 825 | DEBUG |
Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 826 | ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundary.\n", |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 827 | (int)word_length); |
| 828 | status = STATUS_FAILURE; |
| 829 | break; |
| 830 | } |
| 831 | /* |
| 832 | * Position ASIC DPRAM auto-increment pointer. |
| 833 | */ |
| 834 | dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; |
| 835 | if (word_length & 0x1) |
| 836 | word_length++; |
| 837 | word_length = word_length / 2; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 838 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 839 | write_blk_fifo(ft1000dev, &s_file, |
| 840 | &c_file, word_length); |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 841 | if (ft1000dev->usbboot == 0) |
| 842 | ft1000dev->usbboot++; |
| 843 | if (ft1000dev->usbboot == 1) { |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 844 | tempword = 0; |
| 845 | ft1000_write_dpram16(ft1000dev, |
| 846 | DWNLD_MAG1_PS_HDR_LOC, |
| 847 | tempword, |
| 848 | 0); |
| 849 | } |
Marek Belisko | 6e2c2dc | 2010-10-14 11:41:00 +0200 | [diff] [blame] | 850 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 851 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 852 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 853 | case REQUEST_MAILBOX_DATA: |
| 854 | DEBUG |
| 855 | ("FT1000:download: REQUEST_MAILBOX_DATA\n"); |
| 856 | // Convert length from byte count to word count. Make sure we round up. |
| 857 | word_length = |
| 858 | (long)(pft1000info->DSPInfoBlklen + |
| 859 | 1) / 2; |
| 860 | put_request_value(ft1000dev, |
| 861 | word_length); |
| 862 | mailbox_data = |
| 863 | (struct drv_msg *)&(pft1000info-> |
| 864 | DSPInfoBlk[0]); |
| 865 | /* |
| 866 | * Position ASIC DPRAM auto-increment pointer. |
| 867 | */ |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 868 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 869 | data = (u16 *) & mailbox_data->data[0]; |
| 870 | dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; |
| 871 | if (word_length & 0x1) |
| 872 | word_length++; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 873 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 874 | word_length = (word_length / 2); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 875 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 876 | for (; word_length > 0; word_length--) { /* In words */ |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 877 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 878 | templong = *data++; |
| 879 | templong |= (*data++ << 16); |
| 880 | status = |
| 881 | fix_ft1000_write_dpram32 |
| 882 | (ft1000dev, dpram++, |
| 883 | (u8 *) & templong); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 884 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 885 | } |
| 886 | break; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 887 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 888 | case REQUEST_VERSION_INFO: |
| 889 | DEBUG |
| 890 | ("FT1000:download:REQUEST_VERSION_INFO\n"); |
| 891 | word_length = |
| 892 | file_hdr->version_data_size; |
| 893 | put_request_value(ft1000dev, |
| 894 | word_length); |
| 895 | /* |
| 896 | * Position ASIC DPRAM auto-increment pointer. |
| 897 | */ |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 898 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 899 | s_file = |
| 900 | (u16 *) (pFileStart + |
| 901 | file_hdr-> |
| 902 | version_data_offset); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 903 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 904 | dpram = (u16) DWNLD_MAG1_PS_HDR_LOC; |
| 905 | if (word_length & 0x1) |
| 906 | word_length++; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 907 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 908 | word_length = (word_length / 2); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 909 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 910 | for (; word_length > 0; word_length--) { /* In words */ |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 911 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 912 | templong = ntohs(*s_file++); |
| 913 | temp = ntohs(*s_file++); |
| 914 | templong |= (temp << 16); |
| 915 | status = |
| 916 | fix_ft1000_write_dpram32 |
| 917 | (ft1000dev, dpram++, |
Kelley Nielsen | 610554d | 2013-10-12 10:26:48 -0700 | [diff] [blame] | 918 | (u8 *) &templong); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 919 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 920 | } |
| 921 | break; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 922 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 923 | case REQUEST_CODE_BY_VERSION: |
| 924 | DEBUG |
| 925 | ("FT1000:download:REQUEST_CODE_BY_VERSION\n"); |
Rashika Kheria | 36f955bf06 | 2013-10-27 19:50:45 +0530 | [diff] [blame] | 926 | correct_version = false; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 927 | requested_version = |
| 928 | get_request_value(ft1000dev); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 929 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 930 | dsp_img_info = |
| 931 | (struct dsp_image_info *)(pFileStart |
| 932 | + |
| 933 | sizeof |
| 934 | (struct |
| 935 | dsp_file_hdr)); |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 936 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 937 | for (image = 0; |
| 938 | image < file_hdr->nDspImages; |
| 939 | image++) { |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 940 | |
Marek Belisko | dfc9539 | 2011-02-03 11:07:54 +0100 | [diff] [blame] | 941 | if (dsp_img_info->version == |
| 942 | requested_version) { |
Rashika Kheria | 36f955bf06 | 2013-10-27 19:50:45 +0530 | [diff] [blame] | 943 | correct_version = true; |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 944 | DEBUG |
| 945 | ("FT1000:download: correct_version is TRUE\n"); |
| 946 | s_file = |
| 947 | (u16 *) (pFileStart |
| 948 | + |
| 949 | dsp_img_info-> |
| 950 | begin_offset); |
| 951 | c_file = |
| 952 | (u8 *) (pFileStart + |
| 953 | dsp_img_info-> |
| 954 | begin_offset); |
| 955 | code_end = |
| 956 | (u8 *) (pFileStart + |
| 957 | dsp_img_info-> |
| 958 | end_offset); |
| 959 | run_address = |
| 960 | dsp_img_info-> |
| 961 | run_address; |
| 962 | run_size = |
| 963 | dsp_img_info-> |
| 964 | image_size; |
| 965 | image_chksum = |
| 966 | (u32) dsp_img_info-> |
| 967 | checksum; |
| 968 | break; |
| 969 | } |
| 970 | dsp_img_info++; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 971 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 972 | } //end of for |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 973 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 974 | if (!correct_version) { |
| 975 | /* |
| 976 | * Error, beyond boot code range. |
| 977 | */ |
| 978 | DEBUG |
| 979 | ("FT1000:download:Download error: Bad Version Request = 0x%x.\n", |
| 980 | (int)requested_version); |
| 981 | status = STATUS_FAILURE; |
| 982 | break; |
| 983 | } |
| 984 | break; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 985 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 986 | default: |
| 987 | DEBUG |
| 988 | ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n", |
| 989 | request); |
| 990 | status = STATUS_FAILURE; |
| 991 | break; |
| 992 | } |
Ondrej Zary | 3aa2303 | 2012-12-02 12:30:19 +0100 | [diff] [blame] | 993 | if (ft1000dev->usbboot) |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 994 | put_handshake_usb(ft1000dev, |
| 995 | HANDSHAKE_RESPONSE); |
| 996 | else |
| 997 | put_handshake(ft1000dev, |
| 998 | HANDSHAKE_RESPONSE); |
| 999 | } else { |
| 1000 | DEBUG |
| 1001 | ("FT1000:download:Download error: Handshake failed\n"); |
| 1002 | status = STATUS_FAILURE; |
| 1003 | } |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 1004 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1005 | break; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 1006 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1007 | case STATE_DONE_DWNLD: |
| 1008 | DEBUG("FT1000:download:Code loader is done...\n"); |
| 1009 | state = STATE_SECTION_PROV; |
| 1010 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1011 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1012 | case STATE_SECTION_PROV: |
| 1013 | DEBUG("FT1000:download:STATE_SECTION_PROV\n"); |
| 1014 | pseudo_header = (struct pseudo_hdr *)c_file; |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 1015 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1016 | if (pseudo_header->checksum == |
| 1017 | hdr_checksum(pseudo_header)) { |
| 1018 | if (pseudo_header->portdest != |
Kelley Nielsen | 6f5519f | 2013-10-12 10:28:50 -0700 | [diff] [blame] | 1019 | 0x80 /* Dsp OAM */) { |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1020 | state = STATE_DONE_PROV; |
| 1021 | break; |
| 1022 | } |
| 1023 | pseudo_header_len = ntohs(pseudo_header->length); /* Byte length for PROV records */ |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1024 | |
Kelley Nielsen | 0c5e802 | 2013-10-12 08:32:46 -0700 | [diff] [blame] | 1025 | /* Get buffer for provisioning data */ |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1026 | pbuffer = |
| 1027 | kmalloc((pseudo_header_len + |
| 1028 | sizeof(struct pseudo_hdr)), |
| 1029 | GFP_ATOMIC); |
| 1030 | if (pbuffer) { |
| 1031 | memcpy(pbuffer, (void *)c_file, |
| 1032 | (u32) (pseudo_header_len + |
| 1033 | sizeof(struct |
| 1034 | pseudo_hdr))); |
| 1035 | // link provisioning data |
| 1036 | pprov_record = |
| 1037 | kmalloc(sizeof(struct prov_record), |
| 1038 | GFP_ATOMIC); |
| 1039 | if (pprov_record) { |
| 1040 | pprov_record->pprov_data = |
| 1041 | pbuffer; |
| 1042 | list_add_tail(&pprov_record-> |
| 1043 | list, |
| 1044 | &pft1000info-> |
| 1045 | prov_list); |
| 1046 | // Move to next entry if available |
| 1047 | c_file = |
| 1048 | (u8 *) ((unsigned long) |
| 1049 | c_file + |
| 1050 | (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr)); |
| 1051 | if ((unsigned long)(c_file) - |
| 1052 | (unsigned long)(pFileStart) |
| 1053 | >= |
| 1054 | (unsigned long)FileLength) { |
| 1055 | state = STATE_DONE_FILE; |
| 1056 | } |
| 1057 | } else { |
| 1058 | kfree(pbuffer); |
| 1059 | status = STATUS_FAILURE; |
| 1060 | } |
| 1061 | } else { |
| 1062 | status = STATUS_FAILURE; |
| 1063 | } |
| 1064 | } else { |
| 1065 | /* Checksum did not compute */ |
| 1066 | status = STATUS_FAILURE; |
| 1067 | } |
| 1068 | DEBUG |
| 1069 | ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n", |
| 1070 | state, status); |
| 1071 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1072 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1073 | case STATE_DONE_PROV: |
| 1074 | DEBUG("FT1000:download:STATE_DONE_PROV\n"); |
| 1075 | state = STATE_DONE_FILE; |
| 1076 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1077 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1078 | default: |
| 1079 | status = STATUS_FAILURE; |
| 1080 | break; |
| 1081 | } /* End Switch */ |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 1082 | |
Kelley Nielsen | cfd9d1f | 2013-10-12 08:37:53 -0700 | [diff] [blame] | 1083 | if (status != STATUS_SUCCESS) |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1084 | break; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1085 | |
| 1086 | /**** |
| 1087 | // Check if Card is present |
Marek Belisko | 0ce72ea | 2010-12-14 14:02:54 +0100 | [diff] [blame] | 1088 | status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK); |
| 1089 | if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) { |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1090 | break; |
| 1091 | } |
| 1092 | |
Marek Belisko | 0ce72ea | 2010-12-14 14:02:54 +0100 | [diff] [blame] | 1093 | status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID); |
| 1094 | if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) { |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1095 | break; |
| 1096 | } |
| 1097 | ****/ |
| 1098 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1099 | } /* End while */ |
Greg Kroah-Hartman | bf3146c | 2010-09-22 08:34:49 -0700 | [diff] [blame] | 1100 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1101 | DEBUG("Download exiting with status = 0x%8x\n", status); |
| 1102 | ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, |
| 1103 | FT1000_REG_DOORBELL); |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1104 | |
Marek Belisko | 6f953fb | 2011-02-03 11:07:51 +0100 | [diff] [blame] | 1105 | return status; |
Marek Belisko | f7c1be0 | 2010-09-22 07:56:27 +0200 | [diff] [blame] | 1106 | } |
| 1107 | |