0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include <linux/clk.h>
0030 #include <linux/clocksource.h>
0031
0032 #include "soc.h"
0033 #include "common.h"
0034 #include "control.h"
0035 #include "omap-secure.h"
0036
0037 #define REALTIME_COUNTER_BASE 0x48243200
0038 #define INCREMENTER_NUMERATOR_OFFSET 0x10
0039 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
0040 #define NUMERATOR_DENUMERATOR_MASK 0xfffff000
0041
0042 static unsigned long arch_timer_freq;
0043
0044 void set_cntfreq(void)
0045 {
0046 omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 static void __init realtime_counter_init(void)
0059 {
0060 void __iomem *base;
0061 static struct clk *sys_clk;
0062 unsigned long rate;
0063 unsigned int reg;
0064 unsigned long long num, den;
0065
0066 base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
0067 if (!base) {
0068 pr_err("%s: ioremap failed\n", __func__);
0069 return;
0070 }
0071 sys_clk = clk_get(NULL, "sys_clkin");
0072 if (IS_ERR(sys_clk)) {
0073 pr_err("%s: failed to get system clock handle\n", __func__);
0074 iounmap(base);
0075 return;
0076 }
0077
0078 rate = clk_get_rate(sys_clk);
0079
0080 if (soc_is_dra7xx()) {
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
0101 if (reg & DRA7_SPEEDSELECT_MASK) {
0102 num = 75;
0103 den = 244;
0104 goto sysclk1_based;
0105 }
0106 }
0107
0108
0109 switch (rate) {
0110 case 12000000:
0111 num = 64;
0112 den = 125;
0113 break;
0114 case 13000000:
0115 num = 768;
0116 den = 1625;
0117 break;
0118 case 19200000:
0119 num = 8;
0120 den = 25;
0121 break;
0122 case 20000000:
0123 num = 192;
0124 den = 625;
0125 break;
0126 case 26000000:
0127 num = 384;
0128 den = 1625;
0129 break;
0130 case 27000000:
0131 num = 256;
0132 den = 1125;
0133 break;
0134 case 38400000:
0135 default:
0136
0137 num = 4;
0138 den = 25;
0139 break;
0140 }
0141
0142 sysclk1_based:
0143
0144 reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
0145 NUMERATOR_DENUMERATOR_MASK;
0146 reg |= num;
0147 writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
0148
0149 reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
0150 NUMERATOR_DENUMERATOR_MASK;
0151 reg |= den;
0152 writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
0153
0154 arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
0155 set_cntfreq();
0156
0157 iounmap(base);
0158 }
0159
0160 void __init omap5_realtime_timer_init(void)
0161 {
0162 omap_clk_init();
0163 realtime_counter_init();
0164
0165 timer_probe();
0166 }