Project

General

Profile

Download (4.85 KB) Statistics
| Branch: | Tag: | Revision:
1 1dfa375a henryk
/* OpenPC TC (Timer / Clock) support code
2
 * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
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
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program; if not, write to the Free Software
16
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * This idea of this code is to feed the 13.56MHz carrier clock of RC632
19
 * into TCLK1, which is routed to XC1.  Then configure TC0 to divide this
20
 * clock by a configurable divider.
21
 *
22
 */
23
24
#include <lib_AT91SAM7.h>
25
#include <AT91SAM7.h>
26 ee1f0214 henryk
#include "dbgu.h"
27 1dfa375a henryk
28 ee1f0214 henryk
#include "openpicc.h"
29
#include "tc_cdiv.h"
30 ceb64338 henryk
#include "led.h"
31 1dfa375a henryk
32 ee1f0214 henryk
AT91PS_TCB tcb = AT91C_BASE_TCB;
33 1dfa375a henryk
34
/* set carrier divider to a specific */
35 ceb64338 henryk
void __ramfunc tc_cdiv_set_divider(u_int16_t div)
36 1dfa375a henryk
{
37 a72e0c20 henryk
	if(OPENPICC->features.clock_gating) {
38
		if(tcb->TCB_TC0.TC_CV > div
39
				/* Don't spin if FRAME_BURST is clear, the clock is stopped in this case */
40
				&& !(!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC->CLOCK_GATE))
41
		) {
42
			while(tcb->TCB_TC0.TC_CV > 3); /* Three carrier cycles are about 10 clock cycles, should be enough for the loop */  
43
		}
44
	} else {
45
		if(tcb->TCB_TC0.TC_CV > div) {
46
			while(tcb->TCB_TC0.TC_CV > 3); /* Three carrier cycles are about 10 clock cycles, should be enough for the loop */  
47
		}
48 fa61e60d henryk
	}
49 1dfa375a henryk
	tcb->TCB_TC0.TC_RC = div;
50
51
	/* set to 50% duty cycle */
52
	tcb->TCB_TC0.TC_RA = 1;
53
	tcb->TCB_TC0.TC_RB = 1 + (div >> 1);
54 e22f23ef henryk
	
55 f0087983 henryk
	/* We must reset CV to zero when it was greater than RC.
56
	 * In order to not lose phase information when doing that we'll busy wait till CV is
57
	 * zero modulo the new RC.*/
58 a72e0c20 henryk
	if(OPENPICC->features.clock_gating) {
59
		if(tcb->TCB_TC0.TC_CV > div
60
				/* Don't spin if FRAME_BURST is clear, the clock is stopped in this case */
61
				&& !(!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC->CLOCK_GATE))
62
		) {
63
			while(tcb->TCB_TC0.TC_CV % div != 0);
64
			tcb->TCB_TC0.TC_CCR = AT91C_TC_SWTRG;
65
		}
66
	} else {
67
		if(tcb->TCB_TC0.TC_CV > div) {
68
			while(tcb->TCB_TC0.TC_CV % div != 0);
69
			tcb->TCB_TC0.TC_CCR = AT91C_TC_SWTRG;
70
		}
71 ceb64338 henryk
	}
72 1dfa375a henryk
}
73
74 ceb64338 henryk
void __ramfunc tc_cdiv_phase_add(int16_t inc)
75 1dfa375a henryk
{
76
	tcb->TCB_TC0.TC_RA = (tcb->TCB_TC0.TC_RA + inc) % tcb->TCB_TC0.TC_RC;
77
	tcb->TCB_TC0.TC_RB = (tcb->TCB_TC0.TC_RB + inc) % tcb->TCB_TC0.TC_RC;
78
79
	/* FIXME: can this be done more elegantly? */
80
	if (tcb->TCB_TC0.TC_RA == 0) {
81
		tcb->TCB_TC0.TC_RA += 1;
82
		tcb->TCB_TC0.TC_RB += 1;
83
	}
84
}
85
86 5ec39e97 henryk
void tc_cdiv_reset(void)
87
{
88
	/* Reset to start timers */
89
	tcb->TCB_BCR = 1;
90
}
91
92 1dfa375a henryk
void tc_cdiv_init(void)
93
{
94
	/* Cfg PA28(TCLK1), PA0(TIOA0), PA1(TIOB0), PA20(TCLK2) as Periph B */
95
	AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, 
96 ee1f0214 henryk
			    OPENPICC_PIO_CARRIER_IN |
97
			    OPENPICC_PIO_CARRIER_DIV_OUT |
98
			    OPENPICC_PIO_CDIV_HELP_OUT |
99 a72e0c20 henryk
			    OPENPICC_PIO_CDIV_HELP_IN);
