Skip to contentSkip to conversation

Add an i.MX25 specific CCM driver

PATCH Superseded Jean-Christophe Dubois 3 participants 13 messages Nov 26, 2015 – Nov 29, 2015 Arm i.MX and Layerscape

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v4 cover Add an i.MX25 specific CCM driver

i.MX25 SOC has a different CCM device than i.MX31.

Qemu i.MX25 emulation was built with i.MX31 CCM driver. This allows Linux to work on top of the i.MX25 emultion but this is not correct.

Furthermore, other SOC we could emulate like i.MX6 have yet a different implementation of the CCM device.

So we split the i.MX31 into a generic base class and a specific i.MX31 class.

We then add an i.MX25 specific CCM Device and have the i.MX25 SOC use it.

Jean-Christophe Dubois (3):
i.MX: rename i.MX CCM get_clock() function and CLK ID enum names i.MX: Split the CCM class into an abstact base class and a concrete
class.
i.MX: Add an i.MX25 specific CCM class/instance.

 hw/arm/fsl-imx25.c          |   6 +-
 hw/arm/fsl-imx31.c          |   6 +-
 hw/misc/Makefile.objs       |   2 +
 hw/misc/imx25_ccm.c         | 276 +++++++++++++++++++++++++++++++++++++++
 hw/misc/imx31_ccm.c         | 306 ++++++++++++++++++++++++++++++++++++++++++++
 hw/misc/imx_ccm.c           | 226 +++-----------------------------
 hw/timer/imx_epit.c         |  20 ++-
 hw/timer/imx_gpt.c          |  16 +--
 include/hw/arm/fsl-imx25.h  |   4 +-
 include/hw/arm/fsl-imx31.h  |   4 +-
 include/hw/misc/imx25_ccm.h |  59 +++++++++
 include/hw/misc/imx31_ccm.h |  64 +++++++++
 include/hw/misc/imx_ccm.h   |  75 ++++-------
 include/hw/timer/imx_epit.h |   5 +-
 include/hw/timer/imx_gpt.h  |   5 +-
 15 files changed, 784 insertions(+), 290 deletions(-)
 create mode 100644 hw/misc/imx25_ccm.c
 create mode 100644 hw/misc/imx31_ccm.c
 create mode 100644 include/hw/misc/imx25_ccm.h
 create mode 100644 include/hw/misc/imx31_ccm.h
Signature · 1 line
2.5.0
#1 lore raw

PATCH v4 1/3 i.MX: rename i.MX CCM get_clock() function and CLK ID enum names

This is to prepare for CCM code refactoring.

This is just a bit of function and enum values renaming.

We also remove some useless intermediate variables.

---
Changes since v1:
* Not present

Changes since v2:
* Not present

Changes since v3:
* None

 hw/misc/imx_ccm.c         |  8 ++++----
 hw/timer/imx_epit.c       | 20 +++++++++-----------
 hw/timer/imx_gpt.c        | 16 ++++++++--------
 include/hw/misc/imx_ccm.h |  8 ++++----
 4 files changed, 25 insertions(+), 27 deletions(-)
hw/misc/imx_ccm.c +4 -4
index 4cc2bbc..415937f 100644
@@ -49,18 +49,18 @@ static const VMStateDescription vmstate_imx_ccm = {
     .post_load = imx_ccm_post_load,
 };
 
-uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
+uint32_t imx_ccm_get_clock_frequency(DeviceState *dev, IMXClk clock)
 {
     IMXCCMState *s = IMX_CCM(dev);
 
     switch (clock) {
     case NOCLK:
         return 0;
-    case MCU:
+    case CLK_MCU:
         return s->mcu_clk_freq;
-    case HSP:
+    case CLK_HSP:
         return s->hsp_clk_freq;
-    case IPG:
+    case CLK_IPG:
         return s->ipg_clk_freq;
     case CLK_32k:
         return CKIL_FREQ;
hw/timer/imx_epit.c +9 -11
index 967be4a..50bf83c 100644
@@ -51,9 +51,9 @@ static char const *imx_epit_reg_name(uint32_t reg)
  * These are typical.
  */
 static const IMXClk imx_epit_clocks[] =  {
-    0,        /* 00 disabled */
-    IPG,      /* 01 ipg_clk, ~532MHz */
-    IPG,      /* 10 ipg_clk_highfreq */
+    NOCLK,    /* 00 disabled */
+    CLK_IPG,  /* 01 ipg_clk, ~532MHz */
+    CLK_IPG,  /* 10 ipg_clk_highfreq */
     CLK_32k,  /* 11 ipg_clk_32k -- ~32kHz */
 };
 
@@ -73,20 +73,18 @@ static void imx_epit_set_freq(IMXEPITState *s)
 {
     uint32_t clksrc;
     uint32_t prescaler;
-    uint32_t freq;
 
     clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2);
     prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12);
 
-    freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler;
+    s->freq = imx_ccm_get_clock_frequency(s->ccm,
+                                imx_epit_clocks[clksrc]) / prescaler;
 
-    s->freq = freq;
+    DPRINTF("Setting ptimer frequency to %u\n", s->freq);
 
-    DPRINTF("Setting ptimer frequency to %u\n", freq);
-
-    if (freq) {
-        ptimer_set_freq(s->timer_reload, freq);
-        ptimer_set_freq(s->timer_cmp, freq);
+    if (s->freq) {
+        ptimer_set_freq(s->timer_reload, s->freq);
+        ptimer_set_freq(s->timer_cmp, s->freq);
     }
 }
 
hw/timer/imx_gpt.c +8 -8
index 7257f42..b1893b8 100644
@@ -81,8 +81,8 @@ static const VMStateDescription vmstate_imx_timer_gpt = {
 
 static const IMXClk imx_gpt_clocks[] = {
     NOCLK,    /* 000 No clock source */
-    IPG,      /* 001 ipg_clk, 532MHz*/
-    IPG,      /* 010 ipg_clk_highfreq */
+    CLK_IPG,  /* 001 ipg_clk, 532MHz*/
+    CLK_IPG,  /* 010 ipg_clk_highfreq */
     NOCLK,    /* 011 not defined */
     CLK_32k,  /* 100 ipg_clk_32k */
     NOCLK,    /* 101 not defined */
@@ -93,14 +93,14 @@ static const IMXClk imx_gpt_clocks[] = {
 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);
 
-    if (freq) {
-        ptimer_set_freq(s->timer, freq);
+    DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
+
+    if (s->freq) {
+        ptimer_set_freq(s->timer, s->freq);
     }
 }
 
include/hw/misc/imx_ccm.h +4 -4
index 0f2e469..09f6248 100644
@@ -80,12 +80,12 @@ typedef struct IMXCCMState {
 
 typedef enum  {
     NOCLK,
-    MCU,
-    HSP,
-    IPG,
+    CLK_MCU,
+    CLK_HSP,
+    CLK_IPG,
     CLK_32k
 } IMXClk;
 
-uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock);
+uint32_t imx_ccm_get_clock_frequency(DeviceState *s, IMXClk clock);
 
 #endif /* IMX_CCM_H */
Signature · 1 line
2.5.0
Tested-by on v4 1/3
#2 lore raw

Re: [Qemu-devel] [PATCH v4 1/3] i.MX: rename i.MX CCM get_clock() function and CLK ID enum names

Quoted 8 lines · Jean-Christophe Dubois

This is to prepare for CCM code refactoring.

This is just a bit of function and enum values renaming.

We also remove some useless intermediate variables.

Quoted 147 lines

---
Changes since v1:
* Not present

Changes since v2:
* Not present

Changes since v3:
* None

 hw/misc/imx_ccm.c         |  8 ++++----
 hw/timer/imx_epit.c       | 20 +++++++++-----------
 hw/timer/imx_gpt.c        | 16 ++++++++--------
 include/hw/misc/imx_ccm.h |  8 ++++----
 4 files changed, 25 insertions(+), 27 deletions(-)
hw/misc/imx_ccm.c +4 -4
index 4cc2bbc..415937f 100644
@@ -49,18 +49,18 @@ static const VMStateDescription vmstate_imx_ccm = {
     .post_load = imx_ccm_post_load,
 };
 
-uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
+uint32_t imx_ccm_get_clock_frequency(DeviceState *dev, IMXClk clock)
 {
     IMXCCMState *s = IMX_CCM(dev);
 
     switch (clock) {
     case NOCLK:
         return 0;
-    case MCU:
+    case CLK_MCU:
         return s->mcu_clk_freq;
-    case HSP:
+    case CLK_HSP:
         return s->hsp_clk_freq;
-    case IPG:
+    case CLK_IPG:
         return s->ipg_clk_freq;
     case CLK_32k:
         return CKIL_FREQ;
hw/timer/imx_epit.c +9 -11
index 967be4a..50bf83c 100644
@@ -51,9 +51,9 @@ static char const *imx_epit_reg_name(uint32_t reg)
  * These are typical.
  */
 static const IMXClk imx_epit_clocks[] =  {
-    0,        /* 00 disabled */
-    IPG,      /* 01 ipg_clk, ~532MHz */
-    IPG,      /* 10 ipg_clk_highfreq */
+    NOCLK,    /* 00 disabled */
+    CLK_IPG,  /* 01 ipg_clk, ~532MHz */
+    CLK_IPG,  /* 10 ipg_clk_highfreq */
     CLK_32k,  /* 11 ipg_clk_32k -- ~32kHz */
 };
 
@@ -73,20 +73,18 @@ static void imx_epit_set_freq(IMXEPITState *s)
 {
     uint32_t clksrc;
     uint32_t prescaler;
-    uint32_t freq;
 
     clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2);
     prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12);
 
-    freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler;
+    s->freq = imx_ccm_get_clock_frequency(s->ccm,
+                                imx_epit_clocks[clksrc]) / prescaler;
 
-    s->freq = freq;
+    DPRINTF("Setting ptimer frequency to %u\n", s->freq);
 
-    DPRINTF("Setting ptimer frequency to %u\n", freq);
-
-    if (freq) {
-        ptimer_set_freq(s->timer_reload, freq);
-        ptimer_set_freq(s->timer_cmp, freq);
+    if (s->freq) {
+        ptimer_set_freq(s->timer_reload, s->freq);
+        ptimer_set_freq(s->timer_cmp, s->freq);
     }
 }
 
hw/timer/imx_gpt.c +8 -8
index 7257f42..b1893b8 100644
@@ -81,8 +81,8 @@ static const VMStateDescription vmstate_imx_timer_gpt = {
 
 static const IMXClk imx_gpt_clocks[] = {
     NOCLK,    /* 000 No clock source */
-    IPG,      /* 001 ipg_clk, 532MHz*/
-    IPG,      /* 010 ipg_clk_highfreq */
+    CLK_IPG,  /* 001 ipg_clk, 532MHz*/
+    CLK_IPG,  /* 010 ipg_clk_highfreq */
     NOCLK,    /* 011 not defined */
     CLK_32k,  /* 100 ipg_clk_32k */
     NOCLK,    /* 101 not defined */
@@ -93,14 +93,14 @@ static const IMXClk imx_gpt_clocks[] = {
 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);
 
-    if (freq) {
-        ptimer_set_freq(s->timer, freq);
+    DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
+
+    if (s->freq) {
+        ptimer_set_freq(s->timer, s->freq);
     }
 }
 
include/hw/misc/imx_ccm.h +4 -5
index 0f2e469..09f6248 100644
@@ -80,12 +80,12 @@ typedef struct IMXCCMState {
 
 typedef enum  {
     NOCLK,
-    MCU,
-    HSP,
-    IPG,
+    CLK_MCU,
+    CLK_HSP,
+    CLK_IPG,
     CLK_32k
 } IMXClk;
 
-uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock);
+uint32_t imx_ccm_get_clock_frequency(DeviceState *s, IMXClk clock);
 
 #endif /* IMX_CCM_H */
--

2.5.0

#3 lore raw

PATCH v4 2/3 i.MX: Split the CCM class into an abstact base class and a concrete class.

In reply to Jean-Christophe Dubois

The IMX_CCM class is now the base abstract class that is used by EPIT and GPT timer implementation.

IMX31_CCM class is the concrete class implementing CCM for i.MX31 SOC.

For now the i.MX25 continues to use the i.MX31 CCM implementation.

An i.MX25 specific CCM will be introduced in a later patch.

We also rework initialization to stop using deprecated sysbus device init

---

Changes since v1:
* None

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comment on i.MX25 CCM patch.
* Change abstract class function parameter to abstract class type instead of DEVICE type.
* EPIT and GPT timers use abstract class instead of DEVICE class.

 hw/arm/fsl-imx25.c          |   6 +-
 hw/arm/fsl-imx31.c          |   6 +-
 hw/misc/Makefile.objs       |   1 +
 hw/misc/imx31_ccm.c         | 306 ++++++++++++++++++++++++++++++++++++++++++++
 hw/misc/imx_ccm.c           | 226 +++-----------------------------
 include/hw/arm/fsl-imx25.h  |   4 +-
 include/hw/arm/fsl-imx31.h  |   4 +-
 include/hw/misc/imx31_ccm.h |  64 +++++++++
 include/hw/misc/imx_ccm.h   |  69 ++++------
 include/hw/timer/imx_epit.h |   5 +-
 include/hw/timer/imx_gpt.h  |   5 +-
 11 files changed, 428 insertions(+), 268 deletions(-)
 create mode 100644 hw/misc/imx31_ccm.c
 create mode 100644 include/hw/misc/imx31_ccm.h
hw/arm/fsl-imx25.c +3 -3
index e1cadac..9f302ed 100644
@@ -38,7 +38,7 @@ static void fsl_imx25_init(Object *obj)
     object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
     qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
 
-    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
+    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM);
     qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
 
     for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
@@ -150,7 +150,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
             { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
         };
 
-        s->gpt[i].ccm = DEVICE(&s->ccm);
+        s->gpt[i].ccm = IMX_CCM(&s->ccm);
 
         object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
         if (err) {
@@ -173,7 +173,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
             { FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
         };
 
-        s->epit[i].ccm = DEVICE(&s->ccm);
+        s->epit[i].ccm = IMX_CCM(&s->ccm);
 
         object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
         if (err) {
hw/arm/fsl-imx31.c +3 -3
index 53d4473..abdea06 100644
@@ -35,7 +35,7 @@ static void fsl_imx31_init(Object *obj)
     object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
     qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
 
-    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
+    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM);
     qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
 
     for (i = 0; i < FSL_IMX31_NUM_UARTS; i++) {
@@ -128,7 +128,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
                                             serial_table[i].irq));
     }
 
-    s->gpt.ccm = DEVICE(&s->ccm);
+    s->gpt.ccm = IMX_CCM(&s->ccm);
 
     object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err);
     if (err) {
@@ -150,7 +150,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
             { FSL_IMX31_EPIT2_ADDR, FSL_IMX31_EPIT2_IRQ },
         };
 
-        s->epit[i].ccm = DEVICE(&s->ccm);
+        s->epit[i].ccm = IMX_CCM(&s->ccm);
 
         object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
         if (err) {
hw/misc/Makefile.objs +1 -0
index aeb6b7d..c77f3e3 100644
@@ -26,6 +26,7 @@ obj-$(CONFIG_NSERIES) += cbus.o
 obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
 obj-$(CONFIG_IMX) += imx_ccm.o
+obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
hw/misc/imx31_ccm.c new file +306 -0

306 lines not on this page · raw message

hw/misc/imx_ccm.c +17 -209

269 lines not on this page · raw message

include/hw/arm/fsl-imx25.h +2 -2
index 73f50c6..5c62fde 100644
@@ -19,7 +19,7 @@
 
 #include "hw/arm/arm.h"
 #include "hw/intc/imx_avic.h"
-#include "hw/misc/imx_ccm.h"
+#include "hw/misc/imx31_ccm.h"
 #include "hw/char/imx_serial.h"
 #include "hw/timer/imx_gpt.h"
 #include "hw/timer/imx_epit.h"
@@ -44,7 +44,7 @@ typedef struct FslIMX25State {
     /*< public >*/
     ARMCPU         cpu;
     IMXAVICState   avic;
-    IMXCCMState    ccm;
+    IMX31CCMState  ccm;
     IMXSerialState uart[FSL_IMX25_NUM_UARTS];
     IMXGPTState    gpt[FSL_IMX25_NUM_GPTS];
     IMXEPITState   epit[FSL_IMX25_NUM_EPITS];
include/hw/arm/fsl-imx31.h +2 -2
index 5e8f795..d408abb 100644
@@ -19,7 +19,7 @@
 
 #include "hw/arm/arm.h"
 #include "hw/intc/imx_avic.h"
-#include "hw/misc/imx_ccm.h"
+#include "hw/misc/imx31_ccm.h"
 #include "hw/char/imx_serial.h"
 #include "hw/timer/imx_gpt.h"
 #include "hw/timer/imx_epit.h"
@@ -42,7 +42,7 @@ typedef struct FslIMX31State {
     /*< public >*/
     ARMCPU         cpu;
     IMXAVICState   avic;
-    IMXCCMState    ccm;
+    IMX31CCMState  ccm;
     IMXSerialState uart[FSL_IMX31_NUM_UARTS];
     IMXGPTState    gpt;
     IMXEPITState   epit[FSL_IMX31_NUM_EPITS];
include/hw/misc/imx31_ccm.h new file +64 -0

64 lines not on this page · raw message

include/hw/misc/imx_ccm.h +24 -45

101 lines not on this page · raw message

include/hw/timer/imx_epit.h +3 -2
index c5328ae..0730ac3 100644
@@ -31,6 +31,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "hw/misc/imx_ccm.h"
 
 /*
  * EPIT: Enhanced periodic interrupt timer
@@ -63,8 +64,8 @@ typedef struct IMXEPITState{
     /*< public >*/
     ptimer_state *timer_reload;
     ptimer_state *timer_cmp;
-    MemoryRegion iomem;
-    DeviceState *ccm;
+    MemoryRegion  iomem;
+    IMXCCMState  *ccm;
 
     uint32_t cr;
     uint32_t sr;
include/hw/timer/imx_gpt.h +3 -2
index 3f02d3b..461adbe 100644
@@ -31,6 +31,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "hw/misc/imx_ccm.h"
 
 /*
  * GPT : General purpose timer
@@ -82,8 +83,8 @@ typedef struct IMXGPTState{
 
     /*< public >*/
     ptimer_state *timer;
-    MemoryRegion iomem;
-    DeviceState *ccm;
+    MemoryRegion  iomem;
+    IMXCCMState  *ccm;
 
     uint32_t cr;
     uint32_t pr;
Signature · 1 line
2.5.0
Tested-by on v4 2/3
#4 lore raw

Re: [Qemu-devel] [PATCH v4 2/3] i.MX: Split the CCM class into an abstact base class and a concrete class.

Quoted 5 lines · Jean-Christophe Dubois

The IMX_CCM class is now the base abstract class that is used by EPIT and GPT timer implementation.

IMX31_CCM class is the concrete class implementing CCM for i.MX31 SOC.

Quoted 8 lines

For now the i.MX25 continues to use the i.MX31 CCM implementation.

An i.MX25 specific CCM will be introduced in a later patch.

We also rework initialization to stop using deprecated sysbus device init

Quoted 962 lines

---

Changes since v1:
* None

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comment on i.MX25 CCM patch.
* Change abstract class function parameter to abstract class type instead of DEVICE type.
* EPIT and GPT timers use abstract class instead of DEVICE class.

 hw/arm/fsl-imx25.c          |   6 +-
 hw/arm/fsl-imx31.c          |   6 +-
 hw/misc/Makefile.objs       |   1 +
 hw/misc/imx31_ccm.c         | 306 ++++++++++++++++++++++++++++++++++++++++++++
 hw/misc/imx_ccm.c           | 226 +++-----------------------------
 include/hw/arm/fsl-imx25.h  |   4 +-
 include/hw/arm/fsl-imx31.h  |   4 +-
 include/hw/misc/imx31_ccm.h |  64 +++++++++
 include/hw/misc/imx_ccm.h   |  69 ++++------
 include/hw/timer/imx_epit.h |   5 +-
 include/hw/timer/imx_gpt.h  |   5 +-
 11 files changed, 428 insertions(+), 268 deletions(-)
 create mode 100644 hw/misc/imx31_ccm.c
 create mode 100644 include/hw/misc/imx31_ccm.h
hw/arm/fsl-imx25.c +3 -3
index e1cadac..9f302ed 100644
@@ -38,7 +38,7 @@ static void fsl_imx25_init(Object *obj)
     object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
     qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
 
-    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
+    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM);
     qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
 
     for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
@@ -150,7 +150,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
             { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
         };
 
-        s->gpt[i].ccm = DEVICE(&s->ccm);
+        s->gpt[i].ccm = IMX_CCM(&s->ccm);
 
         object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
         if (err) {
@@ -173,7 +173,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
             { FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
         };
 
-        s->epit[i].ccm = DEVICE(&s->ccm);
+        s->epit[i].ccm = IMX_CCM(&s->ccm);
 
         object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
         if (err) {
hw/arm/fsl-imx31.c +3 -3
index 53d4473..abdea06 100644
@@ -35,7 +35,7 @@ static void fsl_imx31_init(Object *obj)
     object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
     qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
 
-    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
+    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM);
     qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
 
     for (i = 0; i < FSL_IMX31_NUM_UARTS; i++) {
@@ -128,7 +128,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
                                             serial_table[i].irq));
     }
 
-    s->gpt.ccm = DEVICE(&s->ccm);
+    s->gpt.ccm = IMX_CCM(&s->ccm);
 
     object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err);
     if (err) {
@@ -150,7 +150,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
             { FSL_IMX31_EPIT2_ADDR, FSL_IMX31_EPIT2_IRQ },
         };
 
-        s->epit[i].ccm = DEVICE(&s->ccm);
+        s->epit[i].ccm = IMX_CCM(&s->ccm);
 
         object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
         if (err) {
hw/misc/Makefile.objs +1 -0
index aeb6b7d..c77f3e3 100644
@@ -26,6 +26,7 @@ obj-$(CONFIG_NSERIES) += cbus.o
 obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
 obj-$(CONFIG_IMX) += imx_ccm.o
+obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
hw/misc/imx31_ccm.c new file +306 -0
new file mode 100644
index 0000000..81245d4
@@ -0,0 +1,306 @@
+/*
+ * IMX31 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by Jean-Christophe Dubois <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * To get the timer frequencies right, we need to emulate at least part of
+ * the i.MX31 CCM.
+ */
+
+#include "hw/misc/imx31_ccm.h"
+
+#define CKIH_FREQ 26000000 /* 26MHz crystal input */
+
+#ifndef DEBUG_IMX31_CCM
+#define DEBUG_IMX31_CCM 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+    do { \
+        if (DEBUG_IMX31_CCM) { \
+            fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX31_CCM, \
+                                             __func__, ##args); \
+        } \
+    } while (0)
+
+static char const *imx31_ccm_reg_name(uint32_t reg)
+{
+    switch (reg) {
+    case 0: /* CCMR */
+        return "CCMR";
+    case 1:
+        return "PDR0";
+    case 2:
+        return "PDR1";
+    case 4:
+        return "MPCTL";
+    case 6:
+        return "SPCTL";
+    case 8:
+        return "CGR0";
+    case 9:
+        return "CGR1";
+    case 10:
+        return "CGR2";
+    case 18:
+        return "LTR1";
+    case 23:
+        return "PMCR0";
+    default:
+        return "???";
+    }
+}
+
+static const VMStateDescription vmstate_imx31_ccm = {
+    .name = TYPE_IMX31_CCM,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ccmr, IMX31CCMState),
+        VMSTATE_UINT32(pdr0, IMX31CCMState),
+        VMSTATE_UINT32(pdr1, IMX31CCMState),
+        VMSTATE_UINT32(mpctl, IMX31CCMState),
+        VMSTATE_UINT32(spctl, IMX31CCMState),
+        VMSTATE_UINT32_ARRAY(cgr, IMX31CCMState, 3),
+        VMSTATE_UINT32(pmcr0, IMX31CCMState),
+        VMSTATE_UINT32(pmcr1, IMX31CCMState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static uint32_t imx31_ccm_get_ref_clk(IMXCCMState *dev)
+{
+    IMX31CCMState *s = IMX31_CCM(dev);
+
+    DPRINTF("()\n");
+
+    if ((s->ccmr & CCMR_PRCS) == 2) {
+        return CKIL_FREQ * 1024;
+    } else {
+        return CKIH_FREQ;
+    }
+}
+
+static uint32_t imx31_ccm_get_mcu_clk(IMXCCMState *dev)
+{
+    IMX31CCMState *s = IMX31_CCM(dev);
+
+    DPRINTF("()\n");
+
+    if ((s->ccmr & CCMR_MDS) || !(s->ccmr & CCMR_MPE)) {
+        return imx31_ccm_get_ref_clk(dev);
+    } else {
+        return imx_ccm_calc_pll(s->mpctl, imx31_ccm_get_ref_clk(dev));
+    }
+}
+
+static uint32_t imx31_ccm_get_hsp_clk(IMXCCMState *dev)
+{
+    IMX31CCMState *s = IMX31_CCM(dev);
+
+    DPRINTF("()\n");
+
+    return imx31_ccm_get_mcu_clk(dev) / (1 + EXTRACT(s->pdr0, HSP));
+}
+
+static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
+{
+    IMX31CCMState *s = IMX31_CCM(dev);
+
+    DPRINTF("()\n");
+
+    return imx31_ccm_get_hsp_clk(dev) / (1 + EXTRACT(s->pdr0, IPG));
+}
+
+static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+    uint32_t freq = 0;
+
+    switch (clock) {
+    case NOCLK:
+        break;
+    case CLK_MCU:
+        freq = imx31_ccm_get_mcu_clk(dev);
+        break;
+    case CLK_HSP:
+        freq = imx31_ccm_get_hsp_clk(dev);
+        break;
+    case CLK_IPG:
+        freq = imx31_ccm_get_ipg_clk(dev);
+        break;
+    case CLK_32k:
+        freq = CKIL_FREQ;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
+                      TYPE_IMX31_CCM, __func__, clock);
+        break;
+    }
+
+    DPRINTF("Clock = %d) = %d\n", clock, freq);
+
+    return freq;
+}
+
+static void imx31_ccm_reset(DeviceState *dev)
+{
+    IMX31CCMState *s = IMX31_CCM(dev);
+
+    DPRINTF("()\n");
+
+    s->ccmr = 0x074b0b7b;
+    s->pdr0 = 0xff870b48;
+    s->pdr1 = 0x49fcfe7f;
+    s->mpctl = PLL_PD(1) | PLL_MFD(0) | PLL_MFI(6) | PLL_MFN(0);
+    s->cgr[0] = s->cgr[1] = s->cgr[2] = 0xffffffff;
+    s->spctl = PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1);
+    s->pmcr0 = 0x80209828;
+}
+
+static uint64_t imx31_ccm_read(void *opaque, hwaddr offset, unsigned size)
+{
+    uint32 value = 0;
+    IMX31CCMState *s = (IMX31CCMState *)opaque;
+
+    switch (offset >> 2) {
+    case 0: /* CCMR */
+        value = s->ccmr;
+        break;
+    case 1:
+        value = s->pdr0;
+        break;
+    case 2:
+        value = s->pdr1;
+        break;
+    case 4:
+        value = s->mpctl;
+        break;
+    case 6:
+        value = s->spctl;
+        break;
+    case 8:
+        value = s->cgr[0];
+        break;
+    case 9:
+        value = s->cgr[1];
+        break;
+    case 10:
+        value = s->cgr[2];
+        break;
+    case 18: /* LTR1 */
+        value = 0x00004040;
+        break;
+    case 23:
+        value = s->pmcr0;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
+        break;
+    }
+
+    DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
+            value);
+
+    return (uint64_t)value;
+}
+
+static void imx31_ccm_write(void *opaque, hwaddr offset, uint64_t value,
+                            unsigned size)
+{
+    IMX31CCMState *s = (IMX31CCMState *)opaque;
+
+    DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
+            (uint32_t)value);
+
+    switch (offset >> 2) {
+    case 0:
+        s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
+        break;
+    case 1:
+        s->pdr0 = value & 0xff9f3fff;
+        break;
+    case 2:
+        s->pdr1 = value;
+        break;
+    case 4:
+        s->mpctl = value & 0xbfff3fff;
+        break;
+    case 6:
+        s->spctl = value & 0xbfff3fff;
+        break;
+    case 8:
+        s->cgr[0] = value;
+        break;
+    case 9:
+        s->cgr[1] = value;
+        break;
+    case 10:
+        s->cgr[2] = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
+        break;
+    }
+}
+
+static const struct MemoryRegionOps imx31_ccm_ops = {
+    .read = imx31_ccm_read,
+    .write = imx31_ccm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        /*
+         * Our device would not work correctly if the guest was doing
+         * unaligned access. This might not be a limitation on the real
+         * device but in practice there is no reason for a guest to access
+         * this device unaligned.
+         */
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+
+};
+
+static void imx31_ccm_init(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    IMX31CCMState *s = IMX31_CCM(obj);
+
+    memory_region_init_io(&s->iomem, OBJECT(dev), &imx31_ccm_ops, s,
+                          TYPE_IMX31_CCM, 0x1000);
+    sysbus_init_mmio(sd, &s->iomem);
+}
+
+static void imx31_ccm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
+
+    dc->reset = imx31_ccm_reset;
+    dc->vmsd = &vmstate_imx31_ccm;
+    dc->desc = "i.MX31 Clock Control Module";
+
+    ccm->get_clock_frequency = imx31_ccm_get_clock_frequency;
+}
+
+static const TypeInfo imx31_ccm_info = {
+    .name          = TYPE_IMX31_CCM,
+    .parent        = TYPE_IMX_CCM,
+    .instance_size = sizeof(IMX31CCMState),
+    .instance_init = imx31_ccm_init,
+    .class_init    = imx31_ccm_class_init,
+};
+
+static void imx31_ccm_register_types(void)
+{
+    type_register_static(&imx31_ccm_info);
+}
+
+type_init(imx31_ccm_register_types)
hw/misc/imx_ccm.c +17 -209
index 415937f..d8c2c34 100644
@@ -7,15 +7,12 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  *
- * To get the timer frequencies right, we need to emulate at least part of
- * the CCM.
+ * This is an abstract base class used to get a common interface to
+ * retrieve the CCM frequencies from the various i.MX SOC.
  */
 
 #include "hw/misc/imx_ccm.h"
 
