aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uwb/i1480/dfu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/uwb/i1480/dfu')
-rw-r--r--drivers/uwb/i1480/dfu/Makefile9
-rw-r--r--drivers/uwb/i1480/dfu/dfu.c217
-rw-r--r--drivers/uwb/i1480/dfu/i1480-dfu.h260
-rw-r--r--drivers/uwb/i1480/dfu/mac.c527
-rw-r--r--drivers/uwb/i1480/dfu/phy.c203
-rw-r--r--drivers/uwb/i1480/dfu/usb.c500
6 files changed, 1716 insertions, 0 deletions
diff --git a/drivers/uwb/i1480/dfu/Makefile b/drivers/uwb/i1480/dfu/Makefile
new file mode 100644
index 000000000000..bd1b9f25424c
--- /dev/null
+++ b/drivers/uwb/i1480/dfu/Makefile
@@ -0,0 +1,9 @@
1obj-$(CONFIG_UWB_I1480U) += i1480-dfu-usb.o
2
3i1480-dfu-usb-objs := \
4 dfu.o \
5 mac.o \
6 phy.o \
7 usb.o
8
9
diff --git a/drivers/uwb/i1480/dfu/dfu.c b/drivers/uwb/i1480/dfu/dfu.c
new file mode 100644
index 000000000000..9097b3b30385
--- /dev/null
+++ b/drivers/uwb/i1480/dfu/dfu.c
@@ -0,0 +1,217 @@
1/*
2 * Intel Wireless UWB Link 1480
3 * Main driver
4 *
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 *
23 * Common code for firmware upload used by the USB and PCI version;
24 * i1480_fw_upload() takes a device descriptor and uses the function
25 * pointers it provides to upload firmware and prepare the PHY.
26 *
27 * As well, provides common functions used by the rest of the code.
28 */
29#include "i1480-dfu.h"
30#include <linux/errno.h>
31#include <linux/delay.h>
32#include <linux/pci.h>
33#include <linux/device.h>
34#include <linux/uwb.h>
35#include <linux/random.h>
36
37#define D_LOCAL 0
38#include <linux/uwb/debug.h>
39
40/**
41 * i1480_rceb_check - Check RCEB for expected field values
42 * @i1480: pointer to device for which RCEB is being checked
43 * @rceb: RCEB being checked
44 * @cmd: which command the RCEB is related to
45 * @context: expected context
46 * @expected_type: expected event type
47 * @expected_event: expected event
48 *
49 * If @cmd is NULL, do not print error messages, but still return an error
50 * code.
51 *
52 * Return 0 if @rceb matches the expected values, -EINVAL otherwise.
53 */
54int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb,
55 const char *cmd, u8 context, u8 expected_type,
56 unsigned expected_event)
57{
58 int result = 0;
59 struct device *dev = i1480->dev;
60 if (rceb->bEventContext != context) {
61 if (cmd)
62 dev_err(dev, "%s: unexpected context id 0x%02x "
63 "(expected 0x%02x)\n", cmd,
64 rceb->bEventContext, context);
65 result = -EINVAL;
66 }
67 if (rceb->bEventType != expected_type) {
68 if (cmd)
69 dev_err(dev, "%s: unexpected event type 0x%02x "
70 "(expected 0x%02x)\n", cmd,
71 rceb->bEventType, expected_type);
72 result = -EINVAL;
73 }
74 if (le16_to_cpu(rceb->wEvent) != expected_event) {
75 if (cmd)
76 dev_err(dev, "%s: unexpected event 0x%04x "
77 "(expected 0x%04x)\n", cmd,
78 le16_to_cpu(rceb->wEvent), expected_event);
79 result = -EINVAL;
80 }
81 return result;
82}
83EXPORT_SYMBOL_GPL(i1480_rceb_check);
84
85
86/**
87 * Execute a Radio Control Command
88 *
89 * Command data has to be in i1480->cmd_buf.
90 *
91 * @returns size of the reply data filled in i1480->evt_buf or < 0 errno
92 * code on error.
93 */
94ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size,
95 size_t reply_size)
96{
97 ssize_t result;
98 struct uwb_rceb *reply = i1480->evt_buf;
99 struct uwb_rccb *cmd = i1480->cmd_buf;
100 u16 expected_event = reply->wEvent;
101 u8 expected_type = reply->bEventType;
102 u8 context;
103
104 d_fnstart(3, i1480->dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size);
105 init_completion(&i1480->evt_complete);
106 i1480->evt_result = -EINPROGRESS;
107 do {
108 get_random_bytes(&context, 1);
109 } while (context == 0x00 || context == 0xff);
110 cmd->bCommandContext = context;
111 result = i1480->cmd(i1480, cmd_name, cmd_size);
112 if (result < 0)
113 goto error;
114 /* wait for the callback to report a event was received */
115 result = wait_for_completion_interruptible_timeout(
116 &i1480->evt_complete, HZ);
117 if (result == 0) {
118 result = -ETIMEDOUT;
119 goto error;
120 }
121 if (result < 0)
122 goto error;
123 result = i1480->evt_result;
124 if (result < 0) {
125 dev_err(i1480->dev, "%s: command reply reception failed: %zd\n",
126 cmd_name, result);
127 goto error;
128 }
129 /*
130 * Firmware versions >= 1.4.12224 for IOGear GUWA100U generate a
131 * spurious notification after firmware is downloaded. So check whether
132 * the receibed RCEB is such notification before assuming that the
133 * command has failed.
134 */
135 if (i1480_rceb_check(i1480, i1480->evt_buf, NULL,
136 0, 0xfd, 0x0022) == 0) {
137 /* Now wait for the actual RCEB for this command. */
138 result = i1480->wait_init_done(i1480);
139 if (result < 0)
140 goto error;
141 result = i1480->evt_result;
142 }
143 if (result != reply_size) {
144 dev_err(i1480->dev, "%s returned only %zu bytes, %zu expected\n",
145 cmd_name, result, reply_size);
146 result = -EINVAL;
147 goto error;
148 }
149 /* Verify we got the right event in response */
150 result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context,
151 expected_type, expected_event);
152error:
153 d_fnend(3, i1480->dev, "(%p, %s, %zu) = %zd\n",
154 i1480, cmd_name, cmd_size, result);
155 return result;
156}
157EXPORT_SYMBOL_GPL(i1480_cmd);
158
159
160static
161int i1480_print_state(struct i1480 *i1480)
162{
163 int result;
164 u32 *buf = (u32 *) i1480->cmd_buf;
165
166 result = i1480->read(i1480, 0x80080000, 2 * sizeof(*buf));
167 if (result < 0) {
168 dev_err(i1480->dev, "cannot read U & L states: %d\n", result);
169 goto error;
170 }
171 dev_info(i1480->dev, "state U 0x%08x, L 0x%08x\n", buf[0], buf[1]);
172error:
173 return result;
174}
175
176
177/*
178 * PCI probe, firmware uploader
179 *
180 * _mac_fw_upload() will call rc_setup(), which needs an rc_release().
181 */
182int i1480_fw_upload(struct i1480 *i1480)
183{
184 int result;
185
186 result = i1480_pre_fw_upload(i1480); /* PHY pre fw */
187 if (result < 0 && result != -ENOENT) {
188 i1480_print_state(i1480);
189 goto error;
190 }
191 result = i1480_mac_fw_upload(i1480); /* MAC fw */
192 if (result < 0) {
193 if (result == -ENOENT)
194 dev_err(i1480->dev, "Cannot locate MAC FW file '%s'\n",
195 i1480->mac_fw_name);
196 else
197 i1480_print_state(i1480);
198 goto error;
199 }
200 result = i1480_phy_fw_upload(i1480); /* PHY fw */
201 if (result < 0 && result != -ENOENT) {
202 i1480_print_state(i1480);
203 goto error_rc_release;
204 }
205 /*
206 * FIXME: find some reliable way to check whether firmware is running
207 * properly. Maybe use some standard request that has no side effects?
208 */
209 dev_info(i1480->dev, "firmware uploaded successfully\n");
210error_rc_release:
211 if (i1480->rc_release)
212 i1480->rc_release(i1480);
213 result = 0;
214error:
215 return result;
216}
217EXPORT_SYMBOL_GPL(i1480_fw_upload);
diff --git a/drivers/uwb/i1480/dfu/i1480-dfu.h b/drivers/uwb/i1480/dfu/i1480-dfu.h
new file mode 100644
index 000000000000..46f45e800f36
--- /dev/null
+++ b/drivers/uwb/i1480/dfu/i1480-dfu.h
@@ -0,0 +1,260 @@
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; /* FIXME: Will go away */
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__ */
diff --git a/drivers/uwb/i1480/dfu/mac.c b/drivers/uwb/i1480/dfu/mac.c
new file mode 100644
index 000000000000..2e4d8f07c165
--- /dev/null
+++ b/drivers/uwb/i1480/dfu/mac.c
@@ -0,0 +1,527 @@
1/*
2 * Intel Wireless UWB Link 1480
3 * MAC Firmware upload implementation
4 *
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 *
23 * Implementation of the code for parsing the firmware file (extract
24 * the headers and binary code chunks) in the fw_*() functions. The
25 * code to upload pre and mac firmwares is the same, so it uses a
26 * common entry point in __mac_fw_upload(), which uses the i1480
27 * function pointers to push the firmware to the device.
28 */
29#include <linux/delay.h>
30#include <linux/firmware.h>
31#include <linux/uwb.h>
32#include "i1480-dfu.h"
33
34#define D_LOCAL 0
35#include <linux/uwb/debug.h>
36
37/*
38 * Descriptor for a continuous segment of MAC fw data
39 */
40struct fw_hdr {
41 unsigned long address;
42 size_t length;
43 const u32 *bin;
44 struct fw_hdr *next;
45};
46
47
48/* Free a chain of firmware headers */
49static
50void fw_hdrs_free(struct fw_hdr *hdr)
51{
52 struct fw_hdr *next;
53
54 while (hdr) {
55 next = hdr->next;
56 kfree(hdr);
57 hdr = next;
58 }
59}
60
61
62/* Fill a firmware header descriptor from a memory buffer */
63static
64int fw_hdr_load(struct i1480 *i1480, struct fw_hdr *hdr, unsigned hdr_cnt,
65 const char *_data, const u32 *data_itr, const u32 *data_top)
66{
67 size_t hdr_offset = (const char *) data_itr - _data;
68 size_t remaining_size = (void *) data_top - (void *) data_itr;
69 if (data_itr + 2 > data_top) {
70 dev_err(i1480->dev, "fw hdr #%u/%zu: EOF reached in header at "
71 "offset %zu, limit %zu\n",
72 hdr_cnt, hdr_offset,
73 (const char *) data_itr + 2 - _data,
74 (const char *) data_top - _data);
75 return -EINVAL;
76 }
77 hdr->next = NULL;
78 hdr->address = le32_to_cpu(*data_itr++);
79 hdr->length = le32_to_cpu(*data_itr++);
80 hdr->bin = data_itr;
81 if (hdr->length > remaining_size) {
82 dev_err(i1480->dev, "fw hdr #%u/%zu: EOF reached in data; "
83 "chunk too long (%zu bytes), only %zu left\n",
84 hdr_cnt, hdr_offset, hdr->length, remaining_size);
85 return -EINVAL;
86 }
87 return 0;
88}
89
90
91/**
92 * Get a buffer where the firmware is supposed to be and create a
93 * chain of headers linking them together.
94 *
95 * @phdr: where to place the pointer to the first header (headers link
96 * to the next via the @hdr->next ptr); need to free the whole
97 * chain when done.
98 *
99 * @_data: Pointer to the data buffer.
100 *
101 * @_data_size: Size of the data buffer (bytes); data size has to be a
102 * multiple of 4. Function will fail if not.
103 *
104 * Goes over the whole binary blob; reads the first chunk and creates
105 * a fw hdr from it (which points to where the data is in @_data and
106 * the length of the chunk); then goes on to the next chunk until
107 * done. Each header is linked to the next.
108 */
109static
110int fw_hdrs_load(struct i1480 *i1480, struct fw_hdr **phdr,
111 const char *_data, size_t data_size)
112{
113 int result;
114 unsigned hdr_cnt = 0;
115 u32 *data = (u32 *) _data, *data_itr, *data_top;
116 struct fw_hdr *hdr, **prev_hdr = phdr;
117
118 result = -EINVAL;
119 /* Check size is ok and pointer is aligned */
120 if (data_size % sizeof(u32) != 0)
121 goto error;
122 if ((unsigned long) _data % sizeof(u16) != 0)
123 goto error;
124 *phdr = NULL;
125 data_itr = data;
126 data_top = (u32 *) (_data + data_size);
127 while (data_itr < data_top) {
128 result = -ENOMEM;
129 hdr = kmalloc(sizeof(*hdr), GFP_KERNEL);
130 if (hdr == NULL) {
131 dev_err(i1480->dev, "Cannot allocate fw header "
132 "for chunk #%u\n", hdr_cnt);
133 goto error_alloc;
134 }
135 result = fw_hdr_load(i1480, hdr, hdr_cnt,
136 _data, data_itr, data_top);
137 if (result < 0)
138 goto error_load;
139 data_itr += 2 + hdr->length;
140 *prev_hdr = hdr;
141 prev_hdr = &hdr->next;
142 hdr_cnt++;
143 };
144 *prev_hdr = NULL;
145 return 0;
146
147error_load:
148 kfree(hdr);
149error_alloc:
150 fw_hdrs_free(*phdr);
151error:
152 return result;
153}
154
155
156/**
157 * Compares a chunk of fw with one in the devices's memory
158 *
159 * @i1480: Device instance
160 * @hdr: Pointer to the firmware chunk
161 * @returns: 0 if equal, < 0 errno on error. If > 0, it is the offset
162 * where the difference was found (plus one).
163 *
164 * Kind of dirty and simplistic, but does the trick in both the PCI
165 * and USB version. We do a quick[er] memcmp(), and if it fails, we do
166 * a byte-by-byte to find the offset.
167 */
168static
169ssize_t i1480_fw_cmp(struct i1480 *i1480, struct fw_hdr *hdr)
170{
171 ssize_t result = 0;
172 u32 src_itr = 0, cnt;
173 size_t size = hdr->length*sizeof(hdr->bin[0]);
174 size_t chunk_size;
175 u8 *bin = (u8 *) hdr->bin;
176
177 while (size > 0) {
178 chunk_size = size < i1480->buf_size ? size : i1480->buf_size;
179 result = i1480->read(i1480, hdr->address + src_itr, chunk_size);
180 if (result < 0) {
181 dev_err(i1480->dev, "error reading for verification: "
182 "%zd\n", result);
183 goto error;
184 }
185 if (memcmp(i1480->cmd_buf, bin + src_itr, result)) {
186 u8 *buf = i1480->cmd_buf;
187 d_printf(2, i1480->dev,
188 "original data @ %p + %u, %zu bytes\n",
189 bin, src_itr, result);
190 d_dump(4, i1480->dev, bin + src_itr, result);
191 for (cnt = 0; cnt < result; cnt++)
192 if (bin[src_itr + cnt] != buf[cnt]) {
193 dev_err(i1480->dev, "byte failed at "
194 "src_itr %u cnt %u [0x%02x "
195 "vs 0x%02x]\n", src_itr, cnt,
196 bin[src_itr + cnt], buf[cnt]);
197 result = src_itr + cnt + 1;
198 goto cmp_failed;
199 }
200 }
201 src_itr += result;
202 size -= result;
203 }
204 result = 0;
205error:
206cmp_failed:
207 return result;
208}
209
210
211/**
212 * Writes firmware headers to the device.
213 *
214 * @prd: PRD instance
215 * @hdr: Processed firmware
216 * @returns: 0 if ok, < 0 errno on error.
217 */
218static
219int mac_fw_hdrs_push(struct i1480 *i1480, struct fw_hdr *hdr,
220 const char *fw_name, const char *fw_tag)
221{
222 struct device *dev = i1480->dev;
223 ssize_t result = 0;
224 struct fw_hdr *hdr_itr;
225 int verif_retry_count;
226
227 d_fnstart(3, dev, "(%p, %p)\n", i1480, hdr);
228 /* Now, header by header, push them to the hw */
229 for (hdr_itr = hdr; hdr_itr != NULL; hdr_itr = hdr_itr->next) {
230 verif_retry_count = 0;
231retry:
232 dev_dbg(dev, "fw chunk (%zu @ 0x%08lx)\n",
233 hdr_itr->length * sizeof(hdr_itr->bin[0]),
234 hdr_itr->address);
235 result = i1480->write(i1480, hdr_itr->address, hdr_itr->bin,
236 hdr_itr->length*sizeof(hdr_itr->bin[0]));
237 if (result < 0) {
238 dev_err(dev, "%s fw '%s': write failed (%zuB @ 0x%lx):"
239 " %zd\n", fw_tag, fw_name,
240 hdr_itr->length * sizeof(hdr_itr->bin[0]),
241 hdr_itr->address, result);
242 break;
243 }
244 result = i1480_fw_cmp(i1480, hdr_itr);
245 if (result < 0) {
246 dev_err(dev, "%s fw '%s': verification read "
247 "failed (%zuB @ 0x%lx): %zd\n",
248 fw_tag, fw_name,
249 hdr_itr->length * sizeof(hdr_itr->bin[0]),
250 hdr_itr->address, result);
251 break;
252 }
253 if (result > 0) { /* Offset where it failed + 1 */
254 result--;
255 dev_err(dev, "%s fw '%s': WARNING: verification "
256 "failed at 0x%lx: retrying\n",
257 fw_tag, fw_name, hdr_itr->address + result);
258 if (++verif_retry_count < 3)
259 goto retry; /* write this block again! */
260 dev_err(dev, "%s fw '%s': verification failed at 0x%lx: "
261 "tried %d times\n", fw_tag, fw_name,
262 hdr_itr->address + result, verif_retry_count);
263 result = -EINVAL;
264 break;
265 }
266 }
267 d_fnend(3, dev, "(%zd)\n", result);
268 return result;
269}
270
271
272/** Puts the device in firmware upload mode.*/
273static
274int mac_fw_upload_enable(struct i1480 *i1480)
275{
276 int result;
277 u32 reg = 0x800000c0;
278 u32 *buffer = (u32 *)i1480->cmd_buf;
279
280 if (i1480->hw_rev > 1)
281 reg = 0x8000d0d4;
282 result = i1480->read(i1480, reg, sizeof(u32));
283 if (result < 0)
284 goto error_cmd;
285 *buffer &= ~i1480_FW_UPLOAD_MODE_MASK;
286 result = i1480->write(i1480, reg, buffer, sizeof(u32));
287 if (result < 0)
288 goto error_cmd;
289 return 0;
290error_cmd:
291 dev_err(i1480->dev, "can't enable fw upload mode: %d\n", result);
292 return result;
293}
294
295
296/** Gets the device out of firmware upload mode. */
297static
298int mac_fw_upload_disable(struct i1480 *i1480)
299{
300 int result;
301 u32 reg = 0x800000c0;
302 u32 *buffer = (u32 *)i1480->cmd_buf;
303
304 if (i1480->hw_rev > 1)
305 reg = 0x8000d0d4;
306 result = i1480->read(i1480, reg, sizeof(u32));
307 if (result < 0)
308 goto error_cmd;
309 *buffer |= i1480_FW_UPLOAD_MODE_MASK;
310 result = i1480->write(i1480, reg, buffer, sizeof(u32));
311 if (result < 0)
312 goto error_cmd;
313 return 0;
314error_cmd:
315 dev_err(i1480->dev, "can't disable fw upload mode: %d\n", result);
316 return result;
317}
318
319
320
321/**
322 * Generic function for uploading a MAC firmware.
323 *
324 * @i1480: Device instance
325 * @fw_name: Name of firmware file to upload.
326 * @fw_tag: Name of the firmware type (for messages)
327 * [eg: MAC, PRE]
328 * @do_wait: Wait for device to emit initialization done message (0
329 * for PRE fws, 1 for MAC fws).
330 * @returns: 0 if ok, < 0 errno on error.
331 */
332static
333int __mac_fw_upload(struct i1480 *i1480, const char *fw_name,
334 const char *fw_tag)
335{
336 int result;
337 const struct firmware *fw;
338 struct fw_hdr *fw_hdrs;
339
340 d_fnstart(3, i1480->dev, "(%p, %s, %s)\n", i1480, fw_name, fw_tag);
341 result = request_firmware(&fw, fw_name, i1480->dev);
342 if (result < 0) /* Up to caller to complain on -ENOENT */
343 goto out;
344 d_printf(3, i1480->dev, "%s fw '%s': uploading\n", fw_tag, fw_name);
345 result = fw_hdrs_load(i1480, &fw_hdrs, fw->data, fw->size);
346 if (result < 0) {
347 dev_err(i1480->dev, "%s fw '%s': failed to parse firmware "
348 "file: %d\n", fw_tag, fw_name, result);
349 goto out_release;
350 }
351 result = mac_fw_upload_enable(i1480);
352 if (result < 0)
353 goto out_hdrs_release;
354 result = mac_fw_hdrs_push(i1480, fw_hdrs, fw_name, fw_tag);
355 mac_fw_upload_disable(i1480);
356out_hdrs_release:
357 if (result >= 0)
358 dev_info(i1480->dev, "%s fw '%s': uploaded\n", fw_tag, fw_name);
359 else
360 dev_err(i1480->dev, "%s fw '%s': failed to upload (%d), "
361 "power cycle device\n", fw_tag, fw_name, result);
362 fw_hdrs_free(fw_hdrs);
363out_release:
364 release_firmware(fw);
365out:
366 d_fnend(3, i1480->dev, "(%p, %s, %s) = %d\n", i1480, fw_name, fw_tag,
367 result);
368 return result;
369}
370
371
372/**
373 * Upload a pre-PHY firmware
374 *
375 */
376int i1480_pre_fw_upload(struct i1480 *i1480)
377{
378 int result;
379 result = __mac_fw_upload(i1480, i1480->pre_fw_name, "PRE");
380 if (result == 0)
381 msleep(400);
382 return result;
383}
384
385
386/**
387 * Reset a the MAC and PHY
388 *
389 * @i1480: Device's instance
390 * @returns: 0 if ok, < 0 errno code on error
391 *
392 * We put the command on kmalloc'ed memory as some arches cannot do
393 * USB from the stack. The reply event is copied from an stage buffer,
394 * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details.
395 *
396 * We issue the reset to make sure the UWB controller reinits the PHY;
397 * this way we can now if the PHY init went ok.
398 */
399static
400int i1480_cmd_reset(struct i1480 *i1480)
401{
402 int result;
403 struct uwb_rccb *cmd = (void *) i1480->cmd_buf;
404 struct i1480_evt_reset {
405 struct uwb_rceb rceb;
406 u8 bResultCode;
407 } __attribute__((packed)) *reply = (void *) i1480->evt_buf;
408
409 result = -ENOMEM;
410 cmd->bCommandType = UWB_RC_CET_GENERAL;
411 cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET);
412 reply->rceb.bEventType = UWB_RC_CET_GENERAL;
413 reply->rceb.wEvent = UWB_RC_CMD_RESET;
414 result = i1480_cmd(i1480, "RESET", sizeof(*cmd), sizeof(*reply));
415 if (result < 0)
416 goto out;
417 if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
418 dev_err(i1480->dev, "RESET: command execution failed: %u\n",
419 reply->bResultCode);
420 result = -EIO;
421 }
422out:
423 return result;
424
425}
426
427
428/* Wait for the MAC FW to start running */
429static
430int i1480_fw_is_running_q(struct i1480 *i1480)
431{
432 int cnt = 0;
433 int result;
434 u32 *val = (u32 *) i1480->cmd_buf;
435
436 d_fnstart(3, i1480->dev, "(i1480 %p)\n", i1480);
437 for (cnt = 0; cnt < 10; cnt++) {
438 msleep(100);
439 result = i1480->read(i1480, 0x80080000, 4);
440 if (result < 0) {
441 dev_err(i1480->dev, "Can't read 0x8008000: %d\n", result);
442 goto out;
443 }
444 if (*val == 0x55555555UL) /* fw running? cool */
445 goto out;
446 }
447 dev_err(i1480->dev, "Timed out waiting for fw to start\n");
448 result = -ETIMEDOUT;
449out:
450 d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result);
451 return result;
452
453}
454
455
456/**
457 * Upload MAC firmware, wait for it to start
458 *
459 * @i1480: Device instance
460 * @fw_name: Name of the file that contains the firmware
461 *
462 * This has to be called after the pre fw has been uploaded (if
463 * there is any).
464 */
465int i1480_mac_fw_upload(struct i1480 *i1480)
466{
467 int result = 0, deprecated_name = 0;
468 struct i1480_rceb *rcebe = (void *) i1480->evt_buf;
469
470 d_fnstart(3, i1480->dev, "(%p)\n", i1480);
471 result = __mac_fw_upload(i1480, i1480->mac_fw_name, "MAC");
472 if (result == -ENOENT) {
473 result = __mac_fw_upload(i1480, i1480->mac_fw_name_deprecate,
474 "MAC");
475 deprecated_name = 1;
476 }
477 if (result < 0)
478 return result;
479 if (deprecated_name == 1)
480 dev_warn(i1480->dev,
481 "WARNING: firmware file name %s is deprecated, "
482 "please rename to %s\n",
483 i1480->mac_fw_name_deprecate, i1480->mac_fw_name);
484 result = i1480_fw_is_running_q(i1480);
485 if (result < 0)
486 goto error_fw_not_running;
487 result = i1480->rc_setup ? i1480->rc_setup(i1480) : 0;
488 if (result < 0) {
489 dev_err(i1480->dev, "Cannot setup after MAC fw upload: %d\n",
490 result);
491 goto error_setup;
492 }
493 result = i1480->wait_init_done(i1480); /* wait init'on */
494 if (result < 0) {
495 dev_err(i1480->dev, "MAC fw '%s': Initialization timed out "
496 "(%d)\n", i1480->mac_fw_name, result);
497 goto error_init_timeout;
498 }
499 /* verify we got the right initialization done event */
500 if (i1480->evt_result != sizeof(*rcebe)) {
501 dev_err(i1480->dev, "MAC fw '%s': initialization event returns "
502 "wrong size (%zu bytes vs %zu needed)\n",
503 i1480->mac_fw_name, i1480->evt_result, sizeof(*rcebe));
504 dump_bytes(i1480->dev, rcebe, min(i1480->evt_result, (ssize_t)32));
505 goto error_size;
506 }
507 result = -EIO;
508 if (i1480_rceb_check(i1480, &rcebe->rceb, NULL, 0, i1480_CET_VS1,
509 i1480_EVT_RM_INIT_DONE) < 0) {
510 dev_err(i1480->dev, "wrong initialization event 0x%02x/%04x/%02x "
511 "received; expected 0x%02x/%04x/00\n",
512 rcebe->rceb.bEventType, le16_to_cpu(rcebe->rceb.wEvent),
513 rcebe->rceb.bEventContext, i1480_CET_VS1,
514 i1480_EVT_RM_INIT_DONE);
515 goto error_init_timeout;
516 }
517 result = i1480_cmd_reset(i1480);
518 if (result < 0)
519 dev_err(i1480->dev, "MAC fw '%s': MBOA reset failed (%d)\n",
520 i1480->mac_fw_name, result);
521error_fw_not_running:
522error_init_timeout:
523error_size:
524error_setup:
525 d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result);
526 return result;
527}
diff --git a/drivers/uwb/i1480/dfu/phy.c b/drivers/uwb/i1480/dfu/phy.c
new file mode 100644
index 000000000000..3b1a87de8e63
--- /dev/null
+++ b/drivers/uwb/i1480/dfu/phy.c
@@ -0,0 +1,203 @@
1/*
2 * Intel Wireless UWB Link 1480
3 * PHY parameters upload
4 *
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 *
23 * Code for uploading the PHY parameters to the PHY through the UWB
24 * Radio Control interface.
25 *
26 * We just send the data through the MPI interface using HWA-like
27 * commands and then reset the PHY to make sure it is ok.
28 */
29#include <linux/delay.h>
30#include <linux/device.h>
31#include <linux/firmware.h>
32#include <linux/usb/wusb.h>
33#include "i1480-dfu.h"
34
35
36/**
37 * Write a value array to an address of the MPI interface
38 *
39 * @i1480: Device descriptor
40 * @data: Data array to write
41 * @size: Size of the data array
42 * @returns: 0 if ok, < 0 errno code on error.
43 *
44 * The data array is organized into pairs:
45 *
46 * ADDRESS VALUE
47 *
48 * ADDRESS is BE 16 bit unsigned, VALUE 8 bit unsigned. Size thus has
49 * to be a multiple of three.
50 */
51static
52int i1480_mpi_write(struct i1480 *i1480, const void *data, size_t size)
53{
54 int result;
55 struct i1480_cmd_mpi_write *cmd = i1480->cmd_buf;
56 struct i1480_evt_confirm *reply = i1480->evt_buf;
57
58 BUG_ON(size > 480);
59 result = -ENOMEM;
60 cmd->rccb.bCommandType = i1480_CET_VS1;
61 cmd->rccb.wCommand = cpu_to_le16(i1480_CMD_MPI_WRITE);
62 cmd->size = cpu_to_le16(size);
63 memcpy(cmd->data, data, size);
64 reply->rceb.bEventType = i1480_CET_VS1;
65 reply->rceb.wEvent = i1480_CMD_MPI_WRITE;
66 result = i1480_cmd(i1480, "MPI-WRITE", sizeof(*cmd) + size, sizeof(*reply));
67 if (result < 0)
68 goto out;
69 if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
70 dev_err(i1480->dev, "MPI-WRITE: command execution failed: %d\n",
71 reply->bResultCode);
72 result = -EIO;
73 }
74out:
75 return result;
76}
77
78
79/**
80 * Read a value array to from an address of the MPI interface
81 *
82 * @i1480: Device descriptor
83 * @data: where to place the read array
84 * @srcaddr: Where to read from
85 * @size: Size of the data read array
86 * @returns: 0 if ok, < 0 errno code on error.
87 *
88 * The command data array is organized into pairs ADDR0 ADDR1..., and
89 * the returned data in ADDR0 VALUE0 ADDR1 VALUE1...
90 *
91 * We generate the command array to be a sequential read and then
92 * rearrange the result.
93 *
94 * We use the i1480->cmd_buf for the command, i1480->evt_buf for the reply.
95 *
96 * As the reply has to fit in 512 bytes (i1480->evt_buffer), the max amount
97 * of values we can read is (512 - sizeof(*reply)) / 3
98 */
99static
100int i1480_mpi_read(struct i1480 *i1480, u8 *data, u16 srcaddr, size_t size)
101{
102 int result;
103 struct i1480_cmd_mpi_read *cmd = i1480->cmd_buf;
104 struct i1480_evt_mpi_read *reply = i1480->evt_buf;
105 unsigned cnt;
106
107 memset(i1480->cmd_buf, 0x69, 512);
108 memset(i1480->evt_buf, 0x69, 512);
109
110 BUG_ON(size > (i1480->buf_size - sizeof(*reply)) / 3);
111 result = -ENOMEM;
112 cmd->rccb.bCommandType = i1480_CET_VS1;
113 cmd->rccb.wCommand = cpu_to_le16(i1480_CMD_MPI_READ);
114 cmd->size = cpu_to_le16(3*size);
115 for (cnt = 0; cnt < size; cnt++) {
116 cmd->data[cnt].page = (srcaddr + cnt) >> 8;
117 cmd->data[cnt].offset = (srcaddr + cnt) & 0xff;
118 }
119 reply->rceb.bEventType = i1480_CET_VS1;
120 reply->rceb.wEvent = i1480_CMD_MPI_READ;
121 result = i1480_cmd(i1480, "MPI-READ", sizeof(*cmd) + 2*size,
122 sizeof(*reply) + 3*size);
123 if (result < 0)
124 goto out;
125 if (reply->bResultCode != UWB_RC_RES_SUCCESS) {
126 dev_err(i1480->dev, "MPI-READ: command execution failed: %d\n",
127 reply->bResultCode);
128 result = -EIO;
129 }
130 for (cnt = 0; cnt < size; cnt++) {
131 if (reply->data[cnt].page != (srcaddr + cnt) >> 8)
132 dev_err(i1480->dev, "MPI-READ: page inconsistency at "
133 "index %u: expected 0x%02x, got 0x%02x\n", cnt,
134 (srcaddr + cnt) >> 8, reply->data[cnt].page);
135 if (reply->data[cnt].offset != ((srcaddr + cnt) & 0x00ff))
136 dev_err(i1480->dev, "MPI-READ: offset inconsistency at "
137 "index %u: expected 0x%02x, got 0x%02x\n", cnt,
138 (srcaddr + cnt) & 0x00ff,
139 reply->data[cnt].offset);
140 data[cnt] = reply->data[cnt].value;
141 }
142 result = 0;
143out:
144 return result;
145}
146
147
148/**
149 * Upload a PHY firmware, wait for it to start
150 *
151 * @i1480: Device instance
152 * @fw_name: Name of the file that contains the firmware
153 *
154 * We assume the MAC fw is up and running. This means we can use the
155 * MPI interface to write the PHY firmware. Once done, we issue an
156 * MBOA Reset, which will force the MAC to reset and reinitialize the
157 * PHY. If that works, we are ready to go.
158 *
159 * Max packet size for the MPI write is 512, so the max buffer is 480
160 * (which gives us 160 byte triads of MSB, LSB and VAL for the data).
161 */
162int i1480_phy_fw_upload(struct i1480 *i1480)
163{
164 int result;
165 const struct firmware *fw;
166 const char *data_itr, *data_top;
167 const size_t MAX_BLK_SIZE = 480; /* 160 triads */
168 size_t data_size;
169 u8 phy_stat;
170
171 result = request_firmware(&fw, i1480->phy_fw_name, i1480->dev);
172 if (result < 0)
173 goto out;
174 /* Loop writing data in chunks as big as possible until done. */
175 for (data_itr = fw->data, data_top = data_itr + fw->size;
176 data_itr < data_top; data_itr += MAX_BLK_SIZE) {
177 data_size = min(MAX_BLK_SIZE, (size_t) (data_top - data_itr));
178 result = i1480_mpi_write(i1480, data_itr, data_size);
179 if (result < 0)
180 goto error_mpi_write;
181 }
182 /* Read MPI page 0, offset 6; if 0, PHY was initialized correctly. */
183 result = i1480_mpi_read(i1480, &phy_stat, 0x0006, 1);
184 if (result < 0) {
185 dev_err(i1480->dev, "PHY: can't get status: %d\n", result);
186 goto error_mpi_status;
187 }
188 if (phy_stat != 0) {
189 result = -ENODEV;
190 dev_info(i1480->dev, "error, PHY not ready: %u\n", phy_stat);
191 goto error_phy_status;
192 }
193 dev_info(i1480->dev, "PHY fw '%s': uploaded\n", i1480->phy_fw_name);
194error_phy_status:
195error_mpi_status:
196error_mpi_write:
197 release_firmware(fw);
198 if (result < 0)
199 dev_err(i1480->dev, "PHY fw '%s': failed to upload (%d), "
200 "power cycle device\n", i1480->phy_fw_name, result);
201out:
202 return result;
203}
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c
new file mode 100644
index 000000000000..98eeeff051aa
--- /dev/null
+++ b/drivers/uwb/i1480/dfu/usb.c
@@ -0,0 +1,500 @@
1/*
2 * Intel Wireless UWB Link 1480
3 * USB SKU firmware upload implementation
4 *
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 *
23 * This driver will prepare the i1480 device to behave as a real
24 * Wireless USB HWA adaptor by uploading the firmware.
25 *
26 * When the device is connected or driver is loaded, i1480_usb_probe()
27 * is called--this will allocate and initialize the device structure,
28 * fill in the pointers to the common functions (read, write,
29 * wait_init_done and cmd for HWA command execution) and once that is
30 * done, call the common firmware uploading routine. Then clean up and
31 * return -ENODEV, as we don't attach to the device.
32 *
33 * The rest are the basic ops we implement that the fw upload code
34 * uses to do its job. All the ops in the common code are i1480->NAME,
35 * the functions are i1480_usb_NAME().
36 */
37#include <linux/module.h>
38#include <linux/version.h>
39#include <linux/usb.h>
40#include <linux/interrupt.h>
41#include <linux/delay.h>
42#include <linux/uwb.h>
43#include <linux/usb/wusb.h>
44#include <linux/usb/wusb-wa.h>
45#include "i1480-dfu.h"
46
47#define D_LOCAL 0
48#include <linux/uwb/debug.h>
49
50
51struct i1480_usb {
52 struct i1480 i1480;
53 struct usb_device *usb_dev;
54 struct usb_interface *usb_iface;
55 struct urb *neep_urb; /* URB for reading from EP1 */
56};
57
58
59static
60void i1480_usb_init(struct i1480_usb *i1480_usb)
61{
62 i1480_init(&i1480_usb->i1480);
63}
64
65
66static
67int i1480_usb_create(struct i1480_usb *i1480_usb, struct usb_interface *iface)
68{
69 struct usb_device *usb_dev = interface_to_usbdev(iface);
70 int result = -ENOMEM;
71
72 i1480_usb->usb_dev = usb_get_dev(usb_dev); /* bind the USB device */
73 i1480_usb->usb_iface = usb_get_intf(iface);
74 usb_set_intfdata(iface, i1480_usb); /* Bind the driver to iface0 */
75 i1480_usb->neep_urb = usb_alloc_urb(0, GFP_KERNEL);
76 if (i1480_usb->neep_urb == NULL)
77 goto error;
78 return 0;
79
80error:
81 usb_set_intfdata(iface, NULL);
82 usb_put_intf(iface);
83 usb_put_dev(usb_dev);
84 return result;
85}
86
87
88static
89void i1480_usb_destroy(struct i1480_usb *i1480_usb)
90{
91 usb_kill_urb(i1480_usb->neep_urb);
92 usb_free_urb(i1480_usb->neep_urb);
93 usb_set_intfdata(i1480_usb->usb_iface, NULL);
94 usb_put_intf(i1480_usb->usb_iface);
95 usb_put_dev(i1480_usb->usb_dev);
96}
97
98
99/**
100 * Write a buffer to a memory address in the i1480 device
101 *
102 * @i1480: i1480 instance
103 * @memory_address:
104 * Address where to write the data buffer to.
105 * @buffer: Buffer to the data
106 * @size: Size of the buffer [has to be < 512].
107 * @returns: 0 if ok, < 0 errno code on error.
108 *
109 * Data buffers to USB cannot be on the stack or in vmalloc'ed areas,
110 * so we copy it to the local i1480 buffer before proceeding. In any
111 * case, we have a max size we can send, soooo.
112 */
113static
114int i1480_usb_write(struct i1480 *i1480, u32 memory_address,
115 const void *buffer, size_t size)
116{
117 int result = 0;
118 struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
119 size_t buffer_size, itr = 0;
120
121 d_fnstart(3, i1480->dev, "(%p, 0x%08x, %p, %zu)\n",
122 i1480, memory_address, buffer, size);
123 BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */
124 while (size > 0) {
125 buffer_size = size < i1480->buf_size ? size : i1480->buf_size;
126 memcpy(i1480->cmd_buf, buffer + itr, buffer_size);
127 result = usb_control_msg(
128 i1480_usb->usb_dev, usb_sndctrlpipe(i1480_usb->usb_dev, 0),
129 0xf0, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
130 cpu_to_le16(memory_address & 0xffff),
131 cpu_to_le16((memory_address >> 16) & 0xffff),
132 i1480->cmd_buf, buffer_size, 100 /* FIXME: arbitrary */);
133 if (result < 0)
134 break;
135 d_printf(3, i1480->dev,
136 "wrote @ 0x%08x %u bytes (of %zu bytes requested)\n",
137 memory_address, result, buffer_size);
138 d_dump(4, i1480->dev, i1480->cmd_buf, result);
139 itr += result;
140 memory_address += result;
141 size -= result;
142 }
143 d_fnend(3, i1480->dev, "(%p, 0x%08x, %p, %zu) = %d\n",
144 i1480, memory_address, buffer, size, result);
145 return result;
146}
147
148
149/**
150 * Read a block [max size 512] of the device's memory to @i1480's buffer.
151 *
152 * @i1480: i1480 instance
153 * @memory_address:
154 * Address where to read from.
155 * @size: Size to read. Smaller than or equal to 512.
156 * @returns: >= 0 number of bytes written if ok, < 0 errno code on error.
157 *
158 * NOTE: if the memory address or block is incorrect, you might get a
159 * stall or a different memory read. Caller has to verify the
160 * memory address and size passed back in the @neh structure.
161 */
162static
163int i1480_usb_read(struct i1480 *i1480, u32 addr, size_t size)
164{
165 ssize_t result = 0, bytes = 0;
166 size_t itr, read_size = i1480->buf_size;
167 struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
168
169 d_fnstart(3, i1480->dev, "(%p, 0x%08x, %zu)\n",
170 i1480, addr, size);
171 BUG_ON(size > i1480->buf_size);
172 BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */
173 BUG_ON(read_size > 512);
174
175 if (addr >= 0x8000d200 && addr < 0x8000d400) /* Yeah, HW quirk */
176 read_size = 4;
177
178 for (itr = 0; itr < size; itr += read_size) {
179 size_t itr_addr = addr + itr;
180 size_t itr_size = min(read_size, size - itr);
181 result = usb_control_msg(
182 i1480_usb->usb_dev, usb_rcvctrlpipe(i1480_usb->usb_dev, 0),
183 0xf0, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
184 cpu_to_le16(itr_addr & 0xffff),
185 cpu_to_le16((itr_addr >> 16) & 0xffff),
186 i1480->cmd_buf + itr, itr_size,
187 100 /* FIXME: arbitrary */);
188 if (result < 0) {
189 dev_err(i1480->dev, "%s: USB read error: %zd\n",
190 __func__, result);
191 goto out;
192 }
193 if (result != itr_size) {
194 result = -EIO;
195 dev_err(i1480->dev,
196 "%s: partial read got only %zu bytes vs %zu expected\n",
197 __func__, result, itr_size);
198 goto out;
199 }
200 bytes += result;
201 }
202 result = bytes;
203out:
204 d_fnend(3, i1480->dev, "(%p, 0x%08x, %zu) = %zd\n",
205 i1480, addr, size, result);
206 if (result > 0)
207 d_dump(4, i1480->dev, i1480->cmd_buf, result);
208 return result;
209}
210
211
212/**
213 * Callback for reads on the notification/event endpoint
214 *
215 * Just enables the completion read handler.
216 */
217static
218void i1480_usb_neep_cb(struct urb *urb)
219{
220 struct i1480 *i1480 = urb->context;
221 struct device *dev = i1480->dev;
222
223 switch (urb->status) {
224 case 0:
225 break;
226 case -ECONNRESET: /* Not an error, but a controlled situation; */
227 case -ENOENT: /* (we killed the URB)...so, no broadcast */
228 dev_dbg(dev, "NEEP: reset/noent %d\n", urb->status);
229 break;
230 case -ESHUTDOWN: /* going away! */
231 dev_dbg(dev, "NEEP: down %d\n", urb->status);
232 break;
233 default:
234 dev_err(dev, "NEEP: unknown status %d\n", urb->status);
235 break;
236 }
237 i1480->evt_result = urb->actual_length;
238 complete(&i1480->evt_complete);
239 return;
240}
241
242
243/**
244 * Wait for the MAC FW to initialize
245 *
246 * MAC FW sends a 0xfd/0101/00 notification to EP1 when done
247 * initializing. Get that notification into i1480->evt_buf; upper layer
248 * will verify it.
249 *
250 * Set i1480->evt_result with the result of getting the event or its
251 * size (if succesful).
252 *
253 * Delivers the data directly to i1480->evt_buf
254 */
255static
256int i1480_usb_wait_init_done(struct i1480 *i1480)
257{
258 int result;
259 struct device *dev = i1480->dev;
260 struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
261 struct usb_endpoint_descriptor *epd;
262
263 d_fnstart(3, dev, "(%p)\n", i1480);
264 init_completion(&i1480->evt_complete);
265 i1480->evt_result = -EINPROGRESS;
266 epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc;
267 usb_fill_int_urb(i1480_usb->neep_urb, i1480_usb->usb_dev,
268 usb_rcvintpipe(i1480_usb->usb_dev, epd->bEndpointAddress),
269 i1480->evt_buf, i1480->buf_size,
270 i1480_usb_neep_cb, i1480, epd->bInterval);
271 result = usb_submit_urb(i1480_usb->neep_urb, GFP_KERNEL);
272 if (result < 0) {
273 dev_err(dev, "init done: cannot submit NEEP read: %d\n",
274 result);
275 goto error_submit;
276 }
277 /* Wait for the USB callback to get the data */
278 result = wait_for_completion_interruptible_timeout(
279 &i1480->evt_complete, HZ);
280 if (result <= 0) {
281 result = result == 0 ? -ETIMEDOUT : result;
282 goto error_wait;
283 }
284 usb_kill_urb(i1480_usb->neep_urb);
285 d_fnend(3, dev, "(%p) = 0\n", i1480);
286 return 0;
287
288error_wait:
289 usb_kill_urb(i1480_usb->neep_urb);
290error_submit:
291 i1480->evt_result = result;
292 d_fnend(3, dev, "(%p) = %d\n", i1480, result);
293 return result;
294}
295
296
297/**
298 * Generic function for issuing commands to the i1480
299 *
300 * @i1480: i1480 instance
301 * @cmd_name: Name of the command (for error messages)
302 * @cmd: Pointer to command buffer
303 * @cmd_size: Size of the command buffer
304 * @reply: Buffer for the reply event
305 * @reply_size: Expected size back (including RCEB); the reply buffer
306 * is assumed to be as big as this.
307 * @returns: >= 0 size of the returned event data if ok,
308 * < 0 errno code on error.
309 *
310 * Arms the NE handle, issues the command to the device and checks the
311 * basics of the reply event.
312 */
313static
314int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size)
315{
316 int result;
317 struct device *dev = i1480->dev;
318 struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
319 struct usb_endpoint_descriptor *epd;
320 struct uwb_rccb *cmd = i1480->cmd_buf;
321 u8 iface_no;
322
323 d_fnstart(3, dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size);
324 /* Post a read on the notification & event endpoint */
325 iface_no = i1480_usb->usb_iface->cur_altsetting->desc.bInterfaceNumber;
326 epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc;
327 usb_fill_int_urb(
328 i1480_usb->neep_urb, i1480_usb->usb_dev,
329 usb_rcvintpipe(i1480_usb->usb_dev, epd->bEndpointAddress),
330 i1480->evt_buf, i1480->buf_size,
331 i1480_usb_neep_cb, i1480, epd->bInterval);
332 result = usb_submit_urb(i1480_usb->neep_urb, GFP_KERNEL);
333 if (result < 0) {
334 dev_err(dev, "%s: cannot submit NEEP read: %d\n",
335 cmd_name, result);
336 goto error_submit_ep1;
337 }
338 /* Now post the command on EP0 */
339 result = usb_control_msg(
340 i1480_usb->usb_dev, usb_sndctrlpipe(i1480_usb->usb_dev, 0),
341 WA_EXEC_RC_CMD,
342 USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
343 0, iface_no,
344 cmd, cmd_size,
345 100 /* FIXME: this is totally arbitrary */);
346 if (result < 0) {
347 dev_err(dev, "%s: control request failed: %d\n",
348 cmd_name, result);
349 goto error_submit_ep0;
350 }
351 d_fnend(3, dev, "(%p, %s, %zu) = %d\n",
352 i1480, cmd_name, cmd_size, result);
353 return result;
354
355error_submit_ep0:
356 usb_kill_urb(i1480_usb->neep_urb);
357error_submit_ep1:
358 d_fnend(3, dev, "(%p, %s, %zu) = %d\n",
359 i1480, cmd_name, cmd_size, result);
360 return result;
361}
362
363
364/*
365 * Probe a i1480 device for uploading firmware.
366 *
367 * We attach only to interface #0, which is the radio control interface.
368 */
369static
370int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
371{
372 struct i1480_usb *i1480_usb;
373 struct i1480 *i1480;
374 struct device *dev = &iface->dev;
375 int result;
376
377 result = -ENODEV;
378 if (iface->cur_altsetting->desc.bInterfaceNumber != 0) {
379 dev_dbg(dev, "not attaching to iface %d\n",
380 iface->cur_altsetting->desc.bInterfaceNumber);
381 goto error;
382 }
383 if (iface->num_altsetting > 1
384 && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) {
385 /* Need altsetting #1 [HW QUIRK] or EP1 won't work */
386 result = usb_set_interface(interface_to_usbdev(iface), 0, 1);
387 if (result < 0)
388 dev_warn(dev,
389 "can't set altsetting 1 on iface 0: %d\n",
390 result);
391 }
392
393 result = -ENOMEM;
394 i1480_usb = kzalloc(sizeof(*i1480_usb), GFP_KERNEL);
395 if (i1480_usb == NULL) {
396 dev_err(dev, "Unable to allocate instance\n");
397 goto error;
398 }
399 i1480_usb_init(i1480_usb);
400
401 i1480 = &i1480_usb->i1480;
402 i1480->buf_size = 512;
403 i1480->cmd_buf = kmalloc(2 * i1480->buf_size, GFP_KERNEL);
404 if (i1480->cmd_buf == NULL) {
405 dev_err(dev, "Cannot allocate transfer buffers\n");
406 result = -ENOMEM;
407 goto error_buf_alloc;
408 }
409 i1480->evt_buf = i1480->cmd_buf + i1480->buf_size;
410
411 result = i1480_usb_create(i1480_usb, iface);
412 if (result < 0) {
413 dev_err(dev, "Cannot create instance: %d\n", result);
414 goto error_create;
415 }
416
417 /* setup the fops and upload the firmare */
418 i1480->pre_fw_name = "i1480-pre-phy-0.0.bin";
419 i1480->mac_fw_name = "i1480-usb-0.0.bin";
420 i1480->mac_fw_name_deprecate = "ptc-0.0.bin";
421 i1480->phy_fw_name = "i1480-phy-0.0.bin";
422 i1480->dev = &iface->dev;
423 i1480->write = i1480_usb_write;
424 i1480->read = i1480_usb_read;
425 i1480->rc_setup = NULL;
426 i1480->wait_init_done = i1480_usb_wait_init_done;
427 i1480->cmd = i1480_usb_cmd;
428
429 result = i1480_fw_upload(&i1480_usb->i1480); /* the real thing */
430 if (result >= 0) {
431 usb_reset_device(i1480_usb->usb_dev);
432 result = -ENODEV; /* we don't want to bind to the iface */
433 }
434 i1480_usb_destroy(i1480_usb);
435error_create:
436 kfree(i1480->cmd_buf);
437error_buf_alloc:
438 kfree(i1480_usb);
439error:
440 return result;
441}
442
443#define i1480_USB_DEV(v, p) \
444{ \
445 .match_flags = USB_DEVICE_ID_MATCH_DEVICE \
446 | USB_DEVICE_ID_MATCH_DEV_INFO \
447 | USB_DEVICE_ID_MATCH_INT_INFO, \
448 .idVendor = (v), \
449 .idProduct = (p), \
450 .bDeviceClass = 0xff, \
451 .bDeviceSubClass = 0xff, \
452 .bDeviceProtocol = 0xff, \
453 .bInterfaceClass = 0xff, \
454 .bInterfaceSubClass = 0xff, \
455 .bInterfaceProtocol = 0xff, \
456}
457
458
459/** USB device ID's that we handle */
460static struct usb_device_id i1480_usb_id_table[] = {
461 i1480_USB_DEV(0x8086, 0xdf3b),
462 i1480_USB_DEV(0x15a9, 0x0005),
463 i1480_USB_DEV(0x07d1, 0x3802),
464 i1480_USB_DEV(0x050d, 0x305a),
465 i1480_USB_DEV(0x3495, 0x3007),
466 {},
467};
468MODULE_DEVICE_TABLE(usb, i1480_usb_id_table);
469
470
471static struct usb_driver i1480_dfu_driver = {
472 .name = "i1480-dfu-usb",
473 .id_table = i1480_usb_id_table,
474 .probe = i1480_usb_probe,
475 .disconnect = NULL,
476};
477
478
479/*
480 * Initialize the i1480 DFU driver.
481 *
482 * We also need to register our function for guessing event sizes.
483 */
484static int __init i1480_dfu_driver_init(void)
485{
486 return usb_register(&i1480_dfu_driver);
487}
488module_init(i1480_dfu_driver_init);
489
490
491static void __exit i1480_dfu_driver_exit(void)
492{
493 usb_deregister(&i1480_dfu_driver);
494}
495module_exit(i1480_dfu_driver_exit);
496
497
498MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
499MODULE_DESCRIPTION("Intel Wireless UWB Link 1480 firmware uploader for USB");
500MODULE_LICENSE("GPL");