Blame view

drivers/pinctrl/pinctrl-axp209.c 12.7 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
2
  /*
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
3
   * AXP20x pinctrl and GPIO driver
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
4
5
   *
   * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
6
   * Copyright (C) 2017 Quentin Schulz <quentin.schulz@free-electrons.com>
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
7
8
9
10
11
12
13
14
15
16
17
   */
  
  #include <linux/bitops.h>
  #include <linux/device.h>
  #include <linux/gpio/driver.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/kernel.h>
  #include <linux/mfd/axp20x.h>
  #include <linux/module.h>
  #include <linux/of.h>
e1190083b   Quentin Schulz   pinctrl: axp209: ...
18
  #include <linux/of_device.h>
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
19
20
21
  #include <linux/pinctrl/pinconf-generic.h>
  #include <linux/pinctrl/pinctrl.h>
  #include <linux/pinctrl/pinmux.h>
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
22
23
24
25
26
27
28
29
  #include <linux/platform_device.h>
  #include <linux/regmap.h>
  #include <linux/slab.h>
  
  #define AXP20X_GPIO_FUNCTIONS		0x7
  #define AXP20X_GPIO_FUNCTION_OUT_LOW	0
  #define AXP20X_GPIO_FUNCTION_OUT_HIGH	1
  #define AXP20X_GPIO_FUNCTION_INPUT	2
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
30
31
32
33
34
35
36
37
38
  #define AXP20X_FUNC_GPIO_OUT		0
  #define AXP20X_FUNC_GPIO_IN		1
  #define AXP20X_FUNC_LDO			2
  #define AXP20X_FUNC_ADC			3
  #define AXP20X_FUNCS_NB			4
  
  #define AXP20X_MUX_GPIO_OUT		0
  #define AXP20X_MUX_GPIO_IN		BIT(1)
  #define AXP20X_MUX_ADC			BIT(2)
e1190083b   Quentin Schulz   pinctrl: axp209: ...
39
  #define AXP813_MUX_ADC			(BIT(2) | BIT(0))
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
40
41
42
43
44
45
46
  struct axp20x_pctrl_desc {
  	const struct pinctrl_pin_desc	*pins;
  	unsigned int			npins;
  	/* Stores the pins supporting LDO function. Bit offset is pin number. */
  	u8				ldo_mask;
  	/* Stores the pins supporting ADC function. Bit offset is pin number. */
  	u8				adc_mask;
48e706fbc   Quentin Schulz   pinctrl: axp209: ...
47
  	u8				gpio_status_offset;
a0a4b4c24   Quentin Schulz   pinctrl: axp209: ...
48
  	u8				adc_mux;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
49
50
51
52
53
54
55
56
  };
  
  struct axp20x_pinctrl_function {
  	const char	*name;
  	unsigned int	muxval;
  	const char	**groups;
  	unsigned int	ngroups;
  };
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
57
  struct axp20x_pctl {
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
58
59
  	struct gpio_chip	chip;
  	struct regmap		*regmap;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
60
61
62
63
64
65
66
67
68
69
70
  	struct pinctrl_dev			*pctl_dev;
  	struct device				*dev;
  	const struct axp20x_pctrl_desc		*desc;
  	struct axp20x_pinctrl_function		funcs[AXP20X_FUNCS_NB];
  };
  
  static const struct pinctrl_pin_desc axp209_pins[] = {
  	PINCTRL_PIN(0, "GPIO0"),
  	PINCTRL_PIN(1, "GPIO1"),
  	PINCTRL_PIN(2, "GPIO2"),
  };
