//! This test first starts the secondary CPUs in order from 1 through 3. When each secondary //! CPU starts, it executes this function. The first thing this function does for secondary CPUs //! is to enable interrupts for the CPU in the GIC. //! //! When the last CPU enters this function, it will start a loop of sending software interrupts //! to all cores in sequence by sending the first SGI to core 0. As each core handles the SGI, //! it will print a message and send an SGI to the next CPU in sequence. void multicore_entry(void * arg) { uint32_t cpu_id = cpu_get_current(); int cpuCount = cpu_get_cores(); if (cpuCount == 1) { printf("This chip only has one CPU!\n"); return; } if (cpu_id != 0) { // Enable interrupts on secondary CPUs. gic_init_cpu(); } // primary cpu if (cpu_id == 0) { isTestDone = 1; // register sgi isr register_interrupt_routine(SW_INTERRUPT_3, SGI3_ISR); printf("Running the GIC Multicore Test \n"); printf("Starting and sending SGIs to secondary CPUs for \"hello world\" \n\n"); // start second cpu cpu_start_secondary(1, &multicore_entry, 0); // cpu0 wait until test is done, that is until cpu3 completes its SGI. while (isTestDone); // put other cores back into reset cpu_disable(1); cpu_disable(2); cpu_disable(3); printf("\nEnd of test\n"); } // other cpus else { printf("secondary main cpu: %d\n", cpu_id); if (cpu_id == (cpuCount - 1)) { // send to cpu_0 to start sgi loop gic_send_sgi(SW_INTERRUPT_3, 1, kGicSgiFilter_UseTargetList); } else { cpu_start_secondary(cpu_id + 1, &multicore_entry, 0); } // do nothing wait to be interrupted while (1); } }
static void set_cpue(uint32_t val) { unsigned i, thisbit; struct lamebus_cpu *cpu; for (i=0; i<ncpus; i++) { thisbit = val & ((uint32_t)1 << i); cpu = &cpus[i]; if (cpu->cpu_enabled && thisbit == 0) { /* * Shutting off cpu. * * Just drop it in its tracks... */ cpu->cpu_enabled = 0; cpu_disable(i); } else if (!cpu->cpu_enabled && thisbit != 0) { /* * Turning on cpu. * * According to spec, set stack to the top end * of CRAM, and load the PC from the bottom * end of CRAM. */ uint32_t cramoffset; uint32_t stackva, pcva, arg; uint32_t *cram; cramoffset = LAMEBUS_SLOT_MEM * LAMEBUS_CONTROLLER_SLOT + 32768 + i * LAMEBUS_PERCPU_SIZE + LBC_CRAM_END; stackva = cpu_get_secondary_start_stack(cramoffset); cram = (uint32_t *)cpu->cpu_cram; pcva = ntohl(cram[0]); arg = ntohl(cram[1]); cpu_set_entrypoint(i, pcva); cpu_set_stack(i, stackva, arg); cpu_enable(i); } } }
int cpu_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned long cpuid; if (argc < 3) { cmd_usage(cmdtp); return 1; } cpuid = simple_strtoul(argv[1], NULL, 10); if (cpuid >= cpu_numcores()) { printf ("Core num: %lu is out of range[0..%d]\n", cpuid, cpu_numcores() - 1); return 1; } if (argc == 3) { if (strncmp(argv[2], "reset", 5) == 0) { cpu_reset(cpuid); } else if (strncmp(argv[2], "status", 6) == 0) { cpu_status(cpuid); } else if (strncmp(argv[2], "disable", 7) == 0) { return cpu_disable(cpuid); } else { cmd_usage(cmdtp); return 1; } return 0; } /* 4 or greater, make sure its release */ if (strncmp(argv[2], "release", 7) != 0) { cmd_usage(cmdtp); return 1; } if (cpu_release(cpuid, argc - 3, argv + 3)) { cmd_usage(cmdtp); return 1; } return 0; }
int checkcpu (void) { sys_info_t sysinfo; uint pvr, svr; uint ver; uint major, minor; struct cpu_type *cpu; char buf1[32], buf2[32]; #if defined(CONFIG_DDR_CLK_FREQ) || defined(CONFIG_FSL_CORENET) ccsr_gur_t __iomem *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); #endif /* * Cornet platforms use ddr sync bit in RCW to indicate sync vs async * mode. Previous platform use ddr ratio to do the same. This * information is only for display here. */ #ifdef CONFIG_FSL_CORENET #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 u32 ddr_sync = 0; /* only async mode is supported */ #else u32 ddr_sync = ((gur->rcwsr[5]) & FSL_CORENET_RCWSR5_DDR_SYNC) >> FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT; #endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ #else /* CONFIG_FSL_CORENET */ #ifdef CONFIG_DDR_CLK_FREQ u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO) >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT; #else u32 ddr_ratio = 0; #endif /* CONFIG_DDR_CLK_FREQ */ #endif /* CONFIG_FSL_CORENET */ unsigned int i, core, nr_cores = cpu_numcores(); u32 mask = cpu_mask(); #ifdef CONFIG_HETROGENOUS_CLUSTERS unsigned int j, dsp_core, dsp_numcores = cpu_num_dspcores(); u32 dsp_mask = cpu_dsp_mask(); #endif svr = get_svr(); major = SVR_MAJ(svr); minor = SVR_MIN(svr); #if defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2) && defined(CONFIG_E6500) if (SVR_SOC_VER(svr) == SVR_T4080) { ccsr_rcpm_t *rcpm = (void __iomem *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR); setbits_be32(&gur->devdisr2, FSL_CORENET_DEVDISR2_DTSEC1_6 || FSL_CORENET_DEVDISR2_DTSEC1_9); setbits_be32(&gur->devdisr3, FSL_CORENET_DEVDISR3_PCIE3); setbits_be32(&gur->devdisr5, FSL_CORENET_DEVDISR5_DDR3); /* It needs SW to disable core4~7 as HW design sake on T4080 */ for (i = 4; i < 8; i++) cpu_disable(i); /* request core4~7 into PH20 state, prior to entering PCL10 * state, all cores in cluster should be placed in PH20 state. */ setbits_be32(&rcpm->pcph20setr, 0xf0); /* put the 2nd cluster into PCL10 state */ setbits_be32(&rcpm->clpcl10setr, 1 << 1); } #endif if (cpu_numcores() > 1) { #ifndef CONFIG_MP puts("Unicore software on multiprocessor system!!\n" "To enable mutlticore build define CONFIG_MP\n"); #endif volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR); printf("CPU%d: ", pic->whoami); } else { puts("CPU: "); } cpu = gd->arch.cpu; puts(cpu->name); if (IS_E_PROCESSOR(svr)) puts("E"); printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); pvr = get_pvr(); ver = PVR_VER(pvr); major = PVR_MAJ(pvr); minor = PVR_MIN(pvr); printf("Core: "); switch(ver) { case PVR_VER_E500_V1: case PVR_VER_E500_V2: puts("e500"); break; case PVR_VER_E500MC: puts("e500mc"); break; case PVR_VER_E5500: puts("e5500"); break; case PVR_VER_E6500: puts("e6500"); break; default: puts("Unknown"); break; } printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr); if (nr_cores > CONFIG_MAX_CPUS) { panic("\nUnexpected number of cores: %d, max is %d\n", nr_cores, CONFIG_MAX_CPUS); } get_sys_info(&sysinfo); #ifdef CONFIG_SYS_FSL_SINGLE_SOURCE_CLK if (sysinfo.diff_sysclk == 1) puts("Single Source Clock Configuration\n"); #endif puts("Clock Configuration:"); for_each_cpu(i, core, nr_cores, mask) { if (!(i & 3)) printf ("\n "); printf("CPU%d:%-4s MHz, ", core, strmhz(buf1, sysinfo.freq_processor[core])); } #ifdef CONFIG_HETROGENOUS_CLUSTERS for_each_cpu(j, dsp_core, dsp_numcores, dsp_mask) { if (!(j & 3)) printf("\n "); printf("DSP CPU%d:%-4s MHz, ", j, strmhz(buf1, sysinfo.freq_processor_dsp[dsp_core])); } #endif printf("\n CCB:%-4s MHz,", strmhz(buf1, sysinfo.freq_systembus)); printf("\n"); #ifdef CONFIG_FSL_CORENET if (ddr_sync == 1) { printf(" DDR:%-4s MHz (%s MT/s data rate) " "(Synchronous), ", strmhz(buf1, sysinfo.freq_ddrbus/2), strmhz(buf2, sysinfo.freq_ddrbus)); } else { printf(" DDR:%-4s MHz (%s MT/s data rate) " "(Asynchronous), ", strmhz(buf1, sysinfo.freq_ddrbus/2), strmhz(buf2, sysinfo.freq_ddrbus)); } #else switch (ddr_ratio) { case 0x0: printf(" DDR:%-4s MHz (%s MT/s data rate), ", strmhz(buf1, sysinfo.freq_ddrbus/2), strmhz(buf2, sysinfo.freq_ddrbus)); break; case 0x7: printf(" DDR:%-4s MHz (%s MT/s data rate) " "(Synchronous), ", strmhz(buf1, sysinfo.freq_ddrbus/2), strmhz(buf2, sysinfo.freq_ddrbus)); break; default: printf(" DDR:%-4s MHz (%s MT/s data rate) " "(Asynchronous), ", strmhz(buf1, sysinfo.freq_ddrbus/2), strmhz(buf2, sysinfo.freq_ddrbus)); break; } #endif #if defined(CONFIG_FSL_LBC) if (sysinfo.freq_localbus > LCRR_CLKDIV) { printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freq_localbus)); } else { printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n", sysinfo.freq_localbus); } #endif #if defined(CONFIG_FSL_IFC) printf("IFC:%-4s MHz\n", strmhz(buf1, sysinfo.freq_localbus)); #endif #ifdef CONFIG_CPM2 printf("CPM: %s MHz\n", strmhz(buf1, sysinfo.freq_systembus)); #endif #ifdef CONFIG_QE printf(" QE:%-4s MHz\n", strmhz(buf1, sysinfo.freq_qe)); #endif #if defined(CONFIG_SYS_CPRI) printf(" "); printf("CPRI:%-4s MHz", strmhz(buf1, sysinfo.freq_cpri)); #endif #if defined(CONFIG_SYS_MAPLE) printf("\n "); printf("MAPLE:%-4s MHz, ", strmhz(buf1, sysinfo.freq_maple)); printf("MAPLE-ULB:%-4s MHz, ", strmhz(buf1, sysinfo.freq_maple_ulb)); printf("MAPLE-eTVPE:%-4s MHz\n", strmhz(buf1, sysinfo.freq_maple_etvpe)); #endif #ifdef CONFIG_SYS_DPAA_FMAN for (i = 0; i < CONFIG_SYS_NUM_FMAN; i++) { printf(" FMAN%d: %s MHz\n", i + 1, strmhz(buf1, sysinfo.freq_fman[i])); } #endif #ifdef CONFIG_SYS_DPAA_QBMAN printf(" QMAN: %s MHz\n", strmhz(buf1, sysinfo.freq_qman)); #endif #ifdef CONFIG_SYS_DPAA_PME printf(" PME: %s MHz\n", strmhz(buf1, sysinfo.freq_pme)); #endif puts("L1: D-cache 32 KiB enabled\n I-cache 32 KiB enabled\n"); #ifdef CONFIG_FSL_CORENET /* Display the RCW, so that no one gets confused as to what RCW * we're actually using for this boot. */ puts("Reset Configuration Word (RCW):"); for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { u32 rcw = in_be32(&gur->rcwsr[i]); if ((i % 4) == 0) printf("\n %08x:", i * 4); printf(" %08x", rcw); } puts("\n"); #endif return 0; }