1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2009 Faraday Technology 4 * Po-Yu Chuang <ratbert@faraday-tech.com> 5 * 6 * 23/08/2022 Port to DM 7 */ 8#include <common.h> 9#include <dm.h> 10#include <log.h> 11#include <timer.h> 12#include <asm/io.h> 13#include <dm/ofnode.h> 14#include <faraday/fttmr010.h> 15#include <asm/global_data.h> 16 17#define TIMER_LOAD_VAL 0xffffffff 18 19struct fttmr010_timer_priv { 20 struct fttmr010 __iomem *regs; 21}; 22 23static u64 fttmr010_timer_get_count(struct udevice *dev) 24{ 25 struct fttmr010_timer_priv *priv = dev_get_priv(dev); 26 struct fttmr010 *tmr = priv->regs; 27 u32 now = TIMER_LOAD_VAL - readl(&tmr->timer3_counter); 28 29 /* increment tbu if tbl has rolled over */ 30 if (now < gd->arch.tbl) 31 gd->arch.tbu++; 32 gd->arch.tbl = now; 33 34 return ((u64)gd->arch.tbu << 32) | gd->arch.tbl; 35} 36 37static int fttmr010_timer_probe(struct udevice *dev) 38{ 39 struct fttmr010_timer_priv *priv = dev_get_priv(dev); 40 struct fttmr010 *tmr; 41 unsigned int cr; 42 43 priv->regs = dev_read_addr_ptr(dev); 44 if (!priv->regs) 45 return -EINVAL; 46 tmr = priv->regs; 47 48 debug("Faraday FTTMR010 timer revision 0x%08X\n", readl(&tmr->revision)); 49 50 /* disable timers */ 51 writel(0, &tmr->cr); 52 53 /* setup timer */ 54 writel(TIMER_LOAD_VAL, &tmr->timer3_load); 55 writel(TIMER_LOAD_VAL, &tmr->timer3_counter); 56 writel(0, &tmr->timer3_match1); 57 writel(0, &tmr->timer3_match2); 58 59 /* we don't want timer to issue interrupts */ 60 writel(FTTMR010_TM3_MATCH1 | 61 FTTMR010_TM3_MATCH2 | 62 FTTMR010_TM3_OVERFLOW, 63 &tmr->interrupt_mask); 64 65 cr = readl(&tmr->cr); 66 cr |= FTTMR010_TM3_CLOCK; /* use external clock */ 67 cr |= FTTMR010_TM3_ENABLE; 68 writel(cr, &tmr->cr); 69 70 gd->arch.tbl = 0; 71 gd->arch.tbu = 0; 72 73 return 0; 74} 75 76static const struct timer_ops fttmr010_timer_ops = { 77 .get_count = fttmr010_timer_get_count, 78}; 79 80static const struct udevice_id fttmr010_timer_ids[] = { 81 { .compatible = "faraday,fttmr010-timer" }, 82 {} 83}; 84 85U_BOOT_DRIVER(fttmr010_timer) = { 86 .name = "fttmr010_timer", 87 .id = UCLASS_TIMER, 88 .of_match = fttmr010_timer_ids, 89 .priv_auto = sizeof(struct fttmr010_timer_priv), 90 .probe = fttmr010_timer_probe, 91 .ops = &fttmr010_timer_ops, 92}; 93