162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Timer/Counter Unit (TC) registers. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 562306a36Sopenharmony_ci * it under the terms of the GNU General Public License as published by 662306a36Sopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 762306a36Sopenharmony_ci * (at your option) any later version. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef __SOC_ATMEL_TCB_H 1162306a36Sopenharmony_ci#define __SOC_ATMEL_TCB_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/compiler.h> 1462306a36Sopenharmony_ci#include <linux/list.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* 1762306a36Sopenharmony_ci * Many 32-bit Atmel SOCs include one or more TC blocks, each of which holds 1862306a36Sopenharmony_ci * three general-purpose 16-bit timers. These timers share one register bank. 1962306a36Sopenharmony_ci * Depending on the SOC, each timer may have its own clock and IRQ, or those 2062306a36Sopenharmony_ci * may be shared by the whole TC block. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * These TC blocks may have up to nine external pins: TCLK0..2 signals for 2362306a36Sopenharmony_ci * clocks or clock gates, and per-timer TIOA and TIOB signals used for PWM 2462306a36Sopenharmony_ci * or triggering. Those pins need to be set up for use with the TC block, 2562306a36Sopenharmony_ci * else they will be used as GPIOs or for a different controller. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * Although we expect each TC block to have a platform_device node, those 2862306a36Sopenharmony_ci * nodes are not what drivers bind to. Instead, they ask for a specific 2962306a36Sopenharmony_ci * TC block, by number ... which is a common approach on systems with many 3062306a36Sopenharmony_ci * timers. Then they use clk_get() and platform_get_irq() to get clock and 3162306a36Sopenharmony_ci * IRQ resources. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct clk; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/** 3762306a36Sopenharmony_ci * struct atmel_tcb_config - SoC data for a Timer/Counter Block 3862306a36Sopenharmony_ci * @counter_width: size in bits of a timer counter register 3962306a36Sopenharmony_ci * @has_gclk: boolean indicating if a timer counter has a generic clock 4062306a36Sopenharmony_ci * @has_qdec: boolean indicating if a timer counter has a quadrature 4162306a36Sopenharmony_ci * decoder. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_cistruct atmel_tcb_config { 4462306a36Sopenharmony_ci size_t counter_width; 4562306a36Sopenharmony_ci bool has_gclk; 4662306a36Sopenharmony_ci bool has_qdec; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/** 5062306a36Sopenharmony_ci * struct atmel_tc - information about a Timer/Counter Block 5162306a36Sopenharmony_ci * @pdev: physical device 5262306a36Sopenharmony_ci * @regs: mapping through which the I/O registers can be accessed 5362306a36Sopenharmony_ci * @id: block id 5462306a36Sopenharmony_ci * @tcb_config: configuration data from SoC 5562306a36Sopenharmony_ci * @irq: irq for each of the three channels 5662306a36Sopenharmony_ci * @clk: internal clock source for each of the three channels 5762306a36Sopenharmony_ci * @node: list node, for tclib internal use 5862306a36Sopenharmony_ci * @allocated: if already used, for tclib internal use 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * On some platforms, each TC channel has its own clocks and IRQs, 6162306a36Sopenharmony_ci * while on others, all TC channels share the same clock and IRQ. 6262306a36Sopenharmony_ci * Drivers should clk_enable() all the clocks they need even though 6362306a36Sopenharmony_ci * all the entries in @clk may point to the same physical clock. 6462306a36Sopenharmony_ci * Likewise, drivers should request irqs independently for each 6562306a36Sopenharmony_ci * channel, but they must use IRQF_SHARED in case some of the entries 6662306a36Sopenharmony_ci * in @irq are actually the same IRQ. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistruct atmel_tc { 6962306a36Sopenharmony_ci struct platform_device *pdev; 7062306a36Sopenharmony_ci void __iomem *regs; 7162306a36Sopenharmony_ci int id; 7262306a36Sopenharmony_ci const struct atmel_tcb_config *tcb_config; 7362306a36Sopenharmony_ci int irq[3]; 7462306a36Sopenharmony_ci struct clk *clk[3]; 7562306a36Sopenharmony_ci struct clk *slow_clk; 7662306a36Sopenharmony_ci struct list_head node; 7762306a36Sopenharmony_ci bool allocated; 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* platform-specific ATMEL_TC_TIMER_CLOCKx divisors (0 means 32KiHz) */ 8162306a36Sopenharmony_ciextern const u8 atmel_tc_divisors[5]; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* 8562306a36Sopenharmony_ci * Two registers have block-wide controls. These are: configuring the three 8662306a36Sopenharmony_ci * "external" clocks (or event sources) used by the timer channels; and 8762306a36Sopenharmony_ci * synchronizing the timers by resetting them all at once. 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * "External" can mean "external to chip" using the TCLK0, TCLK1, or TCLK2 9062306a36Sopenharmony_ci * signals. Or, it can mean "external to timer", using the TIOA output from 9162306a36Sopenharmony_ci * one of the other two timers that's being run in waveform mode. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define ATMEL_TC_BCR 0xc0 /* TC Block Control Register */ 9562306a36Sopenharmony_ci#define ATMEL_TC_SYNC (1 << 0) /* synchronize timers */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define ATMEL_TC_BMR 0xc4 /* TC Block Mode Register */ 9862306a36Sopenharmony_ci#define ATMEL_TC_TC0XC0S (3 << 0) /* external clock 0 source */ 9962306a36Sopenharmony_ci#define ATMEL_TC_TC0XC0S_TCLK0 (0 << 0) 10062306a36Sopenharmony_ci#define ATMEL_TC_TC0XC0S_NONE (1 << 0) 10162306a36Sopenharmony_ci#define ATMEL_TC_TC0XC0S_TIOA1 (2 << 0) 10262306a36Sopenharmony_ci#define ATMEL_TC_TC0XC0S_TIOA2 (3 << 0) 10362306a36Sopenharmony_ci#define ATMEL_TC_TC1XC1S (3 << 2) /* external clock 1 source */ 10462306a36Sopenharmony_ci#define ATMEL_TC_TC1XC1S_TCLK1 (0 << 2) 10562306a36Sopenharmony_ci#define ATMEL_TC_TC1XC1S_NONE (1 << 2) 10662306a36Sopenharmony_ci#define ATMEL_TC_TC1XC1S_TIOA0 (2 << 2) 10762306a36Sopenharmony_ci#define ATMEL_TC_TC1XC1S_TIOA2 (3 << 2) 10862306a36Sopenharmony_ci#define ATMEL_TC_TC2XC2S (3 << 4) /* external clock 2 source */ 10962306a36Sopenharmony_ci#define ATMEL_TC_TC2XC2S_TCLK2 (0 << 4) 11062306a36Sopenharmony_ci#define ATMEL_TC_TC2XC2S_NONE (1 << 4) 11162306a36Sopenharmony_ci#define ATMEL_TC_TC2XC2S_TIOA0 (2 << 4) 11262306a36Sopenharmony_ci#define ATMEL_TC_TC2XC2S_TIOA1 (3 << 4) 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * Each TC block has three "channels", each with one counter and controls. 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * Note that the semantics of ATMEL_TC_TIMER_CLOCKx (input clock selection 11962306a36Sopenharmony_ci * when it's not "external") is silicon-specific. AT91 platforms use one 12062306a36Sopenharmony_ci * set of definitions; AVR32 platforms use a different set. Don't hard-wire 12162306a36Sopenharmony_ci * such knowledge into your code, use the global "atmel_tc_divisors" ... 12262306a36Sopenharmony_ci * where index N is the divisor for clock N+1, else zero to indicate it uses 12362306a36Sopenharmony_ci * the 32 KiHz clock. 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * The timers can be chained in various ways, and operated in "waveform" 12662306a36Sopenharmony_ci * generation mode (including PWM) or "capture" mode (to time events). In 12762306a36Sopenharmony_ci * both modes, behavior can be configured in many ways. 12862306a36Sopenharmony_ci * 12962306a36Sopenharmony_ci * Each timer has two I/O pins, TIOA and TIOB. Waveform mode uses TIOA as a 13062306a36Sopenharmony_ci * PWM output, and TIOB as either another PWM or as a trigger. Capture mode 13162306a36Sopenharmony_ci * uses them only as inputs. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ci#define ATMEL_TC_CHAN(idx) ((idx)*0x40) 13462306a36Sopenharmony_ci#define ATMEL_TC_REG(idx, reg) (ATMEL_TC_CHAN(idx) + ATMEL_TC_ ## reg) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#define ATMEL_TC_CCR 0x00 /* Channel Control Register */ 13762306a36Sopenharmony_ci#define ATMEL_TC_CLKEN (1 << 0) /* clock enable */ 13862306a36Sopenharmony_ci#define ATMEL_TC_CLKDIS (1 << 1) /* clock disable */ 13962306a36Sopenharmony_ci#define ATMEL_TC_SWTRG (1 << 2) /* software trigger */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci#define ATMEL_TC_CMR 0x04 /* Channel Mode Register */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* Both modes share some CMR bits */ 14462306a36Sopenharmony_ci#define ATMEL_TC_TCCLKS (7 << 0) /* clock source */ 14562306a36Sopenharmony_ci#define ATMEL_TC_TIMER_CLOCK1 (0 << 0) 14662306a36Sopenharmony_ci#define ATMEL_TC_TIMER_CLOCK2 (1 << 0) 14762306a36Sopenharmony_ci#define ATMEL_TC_TIMER_CLOCK3 (2 << 0) 14862306a36Sopenharmony_ci#define ATMEL_TC_TIMER_CLOCK4 (3 << 0) 14962306a36Sopenharmony_ci#define ATMEL_TC_TIMER_CLOCK5 (4 << 0) 15062306a36Sopenharmony_ci#define ATMEL_TC_XC0 (5 << 0) 15162306a36Sopenharmony_ci#define ATMEL_TC_XC1 (6 << 0) 15262306a36Sopenharmony_ci#define ATMEL_TC_XC2 (7 << 0) 15362306a36Sopenharmony_ci#define ATMEL_TC_CLKI (1 << 3) /* clock invert */ 15462306a36Sopenharmony_ci#define ATMEL_TC_BURST (3 << 4) /* clock gating */ 15562306a36Sopenharmony_ci#define ATMEL_TC_GATE_NONE (0 << 4) 15662306a36Sopenharmony_ci#define ATMEL_TC_GATE_XC0 (1 << 4) 15762306a36Sopenharmony_ci#define ATMEL_TC_GATE_XC1 (2 << 4) 15862306a36Sopenharmony_ci#define ATMEL_TC_GATE_XC2 (3 << 4) 15962306a36Sopenharmony_ci#define ATMEL_TC_WAVE (1 << 15) /* true = Waveform mode */ 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* CAPTURE mode CMR bits */ 16262306a36Sopenharmony_ci#define ATMEL_TC_LDBSTOP (1 << 6) /* counter stops on RB load */ 16362306a36Sopenharmony_ci#define ATMEL_TC_LDBDIS (1 << 7) /* counter disable on RB load */ 16462306a36Sopenharmony_ci#define ATMEL_TC_ETRGEDG (3 << 8) /* external trigger edge */ 16562306a36Sopenharmony_ci#define ATMEL_TC_ETRGEDG_NONE (0 << 8) 16662306a36Sopenharmony_ci#define ATMEL_TC_ETRGEDG_RISING (1 << 8) 16762306a36Sopenharmony_ci#define ATMEL_TC_ETRGEDG_FALLING (2 << 8) 16862306a36Sopenharmony_ci#define ATMEL_TC_ETRGEDG_BOTH (3 << 8) 16962306a36Sopenharmony_ci#define ATMEL_TC_ABETRG (1 << 10) /* external trigger is TIOA? */ 17062306a36Sopenharmony_ci#define ATMEL_TC_CPCTRG (1 << 14) /* RC compare trigger enable */ 17162306a36Sopenharmony_ci#define ATMEL_TC_LDRA (3 << 16) /* RA loading edge (of TIOA) */ 17262306a36Sopenharmony_ci#define ATMEL_TC_LDRA_NONE (0 << 16) 17362306a36Sopenharmony_ci#define ATMEL_TC_LDRA_RISING (1 << 16) 17462306a36Sopenharmony_ci#define ATMEL_TC_LDRA_FALLING (2 << 16) 17562306a36Sopenharmony_ci#define ATMEL_TC_LDRA_BOTH (3 << 16) 17662306a36Sopenharmony_ci#define ATMEL_TC_LDRB (3 << 18) /* RB loading edge (of TIOA) */ 17762306a36Sopenharmony_ci#define ATMEL_TC_LDRB_NONE (0 << 18) 17862306a36Sopenharmony_ci#define ATMEL_TC_LDRB_RISING (1 << 18) 17962306a36Sopenharmony_ci#define ATMEL_TC_LDRB_FALLING (2 << 18) 18062306a36Sopenharmony_ci#define ATMEL_TC_LDRB_BOTH (3 << 18) 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci/* WAVEFORM mode CMR bits */ 18362306a36Sopenharmony_ci#define ATMEL_TC_CPCSTOP (1 << 6) /* RC compare stops counter */ 18462306a36Sopenharmony_ci#define ATMEL_TC_CPCDIS (1 << 7) /* RC compare disables counter */ 18562306a36Sopenharmony_ci#define ATMEL_TC_EEVTEDG (3 << 8) /* external event edge */ 18662306a36Sopenharmony_ci#define ATMEL_TC_EEVTEDG_NONE (0 << 8) 18762306a36Sopenharmony_ci#define ATMEL_TC_EEVTEDG_RISING (1 << 8) 18862306a36Sopenharmony_ci#define ATMEL_TC_EEVTEDG_FALLING (2 << 8) 18962306a36Sopenharmony_ci#define ATMEL_TC_EEVTEDG_BOTH (3 << 8) 19062306a36Sopenharmony_ci#define ATMEL_TC_EEVT (3 << 10) /* external event source */ 19162306a36Sopenharmony_ci#define ATMEL_TC_EEVT_TIOB (0 << 10) 19262306a36Sopenharmony_ci#define ATMEL_TC_EEVT_XC0 (1 << 10) 19362306a36Sopenharmony_ci#define ATMEL_TC_EEVT_XC1 (2 << 10) 19462306a36Sopenharmony_ci#define ATMEL_TC_EEVT_XC2 (3 << 10) 19562306a36Sopenharmony_ci#define ATMEL_TC_ENETRG (1 << 12) /* external event is trigger */ 19662306a36Sopenharmony_ci#define ATMEL_TC_WAVESEL (3 << 13) /* waveform type */ 19762306a36Sopenharmony_ci#define ATMEL_TC_WAVESEL_UP (0 << 13) 19862306a36Sopenharmony_ci#define ATMEL_TC_WAVESEL_UPDOWN (1 << 13) 19962306a36Sopenharmony_ci#define ATMEL_TC_WAVESEL_UP_AUTO (2 << 13) 20062306a36Sopenharmony_ci#define ATMEL_TC_WAVESEL_UPDOWN_AUTO (3 << 13) 20162306a36Sopenharmony_ci#define ATMEL_TC_ACPA (3 << 16) /* RA compare changes TIOA */ 20262306a36Sopenharmony_ci#define ATMEL_TC_ACPA_NONE (0 << 16) 20362306a36Sopenharmony_ci#define ATMEL_TC_ACPA_SET (1 << 16) 20462306a36Sopenharmony_ci#define ATMEL_TC_ACPA_CLEAR (2 << 16) 20562306a36Sopenharmony_ci#define ATMEL_TC_ACPA_TOGGLE (3 << 16) 20662306a36Sopenharmony_ci#define ATMEL_TC_ACPC (3 << 18) /* RC compare changes TIOA */ 20762306a36Sopenharmony_ci#define ATMEL_TC_ACPC_NONE (0 << 18) 20862306a36Sopenharmony_ci#define ATMEL_TC_ACPC_SET (1 << 18) 20962306a36Sopenharmony_ci#define ATMEL_TC_ACPC_CLEAR (2 << 18) 21062306a36Sopenharmony_ci#define ATMEL_TC_ACPC_TOGGLE (3 << 18) 21162306a36Sopenharmony_ci#define ATMEL_TC_AEEVT (3 << 20) /* external event changes TIOA */ 21262306a36Sopenharmony_ci#define ATMEL_TC_AEEVT_NONE (0 << 20) 21362306a36Sopenharmony_ci#define ATMEL_TC_AEEVT_SET (1 << 20) 21462306a36Sopenharmony_ci#define ATMEL_TC_AEEVT_CLEAR (2 << 20) 21562306a36Sopenharmony_ci#define ATMEL_TC_AEEVT_TOGGLE (3 << 20) 21662306a36Sopenharmony_ci#define ATMEL_TC_ASWTRG (3 << 22) /* software trigger changes TIOA */ 21762306a36Sopenharmony_ci#define ATMEL_TC_ASWTRG_NONE (0 << 22) 21862306a36Sopenharmony_ci#define ATMEL_TC_ASWTRG_SET (1 << 22) 21962306a36Sopenharmony_ci#define ATMEL_TC_ASWTRG_CLEAR (2 << 22) 22062306a36Sopenharmony_ci#define ATMEL_TC_ASWTRG_TOGGLE (3 << 22) 22162306a36Sopenharmony_ci#define ATMEL_TC_BCPB (3 << 24) /* RB compare changes TIOB */ 22262306a36Sopenharmony_ci#define ATMEL_TC_BCPB_NONE (0 << 24) 22362306a36Sopenharmony_ci#define ATMEL_TC_BCPB_SET (1 << 24) 22462306a36Sopenharmony_ci#define ATMEL_TC_BCPB_CLEAR (2 << 24) 22562306a36Sopenharmony_ci#define ATMEL_TC_BCPB_TOGGLE (3 << 24) 22662306a36Sopenharmony_ci#define ATMEL_TC_BCPC (3 << 26) /* RC compare changes TIOB */ 22762306a36Sopenharmony_ci#define ATMEL_TC_BCPC_NONE (0 << 26) 22862306a36Sopenharmony_ci#define ATMEL_TC_BCPC_SET (1 << 26) 22962306a36Sopenharmony_ci#define ATMEL_TC_BCPC_CLEAR (2 << 26) 23062306a36Sopenharmony_ci#define ATMEL_TC_BCPC_TOGGLE (3 << 26) 23162306a36Sopenharmony_ci#define ATMEL_TC_BEEVT (3 << 28) /* external event changes TIOB */ 23262306a36Sopenharmony_ci#define ATMEL_TC_BEEVT_NONE (0 << 28) 23362306a36Sopenharmony_ci#define ATMEL_TC_BEEVT_SET (1 << 28) 23462306a36Sopenharmony_ci#define ATMEL_TC_BEEVT_CLEAR (2 << 28) 23562306a36Sopenharmony_ci#define ATMEL_TC_BEEVT_TOGGLE (3 << 28) 23662306a36Sopenharmony_ci#define ATMEL_TC_BSWTRG (3 << 30) /* software trigger changes TIOB */ 23762306a36Sopenharmony_ci#define ATMEL_TC_BSWTRG_NONE (0 << 30) 23862306a36Sopenharmony_ci#define ATMEL_TC_BSWTRG_SET (1 << 30) 23962306a36Sopenharmony_ci#define ATMEL_TC_BSWTRG_CLEAR (2 << 30) 24062306a36Sopenharmony_ci#define ATMEL_TC_BSWTRG_TOGGLE (3 << 30) 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci#define ATMEL_TC_CV 0x10 /* counter Value */ 24362306a36Sopenharmony_ci#define ATMEL_TC_RA 0x14 /* register A */ 24462306a36Sopenharmony_ci#define ATMEL_TC_RB 0x18 /* register B */ 24562306a36Sopenharmony_ci#define ATMEL_TC_RC 0x1c /* register C */ 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci#define ATMEL_TC_SR 0x20 /* status (read-only) */ 24862306a36Sopenharmony_ci/* Status-only flags */ 24962306a36Sopenharmony_ci#define ATMEL_TC_CLKSTA (1 << 16) /* clock enabled */ 25062306a36Sopenharmony_ci#define ATMEL_TC_MTIOA (1 << 17) /* TIOA mirror */ 25162306a36Sopenharmony_ci#define ATMEL_TC_MTIOB (1 << 18) /* TIOB mirror */ 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci#define ATMEL_TC_IER 0x24 /* interrupt enable (write-only) */ 25462306a36Sopenharmony_ci#define ATMEL_TC_IDR 0x28 /* interrupt disable (write-only) */ 25562306a36Sopenharmony_ci#define ATMEL_TC_IMR 0x2c /* interrupt mask (read-only) */ 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/* Status and IRQ flags */ 25862306a36Sopenharmony_ci#define ATMEL_TC_COVFS (1 << 0) /* counter overflow */ 25962306a36Sopenharmony_ci#define ATMEL_TC_LOVRS (1 << 1) /* load overrun */ 26062306a36Sopenharmony_ci#define ATMEL_TC_CPAS (1 << 2) /* RA compare */ 26162306a36Sopenharmony_ci#define ATMEL_TC_CPBS (1 << 3) /* RB compare */ 26262306a36Sopenharmony_ci#define ATMEL_TC_CPCS (1 << 4) /* RC compare */ 26362306a36Sopenharmony_ci#define ATMEL_TC_LDRAS (1 << 5) /* RA loading */ 26462306a36Sopenharmony_ci#define ATMEL_TC_LDRBS (1 << 6) /* RB loading */ 26562306a36Sopenharmony_ci#define ATMEL_TC_ETRGS (1 << 7) /* external trigger */ 26662306a36Sopenharmony_ci#define ATMEL_TC_ALL_IRQ (ATMEL_TC_COVFS | ATMEL_TC_LOVRS | \ 26762306a36Sopenharmony_ci ATMEL_TC_CPAS | ATMEL_TC_CPBS | \ 26862306a36Sopenharmony_ci ATMEL_TC_CPCS | ATMEL_TC_LDRAS | \ 26962306a36Sopenharmony_ci ATMEL_TC_LDRBS | ATMEL_TC_ETRGS) \ 27062306a36Sopenharmony_ci /* all IRQs */ 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci#endif 273