aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-nomadik.c
diff options
context:
space:
mode:
authorGabriel Fernandez <gabriel.fernandez@stericsson.com>2012-12-17 09:53:24 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-01-11 15:49:21 -0500
commite32af889458837d11a1ec5ec98934a1e711b049d (patch)
tree764ca31b5ca3fc5ed6443f3077c4890d499e9f66 /drivers/pinctrl/pinctrl-nomadik.c
parent50f690d85e4e26ca31082e9943d36b618e7566fe (diff)
pinctrl/nomadik: add device tree support
This implements pin multiplexing and pin configuration for the Nomadik pin controller using the device tree. Signed-off-by: Gabriel Fernandez <gabriel.fernandez@stericsson.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Philippe Langlais <philippe.langlais@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-nomadik.c')
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c277
1 files changed, 276 insertions, 1 deletions
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index f404e644a16e..ec3a5742e413 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -25,6 +25,7 @@
25#include <linux/irqdomain.h> 25#include <linux/irqdomain.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/of_device.h> 27#include <linux/of_device.h>
28#include <linux/pinctrl/machine.h>
28#include <linux/pinctrl/pinctrl.h> 29#include <linux/pinctrl/pinctrl.h>
29#include <linux/pinctrl/pinmux.h> 30#include <linux/pinctrl/pinmux.h>
30#include <linux/pinctrl/pinconf.h> 31#include <linux/pinctrl/pinconf.h>
@@ -1490,11 +1491,285 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
1490 nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); 1491 nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
1491} 1492}
1492 1493
1494static void nmk_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
1495 struct pinctrl_map *map, unsigned num_maps)
1496{
1497 int i;
1498
1499 for (i = 0; i < num_maps; i++)
1500 if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
1501 kfree(map[i].data.configs.configs);
1502 kfree(map);
1503}
1504
1505static int nmk_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
1506 unsigned *num_maps, unsigned reserve)
1507{
1508 unsigned old_num = *reserved_maps;
1509 unsigned new_num = *num_maps + reserve;
1510 struct pinctrl_map *new_map;
1511
1512 if (old_num >= new_num)
1513 return 0;
1514
1515 new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
1516 if (!new_map)
1517 return -ENOMEM;
1518
1519 memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
1520
1521 *map = new_map;
1522 *reserved_maps = new_num;
1523
1524 return 0;
1525}
1526
1527static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
1528 unsigned *num_maps, const char *group,
1529 const char *function)
1530{
1531 if (*num_maps == *reserved_maps)
1532 return -ENOSPC;
1533
1534 (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
1535 (*map)[*num_maps].data.mux.group = group;
1536 (*map)[*num_maps].data.mux.function = function;
1537 (*num_maps)++;
1538
1539 return 0;
1540}
1541
1542static int nmk_dt_add_map_configs(struct pinctrl_map **map,
1543 unsigned *reserved_maps,
1544 unsigned *num_maps, const char *group,
1545 unsigned long *configs, unsigned num_configs)
1546{
1547 unsigned long *dup_configs;
1548
1549 if (*num_maps == *reserved_maps)
1550 return -ENOSPC;
1551
1552 dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
1553 GFP_KERNEL);
1554 if (!dup_configs)
1555 return -ENOMEM;
1556
1557 (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
1558
1559 (*map)[*num_maps].data.configs.group_or_pin = group;
1560 (*map)[*num_maps].data.configs.configs = dup_configs;
1561 (*map)[*num_maps].data.configs.num_configs = num_configs;
1562 (*num_maps)++;
1563
1564 return 0;
1565}
1566
1567#define NMK_CONFIG_PIN(x,y) { .property = x, .config = y, }
1568#define NMK_CONFIG_PIN_ARRAY(x,y) { .property = x, .choice = y, \
1569 .size = ARRAY_SIZE(y), }
1570
1571static const unsigned long nmk_pin_input_modes[] = {
1572 PIN_INPUT_NOPULL,
1573 PIN_INPUT_PULLUP,
1574 PIN_INPUT_PULLDOWN,
1575};
1576
1577static const unsigned long nmk_pin_output_modes[] = {
1578 PIN_OUTPUT_LOW,
1579 PIN_OUTPUT_HIGH,
1580 PIN_DIR_OUTPUT,
1581};
1582
1583static const unsigned long nmk_pin_sleep_modes[] = {
1584 PIN_SLEEPMODE_DISABLED,
1585 PIN_SLEEPMODE_ENABLED,
1586};
1587
1588static const unsigned long nmk_pin_sleep_input_modes[] = {
1589 PIN_SLPM_INPUT_NOPULL,
1590 PIN_SLPM_INPUT_PULLUP,
1591 PIN_SLPM_INPUT_PULLDOWN,
1592 PIN_SLPM_DIR_INPUT,
1593};
1594
1595static const unsigned long nmk_pin_sleep_output_modes[] = {
1596 PIN_SLPM_OUTPUT_LOW,
1597 PIN_SLPM_OUTPUT_HIGH,
1598 PIN_SLPM_DIR_OUTPUT,
1599};
1600
1601static const unsigned long nmk_pin_sleep_wakeup_modes[] = {
1602 PIN_SLPM_WAKEUP_DISABLE,
1603 PIN_SLPM_WAKEUP_ENABLE,
1604};
1605
1606static const unsigned long nmk_pin_gpio_modes[] = {
1607 PIN_GPIOMODE_DISABLED,
1608 PIN_GPIOMODE_ENABLED,
1609};
1610
1611static const unsigned long nmk_pin_sleep_pdis_modes[] = {
1612 PIN_SLPM_PDIS_DISABLED,
1613 PIN_SLPM_PDIS_ENABLED,
1614};
1615
1616struct nmk_cfg_param {
1617 const char *property;
1618 unsigned long config;
1619 const unsigned long *choice;
1620 int size;
1621};
1622
1623static const struct nmk_cfg_param nmk_cfg_params[] = {
1624 NMK_CONFIG_PIN_ARRAY("ste,input", nmk_pin_input_modes),
1625 NMK_CONFIG_PIN_ARRAY("ste,output", nmk_pin_output_modes),
1626 NMK_CONFIG_PIN_ARRAY("ste,sleep", nmk_pin_sleep_modes),
1627 NMK_CONFIG_PIN_ARRAY("ste,sleep-input", nmk_pin_sleep_input_modes),
1628 NMK_CONFIG_PIN_ARRAY("ste,sleep-output", nmk_pin_sleep_output_modes),
1629 NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup", nmk_pin_sleep_wakeup_modes),
1630 NMK_CONFIG_PIN_ARRAY("ste,gpio", nmk_pin_gpio_modes),
1631 NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable", nmk_pin_sleep_pdis_modes),
1632};
1633
1634static int nmk_dt_pin_config(int index, int val, unsigned long *config)
1635{
1636 int ret = 0;
1637
1638 if (nmk_cfg_params[index].choice == NULL)
1639 *config = nmk_cfg_params[index].config;
1640 else {
1641 /* test if out of range */
1642 if (val < nmk_cfg_params[index].size) {
1643 *config = nmk_cfg_params[index].config |
1644 nmk_cfg_params[index].choice[val];
1645 }
1646 }
1647 return ret;
1648}
1649
1650static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name)
1651{
1652 int i, pin_number;
1653 struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
1654
1655 if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
1656 for (i = 0; i < npct->soc->npins; i++)
1657 if (npct->soc->pins[i].number == pin_number)
1658 return npct->soc->pins[i].name;
1659 return NULL;
1660}
1661
1662static bool nmk_pinctrl_dt_get_config(struct device_node *np,
1663 unsigned long *configs)
1664{
1665 bool has_config = 0;
1666 unsigned long cfg = 0;
1667 int i, val, ret;
1668
1669 for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) {
1670 ret = of_property_read_u32(np,
1671 nmk_cfg_params[i].property, &val);
1672 if (ret != -EINVAL) {
1673 if (nmk_dt_pin_config(i, val, &cfg) == 0) {
1674 *configs |= cfg;
1675 has_config = 1;
1676 }
1677 }
1678 }
1679
1680 return has_config;
1681}
1682
1683int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
1684 struct device_node *np,
1685 struct pinctrl_map **map,
1686 unsigned *reserved_maps,
1687 unsigned *num_maps)
1688{
1689 int ret;
1690 const char *function = NULL;
1691 unsigned long configs = 0;
1692 bool has_config = 0;
1693 unsigned reserve = 0;
1694 struct property *prop;
1695 const char *group, *gpio_name;
1696 struct device_node *np_config;
1697
1698 ret = of_property_read_string(np, "ste,function", &function);
1699 if (ret >= 0)
1700 reserve = 1;
1701
1702 has_config = nmk_pinctrl_dt_get_config(np, &configs);
1703
1704 np_config = of_parse_phandle(np, "ste,config", 0);
1705 if (np_config)
1706 has_config |= nmk_pinctrl_dt_get_config(np_config, &configs);
1707
1708 ret = of_property_count_strings(np, "ste,pins");
1709 if (ret < 0)
1710 goto exit;
1711
1712 if (has_config)
1713 reserve++;
1714
1715 reserve *= ret;
1716
1717 ret = nmk_dt_reserve_map(map, reserved_maps, num_maps, reserve);
1718 if (ret < 0)
1719 goto exit;
1720
1721 of_property_for_each_string(np, "ste,pins", prop, group) {
1722 if (function) {
1723 ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps,
1724 group, function);
1725 if (ret < 0)
1726 goto exit;
1727 }
1728 if (has_config) {
1729 gpio_name = nmk_find_pin_name(pctldev, group);
1730
1731 ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps,
1732 gpio_name, &configs, 1);
1733 if (ret < 0)
1734 goto exit;
1735 }
1736
1737 }
1738exit:
1739 return ret;
1740}
1741
1742int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
1743 struct device_node *np_config,
1744 struct pinctrl_map **map, unsigned *num_maps)
1745{
1746 unsigned reserved_maps;
1747 struct device_node *np;
1748 int ret;
1749
1750 reserved_maps = 0;
1751 *map = NULL;
1752 *num_maps = 0;
1753
1754 for_each_child_of_node(np_config, np) {
1755 ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map,
1756 &reserved_maps, num_maps);
1757 if (ret < 0) {
1758 nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps);
1759 return ret;
1760 }
1761 }
1762
1763 return 0;
1764}
1765
1493static struct pinctrl_ops nmk_pinctrl_ops = { 1766static struct pinctrl_ops nmk_pinctrl_ops = {
1494 .get_groups_count = nmk_get_groups_cnt, 1767 .get_groups_count = nmk_get_groups_cnt,
1495 .get_group_name = nmk_get_group_name, 1768 .get_group_name = nmk_get_group_name,
1496 .get_group_pins = nmk_get_group_pins, 1769 .get_group_pins = nmk_get_group_pins,
1497 .pin_dbg_show = nmk_pin_dbg_show, 1770 .pin_dbg_show = nmk_pin_dbg_show,
1771 .dt_node_to_map = nmk_pinctrl_dt_node_to_map,
1772 .dt_free_map = nmk_pinctrl_dt_free_map,
1498}; 1773};
1499 1774
1500static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) 1775static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
@@ -1828,7 +2103,7 @@ static struct pinctrl_desc nmk_pinctrl_desc = {
1828 2103
1829static const struct of_device_id nmk_pinctrl_match[] = { 2104static const struct of_device_id nmk_pinctrl_match[] = {
1830 { 2105 {
1831 .compatible = "stericsson,nmk_pinctrl", 2106 .compatible = "stericsson,nmk-pinctrl",
1832 .data = (void *)PINCTRL_NMK_DB8500, 2107 .data = (void *)PINCTRL_NMK_DB8500,
1833 }, 2108 },
1834 {}, 2109 {},