-#define CKIH_FREQ 26000000 /* 26MHz crystal input */
-#define CKIL_FREQ    32768 /* nominal 32khz clock */
-
 #ifndef DEBUG_IMX_CCM
 #define DEBUG_IMX_CCM 0
 #endif
@@ -28,59 +25,36 @@
         } \
     } while (0)
 
-static int imx_ccm_post_load(void *opaque, int version_id);
 
-static const VMStateDescription vmstate_imx_ccm = {
-    .name = TYPE_IMX_CCM,
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(ccmr, IMXCCMState),
-        VMSTATE_UINT32(pdr0, IMXCCMState),
-        VMSTATE_UINT32(pdr1, IMXCCMState),
-        VMSTATE_UINT32(mpctl, IMXCCMState),
-        VMSTATE_UINT32(spctl, IMXCCMState),
-        VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3),
-        VMSTATE_UINT32(pmcr0, IMXCCMState),
-        VMSTATE_UINT32(pmcr1, IMXCCMState),
-        VMSTATE_UINT32(pll_refclk_freq, IMXCCMState),
-        VMSTATE_END_OF_LIST()
-    },
-    .post_load = imx_ccm_post_load,
-};
-
-uint32_t imx_ccm_get_clock_frequency(DeviceState *dev, IMXClk clock)
+uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
 {
-    IMXCCMState *s = IMX_CCM(dev);
+    IMXCCMClass *klass = IMX_GET_CLASS(dev);
 
-    switch (clock) {
-    case NOCLK:
+    DPRINTF("Clock = %d)\n", clock);
+
+    if (klass->get_clock_frequency) {
+        return klass->get_clock_frequency(dev, clock);
+    } else {
         return 0;
-    case CLK_MCU:
-        return s->mcu_clk_freq;
-    case CLK_HSP:
-        return s->hsp_clk_freq;
-    case CLK_IPG:
-        return s->ipg_clk_freq;
-    case CLK_32k:
-        return CKIL_FREQ;
     }
-    return 0;
 }
 
 /*
  * Calculate PLL output frequency
  */
-static uint32_t calc_pll(uint32_t pllreg, uint32_t base_freq)
+uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
 {
     int32_t mfn = MFN(pllreg);  /* Numerator */
     uint32_t mfi = MFI(pllreg); /* Integer part */
     uint32_t mfd = 1 + MFD(pllreg); /* Denominator */
     uint32_t pd = 1 + PD(pllreg);   /* Pre-divider */
 
+    DPRINTF("pllreg = %d, base_freq = %d)\n", pllreg, base_freq);
+
     if (mfi < 5) {
         mfi = 5;
     }
+
     /* mfn is 10-bit signed twos-complement */
     mfn <<= 32 - 10;
     mfn >>= 32 - 10;
@@ -89,178 +63,12 @@ static uint32_t calc_pll(uint32_t pllreg, uint32_t base_freq)
             (mfd * pd)) << 10;
 }
 
