1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Driver for the NXP SAA7164 PCIe bridge |
4 | * |
5 | * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com> |
6 | */ |
7 | |
8 | #include <linux/firmware.h> |
9 | #include <linux/slab.h> |
10 | |
11 | #include "saa7164.h" |
12 | |
13 | #define SAA7164_REV2_FIRMWARE "NXP7164-2010-03-10.1.fw" |
14 | #define SAA7164_REV2_FIRMWARE_SIZE 4019072 |
15 | |
16 | #define SAA7164_REV3_FIRMWARE "NXP7164-2010-03-10.1.fw" |
17 | #define SAA7164_REV3_FIRMWARE_SIZE 4019072 |
18 | |
19 | struct { |
20 | u32 ; |
21 | u32 ; |
22 | u32 ; |
23 | u32 ; |
24 | }; |
25 | |
26 | static int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg) |
27 | { |
28 | u32 timeout = SAA_DEVICE_TIMEOUT; |
29 | while ((saa7164_readl(reg) & 0x01) == 0) { |
30 | timeout -= 10; |
31 | if (timeout == 0) { |
32 | printk(KERN_ERR "%s() timeout (no d/l ack)\n" , |
33 | __func__); |
34 | return -EBUSY; |
35 | } |
36 | msleep(msecs: 100); |
37 | } |
38 | |
39 | return 0; |
40 | } |
41 | |
42 | static int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg) |
43 | { |
44 | u32 timeout = SAA_DEVICE_TIMEOUT; |
45 | while (saa7164_readl(reg) & 0x01) { |
46 | timeout -= 10; |
47 | if (timeout == 0) { |
48 | printk(KERN_ERR "%s() timeout (no d/l clr)\n" , |
49 | __func__); |
50 | return -EBUSY; |
51 | } |
52 | msleep(msecs: 100); |
53 | } |
54 | |
55 | return 0; |
56 | } |
57 | |
58 | /* TODO: move dlflags into dev-> and change to write/readl/b */ |
59 | /* TODO: Excessive levels of debug */ |
60 | static int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize, |
61 | u32 dlflags, u8 __iomem *dst, u32 dstsize) |
62 | { |
63 | u32 reg, timeout, offset; |
64 | u8 *srcbuf = NULL; |
65 | int ret; |
66 | |
67 | u32 dlflag = dlflags; |
68 | u32 dlflag_ack = dlflag + 4; |
69 | u32 drflag = dlflag_ack + 4; |
70 | u32 drflag_ack = drflag + 4; |
71 | u32 bleflag = drflag_ack + 4; |
72 | |
73 | dprintk(DBGLVL_FW, |
74 | "%s(image=%p, size=%d, flags=0x%x, dst=%p, dstsize=0x%x)\n" , |
75 | __func__, src, srcsize, dlflags, dst, dstsize); |
76 | |
77 | if ((src == NULL) || (dst == NULL)) { |
78 | ret = -EIO; |
79 | goto out; |
80 | } |
81 | |
82 | srcbuf = kzalloc(size: 4 * 1048576, GFP_KERNEL); |
83 | if (NULL == srcbuf) { |
84 | ret = -ENOMEM; |
85 | goto out; |
86 | } |
87 | |
88 | if (srcsize > (4*1048576)) { |
89 | ret = -ENOMEM; |
90 | goto out; |
91 | } |
92 | |
93 | memcpy(srcbuf, src, srcsize); |
94 | |
95 | dprintk(DBGLVL_FW, "%s() dlflag = 0x%x\n" , __func__, dlflag); |
96 | dprintk(DBGLVL_FW, "%s() dlflag_ack = 0x%x\n" , __func__, dlflag_ack); |
97 | dprintk(DBGLVL_FW, "%s() drflag = 0x%x\n" , __func__, drflag); |
98 | dprintk(DBGLVL_FW, "%s() drflag_ack = 0x%x\n" , __func__, drflag_ack); |
99 | dprintk(DBGLVL_FW, "%s() bleflag = 0x%x\n" , __func__, bleflag); |
100 | |
101 | reg = saa7164_readl(dlflag); |
102 | dprintk(DBGLVL_FW, "%s() dlflag (0x%x)= 0x%x\n" , __func__, dlflag, reg); |
103 | if (reg == 1) |
104 | dprintk(DBGLVL_FW, |
105 | "%s() Download flag already set, please reboot\n" , |
106 | __func__); |
107 | |
108 | /* Indicate download start */ |
109 | saa7164_writel(dlflag, 1); |
110 | ret = saa7164_dl_wait_ack(dev, reg: dlflag_ack); |
111 | if (ret < 0) |
112 | goto out; |
113 | |
114 | /* Ack download start, then wait for wait */ |
115 | saa7164_writel(dlflag, 0); |
116 | ret = saa7164_dl_wait_clr(dev, reg: dlflag_ack); |
117 | if (ret < 0) |
118 | goto out; |
119 | |
120 | /* Deal with the raw firmware, in the appropriate chunk size */ |
121 | for (offset = 0; srcsize > dstsize; |
122 | srcsize -= dstsize, offset += dstsize) { |
123 | |
124 | dprintk(DBGLVL_FW, "%s() memcpy %d\n" , __func__, dstsize); |
125 | memcpy_toio(dst, srcbuf + offset, dstsize); |
126 | |
127 | /* Flag the data as ready */ |
128 | saa7164_writel(drflag, 1); |
129 | ret = saa7164_dl_wait_ack(dev, reg: drflag_ack); |
130 | if (ret < 0) |
131 | goto out; |
132 | |
133 | /* Wait for indication data was received */ |
134 | saa7164_writel(drflag, 0); |
135 | ret = saa7164_dl_wait_clr(dev, reg: drflag_ack); |
136 | if (ret < 0) |
137 | goto out; |
138 | |
139 | } |
140 | |
141 | dprintk(DBGLVL_FW, "%s() memcpy(l) %d\n" , __func__, dstsize); |
142 | /* Write last block to the device */ |
143 | memcpy_toio(dst, srcbuf+offset, srcsize); |
144 | |
145 | /* Flag the data as ready */ |
146 | saa7164_writel(drflag, 1); |
147 | ret = saa7164_dl_wait_ack(dev, reg: drflag_ack); |
148 | if (ret < 0) |
149 | goto out; |
150 | |
151 | saa7164_writel(drflag, 0); |
152 | timeout = 0; |
153 | while (saa7164_readl(bleflag) != SAA_DEVICE_IMAGE_BOOTING) { |
154 | if (saa7164_readl(bleflag) & SAA_DEVICE_IMAGE_CORRUPT) { |
155 | printk(KERN_ERR "%s() image corrupt\n" , __func__); |
156 | ret = -EBUSY; |
157 | goto out; |
158 | } |
159 | |
160 | if (saa7164_readl(bleflag) & SAA_DEVICE_MEMORY_CORRUPT) { |
161 | printk(KERN_ERR "%s() device memory corrupt\n" , |
162 | __func__); |
163 | ret = -EBUSY; |
164 | goto out; |
165 | } |
166 | |
167 | msleep(msecs: 10); /* Checkpatch throws a < 20ms warning */ |
168 | if (timeout++ > 60) |
169 | break; |
170 | } |
171 | |
172 | printk(KERN_INFO "%s() Image downloaded, booting...\n" , __func__); |
173 | |
174 | ret = saa7164_dl_wait_clr(dev, reg: drflag_ack); |
175 | if (ret < 0) |
176 | goto out; |
177 | |
178 | printk(KERN_INFO "%s() Image booted successfully.\n" , __func__); |
179 | ret = 0; |
180 | |
181 | out: |
182 | kfree(objp: srcbuf); |
183 | return ret; |
184 | } |
185 | |
186 | /* TODO: Excessive debug */ |
187 | /* Load the firmware. Optionally it can be in ROM or newer versions |
188 | * can be on disk, saving the expense of the ROM hardware. */ |
189 | int saa7164_downloadfirmware(struct saa7164_dev *dev) |
190 | { |
191 | /* u32 second_timeout = 60 * SAA_DEVICE_TIMEOUT; */ |
192 | u32 tmp, filesize, version, err_flags, first_timeout, fwlength; |
193 | u32 second_timeout, updatebootloader = 1, bootloadersize = 0; |
194 | const struct firmware *fw = NULL; |
195 | struct fw_header *hdr, *boothdr = NULL, *fwhdr; |
196 | u32 bootloaderversion = 0, fwloadersize; |
197 | u8 *bootloaderoffset = NULL, *fwloaderoffset; |
198 | char *fwname; |
199 | int ret; |
200 | |
201 | dprintk(DBGLVL_FW, "%s()\n" , __func__); |
202 | |
203 | if (saa7164_boards[dev->board].chiprev == SAA7164_CHIP_REV2) { |
204 | fwname = SAA7164_REV2_FIRMWARE; |
205 | fwlength = SAA7164_REV2_FIRMWARE_SIZE; |
206 | } else { |
207 | fwname = SAA7164_REV3_FIRMWARE; |
208 | fwlength = SAA7164_REV3_FIRMWARE_SIZE; |
209 | } |
210 | |
211 | version = saa7164_getcurrentfirmwareversion(dev); |
212 | |
213 | if (version == 0x00) { |
214 | |
215 | second_timeout = 100; |
216 | first_timeout = 100; |
217 | err_flags = saa7164_readl(SAA_BOOTLOADERERROR_FLAGS); |
218 | dprintk(DBGLVL_FW, "%s() err_flags = %x\n" , |
219 | __func__, err_flags); |
220 | |
221 | while (err_flags != SAA_DEVICE_IMAGE_BOOTING) { |
222 | dprintk(DBGLVL_FW, "%s() err_flags = %x\n" , |
223 | __func__, err_flags); |
224 | msleep(msecs: 10); /* Checkpatch throws a < 20ms warning */ |
225 | |
226 | if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) { |
227 | printk(KERN_ERR "%s() firmware corrupt\n" , |
228 | __func__); |
229 | break; |
230 | } |
231 | if (err_flags & SAA_DEVICE_MEMORY_CORRUPT) { |
232 | printk(KERN_ERR "%s() device memory corrupt\n" , |
233 | __func__); |
234 | break; |
235 | } |
236 | if (err_flags & SAA_DEVICE_NO_IMAGE) { |
237 | printk(KERN_ERR "%s() no first image\n" , |
238 | __func__); |
239 | break; |
240 | } |
241 | if (err_flags & SAA_DEVICE_IMAGE_SEARCHING) { |
242 | first_timeout -= 10; |
243 | if (first_timeout == 0) { |
244 | printk(KERN_ERR |
245 | "%s() no first image\n" , |
246 | __func__); |
247 | break; |
248 | } |
249 | } else if (err_flags & SAA_DEVICE_IMAGE_LOADING) { |
250 | second_timeout -= 10; |
251 | if (second_timeout == 0) { |
252 | printk(KERN_ERR |
253 | "%s() FW load time exceeded\n" , |
254 | __func__); |
255 | break; |
256 | } |
257 | } else { |
258 | second_timeout -= 10; |
259 | if (second_timeout == 0) { |
260 | printk(KERN_ERR |
261 | "%s() Unknown bootloader flags 0x%x\n" , |
262 | __func__, err_flags); |
263 | break; |
264 | } |
265 | } |
266 | |
267 | err_flags = saa7164_readl(SAA_BOOTLOADERERROR_FLAGS); |
268 | } /* While != Booting */ |
269 | |
270 | if (err_flags == SAA_DEVICE_IMAGE_BOOTING) { |
271 | dprintk(DBGLVL_FW, "%s() Loader 1 has loaded.\n" , |
272 | __func__); |
273 | first_timeout = SAA_DEVICE_TIMEOUT; |
274 | second_timeout = 100; |
275 | |
276 | err_flags = saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS); |
277 | dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n" , |
278 | __func__, err_flags); |
279 | while (err_flags != SAA_DEVICE_IMAGE_BOOTING) { |
280 | dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n" , |
281 | __func__, err_flags); |
282 | msleep(msecs: 10); /* Checkpatch throws a < 20ms warning */ |
283 | |
284 | if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) { |
285 | printk(KERN_ERR |
286 | "%s() firmware corrupt\n" , |
287 | __func__); |
288 | break; |
289 | } |
290 | if (err_flags & SAA_DEVICE_MEMORY_CORRUPT) { |
291 | printk(KERN_ERR |
292 | "%s() device memory corrupt\n" , |
293 | __func__); |
294 | break; |
295 | } |
296 | if (err_flags & SAA_DEVICE_NO_IMAGE) { |
297 | printk(KERN_ERR "%s() no second image\n" , |
298 | __func__); |
299 | break; |
300 | } |
301 | if (err_flags & SAA_DEVICE_IMAGE_SEARCHING) { |
302 | first_timeout -= 10; |
303 | if (first_timeout == 0) { |
304 | printk(KERN_ERR |
305 | "%s() no second image\n" , |
306 | __func__); |
307 | break; |
308 | } |
309 | } else if (err_flags & |
310 | SAA_DEVICE_IMAGE_LOADING) { |
311 | second_timeout -= 10; |
312 | if (second_timeout == 0) { |
313 | printk(KERN_ERR |
314 | "%s() FW load time exceeded\n" , |
315 | __func__); |
316 | break; |
317 | } |
318 | } else { |
319 | second_timeout -= 10; |
320 | if (second_timeout == 0) { |
321 | printk(KERN_ERR |
322 | "%s() Unknown bootloader flags 0x%x\n" , |
323 | __func__, err_flags); |
324 | break; |
325 | } |
326 | } |
327 | |
328 | err_flags = |
329 | saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS); |
330 | } /* err_flags != SAA_DEVICE_IMAGE_BOOTING */ |
331 | |
332 | dprintk(DBGLVL_FW, "%s() Loader flags 1:0x%x 2:0x%x.\n" , |
333 | __func__, |
334 | saa7164_readl(SAA_BOOTLOADERERROR_FLAGS), |
335 | saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS)); |
336 | |
337 | } /* err_flags == SAA_DEVICE_IMAGE_BOOTING */ |
338 | |
339 | /* It's possible for both firmwares to have booted, |
340 | * but that doesn't mean they've finished booting yet. |
341 | */ |
342 | if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) == |
343 | SAA_DEVICE_IMAGE_BOOTING) && |
344 | (saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS) == |
345 | SAA_DEVICE_IMAGE_BOOTING)) { |
346 | |
347 | |
348 | dprintk(DBGLVL_FW, "%s() Loader 2 has loaded.\n" , |
349 | __func__); |
350 | |
351 | first_timeout = SAA_DEVICE_TIMEOUT; |
352 | while (first_timeout) { |
353 | msleep(msecs: 10); /* Checkpatch throws a < 20ms warning */ |
354 | |
355 | version = |
356 | saa7164_getcurrentfirmwareversion(dev); |
357 | if (version) { |
358 | dprintk(DBGLVL_FW, |
359 | "%s() All f/w loaded successfully\n" , |
360 | __func__); |
361 | break; |
362 | } else { |
363 | first_timeout -= 10; |
364 | if (first_timeout == 0) { |
365 | printk(KERN_ERR |
366 | "%s() FW did not boot\n" , |
367 | __func__); |
368 | break; |
369 | } |
370 | } |
371 | } |
372 | } |
373 | version = saa7164_getcurrentfirmwareversion(dev); |
374 | } /* version == 0 */ |
375 | |
376 | /* Has the firmware really booted? */ |
377 | if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) == |
378 | SAA_DEVICE_IMAGE_BOOTING) && |
379 | (saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS) == |
380 | SAA_DEVICE_IMAGE_BOOTING) && (version == 0)) { |
381 | |
382 | printk(KERN_ERR |
383 | "%s() The firmware hung, probably bad firmware\n" , |
384 | __func__); |
385 | |
386 | /* Tell the second stage loader we have a deadlock */ |
387 | saa7164_writel(SAA_DEVICE_DEADLOCK_DETECTED_OFFSET, |
388 | SAA_DEVICE_DEADLOCK_DETECTED); |
389 | |
390 | saa7164_getfirmwarestatus(dev); |
391 | |
392 | return -ENOMEM; |
393 | } |
394 | |
395 | dprintk(DBGLVL_FW, "Device has Firmware Version %d.%d.%d.%d\n" , |
396 | (version & 0x0000fc00) >> 10, |
397 | (version & 0x000003e0) >> 5, |
398 | (version & 0x0000001f), |
399 | (version & 0xffff0000) >> 16); |
400 | |
401 | /* Load the firmware from the disk if required */ |
402 | if (version == 0) { |
403 | |
404 | printk(KERN_INFO "%s() Waiting for firmware upload (%s)\n" , |
405 | __func__, fwname); |
406 | |
407 | ret = request_firmware(fw: &fw, name: fwname, device: &dev->pci->dev); |
408 | if (ret) { |
409 | printk(KERN_ERR "%s() Upload failed. (file not found?)\n" , |
410 | __func__); |
411 | return -ENOMEM; |
412 | } |
413 | |
414 | printk(KERN_INFO "%s() firmware read %zu bytes.\n" , |
415 | __func__, fw->size); |
416 | |
417 | if (fw->size != fwlength) { |
418 | printk(KERN_ERR "saa7164: firmware incorrect size %zu != %u\n" , |
419 | fw->size, fwlength); |
420 | ret = -ENOMEM; |
421 | goto out; |
422 | } |
423 | |
424 | printk(KERN_INFO "%s() firmware loaded.\n" , __func__); |
425 | |
426 | hdr = (struct fw_header *)fw->data; |
427 | printk(KERN_INFO "Firmware file header part 1:\n" ); |
428 | printk(KERN_INFO " .FirmwareSize = 0x%x\n" , hdr->firmwaresize); |
429 | printk(KERN_INFO " .BSLSize = 0x%x\n" , hdr->bslsize); |
430 | printk(KERN_INFO " .Reserved = 0x%x\n" , hdr->reserved); |
431 | printk(KERN_INFO " .Version = 0x%x\n" , hdr->version); |
432 | |
433 | /* Retrieve bootloader if reqd */ |
434 | if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) |
435 | /* Second bootloader in the firmware file */ |
436 | filesize = hdr->reserved * 16; |
437 | else |
438 | filesize = (hdr->firmwaresize + hdr->bslsize) * |
439 | 16 + sizeof(struct fw_header); |
440 | |
441 | printk(KERN_INFO "%s() SecBootLoader.FileSize = %d\n" , |
442 | __func__, filesize); |
443 | |
444 | /* Get bootloader (if reqd) and firmware header */ |
445 | if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) { |
446 | /* Second boot loader is required */ |
447 | |
448 | /* Get the loader header */ |
449 | boothdr = (struct fw_header *)(fw->data + |
450 | sizeof(struct fw_header)); |
451 | |
452 | bootloaderversion = |
453 | saa7164_readl(SAA_DEVICE_2ND_VERSION); |
454 | dprintk(DBGLVL_FW, "Onboard BootLoader:\n" ); |
455 | dprintk(DBGLVL_FW, "->Flag 0x%x\n" , |
456 | saa7164_readl(SAA_BOOTLOADERERROR_FLAGS)); |
457 | dprintk(DBGLVL_FW, "->Ack 0x%x\n" , |
458 | saa7164_readl(SAA_DATAREADY_FLAG_ACK)); |
459 | dprintk(DBGLVL_FW, "->FW Version 0x%x\n" , version); |
460 | dprintk(DBGLVL_FW, "->Loader Version 0x%x\n" , |
461 | bootloaderversion); |
462 | |
463 | if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) == |
464 | 0x03) && (saa7164_readl(SAA_DATAREADY_FLAG_ACK) |
465 | == 0x00) && (version == 0x00)) { |
466 | |
467 | dprintk(DBGLVL_FW, "BootLoader version in rom %d.%d.%d.%d\n" , |
468 | (bootloaderversion & 0x0000fc00) >> 10, |
469 | (bootloaderversion & 0x000003e0) >> 5, |
470 | (bootloaderversion & 0x0000001f), |
471 | (bootloaderversion & 0xffff0000) >> 16 |
472 | ); |
473 | dprintk(DBGLVL_FW, "BootLoader version in file %d.%d.%d.%d\n" , |
474 | (boothdr->version & 0x0000fc00) >> 10, |
475 | (boothdr->version & 0x000003e0) >> 5, |
476 | (boothdr->version & 0x0000001f), |
477 | (boothdr->version & 0xffff0000) >> 16 |
478 | ); |
479 | |
480 | if (bootloaderversion == boothdr->version) |
481 | updatebootloader = 0; |
482 | } |
483 | |
484 | /* Calculate offset to firmware header */ |
485 | tmp = (boothdr->firmwaresize + boothdr->bslsize) * 16 + |
486 | (sizeof(struct fw_header) + |
487 | sizeof(struct fw_header)); |
488 | |
489 | fwhdr = (struct fw_header *)(fw->data+tmp); |
490 | } else { |
491 | /* No second boot loader */ |
492 | fwhdr = hdr; |
493 | } |
494 | |
495 | dprintk(DBGLVL_FW, "Firmware version in file %d.%d.%d.%d\n" , |
496 | (fwhdr->version & 0x0000fc00) >> 10, |
497 | (fwhdr->version & 0x000003e0) >> 5, |
498 | (fwhdr->version & 0x0000001f), |
499 | (fwhdr->version & 0xffff0000) >> 16 |
500 | ); |
501 | |
502 | if (version == fwhdr->version) { |
503 | /* No download, firmware already on board */ |
504 | ret = 0; |
505 | goto out; |
506 | } |
507 | |
508 | if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) { |
509 | if (updatebootloader) { |
510 | /* Get ready to upload the bootloader */ |
511 | bootloadersize = (boothdr->firmwaresize + |
512 | boothdr->bslsize) * 16 + |
513 | sizeof(struct fw_header); |
514 | |
515 | bootloaderoffset = (u8 *)(fw->data + |
516 | sizeof(struct fw_header)); |
517 | |
518 | dprintk(DBGLVL_FW, "bootloader d/l starts.\n" ); |
519 | printk(KERN_INFO "%s() FirmwareSize = 0x%x\n" , |
520 | __func__, boothdr->firmwaresize); |
521 | printk(KERN_INFO "%s() BSLSize = 0x%x\n" , |
522 | __func__, boothdr->bslsize); |
523 | printk(KERN_INFO "%s() Reserved = 0x%x\n" , |
524 | __func__, boothdr->reserved); |
525 | printk(KERN_INFO "%s() Version = 0x%x\n" , |
526 | __func__, boothdr->version); |
527 | ret = saa7164_downloadimage( |
528 | dev, |
529 | src: bootloaderoffset, |
530 | srcsize: bootloadersize, |
531 | SAA_DOWNLOAD_FLAGS, |
532 | dst: dev->bmmio + SAA_DEVICE_DOWNLOAD_OFFSET, |
533 | SAA_DEVICE_BUFFERBLOCKSIZE); |
534 | if (ret < 0) { |
535 | printk(KERN_ERR |
536 | "bootloader d/l has failed\n" ); |
537 | goto out; |
538 | } |
539 | dprintk(DBGLVL_FW, |
540 | "bootloader download complete.\n" ); |
541 | |
542 | } |
543 | |
544 | printk(KERN_ERR "starting firmware download(2)\n" ); |
545 | bootloadersize = (boothdr->firmwaresize + |
546 | boothdr->bslsize) * 16 + |
547 | sizeof(struct fw_header); |
548 | |
549 | bootloaderoffset = |
550 | (u8 *)(fw->data + sizeof(struct fw_header)); |
551 | |
552 | fwloaderoffset = bootloaderoffset + bootloadersize; |
553 | |
554 | /* TODO: fix this bounds overrun here with old f/ws */ |
555 | fwloadersize = (fwhdr->firmwaresize + fwhdr->bslsize) * |
556 | 16 + sizeof(struct fw_header); |
557 | |
558 | ret = saa7164_downloadimage( |
559 | dev, |
560 | src: fwloaderoffset, |
561 | srcsize: fwloadersize, |
562 | SAA_DEVICE_2ND_DOWNLOADFLAG_OFFSET, |
563 | dst: dev->bmmio + SAA_DEVICE_2ND_DOWNLOAD_OFFSET, |
564 | SAA_DEVICE_2ND_BUFFERBLOCKSIZE); |
565 | if (ret < 0) { |
566 | printk(KERN_ERR "firmware download failed\n" ); |
567 | goto out; |
568 | } |
569 | printk(KERN_ERR "firmware download complete.\n" ); |
570 | |
571 | } else { |
572 | |
573 | /* No bootloader update reqd, download firmware only */ |
574 | printk(KERN_ERR "starting firmware download(3)\n" ); |
575 | |
576 | ret = saa7164_downloadimage( |
577 | dev, |
578 | src: (u8 *)fw->data, |
579 | srcsize: fw->size, |
580 | SAA_DOWNLOAD_FLAGS, |
581 | dst: dev->bmmio + SAA_DEVICE_DOWNLOAD_OFFSET, |
582 | SAA_DEVICE_BUFFERBLOCKSIZE); |
583 | if (ret < 0) { |
584 | printk(KERN_ERR "firmware download failed\n" ); |
585 | goto out; |
586 | } |
587 | printk(KERN_ERR "firmware download complete.\n" ); |
588 | } |
589 | } |
590 | |
591 | dev->firmwareloaded = 1; |
592 | ret = 0; |
593 | |
594 | out: |
595 | release_firmware(fw); |
596 | return ret; |
597 | } |
598 | |