/* the time set by the user is converted to "ticks" */ staticint convert_time_to_ticks(struct timer_group_priv *priv,
time64_t time, u64 *ticks)
{
u64 max_value; /* prevent u64 overflow */
max_value = div_u64(ULLONG_MAX, priv->timerfreq);
if (time > max_value) return -EINVAL;
*ticks = (u64)time * (u64)priv->timerfreq;
return 0;
}
/* detect whether there is a cascade timer available */ staticstruct mpic_timer *detect_idle_cascade_timer( struct timer_group_priv *priv)
{ struct cascade_priv *casc_priv; unsignedint map; unsignedint array_size = ARRAY_SIZE(cascade_timer); unsignedint num; unsignedint i; unsignedlong flags;
casc_priv = cascade_timer; for (i = 0; i < array_size; i++) {
spin_lock_irqsave(&priv->lock, flags);
map = casc_priv->cascade_map & priv->idle; if (map == casc_priv->cascade_map) {
num = casc_priv->timer_num;
priv->timer[num].cascade_handle = casc_priv;
u64 ticks; unsignedint num; unsignedint i; unsignedlong flags; int ret;
list_for_each_entry(priv, &timer_group_list, node) {
ret = convert_time_to_ticks(priv, time, &ticks); if (ret < 0) return NULL;
if (ticks > MAX_TICKS) { if (!(priv->flags & FSL_GLOBAL_TIMER)) return NULL;
timer = get_cascade_timer(priv, ticks); if (!timer) continue;
return timer;
}
for (i = 0; i < TIMERS_PER_GROUP; i++) { /* one timer: Reverse allocation */
num = TIMERS_PER_GROUP - 1 - i;
spin_lock_irqsave(&priv->lock, flags); if (priv->idle & (1 << i)) { /* set timer busy */
priv->idle &= ~(1 << i); /* set ticks & stop timer */
out_be32(&priv->regs[num].gtbcr,
ticks | TIMER_STOP);
out_be32(&priv->regs[num].gtccr, 0);
priv->timer[num].cascade_handle = NULL;
spin_unlock_irqrestore(&priv->lock, flags); return &priv->timer[num];
}
spin_unlock_irqrestore(&priv->lock, flags);
}
}
return NULL;
}
/** * mpic_start_timer - start hardware timer * @handle: the timer to be started. * * It will do ->fn(->dev) callback from the hardware interrupt at * the 'time64_t' point in the future.
*/ void mpic_start_timer(struct mpic_timer *handle)
{ struct timer_group_priv *priv = container_of(handle, struct timer_group_priv, timer[handle->num]);
/** * mpic_free_timer - free hardware timer * @handle: the timer to be removed. * * Free the timer. * * Note: can not be used in interrupt context.
*/ void mpic_free_timer(struct mpic_timer *handle)
{ struct timer_group_priv *priv = container_of(handle, struct timer_group_priv, timer[handle->num]);
/** * mpic_request_timer - get a hardware timer * @fn: interrupt handler function * @dev: callback function of the data * @time: time for timer * * This executes the "request_irq", returning NULL * else "handle" on success.
*/ struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,
time64_t time)
{ struct mpic_timer *allocated_timer; int ret;
if (list_empty(&timer_group_list)) return NULL;
if (time < 0) return NULL;
allocated_timer = get_timer(time); if (!allocated_timer) return NULL;
ret = request_irq(allocated_timer->irq, fn,
IRQF_TRIGGER_LOW, "global-timer", dev); if (ret) {
mpic_free_timer(allocated_timer); return NULL;
}
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.