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