"Das U-Boot" Source Tree
at master 95 lines 2.3 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2022 StarFive, Inc. All rights reserved. 4 * Author: Kuan Lim Lee <kuanlim.lee@starfivetech.com> 5 */ 6 7#include <clk.h> 8#include <dm.h> 9#include <time.h> 10#include <timer.h> 11#include <asm/io.h> 12#include <dm/device-internal.h> 13#include <linux/err.h> 14 15#define STF_TIMER_INT_STATUS 0x00 16#define STF_TIMER_CTL 0x04 17#define STF_TIMER_LOAD 0x08 18#define STF_TIMER_ENABLE 0x10 19#define STF_TIMER_RELOAD 0x14 20#define STF_TIMER_VALUE 0x18 21#define STF_TIMER_INT_CLR 0x20 22#define STF_TIMER_INT_MASK 0x24 23 24struct starfive_timer_priv { 25 void __iomem *base; 26 u32 timer_size; 27}; 28 29static u64 notrace starfive_get_count(struct udevice *dev) 30{ 31 struct starfive_timer_priv *priv = dev_get_priv(dev); 32 33 /* Read decrement timer value and convert to increment value */ 34 return priv->timer_size - readl(priv->base + STF_TIMER_VALUE); 35} 36 37static const struct timer_ops starfive_ops = { 38 .get_count = starfive_get_count, 39}; 40 41static int starfive_probe(struct udevice *dev) 42{ 43 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 44 struct starfive_timer_priv *priv = dev_get_priv(dev); 45 int timer_channel; 46 struct clk clk; 47 int ret; 48 49 priv->base = dev_read_addr_ptr(dev); 50 if (!priv->base) 51 return -EINVAL; 52 53 timer_channel = dev_read_u32_default(dev, "channel", 0); 54 priv->base = priv->base + (0x40 * timer_channel); 55 56 /* Get clock rate from channel selectecd*/ 57 ret = clk_get_by_index(dev, timer_channel, &clk); 58 if (ret) 59 return ret; 60 61 ret = clk_enable(&clk); 62 if (ret) 63 return ret; 64 uc_priv->clock_rate = clk_get_rate(&clk); 65 66 /* 67 * Initiate timer, channel 0 68 * Unmask Interrupt Mask 69 */ 70 writel(0, priv->base + STF_TIMER_INT_MASK); 71 /* Single run mode Setting */ 72 if (dev_read_bool(dev, "single-run")) 73 writel(1, priv->base + STF_TIMER_CTL); 74 /* Set Reload value */ 75 priv->timer_size = dev_read_u32_default(dev, "timer-size", -1U); 76 writel(priv->timer_size, priv->base + STF_TIMER_LOAD); 77 /* Enable to start timer */ 78 writel(1, priv->base + STF_TIMER_ENABLE); 79 80 return 0; 81} 82 83static const struct udevice_id starfive_ids[] = { 84 { .compatible = "starfive,jh8100-timers" }, 85 { } 86}; 87 88U_BOOT_DRIVER(jh8100_starfive_timer) = { 89 .name = "starfive_timer", 90 .id = UCLASS_TIMER, 91 .of_match = starfive_ids, 92 .probe = starfive_probe, 93 .ops = &starfive_ops, 94 .priv_auto = sizeof(struct starfive_timer_priv), 95};