All of lore.kernel.org
 help / color / mirror / Atom feed
From: Giulio Benetti <giulio.benetti@benettiengineering.com>
To: u-boot@lists.denx.de
Subject: [PATCH 02/16] timer: imx-gpt: Add timer support for i.MX SoCs family
Date: Wed,  7 Apr 2021 21:02:50 +0200	[thread overview]
Message-ID: <20210407190304.1478921-3-giulio.benetti@benettiengineering.com> (raw)
In-Reply-To: <20210407190304.1478921-1-giulio.benetti@benettiengineering.com>

This timer driver is using GPT Timer (General Purpose Timer) available
on almost all i.MX SoCs family. Since this driver is only meant to
provide u-boot's timer and counter, and most of the i.MX* SoCs use a
24Mhz crystal, let's only deal with that specific source.

Signed-off-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
[Giulio: added the driver's stub and handled peripheral clock prescaler
setting]
Signed-off-by: Jesse Taube <mr.bossman075@gmail.com>
[Jesse: added init, setting prescaler for 24Mhz support and enabling
timer]
---
 drivers/timer/Kconfig         |   7 ++
 drivers/timer/Makefile        |   1 +
 drivers/timer/imx-gpt-timer.c | 162 ++++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/timer/imx-gpt-timer.c

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 80743a2551..ee81dfa776 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -227,4 +227,11 @@ config MCHP_PIT64B_TIMER
 	  Select this to enable support for Microchip 64-bit periodic
 	  interval timer.
 
