/* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1, Each can be * programmed to go from @count to @limit and optionally interrupt. * We've designated TIMER0 for clockevents and TIMER1 for clocksource * * ARCv2 based HS38 cores have RTC (in-core) and GFRC (inside ARConnect/MCIP) * which are suitable for UP and SMP based clocksources respectively
*/
/* * From a programming model pov, there seems to be just one instance of * MCIP_CMD/MCIP_READBACK however micro-architecturally there's * an instance PER ARC CORE (not per cluster), and there are dedicated * hardware decode logic (per core) inside ARConnect to handle * simultaneous read/write accesses from cores via those two registers. * So several concurrent commands to ARConnect are OK if they are * trying to access two different sub-components (like GFRC, * inter-core interrupt, etc...). HW also supports simultaneously * accessing GFRC by multiple cores. * That's why it is safe to disable hard interrupts on the local CPU * before access to GFRC instead of taking global MCIP spinlock * defined in arch/arc/kernel/mcip.c
*/
local_irq_save(flags);
__mcip_cmd(CMD_GFRC_READ_LO, 0);
l = read_aux_reg(ARC_REG_MCIP_READBACK);
__mcip_cmd(CMD_GFRC_READ_HI, 0);
h = read_aux_reg(ARC_REG_MCIP_READBACK);
/* * hardware has an internal state machine which tracks readout of * low/high and updates the CTRL.status if * - interrupt/exception taken between the two reads * - high increments after low has been read
*/ do {
l = read_aux_reg(AUX_RTC_LOW);
h = read_aux_reg(AUX_RTC_HIGH);
status = read_aux_reg(AUX_RTC_CTRL);
} while (!(status & BIT(31)));
/* * Arm the timer to interrupt after @cycles * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
*/ staticvoid arc_timer_event_setup(unsignedint cycles)
{
write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
write_aux_reg(ARC_REG_TIMER0_CNT, 0); /* start from 0 */
static irqreturn_t timer_irq_handler(int irq, void *dev_id)
{ /* * Note that generic IRQ core could have passed @evt for @dev_id if * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
*/ struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); int irq_reenable = clockevent_state_periodic(evt);
/* * 1. ACK the interrupt * - For ARC700, any write to CTRL reg ACKs it, so just rewrite * Count when [N]ot [H]alted bit. * - For HS3x, it is a bit subtle. On taken count-down interrupt, * IP bit [3] is set, which needs to be cleared for ACK'ing. * The write below can only update the other two bits, hence * explicitly clears IP bit * 2. Re-arm interrupt if periodic by writing to IE bit [0]
*/
write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | ARC_TIMER_CTRL_NH);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.