aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/clock.h
blob: 50383fb028d9f1ca9a21acf01350bcb210884fdb (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
/*
 *  Copyright (C) 2010 ST-Ericsson SA
 *  Copyright (C) 2009 STMicrolectronics
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

/**
 * struct clkops - ux500 clock operations
 * @enable:	function to enable the clock
 * @disable:	function to disable the clock
 * @get_rate:	function to get the current clock rate
 *
 * This structure contains function pointers to functions that will be used to
 * control the clock.  All of these functions are optional.  If get_rate is
 * NULL, the rate in the struct clk will be used.
 */
extern int __init clk_init(void);

/*PLLSW clk src macros */
#define PLL_SW_SOC0 0x20
#define PLL_SW_SOC1 0x40
#define PLL_SW_DDR 0x80
#define PLL_SELECT_BITS 0xE0

/*Mode clk src macros */
#define MODE_NO_CLK 0x0
#define MODE_CLK32KHZ 0x1
#define MODE_CLK38_4MHZ 0x2
#define MODE_PLL_CLK 0x4

/* Function declarion */
void update_clk_tree(void);

/*CLK38 clk src macros */
#define CLK38_SRC 0x400
#define CLK38 0x200
/* Clock enable bit */
#define ENABLE_BIT 0x100

struct clkops {
	void (*enable) (struct clk *);
	void (*disable) (struct clk *);
	unsigned long (*get_rate) (struct clk *);
};

/**
 * struct clk - ux500 clock structure
 * @ops:		pointer to clkops struct used to control this clock
 * @name:		name, for debugging
 * @enabled:		refcount. positive if enabled, zero if disabled
 * @rate:		fixed rate for clocks which don't implement
 * 			ops->getrate
 * @prcmu_cg_off:	address offset of the combined enable/disable register
 * 			(used on u8500v1)
 * @prcmu_cg_bit:	bit in the combined enable/disable register (used on
 * 			u8500v1)
 * @prcmu_cg_mgt:	address of the enable/disable register (used on
 * 			u8500ed)
 * @cluster:		peripheral cluster number
 * @prcc_bus:		bit for the bus clock in the peripheral's CLKRST
 * @prcc_kernel:	bit for the kernel clock in the peripheral's CLKRST.
 * 			-1 if no kernel clock exists.
 * @parent_cluster:	pointer to parent's cluster clk struct
 * @parent_periph:	pointer to parent's peripheral clk struct
 *
 * Peripherals are organised into clusters, and each cluster has an associated
 * bus clock.  Some peripherals also have a parent peripheral clock.
 *
 * In order to enable a clock for a peripheral, we need to enable:
 * 	(1) the parent cluster (bus) clock at the PRCMU level
 * 	(2) the parent peripheral clock (if any) at the PRCMU level
 * 	(3) the peripheral's bus & kernel clock at the PRCC level
 *
 * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each
 * of the cluster and peripheral clocks, and hooking these as the parents of
 * the individual peripheral clocks.
 *
 * (3) is handled by specifying the bits in the PRCC control registers required
 * to enable these clocks and modifying them in the ->enable and
 * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK).
 *
 * This structure describes both the PRCMU-level clocks and PRCC-level clocks.
 * The prcmu_* fields are only used for the PRCMU clocks, and the cluster,
 * prcc, and parent pointers are only used for the PRCC-level clocks.
 */
struct clk {
	const struct clkops	*ops;
	const char 		*name;
	unsigned int		enabled;

	unsigned long		rate;
	struct list_head	list;

	/* These three are only for PRCMU clks */

	unsigned int		prcmu_cg_off;
	unsigned int		prcmu_cg_bit;
	unsigned int		prcmu_cg_mgt;

	/* The rest are only for PRCC clks */

	int			cluster;
	int			prcc_bus;
	int			prcc_kernel;

	struct clk		*parent_cluster;
	struct clk		*parent_periph;
	struct clk		*clk_src;
	int		is_clk_src;
};

#define DEFINE_CLK_SRC_PLL(_name)		\
struct clk clk_##_name = {							\
		.name		=	#_name,					\
		.ops		=	&clk_pll_ops,				\
		.clk_src	=	NULL,					\
		.is_clk_src	=	1,				\
		.enabled	=	0						\
	}

#define DEFINE_CLK_SRC_MAIN(_name)		\
struct clk clk_##_name = {							\
		.name		=	#_name,					\
		.clk_src	=	NULL,					\
		.is_clk_src	=	2,				\
		.enabled	=	0						\
	}

#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg)		\
struct clk clk_##_name = {					\
		.name		= #_name,			\
		.ops    	= &clk_prcmu_ops, 		\
		.prcmu_cg_off	= _cg_off, 			\
		.prcmu_cg_bit	= _cg_bit,			\
		.prcmu_cg_mgt	= PRCM_##_reg##_MGT		\
	}

#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate)	\
struct clk clk_##_name = {						\
		.name		= #_name,				\
		.ops    	= &clk_prcmu_ops, 			\
		.prcmu_cg_off	= _cg_off, 				\
		.prcmu_cg_bit	= _cg_bit,				\
		.rate		= _rate,				\
		.prcmu_cg_mgt	= PRCM_##_reg##_MGT			\
	}

#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk)	\
struct clk clk_##_name = {						\
		.name		= #_name,				\
		.ops    	= &clk_prcc_ops, 			\
		.cluster 	= _pclust,				\
		.prcc_bus 	= _bus_en, 				\
		.prcc_kernel 	= _kernel_en, 				\
		.parent_cluster = &clk_per##_pclust##clk,		\
		.parent_periph 	= _kernclk				\
	}

#define CLK(_clk, _devname, _conname)			\
	{						\
		.clk	= &clk_##_clk,			\
		.dev_id	= _devname,			\
		.con_id = _conname,			\
	}