1/* 2 * i1480 Device Firmware Upload 3 * 4 * Copyright (C) 2005-2006 Intel Corporation 5 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 9 * 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 * 02110-1301, USA. 20 * 21 * 22 * This driver is the firmware uploader for the Intel Wireless UWB 23 * Link 1480 device (both in the USB and PCI incarnations). 24 * 25 * The process is quite simple: we stop the device, write the firmware 26 * to its memory and then restart it. Wait for the device to let us 27 * know it is done booting firmware. Ready. 28 * 29 * We might have to upload before or after a phy firmware (which might 30 * be done in two methods, using a normal firmware image or through 31 * the MPI port). 32 * 33 * Because USB and PCI use common methods, we just make ops out of the 34 * common operations (read, write, wait_init_done and cmd) and 35 * implement them in usb.c and pci.c. 36 * 37 * The flow is (some parts omitted): 38 * 39 * i1480_{usb,pci}_probe() On enumerate/discovery 40 * i1480_fw_upload() 41 * i1480_pre_fw_upload() 42 * __mac_fw_upload() 43 * fw_hdrs_load() 44 * mac_fw_hdrs_push() 45 * i1480->write() [i1480_{usb,pci}_write()] 46 * i1480_fw_cmp() 47 * i1480->read() [i1480_{usb,pci}_read()] 48 * i1480_mac_fw_upload() 49 * __mac_fw_upload() 50 * i1480->setup(() 51 * i1480->wait_init_done() 52 * i1480_cmd_reset() 53 * i1480->cmd() [i1480_{usb,pci}_cmd()] 54 * ... 55 * i1480_phy_fw_upload() 56 * request_firmware() 57 * i1480_mpi_write() 58 * i1480->cmd() [i1480_{usb,pci}_cmd()] 59 * 60 * Once the probe function enumerates the device and uploads the 61 * firmware, we just exit with -ENODEV, as we don't really want to 62 * attach to the device. 63 */ 64#ifndef __i1480_DFU_H__ 65#define __i1480_DFU_H__ 66 67#include <linux/uwb/spec.h> 68#include <linux/types.h> 69#include <linux/completion.h> 70 71#define i1480_FW_UPLOAD_MODE_MASK (cpu_to_le32(0x00000018)) 72 73#if i1480_FW > 0x00000302 74#define i1480_RCEB_EXTENDED 75#endif 76 77struct uwb_rccb; 78struct uwb_rceb; 79 80/* 81 * Common firmware upload handlers 82 * 83 * Normally you embed this struct in another one specific to your hw. 84 * 85 * @write Write to device's memory from buffer. 86 * @read Read from device's memory to i1480->evt_buf. 87 * @setup Setup device after basic firmware is uploaded 88 * @wait_init_done 89 * Wait for the device to send a notification saying init 90 * is done. 91 * @cmd FOP for issuing the command to the hardware. The 92 * command data is contained in i1480->cmd_buf and the size 93 * is supplied as an argument. The command replied is put 94 * in i1480->evt_buf and the size in i1480->evt_result (or if 95 * an error, a < 0 errno code). 96 * 97 * @cmd_buf Memory buffer used to send commands to the device. 98 * Allocated by the upper layers i1480_fw_upload(). 99 * Size has to be @buf_size. 100 * @evt_buf Memory buffer used to place the async notifications 101 * received by the hw. Allocated by the upper layers 102 * i1480_fw_upload(). 103 * Size has to be @buf_size. 104 * @cmd_complete 105 * Low level driver uses this to notify code waiting afor 106 * an event that the event has arrived and data is in 107 * i1480->evt_buf (and size/result in i1480->evt_result). 108 * @hw_rev 109 * Use this value to activate dfu code to support new revisions 110 * of hardware. i1480_init() sets this to a default value. 111 * It should be updated by the USB and PCI code. 112 */ 113struct i1480 { 114 struct device *dev; 115 116 int (*write)(struct i1480 *, u32 addr, const void *, size_t); 117 int (*read)(struct i1480 *, u32 addr, size_t); 118 int (*rc_setup)(struct i1480 *); 119 void (*rc_release)(struct i1480 *); 120 int (*wait_init_done)(struct i1480 *); 121 int (*cmd)(struct i1480 *, const char *cmd_name, size_t cmd_size); 122 const char *pre_fw_name; 123 const char *mac_fw_name; 124 const char *mac_fw_name_deprecate; 125 const char *phy_fw_name; 126 u8 hw_rev; 127 128 size_t buf_size; /* size of both evt_buf and cmd_buf */ 129 void *evt_buf, *cmd_buf; 130 ssize_t evt_result; 131 struct completion evt_complete; 132}; 133 134static inline 135void i1480_init(struct i1480 *i1480) 136{ 137 i1480->hw_rev = 1; 138 init_completion(&i1480->evt_complete); 139} 140 141extern int i1480_fw_upload(struct i1480 *); 142extern int i1480_pre_fw_upload(struct i1480 *); 143extern int i1480_mac_fw_upload(struct i1480 *); 144extern int i1480_phy_fw_upload(struct i1480 *); 145extern ssize_t i1480_cmd(struct i1480 *, const char *, size_t, size_t); 146extern int i1480_rceb_check(const struct i1480 *, 147 const struct uwb_rceb *, const char *, u8, 148 u8, unsigned); 149 150enum { 151 /* Vendor specific command type */ 152 i1480_CET_VS1 = 0xfd, 153 /* i1480 commands */ 154 i1480_CMD_SET_IP_MAS = 0x000e, 155 i1480_CMD_GET_MAC_PHY_INFO = 0x0003, 156 i1480_CMD_MPI_WRITE = 0x000f, 157 i1480_CMD_MPI_READ = 0x0010, 158 /* i1480 events */ 159#if i1480_FW > 0x00000302 160 i1480_EVT_CONFIRM = 0x0002, 161 i1480_EVT_RM_INIT_DONE = 0x0101, 162 i1480_EVT_DEV_ADD = 0x0103, 163 i1480_EVT_DEV_RM = 0x0104, 164 i1480_EVT_DEV_ID_CHANGE = 0x0105, 165 i1480_EVT_GET_MAC_PHY_INFO = i1480_CMD_GET_MAC_PHY_INFO, 166#else 167 i1480_EVT_CONFIRM = 0x0002, 168 i1480_EVT_RM_INIT_DONE = 0x0101, 169 i1480_EVT_DEV_ADD = 0x0103, 170 i1480_EVT_DEV_RM = 0x0104, 171 i1480_EVT_DEV_ID_CHANGE = 0x0105, 172 i1480_EVT_GET_MAC_PHY_INFO = i1480_EVT_CONFIRM, 173#endif 174}; 175 176 177struct i1480_evt_confirm { 178 struct uwb_rceb rceb; 179#ifdef i1480_RCEB_EXTENDED 180 __le16 wParamLength; 181#endif 182 u8 bResultCode; 183} __attribute__((packed)); 184 185 186struct i1480_rceb { 187 struct uwb_rceb rceb; 188#ifdef i1480_RCEB_EXTENDED 189 __le16 wParamLength; 190#endif 191} __attribute__((packed)); 192 193 194/** 195 * Get MAC & PHY Information confirm event structure 196 * 197 * Confirm event returned by the command. 198 */ 199struct i1480_evt_confirm_GMPI { 200#if i1480_FW > 0x00000302 201 struct uwb_rceb rceb; 202 __le16 wParamLength; 203 __le16 status; 204 u8 mac_addr[6]; /* EUI-64 bit IEEE address [still 8 bytes?] */ 205 u8 dev_addr[2]; 206 __le16 mac_fw_rev; /* major = v >> 8; minor = v & 0xff */ 207 u8 hw_rev; 208 u8 phy_vendor; 209 u8 phy_rev; /* major v = >> 8; minor = v & 0xff */ 210 __le16 mac_caps; 211 u8 phy_caps[3]; 212 u8 key_stores; 213 __le16 mcast_addr_stores; 214 u8 sec_mode_supported; 215#else 216 struct uwb_rceb rceb; 217 u8 status; 218 u8 mac_addr[8]; /* EUI-64 bit IEEE address [still 8 bytes?] */ 219 u8 dev_addr[2]; 220 __le16 mac_fw_rev; /* major = v >> 8; minor = v & 0xff */ 221 __le16 phy_fw_rev; /* major v = >> 8; minor = v & 0xff */ 222 __le16 mac_caps; 223 u8 phy_caps; 224 u8 key_stores; 225 __le16 mcast_addr_stores; 226 u8 sec_mode_supported; 227#endif 228} __attribute__((packed)); 229 230 231struct i1480_cmd_mpi_write { 232 struct uwb_rccb rccb; 233 __le16 size; 234 u8 data[]; 235}; 236 237 238struct i1480_cmd_mpi_read { 239 struct uwb_rccb rccb; 240 __le16 size; 241 struct { 242 u8 page, offset; 243 } __attribute__((packed)) data[]; 244} __attribute__((packed)); 245 246 247struct i1480_evt_mpi_read { 248 struct uwb_rceb rceb; 249#ifdef i1480_RCEB_EXTENDED 250 __le16 wParamLength; 251#endif 252 u8 bResultCode; 253 __le16 size; 254 struct { 255 u8 page, offset, value; 256 } __attribute__((packed)) data[]; 257} __attribute__((packed)); 258 259 260#endif /* #ifndef __i1480_DFU_H__ */ 261