summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/intel/pinctrl-intel.h
blob: 2bb553598e8bd0d4dda73697234d68eb35597a55 (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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Core pinctrl/GPIO driver for Intel GPIO controllers
 *
 * Copyright (C) 2015, Intel Corporation
 * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
 *          Mika Westerberg <mika.westerberg@linux.intel.com>
 */

#ifndef PINCTRL_INTEL_H
#define PINCTRL_INTEL_H

#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/compiler_types.h>
#include <linux/gpio/driver.h>
#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/spinlock_types.h>

struct platform_device;
struct device;

/**
 * struct intel_pingroup - Description about group of pins
 * @grp: Generic data of the pin group (name and pins)
 * @mode: Native mode in which the group is muxed out @pins. Used if @modes is %NULL.
 * @modes: If not %NULL this will hold mode for each pin in @pins
 */
struct intel_pingroup {
	struct pingroup grp;
	unsigned short mode;
	const unsigned int *modes;
};

/**
 * struct intel_function - Description about a function
 * @func: Generic data of the pin function (name and groups of pins)
 */
struct intel_function {
	struct pinfunction func;
};

#define INTEL_PINCTRL_MAX_GPP_SIZE	32

/**
 * struct intel_padgroup - Hardware pad group information
 * @reg_num: GPI_IS register number
 * @base: Starting pin of this group
 * @size: Size of this group (maximum is %INTEL_PINCTRL_MAX_GPP_SIZE).
 * @gpio_base: Starting GPIO base of this group
 * @padown_num: PAD_OWN register number (assigned by the core driver)
 *
 * If pad groups of a community are not the same size, use this structure
 * to specify them.
 */
struct intel_padgroup {
	unsigned int reg_num;
	unsigned int base;
	unsigned int size;
	int gpio_base;
	unsigned int padown_num;
};

/**
 * enum - Special treatment for GPIO base in pad group
 *
 * @INTEL_GPIO_BASE_ZERO:	force GPIO base to be 0
 * @INTEL_GPIO_BASE_NOMAP:	no GPIO mapping should be created
 * @INTEL_GPIO_BASE_MATCH:	matches with starting pin number
 */
enum {
	INTEL_GPIO_BASE_ZERO	= -2,
	INTEL_GPIO_BASE_NOMAP	= -1,
	INTEL_GPIO_BASE_MATCH	= 0,
};

/**
 * struct intel_community - Intel pin community description
 * @barno: MMIO BAR number where registers for this community reside
 * @padown_offset: Register offset of PAD_OWN register from @regs. If %0
 *                 then there is no support for owner.
 * @padcfglock_offset: Register offset of PADCFGLOCK from @regs. If %0 then
 *                     locking is not supported.
 * @hostown_offset: Register offset of HOSTSW_OWN from @regs. If %0 then it
 *                  is assumed that the host owns the pin (rather than
 *                  ACPI).
 * @is_offset: Register offset of GPI_IS from @regs.
 * @ie_offset: Register offset of GPI_IE from @regs.
 * @features: Additional features supported by the hardware
 * @pin_base: Starting pin of pins in this community
 * @npins: Number of pins in this community
 * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
 *            HOSTSW_OWN, GPI_IS, GPI_IE. Used when @gpps is %NULL.
 * @gpp_num_padown_regs: Number of pad registers each pad group consumes at
 *			 minimum. Used when @gpps is %NULL.
 * @gpps: Pad groups if the controller has variable size pad groups
 * @ngpps: Number of pad groups in this community
 * @pad_map: Optional non-linear mapping of the pads
 * @nirqs: Optional total number of IRQs this community can generate
 * @acpi_space_id: Optional address space ID for ACPI OpRegion handler
 * @regs: Community specific common registers (reserved for core driver)
 * @pad_regs: Community specific pad registers (reserved for core driver)
 *
 * In older Intel GPIO host controllers, this driver supports, each pad group
 * is of equal size (except the last one). In that case the driver can just
 * fill in @gpp_size and @gpp_num_padown_regs fields and let the core driver
 * to handle the rest.
 *
 * In newer Intel GPIO host controllers each pad group is of variable size,
 * so the client driver can pass custom @gpps and @ngpps instead.
 */
struct intel_community {
	unsigned int barno;
	unsigned int padown_offset;
	unsigned int padcfglock_offset;
	unsigned int hostown_offset;
	unsigned int is_offset;
	unsigned int ie_offset;
	unsigned int features;
	unsigned int pin_base;
	size_t npins;
	unsigned int gpp_size;
	unsigned int gpp_num_padown_regs;
	const struct intel_padgroup *gpps;
	size_t ngpps;
	const unsigned int *pad_map;
	unsigned short nirqs;
	unsigned short acpi_space_id;

	/* Reserved for the core driver */
	void __iomem *regs;
	void __iomem *pad_regs;
};

/* Additional features supported by the hardware */
#define PINCTRL_FEATURE_DEBOUNCE	BIT(0)
#define PINCTRL_FEATURE_1K_PD		BIT(1)
#define PINCTRL_FEATURE_GPIO_HW_INFO	BIT(2)
#define PINCTRL_FEATURE_PWM		BIT(3)
#define PINCTRL_FEATURE_BLINK		BIT(4)
#define PINCTRL_FEATURE_EXP		BIT(5)

#define __INTEL_COMMUNITY(b, s, e, g, n, gs, gn, soc)		\
	{							\
		.barno = (b),					\
		.padown_offset = soc ## _PAD_OWN,		\
		.padcfglock_offset = soc ## _PADCFGLOCK,	\
		.hostown_offset = soc ## _HOSTSW_OWN,		\
		.is_offset = soc ## _GPI_IS,			\
		.ie_offset = soc ## _GPI_IE,			\
		.gpp_size = (gs),				\
		.gpp_num_padown_regs = (gn),			\
		.pin_base = (s),				\
		.npins = ((e) - (s) + 1),			\
		.gpps = (g),					\
		.ngpps = (n),					\
	}

#define INTEL_COMMUNITY_GPPS(b, s, e, g, soc)			\
	__INTEL_COMMUNITY(b, s, e, g, ARRAY_SIZE(g), 0, 0, soc)

#define INTEL_COMMUNITY_SIZE(b, s, e, gs, gn, soc)		\
	__INTEL_COMMUNITY(b, s, e, NULL, 0, gs, gn, soc)

/**
 * PIN_GROUP - Declare a pin group
 * @n: Name of the group
 * @p: An array of pins this group consists
 * @m: Mode which the pins are put when this group is active. Can be either
 *     a single integer or an array of integers in which case mode is per
 *     pin.
 */
#define PIN_GROUP(n, p, m)								\
	{										\
		.grp = PINCTRL_PINGROUP((n), (p), ARRAY_SIZE((p))),			\
		.mode = __builtin_choose_expr(__builtin_constant_p((m)), (m), 0),	\
		.modes = __builtin_choose_expr(__builtin_constant_p((m)), NULL, (m)),	\
	}

#define FUNCTION(n, g)							\
	{								\
		.func = PINCTRL_PINFUNCTION((n), (g), ARRAY_SIZE(g)),	\
	}

/**
 * struct intel_pinctrl_soc_data - Intel pin controller per-SoC configuration
 * @uid: ACPI _UID for the probe driver use if needed
 * @pins: Array if pins this pinctrl controls
 * @npins: Number of pins in the array
 * @groups: Array of pin groups
 * @ngroups: Number of groups in the array
 * @functions: Array of functions
 * @nfunctions: Number of functions in the array
 * @communities: Array of communities this pinctrl handles
 * @ncommunities: Number of communities in the array
 *
 * The @communities is used as a template by the core driver. It will make
 * copy of all communities and fill in rest of the information.
 */
struct intel_pinctrl_soc_data {
	const char *uid;
	const struct pinctrl_pin_desc *pins;
	size_t npins;
	const struct intel_pingroup *groups;
	size_t ngroups;
	const struct intel_function *functions;
	size_t nfunctions;
	const struct intel_community *communities;
	size_t ncommunities;
};

const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_device *pdev);

