From patchwork Thu Jul 7 13:48:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 9218993 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DEAF26048B for ; Thu, 7 Jul 2016 13:59:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D151526746 for ; Thu, 7 Jul 2016 13:59:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C598126861; Thu, 7 Jul 2016 13:59:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 32EDD26746 for ; Thu, 7 Jul 2016 13:59:15 +0000 (UTC) Received: from localhost ([::1]:40103 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bL9pi-0007WH-Bt for patchwork-qemu-devel@patchwork.kernel.org; Thu, 07 Jul 2016 09:59:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36794) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bL9fw-0003mL-OQ for qemu-devel@nongnu.org; Thu, 07 Jul 2016 09:49:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bL9fu-0001tL-6f for qemu-devel@nongnu.org; Thu, 07 Jul 2016 09:49:07 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:58123) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bL9ft-0001s4-S1 for qemu-devel@nongnu.org; Thu, 07 Jul 2016 09:49:06 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1bL9fo-0004aa-Mj for qemu-devel@nongnu.org; Thu, 07 Jul 2016 14:49:00 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 7 Jul 2016 14:48:57 +0100 Message-Id: <1467899337-19192-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1467899337-19192-1-git-send-email-peter.maydell@linaro.org> References: <1467899337-19192-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PULL 6/6] i.MX: split the GPT timer implementation into per SOC definitions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Jean-Christophe Dubois In various Freescale SOCs, the GPT timers can be configured to select its input clock. Depending on the SOC the set of available input clocks may vary. The actual single GPT definition was no good enough and because of it booting the sabrelite board with a i.MX6DL device tree would fail because of an incorrect input clock definition for the i.MX6DL SOC. This patch fixes the i.MX6DL boot failure by adding the ability to define a different set of input clocks depending on the considered SOC. A different class has been defined for i.MX25, i.MX31 and i.MX6 each with its specific set of input clocks. The patch has been tested by booting KZM, i.MX25 PDK, i.MX6Q sabrelite and i.MX6DL sabrelite. Signed-off-by: Jean-Christophe Dubois Message-id: 1467325619-8374-1-git-send-email-jcd@tribudubois.net Reviewed-by: Peter Maydell [PMM: fixed spacing round '/' operator] Signed-off-by: Peter Maydell --- hw/arm/fsl-imx25.c | 2 +- hw/arm/fsl-imx31.c | 2 +- hw/arm/fsl-imx6.c | 2 +- hw/misc/imx6_ccm.c | 6 ++++ hw/timer/imx_gpt.c | 69 ++++++++++++++++++++++++++++++++++++++++++---- include/hw/misc/imx_ccm.h | 5 +++- include/hw/timer/imx_gpt.h | 9 +++++- 7 files changed, 84 insertions(+), 11 deletions(-) diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index 1a53e51..b4e358d 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -51,7 +51,7 @@ static void fsl_imx25_init(Object *obj) } for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) { - object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT); + object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX25_GPT); qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default()); } diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index b283b71..fe204ac 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -47,7 +47,7 @@ static void fsl_imx31_init(Object *obj) qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default()); } - object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT); + object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX31_GPT); qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default()); for (i = 0; i < FSL_IMX31_NUM_EPITS; i++) { diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index ed392a9..6a1bf26 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -67,7 +67,7 @@ static void fsl_imx6_init(Object *obj) object_property_add_child(obj, name, OBJECT(&s->uart[i]), NULL); } - object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT); + object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX6_GPT); qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default()); object_property_add_child(obj, "gpt", OBJECT(&s->gpt), NULL); diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c index ec58eef..17e15d4 100644 --- a/hw/misc/imx6_ccm.c +++ b/hw/misc/imx6_ccm.c @@ -371,6 +371,12 @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock) case CLK_32k: freq = CKIL_FREQ; break; + case CLK_HIGH: + freq = 24000000; + break; + case CLK_HIGH_DIV: + freq = 24000000 / 8; + break; default: qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n", TYPE_IMX6_CCM, __func__, clock); diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index 3c2f01a..82bc73c 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -14,7 +14,6 @@ #include "qemu/osdep.h" #include "hw/timer/imx_gpt.h" -#include "hw/misc/imx_ccm.h" #include "qemu/main-loop.h" #include "qemu/log.h" @@ -81,7 +80,18 @@ static const VMStateDescription vmstate_imx_timer_gpt = { } }; -static const IMXClk imx_gpt_clocks[] = { +static const IMXClk imx25_gpt_clocks[] = { + CLK_NONE, /* 000 No clock source */ + CLK_IPG, /* 001 ipg_clk, 532MHz*/ + CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ + CLK_NONE, /* 011 not defined */ + CLK_32k, /* 100 ipg_clk_32k */ + CLK_32k, /* 101 ipg_clk_32k */ + CLK_32k, /* 110 ipg_clk_32k */ + CLK_32k, /* 111 ipg_clk_32k */ +}; + +static const IMXClk imx31_gpt_clocks[] = { CLK_NONE, /* 000 No clock source */ CLK_IPG, /* 001 ipg_clk, 532MHz*/ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ @@ -92,12 +102,23 @@ static const IMXClk imx_gpt_clocks[] = { CLK_NONE, /* 111 not defined */ }; +static const IMXClk imx6_gpt_clocks[] = { + CLK_NONE, /* 000 No clock source */ + CLK_IPG, /* 001 ipg_clk, 532MHz*/ + CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */ + CLK_EXT, /* 011 External clock */ + CLK_32k, /* 100 ipg_clk_32k */ + CLK_HIGH_DIV, /* 101 reference clock / 8 */ + CLK_NONE, /* 110 not defined */ + CLK_HIGH, /* 111 reference clock */ +}; + static void imx_gpt_set_freq(IMXGPTState *s) { uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3); s->freq = imx_ccm_get_clock_frequency(s->ccm, - imx_gpt_clocks[clksrc]) / (1 + s->pr); + s->clocks[clksrc]) / (1 + s->pr); DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq); @@ -453,16 +474,52 @@ static void imx_gpt_class_init(ObjectClass *klass, void *data) dc->desc = "i.MX general timer"; } -static const TypeInfo imx_gpt_info = { - .name = TYPE_IMX_GPT, +static void imx25_gpt_init(Object *obj) +{ + IMXGPTState *s = IMX_GPT(obj); + + s->clocks = imx25_gpt_clocks; +} + +static void imx31_gpt_init(Object *obj) +{ + IMXGPTState *s = IMX_GPT(obj); + + s->clocks = imx31_gpt_clocks; +} + +static void imx6_gpt_init(Object *obj) +{ + IMXGPTState *s = IMX_GPT(obj); + + s->clocks = imx6_gpt_clocks; +} + +static const TypeInfo imx25_gpt_info = { + .name = TYPE_IMX25_GPT, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IMXGPTState), + .instance_init = imx25_gpt_init, .class_init = imx_gpt_class_init, }; +static const TypeInfo imx31_gpt_info = { + .name = TYPE_IMX31_GPT, + .parent = TYPE_IMX25_GPT, + .instance_init = imx31_gpt_init, +}; + +static const TypeInfo imx6_gpt_info = { + .name = TYPE_IMX6_GPT, + .parent = TYPE_IMX25_GPT, + .instance_init = imx6_gpt_init, +}; + static void imx_gpt_register_types(void) { - type_register_static(&imx_gpt_info); + type_register_static(&imx25_gpt_info); + type_register_static(&imx31_gpt_info); + type_register_static(&imx6_gpt_info); } type_init(imx_gpt_register_types) diff --git a/include/hw/misc/imx_ccm.h b/include/hw/misc/imx_ccm.h index 48a7afa..33cbc09 100644 --- a/include/hw/misc/imx_ccm.h +++ b/include/hw/misc/imx_ccm.h @@ -46,7 +46,10 @@ typedef enum { CLK_NONE, CLK_IPG, CLK_IPG_HIGH, - CLK_32k + CLK_32k, + CLK_EXT, + CLK_HIGH_DIV, + CLK_HIGH, } IMXClk; typedef struct IMXCCMClass { diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h index 461adbe..eac59b2 100644 --- a/include/hw/timer/imx_gpt.h +++ b/include/hw/timer/imx_gpt.h @@ -74,7 +74,12 @@ #define GPT_IR_OF3IE (1 << 2) #define GPT_IR_ROVIE (1 << 5) -#define TYPE_IMX_GPT "imx.gpt" +#define TYPE_IMX25_GPT "imx25.gpt" +#define TYPE_IMX31_GPT "imx31.gpt" +#define TYPE_IMX6_GPT "imx6.gpt" + +#define TYPE_IMX_GPT TYPE_IMX25_GPT + #define IMX_GPT(obj) OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT) typedef struct IMXGPTState{ @@ -103,6 +108,8 @@ typedef struct IMXGPTState{ uint32_t freq; qemu_irq irq; + + const IMXClk *clocks; } IMXGPTState; #endif /* IMX_GPT_H */