root/drivers/staging/uwb/i1480/dfu/mac.c

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

DEFINITIONS

This source file includes following definitions.
  1. fw_hdrs_free
  2. fw_hdr_load
  3. fw_hdrs_load
  4. i1480_fw_cmp
  5. mac_fw_hdrs_push
  6. mac_fw_upload_enable
  7. mac_fw_upload_disable
  8. __mac_fw_upload
  9. i1480_pre_fw_upload
  10. i1480_cmd_reset
  11. i1480_fw_is_running_q
  12. i1480_mac_fw_upload

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Intel Wireless UWB Link 1480
   4  * MAC Firmware upload implementation
   5  *
   6  * Copyright (C) 2005-2006 Intel Corporation
   7  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
   8  *
   9  * Implementation of the code for parsing the firmware file (extract
  10  * the headers and binary code chunks) in the fw_*() functions. The
  11  * code to upload pre and mac firmwares is the same, so it uses a
  12  * common entry point in __mac_fw_upload(), which uses the i1480
  13  * function pointers to push the firmware to the device.
  14  */
  15 #include <linux/delay.h>
  16 #include <linux/firmware.h>
  17 #include <linux/slab.h>
  18 #include "../../uwb.h"
  19 #include "i1480-dfu.h"
  20 
  21 /*
  22  * Descriptor for a continuous segment of MAC fw data
  23  */
  24 struct fw_hdr {
  25         unsigned long address;
  26         size_t length;
  27         const u32 *bin;
  28         struct fw_hdr *next;
  29 };
  30 
  31 
  32 /* Free a chain of firmware headers */
  33 static
  34 void fw_hdrs_free(struct fw_hdr *hdr)
  35 {
  36         struct fw_hdr *next;
  37 
  38         while (hdr) {
  39                 next = hdr->next;
  40                 kfree(hdr);
  41                 hdr = next;
  42         }
  43 }
  44 
  45 
  46 /* Fill a firmware header descriptor from a memory buffer */
  47 static
  48 int fw_hdr_load(struct i1480 *i1480, struct fw_hdr *hdr, unsigned hdr_cnt,
  49                 const char *_data, const u32 *data_itr, const u32 *data_top)
  50 {
  51         size_t hdr_offset =  (const char *) data_itr - _data;
  52         size_t remaining_size = (void *) data_top - (void *) data_itr;
  53         if (data_itr + 2 > data_top) {
  54                 dev_err(i1480->dev, "fw hdr #%u/%zu: EOF reached in header at "
  55                        "offset %zu, limit %zu\n",
  56                        hdr_cnt, hdr_offset,
  57                        (const char *) data_itr + 2 - _data,
  58                        (const char *) data_top - _data);
  59                 return -EINVAL;
  60         }
  61         hdr->next = NULL;
  62         hdr->address = le32_to_cpu(*data_itr++);
  63         hdr->length = le32_to_cpu(*data_itr++);
  64         hdr->bin = data_itr;
  65         if (hdr->length > remaining_size) {
  66                 dev_err(i1480->dev, "fw hdr #%u/%zu: EOF reached in data; "
  67                        "chunk too long (%zu bytes), only %zu left\n",
  68                        hdr_cnt, hdr_offset, hdr->length, remaining_size);
  69                 return -EINVAL;
  70         }
  71         return 0;
  72 }
  73 
  74 
  75 /**
  76  * Get a buffer where the firmware is supposed to be and create a
  77  * chain of headers linking them together.
  78  *
  79  * @phdr: where to place the pointer to the first header (headers link
  80  *        to the next via the @hdr->next ptr); need to free the whole
  81  *        chain when done.
  82  *
  83  * @_data: Pointer to the data buffer.
  84  *
  85  * @_data_size: Size of the data buffer (bytes); data size has to be a
  86  *              multiple of 4. Function will fail if not.
  87  *
  88  * Goes over the whole binary blob; reads the first chunk and creates
  89  * a fw hdr from it (which points to where the data is in @_data and
  90  * the length of the chunk); then goes on to the next chunk until
  91  * done. Each header is linked to the next.
  92  */
  93 static
  94 int fw_hdrs_load(struct i1480 *i1480, struct fw_hdr **phdr,
  95                  const char *_data, size_t data_size)
  96 {
  97         int result;
  98         unsigned hdr_cnt = 0;
  99         u32 *data = (u32 *) _data, *data_itr, *data_top;
 100         struct fw_hdr *hdr, **prev_hdr = phdr;
 101 
 102         result = -EINVAL;
 103         /* Check size is ok and pointer is aligned */
 104         if (data_size % sizeof(u32) != 0)
 105                 goto error;
 106         if ((unsigned long) _data % sizeof(u16) != 0)
 107                 goto error;
 108         *phdr = NULL;
 109         data_itr = data;
 110         data_top = (u32 *) (_data + data_size);
 111         while (data_itr < data_top) {
 112                 result = -ENOMEM;
 113                 hdr = kmalloc(sizeof(*hdr), GFP_KERNEL);
 114                 if (hdr == NULL) {
 115                         dev_err(i1480->dev, "Cannot allocate fw header "
 116                                "for chunk #%u\n", hdr_cnt);
 117                         goto error_alloc;
 118                 }
 119                 result = fw_hdr_load(i1480, hdr, hdr_cnt,
 120                                      _data, data_itr, data_top);
 121                 if (result < 0)
 122                         goto error_load;
 123                 data_itr += 2 + hdr->length;
 124                 *prev_hdr = hdr;
 125                 prev_hdr = &hdr->next;
 126                 hdr_cnt++;
 127         };
 128         *prev_hdr = NULL;
 129         return 0;
 130 
 131 error_load:
 132         kfree(hdr);
 133 error_alloc:
 134         fw_hdrs_free(*phdr);
 135 error:
 136         return result;
 137 }
 138 
 139 
 140 /**
 141  * Compares a chunk of fw with one in the devices's memory
 142  *
 143  * @i1480:     Device instance
 144  * @hdr:     Pointer to the firmware chunk
 145  * @returns: 0 if equal, < 0 errno on error. If > 0, it is the offset
 146  *           where the difference was found (plus one).
 147  *
 148  * Kind of dirty and simplistic, but does the trick in both the PCI
 149  * and USB version. We do a quick[er] memcmp(), and if it fails, we do
 150  * a byte-by-byte to find the offset.
 151  */
 152 static
 153 ssize_t i1480_fw_cmp(struct i1480 *i1480, struct fw_hdr *hdr)
 154 {
 155         ssize_t result = 0;
 156         u32 src_itr = 0, cnt;
 157         size_t size = hdr->length*sizeof(hdr->bin[0]);
 158         size_t chunk_size;
 159         u8 *bin = (u8 *) hdr->bin;
 160 
 161         while (size > 0) {
 162                 chunk_size = size < i1480->buf_size ? size : i1480->buf_size;
 163                 result = i1480->read(i1480, hdr->address + src_itr, chunk_size);
 164                 if (result < 0) {
 165                         dev_err(i1480->dev, "error reading for verification: "
 166                                 "%zd\n", result);
 167                         goto error;
 168                 }
 169                 if (memcmp(i1480->cmd_buf, bin + src_itr, result)) {
 170                         u8 *buf = i1480->cmd_buf;
 171                         for (cnt = 0; cnt < result; cnt++)
 172                                 if (bin[src_itr + cnt] != buf[cnt]) {
 173                                         dev_err(i1480->dev, "byte failed at "
 174                                                 "src_itr %u cnt %u [0x%02x "
 175                                                 "vs 0x%02x]\n", src_itr, cnt,
 176                                                 bin[src_itr + cnt], buf[cnt]);
 177                                         result = src_itr + cnt + 1;
 178                                         goto cmp_failed;
 179                                 }
 180                 }
 181                 src_itr += result;
 182                 size -= result;
 183         }
 184         result = 0;
 185 error:
 186 cmp_failed:
 187         return result;
 188 }
 189 
 190 
 191 /**
 192  * Writes firmware headers to the device.
 193  *
 194  * @prd:     PRD instance
 195  * @hdr:     Processed firmware
 196  * @returns: 0 if ok, < 0 errno on error.
 197  */
 198 static
 199 int mac_fw_hdrs_push(struct i1480 *i1480, struct fw_hdr *hdr,
 200                      const char *fw_name, const char *fw_tag)
 201 {
 202         struct device *dev = i1480->dev;
 203         ssize_t result = 0;
 204         struct fw_hdr *hdr_itr;
 205         int verif_retry_count;
 206 
 207         /* Now, header by header, push them to the hw */
 208         for (hdr_itr = hdr; hdr_itr != NULL; hdr_itr = hdr_itr->next) {
 209                 verif_retry_count = 0;
 210 retry:
 211                 dev_dbg(dev, "fw chunk (%zu @ 0x%08lx)\n",
 212                         hdr_itr->length * sizeof(hdr_itr->bin[0]),
 213                         hdr_itr->address);
 214                 result = i1480->write(i1480, hdr_itr->address, hdr_itr->bin,
 215                                     hdr_itr->length*sizeof(hdr_itr->bin[0]));
 216                 if (result < 0) {
 217                         dev_err(dev, "%s fw '%s': write failed (%zuB @ 0x%lx):"
 218                                 " %zd\n", fw_tag, fw_name,
 219                                 hdr_itr->length * sizeof(hdr_itr->bin[0]),
 220                                 hdr_itr->address, result);
 221                         break;
 222                 }
 223                 result = i1480_fw_cmp(i1480, hdr_itr);
 224                 if (result < 0) {
 225                         dev_err(dev, "%s fw '%s': verification read "
 226                                 "failed (%zuB @ 0x%lx): %zd\n",
 227                                 fw_tag, fw_name,
 228                                 hdr_itr->length * sizeof(hdr_itr->bin[0]),
 229                                 hdr_itr->address, result);
 230                         break;
 231                 }
 232                 if (result > 0) {       /* Offset where it failed + 1 */
 233                         result--;
 234                         dev_err(dev, "%s fw '%s': WARNING: verification "
 235                                 "failed at 0x%lx: retrying\n",
 236                                 fw_tag, fw_name, hdr_itr->address + result);
 237                         if (++verif_retry_count < 3)
 238                                 goto retry;     /* write this block again! */
 239                         dev_err(dev, "%s fw '%s': verification failed at 0x%lx: "
 240                                 "tried %d times\n", fw_tag, fw_name,
 241                                 hdr_itr->address + result, verif_retry_count);
 242                         result = -EINVAL;
 243                         break;
 244                 }
 245         }
 246         return result;
 247 }
 248 
 249 
 250 /** Puts the device in firmware upload mode.*/
 251 static
 252 int mac_fw_upload_enable(struct i1480 *i1480)
 253 {
 254         int result;
 255         u32 reg = 0x800000c0;
 256         u32 *buffer = (u32 *)i1480->cmd_buf;
 257 
 258         if (i1480->hw_rev > 1)
 259                 reg = 0x8000d0d4;
 260         result = i1480->read(i1480, reg, sizeof(u32));
 261         if (result < 0)
 262                 goto error_cmd;
 263         *buffer &= ~i1480_FW_UPLOAD_MODE_MASK;
 264         result = i1480->write(i1480, reg, buffer, sizeof(u32));
 265         if (result < 0)
 266                 goto error_cmd;
 267         return 0;
 268 error_cmd:
 269         dev_err(i1480->dev, "can't enable fw upload mode: %d\n", result);
 270         return result;
 271 }
 272 
 273 
 274 /** Gets the device out of firmware upload mode. */
 275 static
 276 int mac_fw_upload_disable(struct i1480 *i1480)
 277 {
 278         int result;
 279         u32 reg = 0x800000c0;
 280         u32 *buffer = (u32 *)i1480->cmd_buf;
 281 
 282         if (i1480->hw_rev > 1)
 283                 reg = 0x8000d0d4;
 284         result = i1480->read(i1480, reg, sizeof(u32));
 285         if (result < 0)
 286                 goto error_cmd;
 287         *buffer |= i1480_FW_UPLOAD_MODE_MASK;
 288         result = i1480->write(i1480, reg, buffer, sizeof(u32));
 289         if (result < 0)
 290                 goto error_cmd;
 291         return 0;
 292 error_cmd:
 293         dev_err(i1480->dev, "can't disable fw upload mode: %d\n", result);
 294         return result;
 295 }
 296 
 297 
 298 
 299 /**
 300  * Generic function for uploading a MAC firmware.
 301  *
 302  * @i1480:     Device instance
 303  * @fw_name: Name of firmware file to upload.
 304  * @fw_tag:  Name of the firmware type (for messages)
 305  *           [eg: MAC, PRE]
 306  * @do_wait: Wait for device to emit initialization done message (0
 307  *           for PRE fws, 1 for MAC fws).
 308  * @returns: 0 if ok, < 0 errno on error.
 309  */
 310 static
 311 int __mac_fw_upload(struct i1480 *i1480, const char *fw_name,
 312                     const char *fw_tag)
 313 {
 314         int result;
 315         const struct firmware *fw;
 316         struct fw_hdr *fw_hdrs;
 317 
 318         result = request_firmware(&fw, fw_name, i1480->dev);
 319         if (result < 0) /* Up to caller to complain on -ENOENT */
 320                 goto out;
 321         result = fw_hdrs_load(i1480, &fw_hdrs, fw->data, fw->size);
 322         if (result < 0) {
 323                 dev_err(i1480->dev, "%s fw '%s': failed to parse firmware "
 324                         "file: %d\n", fw_tag, fw_name, result);
 325                 goto out_release;
 326         }
 327         result = mac_fw_upload_enable(i1480);
 328         if (result < 0)
 329                 goto out_hdrs_release;
 330         result = mac_fw_hdrs_push(i1480, fw_hdrs, fw_name, fw_tag);
 331         mac_fw_upload_disable(i1480);
 332 out_hdrs_release:
 333         if (result >= 0)
 334                 dev_info(i1480->dev, "%s fw '%s': uploaded\n", fw_tag, fw_name);
 335         else
 336                 dev_err(i1480->dev, "%s fw '%s': failed to upload (%d), "
 337                         "power cycle device\n", fw_tag, fw_name, result);
 338         fw_hdrs_free(fw_hdrs);
 339 out_release:
 340         release_firmware(fw);
 341 out:
 342         return result;
 343 }
 344 
 345 
 346 /**
 347  * Upload a pre-PHY firmware
 348  *
 349  */
 350 int i1480_pre_fw_upload(struct i1480 *i1480)
 351 {
 352         int result;
 353         result = __mac_fw_upload(i1480, i1480->pre_fw_name, "PRE");
 354         if (result == 0)
 355                 msleep(400);
 356         return result;
 357 }
 358 
 359 
 360 /**
 361  * Reset a the MAC and PHY
 362  *
 363  * @i1480:     Device's instance
 364  * @returns: 0 if ok, < 0 errno code on error
 365  *
 366  * We put the command on kmalloc'ed memory as some arches cannot do
 367  * USB from the stack. The reply event is copied from an stage buffer,
 368  * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details.
 369  *
 370  * We issue the reset to make sure the UWB controller reinits the PHY;
 371  * this way we can now if the PHY init went ok.
 372  */
 373 static
 374 int i1480_cmd_reset(struct i1480 *i1480)
 375 {
 376         int result;
 377         struct uwb_rccb *cmd = (void *) i1480->cmd_buf;
 378         struct i1480_evt_reset {
 379                 struct uwb_rceb rceb;
 380                 u8 bResultCode;
 381         } __attribute__((packed)) *reply = (void *) i1480->evt_buf;
 382 
 383         result = -ENOMEM;
 384         cmd->bCommandType = UWB_RC_CET_GENERAL;
 385         cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET);
 386         reply->rceb.bEventType = UWB_RC_CET_GENERAL;
 387         reply->rceb.wEvent = UWB_RC_CMD_RESET;
 388         result = i1480_cmd(i1480, "RESET", sizeof(*cmd), sizeof(*reply));
 389         if (result < 0)
 390                 goto out;
 391         if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
 392                 dev_err(i1480->dev, "RESET: command execution failed: %u\n",
 393                         reply->bResultCode);
 394                 result = -EIO;
 395         }
 396 out:
 397         return result;
 398 
 399 }
 400 
 401 
 402 /* Wait for the MAC FW to start running */
 403 static
 404 int i1480_fw_is_running_q(struct i1480 *i1480)
 405 {
 406         int cnt = 0;
 407         int result;
 408         u32 *val = (u32 *) i1480->cmd_buf;
 409 
 410         for (cnt = 0; cnt < 10; cnt++) {
 411                 msleep(100);
 412                 result = i1480->read(i1480, 0x80080000, 4);
 413                 if (result < 0) {
 414                         dev_err(i1480->dev, "Can't read 0x8008000: %d\n", result);
 415                         goto out;
 416                 }
 417                 if (*val == 0x55555555UL)       /* fw running? cool */
 418                         goto out;
 419         }
 420         dev_err(i1480->dev, "Timed out waiting for fw to start\n");
 421         result = -ETIMEDOUT;
 422 out:
 423         return result;
 424 
 425 }
 426 
 427 
 428 /**
 429  * Upload MAC firmware, wait for it to start
 430  *
 431  * @i1480:     Device instance
 432  * @fw_name: Name of the file that contains the firmware
 433  *
 434  * This has to be called after the pre fw has been uploaded (if
 435  * there is any).
 436  */
 437 int i1480_mac_fw_upload(struct i1480 *i1480)
 438 {
 439         int result = 0, deprecated_name = 0;
 440         struct i1480_rceb *rcebe = (void *) i1480->evt_buf;
 441 
 442         result = __mac_fw_upload(i1480, i1480->mac_fw_name, "MAC");
 443         if (result == -ENOENT) {
 444                 result = __mac_fw_upload(i1480, i1480->mac_fw_name_deprecate,
 445                                          "MAC");
 446                 deprecated_name = 1;
 447         }
 448         if (result < 0)
 449                 return result;
 450         if (deprecated_name == 1)
 451                 dev_warn(i1480->dev,
 452                          "WARNING: firmware file name %s is deprecated, "
 453                          "please rename to %s\n",
 454                          i1480->mac_fw_name_deprecate, i1480->mac_fw_name);
 455         result = i1480_fw_is_running_q(i1480);
 456         if (result < 0)
 457                 goto error_fw_not_running;
 458         result = i1480->rc_setup ? i1480->rc_setup(i1480) : 0;
 459         if (result < 0) {
 460                 dev_err(i1480->dev, "Cannot setup after MAC fw upload: %d\n",
 461                         result);
 462                 goto error_setup;
 463         }
 464         result = i1480->wait_init_done(i1480);  /* wait init'on */
 465         if (result < 0) {
 466                 dev_err(i1480->dev, "MAC fw '%s': Initialization timed out "
 467                         "(%d)\n", i1480->mac_fw_name, result);
 468                 goto error_init_timeout;
 469         }
 470         /* verify we got the right initialization done event */
 471         if (i1480->evt_result != sizeof(*rcebe)) {
 472                 dev_err(i1480->dev, "MAC fw '%s': initialization event returns "
 473                         "wrong size (%zu bytes vs %zu needed)\n",
 474                         i1480->mac_fw_name, i1480->evt_result, sizeof(*rcebe));
 475                 goto error_size;
 476         }
 477         result = -EIO;
 478         if (i1480_rceb_check(i1480, &rcebe->rceb, NULL, 0, i1480_CET_VS1,
 479                              i1480_EVT_RM_INIT_DONE) < 0) {
 480                 dev_err(i1480->dev, "wrong initialization event 0x%02x/%04x/%02x "
 481                         "received; expected 0x%02x/%04x/00\n",
 482                         rcebe->rceb.bEventType, le16_to_cpu(rcebe->rceb.wEvent),
 483                         rcebe->rceb.bEventContext, i1480_CET_VS1,
 484                         i1480_EVT_RM_INIT_DONE);
 485                 goto error_init_timeout;
 486         }
 487         result = i1480_cmd_reset(i1480);
 488         if (result < 0)
 489                 dev_err(i1480->dev, "MAC fw '%s': MBOA reset failed (%d)\n",
 490                         i1480->mac_fw_name, result);
 491 error_fw_not_running:
 492 error_init_timeout:
 493 error_size:
 494 error_setup:
 495         return result;
 496 }

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