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