e1190083b   Quentin Schulz   pinctrl: axp209: ...
71
72
73
74
  static const struct pinctrl_pin_desc axp813_pins[] = {
  	PINCTRL_PIN(0, "GPIO0"),
  	PINCTRL_PIN(1, "GPIO1"),
  };
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
75
76
77
78
79
  static const struct axp20x_pctrl_desc axp20x_data = {
  	.pins	= axp209_pins,
  	.npins	= ARRAY_SIZE(axp209_pins),
  	.ldo_mask = BIT(0) | BIT(1),
  	.adc_mask = BIT(0) | BIT(1),
48e706fbc   Quentin Schulz   pinctrl: axp209: ...
80
  	.gpio_status_offset = 4,
a0a4b4c24   Quentin Schulz   pinctrl: axp209: ...
81
  	.adc_mux = AXP20X_MUX_ADC,
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
82
  };
e1190083b   Quentin Schulz   pinctrl: axp209: ...
83
84
85
86
87
88
89
90
  static const struct axp20x_pctrl_desc axp813_data = {
  	.pins	= axp813_pins,
  	.npins	= ARRAY_SIZE(axp813_pins),
  	.ldo_mask = BIT(0) | BIT(1),
  	.adc_mask = BIT(0),
  	.gpio_status_offset = 0,
  	.adc_mux = AXP813_MUX_ADC,
  };
3cac991e3   Quentin Schulz   gpio: axp209: swi...
91
  static int axp20x_gpio_get_reg(unsigned int offset)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
92
93
94
95
96
97
98
99
100
101
102
103
  {
  	switch (offset) {
  	case 0:
  		return AXP20X_GPIO0_CTRL;
  	case 1:
  		return AXP20X_GPIO1_CTRL;
  	case 2:
  		return AXP20X_GPIO2_CTRL;
  	}
  
  	return -EINVAL;
  }
3cac991e3   Quentin Schulz   gpio: axp209: swi...
104
  static int axp20x_gpio_input(struct gpio_chip *chip, unsigned int offset)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
105
  {
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
106
  	return pinctrl_gpio_direction_input(chip->base + offset);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
107
  }
3cac991e3   Quentin Schulz   gpio: axp209: swi...
108
  static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
109
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
110
  	struct axp20x_pctl *pctl = gpiochip_get_data(chip);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
111
  	unsigned int val;
1d2b2ac05   Quentin Schulz   gpio: axp209: use...
112
  	int ret;
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
113

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
114
  	ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
115
116
  	if (ret)
  		return ret;
48e706fbc   Quentin Schulz   pinctrl: axp209: ...
117
  	return !!(val & BIT(offset + pctl->desc->gpio_status_offset));
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
118
  }
3cac991e3   Quentin Schulz   gpio: axp209: swi...
119
120
  static int axp20x_gpio_get_direction(struct gpio_chip *chip,
  				     unsigned int offset)
81d3753d9   Maxime Ripard   gpio: axp209: Imp...
121
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
122
  	struct axp20x_pctl *pctl = gpiochip_get_data(chip);
81d3753d9   Maxime Ripard   gpio: axp209: Imp...
123
124
125
126
127
128
  	unsigned int val;
  	int reg, ret;
  
  	reg = axp20x_gpio_get_reg(offset);
  	if (reg < 0)
  		return reg;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
129
  	ret = regmap_read(pctl->regmap, reg, &val);
81d3753d9   Maxime Ripard   gpio: axp209: Imp...
130
131
132
133
134
135
136
137
138
  	if (ret)
  		return ret;
  
  	/*
  	 * This shouldn't really happen if the pin is in use already,
  	 * or if it's not in use yet, it doesn't matter since we're
  	 * going to change the value soon anyway. Default to output.
  	 */
  	if ((val & AXP20X_GPIO_FUNCTIONS) > 2)
3c8278735   Matti Vaittinen   pinctrl: Use new ...
139
  		return GPIO_LINE_DIRECTION_OUT;
81d3753d9   Maxime Ripard   gpio: axp209: Imp...
140
141
142
143
144
  
  	/*
  	 * The GPIO directions are the three lowest values.
  	 * 2 is input, 0 and 1 are output
  	 */
