Blame view

drivers/pinctrl/pinctrl-single.c 48.3 KB
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Generic device tree based pinctrl driver for one register per pin
   * type pinmux controllers
   *
   * Copyright (C) 2012 Texas Instruments, Inc.
   *
   * This file is licensed under the terms of the GNU General Public
   * License version 2. This program is licensed "as is" without any
   * warranty of any kind, whether express or implied.
   */
  
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/io.h>
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/list.h>
3e6cee178   Tony Lindgren   pinctrl: single: ...
18
19
20
  #include <linux/interrupt.h>
  
  #include <linux/irqchip/chained_irq.h>
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
21
22
23
24
  
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/of_address.h>
3e6cee178   Tony Lindgren   pinctrl: single: ...
25
  #include <linux/of_irq.h>
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
26
27
28
  
  #include <linux/pinctrl/pinctrl.h>
  #include <linux/pinctrl/pinmux.h>
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
29
  #include <linux/pinctrl/pinconf-generic.h>
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
30

dc7743aa3   Tony Lindgren   pinctrl: single: ...
31
  #include <linux/platform_data/pinctrl-single.h>
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
32
  #include "core.h"
4622215fb   Tony Lindgren   pinctrl: single: ...
33
  #include "devicetree.h"
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
34
  #include "pinconf.h"
571aec4df   Tony Lindgren   pinctrl: single: ...
35
  #include "pinmux.h"
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
36
37
  
  #define DRIVER_NAME			"pinctrl-single"
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
38
39
40
  #define PCS_OFF_DISABLED		~0U
  
  /**
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
41
42
43
   * struct pcs_func_vals - mux function register offset and value pair
   * @reg:	register virtual address
   * @val:	register value
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
44
   * @mask:	mask
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
45
46
47
48
   */
  struct pcs_func_vals {
  	void __iomem *reg;
  	unsigned val;
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
49
  	unsigned mask;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
50
51
52
  };
  
  /**
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
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
   * struct pcs_conf_vals - pinconf parameter, pinconf register offset
   * and value, enable, disable, mask
   * @param:	config parameter
   * @val:	user input bits in the pinconf register
   * @enable:	enable bits in the pinconf register
   * @disable:	disable bits in the pinconf register
   * @mask:	mask bits in the register value
   */
  struct pcs_conf_vals {
  	enum pin_config_param param;
  	unsigned val;
  	unsigned enable;
  	unsigned disable;
  	unsigned mask;
  };
  
  /**
   * struct pcs_conf_type - pinconf property name, pinconf param pair
   * @name:	property name in DTS file
   * @param:	config parameter
   */
  struct pcs_conf_type {
  	const char *name;
  	enum pin_config_param param;
  };
  
  /**
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
80
81
82
83
84
85
   * struct pcs_function - pinctrl function
   * @name:	pinctrl function name
   * @vals:	register and vals array
   * @nvals:	number of entries in vals array
   * @pgnames:	array of pingroup names the function uses
   * @npgnames:	number of pingroup names the function uses
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
86
87
   * @conf:	array of pin configurations
   * @nconfs:	number of pin configurations available
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
88
89
90
91
92
93
94
95
   * @node:	list node
   */
  struct pcs_function {
  	const char *name;
  	struct pcs_func_vals *vals;
  	unsigned nvals;
  	const char **pgnames;
  	int npgnames;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
96
97
  	struct pcs_conf_vals *conf;
  	int nconfs;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
98
99
100
101
  	struct list_head node;
  };
  
  /**
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
   * struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
   * @offset:	offset base of pins
   * @npins:	number pins with the same mux value of gpio function
   * @gpiofunc:	mux value of gpio function
   * @node:	list node
   */
  struct pcs_gpiofunc_range {
  	unsigned offset;
  	unsigned npins;
  	unsigned gpiofunc;
  	struct list_head node;
  };
  
  /**
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
   * struct pcs_data - wrapper for data needed by pinctrl framework
   * @pa:		pindesc array
   * @cur:	index to current element
   *
   * REVISIT: We should be able to drop this eventually by adding
   * support for registering pins individually in the pinctrl
   * framework for those drivers that don't need a static array.
   */
  struct pcs_data {
  	struct pinctrl_pin_desc *pa;
  	int cur;
  };
  
  /**
02e483f66   Tony Lindgren   pinctrl: single: ...
130
131
   * struct pcs_soc_data - SoC specific settings
   * @flags:	initial SoC specific PCS_FEAT_xxx values
3e6cee178   Tony Lindgren   pinctrl: single: ...
132
133
134
   * @irq:	optional interrupt for the controller
   * @irq_enable_mask:	optional SoC specific interrupt enable mask
   * @irq_status_mask:	optional SoC specific interrupt status mask
dc7743aa3   Tony Lindgren   pinctrl: single: ...
135
   * @rearm:	optional SoC specific wake-up rearm function
02e483f66   Tony Lindgren   pinctrl: single: ...
136
137
138
   */
  struct pcs_soc_data {
  	unsigned flags;
3e6cee178   Tony Lindgren   pinctrl: single: ...
139
140
141
  	int irq;
  	unsigned irq_enable_mask;
  	unsigned irq_status_mask;
dc7743aa3   Tony Lindgren   pinctrl: single: ...
142
  	void (*rearm)(void);
02e483f66   Tony Lindgren   pinctrl: single: ...
143
144
145
  };
  
  /**
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
146
147
148
   * struct pcs_device - pinctrl device instance
   * @res:	resources
   * @base:	virtual address of the controller
88a1dbdec   Keerthy   pinctrl: pinctrl-...
149
   * @saved_vals: saved values for the controller
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
150
151
   * @size:	size of the ioremapped area
   * @dev:	device entry
4622215fb   Tony Lindgren   pinctrl: single: ...
152
   * @np:		device tree node
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
153
   * @pctl:	pin controller device
02e483f66   Tony Lindgren   pinctrl: single: ...
154
   * @flags:	mask of PCS_FEAT_xxx values
4622215fb   Tony Lindgren   pinctrl: single: ...
155
156
   * @missing_nr_pinctrl_cells: for legacy binding, may go away
   * @socdata:	soc specific data
3e6cee178   Tony Lindgren   pinctrl: single: ...
157
   * @lock:	spinlock for register access
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
158
159
160
161
162
163
   * @mutex:	mutex protecting the lists
   * @width:	bits per mux register
   * @fmask:	function register mask
   * @fshift:	function register shift
   * @foff:	value to turn mux off
   * @fmax:	max number of functions in fmask
4622215fb   Tony Lindgren   pinctrl: single: ...
164
165
   * @bits_per_mux: number of bits per mux
   * @bits_per_pin: number of bits per pin
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
166
   * @pins:	physical pins on the SoC
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
167
   * @gpiofuncs:	list of gpio functions
3e6cee178   Tony Lindgren   pinctrl: single: ...
168
169
170
   * @irqs:	list of interrupt registers
   * @chip:	chip container for this instance
   * @domain:	IRQ domain for this instance
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
171
172
173
174
175
176
177
   * @desc:	pin controller descriptor
   * @read:	register read function to use
   * @write:	register write function to use
   */
  struct pcs_device {
  	struct resource *res;
  	void __iomem *base;
88a1dbdec   Keerthy   pinctrl: pinctrl-...
178
  	void *saved_vals;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
179
180
  	unsigned size;
  	struct device *dev;
4622215fb   Tony Lindgren   pinctrl: single: ...
181
  	struct device_node *np;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
182
  	struct pinctrl_dev *pctl;
02e483f66   Tony Lindgren   pinctrl: single: ...
183
  	unsigned flags;
88a1dbdec   Keerthy   pinctrl: pinctrl-...
184
  #define PCS_CONTEXT_LOSS_OFF	(1 << 3)
3e6cee178   Tony Lindgren   pinctrl: single: ...
185
186
  #define PCS_QUIRK_SHARED_IRQ	(1 << 2)
  #define PCS_FEAT_IRQ		(1 << 1)
02e483f66   Tony Lindgren   pinctrl: single: ...
187
  #define PCS_FEAT_PINCONF	(1 << 0)
4622215fb   Tony Lindgren   pinctrl: single: ...
188
  	struct property *missing_nr_pinctrl_cells;
3e6cee178   Tony Lindgren   pinctrl: single: ...
189
190
  	struct pcs_soc_data socdata;
  	raw_spinlock_t lock;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
191
192
193
194
195
196
  	struct mutex mutex;
  	unsigned width;
  	unsigned fmask;
  	unsigned fshift;
  	unsigned foff;
  	unsigned fmax;
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
197
  	bool bits_per_mux;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
198
  	unsigned bits_per_pin;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
199
  	struct pcs_data pins;
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
200
  	struct list_head gpiofuncs;
3e6cee178   Tony Lindgren   pinctrl: single: ...
201
202
203
  	struct list_head irqs;
  	struct irq_chip chip;
  	struct irq_domain *domain;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
204
205
206
207
  	struct pinctrl_desc desc;
  	unsigned (*read)(void __iomem *reg);
  	void (*write)(unsigned val, void __iomem *reg);
  };
3e6cee178   Tony Lindgren   pinctrl: single: ...
208
209
  #define PCS_QUIRK_HAS_SHARED_IRQ	(pcs->flags & PCS_QUIRK_SHARED_IRQ)
  #define PCS_HAS_IRQ		(pcs->flags & PCS_FEAT_IRQ)
02e483f66   Tony Lindgren   pinctrl: single: ...
210
  #define PCS_HAS_PINCONF		(pcs->flags & PCS_FEAT_PINCONF)
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
211
212
213
  static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
  			   unsigned long *config);
  static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
03b054e96   Sherman Yin   pinctrl: Pass all...
214
  			   unsigned long *configs, unsigned num_configs);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
215
216
217
218
219
  
  static enum pin_config_param pcs_bias[] = {
  	PIN_CONFIG_BIAS_PULL_DOWN,
  	PIN_CONFIG_BIAS_PULL_UP,
  };
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
220
  /*
3c177a166   Sudeep Holla   pinctrl: single: ...
221
222
223
224
225
   * This lock class tells lockdep that irqchip core that this single
   * pinctrl can be in a different category than its parents, so it won't
   * report false recursion.
   */
  static struct lock_class_key pcs_lock_class;
39c3fd589   Andrew Lunn   kernel/irq: Exten...
226
227
  /* Class for the IRQ request mutex */
  static struct lock_class_key pcs_request_class;
