All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] timer: mchp-pit64b: add support for pit64b
@ 2020-09-07 15:36 Claudiu Beznea
  2020-09-22  8:32 ` Eugen.Hristev at microchip.com
  2020-10-07 17:49 ` Sean Anderson
  0 siblings, 2 replies; 9+ messages in thread
From: Claudiu Beznea @ 2020-09-07 15:36 UTC (permalink / raw)
  To: u-boot

Add support for Microchip PIT64B timer. The timer is 64 bit length and
is used as a free running counter (in continuous mode with highest values
for period registers). The clock feeding the timer would be no more
than 12.5MHz.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 drivers/timer/Kconfig             |   7 +++
 drivers/timer/Makefile            |   1 +
 drivers/timer/mchp-pit64b-timer.c | 109 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+)
 create mode 100644 drivers/timer/mchp-pit64b-timer.c

diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 5f4bc6edb67b..13a98be4ab92 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -181,4 +181,11 @@ config MTK_TIMER
 	  Select this to enable support for the timer found on
 	  MediaTek devices.
 
+config MCHP_PIT64B_TIMER
+	bool "Microchip 64-bit periodic interval timer support"
+	depends on TIMER
+	help
+	  Select this to enable support for Microchip 64-bit periodic
+	  interval timer.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index fa35bea6c5b2..4744a8d9c93c 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_STI_TIMER)		+= sti-timer.o
 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
diff --git a/drivers/timer/mchp-pit64b-timer.c b/drivers/timer/mchp-pit64b-timer.c
new file mode 100644
index 000000000000..ead8c9b84ad5
--- /dev/null
+++ b/drivers/timer/mchp-pit64b-timer.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 64-bit Periodic Interval Timer driver
+ *
+ * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <timer.h>
+#include <asm/io.h>
+
+#define MCHP_PIT64B_CR			0x00	/* Control Register */
+#define		MCHP_PIT64B_CR_START	BIT(0)
+#define		MCHP_PIT64B_CR_SWRST	BIT(8)
+#define MCHP_PIT64B_MR			0x04	/* Mode Register */
+#define		MCHP_PIT64B_MR_CONT	BIT(0)
+#define MCHP_PIT64B_LSB_PR		0x08	/* LSB Period Register */
+#define MCHP_PIT64B_MSB_PR		0x0C	/* MSB Period Register */
+#define MCHP_PIT64B_TLSBR		0x20	/* Timer LSB Register */
+#define MCHP_PIT64B_TMSBR		0x24	/* Timer MSB Register */
+
+struct mchp_pit64b_priv {
+	void __iomem *base;
+};
+
+static int mchp_pit64b_get_count(struct udevice *dev, u64 *count)
+{
+	struct mchp_pit64b_priv *priv = dev_get_priv(dev);
+
+	u32 lsb = readl(priv->base + MCHP_PIT64B_TLSBR);
+	u32 msb = readl(priv->base + MCHP_PIT64B_TMSBR);
+
+	*count = ((u64)msb << 32) | lsb;
+
+	return 0;
+}
+
+static int mchp_pit64b_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mchp_pit64b_priv *priv = dev_get_priv(dev);
+	struct clk clk;
+	ulong rate;
+	int ret;
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	rate = clk_get_rate(&clk);
+	if (!rate) {
+		clk_disable(&clk);
+		return -ENOTSUPP;
+	}
+
+	/* Reset the timer in case it was used by previous bootloaders. */
+	writel(MCHP_PIT64B_CR_SWRST, priv->base + MCHP_PIT64B_CR);
+
+	/*
+	 * Use highest prescaller (for a peripheral clock running at 200MHz
+	 * this will lead to the timer running at 12.5MHz) and continuous mode.
+	 */
+	writel((15 << 8) | MCHP_PIT64B_MR_CONT, priv->base + MCHP_PIT64B_MR);
+	uc_priv->clock_rate = rate / 16;
+
+	/*
+	 * Simulate free running counter by setting max values to period
+	 * registers.
+	 */
+	writel(~0UL, priv->base + MCHP_PIT64B_MSB_PR);
+	writel(~0UL, priv->base + MCHP_PIT64B_LSB_PR);
+
+	/* Start the timer. */
+	writel(MCHP_PIT64B_CR_START, priv->base + MCHP_PIT64B_CR);
+
+	return 0;
+}
+
+static const struct timer_ops mchp_pit64b_ops = {
+	.get_count = mchp_pit64b_get_count,
+};
+
+static const struct udevice_id mchp_pit64b_ids[] = {
+	{ .compatible = "microchip,sam9x60-pit64b", },
+	{ .compatible = "microchip,sama7g5-pit64b", },
+	{ }
+};
+
+U_BOOT_DRIVER(mchp_pit64b) = {
+	.name	= "mchp-pit64b",
+	.id	= UCLASS_TIMER,
+	.of_match = mchp_pit64b_ids,
+	.priv_auto_alloc_size = sizeof(struct mchp_pit64b_priv),
+	.probe	= mchp_pit64b_probe,
+	.ops	= &mchp_pit64b_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH] timer: mchp-pit64b: add support for pit64b
  2020-09-07 15:36 [PATCH] timer: mchp-pit64b: add support for pit64b Claudiu Beznea
