~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-omap2/timer.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/arch/arm/mach-omap2/timer.c
  3  *
  4  * OMAP2 GP timer support.
  5  *
  6  * Copyright (C) 2009 Nokia Corporation
  7  *
  8  * Update to use new clocksource/clockevent layers
  9  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
 10  * Copyright (C) 2007 MontaVista Software, Inc.
 11  *
 12  * Original driver:
 13  * Copyright (C) 2005 Nokia Corporation
 14  * Author: Paul Mundt <paul.mundt@nokia.com>
 15  *         Juha Yrjölä <juha.yrjola@nokia.com>
 16  * OMAP Dual-mode timer framework support by Timo Teras
 17  *
 18  * Some parts based off of TI's 24xx code:
 19  *
 20  * Copyright (C) 2004-2009 Texas Instruments, Inc.
 21  *
 22  * Roughly modelled after the OMAP1 MPU timer code.
 23  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
 24  *
 25  * This file is subject to the terms and conditions of the GNU General Public
 26  * License. See the file "COPYING" in the main directory of this archive
 27  * for more details.
 28  */
 29 #include <linux/clk.h>
 30 #include <linux/clocksource.h>
 31 
 32 #include "soc.h"
 33 #include "common.h"
 34 #include "control.h"
 35 #include "omap-secure.h"
 36 
 37 #define REALTIME_COUNTER_BASE                           0x48243200
 38 #define INCREMENTER_NUMERATOR_OFFSET                    0x10
 39 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET           0x14
 40 #define NUMERATOR_DENUMERATOR_MASK                      0xfffff000
 41 
 42 static unsigned long arch_timer_freq;
 43 
 44 void set_cntfreq(void)
 45 {
 46         omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
 47 }
 48 
 49 /*
 50  * The realtime counter also called master counter, is a free-running
 51  * counter, which is related to real time. It produces the count used
 52  * by the CPU local timer peripherals in the MPU cluster. The timer counts
 53  * at a rate of 6.144 MHz. Because the device operates on different clocks
 54  * in different power modes, the master counter shifts operation between
 55  * clocks, adjusting the increment per clock in hardware accordingly to
 56  * maintain a constant count rate.
 57  */
 58 static void __init realtime_counter_init(void)
 59 {
 60         void __iomem *base;
 61         static struct clk *sys_clk;
 62         unsigned long rate;
 63         unsigned int reg;
 64         unsigned long long num, den;
 65 
 66         base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
 67         if (!base) {
 68                 pr_err("%s: ioremap failed\n", __func__);
 69                 return;
 70         }
 71         sys_clk = clk_get(NULL, "sys_clkin");
 72         if (IS_ERR(sys_clk)) {
 73                 pr_err("%s: failed to get system clock handle\n", __func__);
 74                 iounmap(base);
 75                 return;
 76         }
 77 
 78         rate = clk_get_rate(sys_clk);
 79         clk_put(sys_clk);
 80 
 81         if (soc_is_dra7xx()) {
 82                 /*
 83                  * Errata i856 says the 32.768KHz crystal does not start at
 84                  * power on, so the CPU falls back to an emulated 32KHz clock
 85                  * based on sysclk / 610 instead. This causes the master counter
 86                  * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
 87                  * (OR sysclk * 75 / 244)
 88                  *
 89                  * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
 90                  * Of course any board built without a populated 32.768KHz
 91                  * crystal would also need this fix even if the CPU is fixed
 92                  * later.
 93                  *
 94                  * Either case can be detected by using the two speedselect bits
 95                  * If they are not 0, then the 32.768KHz clock driving the
 96                  * coarse counter that corrects the fine counter every time it
 97                  * ticks is actually rate/610 rather than 32.768KHz and we
 98                  * should compensate to avoid the 570ppm (at 20MHz, much worse
 99                  * at other rates) too fast system time.
100                  */
101                 reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
102                 if (reg & DRA7_SPEEDSELECT_MASK) {
103                         num = 75;
104                         den = 244;
105                         goto sysclk1_based;
106                 }
107         }
108 
109         /* Numerator/denumerator values refer TRM Realtime Counter section */
110         switch (rate) {
111         case 12000000:
112                 num = 64;
113                 den = 125;
114                 break;
115         case 13000000:
116                 num = 768;
117                 den = 1625;
118                 break;
119         case 19200000:
120                 num = 8;
121                 den = 25;
122                 break;
123         case 20000000:
124                 num = 192;
125                 den = 625;
126                 break;
127         case 26000000:
128                 num = 384;
129                 den = 1625;
130                 break;
131         case 27000000:
132                 num = 256;
133                 den = 1125;
134                 break;
135         case 38400000:
136         default:
137                 /* Program it for 38.4 MHz */
138                 num = 4;
139                 den = 25;
140                 break;
141         }
142 
143 sysclk1_based:
144         /* Program numerator and denumerator registers */
145         reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
146                         NUMERATOR_DENUMERATOR_MASK;
147         reg |= num;
148         writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
149 
150         reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
151                         NUMERATOR_DENUMERATOR_MASK;
152         reg |= den;
153         writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
154 
155         arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
156         set_cntfreq();
157 
158         iounmap(base);
159 }
160 
161 void __init omap5_realtime_timer_init(void)
162 {
163         omap_clk_init();
164         realtime_counter_init();
165 
166         timer_probe();
167 }
168 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php