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

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

DEFINITIONS

This source file includes following definitions.
  1. i1480_mpi_write
  2. i1480_mpi_read
  3. i1480_phy_fw_upload

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Intel Wireless UWB Link 1480
   4  * PHY parameters upload
   5  *
   6  * Copyright (C) 2005-2006 Intel Corporation
   7  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
   8  *
   9  * Code for uploading the PHY parameters to the PHY through the UWB
  10  * Radio Control interface.
  11  *
  12  * We just send the data through the MPI interface using HWA-like
  13  * commands and then reset the PHY to make sure it is ok.
  14  */
  15 #include <linux/delay.h>
  16 #include <linux/device.h>
  17 #include <linux/firmware.h>
  18 #include "../../../wusbcore/include/wusb.h"
  19 #include "i1480-dfu.h"
  20 
  21 
  22 /**
  23  * Write a value array to an address of the MPI interface
  24  *
  25  * @i1480:      Device descriptor
  26  * @data:       Data array to write
  27  * @size:       Size of the data array
  28  * @returns:    0 if ok, < 0 errno code on error.
  29  *
  30  * The data array is organized into pairs:
  31  *
  32  * ADDRESS VALUE
  33  *
  34  * ADDRESS is BE 16 bit unsigned, VALUE 8 bit unsigned. Size thus has
  35  * to be a multiple of three.
  36  */
  37 static
  38 int i1480_mpi_write(struct i1480 *i1480, const void *data, size_t size)
  39 {
  40         int result;
  41         struct i1480_cmd_mpi_write *cmd = i1480->cmd_buf;
  42         struct i1480_evt_confirm *reply = i1480->evt_buf;
  43 
  44         BUG_ON(size > 480);
  45         result = -ENOMEM;
  46         cmd->rccb.bCommandType = i1480_CET_VS1;
  47         cmd->rccb.wCommand = cpu_to_le16(i1480_CMD_MPI_WRITE);
  48         cmd->size = cpu_to_le16(size);
  49         memcpy(cmd->data, data, size);
  50         reply->rceb.bEventType = i1480_CET_VS1;
  51         reply->rceb.wEvent = i1480_CMD_MPI_WRITE;
  52         result = i1480_cmd(i1480, "MPI-WRITE", sizeof(*cmd) + size, sizeof(*reply));
  53         if (result < 0)
  54                 goto out;
  55         if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
  56                 dev_err(i1480->dev, "MPI-WRITE: command execution failed: %d\n",
  57                         reply->bResultCode);
  58                 result = -EIO;
  59         }
  60 out:
  61         return result;
  62 }
  63 
  64 
  65 /**
  66  * Read a value array to from an address of the MPI interface
  67  *
  68  * @i1480:      Device descriptor
  69  * @data:       where to place the read array
  70  * @srcaddr:    Where to read from
  71  * @size:       Size of the data read array
  72  * @returns:    0 if ok, < 0 errno code on error.
  73  *
  74  * The command data array is organized into pairs ADDR0 ADDR1..., and
  75  * the returned data in ADDR0 VALUE0 ADDR1 VALUE1...
  76  *
  77  * We generate the command array to be a sequential read and then
  78  * rearrange the result.
  79  *
  80  * We use the i1480->cmd_buf for the command, i1480->evt_buf for the reply.
  81  *
  82  * As the reply has to fit in 512 bytes (i1480->evt_buffer), the max amount
  83  * of values we can read is (512 - sizeof(*reply)) / 3
  84  */
  85 static
  86 int i1480_mpi_read(struct i1480 *i1480, u8 *data, u16 srcaddr, size_t size)
  87 {
  88         int result;
  89         struct i1480_cmd_mpi_read *cmd = i1480->cmd_buf;
  90         struct i1480_evt_mpi_read *reply = i1480->evt_buf;
  91         unsigned cnt;
  92 
  93         memset(i1480->cmd_buf, 0x69, 512);
  94         memset(i1480->evt_buf, 0x69, 512);
  95 
  96         BUG_ON(size > (i1480->buf_size - sizeof(*reply)) / 3);
  97         result = -ENOMEM;
  98         cmd->rccb.bCommandType = i1480_CET_VS1;
  99         cmd->rccb.wCommand = cpu_to_le16(i1480_CMD_MPI_READ);
 100         cmd->size = cpu_to_le16(3*size);
 101         for (cnt = 0; cnt < size; cnt++) {
 102                 cmd->data[cnt].page = (srcaddr + cnt) >> 8;
 103                 cmd->data[cnt].offset = (srcaddr + cnt) & 0xff;
 104         }
 105         reply->rceb.bEventType = i1480_CET_VS1;
 106         reply->rceb.wEvent = i1480_CMD_MPI_READ;
 107         result = i1480_cmd(i1480, "MPI-READ", sizeof(*cmd) + 2*size,
 108                         sizeof(*reply) + 3*size);
 109         if (result < 0)
 110                 goto out;
 111         if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
 112                 dev_err(i1480->dev, "MPI-READ: command execution failed: %d\n",
 113                         reply->bResultCode);
 114                 result = -EIO;
 115                 goto out;
 116         }
 117         for (cnt = 0; cnt < size; cnt++) {
 118                 if (reply->data[cnt].page != (srcaddr + cnt) >> 8)
 119                         dev_err(i1480->dev, "MPI-READ: page inconsistency at "
 120                                 "index %u: expected 0x%02x, got 0x%02x\n", cnt,
 121                                 (srcaddr + cnt) >> 8, reply->data[cnt].page);
 122                 if (reply->data[cnt].offset != ((srcaddr + cnt) & 0x00ff))
 123                         dev_err(i1480->dev, "MPI-READ: offset inconsistency at "
 124                                 "index %u: expected 0x%02x, got 0x%02x\n", cnt,
 125                                 (srcaddr + cnt) & 0x00ff,
 126                                 reply->data[cnt].offset);
 127                 data[cnt] = reply->data[cnt].value;
 128         }
 129         result = 0;
 130 out:
 131         return result;
 132 }
 133 
 134 
 135 /**
 136  * Upload a PHY firmware, wait for it to start
 137  *
 138  * @i1480:     Device instance
 139  * @fw_name: Name of the file that contains the firmware
 140  *
 141  * We assume the MAC fw is up and running. This means we can use the
 142  * MPI interface to write the PHY firmware. Once done, we issue an
 143  * MBOA Reset, which will force the MAC to reset and reinitialize the
 144  * PHY. If that works, we are ready to go.
 145  *
 146  * Max packet size for the MPI write is 512, so the max buffer is 480
 147  * (which gives us 160 byte triads of MSB, LSB and VAL for the data).
 148  */
 149 int i1480_phy_fw_upload(struct i1480 *i1480)
 150 {
 151         int result;
 152         const struct firmware *fw;
 153         const char *data_itr, *data_top;
 154         const size_t MAX_BLK_SIZE = 480;        /* 160 triads */
 155         size_t data_size;
 156         u8 phy_stat;
 157 
 158         result = request_firmware(&fw, i1480->phy_fw_name, i1480->dev);
 159         if (result < 0)
 160                 goto out;
 161         /* Loop writing data in chunks as big as possible until done. */
 162         for (data_itr = fw->data, data_top = data_itr + fw->size;
 163              data_itr < data_top; data_itr += MAX_BLK_SIZE) {
 164                 data_size = min(MAX_BLK_SIZE, (size_t) (data_top - data_itr));
 165                 result = i1480_mpi_write(i1480, data_itr, data_size);
 166                 if (result < 0)
 167                         goto error_mpi_write;
 168         }
 169         /* Read MPI page 0, offset 6; if 0, PHY was initialized correctly. */
 170         result = i1480_mpi_read(i1480, &phy_stat, 0x0006, 1);
 171         if (result < 0) {
 172                 dev_err(i1480->dev, "PHY: can't get status: %d\n", result);
 173                 goto error_mpi_status;
 174         }
 175         if (phy_stat != 0) {
 176                 result = -ENODEV;
 177                 dev_info(i1480->dev, "error, PHY not ready: %u\n", phy_stat);
 178                 goto error_phy_status;
 179         }
 180         dev_info(i1480->dev, "PHY fw '%s': uploaded\n", i1480->phy_fw_name);
 181 error_phy_status:
 182 error_mpi_status:
 183 error_mpi_write:
 184         release_firmware(fw);
 185         if (result < 0)
 186                 dev_err(i1480->dev, "PHY fw '%s': failed to upload (%d), "
 187                         "power cycle device\n", i1480->phy_fw_name, result);
 188 out:
 189         return result;
 190 }

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