.. | .. |
---|
13 | 13 | #include <linux/io.h> |
---|
14 | 14 | #include <linux/clk.h> |
---|
15 | 15 | #include <linux/gpio/driver.h> |
---|
| 16 | +#include <linux/interrupt.h> |
---|
16 | 17 | #include <linux/irqdomain.h> |
---|
17 | 18 | #include <linux/irqchip/chained_irq.h> |
---|
18 | 19 | #include <linux/export.h> |
---|
.. | .. |
---|
26 | 27 | #include <linux/pinctrl/pinctrl.h> |
---|
27 | 28 | #include <linux/pinctrl/pinconf-generic.h> |
---|
28 | 29 | #include <linux/pinctrl/pinmux.h> |
---|
| 30 | +#include <linux/regulator/consumer.h> |
---|
29 | 31 | #include <linux/platform_device.h> |
---|
30 | 32 | #include <linux/slab.h> |
---|
31 | 33 | |
---|
.. | .. |
---|
33 | 35 | |
---|
34 | 36 | #include "../core.h" |
---|
35 | 37 | #include "pinctrl-sunxi.h" |
---|
| 38 | + |
---|
| 39 | +/* |
---|
| 40 | + * These lock classes tell lockdep that GPIO IRQs are in a different |
---|
| 41 | + * category than their parents, so it won't report false recursion. |
---|
| 42 | + */ |
---|
| 43 | +static struct lock_class_key sunxi_pinctrl_irq_lock_class; |
---|
| 44 | +static struct lock_class_key sunxi_pinctrl_irq_request_class; |
---|
36 | 45 | |
---|
37 | 46 | static struct irq_chip sunxi_pinctrl_edge_irq_chip; |
---|
38 | 47 | static struct irq_chip sunxi_pinctrl_level_irq_chip; |
---|
.. | .. |
---|
332 | 341 | |
---|
333 | 342 | function = sunxi_pctrl_parse_function_prop(node); |
---|
334 | 343 | if (!function) { |
---|
335 | | - dev_err(pctl->dev, "missing function property in node %s\n", |
---|
336 | | - node->name); |
---|
| 344 | + dev_err(pctl->dev, "missing function property in node %pOFn\n", |
---|
| 345 | + node); |
---|
337 | 346 | return -EINVAL; |
---|
338 | 347 | } |
---|
339 | 348 | |
---|
340 | 349 | pin_prop = sunxi_pctrl_find_pins_prop(node, &npins); |
---|
341 | 350 | if (!pin_prop) { |
---|
342 | | - dev_err(pctl->dev, "missing pins property in node %s\n", |
---|
343 | | - node->name); |
---|
| 351 | + dev_err(pctl->dev, "missing pins property in node %pOFn\n", |
---|
| 352 | + node); |
---|
344 | 353 | return -EINVAL; |
---|
345 | 354 | } |
---|
346 | 355 | |
---|
.. | .. |
---|
529 | 538 | return sunxi_pconf_get(pctldev, g->pin, config); |
---|
530 | 539 | } |
---|
531 | 540 | |
---|
532 | | -static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, |
---|
533 | | - unsigned group, |
---|
534 | | - unsigned long *configs, |
---|
535 | | - unsigned num_configs) |
---|
| 541 | +static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin, |
---|
| 542 | + unsigned long *configs, unsigned num_configs) |
---|
536 | 543 | { |
---|
537 | 544 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
---|
538 | | - struct sunxi_pinctrl_group *g = &pctl->groups[group]; |
---|
539 | | - unsigned pin = g->pin - pctl->desc->pin_base; |
---|
540 | 545 | int i; |
---|
| 546 | + |
---|
| 547 | + pin -= pctl->desc->pin_base; |
---|
541 | 548 | |
---|
542 | 549 | for (i = 0; i < num_configs; i++) { |
---|
543 | 550 | enum pin_config_param param; |
---|
.. | .. |
---|
595 | 602 | return 0; |
---|
596 | 603 | } |
---|
597 | 604 | |
---|
| 605 | +static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, |
---|
| 606 | + unsigned long *configs, unsigned num_configs) |
---|
| 607 | +{ |
---|
| 608 | + struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
---|
| 609 | + struct sunxi_pinctrl_group *g = &pctl->groups[group]; |
---|
| 610 | + |
---|
| 611 | + /* We only support 1 pin per group. Chain it to the pin callback */ |
---|
| 612 | + return sunxi_pconf_set(pctldev, g->pin, configs, num_configs); |
---|
| 613 | +} |
---|
| 614 | + |
---|
598 | 615 | static const struct pinconf_ops sunxi_pconf_ops = { |
---|
599 | 616 | .is_generic = true, |
---|
600 | 617 | .pin_config_get = sunxi_pconf_get, |
---|
| 618 | + .pin_config_set = sunxi_pconf_set, |
---|
601 | 619 | .pin_config_group_get = sunxi_pconf_group_get, |
---|
602 | 620 | .pin_config_group_set = sunxi_pconf_group_set, |
---|
603 | 621 | }; |
---|
| 622 | + |
---|
| 623 | +static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl, |
---|
| 624 | + unsigned pin, |
---|
| 625 | + struct regulator *supply) |
---|
| 626 | +{ |
---|
| 627 | + unsigned short bank; |
---|
| 628 | + unsigned long flags; |
---|
| 629 | + u32 val, reg; |
---|
| 630 | + int uV; |
---|
| 631 | + |
---|
| 632 | + if (!pctl->desc->io_bias_cfg_variant) |
---|
| 633 | + return 0; |
---|
| 634 | + |
---|
| 635 | + uV = regulator_get_voltage(supply); |
---|
| 636 | + if (uV < 0) |
---|
| 637 | + return uV; |
---|
| 638 | + |
---|
| 639 | + /* Might be dummy regulator with no voltage set */ |
---|
| 640 | + if (uV == 0) |
---|
| 641 | + return 0; |
---|
| 642 | + |
---|
| 643 | + pin -= pctl->desc->pin_base; |
---|
| 644 | + bank = pin / PINS_PER_BANK; |
---|
| 645 | + |
---|
| 646 | + switch (pctl->desc->io_bias_cfg_variant) { |
---|
| 647 | + case BIAS_VOLTAGE_GRP_CONFIG: |
---|
| 648 | + /* |
---|
| 649 | + * Configured value must be equal or greater to actual |
---|
| 650 | + * voltage. |
---|
| 651 | + */ |
---|
| 652 | + if (uV <= 1800000) |
---|
| 653 | + val = 0x0; /* 1.8V */ |
---|
| 654 | + else if (uV <= 2500000) |
---|
| 655 | + val = 0x6; /* 2.5V */ |
---|
| 656 | + else if (uV <= 2800000) |
---|
| 657 | + val = 0x9; /* 2.8V */ |
---|
| 658 | + else if (uV <= 3000000) |
---|
| 659 | + val = 0xA; /* 3.0V */ |
---|
| 660 | + else |
---|
| 661 | + val = 0xD; /* 3.3V */ |
---|
| 662 | + |
---|
| 663 | + reg = readl(pctl->membase + sunxi_grp_config_reg(pin)); |
---|
| 664 | + reg &= ~IO_BIAS_MASK; |
---|
| 665 | + writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin)); |
---|
| 666 | + return 0; |
---|
| 667 | + case BIAS_VOLTAGE_PIO_POW_MODE_SEL: |
---|
| 668 | + val = uV <= 1800000 ? 1 : 0; |
---|
| 669 | + |
---|
| 670 | + raw_spin_lock_irqsave(&pctl->lock, flags); |
---|
| 671 | + reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG); |
---|
| 672 | + reg &= ~(1 << bank); |
---|
| 673 | + writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG); |
---|
| 674 | + raw_spin_unlock_irqrestore(&pctl->lock, flags); |
---|
| 675 | + return 0; |
---|
| 676 | + default: |
---|
| 677 | + return -EINVAL; |
---|
| 678 | + } |
---|
| 679 | +} |
---|
604 | 680 | |
---|
605 | 681 | static int sunxi_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) |
---|
606 | 682 | { |
---|
.. | .. |
---|
693 | 769 | return 0; |
---|
694 | 770 | } |
---|
695 | 771 | |
---|
| 772 | +static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset) |
---|
| 773 | +{ |
---|
| 774 | + struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
---|
| 775 | + unsigned short bank = offset / PINS_PER_BANK; |
---|
| 776 | + unsigned short bank_offset = bank - pctl->desc->pin_base / |
---|
| 777 | + PINS_PER_BANK; |
---|
| 778 | + struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset]; |
---|
| 779 | + struct regulator *reg = s_reg->regulator; |
---|
| 780 | + char supply[16]; |
---|
| 781 | + int ret; |
---|
| 782 | + |
---|
| 783 | + if (reg) { |
---|
| 784 | + refcount_inc(&s_reg->refcount); |
---|
| 785 | + return 0; |
---|
| 786 | + } |
---|
| 787 | + |
---|
| 788 | + snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank); |
---|
| 789 | + reg = regulator_get(pctl->dev, supply); |
---|
| 790 | + if (IS_ERR(reg)) { |
---|
| 791 | + dev_err(pctl->dev, "Couldn't get bank P%c regulator\n", |
---|
| 792 | + 'A' + bank); |
---|
| 793 | + return PTR_ERR(reg); |
---|
| 794 | + } |
---|
| 795 | + |
---|
| 796 | + ret = regulator_enable(reg); |
---|
| 797 | + if (ret) { |
---|
| 798 | + dev_err(pctl->dev, |
---|
| 799 | + "Couldn't enable bank P%c regulator\n", 'A' + bank); |
---|
| 800 | + goto out; |
---|
| 801 | + } |
---|
| 802 | + |
---|
| 803 | + sunxi_pinctrl_set_io_bias_cfg(pctl, offset, reg); |
---|
| 804 | + |
---|
| 805 | + s_reg->regulator = reg; |
---|
| 806 | + refcount_set(&s_reg->refcount, 1); |
---|
| 807 | + |
---|
| 808 | + return 0; |
---|
| 809 | + |
---|
| 810 | +out: |
---|
| 811 | + regulator_put(s_reg->regulator); |
---|
| 812 | + |
---|
| 813 | + return ret; |
---|
| 814 | +} |
---|
| 815 | + |
---|
| 816 | +static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset) |
---|
| 817 | +{ |
---|
| 818 | + struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
---|
| 819 | + unsigned short bank = offset / PINS_PER_BANK; |
---|
| 820 | + unsigned short bank_offset = bank - pctl->desc->pin_base / |
---|
| 821 | + PINS_PER_BANK; |
---|
| 822 | + struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset]; |
---|
| 823 | + |
---|
| 824 | + if (!refcount_dec_and_test(&s_reg->refcount)) |
---|
| 825 | + return 0; |
---|
| 826 | + |
---|
| 827 | + regulator_disable(s_reg->regulator); |
---|
| 828 | + regulator_put(s_reg->regulator); |
---|
| 829 | + s_reg->regulator = NULL; |
---|
| 830 | + |
---|
| 831 | + return 0; |
---|
| 832 | +} |
---|
| 833 | + |
---|
696 | 834 | static const struct pinmux_ops sunxi_pmx_ops = { |
---|
697 | 835 | .get_functions_count = sunxi_pmx_get_funcs_cnt, |
---|
698 | 836 | .get_function_name = sunxi_pmx_get_func_name, |
---|
699 | 837 | .get_function_groups = sunxi_pmx_get_func_groups, |
---|
700 | 838 | .set_mux = sunxi_pmx_set_mux, |
---|
701 | 839 | .gpio_set_direction = sunxi_pmx_gpio_set_direction, |
---|
| 840 | + .request = sunxi_pmx_request, |
---|
| 841 | + .free = sunxi_pmx_free, |
---|
702 | 842 | .strict = true, |
---|
703 | 843 | }; |
---|
704 | 844 | |
---|
.. | .. |
---|
929 | 1069 | sunxi_pinctrl_irq_unmask(d); |
---|
930 | 1070 | } |
---|
931 | 1071 | |
---|
| 1072 | +static int sunxi_pinctrl_irq_set_wake(struct irq_data *d, unsigned int on) |
---|
| 1073 | +{ |
---|
| 1074 | + struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); |
---|
| 1075 | + u8 bank = d->hwirq / IRQ_PER_BANK; |
---|
| 1076 | + |
---|
| 1077 | + return irq_set_irq_wake(pctl->irq[bank], on); |
---|
| 1078 | +} |
---|
| 1079 | + |
---|
932 | 1080 | static struct irq_chip sunxi_pinctrl_edge_irq_chip = { |
---|
933 | 1081 | .name = "sunxi_pio_edge", |
---|
934 | 1082 | .irq_ack = sunxi_pinctrl_irq_ack, |
---|
.. | .. |
---|
937 | 1085 | .irq_request_resources = sunxi_pinctrl_irq_request_resources, |
---|
938 | 1086 | .irq_release_resources = sunxi_pinctrl_irq_release_resources, |
---|
939 | 1087 | .irq_set_type = sunxi_pinctrl_irq_set_type, |
---|
940 | | - .flags = IRQCHIP_SKIP_SET_WAKE, |
---|
| 1088 | + .irq_set_wake = sunxi_pinctrl_irq_set_wake, |
---|
| 1089 | + .flags = IRQCHIP_MASK_ON_SUSPEND, |
---|
941 | 1090 | }; |
---|
942 | 1091 | |
---|
943 | 1092 | static struct irq_chip sunxi_pinctrl_level_irq_chip = { |
---|
.. | .. |
---|
952 | 1101 | .irq_request_resources = sunxi_pinctrl_irq_request_resources, |
---|
953 | 1102 | .irq_release_resources = sunxi_pinctrl_irq_release_resources, |
---|
954 | 1103 | .irq_set_type = sunxi_pinctrl_irq_set_type, |
---|
955 | | - .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED | |
---|
| 1104 | + .irq_set_wake = sunxi_pinctrl_irq_set_wake, |
---|
| 1105 | + .flags = IRQCHIP_EOI_THREADED | |
---|
| 1106 | + IRQCHIP_MASK_ON_SUSPEND | |
---|
956 | 1107 | IRQCHIP_EOI_IF_HANDLED, |
---|
957 | 1108 | }; |
---|
958 | 1109 | |
---|
.. | .. |
---|
1258 | 1409 | struct pinctrl_pin_desc *pins; |
---|
1259 | 1410 | struct sunxi_pinctrl *pctl; |
---|
1260 | 1411 | struct pinmux_ops *pmxops; |
---|
1261 | | - struct resource *res; |
---|
1262 | 1412 | int i, ret, last_pin, pin_idx; |
---|
1263 | 1413 | struct clk *clk; |
---|
1264 | 1414 | |
---|
.. | .. |
---|
1269 | 1419 | |
---|
1270 | 1420 | raw_spin_lock_init(&pctl->lock); |
---|
1271 | 1421 | |
---|
1272 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1273 | | - pctl->membase = devm_ioremap_resource(&pdev->dev, res); |
---|
| 1422 | + pctl->membase = devm_platform_ioremap_resource(pdev, 0); |
---|
1274 | 1423 | if (IS_ERR(pctl->membase)) |
---|
1275 | 1424 | return PTR_ERR(pctl->membase); |
---|
1276 | 1425 | |
---|
.. | .. |
---|
1341 | 1490 | |
---|
1342 | 1491 | last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number; |
---|
1343 | 1492 | pctl->chip->owner = THIS_MODULE; |
---|
1344 | | - pctl->chip->request = gpiochip_generic_request, |
---|
1345 | | - pctl->chip->free = gpiochip_generic_free, |
---|
1346 | | - pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input, |
---|
1347 | | - pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output, |
---|
1348 | | - pctl->chip->get = sunxi_pinctrl_gpio_get, |
---|
1349 | | - pctl->chip->set = sunxi_pinctrl_gpio_set, |
---|
1350 | | - pctl->chip->of_xlate = sunxi_pinctrl_gpio_of_xlate, |
---|
1351 | | - pctl->chip->to_irq = sunxi_pinctrl_gpio_to_irq, |
---|
1352 | | - pctl->chip->of_gpio_n_cells = 3, |
---|
1353 | | - pctl->chip->can_sleep = false, |
---|
| 1493 | + pctl->chip->request = gpiochip_generic_request; |
---|
| 1494 | + pctl->chip->free = gpiochip_generic_free; |
---|
| 1495 | + pctl->chip->set_config = gpiochip_generic_config; |
---|
| 1496 | + pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input; |
---|
| 1497 | + pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output; |
---|
| 1498 | + pctl->chip->get = sunxi_pinctrl_gpio_get; |
---|
| 1499 | + pctl->chip->set = sunxi_pinctrl_gpio_set; |
---|
| 1500 | + pctl->chip->of_xlate = sunxi_pinctrl_gpio_of_xlate; |
---|
| 1501 | + pctl->chip->to_irq = sunxi_pinctrl_gpio_to_irq; |
---|
| 1502 | + pctl->chip->of_gpio_n_cells = 3; |
---|
| 1503 | + pctl->chip->can_sleep = false; |
---|
1354 | 1504 | pctl->chip->ngpio = round_up(last_pin, PINS_PER_BANK) - |
---|
1355 | 1505 | pctl->desc->pin_base; |
---|
1356 | 1506 | pctl->chip->label = dev_name(&pdev->dev); |
---|
.. | .. |
---|
1412 | 1562 | for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) { |
---|
1413 | 1563 | int irqno = irq_create_mapping(pctl->domain, i); |
---|
1414 | 1564 | |
---|
| 1565 | + irq_set_lockdep_class(irqno, &sunxi_pinctrl_irq_lock_class, |
---|
| 1566 | + &sunxi_pinctrl_irq_request_class); |
---|
1415 | 1567 | irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip, |
---|
1416 | 1568 | handle_edge_irq); |
---|
1417 | 1569 | irq_set_chip_data(irqno, pctl); |
---|