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