AnsweredAssumed Answered

LS1021A. How to start secondary core in a baremetal program loaded via U-Boot?

Question asked by Artem Epishkin on Jun 10, 2016
Latest reply on Jan 3, 2018 by Yaset Oliva

Hello Everyone.

I am having problems booting up core1 of my ls1021a. I compile with QorIQ SDK and plan to run bare metal applications in SMP mode and load them via U-Boot. It seems to me that U-Boot somehow sends all secondary cores to sleep or wait-for-interrupt state during its initialization, so only core0 executes my startup.S code. I've been looking though the Linux kernel source files for this CPU and found the following functions related to second core boot-up procedure:

void ls1021a_set_secondary_entry(void)
{
    unsigned long paddr;

    if (dcfg_base) {
        paddr = virt_to_phys(secondary_startup);
        writel_relaxed(cpu_to_be32(paddr),
                dcfg_base + DCFG_CCSR_SCRATCHRW1);
    }
}

static int ls1021a_reset_secondary(unsigned int cpu)
{
    u32 tmp;

    if (!scfg_base || !dcfg_base || !dcsr_rcpm2_base)
        return -ENOMEM;

    writel_relaxed(secondary_pre_boot_entry,
            dcfg_base + DCFG_CCSR_SCRATCHRW1);

    /* Apply LS1021A specific to write to the BE SCFG space */
    tmp = ioread32be(scfg_base + SCFG_REVCR);
    iowrite32be(0xffffffff, scfg_base + SCFG_REVCR);

    /* Soft reset secondary core */
    iowrite32be(0x80000000, scfg_base + SCFG_CORESRENCR);
    iowrite32be(0x80000000, scfg_base +
                SCFG_CORE0_SFT_RST + STRIDE_4B * cpu);
    mdelay(15);

    /* Release secondary core */
    iowrite32be(1 << cpu, dcfg_base + DCFG_CCSR_BRR);

    ls1021a_set_secondary_entry();

    /* Disable core soft reset register */
    iowrite32be(0x0, scfg_base + SCFG_CORESRENCR);

    /* Revert back to the default */
    iowrite32be(tmp, scfg_base + SCFG_REVCR);

    return 0;
}

static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
    int ret = 0;

    if (system_state == SYSTEM_RUNNING)
        ret = ls1021a_reset_secondary(cpu);

    udelay(1);

    arch_send_wakeup_ipi_mask(cpumask_of(cpu));

    return ret;
}

static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
{
    ls1021a_secondary_iomap();

    secondary_pre_boot_entry = readl_relaxed(dcfg_base +
                        DCFG_CCSR_SCRATCHRW1);

    ls1021a_set_secondary_entry();
}

 

As far as I understand, in order to successful wake up core1 the following has to be executed by core0:

1) Set DCFG_CCSR_SCRATCHRW1 so that it points to the entry code for core1.

2) Enable soft reset .

3) Reset core1.

4) Release core1 from hold-off by setting DCFG_CCSR_BRR to 0x2 or 0x3.

5) Send software interrupt from core0 to core1.

It doesn't work for me when I load  my app via U-Boot. Core1 just doesn't start. I've checked all the big-little endian conversions and still nothing.

Is it a correct procedure? What could be the problem?

Outcomes