diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2013-08-29 03:46:30 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-08-29 03:46:30 -0400 |
commit | 6ad30ce046aefbdc3848232c665a728860d7bb68 (patch) | |
tree | 34af8fc78b28281fcfe531a26401b440c078038e /drivers/pinctrl/pinctrl-sunxi.c | |
parent | 0351c287952483dafa904f84496631198465fbf4 (diff) | |
parent | d8dfad3876e4386666b759da3c833d62fb8b2267 (diff) |
Merge tag 'v3.11-rc7' into devel
Merged in this to avoid conflicts with the big locking fixes
from upstream.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Conflicts:
drivers/pinctrl/pinctrl-sunxi.c
Diffstat (limited to 'drivers/pinctrl/pinctrl-sunxi.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-sunxi.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c index 8dbd465b01d3..532202bbfc33 100644 --- a/drivers/pinctrl/pinctrl-sunxi.c +++ b/drivers/pinctrl/pinctrl-sunxi.c | |||
@@ -279,11 +279,14 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, | |||
279 | { | 279 | { |
280 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | 280 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
281 | struct sunxi_pinctrl_group *g = &pctl->groups[group]; | 281 | struct sunxi_pinctrl_group *g = &pctl->groups[group]; |
282 | unsigned long flags; | ||
282 | u32 val, mask; | 283 | u32 val, mask; |
283 | u16 strength; | 284 | u16 strength; |
284 | u8 dlevel; | 285 | u8 dlevel; |
285 | int i; | 286 | int i; |
286 | 287 | ||
288 | spin_lock_irqsave(&pctl->lock, flags); | ||
289 | |||
287 | for (i = 0; i < num_configs; i++) { | 290 | for (i = 0; i < num_configs; i++) { |
288 | switch (pinconf_to_config_param(configs[i])) { | 291 | switch (pinconf_to_config_param(configs[i])) { |
289 | case PIN_CONFIG_DRIVE_STRENGTH: | 292 | case PIN_CONFIG_DRIVE_STRENGTH: |
@@ -319,11 +322,12 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, | |||
319 | default: | 322 | default: |
320 | break; | 323 | break; |
321 | } | 324 | } |
322 | |||
323 | /* cache the config value */ | 325 | /* cache the config value */ |
324 | g->config = configs[i]; | 326 | g->config = configs[i]; |
325 | } /* for each config */ | 327 | } /* for each config */ |
326 | 328 | ||
329 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
330 | |||
327 | return 0; | 331 | return 0; |
328 | } | 332 | } |
329 | 333 | ||
@@ -365,11 +369,17 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev, | |||
365 | u8 config) | 369 | u8 config) |
366 | { | 370 | { |
367 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | 371 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
372 | unsigned long flags; | ||
373 | u32 val, mask; | ||
374 | |||
375 | spin_lock_irqsave(&pctl->lock, flags); | ||
368 | 376 | ||
369 | u32 val = readl(pctl->membase + sunxi_mux_reg(pin)); | 377 | val = readl(pctl->membase + sunxi_mux_reg(pin)); |
370 | u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin); | 378 | mask = MUX_PINS_MASK << sunxi_mux_offset(pin); |
371 | writel((val & ~mask) | config << sunxi_mux_offset(pin), | 379 | writel((val & ~mask) | config << sunxi_mux_offset(pin), |
372 | pctl->membase + sunxi_mux_reg(pin)); | 380 | pctl->membase + sunxi_mux_reg(pin)); |
381 | |||
382 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
373 | } | 383 | } |
374 | 384 | ||
375 | static int sunxi_pmx_enable(struct pinctrl_dev *pctldev, | 385 | static int sunxi_pmx_enable(struct pinctrl_dev *pctldev, |
@@ -469,8 +479,21 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip, | |||
469 | struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev); | 479 | struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev); |
470 | u32 reg = sunxi_data_reg(offset); | 480 | u32 reg = sunxi_data_reg(offset); |
471 | u8 index = sunxi_data_offset(offset); | 481 | u8 index = sunxi_data_offset(offset); |
482 | unsigned long flags; | ||
483 | u32 regval; | ||
484 | |||
485 | spin_lock_irqsave(&pctl->lock, flags); | ||
486 | |||
487 | regval = readl(pctl->membase + reg); | ||
488 | |||
489 | if (value) | ||
490 | regval |= BIT(index); | ||
491 | else | ||
492 | regval &= ~(BIT(index)); | ||
472 | 493 | ||
473 | writel((value & DATA_PINS_MASK) << index, pctl->membase + reg); | 494 | writel(regval, pctl->membase + reg); |
495 | |||
496 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
474 | } | 497 | } |
475 | 498 | ||
476 | static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc, | 499 | static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc, |
@@ -531,6 +554,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, | |||
531 | struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); | 554 | struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); |
532 | u32 reg = sunxi_irq_cfg_reg(d->hwirq); | 555 | u32 reg = sunxi_irq_cfg_reg(d->hwirq); |
533 | u8 index = sunxi_irq_cfg_offset(d->hwirq); | 556 | u8 index = sunxi_irq_cfg_offset(d->hwirq); |
557 | unsigned long flags; | ||
558 | u32 regval; | ||
534 | u8 mode; | 559 | u8 mode; |
535 | 560 | ||
536 | switch (type) { | 561 | switch (type) { |
@@ -553,7 +578,13 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, | |||
553 | return -EINVAL; | 578 | return -EINVAL; |
554 | } | 579 | } |
555 | 580 | ||
556 | writel((mode & IRQ_CFG_IRQ_MASK) << index, pctl->membase + reg); | 581 | spin_lock_irqsave(&pctl->lock, flags); |
582 | |||
583 | regval = readl(pctl->membase + reg); | ||
584 | regval &= ~IRQ_CFG_IRQ_MASK; | ||
585 | writel(regval | (mode << index), pctl->membase + reg); | ||
586 | |||
587 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
557 | 588 | ||
558 | return 0; | 589 | return 0; |
559 | } | 590 | } |
@@ -565,14 +596,19 @@ static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d) | |||
565 | u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq); | 596 | u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq); |
566 | u32 status_reg = sunxi_irq_status_reg(d->hwirq); | 597 | u32 status_reg = sunxi_irq_status_reg(d->hwirq); |
567 | u8 status_idx = sunxi_irq_status_offset(d->hwirq); | 598 | u8 status_idx = sunxi_irq_status_offset(d->hwirq); |
599 | unsigned long flags; | ||
568 | u32 val; | 600 | u32 val; |
569 | 601 | ||
602 | spin_lock_irqsave(&pctl->lock, flags); | ||
603 | |||
570 | /* Mask the IRQ */ | 604 | /* Mask the IRQ */ |
571 | val = readl(pctl->membase + ctrl_reg); | 605 | val = readl(pctl->membase + ctrl_reg); |
572 | writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg); | 606 | writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg); |
573 | 607 | ||
574 | /* Clear the IRQ */ | 608 | /* Clear the IRQ */ |
575 | writel(1 << status_idx, pctl->membase + status_reg); | 609 | writel(1 << status_idx, pctl->membase + status_reg); |
610 | |||
611 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
576 | } | 612 | } |
577 | 613 | ||
578 | static void sunxi_pinctrl_irq_mask(struct irq_data *d) | 614 | static void sunxi_pinctrl_irq_mask(struct irq_data *d) |
@@ -580,11 +616,16 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d) | |||
580 | struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); | 616 | struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); |
581 | u32 reg = sunxi_irq_ctrl_reg(d->hwirq); | 617 | u32 reg = sunxi_irq_ctrl_reg(d->hwirq); |
582 | u8 idx = sunxi_irq_ctrl_offset(d->hwirq); | 618 | u8 idx = sunxi_irq_ctrl_offset(d->hwirq); |
619 | unsigned long flags; | ||
583 | u32 val; | 620 | u32 val; |
584 | 621 | ||
622 | spin_lock_irqsave(&pctl->lock, flags); | ||
623 | |||
585 | /* Mask the IRQ */ | 624 | /* Mask the IRQ */ |
586 | val = readl(pctl->membase + reg); | 625 | val = readl(pctl->membase + reg); |
587 | writel(val & ~(1 << idx), pctl->membase + reg); | 626 | writel(val & ~(1 << idx), pctl->membase + reg); |
627 | |||
628 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
588 | } | 629 | } |
589 | 630 | ||
590 | static void sunxi_pinctrl_irq_unmask(struct irq_data *d) | 631 | static void sunxi_pinctrl_irq_unmask(struct irq_data *d) |
@@ -593,6 +634,7 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d) | |||
593 | struct sunxi_desc_function *func; | 634 | struct sunxi_desc_function *func; |
594 | u32 reg = sunxi_irq_ctrl_reg(d->hwirq); | 635 | u32 reg = sunxi_irq_ctrl_reg(d->hwirq); |
595 | u8 idx = sunxi_irq_ctrl_offset(d->hwirq); | 636 | u8 idx = sunxi_irq_ctrl_offset(d->hwirq); |
637 | unsigned long flags; | ||
596 | u32 val; | 638 | u32 val; |
597 | 639 | ||
598 | func = sunxi_pinctrl_desc_find_function_by_pin(pctl, | 640 | func = sunxi_pinctrl_desc_find_function_by_pin(pctl, |
@@ -602,9 +644,13 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d) | |||
602 | /* Change muxing to INT mode */ | 644 | /* Change muxing to INT mode */ |
603 | sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval); | 645 | sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval); |
604 | 646 | ||
647 | spin_lock_irqsave(&pctl->lock, flags); | ||
648 | |||
605 | /* Unmask the IRQ */ | 649 | /* Unmask the IRQ */ |
606 | val = readl(pctl->membase + reg); | 650 | val = readl(pctl->membase + reg); |
607 | writel(val | (1 << idx), pctl->membase + reg); | 651 | writel(val | (1 << idx), pctl->membase + reg); |
652 | |||
653 | spin_unlock_irqrestore(&pctl->lock, flags); | ||
608 | } | 654 | } |
609 | 655 | ||
610 | static struct irq_chip sunxi_pinctrl_irq_chip = { | 656 | static struct irq_chip sunxi_pinctrl_irq_chip = { |
@@ -759,6 +805,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev) | |||
759 | return -ENOMEM; | 805 | return -ENOMEM; |
760 | platform_set_drvdata(pdev, pctl); | 806 | platform_set_drvdata(pdev, pctl); |
761 | 807 | ||
808 | spin_lock_init(&pctl->lock); | ||
809 | |||
762 | pctl->membase = of_iomap(node, 0); | 810 | pctl->membase = of_iomap(node, 0); |
763 | if (!pctl->membase) | 811 | if (!pctl->membase) |
764 | return -ENOMEM; | 812 | return -ENOMEM; |