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