cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

timer-ti-dm.h (12553B)


      1/*
      2 * OMAP Dual-Mode Timers
      3 *
      4 * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
      5 * Tarun Kanti DebBarma <tarun.kanti@ti.com>
      6 * Thara Gopinath <thara@ti.com>
      7 *
      8 * Platform device conversion and hwmod support.
      9 *
     10 * Copyright (C) 2005 Nokia Corporation
     11 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
     12 * PWM and clock framwork support by Timo Teras.
     13 *
     14 * This program is free software; you can redistribute it and/or modify it
     15 * under the terms of the GNU General Public License as published by the
     16 * Free Software Foundation; either version 2 of the License, or (at your
     17 * option) any later version.
     18 *
     19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
     20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
     22 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 *
     28 * You should have received a copy of the  GNU General Public License along
     29 * with this program; if not, write  to the Free Software Foundation, Inc.,
     30 * 675 Mass Ave, Cambridge, MA 02139, USA.
     31 */
     32
     33#include <linux/delay.h>
     34#include <linux/io.h>
     35#include <linux/platform_device.h>
     36
     37#ifndef __CLOCKSOURCE_DMTIMER_H
     38#define __CLOCKSOURCE_DMTIMER_H
     39
     40/* clock sources */
     41#define OMAP_TIMER_SRC_SYS_CLK			0x00
     42#define OMAP_TIMER_SRC_32_KHZ			0x01
     43#define OMAP_TIMER_SRC_EXT_CLK			0x02
     44
     45/* timer interrupt enable bits */
     46#define OMAP_TIMER_INT_CAPTURE			(1 << 2)
     47#define OMAP_TIMER_INT_OVERFLOW			(1 << 1)
     48#define OMAP_TIMER_INT_MATCH			(1 << 0)
     49
     50/* trigger types */
     51#define OMAP_TIMER_TRIGGER_NONE			0x00
     52#define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
     53#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
     54
     55/* posted mode types */
     56#define OMAP_TIMER_NONPOSTED			0x00
     57#define OMAP_TIMER_POSTED			0x01
     58
     59/* timer capabilities used in hwmod database */
     60#define OMAP_TIMER_SECURE				0x80000000
     61#define OMAP_TIMER_ALWON				0x40000000
     62#define OMAP_TIMER_HAS_PWM				0x20000000
     63#define OMAP_TIMER_NEEDS_RESET				0x10000000
     64#define OMAP_TIMER_HAS_DSP_IRQ				0x08000000
     65
     66/*
     67 * timer errata flags
     68 *
     69 * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
     70 * errata prevents us from using posted mode on these devices, unless the
     71 * timer counter register is never read. For more details please refer to
     72 * the OMAP3/4/5 errata documents.
     73 */
     74#define OMAP_TIMER_ERRATA_I103_I767			0x80000000
     75
     76struct timer_regs {
     77	u32 ocp_cfg;
     78	u32 tidr;
     79	u32 tier;
     80	u32 twer;
     81	u32 tclr;
     82	u32 tcrr;
     83	u32 tldr;
     84	u32 ttrg;
     85	u32 twps;
     86	u32 tmar;
     87	u32 tcar1;
     88	u32 tsicr;
     89	u32 tcar2;
     90	u32 tpir;
     91	u32 tnir;
     92	u32 tcvr;
     93	u32 tocr;
     94	u32 towr;
     95};
     96
     97struct omap_dm_timer {
     98	int id;
     99	int irq;
    100	struct clk *fclk;
    101
    102	void __iomem	*io_base;
    103	void __iomem	*irq_stat;	/* TISR/IRQSTATUS interrupt status */
    104	void __iomem	*irq_ena;	/* irq enable */
    105	void __iomem	*irq_dis;	/* irq disable, only on v2 ip */
    106	void __iomem	*pend;		/* write pending */
    107	void __iomem	*func_base;	/* function register base */
    108
    109	atomic_t enabled;
    110	unsigned long rate;
    111	unsigned reserved:1;
    112	unsigned posted:1;
    113	struct timer_regs context;
    114	int revision;
    115	u32 capability;
    116	u32 errata;
    117	struct platform_device *pdev;
    118	struct list_head node;
    119	struct notifier_block nb;
    120};
    121
    122int omap_dm_timer_reserve_systimer(int id);
    123struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
    124
    125int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
    126
    127u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
    128
    129int omap_dm_timer_trigger(struct omap_dm_timer *timer);
    130
    131int omap_dm_timers_active(void);
    132
    133/*
    134 * Do not use the defines below, they are not needed. They should be only
    135 * used by dmtimer.c and sys_timer related code.
    136 */
    137
    138/*
    139 * The interrupt registers are different between v1 and v2 ip.
    140 * These registers are offsets from timer->iobase.
    141 */
    142#define OMAP_TIMER_ID_OFFSET		0x00
    143#define OMAP_TIMER_OCP_CFG_OFFSET	0x10
    144
    145#define OMAP_TIMER_V1_SYS_STAT_OFFSET	0x14
    146#define OMAP_TIMER_V1_STAT_OFFSET	0x18
    147#define OMAP_TIMER_V1_INT_EN_OFFSET	0x1c
    148
    149#define OMAP_TIMER_V2_IRQSTATUS_RAW	0x24
    150#define OMAP_TIMER_V2_IRQSTATUS		0x28
    151#define OMAP_TIMER_V2_IRQENABLE_SET	0x2c
    152#define OMAP_TIMER_V2_IRQENABLE_CLR	0x30
    153
    154/*
    155 * The functional registers have a different base on v1 and v2 ip.
    156 * These registers are offsets from timer->func_base. The func_base
    157 * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
    158 *
    159 */
    160#define OMAP_TIMER_V2_FUNC_OFFSET		0x14
    161
    162#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
    163#define _OMAP_TIMER_CTRL_OFFSET		0x24
    164#define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
    165#define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
    166#define		OMAP_TIMER_CTRL_PT		(1 << 12)
    167#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
    168#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
    169#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
    170#define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
    171#define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
    172#define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
    173#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
    174#define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
    175#define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
    176#define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
    177#define _OMAP_TIMER_COUNTER_OFFSET	0x28
    178#define _OMAP_TIMER_LOAD_OFFSET		0x2c
    179#define _OMAP_TIMER_TRIGGER_OFFSET	0x30
    180#define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
    181#define		WP_NONE			0	/* no write pending bit */
    182#define		WP_TCLR			(1 << 0)
    183#define		WP_TCRR			(1 << 1)
    184#define		WP_TLDR			(1 << 2)
    185#define		WP_TTGR			(1 << 3)
    186#define		WP_TMAR			(1 << 4)
    187#define		WP_TPIR			(1 << 5)
    188#define		WP_TNIR			(1 << 6)
    189#define		WP_TCVR			(1 << 7)
    190#define		WP_TOCR			(1 << 8)
    191#define		WP_TOWR			(1 << 9)
    192#define _OMAP_TIMER_MATCH_OFFSET	0x38
    193#define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
    194#define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
    195#define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
    196#define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
    197#define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
    198#define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
    199#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
    200#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
    201
    202/* register offsets with the write pending bit encoded */
    203#define	WPSHIFT					16
    204
    205#define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
    206							| (WP_NONE << WPSHIFT))
    207
    208#define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
    209							| (WP_TCLR << WPSHIFT))
    210
    211#define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
    212							| (WP_TCRR << WPSHIFT))
    213
    214#define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
    215							| (WP_TLDR << WPSHIFT))
    216
    217#define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
    218							| (WP_TTGR << WPSHIFT))
    219
    220#define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
    221							| (WP_NONE << WPSHIFT))
    222
    223#define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
    224							| (WP_TMAR << WPSHIFT))
    225
    226#define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
    227							| (WP_NONE << WPSHIFT))
    228
    229#define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
    230							| (WP_NONE << WPSHIFT))
    231
    232#define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
    233							| (WP_NONE << WPSHIFT))
    234
    235#define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
    236							| (WP_TPIR << WPSHIFT))
    237
    238#define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
    239							| (WP_TNIR << WPSHIFT))
    240
    241#define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
    242							| (WP_TCVR << WPSHIFT))
    243
    244#define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
    245		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
    246
    247#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
    248		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
    249
    250/*
    251 * The below are inlined to optimize code size for system timers. Other code
    252 * should not need these at all.
    253 */
    254#if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2PLUS)
    255static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
    256						int posted)
    257{
    258	if (posted)
    259		while (readl_relaxed(timer->pend) & (reg >> WPSHIFT))
    260			cpu_relax();
    261
    262	return readl_relaxed(timer->func_base + (reg & 0xff));
    263}
    264
    265static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
    266					u32 reg, u32 val, int posted)
    267{
    268	if (posted)
    269		while (readl_relaxed(timer->pend) & (reg >> WPSHIFT))
    270			cpu_relax();
    271
    272	writel_relaxed(val, timer->func_base + (reg & 0xff));
    273}
    274
    275static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
    276{
    277	u32 tidr;
    278
    279	/* Assume v1 ip if bits [31:16] are zero */
    280	tidr = readl_relaxed(timer->io_base);
    281	if (!(tidr >> 16)) {
    282		timer->revision = 1;
    283		timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
    284		timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
    285		timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
    286		timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
    287		timer->func_base = timer->io_base;
    288	} else {
    289		timer->revision = 2;
    290		timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
    291		timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
    292		timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
    293		timer->pend = timer->io_base +
    294			_OMAP_TIMER_WRITE_PEND_OFFSET +
    295				OMAP_TIMER_V2_FUNC_OFFSET;
    296		timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
    297	}
    298}
    299
    300/*
    301 * __omap_dm_timer_enable_posted - enables write posted mode
    302 * @timer:      pointer to timer instance handle
    303 *
    304 * Enables the write posted mode for the timer. When posted mode is enabled
    305 * writes to certain timer registers are immediately acknowledged by the
    306 * internal bus and hence prevents stalling the CPU waiting for the write to
    307 * complete. Enabling this feature can improve performance for writing to the
    308 * timer registers.
    309 */
    310static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
    311{
    312	if (timer->posted)
    313		return;
    314
    315	if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) {
    316		timer->posted = OMAP_TIMER_NONPOSTED;
    317		__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0);
    318		return;
    319	}
    320
    321	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
    322			      OMAP_TIMER_CTRL_POSTED, 0);
    323	timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
    324	timer->posted = OMAP_TIMER_POSTED;
    325}
    326
    327/**
    328 * __omap_dm_timer_override_errata - override errata flags for a timer
    329 * @timer:      pointer to timer handle
    330 * @errata:	errata flags to be ignored
    331 *
    332 * For a given timer, override a timer errata by clearing the flags
    333 * specified by the errata argument. A specific erratum should only be
    334 * overridden for a timer if the timer is used in such a way the erratum
    335 * has no impact.
    336 */
    337static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
    338						   u32 errata)
    339{
    340	timer->errata &= ~errata;
    341}
    342
    343static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
    344					int posted, unsigned long rate)
    345{
    346	u32 l;
    347
    348	l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
    349	if (l & OMAP_TIMER_CTRL_ST) {
    350		l &= ~0x1;
    351		__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
    352#ifdef CONFIG_ARCH_OMAP2PLUS
    353		/* Readback to make sure write has completed */
    354		__omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
    355		/*
    356		 * Wait for functional clock period x 3.5 to make sure that
    357		 * timer is stopped
    358		 */
    359		udelay(3500000 / rate + 1);
    360#endif
    361	}
    362
    363	/* Ack possibly pending interrupt */
    364	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
    365}
    366
    367static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
    368						u32 ctrl, unsigned int load,
    369						int posted)
    370{
    371	__omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
    372	__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
    373}
    374
    375static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
    376						unsigned int value)
    377{
    378	writel_relaxed(value, timer->irq_ena);
    379	__omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
    380}
    381
    382static inline unsigned int
    383__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
    384{
    385	return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
    386}
    387
    388static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
    389						unsigned int value)
    390{
    391	writel_relaxed(value, timer->irq_stat);
    392}
    393#endif /* CONFIG_ARCH_OMAP1 || CONFIG_ARCH_OMAP2PLUS */
    394#endif /* __CLOCKSOURCE_DMTIMER_H */