+config IMX_GPT_TIMER
+	bool "NXP i.MX GPT timer support"
+	depends on TIMER
+	help
+	  Select this to enable support for the timer found on
+	  NXP i.MX devices.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index eb5c48cc6c..e214ba7268 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_STM32_TIMER)	+= stm32_timer.o
 obj-$(CONFIG_X86_TSC_TIMER)	+= tsc_timer.o
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_MCHP_PIT64B_TIMER)	+= mchp-pit64b-timer.o
+obj-$(CONFIG_IMX_GPT_TIMER)	+= imx-gpt-timer.o
diff --git a/drivers/timer/imx-gpt-timer.c b/drivers/timer/imx-gpt-timer.c
new file mode 100644
index 0000000000..a498f2e21c
--- /dev/null
+++ b/drivers/timer/imx-gpt-timer.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021
+ * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <timer.h>
+#include <dm/device_compat.h>
+
+#include <asm/io.h>
+
+#define GPT_CR_EN			BIT(0)
+#define GPT_CR_FRR			BIT(9)
+#define GPT_CR_EN_24M			BIT(10)
+#define GPT_CR_SWR			BIT(15)
+
+#define GPT_PR_PRESCALER24M_MASK	0x0000F000
+#define GPT_PR_PRESCALER24M_SHIFT	12
+#define GPT_PR_PRESCALER24M_MAX	(GPT_PR_PRESCALER24M_MASK >> GPT_PR_PRESCALER24M_SHIFT)
+#define GPT_PR_PRESCALER_MASK		0x00000FFF
+#define GPT_PR_PRESCALER_SHIFT		0
+#define GPT_PR_PRESCALER_MAX		(GPT_PR_PRESCALER_MASK >> GPT_PR_PRESCALER_SHIFT)
+
+#define GPT_CLKSRC_IPG_CLK		(1 << 6)
+#define GPT_CLKSRC_IPG_CLK_24M		(5 << 6)
+
+/* If CONFIG_SYS_HZ_CLOCK not specified et's default to 3Mhz */
+#ifndef CONFIG_SYS_HZ_CLOCK
+#define CONFIG_SYS_HZ_CLOCK		3000000
+#endif
+
+struct imx_gpt_timer_regs {
+	u32 cr;
+	u32 pr;
+	u32 sr;
+	u32 ir;
+	u32 ocr1;
+	u32 ocr2;
+	u32 ocr3;
+	u32 icr1;
+	u32 icr2;
+	u32 cnt;
+};
+
+struct imx_gpt_timer_priv {
+	struct imx_gpt_timer_regs *base;
+};
+
+static u64 imx_gpt_timer_get_count(struct udevice *dev)
+{
+	struct imx_gpt_timer_priv *priv = dev_get_priv(dev);
+	struct imx_gpt_timer_regs *regs = priv->base;
+
+	return readl(&regs->cnt);
+}
+
+static int imx_gpt_setup(struct imx_gpt_timer_regs *regs, u32 rate)
+{
+	u32 prescaler = (rate / CONFIG_SYS_HZ_CLOCK) - 1;
+
+	/* Reset the timer */
+	setbits_le32(&regs->cr, GPT_CR_SWR);
+
+	/* Wait for timer to finish reset */
+	while (readl(&regs->cr) & GPT_CR_SWR)
+		;
+
+	if (rate == 24000000UL) {
+		/* Set timer frequency if using 24M clock source */
+		if (prescaler > GPT_PR_PRESCALER24M_MAX)
+			return -EINVAL;
+
+		/* Set 24M prescaler */
+		writel((prescaler << GPT_PR_PRESCALER24M_SHIFT), &regs->pr);
+		/* Set Oscillator as clock source, enable 24M input and set gpt
+		 * in free-running mode
+		 */
+		writel(GPT_CLKSRC_IPG_CLK_24M | GPT_CR_EN_24M | GPT_CR_FRR, &regs->cr);
+	} else {
+		if (prescaler > GPT_PR_PRESCALER_MAX)
+			return -EINVAL;
+
+		/* Set prescaler */
+		writel((prescaler << GPT_PR_PRESCALER_SHIFT), &regs->pr);
+		/* Set Peripheral as clock source and set gpt in free-running
+		 * mode
+		 */
+		writel(GPT_CLKSRC_IPG_CLK | GPT_CR_FRR, &regs->cr);
+	}
+
+	/* Start timer */
+	setbits_le32(&regs->cr, GPT_CR_EN);
+
+	return 0;
+}
+
+static int imx_gpt_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct imx_gpt_timer_priv *priv = dev_get_priv(dev);
+	struct imx_gpt_timer_regs *regs;
+	struct clk clk;
+	fdt_addr_t addr;
+	u32 clk_rate;
+	int ret;
+
+	addr = dev_read_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->base = (struct imx_gpt_timer_regs *)addr;
+	regs = priv->base;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clock\n");
+		return ret;
+	}
+
+	/* Get timer clock rate */
+	clk_rate = clk_get_rate(&clk);
+	if (clk_rate <= 0) {
+		dev_err(dev, "Could not get clock rate...\n");
+		return -EINVAL;
+	}
+
+	ret = imx_gpt_setup(regs, clk_rate);
+	if (ret) {
+		dev_err(dev, "Could not setup timer\n");
+		return ret;
+	}
+
+	uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK;
+
+	return 0;
+}
+
+static const struct timer_ops imx_gpt_timer_ops = {
+	.get_count = imx_gpt_timer_get_count,
+};
+
+static const struct udevice_id imx_gpt_timer_ids[] = {
+	{ .compatible = "fsl,imxrt-gpt" },
+	{}
+};
+
+U_BOOT_DRIVER(imx_gpt_timer) = {
+	.name = "imx_gpt_timer",
+	.id = UCLASS_TIMER,
+	.of_match = imx_gpt_timer_ids,
+	.priv_auto = sizeof(struct imx_gpt_timer_priv),
+	.probe = imx_gpt_timer_probe,
+	.ops = &imx_gpt_timer_ops,
+};
-- 
2.25.1

  parent reply	other threads:[~2021-04-07 19:02 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-07 19:02 [PATCH 00/16] Fix i.MXRT1020/50 Giulio Benetti
2021-04-07 19:02 ` [PATCH 01/16] arm: imxrt: soc: make mpu regions generic Giulio Benetti
2021-04-07 19:02 ` Giulio Benetti [this message]
2021-04-07 19:20   ` [PATCH 02/16] timer: imx-gpt: Add timer support for i.MX SoCs family Giulio Benetti
2021-04-08  1:06     ` Jesse T
2021-04-08  3:05       ` Giulio Benetti
2021-04-08  1:55   ` Sean Anderson
2021-04-07 19:02 ` [PATCH 03/16] ARM: dts: imxrt1020: add alias to osc Giulio Benetti
2021-05-03 14:00   ` Fabio Estevam
2021-05-03 17:51     ` Giulio Benetti
2021-05-03 18:21       ` Fabio Estevam
2021-05-03 19:03         ` Giulio Benetti
2021-04-07 19:02 ` [PATCH 04/16] ARM: dts: imxrt1020: add gpt1 node Giulio Benetti
2021-04-07 19:02 ` [PATCH 05/16] ARM: dts: imxrt1020-evk: enable gpt1 timer Giulio Benetti
2021-04-07 19:02 ` [PATCH 06/16] ARM: dts: imxrt1020-evk: set gpt1 as tick-timer for u-boot Giulio Benetti
2021-04-07 19:02 ` [PATCH 07/16] ARM: dts: imxrt1020-evk-u-boot: make gpt1 present for SPL Giulio Benetti
2021-04-07 19:02 ` [PATCH 08/16] ARM: dts: imxrt1020-evk: add device_type = "memory" to memory node Giulio Benetti
2021-04-07 19:02 ` [PATCH 09/16] configs: imxrt1020-evk: enable imx gpt timer as tick-timer Giulio Benetti
2021-04-07 19:02 ` [PATCH 10/16] ARM: dts: imxrt1050: add alias to osc Giulio Benetti
2021-04-07 19:02 ` [PATCH 11/16] ARM: dts: imxrt1050: add gpt1 node Giulio Benetti
2021-04-07 19:03 ` [PATCH 12/16] ARM: dts: imxrt1050-evk: enable gpt1 timer Giulio Benetti
2021-05-01 23:42 ` [PATCH v2 00/16] Fix i.MXRT1020/50 Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 01/16] arm: imxrt: soc: make mpu regions generic Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 02/16] timer: imx-gpt: Add timer support for i.MX SoCs family Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 03/16] ARM: dts: imxrt1020: add alias to osc Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 04/16] ARM: dts: imxrt1020: add gpt1 node Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 05/16] ARM: dts: imxrt1020-evk: enable gpt1 timer Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 06/16] ARM: dts: imxrt1020-evk: set gpt1 as tick-timer for u-boot Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 07/16] ARM: dts: imxrt1020-evk-u-boot: make gpt1 present for SPL Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 08/16] ARM: dts: imxrt1020-evk: add device_type = "memory" to memory node Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 09/16] configs: imxrt1020-evk: enable imx gpt timer as tick-timer Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 10/16] ARM: dts: imxrt1050: add alias to osc Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 11/16] ARM: dts: imxrt1050: add gpt1 node Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 12/16] ARM: dts: imxrt1050-evk: enable gpt1 timer Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 13/16] ARM: dts: imxrt1050-evk: set gpt1 as tick-timer for u-boot Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 14/16] ARM: dts: imxrt1050-evk-u-boot: make gpt1 present for SPL Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 15/16] ARM: dts: imxrt1050-evk: add device_type = "memory" to memory node Giulio Benetti
2021-05-01 23:42   ` [PATCH v2 16/16] configs: imxrt1050-evk: enable imx gpt timer as tick-timer Giulio Benetti

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210407190304.1478921-3-giulio.benetti@benettiengineering.com \
    --to=giulio.benetti@benettiengineering.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.