3c8278735   Matti Vaittinen   pinctrl: Use new ...
145
146
147
148
  	if (val & 2)
  		return GPIO_LINE_DIRECTION_IN;
  
  	return GPIO_LINE_DIRECTION_OUT;
81d3753d9   Maxime Ripard   gpio: axp209: Imp...
149
  }
3cac991e3   Quentin Schulz   gpio: axp209: swi...
150
  static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset,
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
151
152
  			      int value)
  {
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
153
154
155
156
157
158
159
160
  	chip->set(chip, offset, value);
  
  	return 0;
  }
  
  static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset,
  			    int value)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
161
  	struct axp20x_pctl *pctl = gpiochip_get_data(chip);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
162
163
164
165
  	int reg;
  
  	reg = axp20x_gpio_get_reg(offset);
  	if (reg < 0)
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
166
  		return;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
167
  	regmap_update_bits(pctl->regmap, reg,
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
168
169
170
171
172
173
174
175
  			   AXP20X_GPIO_FUNCTIONS,
  			   value ? AXP20X_GPIO_FUNCTION_OUT_HIGH :
  			   AXP20X_GPIO_FUNCTION_OUT_LOW);
  }
  
  static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset,
  			  u8 config)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
176
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
177
178
179
180
  	int reg;
  
  	reg = axp20x_gpio_get_reg(offset);
  	if (reg < 0)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
181
  		return reg;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
182
  	return regmap_update_bits(pctl->regmap, reg, AXP20X_GPIO_FUNCTIONS,
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
183
  				  config);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
184
  }
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
185
186
  static int axp20x_pmx_func_cnt(struct pinctrl_dev *pctldev)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
187
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
188

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
189
  	return ARRAY_SIZE(pctl->funcs);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
190
191
192
193
194
  }
  
  static const char *axp20x_pmx_func_name(struct pinctrl_dev *pctldev,
  					unsigned int selector)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
195
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
196

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
197
  	return pctl->funcs[selector].name;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
198
199
200
201
202
203
204
  }
  
  static int axp20x_pmx_func_groups(struct pinctrl_dev *pctldev,
  				  unsigned int selector,
  				  const char * const **groups,
  				  unsigned int *num_groups)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
205
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
206

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
207
208
  	*groups = pctl->funcs[selector].groups;
  	*num_groups = pctl->funcs[selector].ngroups;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
209
210
211
212
213
214
215
  
  	return 0;
  }
  
  static int axp20x_pmx_set_mux(struct pinctrl_dev *pctldev,
  			      unsigned int function, unsigned int group)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
216
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
217
218
219
220
221
  	unsigned int mask;
  
  	/* Every pin supports GPIO_OUT and GPIO_IN functions */
  	if (function <= AXP20X_FUNC_GPIO_IN)
  		return axp20x_pmx_set(pctldev, group,
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
222
  				      pctl->funcs[function].muxval);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
223
224
  
  	if (function == AXP20X_FUNC_LDO)
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
225
  		mask = pctl->desc->ldo_mask;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
226
  	else
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
227
  		mask = pctl->desc->adc_mask;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
228
229
230
231
232
233
234
235
236
237
238
239
  
  	if (!(BIT(group) & mask))
  		return -EINVAL;
  
  	/*
  	 * We let the regulator framework handle the LDO muxing as muxing bits
  	 * are basically also regulators on/off bits. It's better not to enforce
  	 * any state of the regulator when selecting LDO mux so that we don't
  	 * interfere with the regulator driver.
  	 */
  	if (function == AXP20X_FUNC_LDO)
  		return 0;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
240
  	return axp20x_pmx_set(pctldev, group, pctl->funcs[function].muxval);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
241
242
243
244
245
246
  }
  
  static int axp20x_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
  					 struct pinctrl_gpio_range *range,
  					 unsigned int offset, bool input)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