-static void update_clocks(IMXCCMState *s)
-{
-    /*
-     * If we ever emulate more clocks, this should switch to a data-driven
-     * approach
-     */
-
-    if ((s->ccmr & CCMR_PRCS) == 2) {
-        s->pll_refclk_freq = CKIL_FREQ * 1024;
-    } else {
-        s->pll_refclk_freq = CKIH_FREQ;
-    }
-
-    /* ipg_clk_arm aka MCU clock */
-    if ((s->ccmr & CCMR_MDS) || !(s->ccmr & CCMR_MPE)) {
-        s->mcu_clk_freq = s->pll_refclk_freq;
-    } else {
-        s->mcu_clk_freq = calc_pll(s->mpctl, s->pll_refclk_freq);
-    }
-
-    /* High-speed clock */
-    s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP));
-    s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG));
-
-    DPRINTF("mcu %uMHz, HSP %uMHz, IPG %uHz\n",
-            s->mcu_clk_freq / 1000000,
-            s->hsp_clk_freq / 1000000,
-            s->ipg_clk_freq);
-}
-
-static void imx_ccm_reset(DeviceState *dev)
-{
-    IMXCCMState *s = IMX_CCM(dev);
-
-    s->ccmr = 0x074b0b7b;
-    s->pdr0 = 0xff870b48;
-    s->pdr1 = 0x49fcfe7f;
-    s->mpctl = PLL_PD(1) | PLL_MFD(0) | PLL_MFI(6) | PLL_MFN(0);
-    s->cgr[0] = s->cgr[1] = s->cgr[2] = 0xffffffff;
-    s->spctl = PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1);
-    s->pmcr0 = 0x80209828;
-
-    update_clocks(s);
-}
-
-static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
-                                unsigned size)
-{
-    IMXCCMState *s = (IMXCCMState *)opaque;
-
-    DPRINTF("(offset=0x%" HWADDR_PRIx ")\n", offset);
-
-    switch (offset >> 2) {
-    case 0: /* CCMR */
-        DPRINTF(" ccmr = 0x%x\n", s->ccmr);
-        return s->ccmr;
-    case 1:
-        DPRINTF(" pdr0 = 0x%x\n", s->pdr0);
-        return s->pdr0;
-    case 2:
-        DPRINTF(" pdr1 = 0x%x\n", s->pdr1);
-        return s->pdr1;
-    case 4:
-        DPRINTF(" mpctl = 0x%x\n", s->mpctl);
-        return s->mpctl;
-    case 6:
-        DPRINTF(" spctl = 0x%x\n", s->spctl);
-        return s->spctl;
-    case 8:
-        DPRINTF(" cgr0 = 0x%x\n", s->cgr[0]);
-        return s->cgr[0];
-    case 9:
-        DPRINTF(" cgr1 = 0x%x\n", s->cgr[1]);
-        return s->cgr[1];
-    case 10:
-        DPRINTF(" cgr2 = 0x%x\n", s->cgr[2]);
-        return s->cgr[2];
-    case 18: /* LTR1 */
-        return 0x00004040;
-    case 23:
-        DPRINTF(" pcmr0 = 0x%x\n", s->pmcr0);
-        return s->pmcr0;
-    default:
-        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
-                      HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
-        return 0;
-    }
-}
-
-static void imx_ccm_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    IMXCCMState *s = (IMXCCMState *)opaque;
-
-    DPRINTF("(offset=0x%" HWADDR_PRIx ", value = 0x%x)\n",
-            offset, (unsigned int)value);
-
-    switch (offset >> 2) {
-    case 0:
-        s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
-        break;
-    case 1:
-        s->pdr0 = value & 0xff9f3fff;
-        break;
-    case 2:
-        s->pdr1 = value;
-        break;
-    case 4:
-        s->mpctl = value & 0xbfff3fff;
-        break;
-    case 6:
-        s->spctl = value & 0xbfff3fff;
-        break;
-    case 8:
-        s->cgr[0] = value;
-        return;
-    case 9:
-        s->cgr[1] = value;
-        return;
-    case 10:
-        s->cgr[2] = value;
-        return;
-
-    default:
-        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
-                      HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
-        return;
-    }
-    update_clocks(s);
-}
-
-static const struct MemoryRegionOps imx_ccm_ops = {
-    .read = imx_ccm_read,
-    .write = imx_ccm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int imx_ccm_init(SysBusDevice *dev)
-{
-    IMXCCMState *s = IMX_CCM(dev);
-
-    memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s,
-                          TYPE_IMX_CCM, 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static int imx_ccm_post_load(void *opaque, int version_id)
-{
-    IMXCCMState *s = (IMXCCMState *)opaque;
-
-    update_clocks(s);
-    return 0;
-}
-
-static void imx_ccm_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sbc->init = imx_ccm_init;
-    dc->reset = imx_ccm_reset;
-    dc->vmsd = &vmstate_imx_ccm;
-    dc->desc = "i.MX Clock Control Module";
-}
-
 static const TypeInfo imx_ccm_info = {
-    .name = TYPE_IMX_CCM,
-    .parent = TYPE_SYS_BUS_DEVICE,
+    .name          = TYPE_IMX_CCM,
+    .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IMXCCMState),
-    .class_init = imx_ccm_class_init,
+    .class_size    = sizeof(IMXCCMClass),
+    .abstract      = true,
 };
 
 static void imx_ccm_register_types(void)
