root/arch/arm/plat-omap/counter_32k.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. omap_32k_read_sched_clock
  2. omap_read_persistent_clock64
  3. omap_init_clocksource_32k

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * OMAP 32ksynctimer/counter_32k-related code
   4  *
   5  * Copyright (C) 2009 Texas Instruments
   6  * Copyright (C) 2010 Nokia Corporation
   7  * Tony Lindgren <tony@atomide.com>
   8  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
   9  *
  10  * NOTE: This timer is not the same timer as the old OMAP1 MPU timer.
  11  */
  12 #include <linux/kernel.h>
  13 #include <linux/init.h>
  14 #include <linux/clk.h>
  15 #include <linux/err.h>
  16 #include <linux/io.h>
  17 #include <linux/clocksource.h>
  18 #include <linux/sched_clock.h>
  19 
  20 #include <asm/mach/time.h>
  21 
  22 #include <plat/counter-32k.h>
  23 
  24 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
  25 #define OMAP2_32KSYNCNT_REV_OFF         0x0
  26 #define OMAP2_32KSYNCNT_REV_SCHEME      (0x3 << 30)
  27 #define OMAP2_32KSYNCNT_CR_OFF_LOW      0x10
  28 #define OMAP2_32KSYNCNT_CR_OFF_HIGH     0x30
  29 
  30 /*
  31  * 32KHz clocksource ... always available, on pretty most chips except
  32  * OMAP 730 and 1510.  Other timers could be used as clocksources, with
  33  * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
  34  * but systems won't necessarily want to spend resources that way.
  35  */
  36 static void __iomem *sync32k_cnt_reg;
  37 
  38 static u64 notrace omap_32k_read_sched_clock(void)
  39 {
  40         return sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
  41 }
  42 
  43 /**
  44  * omap_read_persistent_clock64 -  Return time from a persistent clock.
  45  *
  46  * Reads the time from a source which isn't disabled during PM, the
  47  * 32k sync timer.  Convert the cycles elapsed since last read into
  48  * nsecs and adds to a monotonically increasing timespec64.
  49  */
  50 static struct timespec64 persistent_ts;
  51 static cycles_t cycles;
  52 static unsigned int persistent_mult, persistent_shift;
  53 
  54 static void omap_read_persistent_clock64(struct timespec64 *ts)
  55 {
  56         unsigned long long nsecs;
  57         cycles_t last_cycles;
  58 
  59         last_cycles = cycles;
  60         cycles = sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
  61 
  62         nsecs = clocksource_cyc2ns(cycles - last_cycles,
  63                                         persistent_mult, persistent_shift);
  64 
  65         timespec64_add_ns(&persistent_ts, nsecs);
  66 
  67         *ts = persistent_ts;
  68 }
  69 
  70 /**
  71  * omap_init_clocksource_32k - setup and register counter 32k as a
  72  * kernel clocksource
  73  * @pbase: base addr of counter_32k module
  74  * @size: size of counter_32k to map
  75  *
  76  * Returns 0 upon success or negative error code upon failure.
  77  *
  78  */
  79 int __init omap_init_clocksource_32k(void __iomem *vbase)
  80 {
  81         int ret;
  82 
  83         /*
  84          * 32k sync Counter IP register offsets vary between the
  85          * highlander version and the legacy ones.
  86          * The 'SCHEME' bits(30-31) of the revision register is used
  87          * to identify the version.
  88          */
  89         if (readl_relaxed(vbase + OMAP2_32KSYNCNT_REV_OFF) &
  90                                                 OMAP2_32KSYNCNT_REV_SCHEME)
  91                 sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_HIGH;
  92         else
  93                 sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_LOW;
  94 
  95         /*
  96          * 120000 rough estimate from the calculations in
  97          * __clocksource_update_freq_scale.
  98          */
  99         clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
 100                         32768, NSEC_PER_SEC, 120000);
 101 
 102         ret = clocksource_mmio_init(sync32k_cnt_reg, "32k_counter", 32768,
 103                                 250, 32, clocksource_mmio_readl_up);
 104         if (ret) {
 105                 pr_err("32k_counter: can't register clocksource\n");
 106                 return ret;
 107         }
 108 
 109         sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
 110         register_persistent_clock(omap_read_persistent_clock64);
 111         pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
 112 
 113         return 0;
 114 }

/* [<][>][^][v][top][bottom][index][help] */