static struct uasm_label labels[32] __initdata;
static struct uasm_reloc relocs[32] __initdata;
-/* CPU dependant sync types */
-static unsigned stype_intervention;
-static unsigned stype_memory;
-static unsigned stype_ordering;
-
enum mips_reg {
zero, at, v0, v1, a0, a1, a2, a3,
t0, t1, t2, t3, t4, t5, t6, t7,
return -EINVAL;
/* Calculate which coupled CPUs (VPEs) are online */
-#ifdef CONFIG_MIPS_MT
+#if defined(CONFIG_MIPS_MT) || defined(CONFIG_CPU_MIPSR6)
if (cpu_online(cpu)) {
cpumask_and(coupled_mask, cpu_online_mask,
&cpu_sibling_map[cpu]);
/* On older ones it's unavailable */
return -1;
- /* CPUs which do not require the workaround */
- case CPU_P5600:
- case CPU_I6400:
- return 0;
-
default:
- WARN_ONCE(1, "pm-cps: FSB flush unsupported for this CPU\n");
- return -1;
+ /* Assume that the CPU does not need this workaround */
+ return 0;
}
/*
i * line_size * line_stride, t0);
}
- /* Completion barrier */
- uasm_i_sync(pp, stype_memory);
+ /* Barrier ensuring previous cache invalidates are complete */
+ uasm_i_sync(pp, STYPE_SYNC);
uasm_i_ehb(pp);
/* Check whether the pipeline stalled due to the FSB being full */
if (coupled_coherence) {
/* Increment ready_count */
- uasm_i_sync(&p, stype_ordering);
+ uasm_i_sync(&p, STYPE_SYNC_MB);
uasm_build_label(&l, p, lbl_incready);
uasm_i_ll(&p, t1, 0, r_nc_count);
uasm_i_addiu(&p, t2, t1, 1);
uasm_il_beqz(&p, &r, t2, lbl_incready);
uasm_i_addiu(&p, t1, t1, 1);
- /* Ordering barrier */
- uasm_i_sync(&p, stype_ordering);
+ /* Barrier ensuring all CPUs see the updated r_nc_count value */
+ uasm_i_sync(&p, STYPE_SYNC_MB);
/*
* If this is the last VPE to become ready for non-coherence
uasm_i_lw(&p, t0, 0, r_nc_count);
uasm_il_bltz(&p, &r, t0, lbl_secondary_cont);
uasm_i_ehb(&p);
- uasm_i_yield(&p, zero, t1);
+ if (cpu_has_mipsmt)
+ uasm_i_yield(&p, zero, t1);
uasm_il_b(&p, &r, lbl_poll_cont);
uasm_i_nop(&p);
} else {
* The core will lose power & this VPE will not continue
* so it can simply halt here.
*/
- uasm_i_addiu(&p, t0, zero, TCHALT_H);
- uasm_i_mtc0(&p, t0, 2, 4);
+ if (cpu_has_mipsmt) {
+ /* Halt the VPE via C0 tchalt register */
+ uasm_i_addiu(&p, t0, zero, TCHALT_H);
+ uasm_i_mtc0(&p, t0, 2, 4);
+ } else if (cpu_has_vp) {
+ /* Halt the VP via the CPC VP_STOP register */
+ unsigned int vpe_id;
+
+ vpe_id = cpu_vpe_id(&cpu_data[cpu]);
+ uasm_i_addiu(&p, t0, zero, 1 << vpe_id);
+ UASM_i_LA(&p, t1, (long)addr_cpc_cl_vp_stop());
+ uasm_i_sw(&p, t0, 0, t1);
+ } else {
+ BUG();
+ }
uasm_build_label(&l, p, lbl_secondary_hang);
uasm_il_b(&p, &r, lbl_secondary_hang);
uasm_i_nop(&p);
cps_gen_cache_routine(&p, &l, &r, &cpu_data[cpu].dcache,
Index_Writeback_Inv_D, lbl_flushdcache);
- /* Completion barrier */
- uasm_i_sync(&p, stype_memory);
+ /* Barrier ensuring previous cache invalidates are complete */
+ uasm_i_sync(&p, STYPE_SYNC);
uasm_i_ehb(&p);
/*
uasm_i_sw(&p, t0, 0, r_pcohctl);
uasm_i_lw(&p, t0, 0, r_pcohctl);
- /* Sync to ensure previous interventions are complete */
- uasm_i_sync(&p, stype_intervention);
+ /* Barrier to ensure write to coherence control is complete */
+ uasm_i_sync(&p, STYPE_SYNC);
uasm_i_ehb(&p);
/* Disable coherence */
goto gen_done;
}
- /* Completion barrier */
- uasm_i_sync(&p, stype_memory);
+ /* Barrier to ensure write to CPC command is complete */
+ uasm_i_sync(&p, STYPE_SYNC);
uasm_i_ehb(&p);
}
uasm_i_sw(&p, t0, 0, r_pcohctl);
uasm_i_lw(&p, t0, 0, r_pcohctl);
- /* Completion barrier */
- uasm_i_sync(&p, stype_memory);
+ /* Barrier to ensure write to coherence control is complete */
+ uasm_i_sync(&p, STYPE_SYNC);
uasm_i_ehb(&p);
if (coupled_coherence && (state == CPS_PM_NC_WAIT)) {
/* Decrement ready_count */
uasm_build_label(&l, p, lbl_decready);
- uasm_i_sync(&p, stype_ordering);
+ uasm_i_sync(&p, STYPE_SYNC_MB);
uasm_i_ll(&p, t1, 0, r_nc_count);
uasm_i_addiu(&p, t2, t1, -1);
uasm_i_sc(&p, t2, 0, r_nc_count);
uasm_il_beqz(&p, &r, t2, lbl_decready);
uasm_i_andi(&p, v0, t1, (1 << fls(smp_num_siblings)) - 1);
- /* Ordering barrier */
- uasm_i_sync(&p, stype_ordering);
+ /* Barrier ensuring all CPUs see the updated r_nc_count value */
+ uasm_i_sync(&p, STYPE_SYNC_MB);
}
if (coupled_coherence && (state == CPS_PM_CLOCK_GATED)) {
*/
uasm_build_label(&l, p, lbl_secondary_cont);
- /* Ordering barrier */
- uasm_i_sync(&p, stype_ordering);
+ /* Barrier ensuring all CPUs see the updated r_nc_count value */
+ uasm_i_sync(&p, STYPE_SYNC_MB);
}
/* The core is coherent, time to return to C code */
unsigned cpu;
int err;
- /* Detect appropriate sync types for the system */
- switch (current_cpu_data.cputype) {
- case CPU_INTERAPTIV:
- case CPU_PROAPTIV:
- case CPU_M5150:
- case CPU_P5600:
- case CPU_I6400:
- stype_intervention = 0x2;
- stype_memory = 0x3;
- stype_ordering = 0x10;
- break;
-
- default:
- pr_warn("Power management is using heavyweight sync 0\n");
- }
-
/* A CM is required for all non-coherent states */
if (!mips_cm_present()) {
pr_warn("pm-cps: no CM, non-coherent states unavailable\n");