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
|
/*
*
* Copyright (C) 2010 Google, Inc.
*
* Author:
* Colin Cross <ccross@google.com>
*
* Copyright (C) 2010-2011 NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#ifndef _TEGRA_DVFS_H_
#define _TEGRA_DVFS_H_
#define MAX_DVFS_FREQS 18
struct clk;
struct dvfs_rail;
/*
* dvfs_relationship between to rails, "from" and "to"
* when the rail changes, it will call dvfs_rail_update on the rails
* in the relationship_to list.
* when determining the voltage to set a rail to, it will consider each
* rail in the relationship_from list.
*/
struct dvfs_relationship {
struct dvfs_rail *to;
struct dvfs_rail *from;
int (*solve)(struct dvfs_rail *, struct dvfs_rail *);
struct list_head to_node; /* node in relationship_to list */
struct list_head from_node; /* node in relationship_from list */
bool solved_at_nominal;
};
struct rail_stats {
ktime_t time_at_mv[MAX_DVFS_FREQS + 1];
ktime_t last_update;
int last_index;
};
struct dvfs_rail {
const char *reg_id;
int min_millivolts;
int max_millivolts;
int nominal_millivolts;
int step;
bool disabled;
bool updating;
bool resolving_to;
struct list_head node; /* node in dvfs_rail_list */
struct list_head dvfs; /* list head of attached dvfs clocks */
struct list_head relationships_to;
struct list_head relationships_from;
struct regulator *reg;
int millivolts;
int new_millivolts;
bool suspended;
struct rail_stats stats;
};
struct dvfs {
/* Used only by tegra2_clock.c */
const char *clk_name;
int speedo_id;
int process_id;
/* Must be initialized before tegra_dvfs_init */
int freqs_mult;
unsigned long freqs[MAX_DVFS_FREQS];
const int *millivolts;
struct dvfs_rail *dvfs_rail;
bool auto_dvfs;
/* Filled in by tegra_dvfs_init */
int max_millivolts;
int num_freqs;
int cur_millivolts;
unsigned long cur_rate;
struct list_head node;
struct list_head debug_node;
struct list_head reg_node;
};
extern struct dvfs_rail *tegra_cpu_rail;
#ifdef CONFIG_TEGRA_SILICON_PLATFORM
void tegra_soc_init_dvfs(void);
int tegra_enable_dvfs_on_clk(struct clk *c, struct dvfs *d);
int dvfs_debugfs_init(struct dentry *clk_debugfs_root);
int tegra_dvfs_late_init(void);
int tegra_dvfs_init_rails(struct dvfs_rail *dvfs_rails[], int n);
void tegra_dvfs_add_relationships(struct dvfs_relationship *rels, int n);
void tegra_dvfs_rail_enable(struct dvfs_rail *rail);
void tegra_dvfs_rail_disable(struct dvfs_rail *rail);
bool tegra_dvfs_rail_updating(struct clk *clk);
void tegra_dvfs_rail_off(struct dvfs_rail *rail, ktime_t now);
void tegra_dvfs_rail_on(struct dvfs_rail *rail, ktime_t now);
void tegra_dvfs_rail_pause(struct dvfs_rail *rail, ktime_t delta, bool on);
struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id);
int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
#else
static inline void tegra_soc_init_dvfs(void)
{}
static inline int tegra_enable_dvfs_on_clk(struct clk *c, struct dvfs *d)
{ return 0; }
static inline int dvfs_debugfs_init(struct dentry *clk_debugfs_root)
{ return 0; }
static inline int tegra_dvfs_late_init(void)
{ return 0; }
static inline int tegra_dvfs_init_rails(struct dvfs_rail *dvfs_rails[], int n)
{ return 0; }
static inline void tegra_dvfs_add_relationships(struct dvfs_relationship *rels, int n)
{}
static inline void tegra_dvfs_rail_enable(struct dvfs_rail *rail)
{}
static inline void tegra_dvfs_rail_disable(struct dvfs_rail *rail)
{}
static inline bool tegra_dvfs_rail_updating(struct clk *clk)
{ return false; }
static inline void tegra_dvfs_rail_off(struct dvfs_rail *rail, ktime_t now)
{}
static inline void tegra_dvfs_rail_on(struct dvfs_rail *rail, ktime_t now)
{}
static inline void tegra_dvfs_rail_pause(
struct dvfs_rail *rail, ktime_t delta, bool on)
{}
static inline struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id)
{ return NULL;}
static inline int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
{ return 0; }
#endif
#endif
|