Commit 2a341f5cf57dce9d89b41484a69e88adc6422f6c
Committed by
Haavard Skinnemoen
1 parent
976dde010e
Exists in
master
and in
39 other branches
atmel_tc library
Create <linux/atmel_tc.h> based on <asm-arm/arch-at91/at91-tc.h> and the at91sam9263 and at32ap7000 datasheets. Most AT91 and AT32 SOCs have one or two of these TC blocks, which include three 16-bit timers that can be interconnected in various ways. These TC blocks can be used for external interfacing (such as PWM and measurement), or used as somewhat quirky sixteen-bit timers. Changes relative to the original version: * Drop unneeded inclusion of <linux/mutex.h> * Support an arbitrary number of TC blocks * Return a struct with information about a TC block from atmel_tc_alloc() instead of using a combination of return values and "out" parameters. * ioremap() the I/O registers on allocation * Look up clocks and irqs for all channels * Add "name" parameter to atmel_tc_alloc() and use this when requesting the iomem resource. * Check if the platform provided the necessary resources at probe() time instead of when the TCB is allocated. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Showing 4 changed files with 422 additions and 0 deletions Side-by-side Diff
drivers/misc/Kconfig
... | ... | @@ -22,6 +22,14 @@ |
22 | 22 | purposes including software controlled power-efficent backlights |
23 | 23 | on LCD displays, motor control, and waveform generation. |
24 | 24 | |
25 | +config ATMEL_TCLIB | |
26 | + bool "Atmel AT32/AT91 Timer/Counter Library" | |
27 | + depends on (AVR32 || ARCH_AT91) | |
28 | + help | |
29 | + Select this if you want a library to allocate the Timer/Counter | |
30 | + blocks found on many Atmel processors. This facilitates using | |
31 | + these blocks by different drivers despite processor differences. | |
32 | + | |
25 | 33 | config IBM_ASM |
26 | 34 | tristate "Device driver for IBM RSA service processor" |
27 | 35 | depends on X86 && PCI && INPUT && EXPERIMENTAL |
drivers/misc/Makefile
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o |
11 | 11 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o |
12 | 12 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
13 | +obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | |
13 | 14 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
14 | 15 | obj-$(CONFIG_LKDTM) += lkdtm.o |
15 | 16 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o |
drivers/misc/atmel_tclib.c
1 | +#include <linux/atmel_tc.h> | |
2 | +#include <linux/clk.h> | |
3 | +#include <linux/err.h> | |
4 | +#include <linux/init.h> | |
5 | +#include <linux/io.h> | |
6 | +#include <linux/ioport.h> | |
7 | +#include <linux/kernel.h> | |
8 | +#include <linux/platform_device.h> | |
9 | + | |
10 | +/* Number of bytes to reserve for the iomem resource */ | |
11 | +#define ATMEL_TC_IOMEM_SIZE 256 | |
12 | + | |
13 | + | |
14 | +/* | |
15 | + * This is a thin library to solve the problem of how to portably allocate | |
16 | + * one of the TC blocks. For simplicity, it doesn't currently expect to | |
17 | + * share individual timers between different drivers. | |
18 | + */ | |
19 | + | |
20 | +#if defined(CONFIG_AVR32) | |
21 | +/* AVR32 has these divide PBB */ | |
22 | +const u8 atmel_tc_divisors[5] = { 0, 4, 8, 16, 32, }; | |
23 | +EXPORT_SYMBOL(atmel_tc_divisors); | |
24 | + | |
25 | +#elif defined(CONFIG_ARCH_AT91) | |
26 | +/* AT91 has these divide MCK */ | |
27 | +const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, }; | |
28 | +EXPORT_SYMBOL(atmel_tc_divisors); | |
29 | + | |
30 | +#endif | |
31 | + | |
32 | +static DEFINE_SPINLOCK(tc_list_lock); | |
33 | +static LIST_HEAD(tc_list); | |
34 | + | |
35 | +/** | |
36 | + * atmel_tc_alloc - allocate a specified TC block | |
37 | + * @block: which block to allocate | |
38 | + * @name: name to be associated with the iomem resource | |
39 | + * | |
40 | + * Caller allocates a block. If it is available, a pointer to a | |
41 | + * pre-initialized struct atmel_tc is returned. The caller can access | |
42 | + * the registers directly through the "regs" field. | |
43 | + */ | |
44 | +struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name) | |
45 | +{ | |
46 | + struct atmel_tc *tc; | |
47 | + struct platform_device *pdev = NULL; | |
48 | + struct resource *r; | |
49 | + | |
50 | + spin_lock(&tc_list_lock); | |
51 | + list_for_each_entry(tc, &tc_list, node) { | |
52 | + if (tc->pdev->id == block) { | |
53 | + pdev = tc->pdev; | |
54 | + break; | |
55 | + } | |
56 | + } | |
57 | + | |
58 | + if (!pdev || tc->iomem) | |
59 | + goto fail; | |
60 | + | |
61 | + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
62 | + r = request_mem_region(r->start, ATMEL_TC_IOMEM_SIZE, name); | |
63 | + if (!r) | |
64 | + goto fail; | |
65 | + | |
66 | + tc->regs = ioremap(r->start, ATMEL_TC_IOMEM_SIZE); | |
67 | + if (!tc->regs) | |
68 | + goto fail_ioremap; | |
69 | + | |
70 | + tc->iomem = r; | |
71 | + | |
72 | +out: | |
73 | + spin_unlock(&tc_list_lock); | |
74 | + return tc; | |
75 | + | |
76 | +fail_ioremap: | |
77 | + release_resource(r); | |
78 | +fail: | |
79 | + tc = NULL; | |
80 | + goto out; | |
81 | +} | |
82 | +EXPORT_SYMBOL_GPL(atmel_tc_alloc); | |
83 | + | |
84 | +/** | |
85 | + * atmel_tc_free - release a specified TC block | |
86 | + * @tc: Timer/counter block that was returned by atmel_tc_alloc() | |
87 | + * | |
88 | + * This reverses the effect of atmel_tc_alloc(), unmapping the I/O | |
89 | + * registers, invalidating the resource returned by that routine and | |
90 | + * making the TC available to other drivers. | |
91 | + */ | |
92 | +void atmel_tc_free(struct atmel_tc *tc) | |
93 | +{ | |
94 | + spin_lock(&tc_list_lock); | |
95 | + if (tc->regs) { | |
96 | + iounmap(tc->regs); | |
97 | + release_resource(tc->iomem); | |
98 | + tc->regs = NULL; | |
99 | + tc->iomem = NULL; | |
100 | + } | |
101 | + spin_unlock(&tc_list_lock); | |
102 | +} | |
103 | +EXPORT_SYMBOL_GPL(atmel_tc_free); | |
104 | + | |
105 | +static int __init tc_probe(struct platform_device *pdev) | |
106 | +{ | |
107 | + struct atmel_tc *tc; | |
108 | + struct clk *clk; | |
109 | + int irq; | |
110 | + | |
111 | + if (!platform_get_resource(pdev, IORESOURCE_MEM, 0)) | |
112 | + return -EINVAL; | |
113 | + | |
114 | + irq = platform_get_irq(pdev, 0); | |
115 | + if (irq < 0) | |
116 | + return -EINVAL; | |
117 | + | |
118 | + tc = kzalloc(sizeof(struct atmel_tc), GFP_KERNEL); | |
119 | + if (!tc) | |
120 | + return -ENOMEM; | |
121 | + | |
122 | + tc->pdev = pdev; | |
123 | + | |
124 | + clk = clk_get(&pdev->dev, "t0_clk"); | |
125 | + if (IS_ERR(clk)) { | |
126 | + kfree(tc); | |
127 | + return -EINVAL; | |
128 | + } | |
129 | + | |
130 | + tc->clk[0] = clk; | |
131 | + tc->clk[1] = clk_get(&pdev->dev, "t1_clk"); | |
132 | + if (IS_ERR(tc->clk[1])) | |
133 | + tc->clk[1] = clk; | |
134 | + tc->clk[2] = clk_get(&pdev->dev, "t2_clk"); | |
135 | + if (IS_ERR(tc->clk[2])) | |
136 | + tc->clk[2] = clk; | |
137 | + | |
138 | + tc->irq[0] = irq; | |
139 | + tc->irq[1] = platform_get_irq(pdev, 1); | |
140 | + if (tc->irq[1] < 0) | |
141 | + tc->irq[1] = irq; | |
142 | + tc->irq[2] = platform_get_irq(pdev, 2); | |
143 | + if (tc->irq[2] < 0) | |
144 | + tc->irq[2] = irq; | |
145 | + | |
146 | + spin_lock(&tc_list_lock); | |
147 | + list_add_tail(&tc->node, &tc_list); | |
148 | + spin_unlock(&tc_list_lock); | |
149 | + | |
150 | + return 0; | |
151 | +} | |
152 | + | |
153 | +static struct platform_driver tc_driver = { | |
154 | + .driver.name = "atmel_tcb", | |
155 | +}; | |
156 | + | |
157 | +static int __init tc_init(void) | |
158 | +{ | |
159 | + return platform_driver_probe(&tc_driver, tc_probe); | |
160 | +} | |
161 | +arch_initcall(tc_init); |
include/linux/atmel_tc.h
1 | +/* | |
2 | + * Timer/Counter Unit (TC) registers. | |
3 | + * | |
4 | + * This program is free software; you can redistribute it and/or modify | |
5 | + * it under the terms of the GNU General Public License as published by | |
6 | + * the Free Software Foundation; either version 2 of the License, or | |
7 | + * (at your option) any later version. | |
8 | + */ | |
9 | + | |
10 | +#ifndef ATMEL_TC_H | |
11 | +#define ATMEL_TC_H | |
12 | + | |
13 | +#include <linux/compiler.h> | |
14 | +#include <linux/list.h> | |
15 | + | |
16 | +/* | |
17 | + * Many 32-bit Atmel SOCs include one or more TC blocks, each of which holds | |
18 | + * three general-purpose 16-bit timers. These timers share one register bank. | |
19 | + * Depending on the SOC, each timer may have its own clock and IRQ, or those | |
20 | + * may be shared by the whole TC block. | |
21 | + * | |
22 | + * These TC blocks may have up to nine external pins: TCLK0..2 signals for | |
23 | + * clocks or clock gates, and per-timer TIOA and TIOB signals used for PWM | |
24 | + * or triggering. Those pins need to be set up for use with the TC block, | |
25 | + * else they will be used as GPIOs or for a different controller. | |
26 | + * | |
27 | + * Although we expect each TC block to have a platform_device node, those | |
28 | + * nodes are not what drivers bind to. Instead, they ask for a specific | |
29 | + * TC block, by number ... which is a common approach on systems with many | |
30 | + * timers. Then they use clk_get() and platform_get_irq() to get clock and | |
31 | + * IRQ resources. | |
32 | + */ | |
33 | + | |
34 | +struct clk; | |
35 | + | |
36 | +/** | |
37 | + * struct atmel_tc - information about a Timer/Counter Block | |
38 | + * @pdev: physical device | |
39 | + * @iomem: resource associated with the I/O register | |
40 | + * @regs: mapping through which the I/O registers can be accessed | |
41 | + * @irq: irq for each of the three channels | |
42 | + * @clk: internal clock source for each of the three channels | |
43 | + * @node: list node, for tclib internal use | |
44 | + * | |
45 | + * On some platforms, each TC channel has its own clocks and IRQs, | |
46 | + * while on others, all TC channels share the same clock and IRQ. | |
47 | + * Drivers should clk_enable() all the clocks they need even though | |
48 | + * all the entries in @clk may point to the same physical clock. | |
49 | + * Likewise, drivers should request irqs independently for each | |
50 | + * channel, but they must use IRQF_SHARED in case some of the entries | |
51 | + * in @irq are actually the same IRQ. | |
52 | + */ | |
53 | +struct atmel_tc { | |
54 | + struct platform_device *pdev; | |
55 | + struct resource *iomem; | |
56 | + void __iomem *regs; | |
57 | + int irq[3]; | |
58 | + struct clk *clk[3]; | |
59 | + struct list_head node; | |
60 | +}; | |
61 | + | |
62 | +extern struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name); | |
63 | +extern void atmel_tc_free(struct atmel_tc *tc); | |
64 | + | |
65 | +/* platform-specific ATMEL_TC_TIMER_CLOCKx divisors (0 means 32KiHz) */ | |
66 | +extern const u8 atmel_tc_divisors[5]; | |
67 | + | |
68 | + | |
69 | +/* | |
70 | + * Two registers have block-wide controls. These are: configuring the three | |
71 | + * "external" clocks (or event sources) used by the timer channels; and | |
72 | + * synchronizing the timers by resetting them all at once. | |
73 | + * | |
74 | + * "External" can mean "external to chip" using the TCLK0, TCLK1, or TCLK2 | |
75 | + * signals. Or, it can mean "external to timer", using the TIOA output from | |
76 | + * one of the other two timers that's being run in waveform mode. | |
77 | + */ | |
78 | + | |
79 | +#define ATMEL_TC_BCR 0xc0 /* TC Block Control Register */ | |
80 | +#define ATMEL_TC_SYNC (1 << 0) /* synchronize timers */ | |
81 | + | |
82 | +#define ATMEL_TC_BMR 0xc4 /* TC Block Mode Register */ | |
83 | +#define ATMEL_TC_TC0XC0S (3 << 0) /* external clock 0 source */ | |
84 | +#define ATMEL_TC_TC0XC0S_TCLK0 (0 << 0) | |
85 | +#define ATMEL_TC_TC0XC0S_NONE (1 << 0) | |
86 | +#define ATMEL_TC_TC0XC0S_TIOA1 (2 << 0) | |
87 | +#define ATMEL_TC_TC0XC0S_TIOA2 (3 << 0) | |
88 | +#define ATMEL_TC_TC1XC1S (3 << 2) /* external clock 1 source */ | |
89 | +#define ATMEL_TC_TC1XC1S_TCLK1 (0 << 2) | |
90 | +#define ATMEL_TC_TC1XC1S_NONE (1 << 2) | |
91 | +#define ATMEL_TC_TC1XC1S_TIOA0 (2 << 2) | |
92 | +#define ATMEL_TC_TC1XC1S_TIOA2 (3 << 2) | |
93 | +#define ATMEL_TC_TC2XC2S (3 << 4) /* external clock 2 source */ | |
94 | +#define ATMEL_TC_TC2XC2S_TCLK2 (0 << 4) | |
95 | +#define ATMEL_TC_TC2XC2S_NONE (1 << 4) | |
96 | +#define ATMEL_TC_TC2XC2S_TIOA0 (2 << 4) | |
97 | +#define ATMEL_TC_TC2XC2S_TIOA1 (3 << 4) | |
98 | + | |
99 | + | |
100 | +/* | |
101 | + * Each TC block has three "channels", each with one counter and controls. | |
102 | + * | |
103 | + * Note that the semantics of ATMEL_TC_TIMER_CLOCKx (input clock selection | |
104 | + * when it's not "external") is silicon-specific. AT91 platforms use one | |
105 | + * set of definitions; AVR32 platforms use a different set. Don't hard-wire | |
106 | + * such knowledge into your code, use the global "atmel_tc_divisors" ... | |
107 | + * where index N is the divisor for clock N+1, else zero to indicate it uses | |
108 | + * the 32 KiHz clock. | |
109 | + * | |
110 | + * The timers can be chained in various ways, and operated in "waveform" | |
111 | + * generation mode (including PWM) or "capture" mode (to time events). In | |
112 | + * both modes, behavior can be configured in many ways. | |
113 | + * | |
114 | + * Each timer has two I/O pins, TIOA and TIOB. Waveform mode uses TIOA as a | |
115 | + * PWM output, and TIOB as either another PWM or as a trigger. Capture mode | |
116 | + * uses them only as inputs. | |
117 | + */ | |
118 | +#define ATMEL_TC_CHAN(idx) ((idx)*0x40) | |
119 | +#define ATMEL_TC_REG(idx, reg) (ATMEL_TC_CHAN(idx) + ATMEL_TC_ ## reg) | |
120 | + | |
121 | +#define ATMEL_TC_CCR 0x00 /* Channel Control Register */ | |
122 | +#define ATMEL_TC_CLKEN (1 << 0) /* clock enable */ | |
123 | +#define ATMEL_TC_CLKDIS (1 << 1) /* clock disable */ | |
124 | +#define ATMEL_TC_SWTRG (1 << 2) /* software trigger */ | |
125 | + | |
126 | +#define ATMEL_TC_CMR 0x04 /* Channel Mode Register */ | |
127 | + | |
128 | +/* Both modes share some CMR bits */ | |
129 | +#define ATMEL_TC_TCCLKS (7 << 0) /* clock source */ | |
130 | +#define ATMEL_TC_TIMER_CLOCK1 (0 << 0) | |
131 | +#define ATMEL_TC_TIMER_CLOCK2 (1 << 0) | |
132 | +#define ATMEL_TC_TIMER_CLOCK3 (2 << 0) | |
133 | +#define ATMEL_TC_TIMER_CLOCK4 (3 << 0) | |
134 | +#define ATMEL_TC_TIMER_CLOCK5 (4 << 0) | |
135 | +#define ATMEL_TC_XC0 (5 << 0) | |
136 | +#define ATMEL_TC_XC1 (6 << 0) | |
137 | +#define ATMEL_TC_XC2 (7 << 0) | |
138 | +#define ATMEL_TC_CLKI (1 << 3) /* clock invert */ | |
139 | +#define ATMEL_TC_BURST (3 << 4) /* clock gating */ | |
140 | +#define ATMEL_TC_GATE_NONE (0 << 4) | |
141 | +#define ATMEL_TC_GATE_XC0 (1 << 4) | |
142 | +#define ATMEL_TC_GATE_XC1 (2 << 4) | |
143 | +#define ATMEL_TC_GATE_XC2 (3 << 4) | |
144 | +#define ATMEL_TC_WAVE (1 << 15) /* true = Waveform mode */ | |
145 | + | |
146 | +/* CAPTURE mode CMR bits */ | |
147 | +#define ATMEL_TC_LDBSTOP (1 << 6) /* counter stops on RB load */ | |
148 | +#define ATMEL_TC_LDBDIS (1 << 7) /* counter disable on RB load */ | |
149 | +#define ATMEL_TC_ETRGEDG (3 << 8) /* external trigger edge */ | |
150 | +#define ATMEL_TC_ETRGEDG_NONE (0 << 8) | |
151 | +#define ATMEL_TC_ETRGEDG_RISING (1 << 8) | |
152 | +#define ATMEL_TC_ETRGEDG_FALLING (2 << 8) | |
153 | +#define ATMEL_TC_ETRGEDG_BOTH (3 << 8) | |
154 | +#define ATMEL_TC_ABETRG (1 << 10) /* external trigger is TIOA? */ | |
155 | +#define ATMEL_TC_CPCTRG (1 << 14) /* RC compare trigger enable */ | |
156 | +#define ATMEL_TC_LDRA (3 << 16) /* RA loading edge (of TIOA) */ | |
157 | +#define ATMEL_TC_LDRA_NONE (0 << 16) | |
158 | +#define ATMEL_TC_LDRA_RISING (1 << 16) | |
159 | +#define ATMEL_TC_LDRA_FALLING (2 << 16) | |
160 | +#define ATMEL_TC_LDRA_BOTH (3 << 16) | |
161 | +#define ATMEL_TC_LDRB (3 << 18) /* RB loading edge (of TIOA) */ | |
162 | +#define ATMEL_TC_LDRB_NONE (0 << 18) | |
163 | +#define ATMEL_TC_LDRB_RISING (1 << 18) | |
164 | +#define ATMEL_TC_LDRB_FALLING (2 << 18) | |
165 | +#define ATMEL_TC_LDRB_BOTH (3 << 18) | |
166 | + | |
167 | +/* WAVEFORM mode CMR bits */ | |
168 | +#define ATMEL_TC_CPCSTOP (1 << 6) /* RC compare stops counter */ | |
169 | +#define ATMEL_TC_CPCDIS (1 << 7) /* RC compare disables counter */ | |
170 | +#define ATMEL_TC_EEVTEDG (3 << 8) /* external event edge */ | |
171 | +#define ATMEL_TC_EEVTEDG_NONE (0 << 8) | |
172 | +#define ATMEL_TC_EEVTEDG_RISING (1 << 8) | |
173 | +#define ATMEL_TC_EEVTEDG_FALLING (2 << 8) | |
174 | +#define ATMEL_TC_EEVTEDG_BOTH (3 << 8) | |
175 | +#define ATMEL_TC_EEVT (3 << 10) /* external event source */ | |
176 | +#define ATMEL_TC_EEVT_TIOB (0 << 10) | |
177 | +#define ATMEL_TC_EEVT_XC0 (1 << 10) | |
178 | +#define ATMEL_TC_EEVT_XC1 (2 << 10) | |
179 | +#define ATMEL_TC_EEVT_XC2 (3 << 10) | |
180 | +#define ATMEL_TC_ENETRG (1 << 12) /* external event is trigger */ | |
181 | +#define ATMEL_TC_WAVESEL (3 << 13) /* waveform type */ | |
182 | +#define ATMEL_TC_WAVESEL_UP (0 << 13) | |
183 | +#define ATMEL_TC_WAVESEL_UPDOWN (1 << 13) | |
184 | +#define ATMEL_TC_WAVESEL_UP_AUTO (2 << 13) | |
185 | +#define ATMEL_TC_WAVESEL_UPDOWN_AUTO (3 << 13) | |
186 | +#define ATMEL_TC_ACPA (3 << 16) /* RA compare changes TIOA */ | |
187 | +#define ATMEL_TC_ACPA_NONE (0 << 16) | |
188 | +#define ATMEL_TC_ACPA_SET (1 << 16) | |
189 | +#define ATMEL_TC_ACPA_CLEAR (2 << 16) | |
190 | +#define ATMEL_TC_ACPA_TOGGLE (3 << 16) | |
191 | +#define ATMEL_TC_ACPC (3 << 18) /* RC compare changes TIOA */ | |
192 | +#define ATMEL_TC_ACPC_NONE (0 << 18) | |
193 | +#define ATMEL_TC_ACPC_SET (1 << 18) | |
194 | +#define ATMEL_TC_ACPC_CLEAR (2 << 18) | |
195 | +#define ATMEL_TC_ACPC_TOGGLE (3 << 18) | |
196 | +#define ATMEL_TC_AEEVT (3 << 20) /* external event changes TIOA */ | |
197 | +#define ATMEL_TC_AEEVT_NONE (0 << 20) | |
198 | +#define ATMEL_TC_AEEVT_SET (1 << 20) | |
199 | +#define ATMEL_TC_AEEVT_CLEAR (2 << 20) | |
200 | +#define ATMEL_TC_AEEVT_TOGGLE (3 << 20) | |
201 | +#define ATMEL_TC_ASWTRG (3 << 22) /* software trigger changes TIOA */ | |
202 | +#define ATMEL_TC_ASWTRG_NONE (0 << 22) | |
203 | +#define ATMEL_TC_ASWTRG_SET (1 << 22) | |
204 | +#define ATMEL_TC_ASWTRG_CLEAR (2 << 22) | |
205 | +#define ATMEL_TC_ASWTRG_TOGGLE (3 << 22) | |
206 | +#define ATMEL_TC_BCPB (3 << 24) /* RB compare changes TIOB */ | |
207 | +#define ATMEL_TC_BCPB_NONE (0 << 24) | |
208 | +#define ATMEL_TC_BCPB_SET (1 << 24) | |
209 | +#define ATMEL_TC_BCPB_CLEAR (2 << 24) | |
210 | +#define ATMEL_TC_BCPB_TOGGLE (3 << 24) | |
211 | +#define ATMEL_TC_BCPC (3 << 26) /* RC compare changes TIOB */ | |
212 | +#define ATMEL_TC_BCPC_NONE (0 << 26) | |
213 | +#define ATMEL_TC_BCPC_SET (1 << 26) | |
214 | +#define ATMEL_TC_BCPC_CLEAR (2 << 26) | |
215 | +#define ATMEL_TC_BCPC_TOGGLE (3 << 26) | |
216 | +#define ATMEL_TC_BEEVT (3 << 28) /* external event changes TIOB */ | |
217 | +#define ATMEL_TC_BEEVT_NONE (0 << 28) | |
218 | +#define ATMEL_TC_BEEVT_SET (1 << 28) | |
219 | +#define ATMEL_TC_BEEVT_CLEAR (2 << 28) | |
220 | +#define ATMEL_TC_BEEVT_TOGGLE (3 << 28) | |
221 | +#define ATMEL_TC_BSWTRG (3 << 30) /* software trigger changes TIOB */ | |
222 | +#define ATMEL_TC_BSWTRG_NONE (0 << 30) | |
223 | +#define ATMEL_TC_BSWTRG_SET (1 << 30) | |
224 | +#define ATMEL_TC_BSWTRG_CLEAR (2 << 30) | |
225 | +#define ATMEL_TC_BSWTRG_TOGGLE (3 << 30) | |
226 | + | |
227 | +#define ATMEL_TC_CV 0x10 /* counter Value */ | |
228 | +#define ATMEL_TC_RA 0x14 /* register A */ | |
229 | +#define ATMEL_TC_RB 0x18 /* register B */ | |
230 | +#define ATMEL_TC_RC 0x1c /* register C */ | |
231 | + | |
232 | +#define ATMEL_TC_SR 0x20 /* status (read-only) */ | |
233 | +/* Status-only flags */ | |
234 | +#define ATMEL_TC_CLKSTA (1 << 16) /* clock enabled */ | |
235 | +#define ATMEL_TC_MTIOA (1 << 17) /* TIOA mirror */ | |
236 | +#define ATMEL_TC_MTIOB (1 << 18) /* TIOB mirror */ | |
237 | + | |
238 | +#define ATMEL_TC_IER 0x24 /* interrupt enable (write-only) */ | |
239 | +#define ATMEL_TC_IDR 0x28 /* interrupt disable (write-only) */ | |
240 | +#define ATMEL_TC_IMR 0x2c /* interrupt mask (read-only) */ | |
241 | + | |
242 | +/* Status and IRQ flags */ | |
243 | +#define ATMEL_TC_COVFS (1 << 0) /* counter overflow */ | |
244 | +#define ATMEL_TC_LOVRS (1 << 1) /* load overrun */ | |
245 | +#define ATMEL_TC_CPAS (1 << 2) /* RA compare */ | |
246 | +#define ATMEL_TC_CPBS (1 << 3) /* RB compare */ | |
247 | +#define ATMEL_TC_CPCS (1 << 4) /* RC compare */ | |
248 | +#define ATMEL_TC_LDRAS (1 << 5) /* RA loading */ | |
249 | +#define ATMEL_TC_LDRBS (1 << 6) /* RB loading */ | |
250 | +#define ATMEL_TC_ETRGS (1 << 7) /* external trigger */ | |
251 | + | |
252 | +#endif |