mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 08:43:55 -06:00
hw/timer/imx_epit: remove explicit fields cnt and freq
The CNT register is a read-only register. There is no need to store it's value, it can be calculated on demand. The calculated frequency is needed temporarily only. Note that this is a migration compatibility break for all boards types that use the EPIT peripheral. Signed-off-by: Axel Heider <axel.heider@hensoldt.net> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
793a6ea075
commit
e662449aa6
2 changed files with 28 additions and 47 deletions
|
@ -73,27 +73,14 @@ static void imx_epit_update_int(IMXEPITState *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static uint32_t imx_epit_get_freq(IMXEPITState *s)
|
||||||
* Must be called from within a ptimer_transaction_begin/commit block
|
|
||||||
* for both s->timer_cmp and s->timer_reload.
|
|
||||||
*/
|
|
||||||
static void imx_epit_set_freq(IMXEPITState *s)
|
|
||||||
{
|
{
|
||||||
uint32_t clksrc;
|
uint32_t clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, CR_CLKSRC_BITS);
|
||||||
uint32_t prescaler;
|
uint32_t prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, CR_PRESCALE_BITS);
|
||||||
|
uint32_t f_in = imx_ccm_get_clock_frequency(s->ccm, imx_epit_clocks[clksrc]);
|
||||||
clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, CR_CLKSRC_BITS);
|
uint32_t freq = f_in / prescaler;
|
||||||
prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, CR_PRESCALE_BITS);
|
DPRINTF("ptimer frequency is %u\n", freq);
|
||||||
|
return freq;
|
||||||
s->freq = imx_ccm_get_clock_frequency(s->ccm,
|
|
||||||
imx_epit_clocks[clksrc]) / prescaler;
|
|
||||||
|
|
||||||
DPRINTF("Setting ptimer frequency to %u\n", s->freq);
|
|
||||||
|
|
||||||
if (s->freq) {
|
|
||||||
ptimer_set_freq(s->timer_reload, s->freq);
|
|
||||||
ptimer_set_freq(s->timer_cmp, s->freq);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -110,32 +97,23 @@ static void imx_epit_reset(IMXEPITState *s, bool is_hard_reset)
|
||||||
s->sr = 0;
|
s->sr = 0;
|
||||||
s->lr = EPIT_TIMER_MAX;
|
s->lr = EPIT_TIMER_MAX;
|
||||||
s->cmp = 0;
|
s->cmp = 0;
|
||||||
s->cnt = 0;
|
|
||||||
ptimer_transaction_begin(s->timer_cmp);
|
ptimer_transaction_begin(s->timer_cmp);
|
||||||
ptimer_transaction_begin(s->timer_reload);
|
ptimer_transaction_begin(s->timer_reload);
|
||||||
/* stop both timers */
|
|
||||||
|
/*
|
||||||
|
* The reset switches off the input clock, so even if the CR.EN is still
|
||||||
|
* set, the timers are no longer running.
|
||||||
|
*/
|
||||||
|
assert(imx_epit_get_freq(s) == 0);
|
||||||
ptimer_stop(s->timer_cmp);
|
ptimer_stop(s->timer_cmp);
|
||||||
ptimer_stop(s->timer_reload);
|
ptimer_stop(s->timer_reload);
|
||||||
/* compute new frequency */
|
|
||||||
imx_epit_set_freq(s);
|
|
||||||
/* init both timers to EPIT_TIMER_MAX */
|
/* init both timers to EPIT_TIMER_MAX */
|
||||||
ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1);
|
ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1);
|
||||||
ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1);
|
ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1);
|
||||||
if (s->freq && (s->cr & CR_EN)) {
|
|
||||||
/* if the timer is still enabled, restart it */
|
|
||||||
ptimer_run(s->timer_reload, 0);
|
|
||||||
}
|
|
||||||
ptimer_transaction_commit(s->timer_cmp);
|
ptimer_transaction_commit(s->timer_cmp);
|
||||||
ptimer_transaction_commit(s->timer_reload);
|
ptimer_transaction_commit(s->timer_reload);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t imx_epit_update_count(IMXEPITState *s)
|
|
||||||
{
|
|
||||||
s->cnt = ptimer_get_count(s->timer_reload);
|
|
||||||
|
|
||||||
return s->cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
IMXEPITState *s = IMX_EPIT(opaque);
|
IMXEPITState *s = IMX_EPIT(opaque);
|
||||||
|
@ -159,8 +137,7 @@ static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* CNT */
|
case 4: /* CNT */
|
||||||
imx_epit_update_count(s);
|
reg_value = ptimer_get_count(s->timer_reload);
|
||||||
reg_value = s->cnt;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -179,7 +156,7 @@ static void imx_epit_reload_compare_timer(IMXEPITState *s)
|
||||||
{
|
{
|
||||||
if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
|
if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
|
||||||
/* if the compare feature is on and timers are running */
|
/* if the compare feature is on and timers are running */
|
||||||
uint32_t tmp = imx_epit_update_count(s);
|
uint32_t tmp = ptimer_get_count(s->timer_reload);
|
||||||
uint64_t next;
|
uint64_t next;
|
||||||
if (tmp > s->cmp) {
|
if (tmp > s->cmp) {
|
||||||
/* It'll fire in this round of the timer */
|
/* It'll fire in this round of the timer */
|
||||||
|
@ -193,6 +170,7 @@ static void imx_epit_reload_compare_timer(IMXEPITState *s)
|
||||||
|
|
||||||
static void imx_epit_write_cr(IMXEPITState *s, uint32_t value)
|
static void imx_epit_write_cr(IMXEPITState *s, uint32_t value)
|
||||||
{
|
{
|
||||||
|
uint32_t freq = 0;
|
||||||
uint32_t oldcr = s->cr;
|
uint32_t oldcr = s->cr;
|
||||||
|
|
||||||
s->cr = value & 0x03ffffff;
|
s->cr = value & 0x03ffffff;
|
||||||
|
@ -217,12 +195,19 @@ static void imx_epit_write_cr(IMXEPITState *s, uint32_t value)
|
||||||
ptimer_transaction_begin(s->timer_cmp);
|
ptimer_transaction_begin(s->timer_cmp);
|
||||||
ptimer_transaction_begin(s->timer_reload);
|
ptimer_transaction_begin(s->timer_reload);
|
||||||
|
|
||||||
/* Update the frequency. Has been done already in case of a reset. */
|
/*
|
||||||
|
* Update the frequency. In case of a reset the input clock was
|
||||||
|
* switched off, so this can be skipped.
|
||||||
|
*/
|
||||||
if (!(s->cr & CR_SWR)) {
|
if (!(s->cr & CR_SWR)) {
|
||||||
imx_epit_set_freq(s);
|
freq = imx_epit_get_freq(s);
|
||||||
|
if (freq) {
|
||||||
|
ptimer_set_freq(s->timer_reload, freq);
|
||||||
|
ptimer_set_freq(s->timer_cmp, freq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
|
if (freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
|
||||||
if (s->cr & CR_ENMOD) {
|
if (s->cr & CR_ENMOD) {
|
||||||
if (s->cr & CR_RLD) {
|
if (s->cr & CR_RLD) {
|
||||||
ptimer_set_limit(s->timer_reload, s->lr, 1);
|
ptimer_set_limit(s->timer_reload, s->lr, 1);
|
||||||
|
@ -356,15 +341,13 @@ static const MemoryRegionOps imx_epit_ops = {
|
||||||
|
|
||||||
static const VMStateDescription vmstate_imx_timer_epit = {
|
static const VMStateDescription vmstate_imx_timer_epit = {
|
||||||
.name = TYPE_IMX_EPIT,
|
.name = TYPE_IMX_EPIT,
|
||||||
.version_id = 2,
|
.version_id = 3,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 3,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(cr, IMXEPITState),
|
VMSTATE_UINT32(cr, IMXEPITState),
|
||||||
VMSTATE_UINT32(sr, IMXEPITState),
|
VMSTATE_UINT32(sr, IMXEPITState),
|
||||||
VMSTATE_UINT32(lr, IMXEPITState),
|
VMSTATE_UINT32(lr, IMXEPITState),
|
||||||
VMSTATE_UINT32(cmp, IMXEPITState),
|
VMSTATE_UINT32(cmp, IMXEPITState),
|
||||||
VMSTATE_UINT32(cnt, IMXEPITState),
|
|
||||||
VMSTATE_UINT32(freq, IMXEPITState),
|
|
||||||
VMSTATE_PTIMER(timer_reload, IMXEPITState),
|
VMSTATE_PTIMER(timer_reload, IMXEPITState),
|
||||||
VMSTATE_PTIMER(timer_cmp, IMXEPITState),
|
VMSTATE_PTIMER(timer_cmp, IMXEPITState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
|
|
|
@ -74,9 +74,7 @@ struct IMXEPITState {
|
||||||
uint32_t sr;
|
uint32_t sr;
|
||||||
uint32_t lr;
|
uint32_t lr;
|
||||||
uint32_t cmp;
|
uint32_t cmp;
|
||||||
uint32_t cnt;
|
|
||||||
|
|
||||||
uint32_t freq;
|
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue