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

Mario Six mario.six at gdsys.cc
Mon Jun 25 09:32:20 UTC 2018


Hi Simon,

On Fri, May 25, 2018 at 4:42 AM, Simon Glass <sjg at chromium.org> wrote:
> 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.
>

I see. I wasn't aware of the fact that the default timer driver infrastructure
already does that, so I copied the old get_timer implementation over to this
driver.

I'll use the default function in v4.

> Regards,
> Simon

Best regards,
Mario


More information about the U-Boot mailing list