247
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
248
249
250
  
  	if (input)
  		return axp20x_pmx_set(pctldev, offset,
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
251
  				      pctl->funcs[AXP20X_FUNC_GPIO_IN].muxval);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
252
253
  
  	return axp20x_pmx_set(pctldev, offset,
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
254
  			      pctl->funcs[AXP20X_FUNC_GPIO_OUT].muxval);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
255
256
257
258
259
260
261
262
263
264
265
266
267
  }
  
  static const struct pinmux_ops axp20x_pmx_ops = {
  	.get_functions_count	= axp20x_pmx_func_cnt,
  	.get_function_name	= axp20x_pmx_func_name,
  	.get_function_groups	= axp20x_pmx_func_groups,
  	.set_mux		= axp20x_pmx_set_mux,
  	.gpio_set_direction	= axp20x_pmx_gpio_set_direction,
  	.strict			= true,
  };
  
  static int axp20x_groups_cnt(struct pinctrl_dev *pctldev)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
268
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
269

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
270
  	return pctl->desc->npins;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
271
272
273
274
275
  }
  
  static int axp20x_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
  			     const unsigned int **pins, unsigned int *num_pins)
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
276
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
277

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
278
  	*pins = (unsigned int *)&pctl->desc->pins[selector];
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
279
280
281
282
283
284
285
  	*num_pins = 1;
  
  	return 0;
  }
  
  static const char *axp20x_group_name(struct pinctrl_dev *pctldev,
  				     unsigned int selector)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
286
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
287
  	struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
288

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
289
  	return pctl->desc->pins[selector].name;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
290
291
292
293
294
295
296
297
298
  }
  
  static const struct pinctrl_ops axp20x_pctrl_ops = {
  	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
  	.dt_free_map		= pinconf_generic_dt_free_map,
  	.get_groups_count	= axp20x_groups_cnt,
  	.get_group_name		= axp20x_group_name,
  	.get_group_pins		= axp20x_group_pins,
  };
504c76979   Anton Vasilyev   pinctrl: axp209: ...
299
  static int axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask,
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
300
301
302
303
304
305
306
307
308
309
310
  					  unsigned int mask_len,
  					  struct axp20x_pinctrl_function *func,
  					  const struct pinctrl_pin_desc *pins)
  {
  	unsigned long int mask_cpy = mask;
  	const char **group;
  	unsigned int ngroups = hweight8(mask);
  	int bit;
  
  	func->ngroups = ngroups;
  	if (func->ngroups > 0) {
a86854d0c   Kees Cook   treewide: devm_kz...
311
312
  		func->groups = devm_kcalloc(dev,
  					    ngroups, sizeof(const char *),
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
313
  					    GFP_KERNEL);
504c76979   Anton Vasilyev   pinctrl: axp209: ...
314
315
  		if (!func->groups)
  			return -ENOMEM;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
316
317
318
319
320
321
  		group = func->groups;
  		for_each_set_bit(bit, &mask_cpy, mask_len) {
  			*group = pins[bit].name;
  			group++;
  		}
  	}
504c76979   Anton Vasilyev   pinctrl: axp209: ...
322
323
  
  	return 0;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
324
  }