@ 2020-09-22  8:32 ` Eugen.Hristev at microchip.com
  2020-09-22 10:49   ` Claudiu.Beznea at microchip.com
  2020-10-07 17:49 ` Sean Anderson
  1 sibling, 1 reply; 9+ messages in thread
From: Eugen.Hristev at microchip.com @ 2020-09-22  8:32 UTC (permalink / raw)
  To: u-boot

On 07.09.2020 18:36, Claudiu Beznea wrote:
> Add support for Microchip PIT64B timer. The timer is 64 bit length and
> is used as a free running counter (in continuous mode with highest values
> for period registers). The clock feeding the timer would be no more
> than 12.5MHz.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> ---

Hi Claudiu,

To make CI/CD scripts happy, this new driver needs a MAINTAINERS entry

Thanks !
Eugen

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] timer: mchp-pit64b: add support for pit64b
  2020-09-22  8:32 ` Eugen.Hristev at microchip.com
@ 2020-09-22 10:49   ` Claudiu.Beznea at microchip.com
  2020-09-22 11:44     ` Eugen.Hristev at microchip.com
  2020-09-28 11:09     ` [PATCH] timer: mchp-pit64b: add support for pit64b Eugen.Hristev at microchip.com
  0 siblings, 2 replies; 9+ messages in thread
From: Claudiu.Beznea at microchip.com @ 2020-09-22 10:49 UTC (permalink / raw)
  To: u-boot

Hi Eugen,

On 22.09.2020 11:32, Eugen Hristev - M18282 wrote:
> On 07.09.2020 18:36, Claudiu Beznea wrote:
>> Add support for Microchip PIT64B timer. The timer is 64 bit length and
>> is used as a free running counter (in continuous mode with highest values
>> for period registers). The clock feeding the timer would be no more
>> than 12.5MHz.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>> ---
> 
> Hi Claudiu,
> 
> To make CI/CD scripts happy, this new driver needs a MAINTAINERS entry

Would you like me to create a new entry or add the file under the
ARM MICROCHIP/ATMEL AT91 hood?

Thank you,
Claudiu Beznea

> 
> Thanks !
> Eugen
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] timer: mchp-pit64b: add support for pit64b
  2020-09-22 10:49   ` Claudiu.Beznea at microchip.com
