Blame view
drivers/pinctrl/pinctrl-single.c
48.3 KB
8b8b091bf 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 pinctrl: single: ... |
18 19 20 |
#include <linux/interrupt.h> #include <linux/irqchip/chained_irq.h> |
8b8b091bf pinctrl: Add one-... |
21 22 23 24 |
#include <linux/of.h> #include <linux/of_device.h> #include <linux/of_address.h> |
3e6cee178 pinctrl: single: ... |
25 |
#include <linux/of_irq.h> |
8b8b091bf pinctrl: Add one-... |
26 27 28 |
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> |
9dddb4df9 pinctrl: single: ... |
29 |
#include <linux/pinctrl/pinconf-generic.h> |
8b8b091bf pinctrl: Add one-... |
30 |
|
dc7743aa3 pinctrl: single: ... |
31 |
#include <linux/platform_data/pinctrl-single.h> |
8b8b091bf pinctrl: Add one-... |
32 |
#include "core.h" |
4622215fb pinctrl: single: ... |
33 |
#include "devicetree.h" |
9dddb4df9 pinctrl: single: ... |
34 |
#include "pinconf.h" |
571aec4df pinctrl: single: ... |
35 |
#include "pinmux.h" |
8b8b091bf pinctrl: Add one-... |
36 37 |
#define DRIVER_NAME "pinctrl-single" |
8b8b091bf pinctrl: Add one-... |
38 39 40 |
#define PCS_OFF_DISABLED ~0U /** |
8b8b091bf 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 pinctrl: pinctrl-... |
44 |
* @mask: mask |
8b8b091bf pinctrl: Add one-... |
45 46 47 48 |
*/ struct pcs_func_vals { void __iomem *reg; unsigned val; |
9e605cb68 pinctrl: pinctrl-... |
49 |
unsigned mask; |
8b8b091bf pinctrl: Add one-... |
50 51 52 |
}; /** |
9dddb4df9 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 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 pinctrl: pinctrl-... |
86 87 |
* @conf: array of pin configurations * @nconfs: number of pin configurations available |
8b8b091bf 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 pinctrl: single: ... |
96 97 |
struct pcs_conf_vals *conf; int nconfs; |
8b8b091bf pinctrl: Add one-... |
98 99 100 101 |
struct list_head node; }; /** |
a1a277eb7 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 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 pinctrl: single: ... |
130 131 |
* struct pcs_soc_data - SoC specific settings * @flags: initial SoC specific PCS_FEAT_xxx values |
3e6cee178 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 pinctrl: single: ... |
135 |
* @rearm: optional SoC specific wake-up rearm function |
02e483f66 pinctrl: single: ... |
136 137 138 |
*/ struct pcs_soc_data { unsigned flags; |
3e6cee178 pinctrl: single: ... |
139 140 141 |
int irq; unsigned irq_enable_mask; unsigned irq_status_mask; |
dc7743aa3 pinctrl: single: ... |
142 |
void (*rearm)(void); |
02e483f66 pinctrl: single: ... |
143 144 145 |
}; /** |
8b8b091bf pinctrl: Add one-... |
146 147 148 |
* struct pcs_device - pinctrl device instance * @res: resources * @base: virtual address of the controller |
88a1dbdec pinctrl: pinctrl-... |
149 |
* @saved_vals: saved values for the controller |
8b8b091bf pinctrl: Add one-... |
150 151 |
* @size: size of the ioremapped area * @dev: device entry |
4622215fb pinctrl: single: ... |
152 |
* @np: device tree node |
8b8b091bf pinctrl: Add one-... |
153 |
* @pctl: pin controller device |
02e483f66 pinctrl: single: ... |
154 |
* @flags: mask of PCS_FEAT_xxx values |
4622215fb pinctrl: single: ... |
155 156 |
* @missing_nr_pinctrl_cells: for legacy binding, may go away * @socdata: soc specific data |
3e6cee178 pinctrl: single: ... |
157 |
* @lock: spinlock for register access |
8b8b091bf 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 pinctrl: single: ... |
164 165 |
* @bits_per_mux: number of bits per mux * @bits_per_pin: number of bits per pin |
8b8b091bf pinctrl: Add one-... |
166 |
* @pins: physical pins on the SoC |
a1a277eb7 pinctrl: single: ... |
167 |
* @gpiofuncs: list of gpio functions |
3e6cee178 pinctrl: single: ... |
168 169 170 |
* @irqs: list of interrupt registers * @chip: chip container for this instance * @domain: IRQ domain for this instance |
8b8b091bf 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 pinctrl: pinctrl-... |
178 |
void *saved_vals; |
8b8b091bf pinctrl: Add one-... |
179 180 |
unsigned size; struct device *dev; |
4622215fb pinctrl: single: ... |
181 |
struct device_node *np; |
8b8b091bf pinctrl: Add one-... |
182 |
struct pinctrl_dev *pctl; |
02e483f66 pinctrl: single: ... |
183 |
unsigned flags; |
88a1dbdec pinctrl: pinctrl-... |
184 |
#define PCS_CONTEXT_LOSS_OFF (1 << 3) |
3e6cee178 pinctrl: single: ... |
185 186 |
#define PCS_QUIRK_SHARED_IRQ (1 << 2) #define PCS_FEAT_IRQ (1 << 1) |
02e483f66 pinctrl: single: ... |
187 |
#define PCS_FEAT_PINCONF (1 << 0) |
4622215fb pinctrl: single: ... |
188 |
struct property *missing_nr_pinctrl_cells; |
3e6cee178 pinctrl: single: ... |
189 190 |
struct pcs_soc_data socdata; raw_spinlock_t lock; |
8b8b091bf pinctrl: Add one-... |
191 192 193 194 195 196 |
struct mutex mutex; unsigned width; unsigned fmask; unsigned fshift; unsigned foff; unsigned fmax; |
9e605cb68 pinctrl: pinctrl-... |
197 |
bool bits_per_mux; |
4e7e8017a pinctrl: pinctrl-... |
198 |
unsigned bits_per_pin; |
8b8b091bf pinctrl: Add one-... |
199 |
struct pcs_data pins; |
a1a277eb7 pinctrl: single: ... |
200 |
struct list_head gpiofuncs; |
3e6cee178 pinctrl: single: ... |
201 202 203 |
struct list_head irqs; struct irq_chip chip; struct irq_domain *domain; |
8b8b091bf pinctrl: Add one-... |
204 205 206 207 |
struct pinctrl_desc desc; unsigned (*read)(void __iomem *reg); void (*write)(unsigned val, void __iomem *reg); }; |
3e6cee178 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 pinctrl: single: ... |
210 |
#define PCS_HAS_PINCONF (pcs->flags & PCS_FEAT_PINCONF) |
9dddb4df9 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 pinctrl: Pass all... |
214 |
unsigned long *configs, unsigned num_configs); |
9dddb4df9 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 pinctrl: Add one-... |
220 |
/* |
3c177a166 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 kernel/irq: Exten... |
226 227 |
/* Class for the IRQ request mutex */ static struct lock_class_key pcs_request_class; |
3c177a166 pinctrl: single: ... |
228 |
/* |
8b8b091bf 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 pinctrl: Add one-... |
266 267 |
static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, |
e7ed67182 pinctrl: single: ... |
268 |
unsigned pin) |
8b8b091bf pinctrl: Add one-... |
269 |
{ |
7d66ce7f8 pinctrl: pinctrl-... |
270 |
struct pcs_device *pcs; |
e7ed67182 pinctrl: single: ... |
271 |
unsigned val, mux_bytes; |
223decc45 pinctrl: single: ... |
272 273 |
unsigned long offset; size_t pa; |
7d66ce7f8 pinctrl: pinctrl-... |
274 275 |
pcs = pinctrl_dev_get_drvdata(pctldev); |
e7ed67182 pinctrl: single: ... |
276 |
mux_bytes = pcs->width / BITS_PER_BYTE; |
223decc45 pinctrl: single: ... |
277 278 279 |
offset = pin * mux_bytes; val = pcs->read(pcs->base + offset); pa = pcs->res->start + offset; |
7d66ce7f8 pinctrl: pinctrl-... |
280 |
|
223decc45 pinctrl: single: ... |
281 |
seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME); |
8b8b091bf 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 pinctrl: Declare ... |
296 |
static const struct pinctrl_ops pcs_pinctrl_ops = { |
caeb774ea 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 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 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 pinctrl: single: ... |
310 |
struct function_desc *function; |
9dddb4df9 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 pinctrl: single: ... |
318 319 |
function = pinmux_generic_get_function(pctldev, fselector); *func = function->data; |
9dddb4df9 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 pinctrl: clean up... |
328 |
static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector, |
8b8b091bf pinctrl: Add one-... |
329 330 331 |
unsigned group) { struct pcs_device *pcs; |
571aec4df pinctrl: single: ... |
332 |
struct function_desc *function; |
8b8b091bf pinctrl: Add one-... |
333 334 335 336 |
struct pcs_function *func; int i; pcs = pinctrl_dev_get_drvdata(pctldev); |
477ac771d pinctrl: single: ... |
337 338 339 |
/* If function mask is null, needn't enable it. */ if (!pcs->fmask) return 0; |
571aec4df pinctrl: single: ... |
340 341 |
function = pinmux_generic_get_function(pctldev, fselector); func = function->data; |
8b8b091bf 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 pinctrl: single: ... |
351 |
unsigned long flags; |
9e605cb68 pinctrl: pinctrl-... |
352 |
unsigned val, mask; |
8b8b091bf pinctrl: Add one-... |
353 354 |
vals = &func->vals[i]; |
3e6cee178 pinctrl: single: ... |
355 |
raw_spin_lock_irqsave(&pcs->lock, flags); |
8b8b091bf pinctrl: Add one-... |
356 |
val = pcs->read(vals->reg); |
4e7e8017a pinctrl: pinctrl-... |
357 358 359 |
if (pcs->bits_per_mux) mask = vals->mask; |
9e605cb68 pinctrl: pinctrl-... |
360 |
else |
4e7e8017a pinctrl: pinctrl-... |
361 |
mask = pcs->fmask; |
9e605cb68 pinctrl: pinctrl-... |
362 363 364 |
val &= ~mask; val |= (vals->val & mask); |
8b8b091bf pinctrl: Add one-... |
365 |
pcs->write(val, vals->reg); |
3e6cee178 pinctrl: single: ... |
366 |
raw_spin_unlock_irqrestore(&pcs->lock, flags); |
8b8b091bf pinctrl: Add one-... |
367 368 369 370 |
} return 0; } |
8b8b091bf pinctrl: Add one-... |
371 |
static int pcs_request_gpio(struct pinctrl_dev *pctldev, |
a1a277eb7 pinctrl: single: ... |
372 |
struct pinctrl_gpio_range *range, unsigned pin) |
8b8b091bf pinctrl: Add one-... |
373 |
{ |
a1a277eb7 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 pinctrl: single: ... |
379 380 381 |
/* If function mask is null, return directly. */ if (!pcs->fmask) return -ENOTSUPP; |
a1a277eb7 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 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 pinctrl: single: ... |
407 408 409 |
break; } return 0; |
8b8b091bf pinctrl: Add one-... |
410 |
} |
022ab148d pinctrl: Declare ... |
411 |
static const struct pinmux_ops pcs_pinmux_ops = { |
571aec4df 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 pinctrl: single: ... |
415 |
.set_mux = pcs_set_mux, |
8b8b091bf pinctrl: Add one-... |
416 417 |
.gpio_request_enable = pcs_request_gpio, }; |
9dddb4df9 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 pinctrl: Pass all... |
425 |
pcs_pinconf_set(pctldev, pin, &config, 1); |
9dddb4df9 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 pinctrl: Add one-... |
447 448 449 |
static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config) { |
9dddb4df9 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 pinctrl: single: ... |
500 |
case PIN_CONFIG_LOW_POWER_MODE: |
9dddb4df9 pinctrl: single: ... |
501 502 503 504 505 506 |
default: *config = data; break; } return 0; } |
8b8b091bf pinctrl: Add one-... |
507 508 509 510 |
return -ENOTSUPP; } static int pcs_pinconf_set(struct pinctrl_dev *pctldev, |
03b054e96 pinctrl: Pass all... |
511 512 |
unsigned pin, unsigned long *configs, unsigned num_configs) |
8b8b091bf pinctrl: Add one-... |
513 |
{ |
9dddb4df9 pinctrl: single: ... |
514 515 |
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); struct pcs_function *func; |
7cba5b3f5 pinctrl: single: ... |
516 |
unsigned offset = 0, shift = 0, i, data, ret; |
58957d2ed pinctrl: Widen th... |
517 |
u32 arg; |
03b054e96 pinctrl: Pass all... |
518 |
int j; |
9dddb4df9 pinctrl: single: ... |
519 520 521 522 |
ret = pcs_get_function(pctldev, pin, &func); if (ret) return ret; |
03b054e96 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 pinctrl: single: ... |
528 529 |
offset = pin * (pcs->width / BITS_PER_BYTE); data = pcs->read(pcs->base + offset); |
03b054e96 pinctrl: Pass all... |
530 |
arg = pinconf_to_config_argument(configs[j]); |
9dddb4df9 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 pinctrl: single: ... |
536 |
case PIN_CONFIG_LOW_POWER_MODE: |
9dddb4df9 pinctrl: single: ... |
537 |
shift = ffs(func->conf[i].mask) - 1; |
9dddb4df9 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 pinctrl: single: ... |
547 |
if (arg) |
9dddb4df9 pinctrl: single: ... |
548 |
pcs_pinconf_clear_bias(pctldev, pin); |
c44295566 pinctrl: single: ... |
549 |
fallthrough; |
9dddb4df9 pinctrl: single: ... |
550 551 |
case PIN_CONFIG_INPUT_SCHMITT_ENABLE: data &= ~func->conf[i].mask; |
7cba5b3f5 pinctrl: single: ... |
552 |
if (arg) |
9dddb4df9 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 pinctrl: Pass all... |
561 562 |
break; |
9dddb4df9 pinctrl: single: ... |
563 |
} |
03b054e96 pinctrl: Pass all... |
564 565 566 567 568 |
if (i >= func->nconfs) return -ENOTSUPP; } /* for each config */ return 0; |
8b8b091bf pinctrl: Add one-... |
569 570 571 572 573 |
} static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned group, unsigned long *config) { |
9dddb4df9 pinctrl: single: ... |
574 575 576 |
const unsigned *pins; unsigned npins, old = 0; int i, ret; |
caeb774ea pinctrl: single: ... |
577 |
ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); |
9dddb4df9 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 pinctrl: Add one-... |
589 590 591 |
} static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev, |
03b054e96 pinctrl: Pass all... |
592 593 |
unsigned group, unsigned long *configs, unsigned num_configs) |
8b8b091bf pinctrl: Add one-... |
594 |
{ |
9dddb4df9 pinctrl: single: ... |
595 596 597 |
const unsigned *pins; unsigned npins; int i, ret; |
caeb774ea pinctrl: single: ... |
598 |
ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); |
9dddb4df9 pinctrl: single: ... |
599 600 601 |
if (ret) return ret; for (i = 0; i < npins; i++) { |
03b054e96 pinctrl: Pass all... |
602 |
if (pcs_pinconf_set(pctldev, pins[i], configs, num_configs)) |
9dddb4df9 pinctrl: single: ... |
603 604 605 |
return -ENOTSUPP; } return 0; |
8b8b091bf pinctrl: Add one-... |
606 607 608 |
} static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev, |
9dddb4df9 pinctrl: single: ... |
609 |
struct seq_file *s, unsigned pin) |
8b8b091bf 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 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 pinctrl: Declare ... |
623 |
static const struct pinconf_ops pcs_pinconf_ops = { |
8b8b091bf 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 pinctrl: single: ... |
630 |
.pin_config_config_dbg_show = pcs_pinconf_config_dbg_show, |
a7bbdd7f8 pinctrl: single: ... |
631 |
.is_generic = true, |
8b8b091bf 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 pinctrl: pinctrl-... |
638 |
* @pin_pos: unused |
8b8b091bf pinctrl: Add one-... |
639 |
*/ |
6f924b0b7 pinctrl: pinctrl-... |
640 641 |
static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, unsigned pin_pos) |
8b8b091bf pinctrl: Add one-... |
642 |
{ |
58968625c pinctrl: single: ... |
643 |
struct pcs_soc_data *pcs_soc = &pcs->socdata; |
8b8b091bf pinctrl: Add one-... |
644 |
struct pinctrl_pin_desc *pin; |
8b8b091bf 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 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 pinctrl: Add one-... |
666 |
pin = &pcs->pins.pa[i]; |
8b8b091bf 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 Drivers: pinctrl:... |
682 |
static int pcs_allocate_pin_table(struct pcs_device *pcs) |
8b8b091bf pinctrl: Add one-... |
683 684 |
{ int mux_bytes, nr_pins, i; |
6f924b0b7 pinctrl: pinctrl-... |
685 |
int num_pins_in_register = 0; |
8b8b091bf pinctrl: Add one-... |
686 687 |
mux_bytes = pcs->width / BITS_PER_BYTE; |
4e7e8017a 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 pinctrl: pinctrl-... |
692 |
num_pins_in_register = pcs->width / pcs->bits_per_pin; |
4e7e8017a pinctrl: pinctrl-... |
693 694 695 |
} else { nr_pins = pcs->size / mux_bytes; } |
8b8b091bf pinctrl: Add one-... |
696 697 698 |
dev_dbg(pcs->dev, "allocating %i pins ", nr_pins); |
a86854d0c treewide: devm_kz... |
699 700 |
pcs->pins.pa = devm_kcalloc(pcs->dev, nr_pins, sizeof(*pcs->pins.pa), |
8b8b091bf pinctrl: Add one-... |
701 702 703 |
GFP_KERNEL); if (!pcs->pins.pa) return -ENOMEM; |
8b8b091bf 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 pinctrl: pinctrl-... |
710 |
int byte_num; |
6f924b0b7 pinctrl: pinctrl-... |
711 |
int pin_pos = 0; |
8b8b091bf pinctrl: Add one-... |
712 |
|
4e7e8017a 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 pinctrl: pinctrl-... |
716 |
pin_pos = i % num_pins_in_register; |
4e7e8017a pinctrl: pinctrl-... |
717 718 719 |
} else { offset = i * mux_bytes; } |
6f924b0b7 pinctrl: pinctrl-... |
720 |
res = pcs_add_pin(pcs, offset, pin_pos); |
8b8b091bf 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 pinctrl: single: ... |
734 |
* @fcn: new function allocated |
8b8b091bf 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 pinctrl: single: ... |
740 741 |
* * Caller must take care of locking. |
8b8b091bf pinctrl: Add one-... |
742 |
*/ |
a4ab10860 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 pinctrl: Add one-... |
750 751 |
{ struct pcs_function *function; |
a4ab10860 pinctrl: single: ... |
752 |
int selector; |
8b8b091bf pinctrl: Add one-... |
753 754 755 |
function = devm_kzalloc(pcs->dev, sizeof(*function), GFP_KERNEL); if (!function) |
a4ab10860 pinctrl: single: ... |
756 |
return -ENOMEM; |
8b8b091bf pinctrl: Add one-... |
757 |
|
8b8b091bf pinctrl: Add one-... |
758 759 |
function->vals = vals; function->nvals = nvals; |
8b8b091bf pinctrl: Add one-... |
760 |
|
a4ab10860 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 pinctrl: Add one-... |
770 |
|
a4ab10860 pinctrl: single: ... |
771 |
return selector; |
8b8b091bf pinctrl: Add one-... |
772 |
} |
8b8b091bf pinctrl: Add one-... |
773 |
/** |
8b8b091bf 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 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 pinctrl: Add one-... |
794 795 796 |
return index; } |
9dddb4df9 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 pinctrl: single: ... |
837 |
unsigned value[2], shift; |
9dddb4df9 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 pinctrl: single: ... |
845 |
shift = ffs(value[1]) - 1; |
9dddb4df9 pinctrl: single: ... |
846 847 |
/* skip enable & disable */ add_config(conf, param, value[0], 0, 0, value[1]); |
7cba5b3f5 pinctrl: single: ... |
848 |
add_setting(settings, param, value[0] >> shift); |
9dddb4df9 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 pinctrl: single: ... |
888 |
static const struct pcs_conf_type prop2[] = { |
9dddb4df9 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 pinctrl: single: ... |
892 |
{ "pinctrl-single,low-power-mode", PIN_CONFIG_LOW_POWER_MODE, }, |
9dddb4df9 pinctrl: single: ... |
893 |
}; |
b582658ae pinctrl: single: ... |
894 |
static const struct pcs_conf_type prop4[] = { |
9dddb4df9 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 pinctrl: single: ... |
902 |
if (!PCS_HAS_PINCONF) |
f46fe79ff pinctrl-single: f... |
903 |
return -ENOTSUPP; |
9dddb4df9 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 pinctrl-single: f... |
915 |
return -ENOTSUPP; |
9dddb4df9 pinctrl: single: ... |
916 |
|
a86854d0c treewide: devm_kz... |
917 918 |
func->conf = devm_kcalloc(pcs->dev, nconfs, sizeof(struct pcs_conf_vals), |
9dddb4df9 pinctrl: single: ... |
919 920 921 922 923 924 |
GFP_KERNEL); if (!func->conf) return -ENOMEM; func->nconfs = nconfs; conf = &(func->conf[0]); m++; |
a86854d0c treewide: devm_kz... |
925 |
settings = devm_kcalloc(pcs->dev, nconfs, sizeof(unsigned long), |
9dddb4df9 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 pinctrl: Add one-... |
943 |
/** |
bc6d20159 pinctrl: single: ... |
944 |
* pcs_parse_one_pinctrl_entry() - parses a device tree mux entry |
8b8b091bf pinctrl: Add one-... |
945 946 947 |
* @pcs: pinctrl driver instance * @np: device node of the mux entry * @map: map entry |
9dddb4df9 pinctrl: single: ... |
948 |
* @num_maps: number of map |
8b8b091bf 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 pinctrl: single: ... |
965 |
unsigned *num_maps, |
8b8b091bf pinctrl: Add one-... |
966 967 |
const char **pgnames) { |
4622215fb pinctrl: single: ... |
968 |
const char *name = "pinctrl-single,pins"; |
8b8b091bf pinctrl: Add one-... |
969 |
struct pcs_func_vals *vals; |
a4ab10860 pinctrl: single: ... |
970 971 |
int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel; struct pcs_function *function = NULL; |
8b8b091bf pinctrl: Add one-... |
972 |
|
4622215fb pinctrl: single: ... |
973 |
rows = pinctrl_count_index_with_args(np, name); |
de7416bce pinctrl: single: ... |
974 |
if (rows <= 0) { |
059a6e630 pinctrl: single: ... |
975 976 |
dev_err(pcs->dev, "Invalid number of rows: %d ", rows); |
de7416bce pinctrl: single: ... |
977 978 |
return -EINVAL; } |
8b8b091bf pinctrl: Add one-... |
979 |
|
a86854d0c treewide: devm_kz... |
980 |
vals = devm_kcalloc(pcs->dev, rows, sizeof(*vals), GFP_KERNEL); |
8b8b091bf pinctrl: Add one-... |
981 982 |
if (!vals) return -ENOMEM; |
a86854d0c treewide: devm_kz... |
983 |
pins = devm_kcalloc(pcs->dev, rows, sizeof(*pins), GFP_KERNEL); |
8b8b091bf pinctrl: Add one-... |
984 985 |
if (!pins) goto free_vals; |
4622215fb pinctrl: single: ... |
986 987 988 |
for (i = 0; i < rows; i++) { struct of_phandle_args pinctrl_spec; unsigned int offset; |
8b8b091bf pinctrl: Add one-... |
989 |
int pin; |
4622215fb pinctrl: single: ... |
990 991 992 |
res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec); if (res) return res; |
9b9448f39 pinctrl: single: ... |
993 |
if (pinctrl_spec.args_count < 2 || pinctrl_spec.args_count > 3) { |
4622215fb pinctrl: single: ... |
994 995 996 997 998 |
dev_err(pcs->dev, "invalid args_count for spec: %i ", pinctrl_spec.args_count); break; } |
4622215fb pinctrl: single: ... |
999 |
offset = pinctrl_spec.args[0]; |
8b8b091bf pinctrl: Add one-... |
1000 |
vals[found].reg = pcs->base + offset; |
a13395418 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 pinctrl: single: ... |
1010 |
|
94f4e54ce pinctrl: Convert ... |
1011 1012 |
dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x ", |
f4a2b19c3 pinctrl: single: ... |
1013 |
pinctrl_spec.np, offset, vals[found].val); |
8b8b091bf pinctrl: Add one-... |
1014 1015 1016 1017 |
pin = pcs_get_pin_by_offset(pcs, offset); if (pin < 0) { dev_err(pcs->dev, |
94f4e54ce pinctrl: Convert ... |
1018 1019 1020 |
"could not add functions for %pOFn %ux ", np, offset); |
8b8b091bf pinctrl: Add one-... |
1021 1022 1023 1024 1025 1026 |
break; } pins[found++] = pin; } pgnames[0] = np->name; |
a4ab10860 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 pinctrl: Add one-... |
1032 |
goto free_pins; |
712778d02 pinctrl: single: ... |
1033 |
} |
8b8b091bf pinctrl: Add one-... |
1034 |
|
a4ab10860 pinctrl: single: ... |
1035 1036 1037 |
gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs); if (gsel < 0) { res = gsel; |
8b8b091bf pinctrl: Add one-... |
1038 |
goto free_function; |
a4ab10860 pinctrl: single: ... |
1039 |
} |
8b8b091bf 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 pinctrl: single: ... |
1044 |
if (PCS_HAS_PINCONF && function) { |
18442e65d pinctrl: single: ... |
1045 |
res = pcs_parse_pinconf(pcs, np, function, map); |
f46fe79ff pinctrl-single: f... |
1046 1047 1048 1049 1050 |
if (res == 0) *num_maps = 2; else if (res == -ENOTSUPP) *num_maps = 1; else |
9dddb4df9 pinctrl: single: ... |
1051 |
goto free_pingroups; |
9dddb4df9 pinctrl: single: ... |
1052 1053 1054 |
} else { *num_maps = 1; } |
a4ab10860 pinctrl: single: ... |
1055 |
mutex_unlock(&pcs->mutex); |
8b8b091bf pinctrl: Add one-... |
1056 |
return 0; |
9dddb4df9 pinctrl: single: ... |
1057 |
free_pingroups: |
a4ab10860 pinctrl: single: ... |
1058 |
pinctrl_generic_remove_group(pcs->pctl, gsel); |
9dddb4df9 pinctrl: single: ... |
1059 |
*num_maps = 1; |
8b8b091bf pinctrl: Add one-... |
1060 |
free_function: |
a4ab10860 pinctrl: single: ... |
1061 |
pinmux_generic_remove_function(pcs->pctl, fsel); |
8b8b091bf pinctrl: Add one-... |
1062 |
free_pins: |
673ba5a05 pinctrl: single: ... |
1063 |
mutex_unlock(&pcs->mutex); |
8b8b091bf 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 pinctrl: pinctrl-... |
1071 |
|
4e7e8017a 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 pinctrl: single: ... |
1078 |
const char *name = "pinctrl-single,bits"; |
4e7e8017a pinctrl: pinctrl-... |
1079 |
struct pcs_func_vals *vals; |
a4ab10860 pinctrl: single: ... |
1080 |
int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel; |
4e7e8017a pinctrl: pinctrl-... |
1081 |
int npins_in_row; |
a4ab10860 pinctrl: single: ... |
1082 |
struct pcs_function *function = NULL; |
4e7e8017a pinctrl: pinctrl-... |
1083 |
|
22d5127ec pinctrl: single: ... |
1084 |
rows = pinctrl_count_index_with_args(np, name); |
de7416bce pinctrl: single: ... |
1085 1086 1087 1088 1089 |
if (rows <= 0) { dev_err(pcs->dev, "Invalid number of rows: %d ", rows); return -EINVAL; } |
4e7e8017a pinctrl: pinctrl-... |
1090 |
|
4e7e8017a pinctrl: pinctrl-... |
1091 |
npins_in_row = pcs->width / pcs->bits_per_pin; |
a86854d0c treewide: devm_kz... |
1092 1093 1094 |
vals = devm_kzalloc(pcs->dev, array3_size(rows, npins_in_row, sizeof(*vals)), GFP_KERNEL); |
4e7e8017a pinctrl: pinctrl-... |
1095 1096 |
if (!vals) return -ENOMEM; |
a86854d0c treewide: devm_kz... |
1097 1098 1099 |
pins = devm_kzalloc(pcs->dev, array3_size(rows, npins_in_row, sizeof(*pins)), GFP_KERNEL); |
4e7e8017a pinctrl: pinctrl-... |
1100 1101 |
if (!pins) goto free_vals; |
22d5127ec pinctrl: single: ... |
1102 1103 |
for (i = 0; i < rows; i++) { struct of_phandle_args pinctrl_spec; |
4e7e8017a 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 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 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 pinctrl: pinctrl-... |
1126 1127 1128 |
/* Parse pins in each row from LSB */ while (mask) { |
56b367c0c pinctrl: single: ... |
1129 |
bit_pos = __ffs(mask); |
4e7e8017a pinctrl: pinctrl-... |
1130 |
pin_num_from_lsb = bit_pos / pcs->bits_per_pin; |
56b367c0c pinctrl: single: ... |
1131 |
mask_pos = ((pcs->fmask) << bit_pos); |
4e7e8017a pinctrl: pinctrl-... |
1132 1133 |
val_pos = val & mask_pos; submask = mask & mask_pos; |
ad5d25fef pinctrl: single: ... |
1134 1135 1136 |
if ((mask & mask_pos) == 0) { dev_err(pcs->dev, |
94f4e54ce pinctrl: Convert ... |
1137 1138 1139 |
"Invalid mask for %pOFn at 0x%x ", np, offset); |
ad5d25fef pinctrl: single: ... |
1140 1141 |
break; } |
4e7e8017a pinctrl: pinctrl-... |
1142 1143 1144 1145 |
mask &= ~mask_pos; if (submask != mask_pos) { dev_warn(pcs->dev, |
94f4e54ce pinctrl: Convert ... |
1146 1147 1148 |
"Invalid submask 0x%x for %pOFn at 0x%x ", submask, np, offset); |
4e7e8017a 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 pinctrl: Convert ... |
1159 1160 1161 |
"could not add functions for %pOFn %ux ", np, offset); |
4e7e8017a pinctrl: pinctrl-... |
1162 1163 1164 1165 1166 1167 1168 |
break; } pins[found++] = pin + pin_num_from_lsb; } } pgnames[0] = np->name; |
a4ab10860 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 pinctrl: pinctrl-... |
1174 |
goto free_pins; |
712778d02 pinctrl: single: ... |
1175 |
} |
4e7e8017a pinctrl: pinctrl-... |
1176 |
|
a4ab10860 pinctrl: single: ... |
1177 1178 1179 |
gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs); if (gsel < 0) { res = gsel; |
4e7e8017a pinctrl: pinctrl-... |
1180 |
goto free_function; |
a4ab10860 pinctrl: single: ... |
1181 |
} |
4e7e8017a 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 pinctrl: single: ... |
1186 |
if (PCS_HAS_PINCONF) { |
4e7e8017a pinctrl: pinctrl-... |
1187 1188 1189 1190 1191 1192 |
dev_err(pcs->dev, "pinconf not supported "); goto free_pingroups; } *num_maps = 1; |
a4ab10860 pinctrl: single: ... |
1193 |
mutex_unlock(&pcs->mutex); |
4e7e8017a pinctrl: pinctrl-... |
1194 1195 1196 |
return 0; free_pingroups: |
a4ab10860 pinctrl: single: ... |
1197 |
pinctrl_generic_remove_group(pcs->pctl, gsel); |
4e7e8017a pinctrl: pinctrl-... |
1198 1199 |
*num_maps = 1; free_function: |
a4ab10860 pinctrl: single: ... |
1200 |
pinmux_generic_remove_function(pcs->pctl, fsel); |
4e7e8017a pinctrl: pinctrl-... |
1201 |
free_pins: |
673ba5a05 pinctrl: single: ... |
1202 |
mutex_unlock(&pcs->mutex); |
4e7e8017a pinctrl: pinctrl-... |
1203 1204 1205 1206 1207 1208 1209 |
devm_kfree(pcs->dev, pins); free_vals: devm_kfree(pcs->dev, vals); return res; } |
8b8b091bf 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 pinctrl: single: ... |
1226 |
/* create 2 maps. One is for pinmux, and the other is for pinconf. */ |
a86854d0c treewide: devm_kz... |
1227 |
*map = devm_kcalloc(pcs->dev, 2, sizeof(**map), GFP_KERNEL); |
00e79d127 pinctrl: pinctrl-... |
1228 |
if (!*map) |
8b8b091bf 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 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 pinctrl: Convert ... |
1242 1243 1244 |
dev_err(pcs->dev, "no pins entries for %pOFn ", np_config); |
4e7e8017a 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 pinctrl: Convert ... |
1251 1252 1253 |
dev_err(pcs->dev, "no pins entries for %pOFn ", np_config); |
4e7e8017a pinctrl: pinctrl-... |
1254 1255 |
goto free_pgnames; } |
8b8b091bf pinctrl: Add one-... |
1256 |
} |
8b8b091bf 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 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 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 pinctrl: single: ... |
1294 |
pcs_irq_free(pcs); |
f10a25858 pinctrl: Delete u... |
1295 |
pinctrl_unregister(pcs->pctl); |
caeb774ea pinctrl: single: ... |
1296 |
|
4622215fb 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 pinctrl: Add one-... |
1301 |
} |
a1a277eb7 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 pinctrl: pinctrl-... |
1332 |
|
3e6cee178 pinctrl: single: ... |
1333 |
/** |
0ba5ab002 pinctrl: pinctrl-... |
1334 |
* struct pcs_interrupt |
3e6cee178 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 pinctrl: pinctrl-... |
1349 1350 1351 |
* @pcs_soc: SoC specific settings * @irq: interrupt * @enable: enable or disable the interrupt |
3e6cee178 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 pinctrl: single: ... |
1380 1381 1382 |
/* flush posted write */ mask = pcs->read(pcswi->reg); |
3e6cee178 pinctrl: single: ... |
1383 1384 |
raw_spin_unlock(&pcs->lock); } |
c9b3a7d22 pinctrl: single: ... |
1385 1386 1387 |
if (pcs_soc->rearm) pcs_soc->rearm(); |
3e6cee178 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 pinctrl: pinctrl-... |
1432 |
* @pcs_soc: SoC specific settings |
3e6cee178 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 pinctrl: single: ... |
1480 1481 1482 1483 1484 |
* @desc: interrupt descriptor * * Use this if you have a separate interrupt for each * pinctrl-single instance. */ |
bd0b9ac40 genirq: Remove ir... |
1485 |
static void pcs_irq_chain_handler(struct irq_desc *desc) |
3e6cee178 pinctrl: single: ... |
1486 1487 1488 |
{ struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc); struct irq_chip *chip; |
3e6cee178 pinctrl: single: ... |
1489 |
|
5663bb27d pinctrl: Use irq_... |
1490 |
chip = irq_desc_get_chip(desc); |
3e6cee178 pinctrl: single: ... |
1491 |
chained_irq_enter(chip, desc); |
849bfe063 pinctrl: pinctrl-... |
1492 |
pcs_irq_handle(pcs_soc); |
3e6cee178 pinctrl: single: ... |
1493 1494 |
/* REVISIT: export and add handle_bad_irq(irq, desc)? */ chained_irq_exit(chip, desc); |
3e6cee178 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 kernel/irq: Exten... |
1520 |
irq_set_lockdep_class(irq, &pcs_lock_class, &pcs_request_class); |
1b9c0fb36 pinctrl: single: ... |
1521 |
irq_set_noprobe(irq); |
3e6cee178 pinctrl: single: ... |
1522 1523 1524 |
return 0; } |
e5b609537 pinctrl: single: ... |
1525 |
static const struct irq_domain_ops pcs_irqdomain_ops = { |
3e6cee178 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 pinctrl: single: ... |
1559 1560 |
IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_NO_THREAD, |
3e6cee178 pinctrl: single: ... |
1561 1562 1563 1564 1565 1566 |
name, pcs_soc); if (res) { pcs_soc->irq = -1; return res; } } else { |
20d5d142a pinctrl: Consolid... |
1567 1568 1569 |
irq_set_chained_handler_and_data(pcs_soc->irq, pcs_irq_chain_handler, pcs_soc); |
3e6cee178 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 pinctrl: single: ... |
1590 |
|
8cb440ab7 pinctrl: pinctrl-... |
1591 |
#ifdef CONFIG_PM |
88a1dbdec 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 pinctrl: single: ... |
1600 |
if (!pcs->saved_vals) { |
88a1dbdec pinctrl: pinctrl-... |
1601 |
pcs->saved_vals = devm_kzalloc(pcs->dev, pcs->size, GFP_ATOMIC); |
7f57871f3 pinctrl: single: ... |
1602 1603 1604 |
if (!pcs->saved_vals) return -ENOMEM; } |
88a1dbdec pinctrl: pinctrl-... |
1605 1606 1607 |
switch (pcs->width) { case 64: |
7d71b5f4b 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 pinctrl: pinctrl-... |
1611 1612 |
break; case 32: |
7d71b5f4b 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 pinctrl: pinctrl-... |
1616 1617 |
break; case 16: |
7d71b5f4b 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 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 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 pinctrl: pinctrl-... |
1641 1642 |
break; case 32: |
7d71b5f4b 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 pinctrl: pinctrl-... |
1646 1647 |
break; case 16: |
7d71b5f4b 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 pinctrl: pinctrl-... |
1651 1652 1653 |
break; } } |
0f9bc4bcd 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 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 pinctrl: pinctrl-... |
1669 |
|
0f9bc4bcd 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 pinctrl: pinctrl-... |
1680 1681 |
if (pcs->flags & PCS_CONTEXT_LOSS_OFF) pcs_restore_context(pcs); |
0f9bc4bcd pinctrl: single: ... |
1682 1683 |
return pinctrl_force_default(pcs->pctl); } |
8cb440ab7 pinctrl: pinctrl-... |
1684 |
#endif |
0f9bc4bcd pinctrl: single: ... |
1685 |
|
4622215fb 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 Drivers: pinctrl:... |
1735 |
static int pcs_probe(struct platform_device *pdev) |
8b8b091bf pinctrl: Add one-... |
1736 1737 |
{ struct device_node *np = pdev->dev.of_node; |
dc7743aa3 pinctrl: single: ... |
1738 |
struct pcs_pdata *pdata; |
8b8b091bf pinctrl: Add one-... |
1739 1740 |
struct resource *res; struct pcs_device *pcs; |
02e483f66 pinctrl: single: ... |
1741 |
const struct pcs_soc_data *soc; |
8b8b091bf pinctrl: Add one-... |
1742 |
int ret; |
1a8764f45 pinctrl: single: ... |
1743 1744 |
soc = of_device_get_match_data(&pdev->dev); if (WARN_ON(!soc)) |
8b8b091bf pinctrl: Add one-... |
1745 1746 1747 |
return -EINVAL; pcs = devm_kzalloc(&pdev->dev, sizeof(*pcs), GFP_KERNEL); |
a14aa2716 pinctrl: single: ... |
1748 |
if (!pcs) |
8b8b091bf pinctrl: Add one-... |
1749 |
return -ENOMEM; |
a14aa2716 pinctrl: single: ... |
1750 |
|
8b8b091bf pinctrl: Add one-... |
1751 |
pcs->dev = &pdev->dev; |
4622215fb pinctrl: single: ... |
1752 |
pcs->np = np; |
3e6cee178 pinctrl: single: ... |
1753 |
raw_spin_lock_init(&pcs->lock); |
8b8b091bf pinctrl: Add one-... |
1754 |
mutex_init(&pcs->mutex); |
a1a277eb7 pinctrl: single: ... |
1755 |
INIT_LIST_HEAD(&pcs->gpiofuncs); |
02e483f66 pinctrl: single: ... |
1756 |
pcs->flags = soc->flags; |
3e6cee178 pinctrl: single: ... |
1757 |
memcpy(&pcs->socdata, soc, sizeof(*soc)); |
8b8b091bf pinctrl: Add one-... |
1758 |
|
cd23604a4 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 pinctrl: Add one-... |
1767 |
|
477ac771d pinctrl: single: ... |
1768 1769 1770 |
ret = of_property_read_u32(np, "pinctrl-single,function-mask", &pcs->fmask); if (!ret) { |
56b367c0c pinctrl: single: ... |
1771 |
pcs->fshift = __ffs(pcs->fmask); |
477ac771d 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 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 pinctrl: pinctrl-... |
1784 1785 |
pcs->bits_per_mux = of_property_read_bool(np, "pinctrl-single,bit-per-mux"); |
4622215fb 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 pinctrl: pinctrl-... |
1794 |
|
8b8b091bf 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 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 pinctrl: single: ... |
1839 |
if (PCS_HAS_PINCONF) |
a7bbdd7f8 pinctrl: single: ... |
1840 |
pcs->desc.confops = &pcs_pinconf_ops; |
8b8b091bf 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 pinctrl: core: Fi... |
1846 1847 |
ret = pinctrl_register_and_init(&pcs->desc, pcs->dev, pcs, &pcs->pctl); if (ret) { |
8b8b091bf pinctrl: Add one-... |
1848 1849 |
dev_err(pcs->dev, "could not register single pinctrl driver "); |
8b8b091bf pinctrl: Add one-... |
1850 1851 |
goto free; } |
a1a277eb7 pinctrl: single: ... |
1852 1853 1854 |
ret = pcs_add_gpio_func(np, pcs); if (ret < 0) goto free; |
3e6cee178 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 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 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 pinctrl: single: ... |
1874 1875 |
dev_info(pcs->dev, "%i pins, size %u ", pcs->desc.npins, pcs->size); |
8b8b091bf pinctrl: Add one-... |
1876 |
|
611871427 pinctrl: core: Fi... |
1877 |
return pinctrl_enable(pcs->pctl); |
8b8b091bf pinctrl: Add one-... |
1878 1879 1880 1881 1882 1883 |
free: pcs_free_resources(pcs); return ret; } |
f90f54b3f pinctrl: remove u... |
1884 |
static int pcs_remove(struct platform_device *pdev) |
8b8b091bf 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 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 pinctrl: single: ... |
1900 |
static const struct pcs_soc_data pinctrl_single_dra7 = { |
31320beaa pinctrl: single: ... |
1901 1902 1903 |
.irq_enable_mask = (1 << 24), /* WAKEUPENABLE */ .irq_status_mask = (1 << 25), /* WAKEUPEVENT */ }; |
aa2293d82 pinctrl: single: ... |
1904 |
static const struct pcs_soc_data pinctrl_single_am437x = { |
88a1dbdec pinctrl: pinctrl-... |
1905 |
.flags = PCS_QUIRK_SHARED_IRQ | PCS_CONTEXT_LOSS_OFF, |
aa2293d82 pinctrl: single: ... |
1906 1907 1908 |
.irq_enable_mask = (1 << 29), /* OMAP_WAKEUP_EN */ .irq_status_mask = (1 << 30), /* OMAP_WAKEUP_EVENT */ }; |
02e483f66 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 pinctrl: constify... |
1915 |
static const struct of_device_id pcs_of_match[] = { |
3e6cee178 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 pinctrl: single: ... |
1919 |
{ .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 }, |
aa2293d82 pinctrl: single: ... |
1920 |
{ .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x }, |
02e483f66 pinctrl: single: ... |
1921 1922 |
{ .compatible = "pinctrl-single", .data = &pinctrl_single }, { .compatible = "pinconf-single", .data = &pinconf_single }, |
8b8b091bf 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 pinctrl: remove u... |
1929 |
.remove = pcs_remove, |
8b8b091bf pinctrl: Add one-... |
1930 |
.driver = { |
8b8b091bf pinctrl: Add one-... |
1931 1932 1933 |
.name = DRIVER_NAME, .of_match_table = pcs_of_match, }, |
0f9bc4bcd pinctrl: single: ... |
1934 1935 1936 1937 |
#ifdef CONFIG_PM .suspend = pinctrl_single_suspend, .resume = pinctrl_single_resume, #endif |
8b8b091bf 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"); |