include/hw/arm/fsl-imx25.h +2 -2
index 73f50c6..5c62fde 100644
@@ -19,7 +19,7 @@
 
 #include "hw/arm/arm.h"
 #include "hw/intc/imx_avic.h"
-#include "hw/misc/imx_ccm.h"
+#include "hw/misc/imx31_ccm.h"
 #include "hw/char/imx_serial.h"
 #include "hw/timer/imx_gpt.h"
 #include "hw/timer/imx_epit.h"
@@ -44,7 +44,7 @@ typedef struct FslIMX25State {
     /*< public >*/
     ARMCPU         cpu;
     IMXAVICState   avic;
-    IMXCCMState    ccm;
+    IMX31CCMState  ccm;
     IMXSerialState uart[FSL_IMX25_NUM_UARTS];
     IMXGPTState    gpt[FSL_IMX25_NUM_GPTS];
     IMXEPITState   epit[FSL_IMX25_NUM_EPITS];
include/hw/arm/fsl-imx31.h +2 -2
index 5e8f795..d408abb 100644
@@ -19,7 +19,7 @@
 
 #include "hw/arm/arm.h"
 #include "hw/intc/imx_avic.h"
-#include "hw/misc/imx_ccm.h"
+#include "hw/misc/imx31_ccm.h"
 #include "hw/char/imx_serial.h"
 #include "hw/timer/imx_gpt.h"
 #include "hw/timer/imx_epit.h"
@@ -42,7 +42,7 @@ typedef struct FslIMX31State {
     /*< public >*/
     ARMCPU         cpu;
     IMXAVICState   avic;
-    IMXCCMState    ccm;
+    IMX31CCMState  ccm;
     IMXSerialState uart[FSL_IMX31_NUM_UARTS];
     IMXGPTState    gpt;
     IMXEPITState   epit[FSL_IMX31_NUM_EPITS];
include/hw/misc/imx31_ccm.h new file +64 -0
new file mode 100644
index 0000000..47be0cd
@@ -0,0 +1,64 @@
+/*
+ * IMX31 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by Jean-Christophe Dubois <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef IMX31_CCM_H
+#define IMX31_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+
+/* CCMR */
+#define CCMR_FPME (1<<0)
+#define CCMR_MPE  (1<<3)
+#define CCMR_MDS  (1<<7)
+#define CCMR_FPMF (1<<26)
+#define CCMR_PRCS (3<<1)
+
+/* PDR0 */
+#define PDR0_MCU_PODF_SHIFT (0)
+#define PDR0_MCU_PODF_MASK (0x7)
+#define PDR0_MAX_PODF_SHIFT (3)
+#define PDR0_MAX_PODF_MASK (0x7)
+#define PDR0_IPG_PODF_SHIFT (6)
+#define PDR0_IPG_PODF_MASK (0x3)
+#define PDR0_NFC_PODF_SHIFT (8)
+#define PDR0_NFC_PODF_MASK (0x7)
+#define PDR0_HSP_PODF_SHIFT (11)
+#define PDR0_HSP_PODF_MASK (0x7)
+#define PDR0_PER_PODF_SHIFT (16)
+#define PDR0_PER_PODF_MASK (0x1f)
+#define PDR0_CSI_PODF_SHIFT (23)
+#define PDR0_CSI_PODF_MASK (0x1ff)
+
+#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \
+                              & PDR0_##name##_PODF_MASK)
+#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \
+                             PDR0_##name##_PODF_SHIFT)
+
+#define TYPE_IMX31_CCM "imx31.ccm"
+#define IMX31_CCM(obj) OBJECT_CHECK(IMX31CCMState, (obj), TYPE_IMX31_CCM)
+
+typedef struct IMX31CCMState {
+    /* <private> */
+    IMXCCMState parent_obj;
+
+    /* <public> */
+    MemoryRegion iomem;
+
+    uint32_t ccmr;
+    uint32_t pdr0;
+    uint32_t pdr1;
+    uint32_t mpctl;
+    uint32_t spctl;
+    uint32_t cgr[3];
+    uint32_t pmcr0;
+    uint32_t pmcr1;
+} IMX31CCMState;
+
+#endif /* IMX31_CCM_H */
include/hw/misc/imx_ccm.h +24 -45
index 09f6248..5c4b795 100644
@@ -1,5 +1,5 @@
 /*
- * IMX31 Clock Control Module
+ * IMX Clock Control Module base class
  *
  * Copyright (C) 2012 NICTA
  * Updated by Jean-Christophe Dubois <[email protected]>
@@ -13,33 +13,7 @@
 
 #include "hw/sysbus.h"
 
-/* CCMR */
-#define CCMR_FPME (1<<0)
-#define CCMR_MPE  (1<<3)
-#define CCMR_MDS  (1<<7)
-#define CCMR_FPMF (1<<26)
-#define CCMR_PRCS (3<<1)
-
-/* PDR0 */
-#define PDR0_MCU_PODF_SHIFT (0)
-#define PDR0_MCU_PODF_MASK (0x7)
-#define PDR0_MAX_PODF_SHIFT (3)
-#define PDR0_MAX_PODF_MASK (0x7)
-#define PDR0_IPG_PODF_SHIFT (6)
-#define PDR0_IPG_PODF_MASK (0x3)
-#define PDR0_NFC_PODF_SHIFT (8)
-#define PDR0_NFC_PODF_MASK (0x7)
-#define PDR0_HSP_PODF_SHIFT (11)
-#define PDR0_HSP_PODF_MASK (0x7)
-#define PDR0_PER_PODF_SHIFT (16)
-#define PDR0_PER_PODF_MASK (0x1f)
-#define PDR0_CSI_PODF_SHIFT (23)
-#define PDR0_CSI_PODF_MASK (0x1ff)
-
-#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \
-                              & PDR0_##name##_PODF_MASK)
-#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \
-                             PDR0_##name##_PODF_SHIFT)
+#define CKIL_FREQ 32768 /* nominal 32khz clock */
 
 /* PLL control registers */
 #define PD(v) (((v) >> 26) & 0xf)
@@ -53,39 +27,44 @@
 #define PLL_MFN(x)              (((x) & 0x3ff) << 0)
 
 #define TYPE_IMX_CCM "imx.ccm"
-#define IMX_CCM(obj) OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
+#define IMX_CCM(obj) \
+     OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
+#define IMX_CCM_CLASS(klass) \
+     OBJECT_CLASS_CHECK(IMXCCMClass, (klass), TYPE_IMX_CCM)
+#define IMX_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(IMXCCMClass, (obj), TYPE_IMX_CCM)
 
 typedef struct IMXCCMState {
     /* <private> */
     SysBusDevice parent_obj;
 
     /* <public> */
-    MemoryRegion iomem;
 
-    uint32_t ccmr;
-    uint32_t pdr0;
-    uint32_t pdr1;
-    uint32_t mpctl;
-    uint32_t spctl;
-    uint32_t cgr[3];
-    uint32_t pmcr0;
-    uint32_t pmcr1;
-
-    /* Frequencies precalculated on register changes */
-    uint32_t pll_refclk_freq;
-    uint32_t mcu_clk_freq;
-    uint32_t hsp_clk_freq;
-    uint32_t ipg_clk_freq;
 } IMXCCMState;
 
 typedef enum  {
     NOCLK,
+    CLK_MPLL,
+    CLK_UPLL,
     CLK_MCU,
     CLK_HSP,
+    CLK_MAX,
+    CLK_AHB,
     CLK_IPG,
+    CLK_PER,
     CLK_32k
 } IMXClk;
 
-uint32_t imx_ccm_get_clock_frequency(DeviceState *s, IMXClk clock);
+typedef struct IMXCCMClass {
+    /* <private> */
+    SysBusDeviceClass parent_class;
+
+    /* <public> */
+    uint32_t (*get_clock_frequency)(IMXCCMState *s, IMXClk clk);
+} IMXCCMClass;
+
+uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq);
+
+uint32_t imx_ccm_get_clock_frequency(IMXCCMState *s, IMXClk clock);
 
 #endif /* IMX_CCM_H */
include/hw/timer/imx_epit.h +3 -2
index c5328ae..0730ac3 100644
@@ -31,6 +31,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "hw/misc/imx_ccm.h"
 
 /*
  * EPIT: Enhanced periodic interrupt timer
@@ -63,8 +64,8 @@ typedef struct IMXEPITState{
     /*< public >*/
     ptimer_state *timer_reload;
     ptimer_state *timer_cmp;
-    MemoryRegion iomem;
-    DeviceState *ccm;
+    MemoryRegion  iomem;
+    IMXCCMState  *ccm;
 
     uint32_t cr;
     uint32_t sr;
include/hw/timer/imx_gpt.h +3 -3
index 3f02d3b..461adbe 100644
@@ -31,6 +31,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
+#include "hw/misc/imx_ccm.h"
 
 /*
  * GPT : General purpose timer
@@ -82,8 +83,8 @@ typedef struct IMXGPTState{
 
     /*< public >*/
     ptimer_state *timer;
-    MemoryRegion iomem;
-    DeviceState *ccm;
+    MemoryRegion  iomem;
+    IMXCCMState  *ccm;
 
     uint32_t cr;
     uint32_t pr;
--

2.5.0

#5 lore raw

PATCH v4 3/3 i.MX: Add an i.MX25 specific CCM class/instance.

In reply to Jean-Christophe Dubois

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

 hw/arm/fsl-imx25.c          |   2 +-
 hw/misc/Makefile.objs       |   1 +
 hw/misc/imx25_ccm.c         | 276 ++++++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/fsl-imx25.h  |   4 +-
 include/hw/misc/imx25_ccm.h |  59 ++++++++++
 5 files changed, 339 insertions(+), 3 deletions(-)
 create mode 100644 hw/misc/imx25_ccm.c
 create mode 100644 include/hw/misc/imx25_ccm.h
hw/arm/fsl-imx25.c +1 -1
index 9f302ed..36818ee 100644
@@ -38,7 +38,7 @@ static void fsl_imx25_init(Object *obj)
     object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
     qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
 
-    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM);
+    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX25_CCM);
     qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
 
     for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
