aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-msm/include/mach/gpiomux.h
blob: 2278677bac174e538dd9912d1f8647c99490267e (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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/* Copyright (c) 2010-2011,2013-2014, The Linux Foundation. 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 and
 * only 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.
 */
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H
#define __ARCH_ARM_MACH_MSM_GPIOMUX_H

#include <linux/bitops.h>
#include <linux/errno.h>

enum msm_gpiomux_setting {
	GPIOMUX_ACTIVE = 0,
	GPIOMUX_SUSPENDED,
	GPIOMUX_NSETTINGS
};

enum gpiomux_drv {
	GPIOMUX_DRV_2MA = 0,
	GPIOMUX_DRV_4MA,
	GPIOMUX_DRV_6MA,
	GPIOMUX_DRV_8MA,
	GPIOMUX_DRV_10MA,
	GPIOMUX_DRV_12MA,
	GPIOMUX_DRV_14MA,
	GPIOMUX_DRV_16MA,
};

enum gpiomux_func {
	GPIOMUX_FUNC_GPIO = 0,
	GPIOMUX_FUNC_1,
	GPIOMUX_FUNC_2,
	GPIOMUX_FUNC_3,
	GPIOMUX_FUNC_4,
	GPIOMUX_FUNC_5,
	GPIOMUX_FUNC_6,
	GPIOMUX_FUNC_7,
	GPIOMUX_FUNC_8,
	GPIOMUX_FUNC_9,
	GPIOMUX_FUNC_A,
	GPIOMUX_FUNC_B,
	GPIOMUX_FUNC_C,
	GPIOMUX_FUNC_D,
	GPIOMUX_FUNC_E,
	GPIOMUX_FUNC_F,
};

enum gpiomux_pull {
	GPIOMUX_PULL_NONE = 0,
	GPIOMUX_PULL_DOWN,
	GPIOMUX_PULL_KEEPER,
	GPIOMUX_PULL_UP,
};

/* Direction settings are only meaningful when GPIOMUX_FUNC_GPIO is selected.
 * This element is ignored for all other FUNC selections, as the output-
 * enable pin is not under software control in those cases.  See the SWI
 * for your target for more details.
 */
enum gpiomux_dir {
	GPIOMUX_IN = 0,
	GPIOMUX_OUT_HIGH,
	GPIOMUX_OUT_LOW,
};

struct gpiomux_setting {
	enum gpiomux_func func;
	enum gpiomux_drv  drv;
	enum gpiomux_pull pull;
	enum gpiomux_dir  dir;
};

/**
 * struct msm_gpiomux_config: gpiomux settings for one gpio line.
 *
 * A complete gpiomux config is the combination of a drive-strength,
 * function, pull, and (sometimes) direction.  For functions other than GPIO,
 * the input/output setting is hard-wired according to the function.
 *
 * @gpio: The index number of the gpio being described.
 * @settings: The settings to be installed, specifically:
 *           GPIOMUX_ACTIVE: The setting to be installed when the
 *           line is active, or its reference count is > 0.
 *           GPIOMUX_SUSPENDED: The setting to be installed when
 *           the line is suspended, or its reference count is 0.
 */
struct msm_gpiomux_config {
	unsigned gpio;
	struct gpiomux_setting *settings[GPIOMUX_NSETTINGS];
};

/**
 * struct msm_gpiomux_configs: a collection of gpiomux configs.
 *
 * It is so common to manage blocks of gpiomux configs that the data structure
 * for doing so has been standardized here as a convenience.
 *
 * @cfg:  A pointer to the first config in an array of configs.
 * @ncfg: The number of configs in the array.
 */
struct msm_gpiomux_configs {
	struct msm_gpiomux_config *cfg;
	size_t                     ncfg;
};

/* Provide an enum and an API to write to misc TLMM registers */
enum msm_tlmm_misc_reg {
	TLMM_ETM_MODE_REG = 0x2014,
	TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
	TLMM_SPARE_REG = 0x2024,
	TLMM_CDC_HDRV_CTL = 0x2054,
	TLMM_CDC_HDRV_PULL_CTL = 0x2058,
};

#ifdef CONFIG_MSM_GPIOMUX

/* Before using gpiomux, initialize the subsystem by telling it how many
 * gpios are going to be managed.  Calling any other gpiomux functions before
 * msm_gpiomux_init is unsupported.
 */
int msm_gpiomux_init(size_t ngpio);

/* DT Variant of msm_gpiomux_init. This will look up the number of gpios from
 * device tree rather than relying on NR_GPIO_IRQS
 */
int msm_gpiomux_init_dt(void);

/* Install a block of gpiomux configurations in gpiomux.  This is functionally
 * identical to calling msm_gpiomux_write many times.
 */
void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs);

/* Install a block of gpiomux configurations in gpiomux. Do not however write
 * to hardware. Just store the settings to be retrieved at a later time
 */
void msm_gpiomux_install_nowrite(struct msm_gpiomux_config *configs,
				unsigned nconfigs);

/* Increment a gpio's reference count, possibly activating the line. */
int __must_check msm_gpiomux_get(unsigned gpio);

/* Decrement a gpio's reference count, possibly suspending the line. */
int msm_gpiomux_put(unsigned gpio);

/* Install a new setting in a gpio.  To erase a slot, use NULL.
 * The old setting that was overwritten can be passed back to the caller
 * old_setting can be NULL if the caller is not interested in the previous
 * setting
 * If a previous setting was not available to return (NULL configuration)
 * - the function returns 1
 * else function returns 0
 */
int msm_gpiomux_write(unsigned gpio, enum msm_gpiomux_setting which,
	struct gpiomux_setting *setting, struct gpiomux_setting *old_setting);

/* Architecture-internal function for use by the framework only.
 * This function can assume the following:
 * - the gpio value has passed a bounds-check
 * - the gpiomux spinlock has been obtained
 *
 * This function is not for public consumption.  External users
 * should use msm_gpiomux_write.
 */
void __msm_gpiomux_write(unsigned gpio, struct gpiomux_setting val);

/* Functions that provide an API for drivers to read from and write to
 * miscellaneous TLMM registers.
 */
int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg);

void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);

#else
static inline int msm_gpiomux_init(size_t ngpio)
{
	return -ENOSYS;
}

static inline void
msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs) {}

static inline int __must_check msm_gpiomux_get(unsigned gpio)
{
	return -ENOSYS;
}

static inline int msm_gpiomux_put(unsigned gpio)
{
	return -ENOSYS;
}

static inline int msm_gpiomux_write(unsigned gpio,
	enum msm_gpiomux_setting which, struct gpiomux_setting *setting,
	struct gpiomux_setting *old_setting)
{
	return -ENOSYS;
}

static inline int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg)
{
	return -ENOSYS;
}

static inline void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg,
						int val)
{
}

#endif
#endif