uboot/drivers/timer/altera_timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2000-2002
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 *
   6 * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
   7 * Scott McNutt <smcnutt@psyent.com>
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <errno.h>
  13#include <timer.h>
  14#include <asm/io.h>
  15
  16/* control register */
  17#define ALTERA_TIMER_CONT       BIT(1)  /* Continuous mode */
  18#define ALTERA_TIMER_START      BIT(2)  /* Start timer */
  19#define ALTERA_TIMER_STOP       BIT(3)  /* Stop timer */
  20
  21struct altera_timer_regs {
  22        u32     status;         /* Timer status reg */
  23        u32     control;        /* Timer control reg */
  24        u32     periodl;        /* Timeout period low */
  25        u32     periodh;        /* Timeout period high */
  26        u32     snapl;          /* Snapshot low */
  27        u32     snaph;          /* Snapshot high */
  28};
  29
  30struct altera_timer_platdata {
  31        struct altera_timer_regs *regs;
  32};
  33
  34static int altera_timer_get_count(struct udevice *dev, u64 *count)
  35{
  36        struct altera_timer_platdata *plat = dev->platdata;
  37        struct altera_timer_regs *const regs = plat->regs;
  38        u32 val;
  39
  40        /* Trigger update */
  41        writel(0x0, &regs->snapl);
  42
  43        /* Read timer value */
  44        val = readl(&regs->snapl) & 0xffff;
  45        val |= (readl(&regs->snaph) & 0xffff) << 16;
  46        *count = timer_conv_64(~val);
  47
  48        return 0;
  49}
  50
  51static int altera_timer_probe(struct udevice *dev)
  52{
  53        struct altera_timer_platdata *plat = dev->platdata;
  54        struct altera_timer_regs *const regs = plat->regs;
  55
  56        writel(0, &regs->status);
  57        writel(0, &regs->control);
  58        writel(ALTERA_TIMER_STOP, &regs->control);
  59
  60        writel(0xffff, &regs->periodl);
  61        writel(0xffff, &regs->periodh);
  62        writel(ALTERA_TIMER_CONT | ALTERA_TIMER_START, &regs->control);
  63
  64        return 0;
  65}
  66
  67static int altera_timer_ofdata_to_platdata(struct udevice *dev)
  68{
  69        struct altera_timer_platdata *plat = dev_get_platdata(dev);
  70
  71        plat->regs = map_physmem(devfdt_get_addr(dev),
  72                                 sizeof(struct altera_timer_regs),
  73                                 MAP_NOCACHE);
  74
  75        return 0;
  76}
  77
  78static const struct timer_ops altera_timer_ops = {
  79        .get_count = altera_timer_get_count,
  80};
  81
  82static const struct udevice_id altera_timer_ids[] = {
  83        { .compatible = "altr,timer-1.0" },
  84        {}
  85};
  86
  87U_BOOT_DRIVER(altera_timer) = {
  88        .name   = "altera_timer",
  89        .id     = UCLASS_TIMER,
  90        .of_match = altera_timer_ids,
  91        .ofdata_to_platdata = altera_timer_ofdata_to_platdata,
  92        .platdata_auto_alloc_size = sizeof(struct altera_timer_platdata),
  93        .probe = altera_timer_probe,
  94        .ops    = &altera_timer_ops,
  95};
  96