
Hi Mario,
On 24 May 2018 at 02:42, Mario Six mario.six@gdsys.cc wrote:
Add a timer driver for the MPC83xx architecture.
Signed-off-by: Mario Six mario.six@gdsys.cc
v2 -> v3:
- Got rid of the static variables
- Added driver files to MAINTAINERS
v1 -> v2:
- Removed now-superfluous comments
- Removed usage of uclass_{first,next}_device_compat
- Switched to usage of new board uclass (instead of devinfo)
MAINTAINERS | 1 + arch/powerpc/cpu/mpc83xx/cpu.c | 4 +- arch/powerpc/lib/Makefile | 4 + arch/powerpc/lib/interrupts.c | 5 +- drivers/timer/Kconfig | 7 ++ drivers/timer/Makefile | 1 + drivers/timer/mpc83xx_timer.c | 182 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 drivers/timer/mpc83xx_timer.c
[..]
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index ee2fcb1fa71..75360d81de3 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o obj-$(CONFIG_STM32_TIMER) += stm32_timer.o +obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c new file mode 100644 index 00000000000..148fb2550ca --- /dev/null +++ b/drivers/timer/mpc83xx_timer.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- (C) Copyright 2018
- Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
- */
+#include <common.h> +#include <dm.h> +#include <clk.h> +#include <timer.h> +#include <watchdog.h> +#include <board.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct mpc83xx_timer_priv {
uint decrementer_count; /* count value for 1e6/HZ microseconds */
ulong timestamp;
+};
+static inline unsigned long get_dec(void) +{
unsigned long val;
asm volatile ("mfdec %0" : "=r" (val) : );
return val;
+}
+static inline void set_dec(unsigned long val) +{
if (val)
asm volatile ("mtdec %0"::"r" (val));
+}
+/* TODO(mario.six@gdsys.cc): This should really be done by timer_init, and the
- interrupt init should go into a interrupt driver.
- */
+int interrupt_init(void) +{
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
struct udevice *csb;
struct udevice *board;
struct udevice *timer = gd->timer;
struct mpc83xx_timer_priv *timer_priv = dev_get_priv(timer);
struct clk clock;
int ret;
if (get_board(&board)) {
debug("%s: board device could not be fetched.\n", __func__);
return -ENOENT;
}
ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, board,
"csb", &csb);
if (ret) {
debug("%s: Could not retrieve CSB device (error: %d)",
__func__, ret);
return ret;
}
ret = clk_get_by_index(csb, 0, &clock);
if (ret) {
debug("%s: Could not retrieve clock (error: %d)",
__func__, ret);
return ret;
}
timer_priv->decrementer_count = (clk_get_rate(&clock) / 4)
/ CONFIG_SYS_HZ;
/* Enable e300 time base */
setbits_be32(&immr->sysconf.spcr, 0x00400000);
set_dec(timer_priv->decrementer_count);
set_msr(get_msr() | MSR_EE);
return 0;
+}
+void timer_interrupt(struct pt_regs *regs) +{
struct udevice *timer = gd->timer;
struct mpc83xx_timer_priv *priv = dev_get_priv(timer);
/* Restore Decrementer Count */
set_dec(priv->decrementer_count);
priv->timestamp++;
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
WATCHDOG_RESET();
+#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
+#ifdef CONFIG_LED_STATUS
status_led_tick(priv->timestamp);
+#endif /* CONFIG_LED_STATUS */
+#ifdef CONFIG_SHOW_ACTIVITY
board_show_activity(priv->timestamp);
+#endif /* CONFIG_SHOW_ACTIVITY */ +}
+ulong get_timer(ulong base)
How come you are defining that? The standard one should work, and it calls get_ticks() which should call your driver.
Regards, Simon