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
|
/*
* Copyright (C) 2010 ST-Ericsson
* Copyright (C) 2009 STMicroelectronics
*
* 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.
*/
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;
unsigned int prcc_bus;
unsigned int prcc_kernel;
struct clk *parent_cluster;
struct clk *parent_periph;
};
#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, \
}
|