*
*/
-#include "hw/arm/imx.h"
+#include "qemu/osdep.h"
#include "hw/timer/imx_gpt.h"
#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
+#include "qemu/log.h"
-/*
- * Define to 1 for debug messages
- */
-#define DEBUG_TIMER 0
-#if DEBUG_TIMER
+#ifndef DEBUG_IMX_GPT
+#define DEBUG_IMX_GPT 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+ do { \
+ if (DEBUG_IMX_GPT) { \
+ fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPT, \
+ __func__, ##args); \
+ } \
+ } while (0)
static char const *imx_gpt_reg_name(uint32_t reg)
{
}
}
-# define DPRINTF(fmt, args...) \
- do { printf("%s: " fmt , __func__, ##args); } while (0)
-#else
-# define DPRINTF(fmt, args...) do {} while (0)
-#endif
-
-/*
- * Define to 1 for messages about attempts to
- * access unimplemented registers or similar.
- */
-#define DEBUG_IMPLEMENTATION 1
-#if DEBUG_IMPLEMENTATION
-# define IPRINTF(fmt, args...) \
- do { fprintf(stderr, "%s: " fmt, __func__, ##args); } while (0)
-#else
-# define IPRINTF(fmt, args...) do {} while (0)
-#endif
-
static const VMStateDescription vmstate_imx_timer_gpt = {
.name = TYPE_IMX_GPT,
.version_id = 3,
};
static const IMXClk imx_gpt_clocks[] = {
- NOCLK, /* 000 No clock source */
- IPG, /* 001 ipg_clk, 532MHz*/
- IPG, /* 010 ipg_clk_highfreq */
- NOCLK, /* 011 not defined */
- CLK_32k, /* 100 ipg_clk_32k */
- NOCLK, /* 101 not defined */
- NOCLK, /* 110 not defined */
- NOCLK, /* 111 not defined */
+ CLK_NONE, /* 000 No clock source */
+ CLK_IPG, /* 001 ipg_clk, 532MHz*/
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
+ CLK_NONE, /* 011 not defined */
+ CLK_32k, /* 100 ipg_clk_32k */
+ CLK_NONE, /* 101 not defined */
+ CLK_NONE, /* 110 not defined */
+ CLK_NONE, /* 111 not defined */
};
static void imx_gpt_set_freq(IMXGPTState *s)
{
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
- uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc])
- / (1 + s->pr);
- s->freq = freq;
- DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq);
+ s->freq = imx_ccm_get_clock_frequency(s->ccm,
+ imx_gpt_clocks[clksrc]) / (1 + s->pr);
+
+ DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
- if (freq) {
- ptimer_set_freq(s->timer, freq);
+ if (s->freq) {
+ ptimer_set_freq(s->timer, s->freq);
}
}
static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event)
{
uint32_t timeout = GPT_TIMER_MAX;
- uint32_t count = 0;
+ uint32_t count;
long long limit;
if (!(s->cr & GPT_CR_EN)) {
return;
}
- if (event) {
- /* This is a timer event */
+ /* update the count */
+ count = imx_gpt_update_count(s);
- if ((s->cr & GPT_CR_FRR) && (s->next_timeout != GPT_TIMER_MAX)) {
- /*
- * if we are in free running mode and we have not reached
- * the GPT_TIMER_MAX limit, then update the count
+ if (event) {
+ /*
+ * This is an event (the ptimer reached 0 and stopped), and the
+ * timer counter is now equal to s->next_timeout.
+ */
+ if (!(s->cr & GPT_CR_FRR) && (count == s->ocr1)) {
+ /* We are in restart mode and we crossed the compare channel 1
+ * value. We need to reset the counter to 0.
*/
- count = imx_gpt_update_count(s);
+ count = s->cnt = s->next_timeout = 0;
+ } else if (count == GPT_TIMER_MAX) {
+ /* We reached GPT_TIMER_MAX so we need to rollover */
+ count = s->cnt = s->next_timeout = 0;
}
- } else {
- /* not a timer event, then just update the count */
-
- count = imx_gpt_update_count(s);
}
/* now, find the next timeout related to count */
{
IMXGPTState *s = IMX_GPT(opaque);
uint32_t reg_value = 0;
- uint32_t reg = offset >> 2;
- switch (reg) {
+ switch (offset >> 2) {
case 0: /* Control Register */
reg_value = s->cr;
break;
break;
case 7: /* input Capture Register 1 */
- qemu_log_mask(LOG_UNIMP, "icr1 feature is not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "[%s]%s: icr1 feature is not implemented\n",
+ TYPE_IMX_GPT, __func__);
reg_value = s->icr1;
break;
case 8: /* input Capture Register 2 */
- qemu_log_mask(LOG_UNIMP, "icr2 feature is not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "[%s]%s: icr2 feature is not implemented\n",
+ TYPE_IMX_GPT, __func__);
reg_value = s->icr2;
break;
break;
default:
- IPRINTF("Bad offset %x\n", reg);
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_GPT, __func__, offset);
break;
}
- DPRINTF("(%s) = 0x%08x\n", imx_gpt_reg_name(reg), reg_value);
+ DPRINTF("(%s) = 0x%08x\n", imx_gpt_reg_name(offset >> 2), reg_value);
return reg_value;
}
{
IMXGPTState *s = IMX_GPT(opaque);
uint32_t oldreg;
- uint32_t reg = offset >> 2;
- DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(reg),
+ DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(offset >> 2),
(uint32_t)value);
- switch (reg) {
+ switch (offset >> 2) {
case 0:
oldreg = s->cr;
s->cr = value & ~0x7c14;
break;
default:
- IPRINTF("Bad offset %x\n", reg);
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_GPT, __func__, offset);
break;
}
}
s->timer = ptimer_init(bh);
}
-void imx_timerg_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
-{
- IMXGPTState *pp;
- DeviceState *dev;
-
- dev = sysbus_create_simple(TYPE_IMX_GPT, addr, irq);
- pp = IMX_GPT(dev);
- pp->ccm = ccm;
-}
-
static void imx_gpt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);