[U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver

Simon Glass sjg at chromium.org
Fri May 25 02:42:07 UTC 2018


Hi Mario,

On 24 May 2018 at 02:42, Mario Six <mario.six at gdsys.cc> wrote:
> Add a timer driver for the MPC83xx architecture.
>
> Signed-off-by: Mario Six <mario.six at 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 at 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 at 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


More information about the U-Boot mailing list