All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/2] dm: implement a Timer uclass
@ 2015-09-28 13:19 Thomas Chou
  2015-09-28 13:19 ` [U-Boot] [PATCH 2/2] nios2: convert altera timer to driver model Thomas Chou
                   ` (8 more replies)
  0 siblings, 9 replies; 45+ messages in thread
From: Thomas Chou @ 2015-09-28 13:19 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
 common/board_r.c             |  2 +-
 drivers/Kconfig              |  2 ++
 drivers/Makefile             |  1 +
 drivers/timer/Kconfig        |  9 ++++++++
 drivers/timer/Makefile       |  7 ++++++
 drivers/timer/timer-uclass.c | 35 ++++++++++++++++++++++++++++++
 drivers/timer/timer.c        | 51 ++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h       |  1 +
 include/timer.h              | 36 +++++++++++++++++++++++++++++++
 9 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 drivers/timer/timer.c
 create mode 100644 include/timer.h

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..2d8ad11 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -829,7 +829,7 @@ init_fnc_t init_sequence_r[] = {
 	initr_enable_interrupts,
 #endif
 #if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) \
-	|| defined(CONFIG_M68K)
+	|| defined(CONFIG_M68K) || defined(CONFIG_DM_TIMER)
 	timer_init,		/* initialize timer */
 #endif
 #if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..97014f3
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,9 @@
+menu "Timer Support"
+
+config DM_TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..58acd7c
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o timer.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..1f088bf
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+int timer_get_rate(struct udevice *dev, unsigned long *rate)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_rate)
+		return -ENOSYS;
+
+	return ops->get_rate(dev, rate);
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+};
diff --git a/drivers/timer/timer.c b/drivers/timer/timer.c
new file mode 100644
index 0000000..648fd06
--- /dev/null
+++ b/drivers/timer/timer.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned long notrace get_tbclk(void)
+{
+	struct udevice *dev;
+	unsigned long rate;
+
+	uclass_first_device(UCLASS_TIMER, &dev);
+	if (!dev)
+		return 100000000; /* 100MHz, fail-safe */
+
+	timer_get_rate(dev, &rate);
+
+	return rate;
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	struct udevice *dev;
+	unsigned long count;
+
+	uclass_first_device(UCLASS_TIMER, &dev);
+	if (!dev)
+		return 0; /* 0, fail-safe */
+
+	timer_get_count(dev, &count);
+
+	return count;
+}
+
+int timer_init(void)
+{
+	struct udevice *dev;
+
+	uclass_first_device(UCLASS_TIMER, &dev);
+	if (!dev)
+		return -ENODEV;
+
+	return 0;
+}
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..5d71612
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+int timer_get_count(struct udevice *dev, unsigned long *count);
+int timer_get_rate(struct udevice *dev, unsigned long *rate);
+
+/*
+ * struct dm_timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct dm_timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev:	The Timer device
+	 * @count:	pointer that returns the currnet timer count
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+	/*
+	 * Get the timer clock rate
+	 *
+	 * @dev:	The Timer device
+	 * @rate:	pointer that returns the timer clock rate
+	 */
+	int (*get_rate)(struct udevice *dev, unsigned long *rate);
+};
+
+#endif	/* _DM_TIMER_H_ */
-- 
2.1.4

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

