summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra_cl_dvfs.h
blob: e37abe3dde60f71778bf565f4933a31265c0c94d (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
/*
 * arch/arm/mach-tegra/tegra_cl_dvfs.h
 *
 * Copyright (c) 2012-2014 NVIDIA Corporation. All rights reserved.
 *
 * 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.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#ifndef _TEGRA_CL_DVFS_H_
#define _TEGRA_CL_DVFS_H_

struct tegra_cl_dvfs;

#define MAX_CL_DVFS_VOLTAGES		33

enum tegra_cl_dvfs_force_mode {
	TEGRA_CL_DVFS_FORCE_NONE = 0,
	TEGRA_CL_DVFS_FORCE_FIXED = 1,
	TEGRA_CL_DVFS_FORCE_AUTO = 2,
};

enum tegra_cl_dvfs_pmu_if {
	TEGRA_CL_DVFS_PMU_I2C,
	TEGRA_CL_DVFS_PMU_PWM,
};

enum tegra_cl_dvfs_pwm_bus {
	TEGRA_CL_DVFS_PWM_1WIRE_BUFFER,
	TEGRA_CL_DVFS_PWM_1WIRE_DIRECT,
	TEGRA_CL_DVFS_PWM_2WIRE,
};

/* CL DVFS plaform flags*/
/* set if output to PMU can be disabled only between I2C transactions */
#define TEGRA_CL_DVFS_FLAGS_I2C_WAIT_QUIET	(0x1UL << 0)
/* dynamic output registers update is supported */
#define TEGRA_CL_DVFS_DYN_OUTPUT_CFG		(0x1UL << 1)
/* monitor data new synchronization can not be used */
#define TEGRA_CL_DVFS_DATA_NEW_NO_USE		(0x1UL << 2)

struct tegra_cl_dvfs_cfg_param {
	unsigned long	sample_rate;

	enum tegra_cl_dvfs_force_mode force_mode;
	u8		cf;
	u8		ci;
	s8		cg;
	bool		cg_scale;

	u8		droop_cut_value;
	u8		droop_restore_ramp;
	u8		scale_out_ramp;
};

struct voltage_reg_map {
	u8		reg_value;
	int		reg_uV;
};

struct tegra_cl_dvfs_platform_data {
	const char *dfll_clk_name;
	u32 flags;

	enum tegra_cl_dvfs_pmu_if pmu_if;
	union {
		struct {
			unsigned long		fs_rate;
			unsigned long		hs_rate; /* if 0 - no hs mode */
			u8			hs_master_code;
			u8			reg;
			u16			slave_addr;
			bool			addr_10;
			u32			sel_mul;
			u32			sel_offs;
		} pmu_i2c;
		struct {
			unsigned long		pwm_rate;
			bool			delta_mode;
			int			min_uV;
			int			step_uV;

			enum tegra_cl_dvfs_pwm_bus pwm_bus;
			int			pwm_pingroup;
			int			pwm_clk_pingroup;
			int			out_gpio;
			bool			out_enable_high;
			struct platform_device	*dfll_bypass_dev;
		} pmu_pwm;
	} u;

	struct voltage_reg_map	*vdd_map;
	int			vdd_map_size;
	int			pmu_undershoot_gb;

	struct tegra_cl_dvfs_cfg_param		*cfg_param;
};

#ifdef CONFIG_ARCH_TEGRA_HAS_CL_DVFS
int tegra_init_cl_dvfs(void);
int tegra_cl_dvfs_debug_init(struct clk *dfll_clk);
void tegra_cl_dvfs_resume(struct tegra_cl_dvfs *cld);

int tegra_cl_dvfs_vmin_read_begin(struct tegra_cl_dvfs *cld, uint *start);
int tegra_cl_dvfs_vmin_read_retry(struct tegra_cl_dvfs *cld, uint start);
int tegra_cl_dvfs_vmax_read_begin(struct tegra_cl_dvfs *cld, uint *start);
int tegra_cl_dvfs_vmax_read_retry(struct tegra_cl_dvfs *cld, uint start);
int tegra_cl_dvfs_vmin_cmp_needed(struct tegra_cl_dvfs *cld, int *needed_mv);

/* functions below are called only within DFLL clock interface DFLL lock held */
void tegra_cl_dvfs_disable(struct tegra_cl_dvfs *cld);
int tegra_cl_dvfs_enable(struct tegra_cl_dvfs *cld);
int tegra_cl_dvfs_lock(struct tegra_cl_dvfs *cld);
int tegra_cl_dvfs_unlock(struct tegra_cl_dvfs *cld);
int tegra_cl_dvfs_request_rate(struct tegra_cl_dvfs *cld, unsigned long rate);
unsigned long tegra_cl_dvfs_request_get(struct tegra_cl_dvfs *cld);
#else
static inline int tegra_init_cl_dvfs(void)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_debug_init(struct clk *dfll_clk)
{ return -ENOSYS; }
static inline void tegra_cl_dvfs_resume(struct tegra_cl_dvfs *cld)
{}

static inline int tegra_cl_dvfs_vmin_read_begin(struct tegra_cl_dvfs *cld,
						uint *start)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_vmin_read_retry(struct tegra_cl_dvfs *cld,
						uint start)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_vmax_read_begin(struct tegra_cl_dvfs *cld,
						uint *start)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_vmax_read_retry(struct tegra_cl_dvfs *cld,
						uint start)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_vmin_cmp_needed(struct tegra_cl_dvfs *cld,
						int *needed_mv)
{ return 0; }

static inline void tegra_cl_dvfs_disable(struct tegra_cl_dvfs *cld)
{}
static inline int tegra_cl_dvfs_enable(struct tegra_cl_dvfs *cld)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_lock(struct tegra_cl_dvfs *cld)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_unlock(struct tegra_cl_dvfs *cld)
{ return -ENOSYS; }
static inline int tegra_cl_dvfs_request_rate(
	struct tegra_cl_dvfs *cld, unsigned long rate)
{ return -ENOSYS; }
static inline unsigned long tegra_cl_dvfs_request_get(struct tegra_cl_dvfs *cld)
{ return 0; }
#endif

#endif