diff mbox

[v4,3/3] i.MX: Add an i.MX25 specific CCM class/instance.

Message ID d53f34e3cf05dde424b6eab7d51cef6f244ef80a.1448521065.git.jcd@tribudubois.net
State New
Headers show

Commit Message

Jean-Christophe Dubois Nov. 26, 2015, 7:16 a.m. UTC
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---

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

Comments

Peter Crosthwaite Nov. 27, 2015, 2:39 a.m. UTC | #1
On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
<jcd@tribudubois.net> wrote:
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>

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


> ---
>
> 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
>
Jean-Christophe Dubois Nov. 27, 2015, 7:54 p.m. UTC | #2
Le 27/11/2015 03:39, Peter Crosthwaite a écrit :
> On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
> <jcd@tribudubois.net> wrote:
>> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
> 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

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
>
>> ---
>>
>> 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
>>
Peter Crosthwaite Nov. 27, 2015, 8:26 p.m. UTC | #3
On Fri, Nov 27, 2015 at 11:54 AM, Jean-Christophe DUBOIS
<jcd@tribudubois.net> wrote:
> Le 27/11/2015 03:39, Peter Crosthwaite a écrit :
>
> On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
> <jcd@tribudubois.net> wrote:
>
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
>
> 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
>
> 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.

> 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.

> 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

> 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
>
>
Guenter Roeck Nov. 27, 2015, 9:43 p.m. UTC | #4
On 11/27/2015 12:26 PM, Peter Crosthwaite wrote:
> On Fri, Nov 27, 2015 at 11:54 AM, Jean-Christophe DUBOIS
> <jcd@tribudubois.net> wrote:
>> Le 27/11/2015 03:39, Peter Crosthwaite a écrit :
>>
>> On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
>> <jcd@tribudubois.net> wrote:
>>
>> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
>>
>> 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
>>
>> 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

>> 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.
>
>> 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
>
>> 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
>>
>>
>
Jean-Christophe Dubois Nov. 27, 2015, 10:05 p.m. UTC | #5
Le 27/11/2015 21:26, Peter Crosthwaite a écrit :
> On Fri, Nov 27, 2015 at 11:54 AM, Jean-Christophe DUBOIS
> <jcd@tribudubois.net> wrote:
>> Le 27/11/2015 03:39, Peter Crosthwaite a écrit :
>>
>> On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
>> <jcd@tribudubois.net> wrote:
>>
>> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
>>
>> 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
>>
>> 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


>
>> 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.
>
>> 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
>
>> 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
>>
>>
Peter Crosthwaite Nov. 27, 2015, 10:12 p.m. UTC | #6
On Fri, Nov 27, 2015 at 2:05 PM, Jean-Christophe DUBOIS
<jcd@tribudubois.net> wrote:
> Le 27/11/2015 21:26, Peter Crosthwaite a écrit :
>>
>> On Fri, Nov 27, 2015 at 11:54 AM, Jean-Christophe DUBOIS
>> <jcd@tribudubois.net> wrote:
>>>
>>> Le 27/11/2015 03:39, Peter Crosthwaite a écrit :
>>>
>>> On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
>>> <jcd@tribudubois.net> wrote:
>>>
>>> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
>>>
>>> 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
>>>
>>> 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.
>

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

> JC
>
>
>
>>
>>> 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.
>>
>>> 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
>>
>>> 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
>>>
>>>
>
Jean-Christophe Dubois Nov. 29, 2015, 11:46 p.m. UTC | #7
Le 27/11/2015 21:26, Peter Crosthwaite a écrit :
> On Fri, Nov 27, 2015 at 11:54 AM, Jean-Christophe DUBOIS
> <jcd@tribudubois.net> wrote:
>> Le 27/11/2015 03:39, Peter Crosthwaite a écrit :
>>
>> On Wed, Nov 25, 2015 at 11:16 PM, Jean-Christophe Dubois
>> <jcd@tribudubois.net> wrote:
>>
>> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
>>
>> 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
>>
>> 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.
>
>> 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

>
>> 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
>
>> 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
>>
>>
diff mbox

Patch

diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
index 9f302ed..36818ee 100644
--- a/hw/arm/fsl-imx25.c
+++ b/hw/arm/fsl-imx25.c
@@ -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++) {
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c77f3e3..8a235df 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -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
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
new file mode 100644
index 0000000..d0fe017
--- /dev/null
+++ b/hw/misc/imx25_ccm.c
@@ -0,0 +1,276 @@ 
+/*
+ * IMX25 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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.
+ */
+
+#include "hw/misc/imx25_ccm.h"
+
+#ifndef DEBUG_IMX25_CCM
+#define DEBUG_IMX25_CCM 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+    do { \
+        if (DEBUG_IMX25_CCM) { \
+            fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX25_CCM, \
+                                             __func__, ##args); \
+        } \
+    } while (0)
+
+#define CKIH_FREQ 24000000 /* 24MHz crystal input */
+
+static const VMStateDescription vmstate_imx25_ccm = {
+    .name = TYPE_IMX25_CCM,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(mpctl, IMX25CCMState),
+        VMSTATE_UINT32(upctl, IMX25CCMState),
+        VMSTATE_UINT32(cctl, IMX25CCMState),
+        VMSTATE_UINT32_ARRAY(cgcr, IMX25CCMState, 3),
+        VMSTATE_UINT32_ARRAY(pcdr, IMX25CCMState, 4),
+        VMSTATE_UINT32(rcsr, IMX25CCMState),
+        VMSTATE_UINT32(crdr, IMX25CCMState),
+        VMSTATE_UINT32_ARRAY(dcvr, IMX25CCMState, 4),
+        VMSTATE_UINT32_ARRAY(ltr, IMX25CCMState, 4),
+        VMSTATE_UINT32_ARRAY(ltbr, IMX25CCMState, 2),
+        VMSTATE_UINT32_ARRAY(pmcr, IMX25CCMState, 3),
+        VMSTATE_UINT32(mcr, IMX25CCMState),
+        VMSTATE_UINT32_ARRAY(lpimr, IMX25CCMState, 2),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
+{
+    IMX25CCMState *s = IMX25_CCM(dev);
+
+    DPRINTF("()\n");
+
+    if (EXTRACT(s->cctl, MPLL_BYPASS)) {
+        return CKIH_FREQ;
+    } else {
+        return imx_ccm_calc_pll(s->mpctl, CKIH_FREQ);
+    }
+}
+
+static uint32_t imx25_ccm_get_upll_clk(IMXCCMState *dev)
+{
+    IMX25CCMState *s = IMX25_CCM(dev);
+
+    DPRINTF("()\n");
+
+    return imx_ccm_calc_pll(s->upctl, CKIH_FREQ);
+}
+
+static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
+{
+    IMX25CCMState *s = IMX25_CCM(dev);
+
+    DPRINTF("()\n");
+
+    if (EXTRACT(s->cctl, ARM_SRC)) {
+        return (imx25_ccm_get_mpll_clk(dev) * 3 / 4) /
+               (1 + EXTRACT(s->cctl, ARM_CLK_DIV));
+    } else {
+        return imx25_ccm_get_mpll_clk(dev) /
+               (1 + EXTRACT(s->cctl, ARM_CLK_DIV));
+    }
+}
+
+static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
+{
+    IMX25CCMState *s = IMX25_CCM(dev);
+
+    DPRINTF("()\n");
+
+    return imx25_ccm_get_mcu_clk(dev) / (1 + EXTRACT(s->cctl, AHB_CLK_DIV));
+}
+
+static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
+{
+    DPRINTF("()\n");
+
+    return imx25_ccm_get_ahb_clk(dev) / 2;
+}
+
+static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+    uint32_t freq = 0;
+    DPRINTF("Clock = %d)\n", clock);
+
+    switch (clock) {
+    case NOCLK:
+        break;
+    case CLK_MPLL:
+        freq = imx25_ccm_get_mpll_clk(dev);
+        break;
+    case CLK_UPLL:
+        freq = imx25_ccm_get_upll_clk(dev);
+        break;
+    case CLK_MCU:
+        freq = imx25_ccm_get_mcu_clk(dev);
+        break;
+    case CLK_AHB:
+        freq = imx25_ccm_get_ahb_clk(dev);
+        break;
+    case CLK_IPG:
+        freq = imx25_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_IMX25_CCM, __func__, clock);
+        break;
+    }
+
+    DPRINTF("Clock = %d) = %d\n", clock, freq);
+
+    return freq;
+}
+
+static void imx25_ccm_reset(DeviceState *dev)
+{
+    IMX25CCMState *s = IMX25_CCM(dev);
+
+    DPRINTF("\n");
+
+    s->mpctl = 0x800b2c01;
+    s->upctl = 0x84002800;
+    s->cctl = 0x40030000;
+    s->cgcr[0] = 0x028A0100;
+    s->cgcr[1] = 0x04008100;
+    s->cgcr[2] = 0x00000438;
+    s->pcdr[0] = 0x01010101;
+    s->pcdr[1] = 0x01010101;
+    s->pcdr[2] = 0x01010101;
+    s->pcdr[3] = 0x01010101;
+    s->rcsr = 0;
+    s->crdr = 0;
+    s->dcvr[0] = 0;
+    s->dcvr[1] = 0;
+    s->dcvr[2] = 0;
+    s->dcvr[3] = 0;
+    s->ltr[0] = 0;
+    s->ltr[1] = 0;
+    s->ltr[2] = 0;
+    s->ltr[3] = 0;
+    s->ltbr[0] = 0;
+    s->ltbr[1] = 0;
+    s->pmcr[0] = 0x00A00000;
+    s->pmcr[1] = 0x0000A030;
+    s->pmcr[2] = 0x0000A030;
+    s->mcr = 0x43000000;
+    s->lpimr[0] = 0;
+    s->lpimr[1] = 0;
+
+    /* default ROM boot will change the reset values */
+    s->cctl |= INSERT(1, ARM_SRC);
+    s->cctl |= INSERT(1, AHB_CLK_DIV);
+}
+
+static uint64_t imx25_ccm_read(void *opaque, hwaddr offset, unsigned size)
+{
+    uint32 value = 0;
+    IMX25CCMState *s = (IMX25CCMState *)opaque;
+    uint32_t *reg = &s->mpctl;
+
+    DPRINTF("(offset=0x%" HWADDR_PRIx ")\n", offset);
+
+    if (offset < 0x70) {
+        value = reg[offset >> 2];
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset);
+    }
+
+    DPRINTF("reg[0x%" HWADDR_PRIx "] => 0x%" PRIx32 "\n", offset, value);
+
+    return value;
+}
+
+static void imx25_ccm_write(void *opaque, hwaddr offset, uint64_t value,
+                            unsigned size)
+{
+    IMX25CCMState *s = (IMX25CCMState *)opaque;
+    uint32_t *reg = &s->mpctl;
+
+    DPRINTF("reg[0x%" HWADDR_PRIx "] <= 0x%" PRIx32 "\n", offset,
+            (uint32_t)value);
+
+    if (offset < 0x70) {
+        /*
+         * We will do a better implementation later. In particular some bits
+         * cannot be written to.
+         */
+        reg[offset >> 2] = value;
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset);
+    }
+}
+
+static const struct MemoryRegionOps imx25_ccm_ops = {
+    .read = imx25_ccm_read,
+    .write = imx25_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 imx25_ccm_init(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    IMX25CCMState *s = IMX25_CCM(obj);
+
+    memory_region_init_io(&s->iomem, OBJECT(dev), &imx25_ccm_ops, s,
+                          TYPE_IMX25_CCM, 0x1000);
+    sysbus_init_mmio(sd, &s->iomem);
+}
+
+static void imx25_ccm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
+
+    dc->reset = imx25_ccm_reset;
+    dc->vmsd = &vmstate_imx25_ccm;
+    dc->desc = "i.MX25 Clock Control Module";
+
+    ccm->get_clock_frequency = imx25_ccm_get_clock_frequency;
+}
+
+static const TypeInfo imx25_ccm_info = {
+    .name          = TYPE_IMX25_CCM,
+    .parent        = TYPE_IMX_CCM,
+    .instance_size = sizeof(IMX25CCMState),
+    .instance_init = imx25_ccm_init,
+    .class_init    = imx25_ccm_class_init,
+};
+
+static void imx25_ccm_register_types(void)
+{
+    type_register_static(&imx25_ccm_info);
+}
+
+type_init(imx25_ccm_register_types)
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
index 5c62fde..d0e8e9d 100644
--- a/include/hw/arm/fsl-imx25.h
+++ b/include/hw/arm/fsl-imx25.h
@@ -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];
diff --git a/include/hw/misc/imx25_ccm.h b/include/hw/misc/imx25_ccm.h
new file mode 100644
index 0000000..80d7c38
--- /dev/null
+++ b/include/hw/misc/imx25_ccm.h
@@ -0,0 +1,59 @@ 
+/*
+ * IMX25 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 IMX25_CCM_H
+#define IMX25_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+
+/* CCTL */
+#define CCTL_ARM_CLK_DIV_SHIFT (30)
+#define CCTL_ARM_CLK_DIV_MASK  (0x3)
+#define CCTL_AHB_CLK_DIV_SHIFT (28)
+#define CCTL_AHB_CLK_DIV_MASK  (0x3)
+#define CCTL_MPLL_BYPASS_SHIFT (22)
+#define CCTL_MPLL_BYPASS_MASK  (0x1)
+#define CCTL_USB_DIV_SHIFT (16)
+#define CCTL_USB_DIV_MASK  (0x3F)
+#define CCTL_ARM_SRC_SHIFT (13)
+#define CCTL_ARM_SRC_MASK  (0x1)
+
+#define EXTRACT(value, name) (((value) >> CCTL_##name##_SHIFT) \
+                              & CCTL_##name##_MASK)
+#define INSERT(value, name) (((value) & CCTL_##name##_MASK) << \
+                             CCTL_##name##_SHIFT)
+
+#define TYPE_IMX25_CCM "imx25.ccm"
+#define IMX25_CCM(obj) OBJECT_CHECK(IMX25CCMState, (obj), TYPE_IMX25_CCM)
+
+typedef struct IMX25CCMState {
+    /* <private> */
+    IMXCCMState parent_obj;
+
+    /* <public> */
+    MemoryRegion iomem;
+
+    uint32_t mpctl;
+    uint32_t upctl;
+    uint32_t cctl;
+    uint32_t cgcr[3];
+    uint32_t pcdr[4];
+    uint32_t rcsr;
+    uint32_t crdr;
+    uint32_t dcvr[4];
+    uint32_t ltr[4];
+    uint32_t ltbr[2];
+    uint32_t pmcr[3];
+    uint32_t mcr;
+    uint32_t lpimr[2];
+
+} IMX25CCMState;
+
+#endif /* IMX25_CCM_H */