|
@@ -31,40 +31,58 @@ int cx18_av_loadfw(struct cx18 *cx)
|
|
|
u32 v;
|
|
|
const u8 *ptr;
|
|
|
int i;
|
|
|
+ int retries = 0;
|
|
|
|
|
|
if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
|
|
|
CX18_ERR("unable to open firmware %s\n", FWFILE);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
|
|
|
- cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */
|
|
|
-
|
|
|
- /* Reset the Mako core (Register is undocumented.) */
|
|
|
- cx18_av_write4(cx, 0x8100, 0x00010000);
|
|
|
-
|
|
|
- /* Put the 8051 in reset and enable firmware upload */
|
|
|
- cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
|
|
|
-
|
|
|
- ptr = fw->data;
|
|
|
- size = fw->size;
|
|
|
-
|
|
|
- for (i = 0; i < size; i++) {
|
|
|
- u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16);
|
|
|
- u32 value = 0;
|
|
|
- int retries;
|
|
|
-
|
|
|
- for (retries = 0; retries < 5; retries++) {
|
|
|
- cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
|
|
|
- value = cx18_av_read4(cx, CXADEC_DL_CTL);
|
|
|
- if ((value & 0x3F00) == (dl_control & 0x3F00))
|
|
|
+ /* The firmware load often has byte errors, so allow for several
|
|
|
+ retries, both at byte level and at the firmware load level. */
|
|
|
+ while (retries < 5) {
|
|
|
+ cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
|
|
|
+ cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
|
|
|
+
|
|
|
+ /* Reset the Mako core (Register is undocumented.) */
|
|
|
+ cx18_av_write4(cx, 0x8100, 0x00010000);
|
|
|
+
|
|
|
+ /* Put the 8051 in reset and enable firmware upload */
|
|
|
+ cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
|
|
|
+
|
|
|
+ ptr = fw->data;
|
|
|
+ size = fw->size;
|
|
|
+
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
|
|
|
+ u32 value = 0;
|
|
|
+ int retries;
|
|
|
+
|
|
|
+ for (retries = 0; retries < 5; retries++) {
|
|
|
+ cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
|
|
|
+ udelay(10);
|
|
|
+ value = cx18_av_read4(cx, CXADEC_DL_CTL);
|
|
|
+ if (value == dl_control)
|
|
|
+ break;
|
|
|
+ /* Check if we can correct the byte by changing
|
|
|
+ the address. We can only write the lower
|
|
|
+ address byte of the address. */
|
|
|
+ if ((value & 0x3F00) != (dl_control & 0x3F00)) {
|
|
|
+ retries = 5;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (retries >= 5)
|
|
|
break;
|
|
|
}
|
|
|
- if (retries >= 5) {
|
|
|
- CX18_ERR("unable to load firmware %s\n", FWFILE);
|
|
|
- release_firmware(fw);
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
+ if (i == size)
|
|
|
+ break;
|
|
|
+ retries++;
|
|
|
+ }
|
|
|
+ if (retries >= 5) {
|
|
|
+ CX18_ERR("unable to load firmware %s\n", FWFILE);
|
|
|
+ release_firmware(fw);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
|