504c76979   Anton Vasilyev   pinctrl: axp209: ...
325
  static int axp20x_build_funcs_groups(struct platform_device *pdev)
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
326
  {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
327
  	struct axp20x_pctl *pctl = platform_get_drvdata(pdev);
504c76979   Anton Vasilyev   pinctrl: axp209: ...
328
  	int i, ret, pin, npins = pctl->desc->npins;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
329
330
331
332
333
334
  
  	pctl->funcs[AXP20X_FUNC_GPIO_OUT].name = "gpio_out";
  	pctl->funcs[AXP20X_FUNC_GPIO_OUT].muxval = AXP20X_MUX_GPIO_OUT;
  	pctl->funcs[AXP20X_FUNC_GPIO_IN].name = "gpio_in";
  	pctl->funcs[AXP20X_FUNC_GPIO_IN].muxval = AXP20X_MUX_GPIO_IN;
  	pctl->funcs[AXP20X_FUNC_LDO].name = "ldo";
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
335
336
337
338
  	/*
  	 * Muxval for LDO is useless as we won't use it.
  	 * See comment in axp20x_pmx_set_mux.
  	 */
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
339
  	pctl->funcs[AXP20X_FUNC_ADC].name = "adc";
a0a4b4c24   Quentin Schulz   pinctrl: axp209: ...
340
  	pctl->funcs[AXP20X_FUNC_ADC].muxval = pctl->desc->adc_mux;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
341
342
343
  
  	/* Every pin supports GPIO_OUT and GPIO_IN functions */
  	for (i = 0; i <= AXP20X_FUNC_GPIO_IN; i++) {
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
344
  		pctl->funcs[i].ngroups = npins;
a86854d0c   Kees Cook   treewide: devm_kz...
345
346
  		pctl->funcs[i].groups = devm_kcalloc(&pdev->dev,
  						     npins, sizeof(char *),
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
347
  						     GFP_KERNEL);
1adc90c73   Aditya Pakki   pinctrl: axp209: ...
348
349
  		if (!pctl->funcs[i].groups)
  			return -ENOMEM;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
350
  		for (pin = 0; pin < npins; pin++)
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
351
  			pctl->funcs[i].groups[pin] = pctl->desc->pins[pin].name;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
352
  	}
504c76979   Anton Vasilyev   pinctrl: axp209: ...
353
  	ret = axp20x_funcs_groups_from_mask(&pdev->dev, pctl->desc->ldo_mask,
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
354
355
  				      npins, &pctl->funcs[AXP20X_FUNC_LDO],
  				      pctl->desc->pins);
504c76979   Anton Vasilyev   pinctrl: axp209: ...
356
357
  	if (ret)
  		return ret;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
358

504c76979   Anton Vasilyev   pinctrl: axp209: ...
359
  	ret = axp20x_funcs_groups_from_mask(&pdev->dev, pctl->desc->adc_mask,
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
360
361
  				      npins, &pctl->funcs[AXP20X_FUNC_ADC],
  				      pctl->desc->pins);
504c76979   Anton Vasilyev   pinctrl: axp209: ...
362
363
364
365
  	if (ret)
  		return ret;
  
  	return 0;
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
366
  }
e1190083b   Quentin Schulz   pinctrl: axp209: ...
367
368
369
370
371
372
  static const struct of_device_id axp20x_pctl_match[] = {
  	{ .compatible = "x-powers,axp209-gpio", .data = &axp20x_data, },
  	{ .compatible = "x-powers,axp813-gpio", .data = &axp813_data, },
  	{ }
  };
  MODULE_DEVICE_TABLE(of, axp20x_pctl_match);
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
373
  static int axp20x_pctl_probe(struct platform_device *pdev)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
