Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl/nomadik: implement pin configuration

This implements the pin configuration interface for the
Nomadik pin controller.

As part of the exercise we add a bit in the pin_cfg_t for
the Nomadik pinctrl driver that indicates if the pin should
be forced into GPIO mode. This is not done to go behind the
back of the GPIO subsystem, but to ensure that default modes
can be set by hogs on boot and system suspend/resume states.
It was used implicitly by the old code defining all config
settings and modes in a single config word but we now have
a split between pinmux and pinconf leading to the need to
have this.

We also add a bit for explicitly setting sleepmode of the
pin. This was previously handled by custom calls with the
_sleep() suffix, but we now have one single interface into
the configuration so we replace this with a bit indicating
that the pin shall be configured into sleep mode.

Some of the configuration can be refactored later to use
less custom fields on the pin_cfg_t but we are currently
leaving the old function calls in place so we stay
compatible.

ChangeLog v1->v2:
- Drop a hunk changing pinmuxing for GPIO and move it
over to the preceding pinmux patch.

Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

+127
+13
arch/arm/plat-nomadik/include/plat/pincfg.h
··· 124 124 #define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) 125 125 #define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) 126 126 127 + #define PIN_GPIOMODE_SHIFT 26 128 + #define PIN_GPIOMODE_MASK (0x1 << PIN_GPIOMODE_SHIFT) 129 + #define PIN_GPIOMODE(x) (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT) 130 + #define PIN_GPIOMODE_DISABLED (0 << PIN_GPIOMODE_SHIFT) 131 + #define PIN_GPIOMODE_ENABLED (1 << PIN_GPIOMODE_SHIFT) 132 + 133 + #define PIN_SLEEPMODE_SHIFT 27 134 + #define PIN_SLEEPMODE_MASK (0x1 << PIN_SLEEPMODE_SHIFT) 135 + #define PIN_SLEEPMODE(x) (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT) 136 + #define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT) 137 + #define PIN_SLEEPMODE_ENABLED (1 << PIN_SLEEPMODE_SHIFT) 138 + 139 + 127 140 /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ 128 141 #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) 129 142 #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP)
+1
drivers/pinctrl/Kconfig
··· 40 40 bool "Nomadik pin controller driver" 41 41 depends on ARCH_U8500 42 42 select PINMUX 43 + select PINCONF 43 44 44 45 config PINCTRL_DB8500 45 46 bool "DB8500 pin controller driver"
+113
drivers/pinctrl/pinctrl-nomadik.c
··· 26 26 #include <linux/slab.h> 27 27 #include <linux/pinctrl/pinctrl.h> 28 28 #include <linux/pinctrl/pinmux.h> 29 + #include <linux/pinctrl/pinconf.h> 29 30 /* Since we request GPIOs from ourself */ 30 31 #include <linux/pinctrl/consumer.h> 31 32 ··· 1569 1568 .gpio_disable_free = nmk_gpio_disable_free, 1570 1569 }; 1571 1570 1571 + int nmk_pin_config_get(struct pinctrl_dev *pctldev, 1572 + unsigned pin, 1573 + unsigned long *config) 1574 + { 1575 + /* Not implemented */ 1576 + return -EINVAL; 1577 + } 1578 + 1579 + int nmk_pin_config_set(struct pinctrl_dev *pctldev, 1580 + unsigned pin, 1581 + unsigned long config) 1582 + { 1583 + static const char *pullnames[] = { 1584 + [NMK_GPIO_PULL_NONE] = "none", 1585 + [NMK_GPIO_PULL_UP] = "up", 1586 + [NMK_GPIO_PULL_DOWN] = "down", 1587 + [3] /* illegal */ = "??" 1588 + }; 1589 + static const char *slpmnames[] = { 1590 + [NMK_GPIO_SLPM_INPUT] = "input/wakeup", 1591 + [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", 1592 + }; 1593 + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); 1594 + struct nmk_gpio_chip *nmk_chip; 1595 + struct pinctrl_gpio_range *range; 1596 + struct gpio_chip *chip; 1597 + unsigned bit; 1598 + 1599 + /* 1600 + * The pin config contains pin number and altfunction fields, here 1601 + * we just ignore that part. It's being handled by the framework and 1602 + * pinmux callback respectively. 1603 + */ 1604 + pin_cfg_t cfg = (pin_cfg_t) config; 1605 + int pull = PIN_PULL(cfg); 1606 + int slpm = PIN_SLPM(cfg); 1607 + int output = PIN_DIR(cfg); 1608 + int val = PIN_VAL(cfg); 1609 + bool lowemi = PIN_LOWEMI(cfg); 1610 + bool gpiomode = PIN_GPIOMODE(cfg); 1611 + bool sleep = PIN_SLEEPMODE(cfg); 1612 + 1613 + range = nmk_match_gpio_range(pctldev, pin); 1614 + if (!range) { 1615 + dev_err(npct->dev, "invalid pin offset %d\n", pin); 1616 + return -EINVAL; 1617 + } 1618 + if (!range->gc) { 1619 + dev_err(npct->dev, "GPIO chip missing in range for pin %d\n", 1620 + pin); 1621 + return -EINVAL; 1622 + } 1623 + chip = range->gc; 1624 + nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); 1625 + 1626 + if (sleep) { 1627 + int slpm_pull = PIN_SLPM_PULL(cfg); 1628 + int slpm_output = PIN_SLPM_DIR(cfg); 1629 + int slpm_val = PIN_SLPM_VAL(cfg); 1630 + 1631 + /* All pins go into GPIO mode at sleep */ 1632 + gpiomode = true; 1633 + 1634 + /* 1635 + * The SLPM_* values are normal values + 1 to allow zero to 1636 + * mean "same as normal". 1637 + */ 1638 + if (slpm_pull) 1639 + pull = slpm_pull - 1; 1640 + if (slpm_output) 1641 + output = slpm_output - 1; 1642 + if (slpm_val) 1643 + val = slpm_val - 1; 1644 + 1645 + dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", 1646 + pin, 1647 + slpm_pull ? pullnames[pull] : "same", 1648 + slpm_output ? (output ? "output" : "input") : "same", 1649 + slpm_val ? (val ? "high" : "low") : "same"); 1650 + } 1651 + 1652 + dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n", 1653 + pin, cfg, pullnames[pull], slpmnames[slpm], 1654 + output ? "output " : "input", 1655 + output ? (val ? "high" : "low") : "", 1656 + lowemi ? "on" : "off" ); 1657 + 1658 + clk_enable(nmk_chip->clk); 1659 + bit = pin % NMK_GPIO_PER_CHIP; 1660 + if (gpiomode) 1661 + /* No glitch when going to GPIO mode */ 1662 + __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO); 1663 + if (output) 1664 + __nmk_gpio_make_output(nmk_chip, bit, val); 1665 + else { 1666 + __nmk_gpio_make_input(nmk_chip, bit); 1667 + __nmk_gpio_set_pull(nmk_chip, bit, pull); 1668 + } 1669 + /* TODO: isn't this only applicable on output pins? */ 1670 + __nmk_gpio_set_lowemi(nmk_chip, bit, lowemi); 1671 + 1672 + __nmk_gpio_set_slpm(nmk_chip, bit, slpm); 1673 + clk_disable(nmk_chip->clk); 1674 + return 0; 1675 + } 1676 + 1677 + static struct pinconf_ops nmk_pinconf_ops = { 1678 + .pin_config_get = nmk_pin_config_get, 1679 + .pin_config_set = nmk_pin_config_set, 1680 + }; 1681 + 1572 1682 static struct pinctrl_desc nmk_pinctrl_desc = { 1573 1683 .name = "pinctrl-nomadik", 1574 1684 .pctlops = &nmk_pinctrl_ops, 1575 1685 .pmxops = &nmk_pinmux_ops, 1686 + .confops = &nmk_pinconf_ops, 1576 1687 .owner = THIS_MODULE, 1577 1688 }; 1578 1689