aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-samsung.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-samsung.c')
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c105
1 files changed, 66 insertions, 39 deletions
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 3d5cf639aa46..976366899f68 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -27,6 +27,7 @@
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/gpio.h> 28#include <linux/gpio.h>
29#include <linux/irqdomain.h> 29#include <linux/irqdomain.h>
30#include <linux/spinlock.h>
30 31
31#include "core.h" 32#include "core.h"
32#include "pinctrl-samsung.h" 33#include "pinctrl-samsung.h"
@@ -214,7 +215,7 @@ static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
214} 215}
215 216
216/* list of pinctrl callbacks for the pinctrl core */ 217/* list of pinctrl callbacks for the pinctrl core */
217static struct pinctrl_ops samsung_pctrl_ops = { 218static const struct pinctrl_ops samsung_pctrl_ops = {
218 .get_groups_count = samsung_get_group_count, 219 .get_groups_count = samsung_get_group_count,
219 .get_group_name = samsung_get_group_name, 220 .get_group_name = samsung_get_group_name,
220 .get_group_pins = samsung_get_group_pins, 221 .get_group_pins = samsung_get_group_pins,
@@ -274,10 +275,6 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
274 *offset = pin - b->pin_base; 275 *offset = pin - b->pin_base;
275 if (bank) 276 if (bank)
276 *bank = b; 277 *bank = b;
277
278 /* some banks have two config registers in a single bank */
279 if (*offset * b->func_width > BITS_PER_LONG)
280 *reg += 4;
281} 278}
282 279
283/* enable or disable a pinmux function */ 280/* enable or disable a pinmux function */
@@ -289,6 +286,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
289 struct samsung_pin_bank *bank; 286 struct samsung_pin_bank *bank;
290 void __iomem *reg; 287 void __iomem *reg;
291 u32 mask, shift, data, pin_offset, cnt; 288 u32 mask, shift, data, pin_offset, cnt;
289 unsigned long flags;
292 290
293 drvdata = pinctrl_dev_get_drvdata(pctldev); 291 drvdata = pinctrl_dev_get_drvdata(pctldev);
294 pins = drvdata->pin_groups[group].pins; 292 pins = drvdata->pin_groups[group].pins;
@@ -298,16 +296,28 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
298 * pin function number in the config register. 296 * pin function number in the config register.
299 */ 297 */
300 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { 298 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
299 struct samsung_pin_bank_type *type;
300
301 pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base, 301 pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
302 &reg, &pin_offset, &bank); 302 &reg, &pin_offset, &bank);
303 mask = (1 << bank->func_width) - 1; 303 type = bank->type;
304 shift = pin_offset * bank->func_width; 304 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
305 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
306 if (shift >= 32) {
307 /* Some banks have two config registers */
308 shift -= 32;
309 reg += 4;
310 }
311
312 spin_lock_irqsave(&bank->slock, flags);
305 313
306 data = readl(reg); 314 data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
307 data &= ~(mask << shift); 315 data &= ~(mask << shift);
308 if (enable) 316 if (enable)
309 data |= drvdata->pin_groups[group].func << shift; 317 data |= drvdata->pin_groups[group].func << shift;
310 writel(data, reg); 318 writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
319
320 spin_unlock_irqrestore(&bank->slock, flags);
311 } 321 }
312} 322}
313 323
@@ -334,30 +344,44 @@ static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
334static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, 344static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
335 struct pinctrl_gpio_range *range, unsigned offset, bool input) 345 struct pinctrl_gpio_range *range, unsigned offset, bool input)
336{ 346{
347 struct samsung_pin_bank_type *type;
337 struct samsung_pin_bank *bank; 348 struct samsung_pin_bank *bank;
338 struct samsung_pinctrl_drv_data *drvdata; 349 struct samsung_pinctrl_drv_data *drvdata;
339 void __iomem *reg; 350 void __iomem *reg;
340 u32 data, pin_offset, mask, shift; 351 u32 data, pin_offset, mask, shift;
352 unsigned long flags;
341 353
342 bank = gc_to_pin_bank(range->gc); 354 bank = gc_to_pin_bank(range->gc);
355 type = bank->type;
343 drvdata = pinctrl_dev_get_drvdata(pctldev); 356 drvdata = pinctrl_dev_get_drvdata(pctldev);
344 357
345 pin_offset = offset - bank->pin_base; 358 pin_offset = offset - bank->pin_base;
346 reg = drvdata->virt_base + bank->pctl_offset; 359 reg = drvdata->virt_base + bank->pctl_offset +
360 type->reg_offset[PINCFG_TYPE_FUNC];
361
362 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
363 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
364 if (shift >= 32) {
365 /* Some banks have two config registers */
366 shift -= 32;
367 reg += 4;
368 }
347 369
348 mask = (1 << bank->func_width) - 1; 370 spin_lock_irqsave(&bank->slock, flags);
349 shift = pin_offset * bank->func_width;
350 371
351 data = readl(reg); 372 data = readl(reg);
352 data &= ~(mask << shift); 373 data &= ~(mask << shift);
353 if (!input) 374 if (!input)
354 data |= FUNC_OUTPUT << shift; 375 data |= FUNC_OUTPUT << shift;
355 writel(data, reg); 376 writel(data, reg);
377
378 spin_unlock_irqrestore(&bank->slock, flags);
379
356 return 0; 380 return 0;
357} 381}
358 382
359/* list of pinmux callbacks for the pinmux vertical in pinctrl core */ 383/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
360static struct pinmux_ops samsung_pinmux_ops = { 384static const struct pinmux_ops samsung_pinmux_ops = {
361 .get_functions_count = samsung_get_functions_count, 385 .get_functions_count = samsung_get_functions_count,
362 .get_function_name = samsung_pinmux_get_fname, 386 .get_function_name = samsung_pinmux_get_fname,
363 .get_function_groups = samsung_pinmux_get_groups, 387 .get_function_groups = samsung_pinmux_get_groups,
@@ -371,40 +395,26 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
371 unsigned long *config, bool set) 395 unsigned long *config, bool set)
372{ 396{
373 struct samsung_pinctrl_drv_data *drvdata; 397 struct samsung_pinctrl_drv_data *drvdata;
398 struct samsung_pin_bank_type *type;
374 struct samsung_pin_bank *bank; 399 struct samsung_pin_bank *bank;
375 void __iomem *reg_base; 400 void __iomem *reg_base;
376 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config); 401 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
377 u32 data, width, pin_offset, mask, shift; 402 u32 data, width, pin_offset, mask, shift;
378 u32 cfg_value, cfg_reg; 403 u32 cfg_value, cfg_reg;
404 unsigned long flags;
379 405
380 drvdata = pinctrl_dev_get_drvdata(pctldev); 406 drvdata = pinctrl_dev_get_drvdata(pctldev);
381 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base, 407 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
382 &pin_offset, &bank); 408 &pin_offset, &bank);
409 type = bank->type;
383 410
384 switch (cfg_type) { 411 if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
385 case PINCFG_TYPE_PUD:
386 width = bank->pud_width;
387 cfg_reg = PUD_REG;
388 break;
389 case PINCFG_TYPE_DRV:
390 width = bank->drv_width;
391 cfg_reg = DRV_REG;
392 break;
393 case PINCFG_TYPE_CON_PDN:
394 width = bank->conpdn_width;
395 cfg_reg = CONPDN_REG;
396 break;
397 case PINCFG_TYPE_PUD_PDN:
398 width = bank->pudpdn_width;
399 cfg_reg = PUDPDN_REG;
400 break;
401 default:
402 WARN_ON(1);
403 return -EINVAL; 412 return -EINVAL;
404 }
405 413
406 if (!width) 414 width = type->fld_width[cfg_type];
407 return -EINVAL; 415 cfg_reg = type->reg_offset[cfg_type];
416
417 spin_lock_irqsave(&bank->slock, flags);
408 418
409 mask = (1 << width) - 1; 419 mask = (1 << width) - 1;
410 shift = pin_offset * width; 420 shift = pin_offset * width;
@@ -420,6 +430,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
420 data &= mask; 430 data &= mask;
421 *config = PINCFG_PACK(cfg_type, data); 431 *config = PINCFG_PACK(cfg_type, data);
422 } 432 }
433
434 spin_unlock_irqrestore(&bank->slock, flags);
435
423 return 0; 436 return 0;
424} 437}
425 438
@@ -468,7 +481,7 @@ static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
468} 481}
469 482
470/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */ 483/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
471static struct pinconf_ops samsung_pinconf_ops = { 484static const struct pinconf_ops samsung_pinconf_ops = {
472 .pin_config_get = samsung_pinconf_get, 485 .pin_config_get = samsung_pinconf_get,
473 .pin_config_set = samsung_pinconf_set, 486 .pin_config_set = samsung_pinconf_set,
474 .pin_config_group_get = samsung_pinconf_group_get, 487 .pin_config_group_get = samsung_pinconf_group_get,
@@ -479,16 +492,22 @@ static struct pinconf_ops samsung_pinconf_ops = {
479static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 492static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
480{ 493{
481 struct samsung_pin_bank *bank = gc_to_pin_bank(gc); 494 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
495 struct samsung_pin_bank_type *type = bank->type;
496 unsigned long flags;
482 void __iomem *reg; 497 void __iomem *reg;
483 u32 data; 498 u32 data;
484 499
485 reg = bank->drvdata->virt_base + bank->pctl_offset; 500 reg = bank->drvdata->virt_base + bank->pctl_offset;
486 501
487 data = readl(reg + DAT_REG); 502 spin_lock_irqsave(&bank->slock, flags);
503
504 data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
488 data &= ~(1 << offset); 505 data &= ~(1 << offset);
489 if (value) 506 if (value)
490 data |= 1 << offset; 507 data |= 1 << offset;
491 writel(data, reg + DAT_REG); 508 writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
509
510 spin_unlock_irqrestore(&bank->slock, flags);
492} 511}
493 512
494/* gpiolib gpio_get callback function */ 513/* gpiolib gpio_get callback function */
@@ -497,10 +516,11 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
497 void __iomem *reg; 516 void __iomem *reg;
498 u32 data; 517 u32 data;
499 struct samsung_pin_bank *bank = gc_to_pin_bank(gc); 518 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
519 struct samsung_pin_bank_type *type = bank->type;
500 520
501 reg = bank->drvdata->virt_base + bank->pctl_offset; 521 reg = bank->drvdata->virt_base + bank->pctl_offset;
502 522
503 data = readl(reg + DAT_REG); 523 data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
504 data >>= offset; 524 data >>= offset;
505 data &= 1; 525 data &= 1;
506 return data; 526 return data;
@@ -859,6 +879,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
859 879
860 bank = ctrl->pin_banks; 880 bank = ctrl->pin_banks;
861 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 881 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
882 spin_lock_init(&bank->slock);
862 bank->drvdata = d; 883 bank->drvdata = d;
863 bank->pin_base = ctrl->nr_pins; 884 bank->pin_base = ctrl->nr_pins;
864 ctrl->nr_pins += bank->nr_pins; 885 ctrl->nr_pins += bank->nr_pins;
@@ -944,12 +965,18 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
944} 965}
945 966
946static const struct of_device_id samsung_pinctrl_dt_match[] = { 967static const struct of_device_id samsung_pinctrl_dt_match[] = {
968#ifdef CONFIG_PINCTRL_EXYNOS
947 { .compatible = "samsung,exynos4210-pinctrl", 969 { .compatible = "samsung,exynos4210-pinctrl",
948 .data = (void *)exynos4210_pin_ctrl }, 970 .data = (void *)exynos4210_pin_ctrl },
949 { .compatible = "samsung,exynos4x12-pinctrl", 971 { .compatible = "samsung,exynos4x12-pinctrl",
950 .data = (void *)exynos4x12_pin_ctrl }, 972 .data = (void *)exynos4x12_pin_ctrl },
951 { .compatible = "samsung,exynos5250-pinctrl", 973 { .compatible = "samsung,exynos5250-pinctrl",
952 .data = (void *)exynos5250_pin_ctrl }, 974 .data = (void *)exynos5250_pin_ctrl },
975#endif
976#ifdef CONFIG_PINCTRL_S3C64XX
977 { .compatible = "samsung,s3c64xx-pinctrl",
978 .data = s3c64xx_pin_ctrl },
979#endif
953 {}, 980 {},
954}; 981};
955MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); 982MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);