uboot/drivers/timer/cadence-ttc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018 Xilinx, Inc. (Michal Simek)
   4 */
   5
   6#include <common.h>
   7#include <bootstage.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <init.h>
  11#include <timer.h>
  12#include <asm/global_data.h>
  13#include <asm/io.h>
  14#include <linux/bitops.h>
  15#include <linux/err.h>
  16
  17#define CNT_CNTRL_RESET         BIT(4)
  18
  19struct cadence_ttc_regs {
  20        u32 clk_cntrl1; /* 0x0 - Clock Control 1 */
  21        u32 clk_cntrl2; /* 0x4 - Clock Control 2 */
  22        u32 clk_cntrl3; /* 0x8 - Clock Control 3 */
  23        u32 counter_cntrl1; /* 0xC - Counter Control 1 */
  24        u32 counter_cntrl2; /* 0x10 - Counter Control 2 */
  25        u32 counter_cntrl3; /* 0x14 - Counter Control 3 */
  26        u32 counter_val1; /* 0x18 - Counter Control 1 */
  27        u32 counter_val2; /* 0x1C - Counter Control 2 */
  28        u32 counter_val3; /* 0x20 - Counter Control 3 */
  29        u32 reserved[15];
  30        u32 interrupt_enable1; /* 0x60 - Interrupt Enable 1 */
  31        u32 interrupt_enable2; /* 0x64 - Interrupt Enable 2 */
  32        u32 interrupt_enable3; /* 0x68 - Interrupt Enable 3 */
  33};
  34
  35struct cadence_ttc_priv {
  36        struct cadence_ttc_regs *regs;
  37};
  38
  39#if CONFIG_IS_ENABLED(BOOTSTAGE)
  40ulong timer_get_boot_us(void)
  41{
  42        u64 ticks = 0;
  43        u32 rate = 1;
  44        u64 us;
  45        int ret;
  46
  47        ret = dm_timer_init();
  48        if (!ret) {
  49                /* The timer is available */
  50                rate = timer_get_rate(gd->timer);
  51                timer_get_count(gd->timer, &ticks);
  52        } else {
  53                return 0;
  54        }
  55
  56        us = (ticks * 1000) / rate;
  57        return us;
  58}
  59#endif
  60
  61static u64 cadence_ttc_get_count(struct udevice *dev)
  62{
  63        struct cadence_ttc_priv *priv = dev_get_priv(dev);
  64
  65        return readl(&priv->regs->counter_val1);
  66}
  67
  68static int cadence_ttc_probe(struct udevice *dev)
  69{
  70        struct cadence_ttc_priv *priv = dev_get_priv(dev);
  71
  72        /* Disable interrupts for sure */
  73        writel(0, &priv->regs->interrupt_enable1);
  74        writel(0, &priv->regs->interrupt_enable2);
  75        writel(0, &priv->regs->interrupt_enable3);
  76
  77        /* Make sure that clocks are configured properly without prescaller */
  78        writel(0, &priv->regs->clk_cntrl1);
  79        writel(0, &priv->regs->clk_cntrl2);
  80        writel(0, &priv->regs->clk_cntrl3);
  81
  82        /* Reset and enable this counter */
  83        writel(CNT_CNTRL_RESET, &priv->regs->counter_cntrl1);
  84
  85        return 0;
  86}
  87
  88static int cadence_ttc_of_to_plat(struct udevice *dev)
  89{
  90        struct cadence_ttc_priv *priv = dev_get_priv(dev);
  91
  92        priv->regs = map_physmem(dev_read_addr(dev),
  93                                 sizeof(struct cadence_ttc_regs), MAP_NOCACHE);
  94        if (IS_ERR(priv->regs))
  95                return PTR_ERR(priv->regs);
  96
  97        return 0;
  98}
  99
 100static const struct timer_ops cadence_ttc_ops = {
 101        .get_count = cadence_ttc_get_count,
 102};
 103
 104static const struct udevice_id cadence_ttc_ids[] = {
 105        { .compatible = "cdns,ttc" },
 106        {}
 107};
 108
 109U_BOOT_DRIVER(cadence_ttc) = {
 110        .name = "cadence_ttc",
 111        .id = UCLASS_TIMER,
 112        .of_match = cadence_ttc_ids,
 113        .of_to_plat = cadence_ttc_of_to_plat,
 114        .priv_auto      = sizeof(struct cadence_ttc_priv),
 115        .probe = cadence_ttc_probe,
 116        .ops = &cadence_ttc_ops,
 117};
 118