linux/arch/blackfin/kernel/gptimers.c
<<
>>
Prefs
   1/*
   2 * gptimers.c - Blackfin General Purpose Timer core API
   3 *
   4 * Copyright (c) 2005-2008 Analog Devices Inc.
   5 * Copyright (C) 2005 John DeHority
   6 * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de)
   7 *
   8 * Licensed under the GPLv2.
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <linux/io.h>
  14
  15#include <asm/blackfin.h>
  16#include <asm/gptimers.h>
  17
  18#ifdef DEBUG
  19# define tassert(expr)
  20#else
  21# define tassert(expr) \
  22        if (!(expr)) \
  23                printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", __FILE__, __func__, __LINE__);
  24#endif
  25
  26#define BFIN_TIMER_NUM_GROUP  (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
  27
  28typedef struct {
  29        uint16_t config;
  30        uint16_t __pad;
  31        uint32_t counter;
  32        uint32_t period;
  33        uint32_t width;
  34} GPTIMER_timer_regs;
  35
  36typedef struct {
  37        uint16_t enable;
  38        uint16_t __pad0;
  39        uint16_t disable;
  40        uint16_t __pad1;
  41        uint32_t status;
  42} GPTIMER_group_regs;
  43
  44static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
  45{
  46        (GPTIMER_timer_regs *)TIMER0_CONFIG,
  47        (GPTIMER_timer_regs *)TIMER1_CONFIG,
  48        (GPTIMER_timer_regs *)TIMER2_CONFIG,
  49#if (MAX_BLACKFIN_GPTIMERS > 3)
  50        (GPTIMER_timer_regs *)TIMER3_CONFIG,
  51        (GPTIMER_timer_regs *)TIMER4_CONFIG,
  52        (GPTIMER_timer_regs *)TIMER5_CONFIG,
  53        (GPTIMER_timer_regs *)TIMER6_CONFIG,
  54        (GPTIMER_timer_regs *)TIMER7_CONFIG,
  55# if (MAX_BLACKFIN_GPTIMERS > 8)
  56        (GPTIMER_timer_regs *)TIMER8_CONFIG,
  57        (GPTIMER_timer_regs *)TIMER9_CONFIG,
  58        (GPTIMER_timer_regs *)TIMER10_CONFIG,
  59#  if (MAX_BLACKFIN_GPTIMERS > 11)
  60        (GPTIMER_timer_regs *)TIMER11_CONFIG,
  61#  endif
  62# endif
  63#endif
  64};
  65
  66static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] =
  67{
  68        (GPTIMER_group_regs *)TIMER0_GROUP_REG,
  69#if (MAX_BLACKFIN_GPTIMERS > 8)
  70        (GPTIMER_group_regs *)TIMER8_GROUP_REG,
  71#endif
  72};
  73
  74static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] =
  75{
  76        TIMER_STATUS_TRUN0,
  77        TIMER_STATUS_TRUN1,
  78        TIMER_STATUS_TRUN2,
  79#if (MAX_BLACKFIN_GPTIMERS > 3)
  80        TIMER_STATUS_TRUN3,
  81        TIMER_STATUS_TRUN4,
  82        TIMER_STATUS_TRUN5,
  83        TIMER_STATUS_TRUN6,
  84        TIMER_STATUS_TRUN7,
  85# if (MAX_BLACKFIN_GPTIMERS > 8)
  86        TIMER_STATUS_TRUN8,
  87        TIMER_STATUS_TRUN9,
  88        TIMER_STATUS_TRUN10,
  89#  if (MAX_BLACKFIN_GPTIMERS > 11)
  90        TIMER_STATUS_TRUN11,
  91#  endif
  92# endif
  93#endif
  94};
  95
  96static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] =
  97{
  98        TIMER_STATUS_TOVF0,
  99        TIMER_STATUS_TOVF1,
 100        TIMER_STATUS_TOVF2,
 101#if (MAX_BLACKFIN_GPTIMERS > 3)
 102        TIMER_STATUS_TOVF3,
 103        TIMER_STATUS_TOVF4,
 104        TIMER_STATUS_TOVF5,
 105        TIMER_STATUS_TOVF6,
 106        TIMER_STATUS_TOVF7,
 107# if (MAX_BLACKFIN_GPTIMERS > 8)
 108        TIMER_STATUS_TOVF8,
 109        TIMER_STATUS_TOVF9,
 110        TIMER_STATUS_TOVF10,
 111#  if (MAX_BLACKFIN_GPTIMERS > 11)
 112        TIMER_STATUS_TOVF11,
 113#  endif
 114# endif
 115#endif
 116};
 117
 118static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
 119{
 120        TIMER_STATUS_TIMIL0,
 121        TIMER_STATUS_TIMIL1,
 122        TIMER_STATUS_TIMIL2,
 123#if (MAX_BLACKFIN_GPTIMERS > 3)
 124        TIMER_STATUS_TIMIL3,
 125        TIMER_STATUS_TIMIL4,
 126        TIMER_STATUS_TIMIL5,
 127        TIMER_STATUS_TIMIL6,
 128        TIMER_STATUS_TIMIL7,
 129# if (MAX_BLACKFIN_GPTIMERS > 8)
 130        TIMER_STATUS_TIMIL8,
 131        TIMER_STATUS_TIMIL9,
 132        TIMER_STATUS_TIMIL10,
 133#  if (MAX_BLACKFIN_GPTIMERS > 11)
 134        TIMER_STATUS_TIMIL11,
 135#  endif
 136# endif
 137#endif
 138};
 139
 140void set_gptimer_pwidth(int timer_id, uint32_t value)
 141{
 142        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 143        timer_regs[timer_id]->width = value;
 144        SSYNC();
 145}
 146EXPORT_SYMBOL(set_gptimer_pwidth);
 147
 148uint32_t get_gptimer_pwidth(int timer_id)
 149{
 150        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 151        return timer_regs[timer_id]->width;
 152}
 153EXPORT_SYMBOL(get_gptimer_pwidth);
 154
 155void set_gptimer_period(int timer_id, uint32_t period)
 156{
 157        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 158        timer_regs[timer_id]->period = period;
 159        SSYNC();
 160}
 161EXPORT_SYMBOL(set_gptimer_period);
 162
 163uint32_t get_gptimer_period(int timer_id)
 164{
 165        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 166        return timer_regs[timer_id]->period;
 167}
 168EXPORT_SYMBOL(get_gptimer_period);
 169
 170uint32_t get_gptimer_count(int timer_id)
 171{
 172        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 173        return timer_regs[timer_id]->counter;
 174}
 175EXPORT_SYMBOL(get_gptimer_count);
 176
 177uint32_t get_gptimer_status(int group)
 178{
 179        tassert(group < BFIN_TIMER_NUM_GROUP);
 180        return group_regs[group]->status;
 181}
 182EXPORT_SYMBOL(get_gptimer_status);
 183
 184void set_gptimer_status(int group, uint32_t value)
 185{
 186        tassert(group < BFIN_TIMER_NUM_GROUP);
 187        group_regs[group]->status = value;
 188        SSYNC();
 189}
 190EXPORT_SYMBOL(set_gptimer_status);
 191
 192int get_gptimer_intr(int timer_id)
 193{
 194        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 195        return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]);
 196}
 197EXPORT_SYMBOL(get_gptimer_intr);
 198
 199void clear_gptimer_intr(int timer_id)
 200{
 201        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 202        group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id];
 203}
 204EXPORT_SYMBOL(clear_gptimer_intr);
 205
 206int get_gptimer_over(int timer_id)
 207{
 208        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 209        return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]);
 210}
 211EXPORT_SYMBOL(get_gptimer_over);
 212
 213void clear_gptimer_over(int timer_id)
 214{
 215        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 216        group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id];
 217}
 218EXPORT_SYMBOL(clear_gptimer_over);
 219
 220int get_gptimer_run(int timer_id)
 221{
 222        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 223        return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]);
 224}
 225EXPORT_SYMBOL(get_gptimer_run);
 226
 227void set_gptimer_config(int timer_id, uint16_t config)
 228{
 229        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 230        timer_regs[timer_id]->config = config;
 231        SSYNC();
 232}
 233EXPORT_SYMBOL(set_gptimer_config);
 234
 235uint16_t get_gptimer_config(int timer_id)
 236{
 237        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 238        return timer_regs[timer_id]->config;
 239}
 240EXPORT_SYMBOL(get_gptimer_config);
 241
 242void enable_gptimers(uint16_t mask)
 243{
 244        int i;
 245        tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
 246        for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
 247                group_regs[i]->enable = mask & 0xFF;
 248                mask >>= 8;
 249        }
 250        SSYNC();
 251}
 252EXPORT_SYMBOL(enable_gptimers);
 253
 254static void _disable_gptimers(uint16_t mask)
 255{
 256        int i;
 257        uint16_t m = mask;
 258        tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
 259        for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
 260                group_regs[i]->disable = m & 0xFF;
 261                m >>= 8;
 262        }
 263}
 264
 265void disable_gptimers(uint16_t mask)
 266{
 267        int i;
 268        _disable_gptimers(mask);
 269        for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
 270                if (mask & (1 << i))
 271                        group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i];
 272        SSYNC();
 273}
 274EXPORT_SYMBOL(disable_gptimers);
 275
 276void disable_gptimers_sync(uint16_t mask)
 277{
 278        _disable_gptimers(mask);
 279        SSYNC();
 280}
 281EXPORT_SYMBOL(disable_gptimers_sync);
 282
 283void set_gptimer_pulse_hi(int timer_id)
 284{
 285        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 286        timer_regs[timer_id]->config |= TIMER_PULSE_HI;
 287        SSYNC();
 288}
 289EXPORT_SYMBOL(set_gptimer_pulse_hi);
 290
 291void clear_gptimer_pulse_hi(int timer_id)
 292{
 293        tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 294        timer_regs[timer_id]->config &= ~TIMER_PULSE_HI;
 295        SSYNC();
 296}
 297EXPORT_SYMBOL(clear_gptimer_pulse_hi);
 298
 299uint16_t get_enabled_gptimers(void)
 300{
 301        int i;
 302        uint16_t result = 0;
 303        for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i)
 304                result |= (group_regs[i]->enable << (i << 3));
 305        return result;
 306}
 307EXPORT_SYMBOL(get_enabled_gptimers);
 308
 309MODULE_AUTHOR("Axel Weiss (awe@aglaia-gmbh.de)");
 310MODULE_DESCRIPTION("Blackfin General Purpose Timers API");
 311MODULE_LICENSE("GPL");
 312