[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