hw/misc/Makefile.objs +1 -0
index c77f3e3..8a235df 100644
@@ -27,6 +27,7 @@ obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
 obj-$(CONFIG_IMX) += imx_ccm.o
 obj-$(CONFIG_IMX) += imx31_ccm.o
+obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
hw/misc/imx25_ccm.c new file +276 -0

276 lines not on this page · raw message

include/hw/arm/fsl-imx25.h +2 -2
index 5c62fde..d0e8e9d 100644
@@ -19,7 +19,7 @@
 
 #include "hw/arm/arm.h"
 #include "hw/intc/imx_avic.h"
-#include "hw/misc/imx31_ccm.h"
+#include "hw/misc/imx25_ccm.h"
 #include "hw/char/imx_serial.h"
 #include "hw/timer/imx_gpt.h"
 #include "hw/timer/imx_epit.h"
@@ -44,7 +44,7 @@ typedef struct FslIMX25State {
     /*< public >*/
     ARMCPU         cpu;
     IMXAVICState   avic;
-    IMX31CCMState  ccm;
+    IMX25CCMState  ccm;
     IMXSerialState uart[FSL_IMX25_NUM_UARTS];
     IMXGPTState    gpt[FSL_IMX25_NUM_GPTS];
     IMXEPITState   epit[FSL_IMX25_NUM_EPITS];
include/hw/misc/imx25_ccm.h new file +59 -0

59 lines not on this page · raw message

Signature · 1 line
2.5.0
#6 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

Quoted 1 line · Jean-Christophe Dubois

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at
/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xf0/0x114()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)
[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)

[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114) [<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560) [<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0) [<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac) [<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90) [<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0) [<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210) [<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8) [<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0) [<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec) [<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

Quoted 20 lines

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

 hw/arm/fsl-imx25.c          |   2 +-
 hw/misc/Makefile.objs       |   1 +
 hw/misc/imx25_ccm.c         | 276 ++++++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/fsl-imx25.h  |   4 +-
 include/hw/misc/imx25_ccm.h |  59 ++++++++++
 5 files changed, 339 insertions(+), 3 deletions(-)
 create mode 100644 hw/misc/imx25_ccm.c
 create mode 100644 include/hw/misc/imx25_ccm.h
#7 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

Quoted 40 lines · Peter Crosthwaite
Quoted 1 line · Jean-Christophe Dubois

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at
/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xf0/0x114()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)
[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)

[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114) [<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560) [<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0) [<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac) [<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90) [<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0) [<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210) [<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8) [<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0) [<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec) [<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Quoted 6 lines

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

The kernel I am testing with is 3.19.0 but without without DTS tree.

Linux version 3.19.0 (jcd@jcd-U31SG) (gcc version 4.6.3 (GCC) ) #2 Mon Jun 22 00:32:04 CEST 2015

So I am not up to date on this side and I might not test the same devices as you do as I generated a "minimal" kernel for my test.

Anyway, testing the timer code I found that running "sleep 60" on both PTF doesn't give the expected 60 seconds in "real world time":

* On i.MX31 (using i.MX31 CCM) => 47 seconds
* On i.MX25 (using i.MX31 CCM) => 52 seconds (before change. close enough?)
* On i.MX25 (using i.MX25 CCM) => 80 seconds

Another indication, the bogomips:

* On i.MX31 (using i.MX31 CCM) => 78
* On i.MX25 (using i.MX31 CCM) => 87 (before change. close enough?)
* On i.MX25 (using i.MX25 CCM) => 133

So, yes, for some reason "time goes slower" after switching to i.MX25 CCM ... (but it was also going too fast before with i.MX31 CCM)

As the CCM doesn't really provide any clock (just a clock value) something must not be right in the way the i.MX GPT timer is computing time.

I need to look after this.

JC

Quoted 21 lines
Quoted 21 lines

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

  hw/arm/fsl-imx25.c          |   2 +-
  hw/misc/Makefile.objs       |   1 +
  hw/misc/imx25_ccm.c         | 276 ++++++++++++++++++++++++++++++++++++++++++++
  include/hw/arm/fsl-imx25.h  |   4 +-
  include/hw/misc/imx25_ccm.h |  59 ++++++++++
  5 files changed, 339 insertions(+), 3 deletions(-)

create mode 100644 hw/misc/imx25_ccm.c
create mode 100644 include/hw/misc/imx25_ccm.h

#8 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

Quoted 55 lines · Jean-Christophe DUBOIS

Le 27/11/2015 03:39, Peter Crosthwaite a écrit :

On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois <[email protected]> wrote:

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at
/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xf0/0x114()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)
[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)

[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114) [<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560) [<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0) [<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac) [<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90)
[<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0)
[<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210)
[<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8) [<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0)
[<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec) [<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

Quoted 7 lines

The kernel I am testing with is 3.19.0 but without without DTS tree. Linux version 3.19.0 (jcd@jcd-U31SG) (gcc version 4.6.3 (GCC) ) #2 Mon Jun 22 00:32:04 CEST 2015

So I am not up to date on this side and I might not test the same devices as you do as I generated a "minimal" kernel for my test.

So the DTB+defconfig boot is actually in pretty good shape. That NAND thing is the only real bootlog issue. All other missing peripherals fail gracefully.

Quoted 6 lines

Anyway, testing the timer code I found that running "sleep 60" on both PTF doesn't give the expected 60 seconds in "real world time":

On i.MX31 (using i.MX31 CCM) => 47 seconds

On i.MX25 (using i.MX31 CCM) => 52 seconds (before change. close enough?)

Confirmed this result, exactly the same here.

Quoted 8 lines

On i.MX25 (using i.MX25 CCM) => 80 seconds

Another indication, the bogomips:

On i.MX31 (using i.MX31 CCM) => 78
On i.MX25 (using i.MX31 CCM) => 87 (before change. close enough?) On i.MX25 (using i.MX25 CCM) => 133

I wouldn't worry about this, this is rarely accurate in QEMU.

Regards,
Peter

Quoted 32 lines

So, yes, for some reason "time goes slower" after switching to i.MX25 CCM ... (but it was also going too fast before with i.MX31 CCM)

As the CCM doesn't really provide any clock (just a clock value) something must not be right in the way the i.MX GPT timer is computing time.

I need to look after this.

JC

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

 hw/arm/fsl-imx25.c          |   2 +-
 hw/misc/Makefile.objs       |   1 +
 hw/misc/imx25_ccm.c         | 276
++++++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/fsl-imx25.h  |   4 +-
 include/hw/misc/imx25_ccm.h |  59 ++++++++++
 5 files changed, 339 insertions(+), 3 deletions(-)
 create mode 100644 hw/misc/imx25_ccm.c
 create mode 100644 include/hw/misc/imx25_ccm.h
#9 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

Quoted 61 lines · Peter Crosthwaite
Quoted 59 lines · Jean-Christophe DUBOIS

Le 27/11/2015 03:39, Peter Crosthwaite a écrit :

On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois <[email protected]> wrote:

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at
/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xf0/0x114()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)
[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)