* [U-Boot] [PATCH 2/2] nios2: convert altera timer to driver model
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
@ 2015-09-28 13:19 ` Thomas Chou
  2015-09-29  1:32 ` [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-09-28 13:19 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
 arch/nios2/cpu/Makefile         |   2 +-
 arch/nios2/cpu/timer.c          |  65 ------------------------
 common/board_f.c                |   3 +-
 configs/nios2-generic_defconfig |   2 +
 drivers/timer/Kconfig           |   7 +++
 drivers/timer/Makefile          |   1 +
 drivers/timer/altera_timer.c    | 110 ++++++++++++++++++++++++++++++++++++++++
 include/configs/nios2-generic.h |   6 ---
 8 files changed, 122 insertions(+), 74 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index d0a9ff7..4c23a7f 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-    defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-    defined(CONFIG_NIOS2)
+    defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 63d99d8..1aa2d9e 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -17,3 +17,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_DM_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 97014f3..70fbcda 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -6,4 +6,11 @@ config DM_TIMER
 	help
 	  Enable driver model for Timer access.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on DM_TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index 58acd7c..db8fa2b 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o timer.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..8128eb6
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long timerclk;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_get_rate(struct udevice *dev, unsigned long *rate)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+
+	*rate = plat->timerclk;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->timerclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct dm_timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+	.get_rate = altera_timer_get_rate,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 90ccbd1..ae19676 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -27,12 +27,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_COUNTS_DOWN
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH 1/2] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
  2015-09-28 13:19 ` [U-Boot] [PATCH 2/2] nios2: convert altera timer to driver model Thomas Chou
@ 2015-09-29  1:32 ` Thomas Chou
  2015-09-29 12:39 ` [U-Boot] [PATCH v2 " Thomas Chou
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-09-29  1:32 UTC (permalink / raw)
  To: u-boot



On 09/28/2015 09:19 PM, Thomas Chou wrote:
> diff --git a/drivers/timer/timer.c b/drivers/timer/timer.c
> new file mode 100644
> index 0000000..648fd06
> --- /dev/null
> +++ b/drivers/timer/timer.c
> @@ -0,0 +1,51 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +unsigned long notrace get_tbclk(void)
> +{
> +	struct udevice *dev;
> +	unsigned long rate;
> +
> +	uclass_first_device(UCLASS_TIMER, &dev);
> +	if (!dev)
> +		return 100000000; /* 100MHz, fail-safe */
		return -ENODEV;

> +
> +	timer_get_rate(dev, &rate);
> +
> +	return rate;
> +}
> +
> +unsigned long notrace timer_read_counter(void)
> +{
> +	struct udevice *dev;
> +	unsigned long count;
> +
> +	uclass_first_device(UCLASS_TIMER, &dev);
> +	if (!dev)
> +		return 0; /* 0, fail-safe */
		return -ENODEV;

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

* [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
  2015-09-28 13:19 ` [U-Boot] [PATCH 2/2] nios2: convert altera timer to driver model Thomas Chou
  2015-09-29  1:32 ` [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
@ 2015-09-29 12:39 ` Thomas Chou
  2015-09-29 12:39   ` [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model Thomas Chou
  2015-09-29 13:57   ` [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass Simon Glass
  2015-10-03  9:19 ` [U-Boot] [PATCH v3 " Thomas Chou
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 45+ messages in thread
From: Thomas Chou @ 2015-09-29 12:39 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
v2
  fix coding style.

 common/board_r.c             |  5 +++--
 drivers/Kconfig              |  2 ++
 drivers/Makefile             |  1 +
 drivers/timer/Kconfig        |  9 ++++++++
 drivers/timer/Makefile       |  7 ++++++
 drivers/timer/timer-uclass.c | 35 ++++++++++++++++++++++++++++++
 drivers/timer/timer.c        | 51 ++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h       |  1 +
 include/timer.h              | 36 +++++++++++++++++++++++++++++++
 9 files changed, 145 insertions(+), 2 deletions(-)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 drivers/timer/timer.c
 create mode 100644 include/timer.h

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..64b0577 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -828,8 +828,9 @@ init_fnc_t init_sequence_r[] = {
 #if defined(CONFIG_ARM) || defined(CONFIG_AVR32)
 	initr_enable_interrupts,
 #endif
-#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) \
-	|| defined(CONFIG_M68K)
+#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || \
+		defined(CONFIG_AVR32) || defined(CONFIG_M68K) || \
+		defined(CONFIG_DM_TIMER)
 	timer_init,		/* initialize timer */
 #endif
 #if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..97014f3
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,9 @@
+menu "Timer Support"
+
+config DM_TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..58acd7c
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o timer.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..1f088bf
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+int timer_get_rate(struct udevice *dev, unsigned long *rate)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_rate)
+		return -ENOSYS;
+
+	return ops->get_rate(dev, rate);
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+};
diff --git a/drivers/timer/timer.c b/drivers/timer/timer.c
new file mode 100644
index 0000000..766eabf
--- /dev/null
+++ b/drivers/timer/timer.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned long notrace get_tbclk(void)
+{
+	struct udevice *dev;
+	unsigned long rate;
+
+	uclass_first_device(UCLASS_TIMER, &dev);
+	if (!dev)
+		return -ENODEV;
+
+	timer_get_rate(dev, &rate);
+
+	return rate;
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	struct udevice *dev;
+	unsigned long count;
+
+	uclass_first_device(UCLASS_TIMER, &dev);
+	if (!dev)
+		return -ENODEV;
+
+	timer_get_count(dev, &count);
+
+	return count;
+}
+
+int timer_init(void)
+{
+	struct udevice *dev;
+
+	uclass_first_device(UCLASS_TIMER, &dev);
+	if (!dev)
+		return -ENODEV;
+
+	return 0;
+}
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..5d71612
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+int timer_get_count(struct udevice *dev, unsigned long *count);
+int timer_get_rate(struct udevice *dev, unsigned long *rate);
+
+/*
+ * struct dm_timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct dm_timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev:	The Timer device
+	 * @count:	pointer that returns the currnet timer count
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+	/*
+	 * Get the timer clock rate
+	 *
+	 * @dev:	The Timer device
+	 * @rate:	pointer that returns the timer clock rate
+	 */
+	int (*get_rate)(struct udevice *dev, unsigned long *rate);
+};
+
+#endif	/* _DM_TIMER_H_ */
-- 
2.1.4

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

* [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model
  2015-09-29 12:39 ` [U-Boot] [PATCH v2 " Thomas Chou
@ 2015-09-29 12:39   ` Thomas Chou
  2015-09-30  0:27     ` Chin Liang See
  2015-09-29 13:57   ` [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass Simon Glass
  1 sibling, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-09-29 12:39 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
v2
  fix coding style.

 arch/nios2/cpu/Makefile         |   2 +-
 arch/nios2/cpu/timer.c          |  65 ------------------------
 common/board_f.c                |   3 +-
 configs/nios2-generic_defconfig |   2 +
 drivers/timer/Kconfig           |   7 +++
 drivers/timer/Makefile          |   1 +
 drivers/timer/altera_timer.c    | 110 ++++++++++++++++++++++++++++++++++++++++
 include/configs/nios2-generic.h |   6 ---
 8 files changed, 122 insertions(+), 74 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index d0a9ff7..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-    defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-    defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..dac0b62 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_DM_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 97014f3..70fbcda 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -6,4 +6,11 @@ config DM_TIMER
 	help
 	  Enable driver model for Timer access.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on DM_TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index 58acd7c..db8fa2b 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o timer.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..8128eb6
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long timerclk;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_get_rate(struct udevice *dev, unsigned long *rate)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+
+	*rate = plat->timerclk;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->timerclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct dm_timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+	.get_rate = altera_timer_get_rate,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 90ccbd1..ae19676 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -27,12 +27,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_COUNTS_DOWN
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass
  2015-09-29 12:39 ` [U-Boot] [PATCH v2 " Thomas Chou
  2015-09-29 12:39   ` [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model Thomas Chou
@ 2015-09-29 13:57   ` Simon Glass
  2015-10-01  7:22     ` Thomas Chou
  1 sibling, 1 reply; 45+ messages in thread
From: Simon Glass @ 2015-09-29 13:57 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On 29 September 2015 at 06:39, Thomas Chou <thomas@wytron.com.tw> wrote:
> Implement a Timer uclass to work with lib/time.c.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>

Thanks for doing this work! I have some comments below.

> ---
> v2
>   fix coding style.
>
>  common/board_r.c             |  5 +++--
>  drivers/Kconfig              |  2 ++
>  drivers/Makefile             |  1 +
>  drivers/timer/Kconfig        |  9 ++++++++
>  drivers/timer/Makefile       |  7 ++++++
>  drivers/timer/timer-uclass.c | 35 ++++++++++++++++++++++++++++++
>  drivers/timer/timer.c        | 51 ++++++++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h       |  1 +
>  include/timer.h              | 36 +++++++++++++++++++++++++++++++
>  9 files changed, 145 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/timer/Kconfig
>  create mode 100644 drivers/timer/Makefile
>  create mode 100644 drivers/timer/timer-uclass.c
>  create mode 100644 drivers/timer/timer.c
>  create mode 100644 include/timer.h
>
> diff --git a/common/board_r.c b/common/board_r.c
> index f8c1baa..64b0577 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -828,8 +828,9 @@ init_fnc_t init_sequence_r[] = {
>  #if defined(CONFIG_ARM) || defined(CONFIG_AVR32)
>         initr_enable_interrupts,
>  #endif
> -#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) \
> -       || defined(CONFIG_M68K)
> +#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || \
> +               defined(CONFIG_AVR32) || defined(CONFIG_M68K) || \
> +               defined(CONFIG_DM_TIMER)
>         timer_init,             /* initialize timer */
>  #endif
>  #if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 63c92c5..f9496f7 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
>
>  source "drivers/thermal/Kconfig"
>
> +source "drivers/timer/Kconfig"
> +
>  source "drivers/tpm/Kconfig"
>
>  source "drivers/usb/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 9d0a595..692da78 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -48,6 +48,7 @@ obj-y += pcmcia/
>  obj-y += dfu/
>  obj-y += rtc/
>  obj-y += sound/
> +obj-y += timer/
>  obj-y += tpm/
>  obj-y += twserial/
>  obj-y += video/
> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
> new file mode 100644
> index 0000000..97014f3
> --- /dev/null
> +++ b/drivers/timer/Kconfig
> @@ -0,0 +1,9 @@
> +menu "Timer Support"
> +
> +config DM_TIMER
> +       bool "Enable Driver Model for Timer drivers"
> +       depends on DM
> +       help
> +         Enable driver model for Timer access.

Can you expand this a little bit?

- Uses the same API
- But now implemented by the uclass
- The first timer is used

> +
> +endmenu
> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
> new file mode 100644
> index 0000000..58acd7c
> --- /dev/null
> +++ b/drivers/timer/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-$(CONFIG_DM_TIMER)         += timer-uclass.o timer.o
> diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
> new file mode 100644
> index 0000000..1f088bf
> --- /dev/null
> +++ b/drivers/timer/timer-uclass.c
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
> +
> +int timer_get_count(struct udevice *dev, unsigned long *count)
> +{
> +       const struct dm_timer_ops *ops = device_get_ops(dev);
> +
> +       if (!ops->get_count)
> +               return -ENOSYS;
> +
> +       return ops->get_count(dev, count);
> +}
> +
> +int timer_get_rate(struct udevice *dev, unsigned long *rate)
> +{
> +       const struct dm_timer_ops *ops = device_get_ops(dev);
> +
> +       if (!ops->get_rate)
> +               return -ENOSYS;
> +
> +       return ops->get_rate(dev, rate);
> +}
> +
> +UCLASS_DRIVER(timer) = {
> +       .id             = UCLASS_TIMER,
> +       .name           = "timer",
> +};
> diff --git a/drivers/timer/timer.c b/drivers/timer/timer.c
> new file mode 100644
> index 0000000..766eabf
> --- /dev/null
> +++ b/drivers/timer/timer.c

I think these functions should go in lib/time.c.

At some point we should look at implementing udelay() also.

> @@ -0,0 +1,51 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +unsigned long notrace get_tbclk(void)
> +{
> +       struct udevice *dev;
> +       unsigned long rate;
> +
> +       uclass_first_device(UCLASS_TIMER, &dev);
> +       if (!dev)
> +               return -ENODEV;
> +
> +       timer_get_rate(dev, &rate);
> +
> +       return rate;
> +}
> +
> +unsigned long notrace timer_read_counter(void)
> +{
> +       struct udevice *dev;
> +       unsigned long count;
> +
> +       uclass_first_device(UCLASS_TIMER, &dev);
> +       if (!dev)
> +               return -ENODEV;

I suggest saving this device in global_data. This might get called a lot.

> +
> +       timer_get_count(dev, &count);
> +
> +       return count;
> +}
> +
> +int timer_init(void)

I suspect this function is not needed. We should try to avoid this
sort of thing with driver model - devices should be able to be inited
when needed. Granted the timer is a very basic device, but it should
follow the same model if possible.

> +{
> +       struct udevice *dev;
> +
> +       uclass_first_device(UCLASS_TIMER, &dev);
> +       if (!dev)
> +               return -ENODEV;
> +
> +       return 0;
> +}
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 1eeec74..aff34a4 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -56,6 +56,7 @@ enum uclass_id {
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
>         UCLASS_THERMAL,         /* Thermal sensor */
> +       UCLASS_TIMER,           /* Timer device */
>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
>         UCLASS_USB,             /* USB bus */
>         UCLASS_USB_DEV_GENERIC, /* USB generic device */
> diff --git a/include/timer.h b/include/timer.h
> new file mode 100644
> index 0000000..5d71612
> --- /dev/null
> +++ b/include/timer.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef _DM_TIMER_H_
> +#define _DM_TIMER_H_
> +
> +int timer_get_count(struct udevice *dev, unsigned long *count);

We should also handle microsecond time in this API. How about:

timer_get_ms()
timer_get_us()

> +int timer_get_rate(struct udevice *dev, unsigned long *rate);

Function comments.

> +
> +/*
> + * struct dm_timer_ops - Driver model Timer operations
> + *
> + * The uclass interface is implemented by all Timer devices which use
> + * driver model.
> + */
> +struct dm_timer_ops {
> +       /*
> +        * Get the current timer count
> +        *
> +        * @dev:        The Timer device
> +        * @count:      pointer that returns the currnet timer count

current
Also don't forget @return

> +        */
> +       int (*get_count)(struct udevice *dev, unsigned long *count);
> +       /*
> +        * Get the timer clock rate
> +        *
> +        * @dev:        The Timer device
> +        * @rate:       pointer that returns the timer clock rate

in Hz. Also, isn't the clock rate required to be 1000 now?

> +        */
> +       int (*get_rate)(struct udevice *dev, unsigned long *rate);
> +};
> +
> +#endif /* _DM_TIMER_H_ */
> --
> 2.1.4
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model
  2015-09-29 12:39   ` [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model Thomas Chou
@ 2015-09-30  0:27     ` Chin Liang See
  2015-10-01  2:51       ` Thomas Chou
  0 siblings, 1 reply; 45+ messages in thread
From: Chin Liang See @ 2015-09-30  0:27 UTC (permalink / raw)
  To: u-boot

Hi Thomas,


On Tue, 2015-09-29 at 07:39 +0000, thomas at wytron.com.tw wrote:
> Convert altera timer to driver model.
> 
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> v2
>   fix coding style.
> 
>  arch/nios2/cpu/Makefile         |   2 +-
>  arch/nios2/cpu/timer.c          |  65 ------------------------
>  common/board_f.c                |   3 +-
>  configs/nios2-generic_defconfig |   2 +
>  drivers/timer/Kconfig           |   7 +++
>  drivers/timer/Makefile          |   1 +
>  drivers/timer/altera_timer.c    | 110 ++++++++++++++++++++++++++++++++++++++++
>  include/configs/nios2-generic.h |   6 ---
>  8 files changed, 122 insertions(+), 74 deletions(-)
>  delete mode 100644 arch/nios2/cpu/timer.c
>  create mode 100644 drivers/timer/altera_timer.c
> 

Thanks for the patch.
The patch looks good except it misses the changes for dts.

Thanks
Chin Liang

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

* [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model
  2015-09-30  0:27     ` Chin Liang See
@ 2015-10-01  2:51       ` Thomas Chou
  2015-10-01  9:12         ` Thomas Chou
  0 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-01  2:51 UTC (permalink / raw)
  To: u-boot

Hi Chin Liang,

On 09/30/2015 08:27 AM, Chin Liang See wrote:
> Thanks for the patch.
> The patch looks good except it misses the changes for dts.

If you mean pre relocation, I will add a pre relocation flag, 
DM_FLAG_PRE_RELOC, to the altera_timer driver. Though I think there is 
no need to initialize the timer before relocation for nios2 and the dts 
is not changed. Those who need timer before relocation can add the 
property "u-boot,dm-pre-reloc;" to dts.

Best regards,
Thomas Chou

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

* [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass
  2015-09-29 13:57   ` [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass Simon Glass
@ 2015-10-01  7:22     ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-01  7:22 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 09/29/2015 09:57 PM, Simon Glass wrote:
>> +int timer_get_count(struct udevice *dev, unsigned long *count);
>
> We should also handle microsecond time in this API. How about:
>
> timer_get_ms()
> timer_get_us()

Please allow the additional API be implemented at some later point. It 
might be better to keep the first patch simple as possible,

>> +       /*
>> +        * Get the timer clock rate
>> +        *
>> +        * @dev:        The Timer device
>> +        * @rate:       pointer that returns the timer clock rate
>> +        */
>> +       int (*get_rate)(struct udevice *dev, unsigned long *rate);
>
> in Hz. Also, isn't the clock rate required to be 1000 now?

Sorry for the confusion. It meant the timer input clock frequency. I 
rename it to get_clock() now. Will this be better?

Thanks a lot for your review.

Best regards,
Thomas Chou

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

* [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model
  2015-10-01  2:51       ` Thomas Chou
@ 2015-10-01  9:12         ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-01  9:12 UTC (permalink / raw)
  To: u-boot

Hi Chin Liang,

On 10/01/2015 10:51 AM, Thomas Chou wrote:
> Hi Chin Liang,
>
> On 09/30/2015 08:27 AM, Chin Liang See wrote:
>> Thanks for the patch.
>> The patch looks good except it misses the changes for dts.
>

Sorry. I guess I misunderstood. The dts binding is added.

Best regards,
Thomas Chou

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

* [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (2 preceding siblings ...)
  2015-09-29 12:39 ` [U-Boot] [PATCH v2 " Thomas Chou
@ 2015-10-03  9:19 ` Thomas Chou
  2015-10-03  9:19   ` [U-Boot] [PATCH v3 2/2] nios2: convert altera timer to driver model Thomas Chou
  2015-10-03 14:29   ` [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass Simon Glass
  2015-10-04 13:56 ` [U-Boot] [PATCH v4 " Thomas Chou
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-03  9:19 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
v2
  fix coding style.
v3
  add description to Kconfig as Simon suggested.
  move timer.c code to lib/time.c.
  add dm_timer dev to global data.
  remove timer_init().
  change API name get_clock.

 common/board_r.c                  |  3 +++
 drivers/Kconfig                   |  2 ++
 drivers/Makefile                  |  1 +
 drivers/timer/Kconfig             | 11 ++++++++
 drivers/timer/Makefile            |  7 +++++
 drivers/timer/timer-uclass.c      | 35 +++++++++++++++++++++++++
 include/asm-generic/global_data.h |  3 +++
 include/dm/uclass-id.h            |  1 +
 include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++
 lib/time.c                        | 54 +++++++++++++++++++++++++++++++++++++++
 10 files changed, 169 insertions(+)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 include/timer.h

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..aaf390e 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -290,6 +290,9 @@ static int initr_dm(void)
 	/* Save the pre-reloc driver model and start a new one */
 	gd->dm_root_f = gd->dm_root;
 	gd->dm_root = NULL;
+#ifdef CONFIG_DM_TIMER
+	gd->dm_timer = NULL;
+#endif
 	return dm_init_and_scan(false);
 }
 #endif
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..5228e26
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,11 @@
+menu "Timer Support"
+
+config DM_TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access. It uses the same API as
+	  lib/time.c. But now implemented by the uclass. The first timer
+	  will be used.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..a24179a
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..8071fcc
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+int timer_get_clock(struct udevice *dev, unsigned long *freq)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_clock)
+		return -ENOSYS;
+
+	return ops->get_clock(dev, freq);
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+};
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..ebecb5f 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -69,6 +69,9 @@ typedef struct global_data {
 	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
 	struct list_head uclass_root;	/* Head of core tree */
 #endif
+#ifdef CONFIG_DM_TIMER
+	struct udevice	*dm_timer;	/* Timer instance for Driver Model */
+#endif
 
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..c18a195
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+/*
+ * Get the current timer count
+ *
+ * @dev: The Timer device
+ * @count: pointer that returns the current timer count
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_count(struct udevice *dev, unsigned long *count);
+/*
+ * Get the timer input clock frequency
+ *
+ * @dev: The Timer device
+ * @freq: pointer that returns the timer clock frequency
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_clock(struct udevice *dev, unsigned long *freq);
+
+/*
+ * struct dm_timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct dm_timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev: The Timer device
+	 * @count: pointer that returns the current timer count
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+	/*
+	 * Get the timer input clock frequency
+	 *
+	 * @dev: The Timer device
+	 * @freq: pointer that returns the timer clock frequency
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_clock)(struct udevice *dev, unsigned long *freq);
+};
+
+#endif	/* _DM_TIMER_H_ */
diff --git a/lib/time.c b/lib/time.c
index 477440d..6b7342e 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -6,6 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
 #include <watchdog.h>
 #include <div64.h>
 #include <asm/io.h>
@@ -37,6 +40,57 @@ unsigned long notrace timer_read_counter(void)
 extern unsigned long __weak timer_read_counter(void);
 #endif
 
+#ifdef CONFIG_DM_TIMER
+static int dm_timer_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (!gd->dm_timer) {
+		ret = uclass_first_device(UCLASS_TIMER, &dev);
+		if (ret)
+			return ret;
+		if (!dev)
+			return -ENODEV;
+		gd->dm_timer = dev;
+	}
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	unsigned long freq;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_clock(gd->dm_timer, &freq);
+	if (ret)
+		return ret;
+
+	return freq;
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	unsigned long count;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_count(gd->dm_timer, &count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+#endif /* CONFIG_DM_TIMER */
+
 uint64_t __weak notrace get_ticks(void)
 {
 	unsigned long now = timer_read_counter();
-- 
2.1.4

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

* [U-Boot] [PATCH v3 2/2] nios2: convert altera timer to driver model
  2015-10-03  9:19 ` [U-Boot] [PATCH v3 " Thomas Chou
@ 2015-10-03  9:19   ` Thomas Chou
  2015-10-03 14:29   ` [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass Simon Glass
  1 sibling, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-03  9:19 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
v2
  fix coding style.
v3
  doc dts binding.

 arch/nios2/cpu/Makefile                         |   2 +-
 arch/nios2/cpu/timer.c                          |  65 --------------
 common/board_f.c                                |   3 +-
 configs/nios2-generic_defconfig                 |   2 +
 doc/device-tree-bindings/timer/altera_timer.txt |  19 ++++
 drivers/timer/Kconfig                           |   7 ++
 drivers/timer/Makefile                          |   1 +
 drivers/timer/altera_timer.c                    | 110 ++++++++++++++++++++++++
 include/configs/nios2-generic.h                 |   6 --
 9 files changed, 141 insertions(+), 74 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index d0a9ff7..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-    defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-    defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..dac0b62 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_DM_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/doc/device-tree-bindings/timer/altera_timer.txt b/doc/device-tree-bindings/timer/altera_timer.txt
new file mode 100644
index 0000000..904a584
--- /dev/null
+++ b/doc/device-tree-bindings/timer/altera_timer.txt
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "altr,timer-1.0";
+	reg = <0x00400000 0x00000020>;
+	interrupt-parent = <&cpu>;
+	interrupts = <11>;
+	clock-frequency = <125000000>;
+};
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 5228e26..5a5558d 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -8,4 +8,11 @@ config DM_TIMER
 	  lib/time.c. But now implemented by the uclass. The first timer
 	  will be used.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on DM_TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index a24179a..0c7398f 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..25856d9
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long timerclk;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_get_clock(struct udevice *dev, unsigned long *freq)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+
+	*freq = plat->timerclk;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->timerclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct dm_timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+	.get_clock = altera_timer_get_clock,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 90ccbd1..ae19676 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -27,12 +27,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_COUNTS_DOWN
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass
  2015-10-03  9:19 ` [U-Boot] [PATCH v3 " Thomas Chou
  2015-10-03  9:19   ` [U-Boot] [PATCH v3 2/2] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-03 14:29   ` Simon Glass
  2015-10-04 13:09     ` Thomas Chou
  1 sibling, 1 reply; 45+ messages in thread
From: Simon Glass @ 2015-10-03 14:29 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On 3 October 2015 at 10:19, Thomas Chou <thomas@wytron.com.tw> wrote:
> Implement a Timer uclass to work with lib/time.c.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> v2
>   fix coding style.
> v3
>   add description to Kconfig as Simon suggested.
>   move timer.c code to lib/time.c.
>   add dm_timer dev to global data.
>   remove timer_init().
>   change API name get_clock.
>
>  common/board_r.c                  |  3 +++
>  drivers/Kconfig                   |  2 ++
>  drivers/Makefile                  |  1 +
>  drivers/timer/Kconfig             | 11 ++++++++
>  drivers/timer/Makefile            |  7 +++++
>  drivers/timer/timer-uclass.c      | 35 +++++++++++++++++++++++++
>  include/asm-generic/global_data.h |  3 +++
>  include/dm/uclass-id.h            |  1 +
>  include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++
>  lib/time.c                        | 54 +++++++++++++++++++++++++++++++++++++++
>  10 files changed, 169 insertions(+)
>  create mode 100644 drivers/timer/Kconfig
>  create mode 100644 drivers/timer/Makefile
>  create mode 100644 drivers/timer/timer-uclass.c
>  create mode 100644 include/timer.h

Reviewed-by: Simon Glass <sjg@chromium.org>

Please see one nit below.

>
> diff --git a/common/board_r.c b/common/board_r.c
> index f8c1baa..aaf390e 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -290,6 +290,9 @@ static int initr_dm(void)
>         /* Save the pre-reloc driver model and start a new one */
>         gd->dm_root_f = gd->dm_root;
>         gd->dm_root = NULL;
> +#ifdef CONFIG_DM_TIMER
> +       gd->dm_timer = NULL;
> +#endif
>         return dm_init_and_scan(false);
>  }
>  #endif
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 63c92c5..f9496f7 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
>
>  source "drivers/thermal/Kconfig"
>
> +source "drivers/timer/Kconfig"
> +
>  source "drivers/tpm/Kconfig"
>
>  source "drivers/usb/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 9d0a595..692da78 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -48,6 +48,7 @@ obj-y += pcmcia/
>  obj-y += dfu/
>  obj-y += rtc/
>  obj-y += sound/
> +obj-y += timer/
>  obj-y += tpm/
>  obj-y += twserial/
>  obj-y += video/
> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
> new file mode 100644
> index 0000000..5228e26
> --- /dev/null
> +++ b/drivers/timer/Kconfig
> @@ -0,0 +1,11 @@
> +menu "Timer Support"
> +
> +config DM_TIMER
> +       bool "Enable Driver Model for Timer drivers"
> +       depends on DM
> +       help
> +         Enable driver model for Timer access. It uses the same API as
> +         lib/time.c. But now implemented by the uclass. The first timer
> +         will be used.
> +
> +endmenu
> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
> new file mode 100644
> index 0000000..a24179a
> --- /dev/null
> +++ b/drivers/timer/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-$(CONFIG_DM_TIMER)         += timer-uclass.o
> diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
> new file mode 100644
> index 0000000..8071fcc
> --- /dev/null
> +++ b/drivers/timer/timer-uclass.c
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
> +
> +int timer_get_count(struct udevice *dev, unsigned long *count)
> +{
> +       const struct dm_timer_ops *ops = device_get_ops(dev);
> +
> +       if (!ops->get_count)
> +               return -ENOSYS;
> +
> +       return ops->get_count(dev, count);

I'm not too keen on get_count(). Isn't this required to be in
milliiseconds now? If so, how about get_ms()?

> +}
> +
> +int timer_get_clock(struct udevice *dev, unsigned long *freq)
> +{
> +       const struct dm_timer_ops *ops = device_get_ops(dev);
> +
> +       if (!ops->get_clock)
> +               return -ENOSYS;
> +
> +       return ops->get_clock(dev, freq);

Isn't this always 1000?

> +}
> +
> +UCLASS_DRIVER(timer) = {
> +       .id             = UCLASS_TIMER,
> +       .name           = "timer",
> +};
> diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
> index 2155265..ebecb5f 100644
> --- a/include/asm-generic/global_data.h
> +++ b/include/asm-generic/global_data.h
> @@ -69,6 +69,9 @@ typedef struct global_data {
>         struct udevice  *dm_root_f;     /* Pre-relocation root instance */
>         struct list_head uclass_root;   /* Head of core tree */
>  #endif
> +#ifdef CONFIG_DM_TIMER
> +       struct udevice  *dm_timer;      /* Timer instance for Driver Model */
> +#endif
>
>         const void *fdt_blob;   /* Our device tree, NULL if none */
>         void *new_fdt;          /* Relocated FDT */
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 1eeec74..aff34a4 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -56,6 +56,7 @@ enum uclass_id {
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
>         UCLASS_THERMAL,         /* Thermal sensor */
> +       UCLASS_TIMER,           /* Timer device */
>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
>         UCLASS_USB,             /* USB bus */
>         UCLASS_USB_DEV_GENERIC, /* USB generic device */
> diff --git a/include/timer.h b/include/timer.h
> new file mode 100644
> index 0000000..c18a195
> --- /dev/null
> +++ b/include/timer.h
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef _DM_TIMER_H_
> +#define _DM_TIMER_H_
> +
> +/*
> + * Get the current timer count
> + *
> + * @dev: The Timer device
> + * @count: pointer that returns the current timer count
> + * @return: 0 if OK, -ve on error
> + */
> +int timer_get_count(struct udevice *dev, unsigned long *count);
> +/*
> + * Get the timer input clock frequency
> + *
> + * @dev: The Timer device
> + * @freq: pointer that returns the timer clock frequency
> + * @return: 0 if OK, -ve on error
> + */
> +int timer_get_clock(struct udevice *dev, unsigned long *freq);
> +
> +/*
> + * struct dm_timer_ops - Driver model Timer operations
> + *
> + * The uclass interface is implemented by all Timer devices which use
> + * driver model.
> + */
> +struct dm_timer_ops {
> +       /*
> +        * Get the current timer count
> +        *
> +        * @dev: The Timer device
> +        * @count: pointer that returns the current timer count
> +        * @return: 0 if OK, -ve on error
> +        */
> +       int (*get_count)(struct udevice *dev, unsigned long *count);
> +       /*
> +        * Get the timer input clock frequency
> +        *
> +        * @dev: The Timer device
> +        * @freq: pointer that returns the timer clock frequency
> +        * @return: 0 if OK, -ve on error
> +        */
> +       int (*get_clock)(struct udevice *dev, unsigned long *freq);
> +};
> +
> +#endif /* _DM_TIMER_H_ */
> diff --git a/lib/time.c b/lib/time.c
> index 477440d..6b7342e 100644
> --- a/lib/time.c
> +++ b/lib/time.c
> @@ -6,6 +6,9 @@
>   */
>
>  #include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
>  #include <watchdog.h>
>  #include <div64.h>
>  #include <asm/io.h>
> @@ -37,6 +40,57 @@ unsigned long notrace timer_read_counter(void)
>  extern unsigned long __weak timer_read_counter(void);
>  #endif
>
> +#ifdef CONFIG_DM_TIMER
> +static int dm_timer_init(void)

nit: need notrace on this one too.

> +{
> +       struct udevice *dev;
> +       int ret;
> +
> +       if (!gd->dm_timer) {
> +               ret = uclass_first_device(UCLASS_TIMER, &dev);
> +               if (ret)
> +                       return ret;
> +               if (!dev)
> +                       return -ENODEV;
> +               gd->dm_timer = dev;
> +       }
> +
> +       return 0;
> +}
> +
> +ulong notrace get_tbclk(void)
> +{
> +       unsigned long freq;
> +       int ret;
> +
> +       ret = dm_timer_init();
> +       if (ret)
> +               return ret;
> +
> +       ret = timer_get_clock(gd->dm_timer, &freq);
> +       if (ret)
> +               return ret;
> +
> +       return freq;
> +}
> +
> +unsigned long notrace timer_read_counter(void)
> +{
> +       unsigned long count;
> +       int ret;
> +
> +       ret = dm_timer_init();
> +       if (ret)
> +               return ret;
> +
> +       ret = timer_get_count(gd->dm_timer, &count);
> +       if (ret)
> +               return ret;
> +
> +       return count;
> +}
> +#endif /* CONFIG_DM_TIMER */
> +
>  uint64_t __weak notrace get_ticks(void)
>  {
>         unsigned long now = timer_read_counter();
> --
> 2.1.4
>

Regards,
Simon

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

* [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass
  2015-10-03 14:29   ` [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass Simon Glass
@ 2015-10-04 13:09     ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-04 13:09 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 10/03/2015 10:29 PM, Simon Glass wrote:
>> +       return ops->get_count(dev, count);
>
> I'm not too keen on get_count(). Isn't this required to be in
> milliiseconds now? If so, how about get_ms()?
>
>> +}
>> +
>> +int timer_get_clock(struct udevice *dev, unsigned long *freq)
>> +{
>> +       const struct dm_timer_ops *ops = device_get_ops(dev);
>> +
>> +       if (!ops->get_clock)
>> +               return -ENOSYS;
>> +
>> +       return ops->get_clock(dev, freq);
>
> Isn't this always 1000?
>

I will add a more specific comment on the uclass.

Implement a Timer uclass to work with lib/time.c. The timer is usually a 
32 bits free-running up counter. The get_clock() method is used to get 
the input clock frequency of the timer. The get_count() method is used 
get the current 32 bits count value. If the hardware is counting down, 
the value should be inversed inside the method. There is no real tick, 
and no timer interrupt.

Ex, the altera timer of nois2 reference design runs at 125MHz and the 
down counter value is inversed inside the get_count() method.

Thanks again for your review.

Best regards,
Thomas Chou

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

* [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (3 preceding siblings ...)
  2015-10-03  9:19 ` [U-Boot] [PATCH v3 " Thomas Chou
@ 2015-10-04 13:56 ` Thomas Chou
  2015-10-04 13:56   ` [U-Boot] [PATCH v4 2/2] nios2: convert altera timer to driver model Thomas Chou
  2015-10-06 14:14   ` [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass Simon Glass
  2015-10-08  1:03 ` [U-Boot] [PATCH v5 1/3] " Thomas Chou
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-04 13:56 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v2
  fix coding style.
v3
  add description to Kconfig as Simon suggested.
  move timer.c code to lib/time.c.
  add dm_timer dev to global data.
  remove timer_init().
  change API name get_clock.
v4
  add comment about timer hardware.

 common/board_r.c                  |  3 +++
 drivers/Kconfig                   |  2 ++
 drivers/Makefile                  |  1 +
 drivers/timer/Kconfig             | 12 +++++++++
 drivers/timer/Makefile            |  7 +++++
 drivers/timer/timer-uclass.c      | 44 +++++++++++++++++++++++++++++++
 include/asm-generic/global_data.h |  3 +++
 include/dm/uclass-id.h            |  1 +
 include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++
 lib/time.c                        | 54 +++++++++++++++++++++++++++++++++++++++
 10 files changed, 179 insertions(+)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 include/timer.h

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..aaf390e 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -290,6 +290,9 @@ static int initr_dm(void)
 	/* Save the pre-reloc driver model and start a new one */
 	gd->dm_root_f = gd->dm_root;
 	gd->dm_root = NULL;
+#ifdef CONFIG_DM_TIMER
+	gd->dm_timer = NULL;
+#endif
 	return dm_init_and_scan(false);
 }
 #endif
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..54a4c40
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,12 @@
+menu "Timer Support"
+
+config DM_TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access. It uses the same API as
+	  lib/time.c. But now implemented by the uclass. The first timer
+	  will be used. The timer is usually a 32 bits free-running up
+	  counter. There may be no real tick, and no timer interrupt.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..a24179a
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..bcf1dde
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+/*
+ * Implement a Timer uclass to work with lib/time.c. The timer is usually
+ * a 32 bits free-running up counter. The get_clock() method is used to get
+ * the input clock frequency of the timer. The get_count() method is used
+ * get the current 32 bits count value. If the hardware is counting down,
+ * the value should be inversed inside the method. There may be no real
+ * tick, and no timer interrupt.
+ */
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+int timer_get_clock(struct udevice *dev, unsigned long *freq)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_clock)
+		return -ENOSYS;
+
+	return ops->get_clock(dev, freq);
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+};
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..ebecb5f 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -69,6 +69,9 @@ typedef struct global_data {
 	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
 	struct list_head uclass_root;	/* Head of core tree */
 #endif
+#ifdef CONFIG_DM_TIMER
+	struct udevice	*dm_timer;	/* Timer instance for Driver Model */
+#endif
 
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..c18a195
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+/*
+ * Get the current timer count
+ *
+ * @dev: The Timer device
+ * @count: pointer that returns the current timer count
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_count(struct udevice *dev, unsigned long *count);
+/*
+ * Get the timer input clock frequency
+ *
+ * @dev: The Timer device
+ * @freq: pointer that returns the timer clock frequency
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_clock(struct udevice *dev, unsigned long *freq);
+
+/*
+ * struct dm_timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct dm_timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev: The Timer device
+	 * @count: pointer that returns the current timer count
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+	/*
+	 * Get the timer input clock frequency
+	 *
+	 * @dev: The Timer device
+	 * @freq: pointer that returns the timer clock frequency
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_clock)(struct udevice *dev, unsigned long *freq);
+};
+
+#endif	/* _DM_TIMER_H_ */
diff --git a/lib/time.c b/lib/time.c
index 477440d..ba063cf 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -6,6 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
 #include <watchdog.h>
 #include <div64.h>
 #include <asm/io.h>
@@ -37,6 +40,57 @@ unsigned long notrace timer_read_counter(void)
 extern unsigned long __weak timer_read_counter(void);
 #endif
 
+#ifdef CONFIG_DM_TIMER
+static int notrace dm_timer_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (!gd->dm_timer) {
+		ret = uclass_first_device(UCLASS_TIMER, &dev);
+		if (ret)
+			return ret;
+		if (!dev)
+			return -ENODEV;
+		gd->dm_timer = dev;
+	}
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	unsigned long freq;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_clock(gd->dm_timer, &freq);
+	if (ret)
+		return ret;
+
+	return freq;
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	unsigned long count;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_count(gd->dm_timer, &count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+#endif /* CONFIG_DM_TIMER */
+
 uint64_t __weak notrace get_ticks(void)
 {
 	unsigned long now = timer_read_counter();
-- 
2.1.4

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

* [U-Boot] [PATCH v4 2/2] nios2: convert altera timer to driver model
  2015-10-04 13:56 ` [U-Boot] [PATCH v4 " Thomas Chou
@ 2015-10-04 13:56   ` Thomas Chou
  2015-10-07  2:27     ` Chin Liang See
  2015-10-06 14:14   ` [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass Simon Glass
  1 sibling, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-04 13:56 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
v2
  fix coding style.
v3
  doc dts binding.
v4
  no change.

 arch/nios2/cpu/Makefile                         |   2 +-
 arch/nios2/cpu/timer.c                          |  65 --------------
 common/board_f.c                                |   3 +-
 configs/nios2-generic_defconfig                 |   2 +
 doc/device-tree-bindings/timer/altera_timer.txt |  19 ++++
 drivers/timer/Kconfig                           |   7 ++
 drivers/timer/Makefile                          |   1 +
 drivers/timer/altera_timer.c                    | 110 ++++++++++++++++++++++++
 include/configs/nios2-generic.h                 |   6 --
 9 files changed, 141 insertions(+), 74 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index d0a9ff7..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-    defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-    defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..dac0b62 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_DM_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/doc/device-tree-bindings/timer/altera_timer.txt b/doc/device-tree-bindings/timer/altera_timer.txt
new file mode 100644
index 0000000..904a584
--- /dev/null
+++ b/doc/device-tree-bindings/timer/altera_timer.txt
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "altr,timer-1.0";
+	reg = <0x00400000 0x00000020>;
+	interrupt-parent = <&cpu>;
+	interrupts = <11>;
+	clock-frequency = <125000000>;
+};
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 54a4c40..f1e681c 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -9,4 +9,11 @@ config DM_TIMER
 	  will be used. The timer is usually a 32 bits free-running up
 	  counter. There may be no real tick, and no timer interrupt.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on DM_TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index a24179a..0c7398f 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..25856d9
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long timerclk;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_get_clock(struct udevice *dev, unsigned long *freq)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+
+	*freq = plat->timerclk;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->timerclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct dm_timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+	.get_clock = altera_timer_get_clock,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 90ccbd1..ae19676 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -27,12 +27,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_COUNTS_DOWN
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass
  2015-10-04 13:56 ` [U-Boot] [PATCH v4 " Thomas Chou
  2015-10-04 13:56   ` [U-Boot] [PATCH v4 2/2] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-06 14:14   ` Simon Glass
  2015-10-08  0:55     ` Thomas Chou
  1 sibling, 1 reply; 45+ messages in thread
From: Simon Glass @ 2015-10-06 14:14 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On 4 October 2015 at 14:56, Thomas Chou <thomas@wytron.com.tw> wrote:
> Implement a Timer uclass to work with lib/time.c.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Sorry, after a lot of consideration I'd like to retract that :-(

Please see below.

> ---
> v2
>   fix coding style.
> v3
>   add description to Kconfig as Simon suggested.
>   move timer.c code to lib/time.c.
>   add dm_timer dev to global data.
>   remove timer_init().
>   change API name get_clock.
> v4
>   add comment about timer hardware.
>
>  common/board_r.c                  |  3 +++
>  drivers/Kconfig                   |  2 ++
>  drivers/Makefile                  |  1 +
>  drivers/timer/Kconfig             | 12 +++++++++
>  drivers/timer/Makefile            |  7 +++++
>  drivers/timer/timer-uclass.c      | 44 +++++++++++++++++++++++++++++++
>  include/asm-generic/global_data.h |  3 +++
>  include/dm/uclass-id.h            |  1 +
>  include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++
>  lib/time.c                        | 54 +++++++++++++++++++++++++++++++++++++++
>  10 files changed, 179 insertions(+)
>  create mode 100644 drivers/timer/Kconfig
>  create mode 100644 drivers/timer/Makefile
>  create mode 100644 drivers/timer/timer-uclass.c
>  create mode 100644 include/timer.h

Can you please split this into a patch that adds the uclass and one
that plumbs it into board_r.c?

Also can you add a patch with a sandbox timer driver and a test (in
test/dm) for the timer?

>
> diff --git a/common/board_r.c b/common/board_r.c
> index f8c1baa..aaf390e 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -290,6 +290,9 @@ static int initr_dm(void)
>         /* Save the pre-reloc driver model and start a new one */
>         gd->dm_root_f = gd->dm_root;
>         gd->dm_root = NULL;
> +#ifdef CONFIG_DM_TIMER
> +       gd->dm_timer = NULL;
> +#endif
>         return dm_init_and_scan(false);
>  }
>  #endif
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 63c92c5..f9496f7 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
>
>  source "drivers/thermal/Kconfig"
>
> +source "drivers/timer/Kconfig"
> +
>  source "drivers/tpm/Kconfig"
>
>  source "drivers/usb/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 9d0a595..692da78 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -48,6 +48,7 @@ obj-y += pcmcia/
>  obj-y += dfu/
>  obj-y += rtc/
>  obj-y += sound/
> +obj-y += timer/
>  obj-y += tpm/
>  obj-y += twserial/
>  obj-y += video/
> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
> new file mode 100644
> index 0000000..54a4c40
> --- /dev/null
> +++ b/drivers/timer/Kconfig
> @@ -0,0 +1,12 @@
> +menu "Timer Support"
> +
> +config DM_TIMER
> +       bool "Enable Driver Model for Timer drivers"
> +       depends on DM
> +       help
> +         Enable driver model for Timer access. It uses the same API as
> +         lib/time.c. But now implemented by the uclass. The first timer
> +         will be used. The timer is usually a 32 bits free-running up
> +         counter. There may be no real tick, and no timer interrupt.
> +
> +endmenu
> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
> new file mode 100644
> index 0000000..a24179a
> --- /dev/null
> +++ b/drivers/timer/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-$(CONFIG_DM_TIMER)         += timer-uclass.o
> diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
> new file mode 100644
> index 0000000..bcf1dde
> --- /dev/null
> +++ b/drivers/timer/timer-uclass.c
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
> +
> +/*
> + * Implement a Timer uclass to work with lib/time.c. The timer is usually
> + * a 32 bits free-running up counter. The get_clock() method is used to get
> + * the input clock frequency of the timer. The get_count() method is used
> + * get the current 32 bits count value. If the hardware is counting down,
> + * the value should be inversed inside the method. There may be no real
> + * tick, and no timer interrupt.
> + */
> +
> +int timer_get_count(struct udevice *dev, unsigned long *count)
> +{
> +       const struct dm_timer_ops *ops = device_get_ops(dev);
> +
> +       if (!ops->get_count)
> +               return -ENOSYS;
> +
> +       return ops->get_count(dev, count);
> +}
> +
> +int timer_get_clock(struct udevice *dev, unsigned long *freq)

Probably timer_get_rate() is better - we yes it has a clock but it is
the clock rate that we are returning.

Isn't the frequency always the same for a given timer? I think this
should be stored in the uclass private data. The timer could do this
in its probe function. Then this function can just return that value
rather than needing a driver method:

unsigned long timer_get_rate(struct udevice *dev)
{
   struct uc_priv *priv = dev_get_uclass_pric(dev);

   return priv->clock_rate;
}

> +{
> +       const struct dm_timer_ops *ops = device_get_ops(dev);
> +
> +       if (!ops->get_clock)
> +               return -ENOSYS;
> +
> +       return ops->get_clock(dev, freq);
> +}
> +
> +UCLASS_DRIVER(timer) = {
> +       .id             = UCLASS_TIMER,
> +       .name           = "timer",
> +};
> diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
> index 2155265..ebecb5f 100644
> --- a/include/asm-generic/global_data.h
> +++ b/include/asm-generic/global_data.h
> @@ -69,6 +69,9 @@ typedef struct global_data {
>         struct udevice  *dm_root_f;     /* Pre-relocation root instance */
>         struct list_head uclass_root;   /* Head of core tree */
>  #endif
> +#ifdef CONFIG_DM_TIMER
> +       struct udevice  *dm_timer;      /* Timer instance for Driver Model */
> +#endif
>
>         const void *fdt_blob;   /* Our device tree, NULL if none */
>         void *new_fdt;          /* Relocated FDT */
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 1eeec74..aff34a4 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -56,6 +56,7 @@ enum uclass_id {
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
>         UCLASS_THERMAL,         /* Thermal sensor */
> +       UCLASS_TIMER,           /* Timer device */
>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
>         UCLASS_USB,             /* USB bus */
>         UCLASS_USB_DEV_GENERIC, /* USB generic device */
> diff --git a/include/timer.h b/include/timer.h
> new file mode 100644
> index 0000000..c18a195
> --- /dev/null
> +++ b/include/timer.h
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef _DM_TIMER_H_
> +#define _DM_TIMER_H_
> +
> +/*
> + * Get the current timer count
> + *
> + * @dev: The Timer device
> + * @count: pointer that returns the current timer count
> + * @return: 0 if OK, -ve on error
> + */
> +int timer_get_count(struct udevice *dev, unsigned long *count);
> +/*
> + * Get the timer input clock frequency
> + *
> + * @dev: The Timer device
> + * @freq: pointer that returns the timer clock frequency
> + * @return: 0 if OK, -ve on error
> + */
> +int timer_get_clock(struct udevice *dev, unsigned long *freq);
> +
> +/*
> + * struct dm_timer_ops - Driver model Timer operations
> + *
> + * The uclass interface is implemented by all Timer devices which use
> + * driver model.
> + */
> +struct dm_timer_ops {
> +       /*
> +        * Get the current timer count
> +        *
> +        * @dev: The Timer device
> +        * @count: pointer that returns the current timer count
> +        * @return: 0 if OK, -ve on error
> +        */
> +       int (*get_count)(struct udevice *dev, unsigned long *count);
> +       /*
> +        * Get the timer input clock frequency
> +        *
> +        * @dev: The Timer device
> +        * @freq: pointer that returns the timer clock frequency
> +        * @return: 0 if OK, -ve on error
> +        */
> +       int (*get_clock)(struct udevice *dev, unsigned long *freq);
> +};
> +
> +#endif /* _DM_TIMER_H_ */
> diff --git a/lib/time.c b/lib/time.c
> index 477440d..ba063cf 100644
> --- a/lib/time.c
> +++ b/lib/time.c
> @@ -6,6 +6,9 @@
>   */
>
>  #include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <timer.h>
>  #include <watchdog.h>
>  #include <div64.h>
>  #include <asm/io.h>
> @@ -37,6 +40,57 @@ unsigned long notrace timer_read_counter(void)
>  extern unsigned long __weak timer_read_counter(void);
>  #endif
>
> +#ifdef CONFIG_DM_TIMER
> +static int notrace dm_timer_init(void)
> +{
> +       struct udevice *dev;
> +       int ret;
> +
> +       if (!gd->dm_timer) {
> +               ret = uclass_first_device(UCLASS_TIMER, &dev);
> +               if (ret)
> +                       return ret;
> +               if (!dev)
> +                       return -ENODEV;
> +               gd->dm_timer = dev;
> +       }
> +
> +       return 0;
> +}
> +
> +ulong notrace get_tbclk(void)
> +{
> +       unsigned long freq;
> +       int ret;
> +
> +       ret = dm_timer_init();
> +       if (ret)
> +               return ret;
> +
> +       ret = timer_get_clock(gd->dm_timer, &freq);
> +       if (ret)
> +               return ret;
> +
> +       return freq;
> +}
> +
> +unsigned long notrace timer_read_counter(void)
> +{
> +       unsigned long count;
> +       int ret;
> +
> +       ret = dm_timer_init();
> +       if (ret)
> +               return ret;
> +
> +       ret = timer_get_count(gd->dm_timer, &count);
> +       if (ret)
> +               return ret;
> +
> +       return count;
> +}
> +#endif /* CONFIG_DM_TIMER */
> +
>  uint64_t __weak notrace get_ticks(void)
>  {
>         unsigned long now = timer_read_counter();
> --
> 2.1.4
>

Regards,
Simon

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

* [U-Boot] [PATCH v4 2/2] nios2: convert altera timer to driver model
  2015-10-04 13:56   ` [U-Boot] [PATCH v4 2/2] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-07  2:27     ` Chin Liang See
  0 siblings, 0 replies; 45+ messages in thread
From: Chin Liang See @ 2015-10-07  2:27 UTC (permalink / raw)
  To: u-boot

Hi,

On Sun, 2015-10-04 at 21:56 +0800, thomas at wytron.com.tw wrote:
> Convert altera timer to driver model.
> 
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> v2
>   fix coding style.
> v3
>   doc dts binding.
> v4
>   no change.
> 
>  arch/nios2/cpu/Makefile                         |   2 +-
>  arch/nios2/cpu/timer.c                          |  65 --------------
>  common/board_f.c                                |   3 +-
>  configs/nios2-generic_defconfig                 |   2 +
>  doc/device-tree-bindings/timer/altera_timer.txt |  19 ++++
>  drivers/timer/Kconfig                           |   7 ++
>  drivers/timer/Makefile                          |   1 +
>  drivers/timer/altera_timer.c                    | 110 ++++++++++++++++++++++++
>  include/configs/nios2-generic.h                 |   6 --
>  9 files changed, 141 insertions(+), 74 deletions(-)
>  delete mode 100644 arch/nios2/cpu/timer.c
>  create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
>  create mode 100644 drivers/timer/altera_timer.c
> 

Acked-by: Chin Liang See <clsee@altera.com>

Thanks
Chin Liang

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

* [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass
  2015-10-06 14:14   ` [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass Simon Glass
@ 2015-10-08  0:55     ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-08  0:55 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 10/06/2015 10:14 PM, Simon Glass wrote:
> Hi Thomas,
>
> On 4 October 2015 at 14:56, Thomas Chou <thomas@wytron.com.tw> wrote:
>> Implement a Timer uclass to work with lib/time.c.
>>
>> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Sorry, after a lot of consideration I'd like to retract that :-(
>
> Please see below.
No worries. Your nits are welcome.

> Also can you add a patch with a sandbox timer driver and a test (in
> test/dm) for the timer?
I didn't  try sandbox before. I will learn sandbox and test. Then submit 
a patch for a sandbox timer driver.

Best regards,
Thomas

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

* [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (4 preceding siblings ...)
  2015-10-04 13:56 ` [U-Boot] [PATCH v4 " Thomas Chou
@ 2015-10-08  1:03 ` Thomas Chou
  2015-10-08  1:03   ` [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation Thomas Chou
                     ` (2 more replies)
  2015-10-09  1:17 ` [U-Boot] [PATCH v6 " Thomas Chou
                   ` (2 subsequent siblings)
  8 siblings, 3 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-08  1:03 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v2
  fix coding style.
v3
  add description to Kconfig as Simon suggested.
  move timer.c code to lib/time.c.
  add dm_timer dev to global data.
  remove timer_init().
  change API name get_clock.
v4
  add comment about timer hardware.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
  split gd->dm_timer renewal to anohter patch.

 drivers/Kconfig                   |  2 ++
 drivers/Makefile                  |  1 +
 drivers/timer/Kconfig             | 12 +++++++++
 drivers/timer/Makefile            |  7 ++++++
 drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
 include/asm-generic/global_data.h |  3 +++
 include/dm/uclass-id.h            |  1 +
 include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
 lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
 9 files changed, 169 insertions(+)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 include/timer.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..54a4c40
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,12 @@
+menu "Timer Support"
+
+config DM_TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access. It uses the same API as
+	  lib/time.c. But now implemented by the uclass. The first timer
+	  will be used. The timer is usually a 32 bits free-running up
+	  counter. There may be no real tick, and no timer interrupt.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..a24179a
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..daf19fa
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+/*
+ * Implement a Timer uclass to work with lib/time.c. The timer is usually
+ * a 32 bits free-running up counter. The get_rate() method is used to get
+ * the input clock frequency of the timer. The get_count() method is used
+ * get the current 32 bits count value. If the hardware is counting down,
+ * the value should be inversed inside the method. There may be no real
+ * tick, and no timer interrupt.
+ */
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+unsigned long timer_get_rate(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	return uc_priv->clock_rate;
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+	.per_device_auto_alloc_size = sizeof(struct timer_dev_priv),
+};
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..ebecb5f 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -69,6 +69,9 @@ typedef struct global_data {
 	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
 	struct list_head uclass_root;	/* Head of core tree */
 #endif
+#ifdef CONFIG_DM_TIMER
+	struct udevice	*dm_timer;	/* Timer instance for Driver Model */
+#endif
 
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..d5e855e
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+/*
+ * Get the current timer count
+ *
+ * @dev: The Timer device
+ * @count: pointer that returns the current timer count
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_count(struct udevice *dev, unsigned long *count);
+/*
+ * Get the timer input clock frequency
+ *
+ * @dev: The Timer device
+ * @return: the timer input clock frequency
+ */
+unsigned long timer_get_rate(struct udevice *dev);
+
+/*
+ * struct dm_timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct dm_timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev: The Timer device
+	 * @count: pointer that returns the current timer count
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+};
+
+/*
+ * struct timer_dev_priv - information about a device used by the uclass
+ *
+ * @clock_rate: the timer input clock frequency
+ */
+struct timer_dev_priv {
+	unsigned long clock_rate;
+};
+
+#endif	/* _DM_TIMER_H_ */
diff --git a/lib/time.c b/lib/time.c
index 477440d..43a5b09 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -6,6 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
 #include <watchdog.h>
 #include <div64.h>
 #include <asm/io.h>
@@ -37,6 +40,52 @@ unsigned long notrace timer_read_counter(void)
 extern unsigned long __weak timer_read_counter(void);
 #endif
 
+#ifdef CONFIG_DM_TIMER
+static int notrace dm_timer_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (!gd->dm_timer) {
+		ret = uclass_first_device(UCLASS_TIMER, &dev);
+		if (ret)
+			return ret;
+		if (!dev)
+			return -ENODEV;
+		gd->dm_timer = dev;
+	}
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	return timer_get_rate(gd->dm_timer);
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	unsigned long count;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_count(gd->dm_timer, &count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+#endif /* CONFIG_DM_TIMER */
+
 uint64_t __weak notrace get_ticks(void)
 {
 	unsigned long now = timer_read_counter();
-- 
2.1.4

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

* [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation
  2015-10-08  1:03 ` [U-Boot] [PATCH v5 1/3] " Thomas Chou
@ 2015-10-08  1:03   ` Thomas Chou
  2015-10-08 16:09     ` Simon Glass
  2015-10-08  1:03   ` [U-Boot] [PATCH v5 3/3] nios2: convert altera timer to driver model Thomas Chou
  2015-10-08 17:14   ` [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass Simon Glass
  2 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-08  1:03 UTC (permalink / raw)
  To: u-boot

Start a new dm_timer after relocation, just in case the
timer has been used in per-relocation.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
 common/board_r.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..aaf390e 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -290,6 +290,9 @@ static int initr_dm(void)
 	/* Save the pre-reloc driver model and start a new one */
 	gd->dm_root_f = gd->dm_root;
 	gd->dm_root = NULL;
+#ifdef CONFIG_DM_TIMER
+	gd->dm_timer = NULL;
+#endif
 	return dm_init_and_scan(false);
 }
 #endif
-- 
2.1.4

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

* [U-Boot] [PATCH v5 3/3] nios2: convert altera timer to driver model
  2015-10-08  1:03 ` [U-Boot] [PATCH v5 1/3] " Thomas Chou
  2015-10-08  1:03   ` [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation Thomas Chou
@ 2015-10-08  1:03   ` Thomas Chou
  2015-10-08 17:14   ` [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass Simon Glass
  2 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-08  1:03 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Chin Liang See <clsee@altera.com>
---
v2
  fix coding style.
v3
  doc dts binding.
v4
  no change.
v5
  revert to get_rate and use uclass priv to store the clock_rate.

 arch/nios2/cpu/Makefile                         |   2 +-
 arch/nios2/cpu/timer.c                          |  65 ---------------
 common/board_f.c                                |   3 +-
 configs/nios2-generic_defconfig                 |   2 +
 doc/device-tree-bindings/timer/altera_timer.txt |  19 +++++
 drivers/timer/Kconfig                           |   7 ++
 drivers/timer/Makefile                          |   1 +
 drivers/timer/altera_timer.c                    | 103 ++++++++++++++++++++++++
 include/configs/nios2-generic.h                 |   6 --
 9 files changed, 134 insertions(+), 74 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index d0a9ff7..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-    defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-    defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..dac0b62 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_DM_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/doc/device-tree-bindings/timer/altera_timer.txt b/doc/device-tree-bindings/timer/altera_timer.txt
new file mode 100644
index 0000000..904a584
--- /dev/null
+++ b/doc/device-tree-bindings/timer/altera_timer.txt
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "altr,timer-1.0";
+	reg = <0x00400000 0x00000020>;
+	interrupt-parent = <&cpu>;
+	interrupts = <11>;
+	clock-frequency = <125000000>;
+};
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 54a4c40..f1e681c 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -9,4 +9,11 @@ config DM_TIMER
 	  will be used. The timer is usually a 32 bits free-running up
 	  counter. There may be no real tick, and no timer interrupt.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on DM_TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index a24179a..0c7398f 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_TIMER)		+= timer-uclass.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..1a54fc7
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long clock_rate;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	uc_priv->clock_rate = plat->clock_rate;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->clock_rate = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct dm_timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 90ccbd1..ae19676 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -27,12 +27,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_COUNTS_DOWN
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation
  2015-10-08  1:03   ` [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation Thomas Chou
@ 2015-10-08 16:09     ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2015-10-08 16:09 UTC (permalink / raw)
  To: u-boot

On 8 October 2015 at 02:03, Thomas Chou <thomas@wytron.com.tw> wrote:
> Start a new dm_timer after relocation, just in case the
> timer has been used in per-relocation.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
>  common/board_r.c | 3 +++
>  1 file changed, 3 insertions(+)

Acked-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass
  2015-10-08  1:03 ` [U-Boot] [PATCH v5 1/3] " Thomas Chou
  2015-10-08  1:03   ` [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation Thomas Chou
  2015-10-08  1:03   ` [U-Boot] [PATCH v5 3/3] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-08 17:14   ` Simon Glass
  2015-10-09  1:19     ` Thomas Chou
  2 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2015-10-08 17:14 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On 8 October 2015 at 02:03, Thomas Chou <thomas@wytron.com.tw> wrote:
> Implement a Timer uclass to work with lib/time.c.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
> v2
>   fix coding style.
> v3
>   add description to Kconfig as Simon suggested.
>   move timer.c code to lib/time.c.
>   add dm_timer dev to global data.
>   remove timer_init().
>   change API name get_clock.
> v4
>   add comment about timer hardware.
> v5
>   revert to get_rate and use uclass priv to store the clock_rate.
>   split gd->dm_timer renewal to anohter patch.
>
>  drivers/Kconfig                   |  2 ++
>  drivers/Makefile                  |  1 +
>  drivers/timer/Kconfig             | 12 +++++++++
>  drivers/timer/Makefile            |  7 ++++++
>  drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
>  include/asm-generic/global_data.h |  3 +++
>  include/dm/uclass-id.h            |  1 +
>  include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
>  lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
>  9 files changed, 169 insertions(+)
>  create mode 100644 drivers/timer/Kconfig
>  create mode 100644 drivers/timer/Makefile
>  create mode 100644 drivers/timer/timer-uclass.c
>  create mode 100644 include/timer.h

Acked-by: Simon Glass <sjg@chromium.org>

Please see one last thing below.

>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 63c92c5..f9496f7 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
>
>  source "drivers/thermal/Kconfig"
>
> +source "drivers/timer/Kconfig"
> +
>  source "drivers/tpm/Kconfig"
>
>  source "drivers/usb/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 9d0a595..692da78 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -48,6 +48,7 @@ obj-y += pcmcia/
>  obj-y += dfu/
>  obj-y += rtc/
>  obj-y += sound/
> +obj-y += timer/
>  obj-y += tpm/
>  obj-y += twserial/
>  obj-y += video/
> diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
> new file mode 100644
> index 0000000..54a4c40
> --- /dev/null
> +++ b/drivers/timer/Kconfig
> @@ -0,0 +1,12 @@
> +menu "Timer Support"
> +
> +config DM_TIMER

One more little nit - this should be just 'TIMER'? All of the DM_...
options will eventually be removed. They indicate that driver model is
being used for a function. In your case, there is no legacy version so
you can just omit the DM_.

> +       bool "Enable Driver Model for Timer drivers"
> +       depends on DM
> +       help
> +         Enable driver model for Timer access. It uses the same API as
> +         lib/time.c. But now implemented by the uclass. The first timer
> +         will be used. The timer is usually a 32 bits free-running up
> +         counter. There may be no real tick, and no timer interrupt.
> +
> +endmenu

Regards,
Simon

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

* [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (5 preceding siblings ...)
  2015-10-08  1:03 ` [U-Boot] [PATCH v5 1/3] " Thomas Chou
@ 2015-10-09  1:17 ` Thomas Chou
  2015-10-09  1:17   ` [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation Thomas Chou
                     ` (2 more replies)
  2015-10-09  7:08 ` [U-Boot] [PATCH v7 " Thomas Chou
  2015-10-10  7:16 ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
  8 siblings, 3 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  1:17 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Simon Glass <sjg@chromium.org>
---
v2
  fix coding style.
v3
  add description to Kconfig as Simon suggested.
  move timer.c code to lib/time.c.
  add dm_timer dev to global data.
  remove timer_init().
  change API name get_clock.
v4
  add comment about timer hardware.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
  split gd->dm_timer renewal to anohter patch.
v6
  rename to CONFIG_TIMER as Simon suggested.

 drivers/Kconfig                   |  2 ++
 drivers/Makefile                  |  1 +
 drivers/timer/Kconfig             | 12 +++++++++
 drivers/timer/Makefile            |  7 ++++++
 drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
 include/asm-generic/global_data.h |  3 +++
 include/dm/uclass-id.h            |  1 +
 include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
 lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
 9 files changed, 169 insertions(+)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 include/timer.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..8e8d600
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,12 @@
+menu "Timer Support"
+
+config TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access. It uses the same API as
+	  lib/time.c. But now implemented by the uclass. The first timer
+	  will be used. The timer is usually a 32 bits free-running up
+	  counter. There may be no real tick, and no timer interrupt.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..afb0009
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_TIMER)		+= timer-uclass.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..ed7ebd6
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+/*
+ * Implement a Timer uclass to work with lib/time.c. The timer is usually
+ * a 32 bits free-running up counter. The get_rate() method is used to get
+ * the input clock frequency of the timer. The get_count() method is used
+ * get the current 32 bits count value. If the hardware is counting down,
+ * the value should be inversed inside the method. There may be no real
+ * tick, and no timer interrupt.
+ */
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct TIMER_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+unsigned long timer_get_rate(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	return uc_priv->clock_rate;
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+	.per_device_auto_alloc_size = sizeof(struct timer_dev_priv),
+};
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..4d109fb 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -69,6 +69,9 @@ typedef struct global_data {
 	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
 	struct list_head uclass_root;	/* Head of core tree */
 #endif
+#ifdef CONFIG_TIMER
+	struct udevice	*TIMER;	/* Timer instance for Driver Model */
+#endif
 
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..677b360
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+/*
+ * Get the current timer count
+ *
+ * @dev: The Timer device
+ * @count: pointer that returns the current timer count
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_count(struct udevice *dev, unsigned long *count);
+/*
+ * Get the timer input clock frequency
+ *
+ * @dev: The Timer device
+ * @return: the timer input clock frequency
+ */
+unsigned long timer_get_rate(struct udevice *dev);
+
+/*
+ * struct TIMER_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct TIMER_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev: The Timer device
+	 * @count: pointer that returns the current timer count
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+};
+
+/*
+ * struct timer_dev_priv - information about a device used by the uclass
+ *
+ * @clock_rate: the timer input clock frequency
+ */
+struct timer_dev_priv {
+	unsigned long clock_rate;
+};
+
+#endif	/* _TIMER_H_ */
diff --git a/lib/time.c b/lib/time.c
index 477440d..8665e6e 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -6,6 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
 #include <watchdog.h>
 #include <div64.h>
 #include <asm/io.h>
@@ -37,6 +40,52 @@ unsigned long notrace timer_read_counter(void)
 extern unsigned long __weak timer_read_counter(void);
 #endif
 
+#ifdef CONFIG_TIMER
+static int notrace TIMER_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (!gd->TIMER) {
+		ret = uclass_first_device(UCLASS_TIMER, &dev);
+		if (ret)
+			return ret;
+		if (!dev)
+			return -ENODEV;
+		gd->TIMER = dev;
+	}
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	int ret;
+
+	ret = TIMER_init();
+	if (ret)
+		return ret;
+
+	return timer_get_rate(gd->TIMER);
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	unsigned long count;
+	int ret;
+
+	ret = TIMER_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_count(gd->TIMER, &count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+#endif /* CONFIG_TIMER */
+
 uint64_t __weak notrace get_ticks(void)
 {
 	unsigned long now = timer_read_counter();
-- 
2.1.4

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

* [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation
  2015-10-09  1:17 ` [U-Boot] [PATCH v6 " Thomas Chou
@ 2015-10-09  1:17   ` Thomas Chou
  2015-10-09  1:32     ` Bin Meng
  2015-10-09  1:17   ` [U-Boot] [PATCH v6 3/3] nios2: convert altera timer to driver model Thomas Chou
  2015-10-09  9:36   ` [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass Simon Glass
  2 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  1:17 UTC (permalink / raw)
  To: u-boot

Start a new TIMER after relocation, just in case the
timer has been used in per-relocation.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Simon Glass <sjg@chromium.org>
---
v6
  rename to CONFIG_TIMER as Simon suggested.

 common/board_r.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..3b193b5 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -290,6 +290,9 @@ static int initr_dm(void)
 	/* Save the pre-reloc driver model and start a new one */
 	gd->dm_root_f = gd->dm_root;
 	gd->dm_root = NULL;
+#ifdef CONFIG_TIMER
+	gd->TIMER = NULL;
+#endif
 	return dm_init_and_scan(false);
 }
 #endif
-- 
2.1.4

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

* [U-Boot] [PATCH v6 3/3] nios2: convert altera timer to driver model
  2015-10-09  1:17 ` [U-Boot] [PATCH v6 " Thomas Chou
  2015-10-09  1:17   ` [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation Thomas Chou
@ 2015-10-09  1:17   ` Thomas Chou
  2015-10-09  9:36   ` [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass Simon Glass
  2 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  1:17 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Chin Liang See <clsee@altera.com>
---
v2
  fix coding style.
v3
  doc dts binding.
v4
  no change.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
v6
  rename to CONFIG_TIMER as Simon suggested.

 arch/nios2/cpu/Makefile                         |   2 +-
 arch/nios2/cpu/timer.c                          |  65 ---------------
 common/board_f.c                                |   3 +-
 configs/nios2-generic_defconfig                 |   2 +
 doc/device-tree-bindings/timer/altera_timer.txt |  19 +++++
 drivers/timer/Kconfig                           |   7 ++
 drivers/timer/Makefile                          |   1 +
 drivers/timer/altera_timer.c                    | 103 ++++++++++++++++++++++++
 include/configs/nios2-generic.h                 |   5 --
 9 files changed, 134 insertions(+), 73 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index 8bb8ded..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-		defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..505a2cf 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/doc/device-tree-bindings/timer/altera_timer.txt b/doc/device-tree-bindings/timer/altera_timer.txt
new file mode 100644
index 0000000..904a584
--- /dev/null
+++ b/doc/device-tree-bindings/timer/altera_timer.txt
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "altr,timer-1.0";
+	reg = <0x00400000 0x00000020>;
+	interrupt-parent = <&cpu>;
+	interrupts = <11>;
+	clock-frequency = <125000000>;
+};
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 8e8d600..97c4128 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -9,4 +9,11 @@ config TIMER
 	  will be used. The timer is usually a 32 bits free-running up
 	  counter. There may be no real tick, and no timer interrupt.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index afb0009..ae66c07 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_TIMER)		+= timer-uclass.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..8fe6a5f
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long clock_rate;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	uc_priv->clock_rate = plat->clock_rate;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->clock_rate = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct TIMER_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 62f7db9..c65b3b3 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -26,11 +26,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass
  2015-10-08 17:14   ` [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass Simon Glass
@ 2015-10-09  1:19     ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  1:19 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 10/09/2015 01:14 AM, Simon Glass wrote:
>> +config DM_TIMER
>
> One more little nit - this should be just 'TIMER'? All of the DM_...
> options will eventually be removed. They indicate that driver model is
> being used for a function. In your case, there is no legacy version so
> you can just omit the DM_.

Yes, I will use CONFIG_TIMER instead. Thanks a lot for your reviews.

Best regards,
Thomas

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

* [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation
  2015-10-09  1:17   ` [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation Thomas Chou
@ 2015-10-09  1:32     ` Bin Meng
  2015-10-09  5:26       ` Thomas Chou
  0 siblings, 1 reply; 45+ messages in thread
From: Bin Meng @ 2015-10-09  1:32 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Fri, Oct 9, 2015 at 9:17 AM, Thomas Chou <thomas@wytron.com.tw> wrote:
> Start a new TIMER after relocation, just in case the
> timer has been used in per-relocation.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> v6
>   rename to CONFIG_TIMER as Simon suggested.
>
>  common/board_r.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/common/board_r.c b/common/board_r.c
> index f8c1baa..3b193b5 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -290,6 +290,9 @@ static int initr_dm(void)
>         /* Save the pre-reloc driver model and start a new one */
>         gd->dm_root_f = gd->dm_root;
>         gd->dm_root = NULL;
> +#ifdef CONFIG_TIMER
> +       gd->TIMER = NULL;

Sorry for jumping in so late. But why is this TIMER all capital letters?

> +#endif
>         return dm_init_and_scan(false);
>  }
>  #endif
> --

Regards,
Bin

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

* [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation
  2015-10-09  1:32     ` Bin Meng
@ 2015-10-09  5:26       ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  5:26 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 10/09/2015 09:32 AM, Bin Meng wrote:
>> +#ifdef CONFIG_TIMER
>> +       gd->TIMER = NULL;
>
> Sorry for jumping in so late. But why is this TIMER all capital letters?

Thanks for reminding. I made wrong string replacement.

Best regards,
Thomas Chou

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

* [U-Boot] [PATCH v7 1/3] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (6 preceding siblings ...)
  2015-10-09  1:17 ` [U-Boot] [PATCH v6 " Thomas Chou
@ 2015-10-09  7:08 ` Thomas Chou
  2015-10-09  7:08   ` [U-Boot] [PATCH v7 2/3] timer: start a new dm_timer after relocation Thomas Chou
  2015-10-09  7:08   ` [U-Boot] [PATCH v7 3/3] nios2: convert altera timer to driver model Thomas Chou
  2015-10-10  7:16 ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
  8 siblings, 2 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  7:08 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Simon Glass <sjg@chromium.org>
---
v2
  fix coding style.
v3
  add description to Kconfig as Simon suggested.
  move timer.c code to lib/time.c.
  add dm_timer dev to global data.
  remove timer_init().
  change API name get_clock.
v4
  add comment about timer hardware.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
  split gd->dm_timer renewal to anohter patch.
v6
  rename to CONFIG_TIMER as Simon suggested.
v7
  fix string replacement error in v6

 drivers/Kconfig                   |  2 ++
 drivers/Makefile                  |  1 +
 drivers/timer/Kconfig             | 12 +++++++++
 drivers/timer/Makefile            |  7 ++++++
 drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
 include/asm-generic/global_data.h |  3 +++
 include/dm/uclass-id.h            |  1 +
 include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
 lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
 9 files changed, 169 insertions(+)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 include/timer.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..8e8d600
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,12 @@
+menu "Timer Support"
+
+config TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access. It uses the same API as
+	  lib/time.c. But now implemented by the uclass. The first timer
+	  will be used. The timer is usually a 32 bits free-running up
+	  counter. There may be no real tick, and no timer interrupt.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..afb0009
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_TIMER)		+= timer-uclass.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..daf19fa
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+/*
+ * Implement a Timer uclass to work with lib/time.c. The timer is usually
+ * a 32 bits free-running up counter. The get_rate() method is used to get
+ * the input clock frequency of the timer. The get_count() method is used
+ * get the current 32 bits count value. If the hardware is counting down,
+ * the value should be inversed inside the method. There may be no real
+ * tick, and no timer interrupt.
+ */
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct dm_timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+unsigned long timer_get_rate(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	return uc_priv->clock_rate;
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+	.per_device_auto_alloc_size = sizeof(struct timer_dev_priv),
+};
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..78da709 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -69,6 +69,9 @@ typedef struct global_data {
 	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
 	struct list_head uclass_root;	/* Head of core tree */
 #endif
+#ifdef CONFIG_TIMER
+	struct udevice	*dm_timer;	/* Timer instance for Driver Model */
+#endif
 
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..d5e855e
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+/*
+ * Get the current timer count
+ *
+ * @dev: The Timer device
+ * @count: pointer that returns the current timer count
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_count(struct udevice *dev, unsigned long *count);
+/*
+ * Get the timer input clock frequency
+ *
+ * @dev: The Timer device
+ * @return: the timer input clock frequency
+ */
+unsigned long timer_get_rate(struct udevice *dev);
+
+/*
+ * struct dm_timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct dm_timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev: The Timer device
+	 * @count: pointer that returns the current timer count
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+};
+
+/*
+ * struct timer_dev_priv - information about a device used by the uclass
+ *
+ * @clock_rate: the timer input clock frequency
+ */
+struct timer_dev_priv {
+	unsigned long clock_rate;
+};
+
+#endif	/* _DM_TIMER_H_ */
diff --git a/lib/time.c b/lib/time.c
index 477440d..680c8e7 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -6,6 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
 #include <watchdog.h>
 #include <div64.h>
 #include <asm/io.h>
@@ -37,6 +40,52 @@ unsigned long notrace timer_read_counter(void)
 extern unsigned long __weak timer_read_counter(void);
 #endif
 
+#ifdef CONFIG_TIMER
+static int notrace dm_timer_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (!gd->dm_timer) {
+		ret = uclass_first_device(UCLASS_TIMER, &dev);
+		if (ret)
+			return ret;
+		if (!dev)
+			return -ENODEV;
+		gd->dm_timer = dev;
+	}
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	return timer_get_rate(gd->dm_timer);
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	unsigned long count;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_count(gd->dm_timer, &count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+#endif /* CONFIG_TIMER */
+
 uint64_t __weak notrace get_ticks(void)
 {
 	unsigned long now = timer_read_counter();
-- 
2.1.4

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

* [U-Boot] [PATCH v7 2/3] timer: start a new dm_timer after relocation
  2015-10-09  7:08 ` [U-Boot] [PATCH v7 " Thomas Chou
@ 2015-10-09  7:08   ` Thomas Chou
  2015-10-09  7:08   ` [U-Boot] [PATCH v7 3/3] nios2: convert altera timer to driver model Thomas Chou
  1 sibling, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  7:08 UTC (permalink / raw)
  To: u-boot

Start a new dm_timer after relocation, just in case the
timer has been used in per-relocation.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Simon Glass <sjg@chromium.org>
---
v6
  rename to CONFIG_TIMER as Simon suggested.
v7
  fix string replacement error in v6

 common/board_r.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..d22118b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -290,6 +290,9 @@ static int initr_dm(void)
 	/* Save the pre-reloc driver model and start a new one */
 	gd->dm_root_f = gd->dm_root;
 	gd->dm_root = NULL;
+#ifdef CONFIG_TIMER
+	gd->dm_timer = NULL;
+#endif
 	return dm_init_and_scan(false);
 }
 #endif
-- 
2.1.4

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

* [U-Boot] [PATCH v7 3/3] nios2: convert altera timer to driver model
  2015-10-09  7:08 ` [U-Boot] [PATCH v7 " Thomas Chou
  2015-10-09  7:08   ` [U-Boot] [PATCH v7 2/3] timer: start a new dm_timer after relocation Thomas Chou
@ 2015-10-09  7:08   ` Thomas Chou
  1 sibling, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09  7:08 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Chin Liang See <clsee@altera.com>
---
v2
  fix coding style.
v3
  doc dts binding.
v4
  no change.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
v6
  rename to CONFIG_TIMER as Simon suggested.
v7
  fix string replacement error in v6.

 arch/nios2/cpu/Makefile                         |   2 +-
 arch/nios2/cpu/timer.c                          |  65 ---------------
 common/board_f.c                                |   3 +-
 configs/nios2-generic_defconfig                 |   2 +
 doc/device-tree-bindings/timer/altera_timer.txt |  19 +++++
 drivers/timer/Kconfig                           |   7 ++
 drivers/timer/Makefile                          |   1 +
 drivers/timer/altera_timer.c                    | 103 ++++++++++++++++++++++++
 include/configs/nios2-generic.h                 |   5 --
 9 files changed, 134 insertions(+), 73 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index 8bb8ded..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-		defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..505a2cf 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/doc/device-tree-bindings/timer/altera_timer.txt b/doc/device-tree-bindings/timer/altera_timer.txt
new file mode 100644
index 0000000..904a584
--- /dev/null
+++ b/doc/device-tree-bindings/timer/altera_timer.txt
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "altr,timer-1.0";
+	reg = <0x00400000 0x00000020>;
+	interrupt-parent = <&cpu>;
+	interrupts = <11>;
+	clock-frequency = <125000000>;
+};
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 8e8d600..97c4128 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -9,4 +9,11 @@ config TIMER
 	  will be used. The timer is usually a 32 bits free-running up
 	  counter. There may be no real tick, and no timer interrupt.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index afb0009..ae66c07 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_TIMER)		+= timer-uclass.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..1a54fc7
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long clock_rate;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	uc_priv->clock_rate = plat->clock_rate;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->clock_rate = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct dm_timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 62f7db9..c65b3b3 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -26,11 +26,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass
  2015-10-09  1:17 ` [U-Boot] [PATCH v6 " Thomas Chou
  2015-10-09  1:17   ` [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation Thomas Chou
  2015-10-09  1:17   ` [U-Boot] [PATCH v6 3/3] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-09  9:36   ` Simon Glass
  2015-10-09 10:44     ` Thomas Chou
  2 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2015-10-09  9:36 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On 9 October 2015 at 02:17, Thomas Chou <thomas@wytron.com.tw> wrote:
> Implement a Timer uclass to work with lib/time.c.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> v2
>   fix coding style.
> v3
>   add description to Kconfig as Simon suggested.
>   move timer.c code to lib/time.c.
>   add dm_timer dev to global data.
>   remove timer_init().
>   change API name get_clock.
> v4
>   add comment about timer hardware.
> v5
>   revert to get_rate and use uclass priv to store the clock_rate.
>   split gd->dm_timer renewal to anohter patch.
> v6
>   rename to CONFIG_TIMER as Simon suggested.

But note you have changed this too broadly - 'TIMER' appears in
several places where it should be 'timer'.
>
>  drivers/Kconfig                   |  2 ++
>  drivers/Makefile                  |  1 +
>  drivers/timer/Kconfig             | 12 +++++++++
>  drivers/timer/Makefile            |  7 ++++++
>  drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
>  include/asm-generic/global_data.h |  3 +++
>  include/dm/uclass-id.h            |  1 +
>  include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
>  lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
>  9 files changed, 169 insertions(+)
>  create mode 100644 drivers/timer/Kconfig
>  create mode 100644 drivers/timer/Makefile
>  create mode 100644 drivers/timer/timer-uclass.c
>  create mode 100644 include/timer.h
>

Regards,
Simon

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

* [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass
  2015-10-09  9:36   ` [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass Simon Glass
@ 2015-10-09 10:44     ` Thomas Chou
  2015-10-09 10:46       ` Bin Meng
  0 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-09 10:44 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 10/09/2015 05:36 PM, Simon Glass wrote:
>> v6
>>    rename to CONFIG_TIMER as Simon suggested.
>
> But note you have changed this too broadly - 'TIMER' appears in
> several places where it should be 'timer'.

Sorry, I made a mistake in the string replacement. Please see v7.

Best regards,
Thomas

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

* [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass
  2015-10-09 10:44     ` Thomas Chou
@ 2015-10-09 10:46       ` Bin Meng
  2015-10-09 13:18         ` Thomas Chou
  0 siblings, 1 reply; 45+ messages in thread
From: Bin Meng @ 2015-10-09 10:46 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Fri, Oct 9, 2015 at 6:44 PM, Thomas Chou <thomas@wytron.com.tw> wrote:
> Hi Simon,
>
> On 10/09/2015 05:36 PM, Simon Glass wrote:
>>>
>>> v6
>>>    rename to CONFIG_TIMER as Simon suggested.
>>
>>
>> But note you have changed this too broadly - 'TIMER' appears in
>> several places where it should be 'timer'.
>
>
> Sorry, I made a mistake in the string replacement. Please see v7.
>

But in v7, it is gd->dm_timer. I think it should be gd->timer?

Regards,
Bin

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

* [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass
  2015-10-09 10:46       ` Bin Meng
@ 2015-10-09 13:18         ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-09 13:18 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 10/09/2015 06:46 PM, Bin Meng wrote:
> But in v7, it is gd->dm_timer. I think it should be gd->timer?

I think it is only CONFIG_DM_TIMER, that Simon suggested to change.

In the gd structure, I keep it neighbor to dm_root. In the initr_dm(), 
they are set to NULL similarly. So I would keep dm_ prefix.

I also spelled the macro in include/timer.h as
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
because some archs have their timer.h.

Best regards,
Thomas

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

* [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass
  2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
                   ` (7 preceding siblings ...)
  2015-10-09  7:08 ` [U-Boot] [PATCH v7 " Thomas Chou
@ 2015-10-10  7:16 ` Thomas Chou
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation Thomas Chou
                     ` (2 more replies)
  8 siblings, 3 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-10  7:16 UTC (permalink / raw)
  To: u-boot

Implement a Timer uclass to work with lib/time.c.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Simon Glass <sjg@chromium.org>
---
v2
  fix coding style.
v3
  add description to Kconfig as Simon suggested.
  move timer.c code to lib/time.c.
  add dm_timer dev to global data.
  remove timer_init().
  change API name get_clock.
v4
  add comment about timer hardware.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
  split gd->dm_timer renewal to anohter patch.
v6
  rename to CONFIG_TIMER as Simon suggested.
v7
  fix string replacement error in v6
v8
  replace all dm_timer with timer.

 drivers/Kconfig                   |  2 ++
 drivers/Makefile                  |  1 +
 drivers/timer/Kconfig             | 12 +++++++++
 drivers/timer/Makefile            |  7 ++++++
 drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
 include/asm-generic/global_data.h |  3 +++
 include/dm/uclass-id.h            |  1 +
 include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
 lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
 9 files changed, 169 insertions(+)
 create mode 100644 drivers/timer/Kconfig
 create mode 100644 drivers/timer/Makefile
 create mode 100644 drivers/timer/timer-uclass.c
 create mode 100644 include/timer.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 63c92c5..f9496f7 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/timer/Kconfig"
+
 source "drivers/tpm/Kconfig"
 
 source "drivers/usb/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d0a595..692da78 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -48,6 +48,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
 obj-y += video/
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
new file mode 100644
index 0000000..8e8d600
--- /dev/null
+++ b/drivers/timer/Kconfig
@@ -0,0 +1,12 @@
+menu "Timer Support"
+
+config TIMER
+	bool "Enable Driver Model for Timer drivers"
+	depends on DM
+	help
+	  Enable driver model for Timer access. It uses the same API as
+	  lib/time.c. But now implemented by the uclass. The first timer
+	  will be used. The timer is usually a 32 bits free-running up
+	  counter. There may be no real tick, and no timer interrupt.
+
+endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
new file mode 100644
index 0000000..afb0009
--- /dev/null
+++ b/drivers/timer/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_TIMER)		+= timer-uclass.o
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
new file mode 100644
index 0000000..daf19fa
--- /dev/null
+++ b/drivers/timer/timer-uclass.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+
+/*
+ * Implement a Timer uclass to work with lib/time.c. The timer is usually
+ * a 32 bits free-running up counter. The get_rate() method is used to get
+ * the input clock frequency of the timer. The get_count() method is used
+ * get the current 32 bits count value. If the hardware is counting down,
+ * the value should be inversed inside the method. There may be no real
+ * tick, and no timer interrupt.
+ */
+
+int timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	const struct timer_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev, count);
+}
+
+unsigned long timer_get_rate(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	return uc_priv->clock_rate;
+}
+
+UCLASS_DRIVER(timer) = {
+	.id		= UCLASS_TIMER,
+	.name		= "timer",
+	.per_device_auto_alloc_size = sizeof(struct timer_dev_priv),
+};
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..78da709 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -69,6 +69,9 @@ typedef struct global_data {
 	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
 	struct list_head uclass_root;	/* Head of core tree */
 #endif
+#ifdef CONFIG_TIMER
+	struct udevice	*timer;	/* Timer instance for Driver Model */
+#endif
 
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 1eeec74..aff34a4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
+	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..d5e855e
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_TIMER_H_
+#define _DM_TIMER_H_
+
+/*
+ * Get the current timer count
+ *
+ * @dev: The Timer device
+ * @count: pointer that returns the current timer count
+ * @return: 0 if OK, -ve on error
+ */
+int timer_get_count(struct udevice *dev, unsigned long *count);
+/*
+ * Get the timer input clock frequency
+ *
+ * @dev: The Timer device
+ * @return: the timer input clock frequency
+ */
+unsigned long timer_get_rate(struct udevice *dev);
+
+/*
+ * struct timer_ops - Driver model Timer operations
+ *
+ * The uclass interface is implemented by all Timer devices which use
+ * driver model.
+ */
+struct timer_ops {
+	/*
+	 * Get the current timer count
+	 *
+	 * @dev: The Timer device
+	 * @count: pointer that returns the current timer count
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev, unsigned long *count);
+};
+
+/*
+ * struct timer_dev_priv - information about a device used by the uclass
+ *
+ * @clock_rate: the timer input clock frequency
+ */
+struct timer_dev_priv {
+	unsigned long clock_rate;
+};
+
+#endif	/* _DM_TIMER_H_ */
diff --git a/lib/time.c b/lib/time.c
index 477440d..680c8e7 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -6,6 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
 #include <watchdog.h>
 #include <div64.h>
 #include <asm/io.h>
@@ -37,6 +40,52 @@ unsigned long notrace timer_read_counter(void)
 extern unsigned long __weak timer_read_counter(void);
 #endif
 
+#ifdef CONFIG_TIMER
+static int notrace dm_timer_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (!gd->timer) {
+		ret = uclass_first_device(UCLASS_TIMER, &dev);
+		if (ret)
+			return ret;
+		if (!dev)
+			return -ENODEV;
+		gd->timer = dev;
+	}
+
+	return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	return timer_get_rate(gd->timer);
+}
+
+unsigned long notrace timer_read_counter(void)
+{
+	unsigned long count;
+	int ret;
+
+	ret = dm_timer_init();
+	if (ret)
+		return ret;
+
+	ret = timer_get_count(gd->timer, &count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+#endif /* CONFIG_TIMER */
+
 uint64_t __weak notrace get_ticks(void)
 {
 	unsigned long now = timer_read_counter();
-- 
2.1.4

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

* [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation
  2015-10-10  7:16 ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
@ 2015-10-10  7:16   ` Thomas Chou
  2015-10-13 13:17     ` Thomas Chou
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 3/3] nios2: convert altera timer to driver model Thomas Chou
  2015-10-13 13:17   ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
  2 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-10  7:16 UTC (permalink / raw)
  To: u-boot

Start a new timer after relocation, just in case the
timer has been used in per-relocation.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Simon Glass <sjg@chromium.org>
---
v6
  rename to CONFIG_TIMER as Simon suggested.
v7
  fix string replacement error in v6
v8
  replace all dm_timer with timer.

 common/board_r.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index f8c1baa..d22118b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -290,6 +290,9 @@ static int initr_dm(void)
 	/* Save the pre-reloc driver model and start a new one */
 	gd->dm_root_f = gd->dm_root;
 	gd->dm_root = NULL;
+#ifdef CONFIG_TIMER
+	gd->timer = NULL;
+#endif
 	return dm_init_and_scan(false);
 }
 #endif
-- 
2.1.4

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

* [U-Boot] [PATCH v8 3/3] nios2: convert altera timer to driver model
  2015-10-10  7:16 ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation Thomas Chou
@ 2015-10-10  7:16   ` Thomas Chou
  2015-10-13 13:17     ` Thomas Chou
  2015-10-13 13:17   ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
  2 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-10  7:16 UTC (permalink / raw)
  To: u-boot

Convert altera timer to driver model.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Acked-by: Chin Liang See <clsee@altera.com>
---
v2
  fix coding style.
v3
  doc dts binding.
v4
  no change.
v5
  revert to get_rate and use uclass priv to store the clock_rate.
v6
  rename to CONFIG_TIMER as Simon suggested.
v7
  fix string replacement error in v6.
v8
  replace all dm_timer with timer.

 arch/nios2/cpu/Makefile                         |   2 +-
 arch/nios2/cpu/timer.c                          |  65 ---------------
 common/board_f.c                                |   3 +-
 configs/nios2-generic_defconfig                 |   2 +
 doc/device-tree-bindings/timer/altera_timer.txt |  19 +++++
 drivers/timer/Kconfig                           |   7 ++
 drivers/timer/Makefile                          |   1 +
 drivers/timer/altera_timer.c                    | 103 ++++++++++++++++++++++++
 include/configs/nios2-generic.h                 |   5 --
 9 files changed, 134 insertions(+), 73 deletions(-)
 delete mode 100644 arch/nios2/cpu/timer.c
 create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
 create mode 100644 drivers/timer/altera_timer.c

diff --git a/arch/nios2/cpu/Makefile b/arch/nios2/cpu/Makefile
index c85e261..3fe7847 100644
--- a/arch/nios2/cpu/Makefile
+++ b/arch/nios2/cpu/Makefile
@@ -7,5 +7,5 @@
 
 extra-y	= start.o
 obj-y	= exceptions.o
-obj-y	+= cpu.o interrupts.o sysid.o timer.o traps.o
+obj-y	+= cpu.o interrupts.o sysid.o traps.o
 obj-y	+= fdt.o
diff --git a/arch/nios2/cpu/timer.c b/arch/nios2/cpu/timer.c
deleted file mode 100644
index b8aa9dd..0000000
--- a/arch/nios2/cpu/timer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
- *
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/nios2.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-struct nios_timer {
-	u32	status;		/* Timer status reg */
-	u32	control;	/* Timer control reg */
-	u32	periodl;	/* Timeout period low */
-	u32	periodh;	/* Timeout period high */
-	u32	snapl;		/* Snapshot low */
-	u32	snaph;		/* Snapshot high */
-};
-
-/* status register */
-#define NIOS_TIMER_TO		(1 << 0)	/* Timeout */
-#define NIOS_TIMER_RUN		(1 << 1)	/* Timer running */
-
-/* control register */
-#define NIOS_TIMER_ITO		(1 << 0)	/* Timeout interrupt enable */
-#define NIOS_TIMER_CONT		(1 << 1)	/* Continuous mode */
-#define NIOS_TIMER_START	(1 << 2)	/* Start timer */
-#define NIOS_TIMER_STOP		(1 << 3)	/* Stop timer */
-
-/*************************************************************************/
-unsigned long notrace timer_read_counter(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-	u32 val;
-
-	/* Trigger update */
-	writel(0x0, &tmr->snapl);
-
-	/* Read timer value */
-	val = readl(&tmr->snapl) & 0xffff;
-	val |= (readl(&tmr->snaph) & 0xffff) << 16;
-
-	return ~val;
-}
-
-int timer_init(void)
-{
-	struct nios_timer *tmr = (struct nios_timer *)CONFIG_SYS_TIMER_BASE;
-
-	writel(0, &tmr->status);
-	writel(0, &tmr->control);
-	writel(NIOS_TIMER_STOP, &tmr->control);
-
-	writel(0xffff, &tmr->periodl);
-	writel(0xffff, &tmr->periodh);
-
-	writel(NIOS_TIMER_CONT | NIOS_TIMER_START, &tmr->control);
-
-	return 0;
-}
diff --git a/common/board_f.c b/common/board_f.c
index 8bb8ded..613332e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -795,8 +795,7 @@ static init_fnc_t init_sequence_f[] = {
 	init_timebase,
 #endif
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
-		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
-		defined(CONFIG_NIOS2)
+		defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
 	timer_init,		/* initialize timer */
 #endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 707ee33..505a2cf 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,3 +18,5 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
+CONFIG_TIMER=y
+CONFIG_ALTERA_TIMER=y
diff --git a/doc/device-tree-bindings/timer/altera_timer.txt b/doc/device-tree-bindings/timer/altera_timer.txt
new file mode 100644
index 0000000..904a584
--- /dev/null
+++ b/doc/device-tree-bindings/timer/altera_timer.txt
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "altr,timer-1.0";
+	reg = <0x00400000 0x00000020>;
+	interrupt-parent = <&cpu>;
+	interrupts = <11>;
+	clock-frequency = <125000000>;
+};
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 8e8d600..97c4128 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -9,4 +9,11 @@ config TIMER
 	  will be used. The timer is usually a 32 bits free-running up
 	  counter. There may be no real tick, and no timer interrupt.
 
+config ALTERA_TIMER
+	bool "Altera Timer support"
+	depends on TIMER
+	help
+	  Select this to enable an timer for Altera devices. Please find
+	  details on the "Embedded Peripherals IP User Guide" of Altera.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index afb0009..ae66c07 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_TIMER)		+= timer-uclass.o
+obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
new file mode 100644
index 0000000..1a54fc7
--- /dev/null
+++ b/drivers/timer/altera_timer.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct altera_timer_regs {
+	u32	status;		/* Timer status reg */
+	u32	control;	/* Timer control reg */
+	u32	periodl;	/* Timeout period low */
+	u32	periodh;	/* Timeout period high */
+	u32	snapl;		/* Snapshot low */
+	u32	snaph;		/* Snapshot high */
+};
+
+struct altera_timer_platdata {
+	struct altera_timer_regs *regs;
+	unsigned long clock_rate;
+};
+
+/* control register */
+#define ALTERA_TIMER_CONT	(1 << 1)	/* Continuous mode */
+#define ALTERA_TIMER_START	(1 << 2)	/* Start timer */
+#define ALTERA_TIMER_STOP	(1 << 3)	/* Stop timer */
+
+static int altera_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+	u32 val;
+
+	/* Trigger update */
+	writel(0x0, &regs->snapl);
+
+	/* Read timer value */
+	val = readl(&regs->snapl) & 0xffff;
+	val |= (readl(&regs->snaph) & 0xffff) << 16;
+	*count = ~val;
+
+	return 0;
+}
+
+static int altera_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct altera_timer_platdata *plat = dev->platdata;
+	struct altera_timer_regs *const regs = plat->regs;
+
+	uc_priv->clock_rate = plat->clock_rate;
+
+	writel(0, &regs->status);
+	writel(0, &regs->control);
+	writel(ALTERA_TIMER_STOP, &regs->control);
+
+	writel(0xffff, &regs->periodl);
+	writel(0xffff, &regs->periodh);
+	writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
+
+	return 0;
+}
+
+static int altera_timer_ofdata_to_platdata(struct udevice *dev)
+{
+	struct altera_timer_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = ioremap(dev_get_addr(dev),
+		sizeof(struct altera_timer_regs));
+	plat->clock_rate = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+		"clock-frequency", 0);
+
+	return 0;
+}
+
+static const struct timer_ops altera_timer_ops = {
+	.get_count = altera_timer_get_count,
+};
+
+static const struct udevice_id altera_timer_ids[] = {
+	{ .compatible = "altr,timer-1.0", },
+	{ }
+};
+
+U_BOOT_DRIVER(altera_timer) = {
+	.name	= "altera_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = altera_timer_ids,
+	.ofdata_to_platdata = altera_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
+	.probe = altera_timer_probe,
+	.ops	= &altera_timer_ops,
+};
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 62f7db9..c65b3b3 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -26,11 +26,6 @@
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* Suppress console info */
 
 /*
- * TIMER
- */
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TIMER_FREQ
-
-/*
  * BOOTP options
  */
 #define CONFIG_BOOTP_BOOTFILESIZE
-- 
2.1.4

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

* [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass
  2015-10-10  7:16 ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation Thomas Chou
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 3/3] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-13 13:17   ` Thomas Chou
  2015-10-19  1:53     ` Simon Glass
  2 siblings, 1 reply; 45+ messages in thread
From: Thomas Chou @ 2015-10-13 13:17 UTC (permalink / raw)
  To: u-boot



On 10/10/2015 03:16 PM, Thomas Chou wrote:
> Implement a Timer uclass to work with lib/time.c.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> v2
>    fix coding style.
> v3
>    add description to Kconfig as Simon suggested.
>    move timer.c code to lib/time.c.
>    add dm_timer dev to global data.
>    remove timer_init().
>    change API name get_clock.
> v4
>    add comment about timer hardware.
> v5
>    revert to get_rate and use uclass priv to store the clock_rate.
>    split gd->dm_timer renewal to anohter patch.
> v6
>    rename to CONFIG_TIMER as Simon suggested.
> v7
>    fix string replacement error in v6
> v8
>    replace all dm_timer with timer.
>
>   drivers/Kconfig                   |  2 ++
>   drivers/Makefile                  |  1 +
>   drivers/timer/Kconfig             | 12 +++++++++
>   drivers/timer/Makefile            |  7 ++++++
>   drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
>   include/asm-generic/global_data.h |  3 +++
>   include/dm/uclass-id.h            |  1 +
>   include/timer.h                   | 52 +++++++++++++++++++++++++++++++++++++++
>   lib/time.c                        | 49 ++++++++++++++++++++++++++++++++++++
>   9 files changed, 169 insertions(+)
>   create mode 100644 drivers/timer/Kconfig
>   create mode 100644 drivers/timer/Makefile
>   create mode 100644 drivers/timer/timer-uclass.c
>   create mode 100644 include/timer.h
>

Applied to u-boot-nios.

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

* [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation Thomas Chou
@ 2015-10-13 13:17     ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-13 13:17 UTC (permalink / raw)
  To: u-boot



On 10/10/2015 03:16 PM, Thomas Chou wrote:
> Start a new timer after relocation, just in case the
> timer has been used in per-relocation.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> v6
>    rename to CONFIG_TIMER as Simon suggested.
> v7
>    fix string replacement error in v6
> v8
>    replace all dm_timer with timer.
>
>   common/board_r.c | 3 +++
>   1 file changed, 3 insertions(+)
>

Applied to u-boot-nios.


> diff --git a/common/board_r.c b/common/board_r.c
> index f8c1baa..d22118b 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -290,6 +290,9 @@ static int initr_dm(void)
>   	/* Save the pre-reloc driver model and start a new one */
>   	gd->dm_root_f = gd->dm_root;
>   	gd->dm_root = NULL;
> +#ifdef CONFIG_TIMER
> +	gd->timer = NULL;
> +#endif
>   	return dm_init_and_scan(false);
>   }
>   #endif
>

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

* [U-Boot] [PATCH v8 3/3] nios2: convert altera timer to driver model
  2015-10-10  7:16   ` [U-Boot] [PATCH v8 3/3] nios2: convert altera timer to driver model Thomas Chou
@ 2015-10-13 13:17     ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-13 13:17 UTC (permalink / raw)
  To: u-boot



On 10/10/2015 03:16 PM, Thomas Chou wrote:
> Convert altera timer to driver model.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> Acked-by: Chin Liang See <clsee@altera.com>
> ---
> v2
>    fix coding style.
> v3
>    doc dts binding.
> v4
>    no change.
> v5
>    revert to get_rate and use uclass priv to store the clock_rate.
> v6
>    rename to CONFIG_TIMER as Simon suggested.
> v7
>    fix string replacement error in v6.
> v8
>    replace all dm_timer with timer.
>
>   arch/nios2/cpu/Makefile                         |   2 +-
>   arch/nios2/cpu/timer.c                          |  65 ---------------
>   common/board_f.c                                |   3 +-
>   configs/nios2-generic_defconfig                 |   2 +
>   doc/device-tree-bindings/timer/altera_timer.txt |  19 +++++
>   drivers/timer/Kconfig                           |   7 ++
>   drivers/timer/Makefile                          |   1 +
>   drivers/timer/altera_timer.c                    | 103 ++++++++++++++++++++++++
>   include/configs/nios2-generic.h                 |   5 --
>   9 files changed, 134 insertions(+), 73 deletions(-)
>   delete mode 100644 arch/nios2/cpu/timer.c
>   create mode 100644 doc/device-tree-bindings/timer/altera_timer.txt
>   create mode 100644 drivers/timer/altera_timer.c
>

Applied to u-boot-nios.

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

* [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass
  2015-10-13 13:17   ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
@ 2015-10-19  1:53     ` Simon Glass
  2015-10-19 10:54       ` Thomas Chou
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2015-10-19  1:53 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On 13 October 2015 at 07:17, Thomas Chou <thomas@wytron.com.tw> wrote:
>
>
> On 10/10/2015 03:16 PM, Thomas Chou wrote:
>>
>> Implement a Timer uclass to work with lib/time.c.
>>
>> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
>> Acked-by: Simon Glass <sjg@chromium.org>
>> ---
>> v2
>>    fix coding style.
>> v3
>>    add description to Kconfig as Simon suggested.
>>    move timer.c code to lib/time.c.
>>    add dm_timer dev to global data.
>>    remove timer_init().
>>    change API name get_clock.
>> v4
>>    add comment about timer hardware.
>> v5
>>    revert to get_rate and use uclass priv to store the clock_rate.
>>    split gd->dm_timer renewal to anohter patch.
>> v6
>>    rename to CONFIG_TIMER as Simon suggested.
>> v7
>>    fix string replacement error in v6
>> v8
>>    replace all dm_timer with timer.
>>
>>   drivers/Kconfig                   |  2 ++
>>   drivers/Makefile                  |  1 +
>>   drivers/timer/Kconfig             | 12 +++++++++
>>   drivers/timer/Makefile            |  7 ++++++
>>   drivers/timer/timer-uclass.c      | 42 +++++++++++++++++++++++++++++++
>>   include/asm-generic/global_data.h |  3 +++
>>   include/dm/uclass-id.h            |  1 +
>>   include/timer.h                   | 52
>> +++++++++++++++++++++++++++++++++++++++
>>   lib/time.c                        | 49
>> ++++++++++++++++++++++++++++++++++++
>>   9 files changed, 169 insertions(+)
>>   create mode 100644 drivers/timer/Kconfig
>>   create mode 100644 drivers/timer/Makefile
>>   create mode 100644 drivers/timer/timer-uclass.c
>>   create mode 100644 include/timer.h
>>
>
> Applied to u-boot-nios.
>

Please do create a test for this uclass using a fake sandbox timer.
Note also time_ut.c which might have some ideas.

Regards,
Simon

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

* [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass
  2015-10-19  1:53     ` Simon Glass
@ 2015-10-19 10:54       ` Thomas Chou
  0 siblings, 0 replies; 45+ messages in thread
From: Thomas Chou @ 2015-10-19 10:54 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 10/19/2015 09:53 AM, Simon Glass wrote:
> Please do create a test for this uclass using a fake sandbox timer.
> Note also time_ut.c which might have some ideas.

I am learning sandbox and working on a sandbox timer now.

Best regards,
Thomas

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

end of thread, other threads:[~2015-10-19 10:54 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-28 13:19 [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
2015-09-28 13:19 ` [U-Boot] [PATCH 2/2] nios2: convert altera timer to driver model Thomas Chou
2015-09-29  1:32 ` [U-Boot] [PATCH 1/2] dm: implement a Timer uclass Thomas Chou
2015-09-29 12:39 ` [U-Boot] [PATCH v2 " Thomas Chou
2015-09-29 12:39   ` [U-Boot] [PATCH v2 2/2] nios2: convert altera timer to driver model Thomas Chou
2015-09-30  0:27     ` Chin Liang See
2015-10-01  2:51       ` Thomas Chou
2015-10-01  9:12         ` Thomas Chou
2015-09-29 13:57   ` [U-Boot] [PATCH v2 1/2] dm: implement a Timer uclass Simon Glass
2015-10-01  7:22     ` Thomas Chou
2015-10-03  9:19 ` [U-Boot] [PATCH v3 " Thomas Chou
2015-10-03  9:19   ` [U-Boot] [PATCH v3 2/2] nios2: convert altera timer to driver model Thomas Chou
2015-10-03 14:29   ` [U-Boot] [PATCH v3 1/2] dm: implement a Timer uclass Simon Glass
2015-10-04 13:09     ` Thomas Chou
2015-10-04 13:56 ` [U-Boot] [PATCH v4 " Thomas Chou
2015-10-04 13:56   ` [U-Boot] [PATCH v4 2/2] nios2: convert altera timer to driver model Thomas Chou
2015-10-07  2:27     ` Chin Liang See
2015-10-06 14:14   ` [U-Boot] [PATCH v4 1/2] dm: implement a Timer uclass Simon Glass
2015-10-08  0:55     ` Thomas Chou
2015-10-08  1:03 ` [U-Boot] [PATCH v5 1/3] " Thomas Chou
2015-10-08  1:03   ` [U-Boot] [PATCH v5 2/3] timer: start a new dm_timer after relocation Thomas Chou
2015-10-08 16:09     ` Simon Glass
2015-10-08  1:03   ` [U-Boot] [PATCH v5 3/3] nios2: convert altera timer to driver model Thomas Chou
2015-10-08 17:14   ` [U-Boot] [PATCH v5 1/3] dm: implement a Timer uclass Simon Glass
2015-10-09  1:19     ` Thomas Chou
2015-10-09  1:17 ` [U-Boot] [PATCH v6 " Thomas Chou
2015-10-09  1:17   ` [U-Boot] [PATCH v6 2/3] timer: start a new TIMER after relocation Thomas Chou
2015-10-09  1:32     ` Bin Meng
2015-10-09  5:26       ` Thomas Chou
2015-10-09  1:17   ` [U-Boot] [PATCH v6 3/3] nios2: convert altera timer to driver model Thomas Chou
2015-10-09  9:36   ` [U-Boot] [PATCH v6 1/3] dm: implement a Timer uclass Simon Glass
2015-10-09 10:44     ` Thomas Chou
2015-10-09 10:46       ` Bin Meng
2015-10-09 13:18         ` Thomas Chou
2015-10-09  7:08 ` [U-Boot] [PATCH v7 " Thomas Chou
2015-10-09  7:08   ` [U-Boot] [PATCH v7 2/3] timer: start a new dm_timer after relocation Thomas Chou
2015-10-09  7:08   ` [U-Boot] [PATCH v7 3/3] nios2: convert altera timer to driver model Thomas Chou
2015-10-10  7:16 ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
2015-10-10  7:16   ` [U-Boot] [PATCH v8 2/3] timer: start a new timer after relocation Thomas Chou
2015-10-13 13:17     ` Thomas Chou
2015-10-10  7:16   ` [U-Boot] [PATCH v8 3/3] nios2: convert altera timer to driver model Thomas Chou
2015-10-13 13:17     ` Thomas Chou
2015-10-13 13:17   ` [U-Boot] [PATCH v8 1/3] dm: implement a Timer uclass Thomas Chou
2015-10-19  1:53     ` Simon Glass
2015-10-19 10:54       ` Thomas Chou

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.