| .. | .. |
|---|
| 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); |
|---|