3c177a166   Sudeep Holla   pinctrl: single: ...
228
  /*
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
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
   * REVISIT: Reads and writes could eventually use regmap or something
   * generic. But at least on omaps, some mux registers are performance
   * critical as they may need to be remuxed every time before and after
   * idle. Adding tests for register access width for every read and
   * write like regmap is doing is not desired, and caching the registers
   * does not help in this case.
   */
  
  static unsigned __maybe_unused pcs_readb(void __iomem *reg)
  {
  	return readb(reg);
  }
  
  static unsigned __maybe_unused pcs_readw(void __iomem *reg)
  {
  	return readw(reg);
  }
  
  static unsigned __maybe_unused pcs_readl(void __iomem *reg)
  {
  	return readl(reg);
  }
  
  static void __maybe_unused pcs_writeb(unsigned val, void __iomem *reg)
  {
  	writeb(val, reg);
  }
  
  static void __maybe_unused pcs_writew(unsigned val, void __iomem *reg)
  {
  	writew(val, reg);
  }
  
  static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg)
  {
  	writel(val, reg);
  }
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
266
267
  static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
  					struct seq_file *s,
e7ed67182   Haojian Zhuang   pinctrl: single: ...
268
  					unsigned pin)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
269
  {
7d66ce7f8   Matt Porter   pinctrl: pinctrl-...
270
  	struct pcs_device *pcs;
e7ed67182   Haojian Zhuang   pinctrl: single: ...
271
  	unsigned val, mux_bytes;
223decc45   Tony Lindgren   pinctrl: single: ...
272
273
  	unsigned long offset;
  	size_t pa;
7d66ce7f8   Matt Porter   pinctrl: pinctrl-...
274
275
  
  	pcs = pinctrl_dev_get_drvdata(pctldev);
e7ed67182   Haojian Zhuang   pinctrl: single: ...
276
  	mux_bytes = pcs->width / BITS_PER_BYTE;
223decc45   Tony Lindgren   pinctrl: single: ...
277
278
279
  	offset = pin * mux_bytes;
  	val = pcs->read(pcs->base + offset);
  	pa = pcs->res->start + offset;
7d66ce7f8   Matt Porter   pinctrl: pinctrl-...
280

223decc45   Tony Lindgren   pinctrl: single: ...
281
  	seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  }
  
  static void pcs_dt_free_map(struct pinctrl_dev *pctldev,
  				struct pinctrl_map *map, unsigned num_maps)
  {
  	struct pcs_device *pcs;
  
  	pcs = pinctrl_dev_get_drvdata(pctldev);
  	devm_kfree(pcs->dev, map);
  }
  
  static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
  				struct device_node *np_config,
  				struct pinctrl_map **map, unsigned *num_maps);
022ab148d   Laurent Pinchart   pinctrl: Declare ...
296
  static const struct pinctrl_ops pcs_pinctrl_ops = {
caeb774ea   Tony Lindgren   pinctrl: single: ...
297
298
299
  	.get_groups_count = pinctrl_generic_get_group_count,
  	.get_group_name = pinctrl_generic_get_group_name,
  	.get_group_pins = pinctrl_generic_get_group_pins,
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
300
301
302
303
  	.pin_dbg_show = pcs_pin_dbg_show,
  	.dt_node_to_map = pcs_dt_node_to_map,
  	.dt_free_map = pcs_dt_free_map,
  };
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
304
305
306
307
308
309
  static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
  			    struct pcs_function **func)
  {
  	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
  	struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
  	const struct pinctrl_setting_mux *setting;
571aec4df   Tony Lindgren   pinctrl: single: ...
310
  	struct function_desc *function;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
311
312
313
314
315
316
317
  	unsigned fselector;
  
  	/* If pin is not described in DTS & enabled, mux_setting is NULL. */
  	setting = pdesc->mux_setting;
  	if (!setting)
  		return -ENOTSUPP;
  	fselector = setting->func;
571aec4df   Tony Lindgren   pinctrl: single: ...
318
319
  	function = pinmux_generic_get_function(pctldev, fselector);
  	*func = function->data;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
320
321
322
323
324
325
326
327
  	if (!(*func)) {
  		dev_err(pcs->dev, "%s could not find function%i
  ",
  			__func__, fselector);
  		return -ENOTSUPP;
  	}
  	return 0;
  }
03e9f0cac   Linus Walleij   pinctrl: clean up...
328
  static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
329
330
331
  	unsigned group)
  {
  	struct pcs_device *pcs;
571aec4df   Tony Lindgren   pinctrl: single: ...
332
  	struct function_desc *function;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
333
334
335
336
  	struct pcs_function *func;
  	int i;
  
  	pcs = pinctrl_dev_get_drvdata(pctldev);
477ac771d   Haojian Zhuang   pinctrl: single: ...
337
338
339
  	/* If function mask is null, needn't enable it. */
  	if (!pcs->fmask)
  		return 0;
571aec4df   Tony Lindgren   pinctrl: single: ...
340
341
  	function = pinmux_generic_get_function(pctldev, fselector);
  	func = function->data;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
342
343
344
345
346
347
348
349
350
  	if (!func)
  		return -EINVAL;
  
  	dev_dbg(pcs->dev, "enabling %s function%i
  ",
  		func->name, fselector);
  
  	for (i = 0; i < func->nvals; i++) {
  		struct pcs_func_vals *vals;
3e6cee178   Tony Lindgren   pinctrl: single: ...
351
  		unsigned long flags;
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
352
  		unsigned val, mask;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
353
354
  
  		vals = &func->vals[i];
3e6cee178   Tony Lindgren   pinctrl: single: ...
355
  		raw_spin_lock_irqsave(&pcs->lock, flags);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
356
  		val = pcs->read(vals->reg);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
357
358
359
  
  		if (pcs->bits_per_mux)
  			mask = vals->mask;
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
360
  		else
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
361
  			mask = pcs->fmask;
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
362
363
364
  
  		val &= ~mask;
  		val |= (vals->val & mask);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
365
  		pcs->write(val, vals->reg);
3e6cee178   Tony Lindgren   pinctrl: single: ...
366
  		raw_spin_unlock_irqrestore(&pcs->lock, flags);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
367
368
369
370
  	}
  
  	return 0;
  }
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
371
  static int pcs_request_gpio(struct pinctrl_dev *pctldev,
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
372
  			    struct pinctrl_gpio_range *range, unsigned pin)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
373
  {
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
374
375
376
377
378
  	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
  	struct pcs_gpiofunc_range *frange = NULL;
  	struct list_head *pos, *tmp;
  	int mux_bytes = 0;
  	unsigned data;
477ac771d   Haojian Zhuang   pinctrl: single: ...
379
380
381
  	/* If function mask is null, return directly. */
  	if (!pcs->fmask)
  		return -ENOTSUPP;
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
382
383
384
385
386
387
  	list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
  		frange = list_entry(pos, struct pcs_gpiofunc_range, node);
  		if (pin >= frange->offset + frange->npins
  			|| pin < frange->offset)
  			continue;
  		mux_bytes = pcs->width / BITS_PER_BYTE;
45dcb54f0   David Lechner   pinctrl: pinctrl-...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  
  		if (pcs->bits_per_mux) {
  			int byte_num, offset, pin_shift;
  
  			byte_num = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
  			offset = (byte_num / mux_bytes) * mux_bytes;
  			pin_shift = pin % (pcs->width / pcs->bits_per_pin) *
  				    pcs->bits_per_pin;
  
  			data = pcs->read(pcs->base + offset);
  			data &= ~(pcs->fmask << pin_shift);
  			data |= frange->gpiofunc << pin_shift;
  			pcs->write(data, pcs->base + offset);
  		} else {
  			data = pcs->read(pcs->base + pin * mux_bytes);
  			data &= ~pcs->fmask;
  			data |= frange->gpiofunc;
  			pcs->write(data, pcs->base + pin * mux_bytes);
  		}
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
407
408
409
  		break;
  	}
  	return 0;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
410
  }
022ab148d   Laurent Pinchart   pinctrl: Declare ...
411
  static const struct pinmux_ops pcs_pinmux_ops = {
571aec4df   Tony Lindgren   pinctrl: single: ...
412
413
414
  	.get_functions_count = pinmux_generic_get_function_count,
  	.get_function_name = pinmux_generic_get_function_name,
  	.get_function_groups = pinmux_generic_get_function_groups,
9e3a979f0   Linus Walleij   pinctrl: single: ...
415
  	.set_mux = pcs_set_mux,
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
416
417
  	.gpio_request_enable = pcs_request_gpio,
  };
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
418
419
420
421
422
423
424
  /* Clear BIAS value */
  static void pcs_pinconf_clear_bias(struct pinctrl_dev *pctldev, unsigned pin)
  {
  	unsigned long config;
  	int i;
  	for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
  		config = pinconf_to_config_packed(pcs_bias[i], 0);
03b054e96   Sherman Yin   pinctrl: Pass all...
425
  		pcs_pinconf_set(pctldev, pin, &config, 1);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  	}
  }
  
  /*
   * Check whether PIN_CONFIG_BIAS_DISABLE is valid.
   * It's depend on that PULL_DOWN & PULL_UP configs are all invalid.
   */
  static bool pcs_pinconf_bias_disable(struct pinctrl_dev *pctldev, unsigned pin)
  {
  	unsigned long config;
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
  		config = pinconf_to_config_packed(pcs_bias[i], 0);
  		if (!pcs_pinconf_get(pctldev, pin, &config))
  			goto out;
  	}
  	return true;
  out:
  	return false;
  }
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
447
448
449
  static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
  				unsigned pin, unsigned long *config)
  {
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
  	struct pcs_function *func;
  	enum pin_config_param param;
  	unsigned offset = 0, data = 0, i, j, ret;
  
  	ret = pcs_get_function(pctldev, pin, &func);
  	if (ret)
  		return ret;
  
  	for (i = 0; i < func->nconfs; i++) {
  		param = pinconf_to_config_param(*config);
  		if (param == PIN_CONFIG_BIAS_DISABLE) {
  			if (pcs_pinconf_bias_disable(pctldev, pin)) {
  				*config = 0;
  				return 0;
  			} else {
  				return -ENOTSUPP;
  			}
  		} else if (param != func->conf[i].param) {
  			continue;
  		}
  
  		offset = pin * (pcs->width / BITS_PER_BYTE);
  		data = pcs->read(pcs->base + offset) & func->conf[i].mask;
  		switch (func->conf[i].param) {
  		/* 4 parameters */
  		case PIN_CONFIG_BIAS_PULL_DOWN:
  		case PIN_CONFIG_BIAS_PULL_UP:
  		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
  			if ((data != func->conf[i].enable) ||
  			    (data == func->conf[i].disable))
  				return -ENOTSUPP;
  			*config = 0;
  			break;
  		/* 2 parameters */
  		case PIN_CONFIG_INPUT_SCHMITT:
  			for (j = 0; j < func->nconfs; j++) {
  				switch (func->conf[j].param) {
  				case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
  					if (data != func->conf[j].enable)
  						return -ENOTSUPP;
  					break;
  				default:
  					break;
  				}
  			}
  			*config = data;
  			break;
  		case PIN_CONFIG_DRIVE_STRENGTH:
  		case PIN_CONFIG_SLEW_RATE:
4bd754775   Chao Xie   pinctrl: single: ...
500
  		case PIN_CONFIG_LOW_POWER_MODE:
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
501
502
503
504
505
506
  		default:
  			*config = data;
  			break;
  		}
  		return 0;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
507
508
509
510
  	return -ENOTSUPP;
  }
  
  static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
03b054e96   Sherman Yin   pinctrl: Pass all...
511
512
  				unsigned pin, unsigned long *configs,
  				unsigned num_configs)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
