Пример #1
0
void
platform_mp_start_ap(void)
{
	uint32_t reg, *ptr, cpu_num;

	/* Copy boot code to SRAM */
	*((unsigned int*)(0xf1020240)) = 0xffff0101;
	*((unsigned int*)(0xf1008500)) = 0xffff0003;

	pmap_kenter_nocache(0x880f0000, 0xffff0000);
	reg = 0x880f0000;

	for (ptr = (uint32_t *)mptramp; ptr < (uint32_t *)mpentry;
	    ptr++, reg += 4)
		*((uint32_t *)reg) = *ptr;

	if (mp_ncpus > 1) {
		reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0);
		reg &= 0x00ffffff;
		reg |= 0x01000000;
		write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0, reg);
	}
	if (mp_ncpus > 2) {
		reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
		reg &= 0xff00ffff;
		reg |= 0x00010000;
		write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg);
	}
	if (mp_ncpus > 3) {
		reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
		reg &= 0x00ffffff;
		reg |= 0x01000000;
		write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg);
	}

	reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0);
	reg |= ((0x1 << (mp_ncpus - 1)) - 1) << 21;
	write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
	reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0);
	reg |= 0x01000000;
	write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);

	DELAY(100);
	reg &= ~(0xf << 21);
	write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
	DELAY(100);

	bus_space_write_4(fdtbus_bs_tag, MV_BASE, CPU_RESUME_CONTROL, 0);

	for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
		bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT,
		    pmap_kextract((vm_offset_t)mpentry));

	cpu_idcache_wbinv_all();

	for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
		bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0);

	/* XXX: Temporary workaround for hangup after releasing AP's */
	wmb();
	DELAY(10);

	initialize_coherency_fabric();
}
Пример #2
0
void
platform_mp_start_ap(void)
{
	uint32_t reg, *src, *dst, cpu_num, div_val, cputype;
	vm_offset_t pmu_boot_off;
	/*
	 * Initialization procedure depends on core revision,
	 * in this step CHIP ID is checked to choose proper procedure
	 */
	cputype = cpufunc_id();
	cputype &= CPU_ID_CPU_MASK;

	/*
	 * Set the PA of CPU0 Boot Address Redirect register used in
	 * mptramp according to the actual SoC registers' base address.
	 */
	pmu_boot_off = (CPU_PMU(0) - MV_BASE) + CPU_PMU_BOOT;
	mptramp_pmu_boot = fdt_immr_pa + pmu_boot_off;
	dst = pmap_mapdev(0xffff0000, PAGE_SIZE);
	for (src = (uint32_t *)mptramp; src < (uint32_t *)mptramp_end;
	    src++, dst++) {
		*dst = *src;
	}
	pmap_unmapdev((vm_offset_t)dst, PAGE_SIZE);
	if (cputype == CPU_ID_MV88SV584X_V7) {
		/* Core rev A0 */
		div_val = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
		div_val &= 0x3f;

		for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) {
			reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
			reg &= CPU_DIVCLK_MASK(cpu_num);
			reg |= div_val << (cpu_num * 8);
			write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg);
		}
	} else {
		/* Core rev Z1 */
		div_val = 0x01;

		if (mp_ncpus > 1) {
			reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0);
			reg &= CPU_DIVCLK_MASK(3);
			reg |= div_val << 24;
			write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0, reg);
		}

		for (cpu_num = 2; cpu_num < mp_ncpus; cpu_num++ ) {
			reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1);
			reg &= CPU_DIVCLK_MASK(cpu_num);
			reg |= div_val << (cpu_num * 8);
			write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg);
		}
	}

	reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0);
	reg |= ((0x1 << (mp_ncpus - 1)) - 1) << 21;
	write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
	reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0);
	reg |= 0x01000000;
	write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);

	DELAY(100);
	reg &= ~(0xf << 21);
	write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg);
	DELAY(100);

	bus_space_write_4(fdtbus_bs_tag, MV_BASE, CPU_RESUME_CONTROL, 0);

	for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
		bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT,
		    pmap_kextract((vm_offset_t)mpentry));

	cpu_idcache_wbinv_all();

	for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
		bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0);

	/* XXX: Temporary workaround for hangup after releasing AP's */
	wmb();
	DELAY(10);

	armadaxp_init_coher_fabric();
}