示例#1
0
int cx18_firmware_init(struct cx18 *cx)
{
    /* Allow chip to control CLKRUN */
    write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);

    write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */

    cx18_msleep_timeout(1, 0);

    sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
    sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);

    /* Only if the processor is not running */
    if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
        int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
                   cx->enc_mem, cx, CX18_FW_APU_SIZE);

        sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
                    cx->enc_mem, cx, CX18_FW_CPU_SIZE);

        if (sz > 0) {
            int retries = 0;

            /* start the CPU */
            write_reg(0x00080000, CX18_PROC_SOFT_RESET);
            while (retries++ < 50) { /* Loop for max 500mS */
                if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
                    break;
                cx18_msleep_timeout(10, 0);
            }
            cx18_msleep_timeout(200, 0);
            if (retries == 51) {
                CX18_ERR("Could not start the CPU\n");
                return -EIO;
            }
        }
        if (sz <= 0)
            return -EIO;
    }
    /* initialize GPIO */
    write_reg(0x14001400, 0xC78110);
    return 0;
}
int cx18_firmware_init(struct cx18 *cx)
{
	u32 fw_entry_addr;
	int sz, retries;
	u32 api_args[MAX_MB_ARGUMENTS];

	/* Allow chip to control CLKRUN */
	cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);

	/* Stop the firmware */
	cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
				  0x0000000F, 0x000F000F);

	cx18_msleep_timeout(1, 0);

	/* If the CPU is still running */
	if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
		CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
		return -EIO;
	}

	cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
	cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);

	sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx);
	if (sz <= 0)
		return sz;

	/* The SCB & IPC area *must* be correct before starting the firmwares */
	cx18_init_scb(cx);

	fw_entry_addr = 0;
	sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx,
				&fw_entry_addr);
	if (sz <= 0)
		return sz;

	/* Start the CPU. The CPU will take care of the APU for us. */
	cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
				  0x00000000, 0x00080008);

	/* Wait up to 500 ms for the APU to come out of reset */
	for (retries = 0;
	     retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
	     retries++)
		cx18_msleep_timeout(10, 0);

	cx18_msleep_timeout(200, 0);

	if (retries == 50 &&
	    (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
		CX18_ERR("Could not start the CPU\n");
		return -EIO;
	}

	/*
	 * The CPU had once before set up to receive an interrupt for it's
	 * outgoing IRQ_CPU_TO_EPU_ACK to us.  If it ever does this, we get an
	 * interrupt when it sends us an ack, but by the time we process it,
	 * that flag in the SW2 status register has been cleared by the CPU
	 * firmware.  We'll prevent that not so useful condition from happening
	 * by clearing the CPU's interrupt enables for Ack IRQ's we want to
	 * process.
	 */
	cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);

	/* Try a benign command to see if the CPU is alive and well */
	sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
	if (sz < 0)
		return sz;

	/* initialize GPIO */
	cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
	return 0;
}