root/drivers/clocksource/timer-ti-32k.c

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

DEFINITIONS

This source file includes following definitions.
  1. to_ti_32k
  2. ti_32k_read_cycles
  3. omap_32k_read_sched_clock
  4. ti_32k_timer_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /**
   3  * timer-ti-32k.c - OMAP2 32k Timer Support
   4  *
   5  * Copyright (C) 2009 Nokia Corporation
   6  *
   7  * Update to use new clocksource/clockevent layers
   8  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
   9  * Copyright (C) 2007 MontaVista Software, Inc.
  10  *
  11  * Original driver:
  12  * Copyright (C) 2005 Nokia Corporation
  13  * Author: Paul Mundt <paul.mundt@nokia.com>
  14  *         Juha Yrjölä <juha.yrjola@nokia.com>
  15  * OMAP Dual-mode timer framework support by Timo Teras
  16  *
  17  * Some parts based off of TI's 24xx code:
  18  *
  19  * Copyright (C) 2004-2009 Texas Instruments, Inc.
  20  *
  21  * Roughly modelled after the OMAP1 MPU timer code.
  22  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  23  *
  24  * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
  25  */
  26 
  27 #include <linux/init.h>
  28 #include <linux/time.h>
  29 #include <linux/sched_clock.h>
  30 #include <linux/clocksource.h>
  31 #include <linux/of.h>
  32 #include <linux/of_address.h>
  33 
  34 /*
  35  * 32KHz clocksource ... always available, on pretty most chips except
  36  * OMAP 730 and 1510.  Other timers could be used as clocksources, with
  37  * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
  38  * but systems won't necessarily want to spend resources that way.
  39  */
  40 
  41 #define OMAP2_32KSYNCNT_REV_OFF         0x0
  42 #define OMAP2_32KSYNCNT_REV_SCHEME      (0x3 << 30)
  43 #define OMAP2_32KSYNCNT_CR_OFF_LOW      0x10
  44 #define OMAP2_32KSYNCNT_CR_OFF_HIGH     0x30
  45 
  46 struct ti_32k {
  47         void __iomem            *base;
  48         void __iomem            *counter;
  49         struct clocksource      cs;
  50 };
  51 
  52 static inline struct ti_32k *to_ti_32k(struct clocksource *cs)
  53 {
  54         return container_of(cs, struct ti_32k, cs);
  55 }
  56 
  57 static u64 notrace ti_32k_read_cycles(struct clocksource *cs)
  58 {
  59         struct ti_32k *ti = to_ti_32k(cs);
  60 
  61         return (u64)readl_relaxed(ti->counter);
  62 }
  63 
  64 static struct ti_32k ti_32k_timer = {
  65         .cs = {
  66                 .name           = "32k_counter",
  67                 .rating         = 250,
  68                 .read           = ti_32k_read_cycles,
  69                 .mask           = CLOCKSOURCE_MASK(32),
  70                 .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
  71         },
  72 };
  73 
  74 static u64 notrace omap_32k_read_sched_clock(void)
  75 {
  76         return ti_32k_read_cycles(&ti_32k_timer.cs);
  77 }
  78 
  79 static int __init ti_32k_timer_init(struct device_node *np)
  80 {
  81         int ret;
  82 
  83         ti_32k_timer.base = of_iomap(np, 0);
  84         if (!ti_32k_timer.base) {
  85                 pr_err("Can't ioremap 32k timer base\n");
  86                 return -ENXIO;
  87         }
  88 
  89         if (!of_machine_is_compatible("ti,am43"))
  90                 ti_32k_timer.cs.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
  91 
  92         ti_32k_timer.counter = ti_32k_timer.base;
  93 
  94         /*
  95          * 32k sync Counter IP register offsets vary between the highlander
  96          * version and the legacy ones.
  97          *
  98          * The 'SCHEME' bits(30-31) of the revision register is used to identify
  99          * the version.
 100          */
 101         if (readl_relaxed(ti_32k_timer.base + OMAP2_32KSYNCNT_REV_OFF) &
 102                         OMAP2_32KSYNCNT_REV_SCHEME)
 103                 ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_HIGH;
 104         else
 105                 ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_LOW;
 106 
 107         ret = clocksource_register_hz(&ti_32k_timer.cs, 32768);
 108         if (ret) {
 109                 pr_err("32k_counter: can't register clocksource\n");
 110                 return ret;
 111         }
 112 
 113         sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
 114         pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
 115 
 116         return 0;
 117 }
 118 TIMER_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
 119                 ti_32k_timer_init);

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