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