@ 2020-09-22 11:44     ` Eugen.Hristev at microchip.com
  2020-09-23 10:17       ` [PATCH] MAINTAINERS: add Microchip PIT64B timer Claudiu Beznea
  2020-09-28 11:09     ` [PATCH] timer: mchp-pit64b: add support for pit64b Eugen.Hristev at microchip.com
  1 sibling, 1 reply; 9+ messages in thread
From: Eugen.Hristev at microchip.com @ 2020-09-22 11:44 UTC (permalink / raw)
  To: u-boot

On 22.09.2020 13:49, Claudiu Beznea - M18063 wrote:
> Hi Eugen,
> 
> On 22.09.2020 11:32, Eugen Hristev - M18282 wrote:
>> On 07.09.2020 18:36, Claudiu Beznea wrote:
>>> Add support for Microchip PIT64B timer. The timer is 64 bit length and
>>> is used as a free running counter (in continuous mode with highest values
>>> for period registers). The clock feeding the timer would be no more
>>> than 12.5MHz.
>>>
>>> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>>> ---
>>
>> Hi Claudiu,
>>
>> To make CI/CD scripts happy, this new driver needs a MAINTAINERS entry
> 
> Would you like me to create a new entry or add the file under the
> ARM MICROCHIP/ATMEL AT91 hood?

I am fine with both solutions, but I think one separate entry will be 
better.

Eugen
> 
> Thank you,
> Claudiu Beznea
> 
>>
>> Thanks !
>> Eugen

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] MAINTAINERS: add Microchip PIT64B timer
  2020-09-22 11:44     ` Eugen.Hristev at microchip.com
@ 2020-09-23 10:17       ` Claudiu Beznea
  2020-09-28 11:08         ` Eugen.Hristev at microchip.com
  0 siblings, 1 reply; 9+ messages in thread
From: Claudiu Beznea @ 2020-09-23 10:17 UTC (permalink / raw)
  To: u-boot

Add Microchip PIT64B timer.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---

Hi Eugen,

I chosed to have it under AT91 hood to not create an entry only for this
driver as there are mostly architecture/subsystem related entries in
MAINTAINERS file.

Thank you,
Claudiu Beznea

 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 438fb225ab0f..f0af12adb034 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -257,6 +257,7 @@ T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-atmel.git
 F:	arch/arm/mach-at91/
 F:	board/atmel/
 F:	drivers/misc/microchip_flexcom.c
+F:	drivers/timer/mchp-pit64b-timer.c
 
 ARM OWL
 M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH] MAINTAINERS: add Microchip PIT64B timer
  2020-09-23 10:17       ` [PATCH] MAINTAINERS: add Microchip PIT64B timer Claudiu Beznea
@ 2020-09-28 11:08         ` Eugen.Hristev at microchip.com
  0 siblings, 0 replies; 9+ messages in thread
From: Eugen.Hristev at microchip.com @ 2020-09-28 11:08 UTC (permalink / raw)
  To: u-boot

On 23.09.2020 13:17, Claudiu Beznea wrote:
> Add Microchip PIT64B timer.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> ---
> 
> Hi Eugen,
> 
> I chosed to have it under AT91 hood to not create an entry only for this
> driver as there are mostly architecture/subsystem related entries in
> MAINTAINERS file.
> 
> Thank you,
> Claudiu Beznea
> 

Applied to u-boot-atmel/next , thanks !

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] timer: mchp-pit64b: add support for pit64b
  2020-09-22 10:49   ` Claudiu.Beznea at microchip.com
  2020-09-22 11:44     ` Eugen.Hristev at microchip.com
@ 2020-09-28 11:09     ` Eugen.Hristev at microchip.com
  1 sibling, 0 replies; 9+ messages in thread
From: Eugen.Hristev at microchip.com @ 2020-09-28 11:09 UTC (permalink / raw)
  To: u-boot

On 22.09.2020 13:49, Claudiu Beznea - M18063 wrote:
> Hi Eugen,
> 
> On 22.09.2020 11:32, Eugen Hristev - M18282 wrote:
>> On 07.09.2020 18:36, Claudiu Beznea wrote:
>>> Add support for Microchip PIT64B timer. The timer is 64 bit length and
>>> is used as a free running counter (in continuous mode with highest values
>>> for period registers). The clock feeding the timer would be no more
>>> than 12.5MHz.
>>>
>>> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>>> ---
>>
>> Hi Claudiu,
>>
>> To make CI/CD scripts happy, this new driver needs a MAINTAINERS entry
> 
> Would you like me to create a new entry or add the file under the
> ARM MICROCHIP/ATMEL AT91 hood?
> 
> Thank you,
> Claudiu Beznea
> 
>>
>> Thanks !
>> Eugen

Applied to u-boot-atmel/next , thanks !

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] timer: mchp-pit64b: add support for pit64b
  2020-09-07 15:36 [PATCH] timer: mchp-pit64b: add support for pit64b Claudiu Beznea
  2020-09-22  8:32 ` Eugen.Hristev at microchip.com
