1 /* 2 * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <mapmem.h> 10 #include <asm/arch/timer.h> 11 #include <dt-structs.h> 12 #include <timer.h> 13 #include <asm/io.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 #if CONFIG_IS_ENABLED(OF_PLATDATA) 18 struct rockchip_timer_plat { 19 struct dtd_rockchip_rk3368_timer dtd; 20 }; 21 #endif 22 23 /* Driver private data. Contains timer id. Could be either 0 or 1. */ 24 struct rockchip_timer_priv { 25 struct rk_timer *timer; 26 }; 27 28 static int rockchip_timer_get_count(struct udevice *dev, u64 *count) 29 { 30 struct rockchip_timer_priv *priv = dev_get_priv(dev); 31 uint64_t timebase_h, timebase_l; 32 uint64_t cntr; 33 34 timebase_l = readl(&priv->timer->timer_curr_value0); 35 timebase_h = readl(&priv->timer->timer_curr_value1); 36 37 /* timers are down-counting */ 38 cntr = timebase_h << 32 | timebase_l; 39 *count = ~0ull - cntr; 40 return 0; 41 } 42 43 static int rockchip_clk_ofdata_to_platdata(struct udevice *dev) 44 { 45 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 46 struct rockchip_timer_priv *priv = dev_get_priv(dev); 47 48 priv->timer = (struct rk_timer *)devfdt_get_addr(dev); 49 #endif 50 51 return 0; 52 } 53 54 static int rockchip_timer_start(struct udevice *dev) 55 { 56 struct rockchip_timer_priv *priv = dev_get_priv(dev); 57 const uint64_t reload_val = ~0uLL; 58 const uint32_t reload_val_l = reload_val & 0xffffffff; 59 const uint32_t reload_val_h = reload_val >> 32; 60 61 /* disable timer and reset all control */ 62 writel(0, &priv->timer->timer_ctrl_reg); 63 /* write reload value */ 64 writel(reload_val_l, &priv->timer->timer_load_count0); 65 writel(reload_val_h, &priv->timer->timer_load_count1); 66 /* enable timer */ 67 writel(1, &priv->timer->timer_ctrl_reg); 68 69 return 0; 70 } 71 72 static int rockchip_timer_probe(struct udevice *dev) 73 { 74 #if CONFIG_IS_ENABLED(OF_PLATDATA) 75 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 76 struct rockchip_timer_priv *priv = dev_get_priv(dev); 77 struct rockchip_timer_plat *plat = dev_get_platdata(dev); 78 79 priv->timer = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); 80 uc_priv->clock_rate = plat->dtd.clock_frequency; 81 #endif 82 83 return rockchip_timer_start(dev); 84 } 85 86 static const struct timer_ops rockchip_timer_ops = { 87 .get_count = rockchip_timer_get_count, 88 }; 89 90 static const struct udevice_id rockchip_timer_ids[] = { 91 { .compatible = "rockchip,rk3368-timer" }, 92 {} 93 }; 94 95 U_BOOT_DRIVER(rockchip_rk3368_timer) = { 96 .name = "rockchip_rk3368_timer", 97 .id = UCLASS_TIMER, 98 .of_match = rockchip_timer_ids, 99 .probe = rockchip_timer_probe, 100 .ops = &rockchip_timer_ops, 101 .flags = DM_FLAG_PRE_RELOC, 102 .priv_auto_alloc_size = sizeof(struct rockchip_timer_priv), 103 #if CONFIG_IS_ENABLED(OF_PLATDATA) 104 .platdata_auto_alloc_size = sizeof(struct rockchip_timer_plat), 105 #endif 106 .ofdata_to_platdata = rockchip_clk_ofdata_to_platdata, 107 }; 108