1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw> 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <dm/lists.h> 9 #include <dm/device-internal.h> 10 #include <dm/root.h> 11 #include <clk.h> 12 #include <errno.h> 13 #include <timer.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 /* 18 * Implement a timer uclass to work with lib/time.c. The timer is usually 19 * a 32/64 bits free-running up counter. The get_rate() method is used to get 20 * the input clock frequency of the timer. The get_count() method is used 21 * to get the current 64 bits count value. If the hardware is counting down, 22 * the value should be inversed inside the method. There may be no real 23 * tick, and no timer interrupt. 24 */ 25 26 int notrace timer_get_count(struct udevice *dev, u64 *count) 27 { 28 const struct timer_ops *ops = device_get_ops(dev); 29 30 if (!ops->get_count) 31 return -ENOSYS; 32 33 return ops->get_count(dev, count); 34 } 35 36 unsigned long notrace timer_get_rate(struct udevice *dev) 37 { 38 struct timer_dev_priv *uc_priv = dev->uclass_priv; 39 40 return uc_priv->clock_rate; 41 } 42 43 static int timer_pre_probe(struct udevice *dev) 44 { 45 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 46 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 47 struct clk timer_clk; 48 int err; 49 ulong ret; 50 51 err = clk_get_by_index(dev, 0, &timer_clk); 52 if (!err) { 53 ret = clk_get_rate(&timer_clk); 54 if (IS_ERR_VALUE(ret)) 55 return ret; 56 uc_priv->clock_rate = ret; 57 } else { 58 uc_priv->clock_rate = 59 dev_read_u32_default(dev, "clock-frequency", 0); 60 } 61 #endif 62 63 return 0; 64 } 65 66 static int timer_post_probe(struct udevice *dev) 67 { 68 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 69 70 if (!uc_priv->clock_rate) 71 return -EINVAL; 72 73 return 0; 74 } 75 76 u64 timer_conv_64(u32 count) 77 { 78 /* increment tbh if tbl has rolled over */ 79 if (count < gd->timebase_l) 80 gd->timebase_h++; 81 gd->timebase_l = count; 82 return ((u64)gd->timebase_h << 32) | gd->timebase_l; 83 } 84 85 int notrace dm_timer_init(void) 86 { 87 struct udevice *dev = NULL; 88 __maybe_unused ofnode node; 89 int ret; 90 91 if (gd->timer) 92 return 0; 93 94 /* 95 * Directly access gd->dm_root to suppress error messages, if the 96 * virtual root driver does not yet exist. 97 */ 98 if (gd->dm_root == NULL) 99 return -EAGAIN; 100 101 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 102 /* Check for a chosen timer to be used for tick */ 103 node = ofnode_get_chosen_node("tick-timer"); 104 105 if (ofnode_valid(node) && 106 uclass_get_device_by_ofnode(UCLASS_TIMER, node, &dev)) { 107 /* 108 * If the timer is not marked to be bound before 109 * relocation, bind it anyway. 110 */ 111 if (!lists_bind_fdt(dm_root(), node, &dev)) { 112 ret = device_probe(dev); 113 if (ret) 114 return ret; 115 } 116 } 117 #endif 118 119 if (!dev) { 120 /* Fall back to the first available timer */ 121 ret = uclass_first_device_err(UCLASS_TIMER, &dev); 122 if (ret) 123 return ret; 124 } 125 126 if (dev) { 127 gd->timer = dev; 128 return 0; 129 } 130 131 return -ENODEV; 132 } 133 134 UCLASS_DRIVER(timer) = { 135 .id = UCLASS_TIMER, 136 .name = "timer", 137 .pre_probe = timer_pre_probe, 138 .flags = DM_UC_FLAG_SEQ_ALIAS, 139 .post_probe = timer_post_probe, 140 .per_device_auto_alloc_size = sizeof(struct timer_dev_priv), 141 }; 142