rockbox/firmware/target/arm/imx233/kernel-imx233.c
Amaury Pouly 3afcb53fb9 imx233: rework power management
The current code was spreaded over power and powermgmt which made
it behave strangely, especially since there are relationships
between power management and frequency scaling. The new code makes
sure power management is initialised before frequency scaling
starts. It also makes sure to start from a known state, thus
fixing potential issue when the bootloader stops in a trickle
state where DCDC is improperly configured.

Change-Id: Ibded2e590e108f6c98daa52d2cf1bd28763c8923
2013-07-07 17:36:21 +02:00

84 lines
2.6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "kernel.h"
#include "timrot-imx233.h"
#include "clkctrl-imx233.h"
#include "kernel-imx233.h"
static void tick_timer(void)
{
/* Run through the list of tick tasks */
call_tick_tasks();
}
void tick_start(unsigned int interval_in_ms)
{
/* use the 1-kHz XTAL clock source */
imx233_setup_timer(TICK_TIMER_NR, true, interval_in_ms,
BV_TIMROT_TIMCTRLn_SELECT__1KHZ_XTAL, BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_1,
false, &tick_timer);
}
void arbiter_init(struct channel_arbiter_t *a, unsigned count)
{
mutex_init(&a->mutex);
semaphore_init(&a->sema, count, count);
a->free_bm = (1 << count) - 1;
a->count = count;
}
// doesn't check in use !
void arbiter_reserve(struct channel_arbiter_t *a, unsigned channel)
{
// assume semaphore has a free slot immediately
if(semaphore_wait(&a->sema, TIMEOUT_NOBLOCK) != OBJ_WAIT_SUCCEEDED)
panicf("arbiter_reserve failed on semaphore_wait !");
mutex_lock(&a->mutex);
a->free_bm &= ~(1 << channel);
mutex_unlock(&a->mutex);
}
int arbiter_acquire(struct channel_arbiter_t *a, int timeout)
{
int w = semaphore_wait(&a->sema, timeout);
if(w == OBJ_WAIT_TIMEDOUT)
return w;
mutex_lock(&a->mutex);
int chan = find_first_set_bit(a->free_bm);
if(chan >= a->count)
panicf("arbiter_acquire cannot find a free channel !");
a->free_bm &= ~(1 << chan);
mutex_unlock(&a->mutex);
return chan;
}
bool arbiter_acquired(struct channel_arbiter_t *a, int channel)
{
return !(a->free_bm & (1 << channel));
}
void arbiter_release(struct channel_arbiter_t *a, int channel)
{
mutex_lock(&a->mutex);
a->free_bm |= 1 << channel;
mutex_unlock(&a->mutex);
semaphore_release(&a->sema);
}