root/include/clocksource/timer-ti-dm.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. __omap_dm_timer_read
  2. __omap_dm_timer_write
  3. __omap_dm_timer_init_regs
  4. __omap_dm_timer_enable_posted
  5. __omap_dm_timer_override_errata
  6. __omap_dm_timer_stop
  7. __omap_dm_timer_load_start
  8. __omap_dm_timer_int_enable
  9. __omap_dm_timer_read_counter
  10. __omap_dm_timer_write_status

   1 /*
   2  * OMAP Dual-Mode Timers
   3  *
   4  * Copyright (C) 2010 Texas Instruments Incorporated - http://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 
  76 struct timer_regs {
  77         u32 tidr;
  78         u32 tier;
  79         u32 twer;
  80         u32 tclr;
  81         u32 tcrr;
  82         u32 tldr;
  83         u32 ttrg;
  84         u32 twps;
  85         u32 tmar;
  86         u32 tcar1;
  87         u32 tsicr;
  88         u32 tcar2;
  89         u32 tpir;
  90         u32 tnir;
  91         u32 tcvr;
  92         u32 tocr;
  93         u32 towr;
  94 };
  95 
  96 struct omap_dm_timer {
  97         int id;
  98         int irq;
  99         struct clk *fclk;
 100 
 101         void __iomem    *io_base;
 102         void __iomem    *irq_stat;      /* TISR/IRQSTATUS interrupt status */
 103         void __iomem    *irq_ena;       /* irq enable */
 104         void __iomem    *irq_dis;       /* irq disable, only on v2 ip */
 105         void __iomem    *pend;          /* write pending */
 106         void __iomem    *func_base;     /* function register base */
 107 
 108         unsigned long rate;
 109         unsigned reserved:1;
 110         unsigned posted:1;
 111         struct timer_regs context;
 112         int (*get_context_loss_count)(struct device *);
 113         int ctx_loss_count;
 114         int revision;
 115         u32 capability;
 116         u32 errata;
 117         struct platform_device *pdev;
 118         struct list_head node;
 119 };
 120 
 121 int omap_dm_timer_reserve_systimer(int id);
 122 struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
 123 
 124 int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
 125 
 126 u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
 127 
 128 int omap_dm_timer_trigger(struct omap_dm_timer *timer);
 129 
 130 int omap_dm_timers_active(void);
 131 
 132 /*
 133  * Do not use the defines below, they are not needed. They should be only
 134  * used by dmtimer.c and sys_timer related code.
 135  */
 136 
 137 /*
 138  * The interrupt registers are different between v1 and v2 ip.
 139  * These registers are offsets from timer->iobase.
 140  */
 141 #define OMAP_TIMER_ID_OFFSET            0x00
 142 #define OMAP_TIMER_OCP_CFG_OFFSET       0x10
 143 
 144 #define OMAP_TIMER_V1_SYS_STAT_OFFSET   0x14
 145 #define OMAP_TIMER_V1_STAT_OFFSET       0x18
 146 #define OMAP_TIMER_V1_INT_EN_OFFSET     0x1c
 147 
 148 #define OMAP_TIMER_V2_IRQSTATUS_RAW     0x24
 149 #define OMAP_TIMER_V2_IRQSTATUS         0x28
 150 #define OMAP_TIMER_V2_IRQENABLE_SET     0x2c
 151 #define OMAP_TIMER_V2_IRQENABLE_CLR     0x30
 152 
 153 /*
 154  * The functional registers have a different base on v1 and v2 ip.
 155  * These registers are offsets from timer->func_base. The func_base
 156  * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
 157  *
 158  */
 159 #define OMAP_TIMER_V2_FUNC_OFFSET               0x14
 160 
 161 #define _OMAP_TIMER_WAKEUP_EN_OFFSET    0x20
 162 #define _OMAP_TIMER_CTRL_OFFSET         0x24
 163 #define         OMAP_TIMER_CTRL_GPOCFG          (1 << 14)
 164 #define         OMAP_TIMER_CTRL_CAPTMODE        (1 << 13)
 165 #define         OMAP_TIMER_CTRL_PT              (1 << 12)
 166 #define         OMAP_TIMER_CTRL_TCM_LOWTOHIGH   (0x1 << 8)
 167 #define         OMAP_TIMER_CTRL_TCM_HIGHTOLOW   (0x2 << 8)
 168 #define         OMAP_TIMER_CTRL_TCM_BOTHEDGES   (0x3 << 8)
 169 #define         OMAP_TIMER_CTRL_SCPWM           (1 << 7)
 170 #define         OMAP_TIMER_CTRL_CE              (1 << 6) /* compare enable */
 171 #define         OMAP_TIMER_CTRL_PRE             (1 << 5) /* prescaler enable */
 172 #define         OMAP_TIMER_CTRL_PTV_SHIFT       2 /* prescaler value shift */
 173 #define         OMAP_TIMER_CTRL_POSTED          (1 << 2)
 174 #define         OMAP_TIMER_CTRL_AR              (1 << 1) /* auto-reload enable */
 175 #define         OMAP_TIMER_CTRL_ST              (1 << 0) /* start timer */
 176 #define _OMAP_TIMER_COUNTER_OFFSET      0x28
 177 #define _OMAP_TIMER_LOAD_OFFSET         0x2c
 178 #define _OMAP_TIMER_TRIGGER_OFFSET      0x30
 179 #define _OMAP_TIMER_WRITE_PEND_OFFSET   0x34
 180 #define         WP_NONE                 0       /* no write pending bit */
 181 #define         WP_TCLR                 (1 << 0)
 182 #define         WP_TCRR                 (1 << 1)
 183 #define         WP_TLDR                 (1 << 2)
 184 #define         WP_TTGR                 (1 << 3)
 185 #define         WP_TMAR                 (1 << 4)
 186 #define         WP_TPIR                 (1 << 5)
 187 #define         WP_TNIR                 (1 << 6)
 188 #define         WP_TCVR                 (1 << 7)
 189 #define         WP_TOCR                 (1 << 8)
 190 #define         WP_TOWR                 (1 << 9)
 191 #define _OMAP_TIMER_MATCH_OFFSET        0x38
 192 #define _OMAP_TIMER_CAPTURE_OFFSET      0x3c
 193 #define _OMAP_TIMER_IF_CTRL_OFFSET      0x40
 194 #define _OMAP_TIMER_CAPTURE2_OFFSET             0x44    /* TCAR2, 34xx only */
 195 #define _OMAP_TIMER_TICK_POS_OFFSET             0x48    /* TPIR, 34xx only */
 196 #define _OMAP_TIMER_TICK_NEG_OFFSET             0x4c    /* TNIR, 34xx only */
 197 #define _OMAP_TIMER_TICK_COUNT_OFFSET           0x50    /* TCVR, 34xx only */
 198 #define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET    0x54    /* TOCR, 34xx only */
 199 #define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET  0x58    /* TOWR, 34xx only */
 200 
 201 /* register offsets with the write pending bit encoded */
 202 #define WPSHIFT                                 16
 203 
 204 #define OMAP_TIMER_WAKEUP_EN_REG                (_OMAP_TIMER_WAKEUP_EN_OFFSET \
 205                                                         | (WP_NONE << WPSHIFT))
 206 
 207 #define OMAP_TIMER_CTRL_REG                     (_OMAP_TIMER_CTRL_OFFSET \
 208                                                         | (WP_TCLR << WPSHIFT))
 209 
 210 #define OMAP_TIMER_COUNTER_REG                  (_OMAP_TIMER_COUNTER_OFFSET \
 211                                                         | (WP_TCRR << WPSHIFT))
 212 
 213 #define OMAP_TIMER_LOAD_REG                     (_OMAP_TIMER_LOAD_OFFSET \
 214                                                         | (WP_TLDR << WPSHIFT))
 215 
 216 #define OMAP_TIMER_TRIGGER_REG                  (_OMAP_TIMER_TRIGGER_OFFSET \
 217                                                         | (WP_TTGR << WPSHIFT))
 218 
 219 #define OMAP_TIMER_WRITE_PEND_REG               (_OMAP_TIMER_WRITE_PEND_OFFSET \
 220                                                         | (WP_NONE << WPSHIFT))
 221 
 222 #define OMAP_TIMER_MATCH_REG                    (_OMAP_TIMER_MATCH_OFFSET \
 223                                                         | (WP_TMAR << WPSHIFT))
 224 
 225 #define OMAP_TIMER_CAPTURE_REG                  (_OMAP_TIMER_CAPTURE_OFFSET \
 226                                                         | (WP_NONE << WPSHIFT))
 227 
 228 #define OMAP_TIMER_IF_CTRL_REG                  (_OMAP_TIMER_IF_CTRL_OFFSET \
 229                                                         | (WP_NONE << WPSHIFT))
 230 
 231 #define OMAP_TIMER_CAPTURE2_REG                 (_OMAP_TIMER_CAPTURE2_OFFSET \
 232                                                         | (WP_NONE << WPSHIFT))
 233 
 234 #define OMAP_TIMER_TICK_POS_REG                 (_OMAP_TIMER_TICK_POS_OFFSET \
 235                                                         | (WP_TPIR << WPSHIFT))
 236 
 237 #define OMAP_TIMER_TICK_NEG_REG                 (_OMAP_TIMER_TICK_NEG_OFFSET \
 238                                                         | (WP_TNIR << WPSHIFT))
 239 
 240 #define OMAP_TIMER_TICK_COUNT_REG               (_OMAP_TIMER_TICK_COUNT_OFFSET \
 241                                                         | (WP_TCVR << WPSHIFT))
 242 
 243 #define OMAP_TIMER_TICK_INT_MASK_SET_REG                                \
 244                 (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
 245 
 246 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG                              \
 247                 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
 248 
 249 /*
 250  * The below are inlined to optimize code size for system timers. Other code
 251  * should not need these at all, see
 252  * include/linux/platform_data/pwm_omap_dmtimer.h
 253  */
 254 #if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2PLUS)
 255 static 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 
 265 static 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 
 275 static 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  */
 310 static 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  */
 337 static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
 338                                                    u32 errata)
 339 {
 340         timer->errata &= ~errata;
 341 }
 342 
 343 static 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 
 367 static 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 
 375 static 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 
 382 static 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 
 388 static 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 */

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