513
  {
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
514
515
  	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
  	struct pcs_function *func;
7cba5b3f5   Haojian Zhuang   pinctrl: single: ...
516
  	unsigned offset = 0, shift = 0, i, data, ret;
58957d2ed   Mika Westerberg   pinctrl: Widen th...
517
  	u32 arg;
03b054e96   Sherman Yin   pinctrl: Pass all...
518
  	int j;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
519
520
521
522
  
  	ret = pcs_get_function(pctldev, pin, &func);
  	if (ret)
  		return ret;
03b054e96   Sherman Yin   pinctrl: Pass all...
523
524
525
526
527
  	for (j = 0; j < num_configs; j++) {
  		for (i = 0; i < func->nconfs; i++) {
  			if (pinconf_to_config_param(configs[j])
  				!= func->conf[i].param)
  				continue;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
528
529
  			offset = pin * (pcs->width / BITS_PER_BYTE);
  			data = pcs->read(pcs->base + offset);
03b054e96   Sherman Yin   pinctrl: Pass all...
530
  			arg = pinconf_to_config_argument(configs[j]);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
531
532
533
534
535
  			switch (func->conf[i].param) {
  			/* 2 parameters */
  			case PIN_CONFIG_INPUT_SCHMITT:
  			case PIN_CONFIG_DRIVE_STRENGTH:
  			case PIN_CONFIG_SLEW_RATE:
4bd754775   Chao Xie   pinctrl: single: ...
536
  			case PIN_CONFIG_LOW_POWER_MODE:
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
537
  				shift = ffs(func->conf[i].mask) - 1;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
538
539
540
541
542
543
544
545
546
  				data &= ~func->conf[i].mask;
  				data |= (arg << shift) & func->conf[i].mask;
  				break;
  			/* 4 parameters */
  			case PIN_CONFIG_BIAS_DISABLE:
  				pcs_pinconf_clear_bias(pctldev, pin);
  				break;
  			case PIN_CONFIG_BIAS_PULL_DOWN:
  			case PIN_CONFIG_BIAS_PULL_UP:
7cba5b3f5   Haojian Zhuang   pinctrl: single: ...
547
  				if (arg)
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
548
  					pcs_pinconf_clear_bias(pctldev, pin);
c44295566   Gustavo A. R. Silva   pinctrl: single: ...
549
  				fallthrough;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
550
551
  			case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
  				data &= ~func->conf[i].mask;
7cba5b3f5   Haojian Zhuang   pinctrl: single: ...
552
  				if (arg)
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
553
554
555
556
557
558
559
560
  					data |= func->conf[i].enable;
  				else
  					data |= func->conf[i].disable;
  				break;
  			default:
  				return -ENOTSUPP;
  			}
  			pcs->write(data, pcs->base + offset);
03b054e96   Sherman Yin   pinctrl: Pass all...
561
562
  
  			break;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
563
  		}
03b054e96   Sherman Yin   pinctrl: Pass all...
564
565
566
567
568
  		if (i >= func->nconfs)
  			return -ENOTSUPP;
  	} /* for each config */
  
  	return 0;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
569
570
571
572
573
  }
  
  static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
  				unsigned group, unsigned long *config)
  {
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
574
575
576
  	const unsigned *pins;
  	unsigned npins, old = 0;
  	int i, ret;
caeb774ea   Tony Lindgren   pinctrl: single: ...
577
  	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
578
579
580
581
582
583
584
585
586
587
588
  	if (ret)
  		return ret;
  	for (i = 0; i < npins; i++) {
  		if (pcs_pinconf_get(pctldev, pins[i], config))
  			return -ENOTSUPP;
  		/* configs do not match between two pins */
  		if (i && (old != *config))
  			return -ENOTSUPP;
  		old = *config;
  	}
  	return 0;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
589
590
591
  }
  
  static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
03b054e96   Sherman Yin   pinctrl: Pass all...
592
593
  				unsigned group, unsigned long *configs,
  				unsigned num_configs)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
594
  {
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
595
596
597
  	const unsigned *pins;
  	unsigned npins;
  	int i, ret;
caeb774ea   Tony Lindgren   pinctrl: single: ...
598
  	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
599
600
601
  	if (ret)
  		return ret;
  	for (i = 0; i < npins; i++) {
03b054e96   Sherman Yin   pinctrl: Pass all...
602
  		if (pcs_pinconf_set(pctldev, pins[i], configs, num_configs))
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
603
604
605
  			return -ENOTSUPP;
  	}
  	return 0;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
606
607
608
  }
  
  static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
609
  				struct seq_file *s, unsigned pin)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
610
611
612
613
614
615
616
  {
  }
  
  static void pcs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
  				struct seq_file *s, unsigned selector)
  {
  }
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
617
618
619
620
621
622
  static void pcs_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
  					struct seq_file *s,
  					unsigned long config)
  {
  	pinconf_generic_dump_config(pctldev, s, config);
  }
022ab148d   Laurent Pinchart   pinctrl: Declare ...
623
  static const struct pinconf_ops pcs_pinconf_ops = {
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
624
625
626
627
628
629
  	.pin_config_get = pcs_pinconf_get,
  	.pin_config_set = pcs_pinconf_set,
  	.pin_config_group_get = pcs_pinconf_group_get,
  	.pin_config_group_set = pcs_pinconf_group_set,
  	.pin_config_dbg_show = pcs_pinconf_dbg_show,
  	.pin_config_group_dbg_show = pcs_pinconf_group_dbg_show,
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
630
  	.pin_config_config_dbg_show = pcs_pinconf_config_dbg_show,
a7bbdd7f8   Axel Lin   pinctrl: single: ...
631
  	.is_generic = true,
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
632
633
634
635
636
637
  };
  
  /**
   * pcs_add_pin() - add a pin to the static per controller pin array
   * @pcs: pcs driver instance
   * @offset: register offset from base
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
638
   * @pin_pos: unused
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
639
   */
6f924b0b7   Manjunathappa, Prakash   pinctrl: pinctrl-...
640
641
  static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
  		unsigned pin_pos)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