374
375
  {
  	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
376
  	struct axp20x_pctl *pctl;
e1190083b   Quentin Schulz   pinctrl: axp209: ...
377
  	struct device *dev = &pdev->dev;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
378
  	struct pinctrl_desc *pctrl_desc;
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
379
380
381
382
383
384
385
386
387
388
  	int ret;
  
  	if (!of_device_is_available(pdev->dev.of_node))
  		return -ENODEV;
  
  	if (!axp20x) {
  		dev_err(&pdev->dev, "Parent drvdata not set
  ");
  		return -EINVAL;
  	}
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
389
390
  	pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
  	if (!pctl)
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
391
  		return -ENOMEM;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
392
393
394
395
396
397
398
399
400
401
402
403
  	pctl->chip.base			= -1;
  	pctl->chip.can_sleep		= true;
  	pctl->chip.request		= gpiochip_generic_request;
  	pctl->chip.free			= gpiochip_generic_free;
  	pctl->chip.parent		= &pdev->dev;
  	pctl->chip.label		= dev_name(&pdev->dev);
  	pctl->chip.owner		= THIS_MODULE;
  	pctl->chip.get			= axp20x_gpio_get;
  	pctl->chip.get_direction	= axp20x_gpio_get_direction;
  	pctl->chip.set			= axp20x_gpio_set;
  	pctl->chip.direction_input	= axp20x_gpio_input;
  	pctl->chip.direction_output	= axp20x_gpio_output;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
404

9b8ee3c0f   Julia Lawall   pinctrl: axp209: ...
405
  	pctl->desc = of_device_get_match_data(dev);
a04981522   Quentin Schulz   pinctrl: axp209: ...
406
407
  
  	pctl->chip.ngpio		= pctl->desc->npins;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
408
409
410
411
  	pctl->regmap = axp20x->regmap;
  	pctl->dev = &pdev->dev;
  
  	platform_set_drvdata(pdev, pctl);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
412

504c76979   Anton Vasilyev   pinctrl: axp209: ...
413
414
415
416
417
418
  	ret = axp20x_build_funcs_groups(pdev);
  	if (ret) {
  		dev_err(&pdev->dev, "failed to build groups
  ");
  		return ret;
  	}
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
419
420
421
422
423
424
425
  
  	pctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctrl_desc), GFP_KERNEL);
  	if (!pctrl_desc)
  		return -ENOMEM;
  
  	pctrl_desc->name = dev_name(&pdev->dev);
  	pctrl_desc->owner = THIS_MODULE;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
426
427
  	pctrl_desc->pins = pctl->desc->pins;
  	pctrl_desc->npins = pctl->desc->npins;
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
428
429
  	pctrl_desc->pctlops = &axp20x_pctrl_ops;
  	pctrl_desc->pmxops = &axp20x_pmx_ops;
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
430
431
  	pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, pctl);
  	if (IS_ERR(pctl->pctl_dev)) {
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
432
433
  		dev_err(&pdev->dev, "couldn't register pinctrl driver
  ");
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
434
  		return PTR_ERR(pctl->pctl_dev);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
435
  	}
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
436

d242e60c7   Quentin Schulz   pinctrl: axp209: ...
437
  	ret = devm_gpiochip_add_data(&pdev->dev, &pctl->chip, pctl);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
438
439
440
441
442
  	if (ret) {
  		dev_err(&pdev->dev, "Failed to register GPIO chip
  ");
  		return ret;
  	}
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
443
444
445
446
  	ret = gpiochip_add_pin_range(&pctl->chip, dev_name(&pdev->dev),
  				     pctl->desc->pins->number,
  				     pctl->desc->pins->number,
  				     pctl->desc->npins);
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
447
448
449
450
451
452
453
454
  	if (ret) {
  		dev_err(&pdev->dev, "failed to add pin range
  ");
  		return ret;
  	}
  
  	dev_info(&pdev->dev, "AXP209 pinctrl and GPIO driver loaded
  ");
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
455
456
457
  
  	return 0;
  }
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
458
459
  static struct platform_driver axp20x_pctl_driver = {
  	.probe		= axp20x_pctl_probe,
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
460
461
  	.driver = {
  		.name		= "axp20x-gpio",
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
462
  		.of_match_table	= axp20x_pctl_match,
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
463
464
  	},
  };
d242e60c7   Quentin Schulz   pinctrl: axp209: ...
465
  module_platform_driver(axp20x_pctl_driver);
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
466
467
  
  MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
23f75d7df   Quentin Schulz   pinctrl: axp209: ...
468
469
  MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
  MODULE_DESCRIPTION("AXP20x PMIC pinctrl and GPIO driver");
f72f4b44d   Maxime Ripard   gpio: Add AXP209 ...
470
  MODULE_LICENSE("GPL");