
On 2/14/21 4:55 AM, Jesse wrote:
From: Jesse Taube mr.bossman075@gmail.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.
Still too many columns ^^^
Signed-off-by: Giulio Benetti giulio.benetti@benettiengineering.com Signed-off-by: Jesse Taube mr.bossman075@gmail.com
drivers/timer/Kconfig | 7 ++ drivers/timer/Makefile | 1 + drivers/timer/imx-gpt-timer.c | 153 ++++++++++++++++++++++++++++++++++ 3 files changed, 161 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..e7e46c8037 --- /dev/null +++ b/drivers/timer/imx-gpt-timer.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2020
- 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_SWR 0x00008000 +#define GPT_CR_EN_24M 0x00000400
Too any tabs ^^^^
+#define GPT_CR_EN 0x00000001 +#define GPT_PR_PRESCALER 0x00000FFF
+#define GPT_CLKSRC_IPG_CLK (1 << 6) +#define GPT_CLKSRC_IPG_CLK_24M (5 << 6)
Ditto ^^^
+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(®s->cnt);
+}
+static inline void imx_gpt_setup_24M(struct imx_gpt_timer_regs *regs) +{
- writel(GPT_CLKSRC_IPG_CLK_24M | GPT_CR_EN_24M, ®s->cr);
+}
+static inline void imx_gpt_setup_per(struct imx_gpt_timer_regs *regs) +{
- writel(GPT_CLKSRC_IPG_CLK, ®s->cr);
+}
+static inline void imx_gpt_sof_reset(struct imx_gpt_timer_regs *regs) +{
- /* Reset the timer */
- setbits_le32(®s->cr, GPT_CR_SWR);
- /* Wait for timer to finish reset */
- while (readl(®s->cr) & GPT_CR_SWR)
;
+}
+static int imx_gpt_setup(u32 rate, struct imx_gpt_timer_regs *regs) +{
- u32 prescaler;
- imx_gpt_sof_reset(regs);
This function ^^^ can be avoided at the moment since it's called only from here and it only set a bit and loop-check it.
- /* Set timer frequency to 1MHz */
- prescaler = (rate / CONFIG_SYS_HZ_CLOCK) - 1;
- if (prescaler > GPT_PR_PRESCALER)
return -EINVAL;
- /* We set timer prescaler to obtain a 1MHz timer counter frequency */
- writel(prescaler, ®s->pr);
Prescaler setting is specific to PER case and should go inside the two functions imx_gpt_setup_per/24M().
- if (rate != 24000000UL)
imx_gpt_setup_per(regs);
... this ^^^
- else
imx_gpt_setup_24M(regs);
... and this ^^^
Also, I've taken a look again at linux driver[1] and like here in u-boot they set as prescaler to 8 for 24M to obtina 3Mhz. And that is for compatibility with u-boot I think, so here I would try to set prescaler for having timer frequency set to 3Mhz instead of 1Mhz. And this could be true for the PER clock source, but of course you have to set 24M prescaler(to 8) or PER prescaler(the one you use) the way already do.
[1]: https://github.com/torvalds/linux/blob/master/drivers/clocksource/timer-imx-...
For the rest it looks good. On next iteration, patch should be ready to be tested on my imxrt1050-evk.
Thank you Best regards