summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/clk_gk20a.h
blob: f07efa407eb6362153799207560f193be6074694 (plain) (blame)
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
/*
 * Copyright (c) 2011 - 2017, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
 */
#ifndef CLK_GK20A_H
#define CLK_GK20A_H

#include <nvgpu/lock.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>

#define GPUFREQ_TABLE_END     ~(u32)1
enum {
	/* only one PLL for gk20a */
	GK20A_GPC_PLL = 0,
	/* 2 PLL revisions for gm20b */
	GM20B_GPC_PLL_B1,
	GM20B_GPC_PLL_C1,
};

enum gpc_pll_mode {
	GPC_PLL_MODE_F = 0,	/* fixed frequency mode a.k.a legacy mode */
	GPC_PLL_MODE_DVFS,	/* DVFS mode a.k.a NA mode */
};

struct na_dvfs {
	u32 n_int;
	u32 sdm_din;
	int dfs_coeff;
	int dfs_det_max;
	int dfs_ext_cal;
	int uv_cal;
	int mv;
};

struct pll {
	u32 id;
	u32 clk_in;	/* KHz */
	u32 M;
	u32 N;
	u32 PL;
	u32 freq;	/* KHz */
	bool enabled;
	enum gpc_pll_mode mode;
	struct na_dvfs dvfs;
};

struct pll_parms {
	u32 min_freq, max_freq;	/* KHz */
	u32 min_vco, max_vco;	/* KHz */
	u32 min_u,   max_u;	/* KHz */
	u32 min_M,   max_M;
	u32 min_N,   max_N;
	u32 min_PL,  max_PL;
	/* NA mode parameters*/
	int coeff_slope, coeff_offs; /* coeff = slope * V + offs */
	int uvdet_slope, uvdet_offs; /* uV = slope * det + offs */
	u32 vco_ctrl;
	/*
	 * Timing parameters in us. Lock timeout is applied to locking in fixed
	 * frequency mode and to dynamic ramp in any mode; does not affect lock
	 * latency, since lock/ramp done status bit is polled. NA mode lock and
	 * and IDDQ exit delays set the time of the respective opertaions with
	 * no status polling.
	 */
	u32 lock_timeout;
	u32 na_lock_delay;
	u32 iddq_exit_delay;
};

struct namemap_cfg;

struct clk_gk20a {
	struct gk20a *g;
	struct clk *tegra_clk;
#if defined(CONFIG_COMMON_CLK)
	struct clk_hw hw;
#endif
	struct pll gpc_pll;
	struct pll gpc_pll_last;
	struct nvgpu_mutex clk_mutex;
	struct namemap_cfg *clk_namemap;
	u32 namemap_num;
	u32 *namemap_xlat_table;
	bool sw_ready;
	bool clk_hw_on;
	bool debugfs_set;
	int pll_poweron_uv;
};

#if defined(CONFIG_COMMON_CLK)
#define to_clk_gk20a(_hw) container_of(_hw, struct clk_gk20a, hw)
#endif

struct gpu_ops;
#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
void gk20a_init_clk_ops(struct gpu_ops *gops);
#else
static inline void gk20a_init_clk_ops(struct gpu_ops *gops) {}
#endif

/* APIs used for both GK20A and GM20B */
unsigned long gk20a_clk_get_rate(struct gk20a *g);
int gk20a_clk_set_rate(struct gk20a *g, unsigned long rate);
long gk20a_clk_round_rate(struct gk20a *g, unsigned long rate);
struct clk *gk20a_clk_get(struct gk20a *g);

#define KHZ 1000
#define MHZ 1000000

static inline unsigned long rate_gpc2clk_to_gpu(unsigned long rate)
{
	/* convert the kHz gpc2clk frequency to Hz gpcpll frequency */
	return (rate * KHZ) / 2;
}
static inline unsigned long rate_gpu_to_gpc2clk(unsigned long rate)
{
	/* convert the Hz gpcpll frequency to kHz gpc2clk frequency */
	return (rate * 2) / KHZ;
}

#endif /* CLK_GK20A_H */