642
  {
58968625c   Tony Lindgren   pinctrl: single: ...
643
  	struct pcs_soc_data *pcs_soc = &pcs->socdata;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
644
  	struct pinctrl_pin_desc *pin;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
645
646
647
648
649
650
651
652
653
  	int i;
  
  	i = pcs->pins.cur;
  	if (i >= pcs->desc.npins) {
  		dev_err(pcs->dev, "too many pins, max %i
  ",
  			pcs->desc.npins);
  		return -ENOMEM;
  	}
58968625c   Tony Lindgren   pinctrl: single: ...
654
655
656
657
658
659
660
661
662
663
664
665
  	if (pcs_soc->irq_enable_mask) {
  		unsigned val;
  
  		val = pcs->read(pcs->base + offset);
  		if (val & pcs_soc->irq_enable_mask) {
  			dev_dbg(pcs->dev, "irq enabled at boot for pin at %lx (%x), clearing
  ",
  				(unsigned long)pcs->res->start + offset, val);
  			val &= ~pcs_soc->irq_enable_mask;
  			pcs->write(val, pcs->base + offset);
  		}
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
666
  	pin = &pcs->pins.pa[i];
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  	pin->number = i;
  	pcs->pins.cur++;
  
  	return i;
  }
  
  /**
   * pcs_allocate_pin_table() - adds all the pins for the pinctrl driver
   * @pcs: pcs driver instance
   *
   * In case of errors, resources are freed in pcs_free_resources.
   *
   * If your hardware needs holes in the address space, then just set
   * up multiple driver instances.
   */
150632b09   Greg Kroah-Hartman   Drivers: pinctrl:...
682
  static int pcs_allocate_pin_table(struct pcs_device *pcs)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
683
684
  {
  	int mux_bytes, nr_pins, i;
6f924b0b7   Manjunathappa, Prakash   pinctrl: pinctrl-...
685
  	int num_pins_in_register = 0;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
686
687
  
  	mux_bytes = pcs->width / BITS_PER_BYTE;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
688
689
690
691
  
  	if (pcs->bits_per_mux) {
  		pcs->bits_per_pin = fls(pcs->fmask);
  		nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
6f924b0b7   Manjunathappa, Prakash   pinctrl: pinctrl-...
692
  		num_pins_in_register = pcs->width / pcs->bits_per_pin;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
693
694
695
  	} else {
  		nr_pins = pcs->size / mux_bytes;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
696
697
698
  
  	dev_dbg(pcs->dev, "allocating %i pins
  ", nr_pins);
a86854d0c   Kees Cook   treewide: devm_kz...
699
700
  	pcs->pins.pa = devm_kcalloc(pcs->dev,
  				nr_pins, sizeof(*pcs->pins.pa),
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
701
702
703
  				GFP_KERNEL);
  	if (!pcs->pins.pa)
  		return -ENOMEM;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
704
705
706
707
708
709
  	pcs->desc.pins = pcs->pins.pa;
  	pcs->desc.npins = nr_pins;
  
  	for (i = 0; i < pcs->desc.npins; i++) {
  		unsigned offset;
  		int res;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
710
  		int byte_num;
6f924b0b7   Manjunathappa, Prakash   pinctrl: pinctrl-...
711
  		int pin_pos = 0;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
712

4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
713
714
715
  		if (pcs->bits_per_mux) {
  			byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
  			offset = (byte_num / mux_bytes) * mux_bytes;
6f924b0b7   Manjunathappa, Prakash   pinctrl: pinctrl-...
716
  			pin_pos = i % num_pins_in_register;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
717
718
719
  		} else {
  			offset = i * mux_bytes;
  		}
6f924b0b7   Manjunathappa, Prakash   pinctrl: pinctrl-...
720
  		res = pcs_add_pin(pcs, offset, pin_pos);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
721
722
723
724
725
726
727
728
729
730
731
732
733
  		if (res < 0) {
  			dev_err(pcs->dev, "error adding pins: %i
  ", res);
  			return res;
  		}
  	}
  
  	return 0;
  }
  
  /**
   * pcs_add_function() - adds a new function to the function list
   * @pcs: pcs driver instance
a4ab10860   Tony Lindgren   pinctrl: single: ...
734
   * @fcn: new function allocated
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
735
736
737
738
739
   * @name: name of the function
   * @vals: array of mux register value pairs used by the function
   * @nvals: number of mux register value pairs
   * @pgnames: array of pingroup names for the function
   * @npgnames: number of pingroup names
a4ab10860   Tony Lindgren   pinctrl: single: ...
740
741
   *
   * Caller must take care of locking.
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
742
   */
a4ab10860   Tony Lindgren   pinctrl: single: ...
743
744
745
746
747
748
749
  static int pcs_add_function(struct pcs_device *pcs,
  			    struct pcs_function **fcn,
  			    const char *name,
  			    struct pcs_func_vals *vals,
  			    unsigned int nvals,
  			    const char **pgnames,
  			    unsigned int npgnames)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
750
751
  {
  	struct pcs_function *function;
a4ab10860   Tony Lindgren   pinctrl: single: ...
752
  	int selector;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
753
754
755
  
  	function = devm_kzalloc(pcs->dev, sizeof(*function), GFP_KERNEL);
  	if (!function)
a4ab10860   Tony Lindgren   pinctrl: single: ...
756
  		return -ENOMEM;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
757

8b8b091bf   Tony Lindgren   pinctrl: Add one-...
758
759
  	function->vals = vals;
  	function->nvals = nvals;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
760

a4ab10860   Tony Lindgren   pinctrl: single: ...
761
762
763
764
765
766
767
768
769
  	selector = pinmux_generic_add_function(pcs->pctl, name,
  					       pgnames, npgnames,
  					       function);
  	if (selector < 0) {
  		devm_kfree(pcs->dev, function);
  		*fcn = NULL;
  	} else {
  		*fcn = function;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
770

a4ab10860   Tony Lindgren   pinctrl: single: ...
771
  	return selector;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
772
  }
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
773
  /**
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
   * pcs_get_pin_by_offset() - get a pin index based on the register offset
   * @pcs: pcs driver instance
   * @offset: register offset from the base
   *
   * Note that this is OK as long as the pins are in a static array.
   */
  static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
  {
  	unsigned index;
  
  	if (offset >= pcs->size) {
  		dev_err(pcs->dev, "mux offset out of range: 0x%x (0x%x)
  ",
  			offset, pcs->size);
  		return -EINVAL;
  	}
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
790
791
792
793
  	if (pcs->bits_per_mux)
  		index = (offset * BITS_PER_BYTE) / pcs->bits_per_pin;
  	else
  		index = offset / (pcs->width / BITS_PER_BYTE);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
794
795
796
  
  	return index;
  }
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  /*
   * check whether data matches enable bits or disable bits
   * Return value: 1 for matching enable bits, 0 for matching disable bits,
   *               and negative value for matching failure.
   */
  static int pcs_config_match(unsigned data, unsigned enable, unsigned disable)
  {
  	int ret = -EINVAL;
  
  	if (data == enable)
  		ret = 1;
  	else if (data == disable)
  		ret = 0;
  	return ret;
  }
  
  static void add_config(struct pcs_conf_vals **conf, enum pin_config_param param,
  		       unsigned value, unsigned enable, unsigned disable,
  		       unsigned mask)
  {
  	(*conf)->param = param;
  	(*conf)->val = value;
  	(*conf)->enable = enable;
  	(*conf)->disable = disable;
  	(*conf)->mask = mask;
  	(*conf)++;
  }
  
  static void add_setting(unsigned long **setting, enum pin_config_param param,
  			unsigned arg)
  {
  	**setting = pinconf_to_config_packed(param, arg);
  	(*setting)++;
  }
  
  /* add pinconf setting with 2 parameters */
  static void pcs_add_conf2(struct pcs_device *pcs, struct device_node *np,
  			  const char *name, enum pin_config_param param,
  			  struct pcs_conf_vals **conf, unsigned long **settings)
  {
7cba5b3f5   Haojian Zhuang   pinctrl: single: ...
837
  	unsigned value[2], shift;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
838
839
840
841
842
843
844
  	int ret;
  
  	ret = of_property_read_u32_array(np, name, value, 2);
  	if (ret)
  		return;
  	/* set value & mask */
  	value[0] &= value[1];
7cba5b3f5   Haojian Zhuang   pinctrl: single: ...
845
  	shift = ffs(value[1]) - 1;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
846
847
  	/* skip enable & disable */
  	add_config(conf, param, value[0], 0, 0, value[1]);
7cba5b3f5   Haojian Zhuang   pinctrl: single: ...
848
  	add_setting(settings, param, value[0] >> shift);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
  }
  
  /* add pinconf setting with 4 parameters */
  static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np,
  			  const char *name, enum pin_config_param param,
  			  struct pcs_conf_vals **conf, unsigned long **settings)
  {
  	unsigned value[4];
  	int ret;
  
  	/* value to set, enable, disable, mask */
  	ret = of_property_read_u32_array(np, name, value, 4);
  	if (ret)
  		return;
  	if (!value[3]) {
  		dev_err(pcs->dev, "mask field of the property can't be 0
  ");
  		return;
  	}
  	value[0] &= value[3];
  	value[1] &= value[3];
  	value[2] &= value[3];
  	ret = pcs_config_match(value[0], value[1], value[2]);
  	if (ret < 0)
  		dev_dbg(pcs->dev, "failed to match enable or disable bits
  ");
  	add_config(conf, param, value[0], value[1], value[2], value[3]);
  	add_setting(settings, param, ret);
  }
  
  static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
  			     struct pcs_function *func,
  			     struct pinctrl_map **map)
  
  {
  	struct pinctrl_map *m = *map;
  	int i = 0, nconfs = 0;
  	unsigned long *settings = NULL, *s = NULL;
  	struct pcs_conf_vals *conf = NULL;
b582658ae   Colin Ian King   pinctrl: single: ...
888
  	static const struct pcs_conf_type prop2[] = {
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
889
890
891
  		{ "pinctrl-single,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, },
  		{ "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, },
  		{ "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, },
4bd754775   Chao Xie   pinctrl: single: ...
892
  		{ "pinctrl-single,low-power-mode", PIN_CONFIG_LOW_POWER_MODE, },
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
893
  	};
b582658ae   Colin Ian King   pinctrl: single: ...
894
  	static const struct pcs_conf_type prop4[] = {
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
895
896
897
898
899
900
901
  		{ "pinctrl-single,bias-pullup", PIN_CONFIG_BIAS_PULL_UP, },
  		{ "pinctrl-single,bias-pulldown", PIN_CONFIG_BIAS_PULL_DOWN, },
  		{ "pinctrl-single,input-schmitt-enable",
  			PIN_CONFIG_INPUT_SCHMITT_ENABLE, },
  	};
  
  	/* If pinconf isn't supported, don't parse properties in below. */
02e483f66   Tony Lindgren   pinctrl: single: ...
902
  	if (!PCS_HAS_PINCONF)
f46fe79ff   Drew Fustini   pinctrl-single: f...
903
  		return -ENOTSUPP;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
904
905
906
907
908
909
910
911
912
913
914
  
  	/* cacluate how much properties are supported in current node */
  	for (i = 0; i < ARRAY_SIZE(prop2); i++) {
  		if (of_find_property(np, prop2[i].name, NULL))
  			nconfs++;
  	}
  	for (i = 0; i < ARRAY_SIZE(prop4); i++) {
  		if (of_find_property(np, prop4[i].name, NULL))
  			nconfs++;
  	}
  	if (!nconfs)
f46fe79ff   Drew Fustini   pinctrl-single: f...
915
  		return -ENOTSUPP;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
916

a86854d0c   Kees Cook   treewide: devm_kz...
917
918
  	func->conf = devm_kcalloc(pcs->dev,
  				  nconfs, sizeof(struct pcs_conf_vals),
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
919
920
921
922
923
924
  				  GFP_KERNEL);
  	if (!func->conf)
  		return -ENOMEM;
  	func->nconfs = nconfs;
  	conf = &(func->conf[0]);
  	m++;
a86854d0c   Kees Cook   treewide: devm_kz...
925
  	settings = devm_kcalloc(pcs->dev, nconfs, sizeof(unsigned long),
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
  				GFP_KERNEL);
  	if (!settings)
  		return -ENOMEM;
  	s = &settings[0];
  
  	for (i = 0; i < ARRAY_SIZE(prop2); i++)
  		pcs_add_conf2(pcs, np, prop2[i].name, prop2[i].param,
  			      &conf, &s);
  	for (i = 0; i < ARRAY_SIZE(prop4); i++)
  		pcs_add_conf4(pcs, np, prop4[i].name, prop4[i].param,
  			      &conf, &s);
  	m->type = PIN_MAP_TYPE_CONFIGS_GROUP;
  	m->data.configs.group_or_pin = np->name;
  	m->data.configs.configs = settings;
  	m->data.configs.num_configs = nconfs;
  	return 0;
  }
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
943
  /**
bc6d20159   Drew Fustini   pinctrl: single: ...
944
   * pcs_parse_one_pinctrl_entry() - parses a device tree mux entry
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
945
946
947
   * @pcs: pinctrl driver instance
   * @np: device node of the mux entry
   * @map: map entry
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
948
   * @num_maps: number of map
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
   * @pgnames: pingroup names
   *
   * Note that this binding currently supports only sets of one register + value.
   *
   * Also note that this driver tries to avoid understanding pin and function
   * names because of the extra bloat they would cause especially in the case of
   * a large number of pins. This driver just sets what is specified for the board
   * in the .dts file. Further user space debugging tools can be developed to
   * decipher the pin and function names using debugfs.
   *
   * If you are concerned about the boot time, set up the static pins in
   * the bootloader, and only set up selected pins as device tree entries.
   */
  static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
  						struct device_node *np,
  						struct pinctrl_map **map,
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
965
  						unsigned *num_maps,
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
966
967
  						const char **pgnames)
  {
4622215fb   Tony Lindgren   pinctrl: single: ...
968
  	const char *name = "pinctrl-single,pins";
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
969
  	struct pcs_func_vals *vals;
a4ab10860   Tony Lindgren   pinctrl: single: ...
970
971
  	int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel;
  	struct pcs_function *function = NULL;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
972

4622215fb   Tony Lindgren   pinctrl: single: ...
973
  	rows = pinctrl_count_index_with_args(np, name);
de7416bce   Axel Haslam   pinctrl: single: ...
974
  	if (rows <= 0) {
059a6e630   Colin Ian King   pinctrl: single: ...
975
976
  		dev_err(pcs->dev, "Invalid number of rows: %d
  ", rows);
de7416bce   Axel Haslam   pinctrl: single: ...
977
978
  		return -EINVAL;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
979

a86854d0c   Kees Cook   treewide: devm_kz...
980
  	vals = devm_kcalloc(pcs->dev, rows, sizeof(*vals), GFP_KERNEL);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
981
982
  	if (!vals)
  		return -ENOMEM;
a86854d0c   Kees Cook   treewide: devm_kz...
983
  	pins = devm_kcalloc(pcs->dev, rows, sizeof(*pins), GFP_KERNEL);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
984
985
  	if (!pins)
  		goto free_vals;
4622215fb   Tony Lindgren   pinctrl: single: ...
986
987
988
  	for (i = 0; i < rows; i++) {
  		struct of_phandle_args pinctrl_spec;
  		unsigned int offset;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
989
  		int pin;
4622215fb   Tony Lindgren   pinctrl: single: ...
990
991
992
  		res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
  		if (res)
  			return res;
9b9448f39   Drew Fustini   pinctrl: single: ...
993
  		if (pinctrl_spec.args_count < 2 || pinctrl_spec.args_count > 3) {
4622215fb   Tony Lindgren   pinctrl: single: ...
994
995
996
997
998
  			dev_err(pcs->dev, "invalid args_count for spec: %i
  ",
  				pinctrl_spec.args_count);
  			break;
  		}
4622215fb   Tony Lindgren   pinctrl: single: ...
999
  		offset = pinctrl_spec.args[0];
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1000
  		vals[found].reg = pcs->base + offset;
a13395418   Drew Fustini   pinctrl: single: ...
1001
1002
1003
1004
1005
1006
1007
1008
1009
  
  		switch (pinctrl_spec.args_count) {
  		case 2:
  			vals[found].val = pinctrl_spec.args[1];
  			break;
  		case 3:
  			vals[found].val = (pinctrl_spec.args[1] | pinctrl_spec.args[2]);
  			break;
  		}
4622215fb   Tony Lindgren   pinctrl: single: ...
1010

94f4e54ce   Rob Herring   pinctrl: Convert ...
1011
1012
  		dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x
  ",
f4a2b19c3   Drew Fustini   pinctrl: single: ...
1013
  			pinctrl_spec.np, offset, vals[found].val);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1014
1015
1016
1017
  
  		pin = pcs_get_pin_by_offset(pcs, offset);
  		if (pin < 0) {
  			dev_err(pcs->dev,
94f4e54ce   Rob Herring   pinctrl: Convert ...
1018
1019
1020
  				"could not add functions for %pOFn %ux
  ",
  				np, offset);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1021
1022
1023
1024
1025
1026
  			break;
  		}
  		pins[found++] = pin;
  	}
  
  	pgnames[0] = np->name;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1027
1028
1029
1030
1031
  	mutex_lock(&pcs->mutex);
  	fsel = pcs_add_function(pcs, &function, np->name, vals, found,
  				pgnames, 1);
  	if (fsel < 0) {
  		res = fsel;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1032
  		goto free_pins;
712778d02   Dan Carpenter   pinctrl: single: ...
1033
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1034

a4ab10860   Tony Lindgren   pinctrl: single: ...
1035
1036
1037
  	gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
  	if (gsel < 0) {
  		res = gsel;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1038
  		goto free_function;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1039
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1040
1041
1042
1043
  
  	(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
  	(*map)->data.mux.group = np->name;
  	(*map)->data.mux.function = np->name;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1044
  	if (PCS_HAS_PINCONF && function) {
18442e65d   Wei Yongjun   pinctrl: single: ...
1045
  		res = pcs_parse_pinconf(pcs, np, function, map);
f46fe79ff   Drew Fustini   pinctrl-single: f...
1046
1047
1048
1049
1050
  		if (res == 0)
  			*num_maps = 2;
  		else if (res == -ENOTSUPP)
  			*num_maps = 1;
  		else
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
1051
  			goto free_pingroups;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
1052
1053
1054
  	} else {
  		*num_maps = 1;
  	}
a4ab10860   Tony Lindgren   pinctrl: single: ...
1055
  	mutex_unlock(&pcs->mutex);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1056
  	return 0;
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
1057
  free_pingroups:
a4ab10860   Tony Lindgren   pinctrl: single: ...
1058
  	pinctrl_generic_remove_group(pcs->pctl, gsel);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
1059
  	*num_maps = 1;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1060
  free_function:
a4ab10860   Tony Lindgren   pinctrl: single: ...
1061
  	pinmux_generic_remove_function(pcs->pctl, fsel);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1062
  free_pins:
673ba5a05   Wei Yongjun   pinctrl: single: ...
1063
  	mutex_unlock(&pcs->mutex);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1064
1065
1066
1067
1068
1069
1070
  	devm_kfree(pcs->dev, pins);
  
  free_vals:
  	devm_kfree(pcs->dev, vals);
  
  	return res;
  }
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1071

4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1072
1073
1074
1075
1076
1077
  static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
  						struct device_node *np,
  						struct pinctrl_map **map,
  						unsigned *num_maps,
  						const char **pgnames)
  {
dd68a526c   Axel Haslam   pinctrl: single: ...
1078
  	const char *name = "pinctrl-single,bits";
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1079
  	struct pcs_func_vals *vals;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1080
  	int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1081
  	int npins_in_row;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1082
  	struct pcs_function *function = NULL;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1083

22d5127ec   Tony Lindgren   pinctrl: single: ...
1084
  	rows = pinctrl_count_index_with_args(np, name);
de7416bce   Axel Haslam   pinctrl: single: ...
1085
1086
1087
1088
1089
  	if (rows <= 0) {
  		dev_err(pcs->dev, "Invalid number of rows: %d
  ", rows);
  		return -EINVAL;
  	}
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1090

4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1091
  	npins_in_row = pcs->width / pcs->bits_per_pin;
a86854d0c   Kees Cook   treewide: devm_kz...
1092
1093
1094
  	vals = devm_kzalloc(pcs->dev,
  			    array3_size(rows, npins_in_row, sizeof(*vals)),
  			    GFP_KERNEL);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1095
1096
  	if (!vals)
  		return -ENOMEM;
a86854d0c   Kees Cook   treewide: devm_kz...
1097
1098
1099
  	pins = devm_kzalloc(pcs->dev,
  			    array3_size(rows, npins_in_row, sizeof(*pins)),
  			    GFP_KERNEL);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1100
1101
  	if (!pins)
  		goto free_vals;
22d5127ec   Tony Lindgren   pinctrl: single: ...
1102
1103
  	for (i = 0; i < rows; i++) {
  		struct of_phandle_args pinctrl_spec;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1104
1105
1106
1107
  		unsigned offset, val;
  		unsigned mask, bit_pos, val_pos, mask_pos, submask;
  		unsigned pin_num_from_lsb;
  		int pin;
22d5127ec   Tony Lindgren   pinctrl: single: ...
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
  		res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
  		if (res)
  			return res;
  
  		if (pinctrl_spec.args_count < 3) {
  			dev_err(pcs->dev, "invalid args_count for spec: %i
  ",
  				pinctrl_spec.args_count);
  			break;
  		}
  
  		/* Index plus two value cells */
  		offset = pinctrl_spec.args[0];
  		val = pinctrl_spec.args[1];
  		mask = pinctrl_spec.args[2];
94f4e54ce   Rob Herring   pinctrl: Convert ...
1123
1124
1125
  		dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x mask: 0x%x
  ",
  			pinctrl_spec.np, offset, val, mask);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1126
1127
1128
  
  		/* Parse pins in each row from LSB */
  		while (mask) {
56b367c0c   Keerthy   pinctrl: single: ...
1129
  			bit_pos = __ffs(mask);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1130
  			pin_num_from_lsb = bit_pos / pcs->bits_per_pin;
56b367c0c   Keerthy   pinctrl: single: ...
1131
  			mask_pos = ((pcs->fmask) << bit_pos);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1132
1133
  			val_pos = val & mask_pos;
  			submask = mask & mask_pos;
ad5d25fef   Tomi Valkeinen   pinctrl: single: ...
1134
1135
1136
  
  			if ((mask & mask_pos) == 0) {
  				dev_err(pcs->dev,
94f4e54ce   Rob Herring   pinctrl: Convert ...
1137
1138
1139
  					"Invalid mask for %pOFn at 0x%x
  ",
  					np, offset);
ad5d25fef   Tomi Valkeinen   pinctrl: single: ...
1140
1141
  				break;
  			}
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1142
1143
1144
1145
  			mask &= ~mask_pos;
  
  			if (submask != mask_pos) {
  				dev_warn(pcs->dev,
94f4e54ce   Rob Herring   pinctrl: Convert ...
1146
1147
1148
  						"Invalid submask 0x%x for %pOFn at 0x%x
  ",
  						submask, np, offset);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
  				continue;
  			}
  
  			vals[found].mask = submask;
  			vals[found].reg = pcs->base + offset;
  			vals[found].val = val_pos;
  
  			pin = pcs_get_pin_by_offset(pcs, offset);
  			if (pin < 0) {
  				dev_err(pcs->dev,
94f4e54ce   Rob Herring   pinctrl: Convert ...
1159
1160
1161
  					"could not add functions for %pOFn %ux
  ",
  					np, offset);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1162
1163
1164
1165
1166
1167
1168
  				break;
  			}
  			pins[found++] = pin + pin_num_from_lsb;
  		}
  	}
  
  	pgnames[0] = np->name;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1169
1170
1171
1172
1173
  	mutex_lock(&pcs->mutex);
  	fsel = pcs_add_function(pcs, &function, np->name, vals, found,
  				pgnames, 1);
  	if (fsel < 0) {
  		res = fsel;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1174
  		goto free_pins;
712778d02   Dan Carpenter   pinctrl: single: ...
1175
  	}
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1176

a4ab10860   Tony Lindgren   pinctrl: single: ...
1177
1178
1179
  	gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
  	if (gsel < 0) {
  		res = gsel;
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1180
  		goto free_function;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1181
  	}
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1182
1183
1184
1185
  
  	(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
  	(*map)->data.mux.group = np->name;
  	(*map)->data.mux.function = np->name;
02e483f66   Tony Lindgren   pinctrl: single: ...
1186
  	if (PCS_HAS_PINCONF) {
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1187
1188
1189
1190
1191
1192
  		dev_err(pcs->dev, "pinconf not supported
  ");
  		goto free_pingroups;
  	}
  
  	*num_maps = 1;
a4ab10860   Tony Lindgren   pinctrl: single: ...
1193
  	mutex_unlock(&pcs->mutex);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1194
1195
1196
  	return 0;
  
  free_pingroups:
a4ab10860   Tony Lindgren   pinctrl: single: ...
1197
  	pinctrl_generic_remove_group(pcs->pctl, gsel);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1198
1199
  	*num_maps = 1;
  free_function:
a4ab10860   Tony Lindgren   pinctrl: single: ...
1200
  	pinmux_generic_remove_function(pcs->pctl, fsel);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1201
  free_pins:
673ba5a05   Wei Yongjun   pinctrl: single: ...
1202
  	mutex_unlock(&pcs->mutex);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1203
1204
1205
1206
1207
1208
1209
  	devm_kfree(pcs->dev, pins);
  
  free_vals:
  	devm_kfree(pcs->dev, vals);
  
  	return res;
  }
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  /**
   * pcs_dt_node_to_map() - allocates and parses pinctrl maps
   * @pctldev: pinctrl instance
   * @np_config: device tree pinmux entry
   * @map: array of map entries
   * @num_maps: number of maps
   */
  static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
  				struct device_node *np_config,
  				struct pinctrl_map **map, unsigned *num_maps)
  {
  	struct pcs_device *pcs;
  	const char **pgnames;
  	int ret;
  
  	pcs = pinctrl_dev_get_drvdata(pctldev);
9dddb4df9   Haojian Zhuang   pinctrl: single: ...
1226
  	/* create 2 maps. One is for pinmux, and the other is for pinconf. */
a86854d0c   Kees Cook   treewide: devm_kz...
1227
  	*map = devm_kcalloc(pcs->dev, 2, sizeof(**map), GFP_KERNEL);
00e79d127   Sachin Kamat   pinctrl: pinctrl-...
1228
  	if (!*map)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1229
1230
1231
1232
1233
1234
1235
1236
1237
  		return -ENOMEM;
  
  	*num_maps = 0;
  
  	pgnames = devm_kzalloc(pcs->dev, sizeof(*pgnames), GFP_KERNEL);
  	if (!pgnames) {
  		ret = -ENOMEM;
  		goto free_map;
  	}
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1238
1239
1240
1241
  	if (pcs->bits_per_mux) {
  		ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map,
  				num_maps, pgnames);
  		if (ret < 0) {
94f4e54ce   Rob Herring   pinctrl: Convert ...
1242
1243
1244
  			dev_err(pcs->dev, "no pins entries for %pOFn
  ",
  				np_config);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1245
1246
1247
1248
1249
1250
  			goto free_pgnames;
  		}
  	} else {
  		ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map,
  				num_maps, pgnames);
  		if (ret < 0) {
94f4e54ce   Rob Herring   pinctrl: Convert ...
1251
1252
1253
  			dev_err(pcs->dev, "no pins entries for %pOFn
  ",
  				np_config);
4e7e8017a   Manjunathappa, Prakash   pinctrl: pinctrl-...
1254
1255
  			goto free_pgnames;
  		}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1256
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  
  	return 0;
  
  free_pgnames:
  	devm_kfree(pcs->dev, pgnames);
  free_map:
  	devm_kfree(pcs->dev, *map);
  
  	return ret;
  }
  
  /**
3e6cee178   Tony Lindgren   pinctrl: single: ...
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
   * pcs_irq_free() - free interrupt
   * @pcs: pcs driver instance
   */
  static void pcs_irq_free(struct pcs_device *pcs)
  {
  	struct pcs_soc_data *pcs_soc = &pcs->socdata;
  
  	if (pcs_soc->irq < 0)
  		return;
  
  	if (pcs->domain)
  		irq_domain_remove(pcs->domain);
  
  	if (PCS_QUIRK_HAS_SHARED_IRQ)
  		free_irq(pcs_soc->irq, pcs_soc);
  	else
  		irq_set_chained_handler(pcs_soc->irq, NULL);
  }
  
  /**
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1289
1290
1291
1292
1293
   * pcs_free_resources() - free memory used by this driver
   * @pcs: pcs driver instance
   */
  static void pcs_free_resources(struct pcs_device *pcs)
  {
3e6cee178   Tony Lindgren   pinctrl: single: ...
1294
  	pcs_irq_free(pcs);
f10a25858   Markus Elfring   pinctrl: Delete u...
1295
  	pinctrl_unregister(pcs->pctl);
caeb774ea   Tony Lindgren   pinctrl: single: ...
1296

4622215fb   Tony Lindgren   pinctrl: single: ...
1297
1298
1299
1300
  #if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
  	if (pcs->missing_nr_pinctrl_cells)
  		of_remove_property(pcs->np, pcs->missing_nr_pinctrl_cells);
  #endif
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1301
  }
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
  static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
  {
  	const char *propname = "pinctrl-single,gpio-range";
  	const char *cellname = "#pinctrl-single,gpio-range-cells";
  	struct of_phandle_args gpiospec;
  	struct pcs_gpiofunc_range *range;
  	int ret, i;
  
  	for (i = 0; ; i++) {
  		ret = of_parse_phandle_with_args(node, propname, cellname,
  						 i, &gpiospec);
  		/* Do not treat it as error. Only treat it as end condition. */
  		if (ret) {
  			ret = 0;
  			break;
  		}
  		range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
  		if (!range) {
  			ret = -ENOMEM;
  			break;
  		}
  		range->offset = gpiospec.args[0];
  		range->npins = gpiospec.args[1];
  		range->gpiofunc = gpiospec.args[2];
  		mutex_lock(&pcs->mutex);
  		list_add_tail(&range->node, &pcs->gpiofuncs);
  		mutex_unlock(&pcs->mutex);
  	}
  	return ret;
  }
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
1332

3e6cee178   Tony Lindgren   pinctrl: single: ...
1333
  /**
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
1334
   * struct pcs_interrupt
3e6cee178   Tony Lindgren   pinctrl: single: ...
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
   * @reg:	virtual address of interrupt register
   * @hwirq:	hardware irq number
   * @irq:	virtual irq number
   * @node:	list node
   */
  struct pcs_interrupt {
  	void __iomem *reg;
  	irq_hw_number_t hwirq;
  	unsigned int irq;
  	struct list_head node;
  };
  
  /**
   * pcs_irq_set() - enables or disables an interrupt
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
1349
1350
1351
   * @pcs_soc: SoC specific settings
   * @irq: interrupt
   * @enable: enable or disable the interrupt
3e6cee178   Tony Lindgren   pinctrl: single: ...
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
   *
   * Note that this currently assumes one interrupt per pinctrl
   * register that is typically used for wake-up events.
   */
  static inline void pcs_irq_set(struct pcs_soc_data *pcs_soc,
  			       int irq, const bool enable)
  {
  	struct pcs_device *pcs;
  	struct list_head *pos;
  	unsigned mask;
  
  	pcs = container_of(pcs_soc, struct pcs_device, socdata);
  	list_for_each(pos, &pcs->irqs) {
  		struct pcs_interrupt *pcswi;
  		unsigned soc_mask;
  
  		pcswi = list_entry(pos, struct pcs_interrupt, node);
  		if (irq != pcswi->irq)
  			continue;
  
  		soc_mask = pcs_soc->irq_enable_mask;
  		raw_spin_lock(&pcs->lock);
  		mask = pcs->read(pcswi->reg);
  		if (enable)
  			mask |= soc_mask;
  		else
  			mask &= ~soc_mask;
  		pcs->write(mask, pcswi->reg);
0ac3c0a40   Tony Lindgren   pinctrl: single: ...
1380
1381
1382
  
  		/* flush posted write */
  		mask = pcs->read(pcswi->reg);
3e6cee178   Tony Lindgren   pinctrl: single: ...
1383
1384
  		raw_spin_unlock(&pcs->lock);
  	}
c9b3a7d22   Roger Quadros   pinctrl: single: ...
1385
1386
1387
  
  	if (pcs_soc->rearm)
  		pcs_soc->rearm();
3e6cee178   Tony Lindgren   pinctrl: single: ...
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
  }
  
  /**
   * pcs_irq_mask() - mask pinctrl interrupt
   * @d: interrupt data
   */
  static void pcs_irq_mask(struct irq_data *d)
  {
  	struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d);
  
  	pcs_irq_set(pcs_soc, d->irq, false);
  }
  
  /**
   * pcs_irq_unmask() - unmask pinctrl interrupt
   * @d: interrupt data
   */
  static void pcs_irq_unmask(struct irq_data *d)
  {
  	struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d);
  
  	pcs_irq_set(pcs_soc, d->irq, true);
  }
  
  /**
   * pcs_irq_set_wake() - toggle the suspend and resume wake up
   * @d: interrupt data
   * @state: wake-up state
   *
   * Note that this should be called only for suspend and resume.
   * For runtime PM, the wake-up events should be enabled by default.
   */
  static int pcs_irq_set_wake(struct irq_data *d, unsigned int state)
  {
  	if (state)
  		pcs_irq_unmask(d);
  	else
  		pcs_irq_mask(d);
  
  	return 0;
  }
  
  /**
   * pcs_irq_handle() - common interrupt handler
0ba5ab002   Lee Jones   pinctrl: pinctrl-...
1432
   * @pcs_soc: SoC specific settings
3e6cee178   Tony Lindgren   pinctrl: single: ...
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
   *
   * Note that this currently assumes we have one interrupt bit per
   * mux register. This interrupt is typically used for wake-up events.
   * For more complex interrupts different handlers can be specified.
   */
  static int pcs_irq_handle(struct pcs_soc_data *pcs_soc)
  {
  	struct pcs_device *pcs;
  	struct list_head *pos;
  	int count = 0;
  
  	pcs = container_of(pcs_soc, struct pcs_device, socdata);
  	list_for_each(pos, &pcs->irqs) {
  		struct pcs_interrupt *pcswi;
  		unsigned mask;
  
  		pcswi = list_entry(pos, struct pcs_interrupt, node);
  		raw_spin_lock(&pcs->lock);
  		mask = pcs->read(pcswi->reg);
  		raw_spin_unlock(&pcs->lock);
  		if (mask & pcs_soc->irq_status_mask) {
  			generic_handle_irq(irq_find_mapping(pcs->domain,
  							    pcswi->hwirq));
  			count++;
  		}
  	}
  
  	return count;
  }
  
  /**
   * pcs_irq_handler() - handler for the shared interrupt case
   * @irq: interrupt
   * @d: data
   *
   * Use this for cases where multiple instances of
   * pinctrl-single share a single interrupt like on omaps.
   */
  static irqreturn_t pcs_irq_handler(int irq, void *d)
  {
  	struct pcs_soc_data *pcs_soc = d;
  
  	return pcs_irq_handle(pcs_soc) ? IRQ_HANDLED : IRQ_NONE;
  }
  
  /**
   * pcs_irq_handle() - handler for the dedicated chained interrupt case
3e6cee178   Tony Lindgren   pinctrl: single: ...
1480
1481
1482
1483
1484
   * @desc: interrupt descriptor
   *
   * Use this if you have a separate interrupt for each
   * pinctrl-single instance.
   */
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
1485
  static void pcs_irq_chain_handler(struct irq_desc *desc)
3e6cee178   Tony Lindgren   pinctrl: single: ...
1486
1487
1488
  {
  	struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
  	struct irq_chip *chip;
3e6cee178   Tony Lindgren   pinctrl: single: ...
1489

5663bb27d   Jiang Liu   pinctrl: Use irq_...
1490
  	chip = irq_desc_get_chip(desc);
3e6cee178   Tony Lindgren   pinctrl: single: ...
1491
  	chained_irq_enter(chip, desc);
849bfe063   Rickard Strandqvist   pinctrl: pinctrl-...
1492
  	pcs_irq_handle(pcs_soc);
3e6cee178   Tony Lindgren   pinctrl: single: ...
1493
1494
  	/* REVISIT: export and add handle_bad_irq(irq, desc)? */
  	chained_irq_exit(chip, desc);
3e6cee178   Tony Lindgren   pinctrl: single: ...
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
  }
  
  static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq,
  			     irq_hw_number_t hwirq)
  {
  	struct pcs_soc_data *pcs_soc = d->host_data;
  	struct pcs_device *pcs;
  	struct pcs_interrupt *pcswi;
  
  	pcs = container_of(pcs_soc, struct pcs_device, socdata);
  	pcswi = devm_kzalloc(pcs->dev, sizeof(*pcswi), GFP_KERNEL);
  	if (!pcswi)
  		return -ENOMEM;
  
  	pcswi->reg = pcs->base + hwirq;
  	pcswi->hwirq = hwirq;
  	pcswi->irq = irq;
  
  	mutex_lock(&pcs->mutex);
  	list_add_tail(&pcswi->node, &pcs->irqs);
  	mutex_unlock(&pcs->mutex);
  
  	irq_set_chip_data(irq, pcs_soc);
  	irq_set_chip_and_handler(irq, &pcs->chip,
  				 handle_level_irq);
39c3fd589   Andrew Lunn   kernel/irq: Exten...
1520
  	irq_set_lockdep_class(irq, &pcs_lock_class, &pcs_request_class);
1b9c0fb36   Tony Lindgren   pinctrl: single: ...
1521
  	irq_set_noprobe(irq);
3e6cee178   Tony Lindgren   pinctrl: single: ...
1522
1523
1524
  
  	return 0;
  }
e5b609537   Krzysztof Kozlowski   pinctrl: single: ...
1525
  static const struct irq_domain_ops pcs_irqdomain_ops = {
3e6cee178   Tony Lindgren   pinctrl: single: ...
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
  	.map = pcs_irqdomain_map,
  	.xlate = irq_domain_xlate_onecell,
  };
  
  /**
   * pcs_irq_init_chained_handler() - set up a chained interrupt handler
   * @pcs: pcs driver instance
   * @np: device node pointer
   */
  static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
  					struct device_node *np)
  {
  	struct pcs_soc_data *pcs_soc = &pcs->socdata;
  	const char *name = "pinctrl";
  	int num_irqs;
  
  	if (!pcs_soc->irq_enable_mask ||
  	    !pcs_soc->irq_status_mask) {
  		pcs_soc->irq = -1;
  		return -EINVAL;
  	}
  
  	INIT_LIST_HEAD(&pcs->irqs);
  	pcs->chip.name = name;
  	pcs->chip.irq_ack = pcs_irq_mask;
  	pcs->chip.irq_mask = pcs_irq_mask;
  	pcs->chip.irq_unmask = pcs_irq_unmask;
  	pcs->chip.irq_set_wake = pcs_irq_set_wake;
  
  	if (PCS_QUIRK_HAS_SHARED_IRQ) {
  		int res;
  
  		res = request_irq(pcs_soc->irq, pcs_irq_handler,
c10372e61   Grygorii Strashko   pinctrl: single: ...
1559
1560
  				  IRQF_SHARED | IRQF_NO_SUSPEND |
  				  IRQF_NO_THREAD,
3e6cee178   Tony Lindgren   pinctrl: single: ...
1561
1562
1563
1564
1565
1566
  				  name, pcs_soc);
  		if (res) {
  			pcs_soc->irq = -1;
  			return res;
  		}
  	} else {
20d5d142a   Thomas Gleixner   pinctrl: Consolid...
1567
1568
1569
  		irq_set_chained_handler_and_data(pcs_soc->irq,
  						 pcs_irq_chain_handler,
  						 pcs_soc);
3e6cee178   Tony Lindgren   pinctrl: single: ...
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
  	}
  
  	/*
  	 * We can use the register offset as the hardirq
  	 * number as irq_domain_add_simple maps them lazily.
  	 * This way we can easily support more than one
  	 * interrupt per function if needed.
  	 */
  	num_irqs = pcs->size;
  
  	pcs->domain = irq_domain_add_simple(np, num_irqs, 0,
  					    &pcs_irqdomain_ops,
  					    pcs_soc);
  	if (!pcs->domain) {
  		irq_set_chained_handler(pcs_soc->irq, NULL);
  		return -EINVAL;
  	}
  
  	return 0;
  }
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
1590

8cb440ab7   Jean-Francois Moine   pinctrl: pinctrl-...
1591
  #ifdef CONFIG_PM
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1592
1593
1594
1595
1596
1597
1598
1599
  static int pcs_save_context(struct pcs_device *pcs)
  {
  	int i, mux_bytes;
  	u64 *regsl;
  	u32 *regsw;
  	u16 *regshw;
  
  	mux_bytes = pcs->width / BITS_PER_BYTE;
7f57871f3   Colin Ian King   pinctrl: single: ...
1600
  	if (!pcs->saved_vals) {
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1601
  		pcs->saved_vals = devm_kzalloc(pcs->dev, pcs->size, GFP_ATOMIC);
7f57871f3   Colin Ian King   pinctrl: single: ...
1602
1603
1604
  		if (!pcs->saved_vals)
  			return -ENOMEM;
  	}
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1605
1606
1607
  
  	switch (pcs->width) {
  	case 64:
7d71b5f4b   Geert Uytterhoeven   pinctrl: pinctrl-...
1608
1609
1610
  		regsl = pcs->saved_vals;
  		for (i = 0; i < pcs->size; i += mux_bytes)
  			*regsl++ = pcs->read(pcs->base + i);
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1611
1612
  		break;
  	case 32:
7d71b5f4b   Geert Uytterhoeven   pinctrl: pinctrl-...
1613
1614
1615
  		regsw = pcs->saved_vals;
  		for (i = 0; i < pcs->size; i += mux_bytes)
  			*regsw++ = pcs->read(pcs->base + i);
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1616
1617
  		break;
  	case 16:
7d71b5f4b   Geert Uytterhoeven   pinctrl: pinctrl-...
1618
1619
1620
  		regshw = pcs->saved_vals;
  		for (i = 0; i < pcs->size; i += mux_bytes)
  			*regshw++ = pcs->read(pcs->base + i);
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
  		break;
  	}
  
  	return 0;
  }
  
  static void pcs_restore_context(struct pcs_device *pcs)
  {
  	int i, mux_bytes;
  	u64 *regsl;
  	u32 *regsw;
  	u16 *regshw;
  
  	mux_bytes = pcs->width / BITS_PER_BYTE;
  
  	switch (pcs->width) {
  	case 64:
7d71b5f4b   Geert Uytterhoeven   pinctrl: pinctrl-...
1638
1639
1640
  		regsl = pcs->saved_vals;
  		for (i = 0; i < pcs->size; i += mux_bytes)
  			pcs->write(*regsl++, pcs->base + i);
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1641
1642
  		break;
  	case 32:
7d71b5f4b   Geert Uytterhoeven   pinctrl: pinctrl-...
1643
1644
1645
  		regsw = pcs->saved_vals;
  		for (i = 0; i < pcs->size; i += mux_bytes)
  			pcs->write(*regsw++, pcs->base + i);
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1646
1647
  		break;
  	case 16:
7d71b5f4b   Geert Uytterhoeven   pinctrl: pinctrl-...
1648
1649
1650
  		regshw = pcs->saved_vals;
  		for (i = 0; i < pcs->size; i += mux_bytes)
  			pcs->write(*regshw++, pcs->base + i);
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1651
1652
1653
  		break;
  	}
  }
0f9bc4bcd   Hebbar Gururaja   pinctrl: single: ...
1654
1655
1656
1657
1658
1659
1660
1661
  static int pinctrl_single_suspend(struct platform_device *pdev,
  					pm_message_t state)
  {
  	struct pcs_device *pcs;
  
  	pcs = platform_get_drvdata(pdev);
  	if (!pcs)
  		return -EINVAL;
7f57871f3   Colin Ian King   pinctrl: single: ...
1662
1663
1664
1665
1666
1667
1668
  	if (pcs->flags & PCS_CONTEXT_LOSS_OFF) {
  		int ret;
  
  		ret = pcs_save_context(pcs);
  		if (ret < 0)
  			return ret;
  	}
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1669

0f9bc4bcd   Hebbar Gururaja   pinctrl: single: ...
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
  	return pinctrl_force_sleep(pcs->pctl);
  }
  
  static int pinctrl_single_resume(struct platform_device *pdev)
  {
  	struct pcs_device *pcs;
  
  	pcs = platform_get_drvdata(pdev);
  	if (!pcs)
  		return -EINVAL;
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1680
1681
  	if (pcs->flags & PCS_CONTEXT_LOSS_OFF)
  		pcs_restore_context(pcs);
0f9bc4bcd   Hebbar Gururaja   pinctrl: single: ...
1682
1683
  	return pinctrl_force_default(pcs->pctl);
  }
8cb440ab7   Jean-Francois Moine   pinctrl: pinctrl-...
1684
  #endif
0f9bc4bcd   Hebbar Gururaja   pinctrl: single: ...
1685

4622215fb   Tony Lindgren   pinctrl: single: ...
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
  /**
   * pcs_quirk_missing_pinctrl_cells - handle legacy binding
   * @pcs: pinctrl driver instance
   * @np: device tree node
   * @cells: number of cells
   *
   * Handle legacy binding with no #pinctrl-cells. This should be
   * always two pinctrl-single,bit-per-mux and one for others.
   * At some point we may want to consider removing this.
   */
  static int pcs_quirk_missing_pinctrl_cells(struct pcs_device *pcs,
  					   struct device_node *np,
  					   int cells)
  {
  	struct property *p;
  	const char *name = "#pinctrl-cells";
  	int error;
  	u32 val;
  
  	error = of_property_read_u32(np, name, &val);
  	if (!error)
  		return 0;
  
  	dev_warn(pcs->dev, "please update dts to use %s = <%i>
  ",
  		 name, cells);
  
  	p = devm_kzalloc(pcs->dev, sizeof(*p), GFP_KERNEL);
  	if (!p)
  		return -ENOMEM;
  
  	p->length = sizeof(__be32);
  	p->value = devm_kzalloc(pcs->dev, sizeof(__be32), GFP_KERNEL);
  	if (!p->value)
  		return -ENOMEM;
  	*(__be32 *)p->value = cpu_to_be32(cells);
  
  	p->name = devm_kstrdup(pcs->dev, name, GFP_KERNEL);
  	if (!p->name)
  		return -ENOMEM;
  
  	pcs->missing_nr_pinctrl_cells = p;
  
  #if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
  	error = of_add_property(np, pcs->missing_nr_pinctrl_cells);
  #endif
  
  	return error;
  }
150632b09   Greg Kroah-Hartman   Drivers: pinctrl:...
1735
  static int pcs_probe(struct platform_device *pdev)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1736
1737
  {
  	struct device_node *np = pdev->dev.of_node;
dc7743aa3   Tony Lindgren   pinctrl: single: ...
1738
  	struct pcs_pdata *pdata;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1739
1740
  	struct resource *res;
  	struct pcs_device *pcs;
02e483f66   Tony Lindgren   pinctrl: single: ...
1741
  	const struct pcs_soc_data *soc;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1742
  	int ret;
1a8764f45   Masahiro Yamada   pinctrl: single: ...
1743
1744
  	soc = of_device_get_match_data(&pdev->dev);
  	if (WARN_ON(!soc))
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1745
1746
1747
  		return -EINVAL;
  
  	pcs = devm_kzalloc(&pdev->dev, sizeof(*pcs), GFP_KERNEL);
a14aa2716   Markus Elfring   pinctrl: single: ...
1748
  	if (!pcs)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1749
  		return -ENOMEM;
a14aa2716   Markus Elfring   pinctrl: single: ...
1750

8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1751
  	pcs->dev = &pdev->dev;
4622215fb   Tony Lindgren   pinctrl: single: ...
1752
  	pcs->np = np;
3e6cee178   Tony Lindgren   pinctrl: single: ...
1753
  	raw_spin_lock_init(&pcs->lock);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1754
  	mutex_init(&pcs->mutex);
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
1755
  	INIT_LIST_HEAD(&pcs->gpiofuncs);
02e483f66   Tony Lindgren   pinctrl: single: ...
1756
  	pcs->flags = soc->flags;
3e6cee178   Tony Lindgren   pinctrl: single: ...
1757
  	memcpy(&pcs->socdata, soc, sizeof(*soc));
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1758

cd23604a4   Tony Lindgren   pinctrl: single: ...
1759
1760
1761
1762
1763
1764
1765
1766
  	ret = of_property_read_u32(np, "pinctrl-single,register-width",
  				   &pcs->width);
  	if (ret) {
  		dev_err(pcs->dev, "register width not specified
  ");
  
  		return ret;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1767

477ac771d   Haojian Zhuang   pinctrl: single: ...
1768
1769
1770
  	ret = of_property_read_u32(np, "pinctrl-single,function-mask",
  				   &pcs->fmask);
  	if (!ret) {
56b367c0c   Keerthy   pinctrl: single: ...
1771
  		pcs->fshift = __ffs(pcs->fmask);
477ac771d   Haojian Zhuang   pinctrl: single: ...
1772
1773
1774
1775
1776
1777
1778
  		pcs->fmax = pcs->fmask >> pcs->fshift;
  	} else {
  		/* If mask property doesn't exist, function mux is invalid. */
  		pcs->fmask = 0;
  		pcs->fshift = 0;
  		pcs->fmax = 0;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1779
1780
1781
1782
1783
  
  	ret = of_property_read_u32(np, "pinctrl-single,function-off",
  					&pcs->foff);
  	if (ret)
  		pcs->foff = PCS_OFF_DISABLED;
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
1784
1785
  	pcs->bits_per_mux = of_property_read_bool(np,
  						  "pinctrl-single,bit-per-mux");
4622215fb   Tony Lindgren   pinctrl: single: ...
1786
1787
1788
1789
1790
1791
1792
1793
  	ret = pcs_quirk_missing_pinctrl_cells(pcs, np,
  					      pcs->bits_per_mux ? 2 : 1);
  	if (ret) {
  		dev_err(&pdev->dev, "unable to patch #pinctrl-cells
  ");
  
  		return ret;
  	}
9e605cb68   Peter Ujfalusi   pinctrl: pinctrl-...
1794

8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!res) {
  		dev_err(pcs->dev, "could not get resource
  ");
  		return -ENODEV;
  	}
  
  	pcs->res = devm_request_mem_region(pcs->dev, res->start,
  			resource_size(res), DRIVER_NAME);
  	if (!pcs->res) {
  		dev_err(pcs->dev, "could not get mem_region
  ");
  		return -EBUSY;
  	}
  
  	pcs->size = resource_size(pcs->res);
  	pcs->base = devm_ioremap(pcs->dev, pcs->res->start, pcs->size);
  	if (!pcs->base) {
  		dev_err(pcs->dev, "could not ioremap
  ");
  		return -ENODEV;
  	}
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
  	platform_set_drvdata(pdev, pcs);
  
  	switch (pcs->width) {
  	case 8:
  		pcs->read = pcs_readb;
  		pcs->write = pcs_writeb;
  		break;
  	case 16:
  		pcs->read = pcs_readw;
  		pcs->write = pcs_writew;
  		break;
  	case 32:
  		pcs->read = pcs_readl;
  		pcs->write = pcs_writel;
  		break;
  	default:
  		break;
  	}
  
  	pcs->desc.name = DRIVER_NAME;
  	pcs->desc.pctlops = &pcs_pinctrl_ops;
  	pcs->desc.pmxops = &pcs_pinmux_ops;
02e483f66   Tony Lindgren   pinctrl: single: ...
1839
  	if (PCS_HAS_PINCONF)
a7bbdd7f8   Axel Lin   pinctrl: single: ...
1840
  		pcs->desc.confops = &pcs_pinconf_ops;
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1841
1842
1843
1844
1845
  	pcs->desc.owner = THIS_MODULE;
  
  	ret = pcs_allocate_pin_table(pcs);
  	if (ret < 0)
  		goto free;
950b0d91d   Tony Lindgren   pinctrl: core: Fi...
1846
1847
  	ret = pinctrl_register_and_init(&pcs->desc, pcs->dev, pcs, &pcs->pctl);
  	if (ret) {
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1848
1849
  		dev_err(pcs->dev, "could not register single pinctrl driver
  ");
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1850
1851
  		goto free;
  	}
a1a277eb7   Haojian Zhuang   pinctrl: single: ...
1852
1853
1854
  	ret = pcs_add_gpio_func(np, pcs);
  	if (ret < 0)
  		goto free;
3e6cee178   Tony Lindgren   pinctrl: single: ...
1855
1856
1857
  	pcs->socdata.irq = irq_of_parse_and_map(np, 0);
  	if (pcs->socdata.irq)
  		pcs->flags |= PCS_FEAT_IRQ;
dc7743aa3   Tony Lindgren   pinctrl: single: ...
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
  	/* We still need auxdata for some omaps for PRM interrupts */
  	pdata = dev_get_platdata(&pdev->dev);
  	if (pdata) {
  		if (pdata->rearm)
  			pcs->socdata.rearm = pdata->rearm;
  		if (pdata->irq) {
  			pcs->socdata.irq = pdata->irq;
  			pcs->flags |= PCS_FEAT_IRQ;
  		}
  	}
3e6cee178   Tony Lindgren   pinctrl: single: ...
1868
1869
1870
1871
1872
1873
  	if (PCS_HAS_IRQ) {
  		ret = pcs_irq_init_chained_handler(pcs, np);
  		if (ret < 0)
  			dev_warn(pcs->dev, "initialized with no interrupts
  ");
  	}
c2584927b   Tony Lindgren   pinctrl: single: ...
1874
1875
  	dev_info(pcs->dev, "%i pins, size %u
  ", pcs->desc.npins, pcs->size);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1876

611871427   Tony Lindgren   pinctrl: core: Fi...
1877
  	return pinctrl_enable(pcs->pctl);
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1878
1879
1880
1881
1882
1883
  
  free:
  	pcs_free_resources(pcs);
  
  	return ret;
  }
f90f54b3f   Bill Pemberton   pinctrl: remove u...
1884
  static int pcs_remove(struct platform_device *pdev)
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
  {
  	struct pcs_device *pcs = platform_get_drvdata(pdev);
  
  	if (!pcs)
  		return 0;
  
  	pcs_free_resources(pcs);
  
  	return 0;
  }
3e6cee178   Tony Lindgren   pinctrl: single: ...
1895
1896
1897
1898
1899
  static const struct pcs_soc_data pinctrl_single_omap_wkup = {
  	.flags = PCS_QUIRK_SHARED_IRQ,
  	.irq_enable_mask = (1 << 14),	/* OMAP_WAKEUP_EN */
  	.irq_status_mask = (1 << 15),	/* OMAP_WAKEUP_EVENT */
  };
31320beaa   Nishanth Menon   pinctrl: single: ...
1900
  static const struct pcs_soc_data pinctrl_single_dra7 = {
31320beaa   Nishanth Menon   pinctrl: single: ...
1901
1902
1903
  	.irq_enable_mask = (1 << 24),	/* WAKEUPENABLE */
  	.irq_status_mask = (1 << 25),	/* WAKEUPEVENT */
  };
aa2293d82   Keerthy   pinctrl: single: ...
1904
  static const struct pcs_soc_data pinctrl_single_am437x = {
88a1dbdec   Keerthy   pinctrl: pinctrl-...
1905
  	.flags = PCS_QUIRK_SHARED_IRQ | PCS_CONTEXT_LOSS_OFF,
aa2293d82   Keerthy   pinctrl: single: ...
1906
1907
1908
  	.irq_enable_mask = (1 << 29),   /* OMAP_WAKEUP_EN */
  	.irq_status_mask = (1 << 30),   /* OMAP_WAKEUP_EVENT */
  };
02e483f66   Tony Lindgren   pinctrl: single: ...
1909
1910
1911
1912
1913
1914
  static const struct pcs_soc_data pinctrl_single = {
  };
  
  static const struct pcs_soc_data pinconf_single = {
  	.flags = PCS_FEAT_PINCONF,
  };
baa9946e3   Fabian Frederick   pinctrl: constify...
1915
  static const struct of_device_id pcs_of_match[] = {
3e6cee178   Tony Lindgren   pinctrl: single: ...
1916
1917
1918
  	{ .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup },
  	{ .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup },
  	{ .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup },
31320beaa   Nishanth Menon   pinctrl: single: ...
1919
  	{ .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 },
aa2293d82   Keerthy   pinctrl: single: ...
1920
  	{ .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x },
02e483f66   Tony Lindgren   pinctrl: single: ...
1921
1922
  	{ .compatible = "pinctrl-single", .data = &pinctrl_single },
  	{ .compatible = "pinconf-single", .data = &pinconf_single },
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1923
1924
1925
1926
1927
1928
  	{ },
  };
  MODULE_DEVICE_TABLE(of, pcs_of_match);
  
  static struct platform_driver pcs_driver = {
  	.probe		= pcs_probe,
2a36f0863   Bill Pemberton   pinctrl: remove u...
1929
  	.remove		= pcs_remove,
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1930
  	.driver = {
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1931
1932
1933
  		.name		= DRIVER_NAME,
  		.of_match_table	= pcs_of_match,
  	},
0f9bc4bcd   Hebbar Gururaja   pinctrl: single: ...
1934
1935
1936
1937
  #ifdef CONFIG_PM
  	.suspend = pinctrl_single_suspend,
  	.resume = pinctrl_single_resume,
  #endif
8b8b091bf   Tony Lindgren   pinctrl: Add one-...
1938
1939
1940
1941
1942
1943
1944
  };
  
  module_platform_driver(pcs_driver);
  
  MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
  MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver");
  MODULE_LICENSE("GPL v2");