@ 2020-10-07 17:49 ` Sean Anderson
  2020-10-08  8:18   ` Claudiu.Beznea at microchip.com
  1 sibling, 1 reply; 9+ messages in thread
From: Sean Anderson @ 2020-10-07 17:49 UTC (permalink / raw)
  To: u-boot

On 9/7/20 11:36 AM, Claudiu Beznea wrote:
> Add support for Microchip PIT64B timer. The timer is 64 bit length and
> is used as a free running counter (in continuous mode with highest values
> for period registers). The clock feeding the timer would be no more
> than 12.5MHz.
> 
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
> ---
>  drivers/timer/Kconfig             |   7 +++
>  drivers/timer/Makefile            |   1 +
>  drivers/timer/mchp-pit64b-timer.c | 109 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 117 insertions(+)
>  create mode 100644 drivers/timer/mchp-pit64b-timer.c
> 
> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
> index 5f4bc6edb67b..13a98be4ab92 100644
> --- a/drivers/timer/Kconfig
> +++ b/drivers/timer/Kconfig
> @@ -181,4 +181,11 @@ config MTK_TIMER
>  	  Select this to enable support for the timer found on
>  	  MediaTek devices.
>  
> +config MCHP_PIT64B_TIMER
> +	bool "Microchip 64-bit periodic interval timer support"
> +	depends on TIMER
> +	help
> +	  Select this to enable support for Microchip 64-bit periodic
> +	  interval timer.
> +
>  endmenu
> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
> index fa35bea6c5b2..4744a8d9c93c 100644
> --- a/drivers/timer/Makefile
> +++ b/drivers/timer/Makefile
> @@ -21,3 +21,4 @@ obj-$(CONFIG_STI_TIMER)		+= sti-timer.o
>  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
> diff --git a/drivers/timer/mchp-pit64b-timer.c b/drivers/timer/mchp-pit64b-timer.c
> new file mode 100644
> index 000000000000..ead8c9b84ad5
> --- /dev/null
> +++ b/drivers/timer/mchp-pit64b-timer.c
> @@ -0,0 +1,109 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * 64-bit Periodic Interval Timer driver
> + *
> + * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
> + *
> + * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <timer.h>
> +#include <asm/io.h>
> +
> +#define MCHP_PIT64B_CR			0x00	/* Control Register */
> +#define		MCHP_PIT64B_CR_START	BIT(0)
> +#define		MCHP_PIT64B_CR_SWRST	BIT(8)
> +#define MCHP_PIT64B_MR			0x04	/* Mode Register */
> +#define		MCHP_PIT64B_MR_CONT	BIT(0)
> +#define MCHP_PIT64B_LSB_PR		0x08	/* LSB Period Register */
> +#define MCHP_PIT64B_MSB_PR		0x0C	/* MSB Period Register */
> +#define MCHP_PIT64B_TLSBR		0x20	/* Timer LSB Register */
> +#define MCHP_PIT64B_TMSBR		0x24	/* Timer MSB Register */
> +
> +struct mchp_pit64b_priv {
> +	void __iomem *base;
> +};
> +
> +static int mchp_pit64b_get_count(struct udevice *dev, u64 *count)
> +{
> +	struct mchp_pit64b_priv *priv = dev_get_priv(dev);
> +
> +	u32 lsb = readl(priv->base + MCHP_PIT64B_TLSBR);
> +	u32 msb = readl(priv->base + MCHP_PIT64B_TMSBR);

Is there a chance of rollover here? E.g. lets say the 64-bit counter is
0x0000_0000_FFFF_FFFF when we read lsb, but it increments to
0x0000_0001_0000_0000 when we read msb. Then the next time we read the
timer, it will look like we jumped backward in time.

One way to get around this is by doing something like

	do {
		msb = readl(priv->base + MCHP_PIT64B_TMSBR);
		lsb = readl(priv->base + MCHP_PIT64B_TLSBR);
	} while (msb != readl(priv->base + MCHP_PIT64B_TMSBR));

That way, if we ever roll-over between the two reads, we just redo the
lsb read. This is the method used by drivers/timer/riscv_timer.c on
32-bit systems.

--Sean

> +
> +	*count = ((u64)msb << 32) | lsb;
> +
> +	return 0;
> +}
> +
> +static int mchp_pit64b_probe(struct udevice *dev)
> +{
> +	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +	struct mchp_pit64b_priv *priv = dev_get_priv(dev);
> +	struct clk clk;
> +	ulong rate;
> +	int ret;
> +
> +	priv->base = dev_read_addr_ptr(dev);
> +	if (IS_ERR(priv->base))
> +		return PTR_ERR(priv->base);
> +
> +	ret = clk_get_by_index(dev, 0, &clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_enable(&clk);
> +	if (ret)
> +		return ret;
> +
> +	rate = clk_get_rate(&clk);
> +	if (!rate) {
> +		clk_disable(&clk);
> +		return -ENOTSUPP;
> +	}
> +
> +	/* Reset the timer in case it was used by previous bootloaders. */
> +	writel(MCHP_PIT64B_CR_SWRST, priv->base + MCHP_PIT64B_CR);
> +
> +	/*
> +	 * Use highest prescaller (for a peripheral clock running at 200MHz
> +	 * this will lead to the timer running at 12.5MHz) and continuous mode.
> +	 */
> +	writel((15 << 8) | MCHP_PIT64B_MR_CONT, priv->base + MCHP_PIT64B_MR);
> +	uc_priv->clock_rate = rate / 16;
> +
> +	/*
> +	 * Simulate free running counter by setting max values to period
> +	 * registers.
> +	 */
> +	writel(~0UL, priv->base + MCHP_PIT64B_MSB_PR);
> +	writel(~0UL, priv->base + MCHP_PIT64B_LSB_PR);
> +
> +	/* Start the timer. */
> +	writel(MCHP_PIT64B_CR_START, priv->base + MCHP_PIT64B_CR);
> +
> +	return 0;
> +}
> +
> +static const struct timer_ops mchp_pit64b_ops = {
> +	.get_count = mchp_pit64b_get_count,
> +};
> +
> +static const struct udevice_id mchp_pit64b_ids[] = {
> +	{ .compatible = "microchip,sam9x60-pit64b", },
> +	{ .compatible = "microchip,sama7g5-pit64b", },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(mchp_pit64b) = {
> +	.name	= "mchp-pit64b",
> +	.id	= UCLASS_TIMER,
> +	.of_match = mchp_pit64b_ids,
> +	.priv_auto_alloc_size = sizeof(struct mchp_pit64b_priv),
> +	.probe	= mchp_pit64b_probe,
> +	.ops	= &mchp_pit64b_ops,
> +	.flags	= DM_FLAG_PRE_RELOC,
> +};
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH] timer: mchp-pit64b: add support for pit64b
  2020-10-07 17:49 ` Sean Anderson
@ 2020-10-08  8:18   ` Claudiu.Beznea at microchip.com
  0 siblings, 0 replies; 9+ messages in thread
From: Claudiu.Beznea at microchip.com @ 2020-10-08  8:18 UTC (permalink / raw)
  To: u-boot



On 07.10.2020 20:49, Sean Anderson wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 9/7/20 11:36 AM, Claudiu Beznea wrote:
>> Add support for Microchip PIT64B timer. The timer is 64 bit length and
>> is used as a free running counter (in continuous mode with highest values
>> for period registers). The clock feeding the timer would be no more
>> than 12.5MHz.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>> ---
>>  drivers/timer/Kconfig             |   7 +++
>>  drivers/timer/Makefile            |   1 +
>>  drivers/timer/mchp-pit64b-timer.c | 109 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 117 insertions(+)
>>  create mode 100644 drivers/timer/mchp-pit64b-timer.c
>>
>> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
>> index 5f4bc6edb67b..13a98be4ab92 100644
>> --- a/drivers/timer/Kconfig
>> +++ b/drivers/timer/Kconfig
>> @@ -181,4 +181,11 @@ config MTK_TIMER
>>         Select this to enable support for the timer found on
>>         MediaTek devices.
>>
>> +config MCHP_PIT64B_TIMER
>> +     bool "Microchip 64-bit periodic interval timer support"
>> +     depends on TIMER
>> +     help
>> +       Select this to enable support for Microchip 64-bit periodic
>> +       interval timer.
>> +
>>  endmenu
>> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
>> index fa35bea6c5b2..4744a8d9c93c 100644
>> --- a/drivers/timer/Makefile
>> +++ b/drivers/timer/Makefile
>> @@ -21,3 +21,4 @@ obj-$(CONFIG_STI_TIMER)             += sti-timer.o
>>  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
>> diff --git a/drivers/timer/mchp-pit64b-timer.c b/drivers/timer/mchp-pit64b-timer.c
>> new file mode 100644
>> index 000000000000..ead8c9b84ad5
>> --- /dev/null
>> +++ b/drivers/timer/mchp-pit64b-timer.c
>> @@ -0,0 +1,109 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * 64-bit Periodic Interval Timer driver
>> + *
>> + * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
>> + *
>> + * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <timer.h>
>> +#include <asm/io.h>
>> +
>> +#define MCHP_PIT64B_CR                       0x00    /* Control Register */
>> +#define              MCHP_PIT64B_CR_START    BIT(0)
>> +#define              MCHP_PIT64B_CR_SWRST    BIT(8)
>> +#define MCHP_PIT64B_MR                       0x04    /* Mode Register */
>> +#define              MCHP_PIT64B_MR_CONT     BIT(0)
>> +#define MCHP_PIT64B_LSB_PR           0x08    /* LSB Period Register */
>> +#define MCHP_PIT64B_MSB_PR           0x0C    /* MSB Period Register */
>> +#define MCHP_PIT64B_TLSBR            0x20    /* Timer LSB Register */
>> +#define MCHP_PIT64B_TMSBR            0x24    /* Timer MSB Register */
>> +
>> +struct mchp_pit64b_priv {
>> +     void __iomem *base;
>> +};
>> +
>> +static int mchp_pit64b_get_count(struct udevice *dev, u64 *count)
>> +{
>> +     struct mchp_pit64b_priv *priv = dev_get_priv(dev);
>> +
>> +     u32 lsb = readl(priv->base + MCHP_PIT64B_TLSBR);
>> +     u32 msb = readl(priv->base + MCHP_PIT64B_TMSBR);
> 
> Is there a chance of rollover here? E.g. lets say the 64-bit counter is
> 0x0000_0000_FFFF_FFFF when we read lsb, but it increments to
> 0x0000_0001_0000_0000 when we read msb. Then the next time we read the
> timer, it will look like we jumped backward in time.

This should not happen as the hardware takes care of it as follows:
when using a 64 bit period TLSB must be read first, followed by the
read of TMSB. This sequence generates an atomic read of the 64 bit
timer value whatever the lapse of time between the accesses.

Thank you,
Claudiu Beznea

> 
> One way to get around this is by doing something like
> 
>         do {
>                 msb = readl(priv->base + MCHP_PIT64B_TMSBR);
>                 lsb = readl(priv->base + MCHP_PIT64B_TLSBR);
>         } while (msb != readl(priv->base + MCHP_PIT64B_TMSBR));
> 
> That way, if we ever roll-over between the two reads, we just redo the
> lsb read. This is the method used by drivers/timer/riscv_timer.c on
> 32-bit systems.
> 
> --Sean
> 
>> +
>> +     *count = ((u64)msb << 32) | lsb;
>> +
>> +     return 0;
>> +}
>> +
>> +static int mchp_pit64b_probe(struct udevice *dev)
>> +{
>> +     struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>> +     struct mchp_pit64b_priv *priv = dev_get_priv(dev);
>> +     struct clk clk;
>> +     ulong rate;
>> +     int ret;
>> +
>> +     priv->base = dev_read_addr_ptr(dev);
>> +     if (IS_ERR(priv->base))
>> +             return PTR_ERR(priv->base);
>> +
>> +     ret = clk_get_by_index(dev, 0, &clk);
>> +     if (ret)
>> +             return ret;
>> +
>> +     ret = clk_enable(&clk);
>> +     if (ret)
>> +             return ret;
>> +
>> +     rate = clk_get_rate(&clk);
>> +     if (!rate) {
>> +             clk_disable(&clk);
>> +             return -ENOTSUPP;
>> +     }
>> +
>> +     /* Reset the timer in case it was used by previous bootloaders. */
>> +     writel(MCHP_PIT64B_CR_SWRST, priv->base + MCHP_PIT64B_CR);
>> +
>> +     /*
>> +      * Use highest prescaller (for a peripheral clock running at 200MHz
>> +      * this will lead to the timer running at 12.5MHz) and continuous mode.
>> +      */
>> +     writel((15 << 8) | MCHP_PIT64B_MR_CONT, priv->base + MCHP_PIT64B_MR);
>> +     uc_priv->clock_rate = rate / 16;
>> +
>> +     /*
>> +      * Simulate free running counter by setting max values to period
>> +      * registers.
>> +      */
>> +     writel(~0UL, priv->base + MCHP_PIT64B_MSB_PR);
>> +     writel(~0UL, priv->base + MCHP_PIT64B_LSB_PR);
>> +
>> +     /* Start the timer. */
>> +     writel(MCHP_PIT64B_CR_START, priv->base + MCHP_PIT64B_CR);
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct timer_ops mchp_pit64b_ops = {
>> +     .get_count = mchp_pit64b_get_count,
>> +};
>> +
>> +static const struct udevice_id mchp_pit64b_ids[] = {
>> +     { .compatible = "microchip,sam9x60-pit64b", },
>> +     { .compatible = "microchip,sama7g5-pit64b", },
>> +     { }
>> +};
>> +
>> +U_BOOT_DRIVER(mchp_pit64b) = {
>> +     .name   = "mchp-pit64b",
>> +     .id     = UCLASS_TIMER,
>> +     .of_match = mchp_pit64b_ids,
>> +     .priv_auto_alloc_size = sizeof(struct mchp_pit64b_priv),
>> +     .probe  = mchp_pit64b_probe,
>> +     .ops    = &mchp_pit64b_ops,
>> +     .flags  = DM_FLAG_PRE_RELOC,
>> +};
>>
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-10-08  8:18 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-07 15:36 [PATCH] timer: mchp-pit64b: add support for pit64b Claudiu Beznea
2020-09-22  8:32 ` Eugen.Hristev at microchip.com
2020-09-22 10:49   ` Claudiu.Beznea at microchip.com
2020-09-22 11:44     ` Eugen.Hristev at microchip.com
2020-09-23 10:17       ` [PATCH] MAINTAINERS: add Microchip PIT64B timer Claudiu Beznea
2020-09-28 11:08         ` Eugen.Hristev at microchip.com
2020-09-28 11:09     ` [PATCH] timer: mchp-pit64b: add support for pit64b Eugen.Hristev at microchip.com
2020-10-07 17:49 ` Sean Anderson
2020-10-08  8:18   ` Claudiu.Beznea at microchip.com

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.