struct intel_pad_context;
struct intel_community_context;

/**
 * struct intel_pinctrl_context - context to be saved during suspend-resume
 * @pads: Opaque context per pad (driver dependent)
 * @communities: Opaque context per community (driver dependent)
 */
struct intel_pinctrl_context {
	struct intel_pad_context *pads;
	struct intel_community_context *communities;
};

/**
 * struct intel_pinctrl - Intel pinctrl private structure
 * @dev: Pointer to the device structure
 * @lock: Lock to serialize register access
 * @pctldesc: Pin controller description
 * @pctldev: Pointer to the pin controller device
 * @chip: GPIO chip in this pin controller
 * @soc: SoC/PCH specific pin configuration data
 * @communities: All communities in this pin controller
 * @ncommunities: Number of communities in this pin controller
 * @context: Configuration saved over system sleep
 * @irq: pinctrl/GPIO chip irq number
 */
struct intel_pinctrl {
	struct device *dev;
	raw_spinlock_t lock;
	struct pinctrl_desc pctldesc;
	struct pinctrl_dev *pctldev;
	struct gpio_chip chip;
	const struct intel_pinctrl_soc_data *soc;
	struct intel_community *communities;
	size_t ncommunities;
	struct intel_pinctrl_context context;
	int irq;
};

int intel_pinctrl_probe_by_hid(struct platform_device *pdev);
int intel_pinctrl_probe_by_uid(struct platform_device *pdev);

#ifdef CONFIG_PM_SLEEP
int intel_pinctrl_suspend_noirq(struct device *dev);
int intel_pinctrl_resume_noirq(struct device *dev);
#endif

#define INTEL_PINCTRL_PM_OPS(_name)					\
const struct dev_pm_ops _name = {					\
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend_noirq,	\
				      intel_pinctrl_resume_noirq)	\
}

struct intel_community *intel_get_community(struct intel_pinctrl *pctrl, unsigned int pin);

int intel_get_groups_count(struct pinctrl_dev *pctldev);
const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group);
int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
			 const unsigned int **pins, unsigned int *npins);

int intel_get_functions_count(struct pinctrl_dev *pctldev);
const char *intel_get_function_name(struct pinctrl_dev *pctldev, unsigned int function);
int intel_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function,
			      const char * const **groups, unsigned int * const ngroups);

#endif /* PINCTRL_INTEL_H */