[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114) [<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560) [<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0) [<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac) [<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90)
[<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0)
[<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210)
[<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8) [<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0)
[<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec) [<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

The kernel I am testing with is 3.19.0 but without without DTS tree. Linux version 3.19.0 (jcd@jcd-U31SG) (gcc version 4.6.3 (GCC) ) #2 Mon Jun 22 00:32:04 CEST 2015

Quoted 8 lines
Quoted 3 lines

So I am not up to date on this side and I might not test the same devices as you do as I generated a "minimal" kernel for my test.

So the DTB+defconfig boot is actually in pretty good shape. That NAND thing is the only real bootlog issue. All other missing peripherals fail gracefully.

In my runtime linux kernel tests, I disable CONFIG_MTD_NAND_MXC to avoid the nand problem - both the log message and the long boot time.

Guenter

Quoted 56 lines
Quoted 6 lines

Anyway, testing the timer code I found that running "sleep 60" on both PTF doesn't give the expected 60 seconds in "real world time":

On i.MX31 (using i.MX31 CCM) => 47 seconds

On i.MX25 (using i.MX31 CCM) => 52 seconds (before change. close enough?)

Confirmed this result, exactly the same here.

Quoted 8 lines

On i.MX25 (using i.MX25 CCM) => 80 seconds

Another indication, the bogomips:

On i.MX31 (using i.MX31 CCM) => 78
On i.MX25 (using i.MX31 CCM) => 87 (before change. close enough?) On i.MX25 (using i.MX25 CCM) => 133

I wouldn't worry about this, this is rarely accurate in QEMU.

Regards,
Peter

Quoted 32 lines

So, yes, for some reason "time goes slower" after switching to i.MX25 CCM ... (but it was also going too fast before with i.MX31 CCM)

As the CCM doesn't really provide any clock (just a clock value) something must not be right in the way the i.MX GPT timer is computing time.

I need to look after this.

JC

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

  hw/arm/fsl-imx25.c          |   2 +-
  hw/misc/Makefile.objs       |   1 +
  hw/misc/imx25_ccm.c         | 276
++++++++++++++++++++++++++++++++++++++++++++
  include/hw/arm/fsl-imx25.h  |   4 +-
  include/hw/misc/imx25_ccm.h |  59 ++++++++++
  5 files changed, 339 insertions(+), 3 deletions(-)

create mode 100644 hw/misc/imx25_ccm.c
create mode 100644 include/hw/misc/imx25_ccm.h

#10 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

In reply to Peter Crosthwaite
Quoted 61 lines · Peter Crosthwaite
Quoted 59 lines · Jean-Christophe DUBOIS

Le 27/11/2015 03:39, Peter Crosthwaite a écrit :

On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois <[email protected]> wrote:

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at
/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xf0/0x114()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)
[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)

[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114) [<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560) [<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0) [<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac) [<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90)
[<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0)
[<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210)
[<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8) [<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0)
[<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec) [<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

The kernel I am testing with is 3.19.0 but without without DTS tree. Linux version 3.19.0 (jcd@jcd-U31SG) (gcc version 4.6.3 (GCC) ) #2 Mon Jun 22 00:32:04 CEST 2015

Quoted 6 lines
Quoted 3 lines

So I am not up to date on this side and I might not test the same devices as you do as I generated a "minimal" kernel for my test.

So the DTB+defconfig boot is actually in pretty good shape. That NAND thing is the only real bootlog issue. All other missing peripherals fail gracefully.

I tried the latest kernel (4.4.0 rc2) with full defconfig and dtb and I am getting the same timeout issue even with the i.MX31 CCM module.

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at drivers/mtd/nand/mxc_nand.c:464 wait_op_done+0xe0/0x104()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.4.0-rc2-00118-g1724734 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eb8c>] (unwind_backtrace) from [<c000d014>] (show_stack+0x10/0x14)
[<c000d014>] (show_stack) from [<c0018c10>] (warn_slowpath_common+0x78/0xb0)
[<c0018c10>] (warn_slowpath_common) from [<c0018cdc>] (warn_slowpath_fmt+0x30/0x40)
[<c0018cdc>] (warn_slowpath_fmt) from [<c035ace4>] (wait_op_done+0xe0/0x104)
[<c035ace4>] (wait_op_done) from [<c035a86c>] (mxc_nand_command+0x150/0x4a8)
[<c035a86c>] (mxc_nand_command) from [<c03546d8>] (nand_scan_ident+0xe4/0x1580)
[<c03546d8>] (nand_scan_ident) from [<c035a25c>] (mxcnd_probe+0x370/0x5a0)
[<c035a25c>] (mxcnd_probe) from [<c02f0698>] (platform_drv_probe+0x54/0xa4)
[<c02f0698>] (platform_drv_probe) from [<c02eec08>] (driver_probe_device+0x1e4/0x2a8)
[<c02eec08>] (driver_probe_device) from [<c02eed58>] (__driver_attach+0x8c/0x90)
[<c02eed58>] (__driver_attach) from [<c02ed484>] (bus_for_each_dev+0x5c/0x8c)
[<c02ed484>] (bus_for_each_dev) from [<c02ee380>] (bus_add_driver+0x160/0x1f8)
[<c02ee380>] (bus_add_driver) from [<c02ef814>] (driver_register+0x78/0xf4)
[<c02ef814>] (driver_register) from [<c0009600>] (do_one_initcall+0x84/0x1f4)
[<c0009600>] (do_one_initcall) from [<c0708cf0>] (kernel_init_freeable+0xf8/0x1bc)
[<c0708cf0>] (kernel_init_freeable) from [<c05373d8>] (kernel_init+0x8/0xe4)
[<c05373d8>] (kernel_init) from [<c000a370>] (ret_from_fork+0x14/0x24)
---[ end trace 03bc7274bbc34493 ]---

nand: No NAND device found

I tried it with mainline qemu (so without any of my changes) and I still run in the problem.

So not sure it is related to the change in the i.MX25 CCM device.

JC

Quoted 53 lines
Quoted 6 lines

Anyway, testing the timer code I found that running "sleep 60" on both PTF doesn't give the expected 60 seconds in "real world time":

On i.MX31 (using i.MX31 CCM) => 47 seconds
On i.MX25 (using i.MX31 CCM) => 52 seconds (before change. close enough?)

Confirmed this result, exactly the same here.

Quoted 8 lines

On i.MX25 (using i.MX25 CCM) => 80 seconds

Another indication, the bogomips:

On i.MX31 (using i.MX31 CCM) => 78
On i.MX25 (using i.MX31 CCM) => 87 (before change. close enough?) On i.MX25 (using i.MX25 CCM) => 133

I wouldn't worry about this, this is rarely accurate in QEMU.

Regards,
Peter

Quoted 32 lines

So, yes, for some reason "time goes slower" after switching to i.MX25 CCM ... (but it was also going too fast before with i.MX31 CCM)

As the CCM doesn't really provide any clock (just a clock value) something must not be right in the way the i.MX GPT timer is computing time.

I need to look after this.

JC

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

  hw/arm/fsl-imx25.c          |   2 +-
  hw/misc/Makefile.objs       |   1 +
  hw/misc/imx25_ccm.c         | 276
++++++++++++++++++++++++++++++++++++++++++++
  include/hw/arm/fsl-imx25.h  |   4 +-
  include/hw/misc/imx25_ccm.h |  59 ++++++++++
  5 files changed, 339 insertions(+), 3 deletions(-)

create mode 100644 hw/misc/imx25_ccm.c
create mode 100644 include/hw/misc/imx25_ccm.h

#11 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

Quoted 117 lines · Jean-Christophe DUBOIS
Quoted 72 lines · Peter Crosthwaite
Quoted 69 lines · Jean-Christophe DUBOIS

Le 27/11/2015 03:39, Peter Crosthwaite a écrit :

On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois <[email protected]> wrote:

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at

/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464 wait_op_done+0xf0/0x114()
timeout! useirq=0

Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)

[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)
[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114)
[<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560)
[<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0)
[<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac)
[<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90)
[<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0)
[<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210)
[<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8)
[<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0)
[<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec)
[<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

The kernel I am testing with is 3.19.0 but without without DTS tree. Linux version 3.19.0 (jcd@jcd-U31SG) (gcc version 4.6.3 (GCC) ) #2 Mon Jun
22 00:32:04 CEST 2015

Quoted 7 lines
Quoted 4 lines

So I am not up to date on this side and I might not test the same devices as
you do as I generated a "minimal" kernel for my test.

So the DTB+defconfig boot is actually in pretty good shape. That NAND thing is the only real bootlog issue. All other missing peripherals fail gracefully.

I tried the latest kernel (4.4.0 rc2) with full defconfig and dtb and I am getting the same timeout issue even with the i.MX31 CCM module.

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xe0/0x104()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.4.0-rc2-00118-g1724734 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eb8c>] (unwind_backtrace) from [<c000d014>] (show_stack+0x10/0x14)
[<c000d014>] (show_stack) from [<c0018c10>] (warn_slowpath_common+0x78/0xb0)

