aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/sh-pfc/pinctrl.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-06-17 14:50:02 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-06-18 04:57:51 -0400
commitfe1c9a822ce72c6ec8476a2501c412265ee2172c (patch)
tree743e3e67152fd5883e02a4eded386787d7fa8be5 /drivers/pinctrl/sh-pfc/pinctrl.c
parent3a7f520e63727e14de9567515d8727c2c01fedb4 (diff)
sh-pfc: Add DT support
Support device instantiation through the device tree. The compatible property is used to select the SoC pinmux information. Set the gpio_chip device field to the PFC device to enable automatic GPIO OF support. Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/sh-pfc/pinctrl.c')
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 3492ec9a33b7..7e32bb8c08dd 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -14,7 +14,9 @@
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/of.h>
17#include <linux/pinctrl/consumer.h> 18#include <linux/pinctrl/consumer.h>
19#include <linux/pinctrl/machine.h>
18#include <linux/pinctrl/pinconf.h> 20#include <linux/pinctrl/pinconf.h>
19#include <linux/pinctrl/pinconf-generic.h> 21#include <linux/pinctrl/pinconf-generic.h>
20#include <linux/pinctrl/pinctrl.h> 22#include <linux/pinctrl/pinctrl.h>
@@ -72,11 +74,125 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
72 seq_printf(s, "%s", DRV_NAME); 74 seq_printf(s, "%s", DRV_NAME);
73} 75}
74 76
77static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
78 struct pinctrl_map **map,
79 unsigned int *num_maps, unsigned int *index)
80{
81 struct pinctrl_map *maps = *map;
82 unsigned int nmaps = *num_maps;
83 unsigned int idx = *index;
84 const char *function = NULL;
85 struct property *prop;
86 const char *group;
87 int ret;
88
89 /* Parse the function and configuration properties. At least a function
90 * or one configuration must be specified.
91 */
92 ret = of_property_read_string(np, "renesas,function", &function);
93 if (ret < 0 && ret != -EINVAL) {
94 dev_err(dev, "Invalid function in DT\n");
95 return ret;
96 }
97
98 if (!function) {
99 dev_err(dev, "DT node must contain at least one function\n");
100 goto done;
101 }
102
103 /* Count the number of groups and reallocate mappings. */
104 ret = of_property_count_strings(np, "renesas,groups");
105 if (ret < 0 && ret != -EINVAL) {
106 dev_err(dev, "Invalid pin groups list in DT\n");
107 goto done;
108 }
109
110 if (!ret) {
111 dev_err(dev, "No group provided in DT node\n");
112 ret = -ENODEV;
113 goto done;
114 }
115
116 nmaps += ret;
117
118 maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
119 if (maps == NULL) {
120 ret = -ENOMEM;
121 goto done;
122 }
123
124 *map = maps;
125 *num_maps = nmaps;
126
127 /* Iterate over pins and groups and create the mappings. */
128 of_property_for_each_string(np, "renesas,groups", prop, group) {
129 maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
130 maps[idx].data.mux.group = group;
131 maps[idx].data.mux.function = function;
132 idx++;
133 }
134
135 ret = 0;
136
137done:
138 *index = idx;
139 return ret;
140}
141
142static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
143 struct pinctrl_map *map, unsigned num_maps)
144{
145 kfree(map);
146}
147
148static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
149 struct device_node *np,
150 struct pinctrl_map **map, unsigned *num_maps)
151{
152 struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
153 struct device *dev = pmx->pfc->dev;
154 struct device_node *child;
155 unsigned int index;
156 int ret;
157
158 *map = NULL;
159 *num_maps = 0;
160 index = 0;
161
162 for_each_child_of_node(np, child) {
163 ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps,
164 &index);
165 if (ret < 0)
166 goto done;
167 }
168
169 /* If no mapping has been found in child nodes try the config node. */
170 if (*num_maps == 0) {
171 ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index);
172 if (ret < 0)
173 goto done;
174 }
175
176 if (*num_maps)
177 return 0;
178
179 dev_err(dev, "no mapping found in node %s\n", np->full_name);
180 ret = -EINVAL;
181
182done:
183 if (ret < 0)
184 sh_pfc_dt_free_map(pctldev, *map, *num_maps);
185
186 return ret;
187}
188
75static const struct pinctrl_ops sh_pfc_pinctrl_ops = { 189static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
76 .get_groups_count = sh_pfc_get_groups_count, 190 .get_groups_count = sh_pfc_get_groups_count,
77 .get_group_name = sh_pfc_get_group_name, 191 .get_group_name = sh_pfc_get_group_name,
78 .get_group_pins = sh_pfc_get_group_pins, 192 .get_group_pins = sh_pfc_get_group_pins,
79 .pin_dbg_show = sh_pfc_pin_dbg_show, 193 .pin_dbg_show = sh_pfc_pin_dbg_show,
194 .dt_node_to_map = sh_pfc_dt_node_to_map,
195 .dt_free_map = sh_pfc_dt_free_map,
80}; 196};
81 197
82static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev) 198static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)