| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * (C) Copyright 2009 Faraday Technology |
| * Po-Yu Chuang <ratbert@faraday-tech.com> |
| * |
| * 23/08/2022 Port to DM |
| */ |
| #include <dm.h> |
| #include <log.h> |
| #include <timer.h> |
| #include <asm/io.h> |
| #include <dm/ofnode.h> |
| #include <faraday/fttmr010.h> |
| #include <asm/global_data.h> |
| |
| #define TIMER_LOAD_VAL 0xffffffff |
| |
| struct fttmr010_timer_priv { |
| struct fttmr010 __iomem *regs; |
| }; |
| |
| static u64 fttmr010_timer_get_count(struct udevice *dev) |
| { |
| struct fttmr010_timer_priv *priv = dev_get_priv(dev); |
| struct fttmr010 *tmr = priv->regs; |
| u32 now = TIMER_LOAD_VAL - readl(&tmr->timer3_counter); |
| |
| /* increment tbu if tbl has rolled over */ |
| if (now < gd->arch.tbl) |
| gd->arch.tbu++; |
| gd->arch.tbl = now; |
| |
| return ((u64)gd->arch.tbu << 32) | gd->arch.tbl; |
| } |
| |
| static int fttmr010_timer_probe(struct udevice *dev) |
| { |
| struct fttmr010_timer_priv *priv = dev_get_priv(dev); |
| struct fttmr010 *tmr; |
| unsigned int cr; |
| |
| priv->regs = dev_read_addr_ptr(dev); |
| if (!priv->regs) |
| return -EINVAL; |
| tmr = priv->regs; |
| |
| debug("Faraday FTTMR010 timer revision 0x%08X\n", readl(&tmr->revision)); |
| |
| /* disable timers */ |
| writel(0, &tmr->cr); |
| |
| /* setup timer */ |
| writel(TIMER_LOAD_VAL, &tmr->timer3_load); |
| writel(TIMER_LOAD_VAL, &tmr->timer3_counter); |
| writel(0, &tmr->timer3_match1); |
| writel(0, &tmr->timer3_match2); |
| |
| /* we don't want timer to issue interrupts */ |
| writel(FTTMR010_TM3_MATCH1 | |
| FTTMR010_TM3_MATCH2 | |
| FTTMR010_TM3_OVERFLOW, |
| &tmr->interrupt_mask); |
| |
| cr = readl(&tmr->cr); |
| cr |= FTTMR010_TM3_CLOCK; /* use external clock */ |
| cr |= FTTMR010_TM3_ENABLE; |
| writel(cr, &tmr->cr); |
| |
| gd->arch.tbl = 0; |
| gd->arch.tbu = 0; |
| |
| return 0; |
| } |
| |
| static const struct timer_ops fttmr010_timer_ops = { |
| .get_count = fttmr010_timer_get_count, |
| }; |
| |
| static const struct udevice_id fttmr010_timer_ids[] = { |
| { .compatible = "faraday,fttmr010-timer" }, |
| {} |
| }; |
| |
| U_BOOT_DRIVER(fttmr010_timer) = { |
| .name = "fttmr010_timer", |
| .id = UCLASS_TIMER, |
| .of_match = fttmr010_timer_ids, |
| .priv_auto = sizeof(struct fttmr010_timer_priv), |
| .probe = fttmr010_timer_probe, |
| .ops = &fttmr010_timer_ops, |
| }; |