100
	if(OPENPICC->features.clock_gating)
101
		AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, OPENPICC->CLOCK_GATE); 
102 1dfa375a henryk
103
	AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 
104
				    ((unsigned int) 1 << AT91C_ID_TC0));
105
106
	/* Enable Clock for TC0 */
107
	tcb->TCB_TC0.TC_CCR = AT91C_TC_CLKEN;
108
109
	/* Connect TCLK1 to XC1, TCLK2 to XC2 */
110
	tcb->TCB_BMR &= ~(AT91C_TCB_TC1XC1S | AT91C_TCB_TC2XC2S);
111
	tcb->TCB_BMR |=  (AT91C_TCB_TC1XC1S_TCLK1 | AT91C_TCB_TC2XC2S_TCLK2);
112 f06c7a7f henryk
#ifdef OPENPICC_USE_CLOCK_GATING
113 5ec39e97 henryk
	/* Connect TCLK0 to XC0 */
114
	tcb->TCB_BMR &= ~(AT91C_TCB_TC0XC0S);
115
	tcb->TCB_BMR |=  (AT91C_TCB_TC0XC0S_TCLK0);
116
#endif
117 1dfa375a henryk
118
	/* Clock XC1, Wave mode, Reset on RC comp
119
	 * TIOA0 on RA comp = set, * TIOA0 on RC comp = clear,
120
	 * TIOB0 on EEVT = set, TIOB0 on RB comp = clear,
121 5ec39e97 henryk
	 * EEVT = XC2 (TIOA0) 
122 a72e0c20 henryk
	 * if features.clock_gating: BURST on XC0 */
123 1dfa375a henryk
	tcb->TCB_TC0.TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE |
124
			      AT91C_TC_WAVESEL_UP_AUTO | 
125
			      AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR |
126
			      AT91C_TC_BEEVT_SET | AT91C_TC_BCPB_CLEAR |
127
			      AT91C_TC_EEVT_XC2 | AT91C_TC_ETRGEDG_RISING |
128 5ec39e97 henryk
			      AT91C_TC_BSWTRG_CLEAR | AT91C_TC_ASWTRG_CLEAR
129 a72e0c20 henryk
				| (OPENPICC->features.clock_gating ? AT91C_TC_BURST_XC0 : 0)
130 5ec39e97 henryk
			      ;
131 1dfa375a henryk
132
	tc_cdiv_set_divider(128);
133
134 5ec39e97 henryk
	tc_cdiv_reset();
135 1dfa375a henryk
}
136
137
void tc_cdiv_print(void)
138
{
139
	DEBUGP("TCB_BMR=0x%08x ", tcb->TCB_BMR);
140
	DEBUGP("TC0_CV=0x%08x ", tcb->TCB_TC0.TC_CV);
141
	DEBUGP("TC0_CMR=0x%08x ", tcb->TCB_TC0.TC_CMR);
142
	DEBUGPCR("TC0_SR=0x%08x", tcb->TCB_TC0.TC_SR);
143
144
	DEBUGPCR("TC0_RA=0x%04x, TC0_RB=0x%04x, TC0_RC=0x%04x",
145
		 tcb->TCB_TC0.TC_RA, tcb->TCB_TC0.TC_RB, tcb->TCB_TC0.TC_RC);
146
}
147
148
void tc_cdiv_fini(void)
149
{
150
	tcb->TCB_TC0.TC_CCR = AT91C_TC_CLKDIS;
151
	AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,
152
				     ((unsigned int) 1 << AT91C_ID_TC0));
153
}
Add picture from clipboard (Maximum size: 48.8 MB)