aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt140
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c2
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c277
4 files changed, 418 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt b/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt
new file mode 100644
index 000000000000..9a2f3f420526
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt
@@ -0,0 +1,140 @@
1ST Ericsson Nomadik pinmux controller
2
3Required properties:
4- compatible: "stericsson,nmk-pinctrl", "stericsson,nmk-pinctrl-db8540",
5 "stericsson,nmk-pinctrl-stn8815"
6- reg: Should contain the register physical address and length of the PRCMU.
7
8Please refer to pinctrl-bindings.txt in this directory for details of the
9common pinctrl bindings used by client devices, including the meaning of the
10phrase "pin configuration node".
11
12ST Ericsson's pin configuration nodes act as a container for an arbitrary number of
13subnodes. Each of these subnodes represents some desired configuration for a
14pin, a group, or a list of pins or groups. This configuration can include the
15mux function to select on those pin(s)/group(s), and various pin configuration
16parameters, such as input, output, pull up, pull down...
17
18The name of each subnode is not important; all subnodes should be enumerated
19and processed purely based on their content.
20
21Required subnode-properties:
22- ste,pins : An array of strings. Each string contains the name of a pin or
23 group.
24
25Optional subnode-properties:
26- ste,function: A string containing the name of the function to mux to the
27 pin or group.
28
29- ste,config: Handle of pin configuration node (e.g. ste,config = <&slpm_in_wkup_pdis>)
30
31- ste,input : <0/1/2>
32 0: input with no pull
33 1: input with pull up,
34 2: input with pull down,
35
36- ste,output: <0/1/2>
37 0: output low,
38 1: output high,
39 2: output (value is not specified).
40
41- ste,sleep: <0/1>
42 0: sleep mode disable,
43 1: sleep mode enable.
44
45- ste,sleep-input: <0/1/2/3>
46 0: sleep input with no pull,
47 1: sleep input with pull up,
48 2: sleep input with pull down.
49 3: sleep input and keep last input configuration (no pull, pull up or pull down).
50
51- ste,sleep-output: <0/1/2>
52 0: sleep output low,
53 1: sleep output high,
54 2: sleep output (value is not specified).
55
56- ste,sleep-gpio: <0/1>
57 0: disable sleep gpio mode,
58 1: enable sleep gpio mode.
59
60- ste,sleep-wakeup: <0/1>
61 0: wake-up detection enabled,
62 1: wake-up detection disabled.
63
64- ste,sleep-pull-disable: <0/1>
65 0: GPIO pull-up or pull-down resistor is enabled, when pin is an input,
66 1: GPIO pull-up and pull-down resistor are disabled.
67
68Example board file extract:
69
70 pinctrl@80157000 {
71 compatible = "stericsson,nmk-pinctrl";
72 reg = <0x80157000 0x2000>;
73
74 pinctrl-names = "default";
75
76 slpm_in_wkup_pdis: slpm_in_wkup_pdis {
77 ste,sleep = <1>;
78 ste,sleep-input = <3>;
79 ste,sleep-wakeup = <1>;
80 ste,sleep-pull-disable = <0>;
81 };
82
83 slpm_out_hi_wkup_pdis: slpm_out_hi_wkup_pdis {
84 ste,sleep = <1>;
85 ste,sleep-output = <1>;
86 ste,sleep-wakeup = <1>;
87 ste,sleep-pull-disable = <0>;
88 };
89
90 slpm_out_wkup_pdis: slpm_out_wkup_pdis {
91 ste,sleep = <1>;
92 ste,sleep-output = <2>;
93 ste,sleep-wakeup = <1>;
94 ste,sleep-pull-disable = <0>;
95 };
96
97 uart0 {
98 uart0_default_mux: uart0_mux {
99 u0_default_mux {
100 ste,function = "u0";
101 ste,pins = "u0_a_1";
102 };
103 };
104 uart0_default_mode: uart0_default {
105 uart0_default_cfg1 {
106 ste,pins = "GPIO0", "GPIO2";
107 ste,input = <1>;
108 };
109
110 uart0_default_cfg2 {
111 ste,pins = "GPIO1", "GPIO3";
112 ste,output = <1>;
113 };
114 };
115 uart0_sleep_mode: uart0_sleep {
116 uart0_sleep_cfg1 {
117 ste,pins = "GPIO0", "GPIO2";
118 ste,config = <&slpm_in_wkup_pdis>;
119 };
120 uart0_sleep_cfg2 {
121 ste,pins = "GPIO1";
122 ste,config = <&slpm_out_hi_wkup_pdis>;
123 };
124 uart0_sleep_cfg3 {
125 ste,pins = "GPIO3";
126 ste,config = <&slpm_out_wkup_pdis>;
127 };
128 };
129 };
130 };
131
132 uart@80120000 {
133 compatible = "arm,pl011", "arm,primecell";
134 reg = <0x80120000 0x1000>;
135 interrupts = <0 11 0x4>;
136
137 pinctrl-names = "default","sleep";
138 pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
139 pinctrl-1 = <&uart0_sleep_mode>;
140 };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 902b1b1f568e..15321373ec8d 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -50,6 +50,7 @@ simtek
50sirf SiRF Technology, Inc. 50sirf SiRF Technology, Inc.
51snps Synopsys, Inc. 51snps Synopsys, Inc.
52st STMicroelectronics 52st STMicroelectronics
53ste ST-Ericsson
53stericsson ST-Ericsson 54stericsson ST-Ericsson
54ti Texas Instruments 55ti Texas Instruments
55via VIA Technologies, Inc. 56via VIA Technologies, Inc.
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 5b286e06474c..b80ad9610e97 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -285,7 +285,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
285 OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL), 285 OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
286 OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL), 286 OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
287 /* Requires device name bindings. */ 287 /* Requires device name bindings. */
288 OF_DEV_AUXDATA("stericsson,nmk_pinctrl", U8500_PRCMU_BASE, 288 OF_DEV_AUXDATA("stericsson,nmk-pinctrl", U8500_PRCMU_BASE,
289 "pinctrl-db8500", NULL), 289 "pinctrl-db8500", NULL),
290 /* Requires clock name and DMA bindings. */ 290 /* Requires clock name and DMA bindings. */
291 OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000, 291 OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
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 {},