summaryrefslogtreecommitdiff
path: root/include/asm-avr32/arch-at32ap700x/clk.h
blob: b2710a4ba8584f2a0a765177a75f4e04a9c58854 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Copyright (C) 2006 Atmel Corporation
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */
#ifndef __ASM_AVR32_ARCH_CLK_H__
#define __ASM_AVR32_ARCH_CLK_H__

#include <asm/arch/chip-features.h>
#include <asm/arch/portmux.h>

#ifdef CONFIG_PLL
#define PLL0_RATE	((CFG_OSC0_HZ / CFG_PLL0_DIV) * CFG_PLL0_MUL)
#define MAIN_CLK_RATE	PLL0_RATE
#else
#define MAIN_CLK_RATE	(CFG_OSC0_HZ)
#endif

static inline unsigned long get_cpu_clk_rate(void)
{
	return MAIN_CLK_RATE >> CFG_CLKDIV_CPU;
}
static inline unsigned long get_hsb_clk_rate(void)
{
	return MAIN_CLK_RATE >> CFG_CLKDIV_HSB;
}
static inline unsigned long get_pba_clk_rate(void)
{
	return MAIN_CLK_RATE >> CFG_CLKDIV_PBA;
}
static inline unsigned long get_pbb_clk_rate(void)
{
	return MAIN_CLK_RATE >> CFG_CLKDIV_PBB;
}

/* Accessors for specific devices. More will be added as needed. */
static inline unsigned long get_sdram_clk_rate(void)
{
	return get_hsb_clk_rate();
}
#ifdef AT32AP700x_CHIP_HAS_USART
static inline unsigned long get_usart_clk_rate(unsigned int dev_id)
{
	return get_pba_clk_rate();
}
#endif
#ifdef AT32AP700x_CHIP_HAS_MACB
static inline unsigned long get_macb_pclk_rate(unsigned int dev_id)
{
	return get_pbb_clk_rate();
}
static inline unsigned long get_macb_hclk_rate(unsigned int dev_id)
{
	return get_hsb_clk_rate();
}
#endif
#ifdef AT32AP700x_CHIP_HAS_MMCI
static inline unsigned long get_mci_clk_rate(void)
{
	return get_pbb_clk_rate();
}
#endif
#ifdef AT32AP700x_CHIP_HAS_SPI
static inline unsigned long get_spi_clk_rate(unsigned int dev_id)
{
	return get_pba_clk_rate();
}
#endif

extern void clk_init(void);
extern void gclk_init(void) __attribute__((weak));

/* Board code may need the SDRAM base clock as a compile-time constant */
#define SDRAMC_BUS_HZ	(MAIN_CLK_RATE >> CFG_CLKDIV_HSB)

/* Generic clock control */
enum gclk_parent {
	GCLK_PARENT_OSC0 = 0,
	GCLK_PARENT_OSC1 = 1,
	GCLK_PARENT_PLL0 = 2,
	GCLK_PARENT_PLL1 = 3,
};

/* Some generic clocks have specific roles */
#define GCLK_DAC_SAMPLE_CLK	6
#define GCLK_LCDC_PIXCLK	7

extern unsigned long __gclk_set_rate(unsigned int id, enum gclk_parent parent,
		unsigned long rate, unsigned long parent_rate);

/**
 * gclk_set_rate - configure and enable a generic clock
 * @id: Which GCLK[id] to enable
 * @parent: Parent clock feeding the GCLK
 * @rate: Target rate of the GCLK in Hz
 *
 * Returns the actual GCLK rate in Hz, after rounding to the nearest
 * supported rate.
 *
 * All three parameters are usually constant, hence the inline.
 */
static inline unsigned long gclk_set_rate(unsigned int id,
		enum gclk_parent parent, unsigned long rate)
{
	unsigned long parent_rate;

	if (id > 7)
		return 0;

	switch (parent) {
	case GCLK_PARENT_OSC0:
		parent_rate = CFG_OSC0_HZ;
		break;
#ifdef CFG_OSC1_HZ
	case GCLK_PARENT_OSC1:
		parent_rate = CFG_OSC1_HZ;
		break;
#endif
#ifdef PLL0_RATE
	case GCLK_PARENT_PLL0:
		parent_rate = PLL0_RATE;
		break;
#endif
#ifdef PLL1_RATE
	case GCLK_PARENT_PLL1:
		parent_rate = PLL1_RATE;
		break;
#endif
	default:
		parent_rate = 0;
		break;
	}

	return __gclk_set_rate(id, parent, rate, parent_rate);
}

/**
 * gclk_enable_output - enable output on a GCLK pin
 * @id: Which GCLK[id] pin to enable
 * @drive_strength: Drive strength of external GCLK pin, if applicable
 */
static inline void gclk_enable_output(unsigned int id,
		unsigned long drive_strength)
{
	switch (id) {
	case 0:
		portmux_select_peripheral(PORTMUX_PORT_A, 1 << 30,
				PORTMUX_FUNC_A, drive_strength);
		break;
	case 1:
		portmux_select_peripheral(PORTMUX_PORT_A, 1 << 31,
				PORTMUX_FUNC_A, drive_strength);
		break;
	case 2:
		portmux_select_peripheral(PORTMUX_PORT_B, 1 << 19,
				PORTMUX_FUNC_A, drive_strength);
		break;
	case 3:
		portmux_select_peripheral(PORTMUX_PORT_B, 1 << 29,
				PORTMUX_FUNC_A, drive_strength);
		break;
	case 4:
		portmux_select_peripheral(PORTMUX_PORT_B, 1 << 30,
				PORTMUX_FUNC_A, drive_strength);
		break;
	}
}

#endif /* __ASM_AVR32_ARCH_CLK_H__ */