linux/arch/arm/mach-omap2/timer.c
<<
>>
Prefs
   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/init.h>
  30#include <linux/time.h>
  31#include <linux/interrupt.h>
  32#include <linux/err.h>
  33#include <linux/clk.h>
  34#include <linux/delay.h>
  35#include <linux/irq.h>
  36#include <linux/clocksource.h>
  37#include <linux/clockchips.h>
  38#include <linux/slab.h>
  39#include <linux/of.h>
  40#include <linux/of_address.h>
  41#include <linux/of_irq.h>
  42#include <linux/platform_device.h>
  43#include <linux/platform_data/dmtimer-omap.h>
  44#include <linux/sched_clock.h>
  45
  46#include <asm/mach/time.h>
  47#include <asm/smp_twd.h>
  48
  49#include "omap_hwmod.h"
  50#include "omap_device.h"
  51#include <plat/counter-32k.h>
  52#include <clocksource/timer-ti-dm.h>
  53
  54#include "soc.h"
  55#include "common.h"
  56#include "control.h"
  57#include "powerdomain.h"
  58#include "omap-secure.h"
  59
  60#define REALTIME_COUNTER_BASE                           0x48243200
  61#define INCREMENTER_NUMERATOR_OFFSET                    0x10
  62#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET           0x14
  63#define NUMERATOR_DENUMERATOR_MASK                      0xfffff000
  64
  65/* Clockevent code */
  66
  67static struct omap_dm_timer clkev;
  68static struct clock_event_device clockevent_gpt;
  69
  70/* Clockevent hwmod for am335x and am437x suspend */
  71static struct omap_hwmod *clockevent_gpt_hwmod;
  72
  73/* Clockesource hwmod for am437x suspend */
  74static struct omap_hwmod *clocksource_gpt_hwmod;
  75
  76#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
  77static unsigned long arch_timer_freq;
  78
  79void set_cntfreq(void)
  80{
  81        omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
  82}
  83#endif
  84
  85static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
  86{
  87        struct clock_event_device *evt = &clockevent_gpt;
  88
  89        __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
  90
  91        evt->event_handler(evt);
  92        return IRQ_HANDLED;
  93}
  94
  95static struct irqaction omap2_gp_timer_irq = {
  96        .name           = "gp_timer",
  97        .flags          = IRQF_TIMER | IRQF_IRQPOLL,
  98        .handler        = omap2_gp_timer_interrupt,
  99};
 100
 101static int omap2_gp_timer_set_next_event(unsigned long cycles,
 102                                         struct clock_event_device *evt)
 103{
 104        __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
 105                                   0xffffffff - cycles, OMAP_TIMER_POSTED);
 106
 107        return 0;
 108}
 109
 110static int omap2_gp_timer_shutdown(struct clock_event_device *evt)
 111{
 112        __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
 113        return 0;
 114}
 115
 116static int omap2_gp_timer_set_periodic(struct clock_event_device *evt)
 117{
 118        u32 period;
 119
 120        __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
 121
 122        period = clkev.rate / HZ;
 123        period -= 1;
 124        /* Looks like we need to first set the load value separately */
 125        __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, 0xffffffff - period,
 126                              OMAP_TIMER_POSTED);
 127        __omap_dm_timer_load_start(&clkev,
 128                                   OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
 129                                   0xffffffff - period, OMAP_TIMER_POSTED);
 130        return 0;
 131}
 132
 133static void omap_clkevt_idle(struct clock_event_device *unused)
 134{
 135        if (!clockevent_gpt_hwmod)
 136                return;
 137
 138        omap_hwmod_idle(clockevent_gpt_hwmod);
 139}
 140
 141static void omap_clkevt_unidle(struct clock_event_device *unused)
 142{
 143        if (!clockevent_gpt_hwmod)
 144                return;
 145
 146        omap_hwmod_enable(clockevent_gpt_hwmod);
 147        __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
 148}
 149
 150static struct clock_event_device clockevent_gpt = {
 151        .features               = CLOCK_EVT_FEAT_PERIODIC |
 152                                  CLOCK_EVT_FEAT_ONESHOT,
 153        .rating                 = 300,
 154        .set_next_event         = omap2_gp_timer_set_next_event,
 155        .set_state_shutdown     = omap2_gp_timer_shutdown,
 156        .set_state_periodic     = omap2_gp_timer_set_periodic,
 157        .set_state_oneshot      = omap2_gp_timer_shutdown,
 158        .tick_resume            = omap2_gp_timer_shutdown,
 159};
 160
 161static const struct of_device_id omap_timer_match[] __initconst = {
 162        { .compatible = "ti,omap2420-timer", },
 163        { .compatible = "ti,omap3430-timer", },
 164        { .compatible = "ti,omap4430-timer", },
 165        { .compatible = "ti,omap5430-timer", },
 166        { .compatible = "ti,dm814-timer", },
 167        { .compatible = "ti,dm816-timer", },
 168        { .compatible = "ti,am335x-timer", },
 169        { .compatible = "ti,am335x-timer-1ms", },
 170        { }
 171};
 172
 173static int omap_timer_add_disabled_property(struct device_node *np)
 174{
 175        struct property *prop;
 176
 177        prop = kzalloc(sizeof(*prop), GFP_KERNEL);
 178        if (!prop)
 179                return -ENOMEM;
 180
 181        prop->name = "status";
 182        prop->value = "disabled";
 183        prop->length = strlen(prop->value);
 184
 185        return of_add_property(np, prop);
 186}
 187
 188static int omap_timer_update_dt(struct device_node *np)
 189{
 190        int error = 0;
 191
 192        if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
 193                error = omap_timer_add_disabled_property(np);
 194                if (error)
 195                        return error;
 196        }
 197
 198        /* No parent interconnect target module configured? */
 199        if (of_get_property(np, "ti,hwmods", NULL))
 200                return error;
 201
 202        /* Tag parent interconnect target module disabled */
 203        error = omap_timer_add_disabled_property(np->parent);
 204        if (error)
 205                return error;
 206
 207        return 0;
 208}
 209
 210/**
 211 * omap_get_timer_dt - get a timer using device-tree
 212 * @match       - device-tree match structure for matching a device type
 213 * @property    - optional timer property to match
 214 *
 215 * Helper function to get a timer during early boot using device-tree for use
 216 * as kernel system timer. Optionally, the property argument can be used to
 217 * select a timer with a specific property. Once a timer is found then mark
 218 * the timer node in device-tree as disabled, to prevent the kernel from
 219 * registering this timer as a platform device and so no one else can use it.
 220 */
 221static struct device_node * __init omap_get_timer_dt(const struct of_device_id *match,
 222                                                     const char *property)
 223{
 224        struct device_node *np;
 225        int error;
 226
 227        for_each_matching_node(np, match) {
 228                if (!of_device_is_available(np))
 229                        continue;
 230
 231                if (property && !of_get_property(np, property, NULL))
 232                        continue;
 233
 234                if (!property && (of_get_property(np, "ti,timer-alwon", NULL) ||
 235                                  of_get_property(np, "ti,timer-dsp", NULL) ||
 236                                  of_get_property(np, "ti,timer-pwm", NULL) ||
 237                                  of_get_property(np, "ti,timer-secure", NULL)))
 238                        continue;
 239
 240                error = omap_timer_update_dt(np);
 241                WARN(error, "%s: Could not update dt: %i\n", __func__, error);
 242
 243                return np;
 244        }
 245
 246        return NULL;
 247}
 248
 249/**
 250 * omap_dmtimer_init - initialisation function when device tree is used
 251 *
 252 * For secure OMAP3/DRA7xx devices, timers with device type "timer-secure"
 253 * cannot be used by the kernel as they are reserved. Therefore, to prevent the
 254 * kernel registering these devices remove them dynamically from the device
 255 * tree on boot.
 256 */
 257static void __init omap_dmtimer_init(void)
 258{
 259        struct device_node *np;
 260
 261        if (!cpu_is_omap34xx() && !soc_is_dra7xx())
 262                return;
 263
 264        /* If we are a secure device, remove any secure timer nodes */
 265        if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) {
 266                np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure");
 267                of_node_put(np);
 268        }
 269}
 270
 271/**
 272 * omap_dm_timer_get_errata - get errata flags for a timer
 273 *
 274 * Get the timer errata flags that are specific to the OMAP device being used.
 275 */
 276static u32 __init omap_dm_timer_get_errata(void)
 277{
 278        if (cpu_is_omap24xx())
 279                return 0;
 280
 281        return OMAP_TIMER_ERRATA_I103_I767;
 282}
 283
 284static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 285                                         const char *fck_source,
 286                                         const char *property,
 287                                         const char **timer_name,
 288                                         int posted)
 289{
 290        const char *oh_name = NULL;
 291        struct device_node *np;
 292        struct omap_hwmod *oh;
 293        struct clk *src;
 294        int r = 0;
 295
 296        np = omap_get_timer_dt(omap_timer_match, property);
 297        if (!np)
 298                return -ENODEV;
 299
 300        of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
 301        if (!oh_name) {
 302                of_property_read_string_index(np->parent, "ti,hwmods", 0,
 303                                              &oh_name);
 304                if (!oh_name)
 305                        return -ENODEV;
 306        }
 307
 308        timer->irq = irq_of_parse_and_map(np, 0);
 309        if (!timer->irq)
 310                return -ENXIO;
 311
 312        timer->io_base = of_iomap(np, 0);
 313
 314        timer->fclk = of_clk_get_by_name(np, "fck");
 315
 316        of_node_put(np);
 317
 318        oh = omap_hwmod_lookup(oh_name);
 319        if (!oh)
 320                return -ENODEV;
 321
 322        *timer_name = oh->name;
 323
 324        if (!timer->io_base)
 325                return -ENXIO;
 326
 327        omap_hwmod_setup_one(oh_name);
 328
 329        /* After the dmtimer is using hwmod these clocks won't be needed */
 330        if (IS_ERR_OR_NULL(timer->fclk))
 331                timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
 332        if (IS_ERR(timer->fclk))
 333                return PTR_ERR(timer->fclk);
 334
 335        src = clk_get(NULL, fck_source);
 336        if (IS_ERR(src))
 337                return PTR_ERR(src);
 338
 339        WARN(clk_set_parent(timer->fclk, src) < 0,
 340             "Cannot set timer parent clock, no PLL clock driver?");
 341
 342        clk_put(src);
 343
 344        omap_hwmod_enable(oh);
 345        __omap_dm_timer_init_regs(timer);
 346
 347        if (posted)
 348                __omap_dm_timer_enable_posted(timer);
 349
 350        /* Check that the intended posted configuration matches the actual */
 351        if (posted != timer->posted)
 352                return -EINVAL;
 353
 354        timer->rate = clk_get_rate(timer->fclk);
 355        timer->reserved = 1;
 356
 357        return r;
 358}
 359
 360#if !defined(CONFIG_SMP) && defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
 361void tick_broadcast(const struct cpumask *mask)
 362{
 363}
 364#endif
 365
 366static void __init omap2_gp_clockevent_init(int gptimer_id,
 367                                                const char *fck_source,
 368                                                const char *property)
 369{
 370        int res;
 371
 372        clkev.id = gptimer_id;
 373        clkev.errata = omap_dm_timer_get_errata();
 374
 375        /*
 376         * For clock-event timers we never read the timer counter and
 377         * so we are not impacted by errata i103 and i767. Therefore,
 378         * we can safely ignore this errata for clock-event timers.
 379         */
 380        __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
 381
 382        res = omap_dm_timer_init_one(&clkev, fck_source, property,
 383                                     &clockevent_gpt.name, OMAP_TIMER_POSTED);
 384        BUG_ON(res);
 385
 386        omap2_gp_timer_irq.dev_id = &clkev;
 387        setup_irq(clkev.irq, &omap2_gp_timer_irq);
 388
 389        __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
 390
 391        clockevent_gpt.cpumask = cpu_possible_mask;
 392        clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
 393        clockevents_config_and_register(&clockevent_gpt, clkev.rate,
 394                                        3, /* Timer internal resynch latency */
 395                                        0xffffffff);
 396
 397        if (soc_is_am33xx() || soc_is_am43xx()) {
 398                clockevent_gpt.suspend = omap_clkevt_idle;
 399                clockevent_gpt.resume = omap_clkevt_unidle;
 400
 401                clockevent_gpt_hwmod =
 402                        omap_hwmod_lookup(clockevent_gpt.name);
 403        }
 404
 405        pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
 406                clkev.rate);
 407}
 408
 409/* Clocksource code */
 410static struct omap_dm_timer clksrc;
 411static bool use_gptimer_clksrc __initdata;
 412
 413/*
 414 * clocksource
 415 */
 416static u64 clocksource_read_cycles(struct clocksource *cs)
 417{
 418        return (u64)__omap_dm_timer_read_counter(&clksrc,
 419                                                     OMAP_TIMER_NONPOSTED);
 420}
 421
 422static struct clocksource clocksource_gpt = {
 423        .rating         = 300,
 424        .read           = clocksource_read_cycles,
 425        .mask           = CLOCKSOURCE_MASK(32),
 426        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 427};
 428
 429static u64 notrace dmtimer_read_sched_clock(void)
 430{
 431        if (clksrc.reserved)
 432                return __omap_dm_timer_read_counter(&clksrc,
 433                                                    OMAP_TIMER_NONPOSTED);
 434
 435        return 0;
 436}
 437
 438static const struct of_device_id omap_counter_match[] __initconst = {
 439        { .compatible = "ti,omap-counter32k", },
 440        { }
 441};
 442
 443/* Setup free-running counter for clocksource */
 444static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
 445{
 446        int ret;
 447        struct device_node *np = NULL;
 448        struct omap_hwmod *oh;
 449        const char *oh_name = "counter_32k";
 450
 451        /*
 452         * See if the 32kHz counter is supported.
 453         */
 454        np = omap_get_timer_dt(omap_counter_match, NULL);
 455        if (!np)
 456                return -ENODEV;
 457
 458        of_property_read_string_index(np->parent, "ti,hwmods", 0, &oh_name);
 459        if (!oh_name) {
 460                of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
 461                if (!oh_name)
 462                        return -ENODEV;
 463        }
 464
 465        /*
 466         * First check hwmod data is available for sync32k counter
 467         */
 468        oh = omap_hwmod_lookup(oh_name);
 469        if (!oh || oh->slaves_cnt == 0)
 470                return -ENODEV;
 471
 472        omap_hwmod_setup_one(oh_name);
 473
 474        ret = omap_hwmod_enable(oh);
 475        if (ret) {
 476                pr_warn("%s: failed to enable counter_32k module (%d)\n",
 477                                                        __func__, ret);
 478                return ret;
 479        }
 480
 481        return ret;
 482}
 483
 484static unsigned int omap2_gptimer_clksrc_load;
 485
 486static void omap2_gptimer_clksrc_suspend(struct clocksource *unused)
 487{
 488        omap2_gptimer_clksrc_load =
 489                __omap_dm_timer_read_counter(&clksrc, OMAP_TIMER_NONPOSTED);
 490
 491        omap_hwmod_idle(clocksource_gpt_hwmod);
 492}
 493
 494static void omap2_gptimer_clksrc_resume(struct clocksource *unused)
 495{
 496        omap_hwmod_enable(clocksource_gpt_hwmod);
 497
 498        __omap_dm_timer_load_start(&clksrc,
 499                                   OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
 500                                   omap2_gptimer_clksrc_load,
 501                                   OMAP_TIMER_NONPOSTED);
 502}
 503
 504static void __init omap2_gptimer_clocksource_init(int gptimer_id,
 505                                                  const char *fck_source,
 506                                                  const char *property)
 507{
 508        int res;
 509
 510        clksrc.id = gptimer_id;
 511        clksrc.errata = omap_dm_timer_get_errata();
 512
 513        res = omap_dm_timer_init_one(&clksrc, fck_source, property,
 514                                     &clocksource_gpt.name,
 515                                     OMAP_TIMER_NONPOSTED);
 516
 517        if (soc_is_am43xx()) {
 518                clocksource_gpt.suspend = omap2_gptimer_clksrc_suspend;
 519                clocksource_gpt.resume = omap2_gptimer_clksrc_resume;
 520
 521                clocksource_gpt_hwmod =
 522                        omap_hwmod_lookup(clocksource_gpt.name);
 523        }
 524
 525        BUG_ON(res);
 526
 527        __omap_dm_timer_load_start(&clksrc,
 528                                   OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
 529                                   OMAP_TIMER_NONPOSTED);
 530        sched_clock_register(dmtimer_read_sched_clock, 32, clksrc.rate);
 531
 532        if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
 533                pr_err("Could not register clocksource %s\n",
 534                        clocksource_gpt.name);
 535        else
 536                pr_info("OMAP clocksource: %s at %lu Hz\n",
 537                        clocksource_gpt.name, clksrc.rate);
 538}
 539
 540static void __init __omap_sync32k_timer_init(int clkev_nr, const char *clkev_src,
 541                const char *clkev_prop, int clksrc_nr, const char *clksrc_src,
 542                const char *clksrc_prop, bool gptimer)
 543{
 544        omap_clk_init();
 545        omap_dmtimer_init();
 546        omap2_gp_clockevent_init(clkev_nr, clkev_src, clkev_prop);
 547
 548        /* Enable the use of clocksource="gp_timer" kernel parameter */
 549        if (use_gptimer_clksrc || gptimer)
 550                omap2_gptimer_clocksource_init(clksrc_nr, clksrc_src,
 551                                                clksrc_prop);
 552        else
 553                omap2_sync32k_clocksource_init();
 554}
 555
 556void __init omap_init_time(void)
 557{
 558        __omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
 559                        2, "timer_sys_ck", NULL, false);
 560
 561        timer_probe();
 562}
 563
 564#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
 565void __init omap3_secure_sync32k_timer_init(void)
 566{
 567        __omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",
 568                        2, "timer_sys_ck", NULL, false);
 569
 570        timer_probe();
 571}
 572#endif /* CONFIG_ARCH_OMAP3 */
 573
 574#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
 575        defined(CONFIG_SOC_AM43XX)
 576void __init omap3_gptimer_timer_init(void)
 577{
 578        __omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
 579                        1, "timer_sys_ck", "ti,timer-alwon", true);
 580        if (of_have_populated_dt())
 581                timer_probe();
 582}
 583#endif
 584
 585#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) ||          \
 586        defined(CONFIG_SOC_DRA7XX)
 587static void __init omap4_sync32k_timer_init(void)
 588{
 589        __omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
 590                        2, "sys_clkin_ck", NULL, false);
 591}
 592
 593void __init omap4_local_timer_init(void)
 594{
 595        omap4_sync32k_timer_init();
 596        timer_probe();
 597}
 598#endif
 599
 600#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
 601
 602/*
 603 * The realtime counter also called master counter, is a free-running
 604 * counter, which is related to real time. It produces the count used
 605 * by the CPU local timer peripherals in the MPU cluster. The timer counts
 606 * at a rate of 6.144 MHz. Because the device operates on different clocks
 607 * in different power modes, the master counter shifts operation between
 608 * clocks, adjusting the increment per clock in hardware accordingly to
 609 * maintain a constant count rate.
 610 */
 611static void __init realtime_counter_init(void)
 612{
 613#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
 614        void __iomem *base;
 615        static struct clk *sys_clk;
 616        unsigned long rate;
 617        unsigned int reg;
 618        unsigned long long num, den;
 619
 620        base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
 621        if (!base) {
 622                pr_err("%s: ioremap failed\n", __func__);
 623                return;
 624        }
 625        sys_clk = clk_get(NULL, "sys_clkin");
 626        if (IS_ERR(sys_clk)) {
 627                pr_err("%s: failed to get system clock handle\n", __func__);
 628                iounmap(base);
 629                return;
 630        }
 631
 632        rate = clk_get_rate(sys_clk);
 633
 634        if (soc_is_dra7xx()) {
 635                /*
 636                 * Errata i856 says the 32.768KHz crystal does not start at
 637                 * power on, so the CPU falls back to an emulated 32KHz clock
 638                 * based on sysclk / 610 instead. This causes the master counter
 639                 * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
 640                 * (OR sysclk * 75 / 244)
 641                 *
 642                 * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
 643                 * Of course any board built without a populated 32.768KHz
 644                 * crystal would also need this fix even if the CPU is fixed
 645                 * later.
 646                 *
 647                 * Either case can be detected by using the two speedselect bits
 648                 * If they are not 0, then the 32.768KHz clock driving the
 649                 * coarse counter that corrects the fine counter every time it
 650                 * ticks is actually rate/610 rather than 32.768KHz and we
 651                 * should compensate to avoid the 570ppm (at 20MHz, much worse
 652                 * at other rates) too fast system time.
 653                 */
 654                reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
 655                if (reg & DRA7_SPEEDSELECT_MASK) {
 656                        num = 75;
 657                        den = 244;
 658                        goto sysclk1_based;
 659                }
 660        }
 661
 662        /* Numerator/denumerator values refer TRM Realtime Counter section */
 663        switch (rate) {
 664        case 12000000:
 665                num = 64;
 666                den = 125;
 667                break;
 668        case 13000000:
 669                num = 768;
 670                den = 1625;
 671                break;
 672        case 19200000:
 673                num = 8;
 674                den = 25;
 675                break;
 676        case 20000000:
 677                num = 192;
 678                den = 625;
 679                break;
 680        case 26000000:
 681                num = 384;
 682                den = 1625;
 683                break;
 684        case 27000000:
 685                num = 256;
 686                den = 1125;
 687                break;
 688        case 38400000:
 689        default:
 690                /* Program it for 38.4 MHz */
 691                num = 4;
 692                den = 25;
 693                break;
 694        }
 695
 696sysclk1_based:
 697        /* Program numerator and denumerator registers */
 698        reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
 699                        NUMERATOR_DENUMERATOR_MASK;
 700        reg |= num;
 701        writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
 702
 703        reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
 704                        NUMERATOR_DENUMERATOR_MASK;
 705        reg |= den;
 706        writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
 707
 708        arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
 709        set_cntfreq();
 710
 711        iounmap(base);
 712#endif
 713}
 714
 715void __init omap5_realtime_timer_init(void)
 716{
 717        omap4_sync32k_timer_init();
 718        realtime_counter_init();
 719
 720        timer_probe();
 721}
 722#endif /* CONFIG_SOC_OMAP5 || CONFIG_SOC_DRA7XX */
 723
 724/**
 725 * omap2_override_clocksource - clocksource override with user configuration
 726 *
 727 * Allows user to override default clocksource, using kernel parameter
 728 *   clocksource="gp_timer"     (For all OMAP2PLUS architectures)
 729 *
 730 * Note that, here we are using same standard kernel parameter "clocksource=",
 731 * and not introducing any OMAP specific interface.
 732 */
 733static int __init omap2_override_clocksource(char *str)
 734{
 735        if (!str)
 736                return 0;
 737        /*
 738         * For OMAP architecture, we only have two options
 739         *    - sync_32k (default)
 740         *    - gp_timer (sys_clk based)
 741         */
 742        if (!strcmp(str, "gp_timer"))
 743                use_gptimer_clksrc = true;
 744
 745        return 0;
 746}
 747early_param("clocksource", omap2_override_clocksource);
 748