/* * Copyright (c) 2012, ARM Limited. All rights reserved. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the * following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its * contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. */ #include "events.h" /* * Set the specified event for that cpu. */ void _set_event(unsigned event_id, unsigned cpu_id, unsigned event_type) { dsb(); secure_event[cpu_id][event_id] = TRUE; dsb(); sev(); return; } inline unsigned _get_event(unsigned event_id, unsigned cpu_id) { return secure_event[cpu_id][event_id]; } void _reset_event(unsigned event_id, unsigned cpu_id, unsigned event_type) { dsb(); secure_event[cpu_id][event_id] = FALSE; dsb(); return; } void _wait_for_event(unsigned event_id, unsigned cpu_id, unsigned event_type) { dsb(); do { wfe(); isb(); dsb(); } while (FALSE == _get_event(event_id, cpu_id)); return; } /* * Wait for events from each core. Its a little trickier than * waiting for a single event. The event register as per the * architecture is just a single bit to flag an event rather * than the number of events. If multiple events are sent by * the time we enter wfe() then each flag variable should be * checked. */ void _wait_for_events(unsigned event_id, unsigned event_type) { unsigned ctr, event_count = 0, num_cpus = num_secondaries() + 1;; dsb(); do { wfe(); for (ctr = 0; ctr < num_cpus; ctr++) { if (TRUE == _get_event(event_id, ctr)) { event_count++; _reset_event(event_id, ctr, event_type); } } } while (event_count != num_cpus); return; } void _set_events(unsigned event_id, unsigned event_type) { unsigned ctr; for (ctr = 0; ctr < (num_secondaries() + 1); ctr++) { _set_event(event_id, ctr, event_type); } return; }