[<c0018c10>] (warn_slowpath_common) from [<c0018cdc>] (warn_slowpath_fmt+0x30/0x40)
[<c0018cdc>] (warn_slowpath_fmt) from [<c035ace4>] (wait_op_done+0xe0/0x104) [<c035ace4>] (wait_op_done) from [<c035a86c>] (mxc_nand_command+0x150/0x4a8) [<c035a86c>] (mxc_nand_command) from [<c03546d8>] (nand_scan_ident+0xe4/0x1580)
[<c03546d8>] (nand_scan_ident) from [<c035a25c>] (mxcnd_probe+0x370/0x5a0) [<c035a25c>] (mxcnd_probe) from [<c02f0698>] (platform_drv_probe+0x54/0xa4) [<c02f0698>] (platform_drv_probe) from [<c02eec08>] (driver_probe_device+0x1e4/0x2a8)
[<c02eec08>] (driver_probe_device) from [<c02eed58>] (__driver_attach+0x8c/0x90)
[<c02eed58>] (__driver_attach) from [<c02ed484>] (bus_for_each_dev+0x5c/0x8c)
[<c02ed484>] (bus_for_each_dev) from [<c02ee380>] (bus_add_driver+0x160/0x1f8)
[<c02ee380>] (bus_add_driver) from [<c02ef814>] (driver_register+0x78/0xf4) [<c02ef814>] (driver_register) from [<c0009600>] (do_one_initcall+0x84/0x1f4)
[<c0009600>] (do_one_initcall) from [<c0708cf0>] (kernel_init_freeable+0xf8/0x1bc)
[<c0708cf0>] (kernel_init_freeable) from [<c05373d8>] (kernel_init+0x8/0xe4) [<c05373d8>] (kernel_init) from [<c000a370>] (ret_from_fork+0x14/0x24)

Quoted 8 lines
---[ end trace 03bc7274bbc34493 ]---

nand: No NAND device found

I tried it with mainline qemu (so without any of my changes) and I still run in the problem.

So not sure it is related to the change in the i.MX25 CCM device.

The NAND failure is always present and not an issue. Just I observe a large change in the timeout delay with this patch applied.

Regards,
Peter

Quoted 61 lines

JC

Quoted 56 lines
Quoted 7 lines

Anyway, testing the timer code I found that running "sleep 60" on both PTF
doesn't give the expected 60 seconds in "real world time":

On i.MX31 (using i.MX31 CCM) => 47 seconds
On i.MX25 (using i.MX31 CCM) => 52 seconds (before change. close enough?)

Confirmed this result, exactly the same here.

Quoted 8 lines

On i.MX25 (using i.MX25 CCM) => 80 seconds

Another indication, the bogomips:

On i.MX31 (using i.MX31 CCM) => 78
On i.MX25 (using i.MX31 CCM) => 87 (before change. close enough?) On i.MX25 (using i.MX25 CCM) => 133

I wouldn't worry about this, this is rarely accurate in QEMU.

Regards,
Peter

Quoted 33 lines

So, yes, for some reason "time goes slower" after switching to i.MX25 CCM ... (but it was also going too fast before with i.MX31 CCM)

As the CCM doesn't really provide any clock (just a clock value) something
must not be right in the way the i.MX GPT timer is computing time.

I need to look after this.

JC

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

  hw/arm/fsl-imx25.c          |   2 +-
  hw/misc/Makefile.objs       |   1 +
  hw/misc/imx25_ccm.c         | 276
++++++++++++++++++++++++++++++++++++++++++++
  include/hw/arm/fsl-imx25.h  |   4 +-
  include/hw/misc/imx25_ccm.h |  59 ++++++++++
  5 files changed, 339 insertions(+), 3 deletions(-)

create mode 100644 hw/misc/imx25_ccm.c
create mode 100644 include/hw/misc/imx25_ccm.h

#12 lore raw

Re: [Qemu-arm] [PATCH v4 3/3] i.MX: Add an i.MX25 specific CCM class/instance.

In reply to Peter Crosthwaite
Quoted 68 lines · Peter Crosthwaite
Quoted 55 lines · Jean-Christophe DUBOIS

Le 27/11/2015 03:39, Peter Crosthwaite a écrit :

On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois <[email protected]> wrote:

This seems to slow down boot performance for i.MX25 Linux. Admittedly, the issue looks to be in timeout code for an unmodelled periph (NAND):

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at
/home/pcrost/poky/build/tmp/work-shared/qemuarmv5imx/kernel-source/drivers/mtd/nand/mxc_nand.c:464
wait_op_done+0xf0/0x114()
timeout! useirq=0
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.1 #1
Hardware name: Freescale i.MX25 (Device Tree Support)
[<c000eec8>] (unwind_backtrace) from [<c000d2b0>] (show_stack+0x10/0x14)
[<c000d2b0>] (show_stack) from [<c0019154>] (warn_slowpath_common+0x74/0xac)

[<c0019154>] (warn_slowpath_common) from [<c00191bc>] (warn_slowpath_fmt+0x30/0x40)
[<c00191bc>] (warn_slowpath_fmt) from [<c036eaa0>] (wait_op_done+0xf0/0x114) [<c036eaa0>] (wait_op_done) from [<c0369698>] (nand_scan_ident+0xdc/0x1560) [<c0369698>] (nand_scan_ident) from [<c036e6a8>] (mxcnd_probe+0x378/0x5c0) [<c036e6a8>] (mxcnd_probe) from [<c03081a4>] (platform_drv_probe+0x44/0xac) [<c03081a4>] (platform_drv_probe) from [<c0306654>] (driver_probe_device+0x180/0x2c4)
[<c0306654>] (driver_probe_device) from [<c0306824>] (__driver_attach+0x8c/0x90)
[<c0306824>] (__driver_attach) from [<c0304a80>] (bus_for_each_dev+0x70/0xa0)
[<c0304a80>] (bus_for_each_dev) from [<c0305d08>] (bus_add_driver+0x188/0x210)
[<c0305d08>] (bus_add_driver) from [<c03071d4>] (driver_register+0x78/0xf8) [<c03071d4>] (driver_register) from [<c00095e0>] (do_one_initcall+0x84/0x1f0)
[<c00095e0>] (do_one_initcall) from [<c071bd24>] (kernel_init_freeable+0x108/0x1c8)
[<c071bd24>] (kernel_init_freeable) from [<c0541a0c>] (kernel_init+0x8/0xec) [<c0541a0c>] (kernel_init) from [<c000a340>] (ret_from_fork+0x14/0x34)

---[ end trace 13248cb1a1bbcb9c ]---

<<Delay happens here>>

nand: No NAND device found
...

Without this patch, the delay is around 2 seconds, with this patch it is 10+. Any idea what would cause it? Are you removing the NAND from DTS for your testing and do we not care about these errors paths?

Regards,
Peter

Quoted 7 lines

The kernel I am testing with is 3.19.0 but without without DTS tree. Linux version 3.19.0 (jcd@jcd-U31SG) (gcc version 4.6.3 (GCC) ) #2 Mon Jun 22 00:32:04 CEST 2015

So I am not up to date on this side and I might not test the same devices as you do as I generated a "minimal" kernel for my test.

So the DTB+defconfig boot is actually in pretty good shape. That NAND thing is the only real bootlog issue. All other missing peripherals fail gracefully.

Quoted 6 lines
Quoted 5 lines

Anyway, testing the timer code I found that running "sleep 60" on both PTF doesn't give the expected 60 seconds in "real world time":

On i.MX31 (using i.MX31 CCM) => 47 seconds
On i.MX25 (using i.MX31 CCM) => 52 seconds (before change. close enough?)

Confirmed this result, exactly the same here.

The 47 sec for i.MX31 is because Qemu sets the IPG/GPT clock to 50 MHz but the Linux guest code for some reason detects only a 39 MHz GPT clock. The decrepancy explains that the time then goes faster for the Linux guest (sleep 60 wait in fact for 47 real seconds).

I need to find why Linux is not retrieving the "correct" freq value from Qemu.

JC

Quoted 46 lines
Quoted 9 lines

On i.MX25 (using i.MX25 CCM) => 80 seconds

Another indication, the bogomips:

On i.MX31 (using i.MX31 CCM) => 78
On i.MX25 (using i.MX31 CCM) => 87 (before change. close enough?) On i.MX25 (using i.MX25 CCM) => 133

I wouldn't worry about this, this is rarely accurate in QEMU.

Regards,
Peter

Quoted 32 lines

So, yes, for some reason "time goes slower" after switching to i.MX25 CCM ... (but it was also going too fast before with i.MX31 CCM)

As the CCM doesn't really provide any clock (just a clock value) something must not be right in the way the i.MX GPT timer is computing time.

I need to look after this.

JC

---

Changes since v1:
* rework loging to match other i.MX drivers

Changes since v2:
* We moved to an inheritance QOM scheme

Changes since v3:
* Rework logging based on comments.

  hw/arm/fsl-imx25.c          |   2 +-
  hw/misc/Makefile.objs       |   1 +
  hw/misc/imx25_ccm.c         | 276
++++++++++++++++++++++++++++++++++++++++++++
  include/hw/arm/fsl-imx25.h  |   4 +-
  include/hw/misc/imx25_ccm.h |  59 ++++++++++
  5 files changed, 339 insertions(+), 3 deletions(-)

create mode 100644 hw/misc/imx25_ccm.c
create mode 100644 include/hw/misc/imx25_ccm.h