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