aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2014-07-02 11:41:03 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-07-11 08:08:37 -0400
commit9a2c1c3b91aae73ef7aa97cce1f88002d0a7cfe8 (patch)
treea9d32ab46f7b9e1dd0ac866adaae8c31edd4bfbf /drivers/pinctrl
parent2e4a4fda30fcf961f06573336db98cd460d3bf72 (diff)
pinctrl: samsung: Allow grouping multiple pinmux/pinconf nodes
One of remaining limitations of current pinctrl-samsung driver was the inability to parse multiple pinmux/pinconf group nodes grouped inside a single device tree node. It made defining groups of pins for single purpose, but with different parameters very inconvenient. This patch implements Tegra-like support for grouping multiple pinctrl groups inside one device tree node, by completely changing the way pin groups and functions are parsed from device tree. The code creating pinctrl maps from DT nodes has been borrowed from pinctrl-tegra, while the initial creation of groups and functions has been completely rewritten with following assumptions: - each group consists of just one pin and does not depend on data from device tree, - each function is represented by a device tree child node of the pin controller, which in turn can contain multiple child nodes for pins that need to have different configuration values. Device Tree bindings are fully backwards compatible. New functionality can be used by defining a new pinctrl group consisting of several child nodes, as on following example: sd4_bus8: sd4-bus-width8 { part-1 { samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6"; samsung,pin-function = <3>; samsung,pin-pud = <3>; samsung,pin-drv = <3>; }; part-2 { samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6"; samsung,pin-function = <4>; samsung,pin-pud = <4>; samsung,pin-drv = <3>; }; }; Tested on Exynos4210-Trats board and a custom Exynos4212-based one. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Cc: devicetree@vger.kernel.org Cc: Rob Herring <robh+dt@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c613
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h1
2 files changed, 362 insertions, 252 deletions
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index a09d8209ac2c..b7de66c3b51d 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -40,9 +40,9 @@
40 40
41/* list of all possible config options supported */ 41/* list of all possible config options supported */
42static struct pin_config { 42static struct pin_config {
43 char *prop_cfg; 43 const char *property;
44 unsigned int cfg_type; 44 enum pincfg_type param;
45} pcfgs[] = { 45} cfg_params[] = {
46 { "samsung,pin-pud", PINCFG_TYPE_PUD }, 46 { "samsung,pin-pud", PINCFG_TYPE_PUD },
47 { "samsung,pin-drv", PINCFG_TYPE_DRV }, 47 { "samsung,pin-drv", PINCFG_TYPE_DRV },
48 { "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN }, 48 { "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN },
@@ -59,163 +59,242 @@ static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
59 return container_of(gc, struct samsung_pin_bank, gpio_chip); 59 return container_of(gc, struct samsung_pin_bank, gpio_chip);
60} 60}
61 61
62/* check if the selector is a valid pin group selector */
63static int samsung_get_group_count(struct pinctrl_dev *pctldev) 62static int samsung_get_group_count(struct pinctrl_dev *pctldev)
64{ 63{
65 struct samsung_pinctrl_drv_data *drvdata; 64 struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
66 65
67 drvdata = pinctrl_dev_get_drvdata(pctldev); 66 return pmx->nr_groups;
68 return drvdata->nr_groups;
69} 67}
70 68
71/* return the name of the group selected by the group selector */
72static const char *samsung_get_group_name(struct pinctrl_dev *pctldev, 69static const char *samsung_get_group_name(struct pinctrl_dev *pctldev,
73 unsigned selector) 70 unsigned group)
74{ 71{
75 struct samsung_pinctrl_drv_data *drvdata; 72 struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
76 73
77 drvdata = pinctrl_dev_get_drvdata(pctldev); 74 return pmx->pin_groups[group].name;
78 return drvdata->pin_groups[selector].name;
79} 75}
80 76
81/* return the pin numbers associated with the specified group */
82static int samsung_get_group_pins(struct pinctrl_dev *pctldev, 77static int samsung_get_group_pins(struct pinctrl_dev *pctldev,
83 unsigned selector, const unsigned **pins, unsigned *num_pins) 78 unsigned group,
79 const unsigned **pins,
80 unsigned *num_pins)
84{ 81{
85 struct samsung_pinctrl_drv_data *drvdata; 82 struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
83
84 *pins = pmx->pin_groups[group].pins;
85 *num_pins = pmx->pin_groups[group].num_pins;
86 86
87 drvdata = pinctrl_dev_get_drvdata(pctldev);
88 *pins = drvdata->pin_groups[selector].pins;
89 *num_pins = drvdata->pin_groups[selector].num_pins;
90 return 0; 87 return 0;
91} 88}
92 89
93/* create pinctrl_map entries by parsing device tree nodes */ 90static int reserve_map(struct device *dev, struct pinctrl_map **map,
94static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev, 91 unsigned *reserved_maps, unsigned *num_maps,
95 struct device_node *np, struct pinctrl_map **maps, 92 unsigned reserve)
96 unsigned *nmaps)
97{ 93{
98 struct device *dev = pctldev->dev; 94 unsigned old_num = *reserved_maps;
99 struct pinctrl_map *map; 95 unsigned new_num = *num_maps + reserve;
100 unsigned long *cfg = NULL; 96 struct pinctrl_map *new_map;
101 char *gname, *fname;
102 int cfg_cnt = 0, map_cnt = 0, idx = 0;
103
104 /* count the number of config options specfied in the node */
105 for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
106 if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
107 cfg_cnt++;
108 }
109 97
110 /* 98 if (old_num >= new_num)
111 * Find out the number of map entries to create. All the config options 99 return 0;
112 * can be accomadated into a single config map entry.
113 */
114 if (cfg_cnt)
115 map_cnt = 1;
116 if (of_find_property(np, "samsung,pin-function", NULL))
117 map_cnt++;
118 if (!map_cnt) {
119 dev_err(dev, "node %s does not have either config or function "
120 "configurations\n", np->name);
121 return -EINVAL;
122 }
123 100
124 /* Allocate memory for pin-map entries */ 101 new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
125 map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL); 102 if (!new_map) {
126 if (!map) { 103 dev_err(dev, "krealloc(map) failed\n");
127 dev_err(dev, "could not alloc memory for pin-maps\n");
128 return -ENOMEM; 104 return -ENOMEM;
129 } 105 }
130 *nmaps = 0;
131 106
132 /* 107 memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
133 * Allocate memory for pin group name. The pin group name is derived 108
134 * from the node name from which these map entries are be created. 109 *map = new_map;
135 */ 110 *reserved_maps = new_num;
136 gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL); 111
137 if (!gname) { 112 return 0;
138 dev_err(dev, "failed to alloc memory for group name\n"); 113}
139 goto free_map; 114
115static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
116 unsigned *num_maps, const char *group,
117 const char *function)
118{
119 if (WARN_ON(*num_maps == *reserved_maps))
120 return -ENOSPC;
121
122 (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
123 (*map)[*num_maps].data.mux.group = group;
124 (*map)[*num_maps].data.mux.function = function;
125 (*num_maps)++;
126
127 return 0;
128}
129
130static int add_map_configs(struct device *dev, struct pinctrl_map **map,
131 unsigned *reserved_maps, unsigned *num_maps,
132 const char *group, unsigned long *configs,
133 unsigned num_configs)
134{
135 unsigned long *dup_configs;
136
137 if (WARN_ON(*num_maps == *reserved_maps))
138 return -ENOSPC;
139
140 dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
141 GFP_KERNEL);
142 if (!dup_configs) {
143 dev_err(dev, "kmemdup(configs) failed\n");
144 return -ENOMEM;
140 } 145 }
141 sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
142 146
143 /* 147 (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
144 * don't have config options? then skip over to creating function 148 (*map)[*num_maps].data.configs.group_or_pin = group;
145 * map entries. 149 (*map)[*num_maps].data.configs.configs = dup_configs;
146 */ 150 (*map)[*num_maps].data.configs.num_configs = num_configs;
147 if (!cfg_cnt) 151 (*num_maps)++;
148 goto skip_cfgs; 152
149 153 return 0;
150 /* Allocate memory for config entries */ 154}
151 cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL); 155
152 if (!cfg) { 156static int add_config(struct device *dev, unsigned long **configs,
153 dev_err(dev, "failed to alloc memory for configs\n"); 157 unsigned *num_configs, unsigned long config)
154 goto free_gname; 158{
159 unsigned old_num = *num_configs;
160 unsigned new_num = old_num + 1;
161 unsigned long *new_configs;
162
163 new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
164 GFP_KERNEL);
165 if (!new_configs) {
166 dev_err(dev, "krealloc(configs) failed\n");
167 return -ENOMEM;
155 } 168 }
156 169
157 /* Prepare a list of config settings */ 170 new_configs[old_num] = config;
158 for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) { 171
159 u32 value; 172 *configs = new_configs;
160 if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value)) 173 *num_configs = new_num;
161 cfg[cfg_cnt++] = 174
162 PINCFG_PACK(pcfgs[idx].cfg_type, value); 175 return 0;
176}
177
178static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
179 struct pinctrl_map *map,
180 unsigned num_maps)
181{
182 int i;
183
184 for (i = 0; i < num_maps; i++)
185 if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
186 kfree(map[i].data.configs.configs);
187
188 kfree(map);
189}
190
191static int samsung_dt_subnode_to_map(struct samsung_pinctrl_drv_data *drvdata,
192 struct device *dev,
193 struct device_node *np,
194 struct pinctrl_map **map,
195 unsigned *reserved_maps,
196 unsigned *num_maps)
197{
198 int ret, i;
199 u32 val;
200 unsigned long config;
201 unsigned long *configs = NULL;
202 unsigned num_configs = 0;
203 unsigned reserve;
204 struct property *prop;
205 const char *group;
206 bool has_func = false;
207
208 ret = of_property_read_u32(np, "samsung,pin-function", &val);
209 if (!ret)
210 has_func = true;
211
212 for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
213 ret = of_property_read_u32(np, cfg_params[i].property, &val);
214 if (!ret) {
215 config = PINCFG_PACK(cfg_params[i].param, val);
216 ret = add_config(dev, &configs, &num_configs, config);
217 if (ret < 0)
218 goto exit;
219 /* EINVAL=missing, which is fine since it's optional */
220 } else if (ret != -EINVAL) {
221 dev_err(dev, "could not parse property %s\n",
222 cfg_params[i].property);
223 }
163 } 224 }
164 225
165 /* create the config map entry */ 226 reserve = 0;
166 map[*nmaps].data.configs.group_or_pin = gname; 227 if (has_func)
167 map[*nmaps].data.configs.configs = cfg; 228 reserve++;
168 map[*nmaps].data.configs.num_configs = cfg_cnt; 229 if (num_configs)
169 map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP; 230 reserve++;
170 *nmaps += 1; 231 ret = of_property_count_strings(np, "samsung,pins");
171 232 if (ret < 0) {
172skip_cfgs: 233 dev_err(dev, "could not parse property samsung,pins\n");
173 /* create the function map entry */ 234 goto exit;
174 if (of_find_property(np, "samsung,pin-function", NULL)) { 235 }
175 fname = kzalloc(strlen(np->name) + FSUFFIX_LEN, GFP_KERNEL); 236 reserve *= ret;
176 if (!fname) { 237
177 dev_err(dev, "failed to alloc memory for func name\n"); 238 ret = reserve_map(dev, map, reserved_maps, num_maps, reserve);
178 goto free_cfg; 239 if (ret < 0)
240 goto exit;
241
242 of_property_for_each_string(np, "samsung,pins", prop, group) {
243 if (has_func) {
244 ret = add_map_mux(map, reserved_maps,
245 num_maps, group, np->full_name);
246 if (ret < 0)
247 goto exit;
179 } 248 }
180 sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
181 249
182 map[*nmaps].data.mux.group = gname; 250 if (num_configs) {
183 map[*nmaps].data.mux.function = fname; 251 ret = add_map_configs(dev, map, reserved_maps,
184 map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP; 252 num_maps, group, configs,
185 *nmaps += 1; 253 num_configs);
254 if (ret < 0)
255 goto exit;
256 }
186 } 257 }
187 258
188 *maps = map; 259 ret = 0;
189 return 0;
190 260
191free_cfg: 261exit:
192 kfree(cfg); 262 kfree(configs);
193free_gname: 263 return ret;
194 kfree(gname);
195free_map:
196 kfree(map);
197 return -ENOMEM;
198} 264}
199 265
200/* free the memory allocated to hold the pin-map table */ 266static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
201static void samsung_dt_free_map(struct pinctrl_dev *pctldev, 267 struct device_node *np_config,
202 struct pinctrl_map *map, unsigned num_maps) 268 struct pinctrl_map **map,
269 unsigned *num_maps)
203{ 270{
204 int idx; 271 struct samsung_pinctrl_drv_data *drvdata;
205 272 unsigned reserved_maps;
206 for (idx = 0; idx < num_maps; idx++) { 273 struct device_node *np;
207 if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) { 274 int ret;
208 kfree(map[idx].data.mux.function); 275
209 if (!idx) 276 drvdata = pinctrl_dev_get_drvdata(pctldev);
210 kfree(map[idx].data.mux.group); 277
211 } else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) { 278 reserved_maps = 0;
212 kfree(map[idx].data.configs.configs); 279 *map = NULL;
213 if (!idx) 280 *num_maps = 0;
214 kfree(map[idx].data.configs.group_or_pin); 281
282 if (!of_get_child_count(np_config))
283 return samsung_dt_subnode_to_map(drvdata, pctldev->dev,
284 np_config, map,
285 &reserved_maps,
286 num_maps);
287
288 for_each_child_of_node(np_config, np) {
289 ret = samsung_dt_subnode_to_map(drvdata, pctldev->dev, np, map,
290 &reserved_maps, num_maps);
291 if (ret < 0) {
292 samsung_dt_free_map(pctldev, *map, *num_maps);
293 return ret;
215 } 294 }
216 }; 295 }
217 296
218 kfree(map); 297 return 0;
219} 298}
220 299
221/* list of pinctrl callbacks for the pinctrl core */ 300/* list of pinctrl callbacks for the pinctrl core */
@@ -286,43 +365,38 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
286 unsigned group, bool enable) 365 unsigned group, bool enable)
287{ 366{
288 struct samsung_pinctrl_drv_data *drvdata; 367 struct samsung_pinctrl_drv_data *drvdata;
289 const unsigned int *pins; 368 struct samsung_pin_bank_type *type;
290 struct samsung_pin_bank *bank; 369 struct samsung_pin_bank *bank;
291 void __iomem *reg; 370 void __iomem *reg;
292 u32 mask, shift, data, pin_offset, cnt; 371 u32 mask, shift, data, pin_offset;
293 unsigned long flags; 372 unsigned long flags;
373 const struct samsung_pmx_func *func;
374 const struct samsung_pin_group *grp;
294 375
295 drvdata = pinctrl_dev_get_drvdata(pctldev); 376 drvdata = pinctrl_dev_get_drvdata(pctldev);
296 pins = drvdata->pin_groups[group].pins; 377 func = &drvdata->pmx_functions[selector];
378 grp = &drvdata->pin_groups[group];
297 379
298 /* 380 pin_to_reg_bank(drvdata, grp->pins[0] - drvdata->ctrl->base,
299 * for each pin in the pin group selected, program the correspoding pin 381 &reg, &pin_offset, &bank);
300 * pin function number in the config register. 382 type = bank->type;
301 */ 383 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
302 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { 384 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
303 struct samsung_pin_bank_type *type; 385 if (shift >= 32) {
304 386 /* Some banks have two config registers */
305 pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base, 387 shift -= 32;
306 &reg, &pin_offset, &bank); 388 reg += 4;
307 type = bank->type; 389 }
308 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
309 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
310 if (shift >= 32) {
311 /* Some banks have two config registers */
312 shift -= 32;
313 reg += 4;
314 }
315 390
316 spin_lock_irqsave(&bank->slock, flags); 391 spin_lock_irqsave(&bank->slock, flags);
317 392
318 data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]); 393 data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
319 data &= ~(mask << shift); 394 data &= ~(mask << shift);
320 if (enable) 395 if (enable)
321 data |= drvdata->pin_groups[group].func << shift; 396 data |= func->val << shift;
322 writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]); 397 writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
323 398
324 spin_unlock_irqrestore(&bank->slock, flags); 399 spin_unlock_irqrestore(&bank->slock, flags);
325 }
326} 400}
327 401
328/* enable a specified pinmux by writing to registers */ 402/* enable a specified pinmux by writing to registers */
@@ -559,87 +633,115 @@ static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
559 return (virq) ? : -ENXIO; 633 return (virq) ? : -ENXIO;
560} 634}
561 635
562/* 636static struct samsung_pin_group *samsung_pinctrl_create_groups(
563 * Parse the pin names listed in the 'samsung,pins' property and convert it 637 struct device *dev,
564 * into a list of gpio numbers are create a pin group from it. 638 struct samsung_pinctrl_drv_data *drvdata,
565 */ 639 unsigned int *cnt)
566static int samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
567 struct device_node *cfg_np,
568 struct pinctrl_desc *pctl,
569 unsigned int **pin_list,
570 unsigned int *npins)
571{ 640{
572 struct device *dev = &pdev->dev; 641 struct pinctrl_desc *ctrldesc = &drvdata->pctl;
573 struct property *prop; 642 struct samsung_pin_group *groups, *grp;
574 struct pinctrl_pin_desc const *pdesc = pctl->pins; 643 const struct pinctrl_pin_desc *pdesc;
575 unsigned int idx = 0, cnt; 644 int i;
576 const char *pin_name; 645
646 groups = devm_kzalloc(dev, ctrldesc->npins * sizeof(*groups),
647 GFP_KERNEL);
648 if (!groups)
649 return ERR_PTR(-EINVAL);
650 grp = groups;
651
652 pdesc = ctrldesc->pins;
653 for (i = 0; i < ctrldesc->npins; ++i, ++pdesc, ++grp) {
654 grp->name = pdesc->name;
655 grp->pins = &pdesc->number;
656 grp->num_pins = 1;
657 }
658
659 *cnt = ctrldesc->npins;
660 return groups;
661}
577 662
578 *npins = of_property_count_strings(cfg_np, "samsung,pins"); 663static int samsung_pinctrl_create_function(struct device *dev,
579 if (IS_ERR_VALUE(*npins)) { 664 struct samsung_pinctrl_drv_data *drvdata,
580 dev_err(dev, "invalid pin list in %s node", cfg_np->name); 665 struct device_node *func_np,
666 struct samsung_pmx_func *func)
667{
668 int npins;
669 int ret;
670 int i;
671
672 if (of_property_read_u32(func_np, "samsung,pin-function", &func->val))
673 return 0;
674
675 npins = of_property_count_strings(func_np, "samsung,pins");
676 if (npins < 1) {
677 dev_err(dev, "invalid pin list in %s node", func_np->name);
581 return -EINVAL; 678 return -EINVAL;
582 } 679 }
583 680
584 *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL); 681 func->name = func_np->full_name;
585 if (!*pin_list) { 682
586 dev_err(dev, "failed to allocate memory for pin list\n"); 683 func->groups = devm_kzalloc(dev, npins * sizeof(char *), GFP_KERNEL);
684 if (!func->groups)
587 return -ENOMEM; 685 return -ENOMEM;
588 }
589 686
590 of_property_for_each_string(cfg_np, "samsung,pins", prop, pin_name) { 687 for (i = 0; i < npins; ++i) {
591 for (cnt = 0; cnt < pctl->npins; cnt++) { 688 const char *gname;
592 if (pdesc[cnt].name) { 689
593 if (!strcmp(pin_name, pdesc[cnt].name)) { 690 ret = of_property_read_string_index(func_np, "samsung,pins",
594 (*pin_list)[idx++] = pdesc[cnt].number; 691 i, &gname);
595 break; 692 if (ret) {
596 } 693 dev_err(dev,
597 } 694 "failed to read pin name %d from %s node\n",
598 } 695 i, func_np->name);
599 if (cnt == pctl->npins) { 696 return ret;
600 dev_err(dev, "pin %s not valid in %s node\n",
601 pin_name, cfg_np->name);
602 devm_kfree(dev, *pin_list);
603 return -EINVAL;
604 } 697 }
698
699 func->groups[i] = gname;
605 } 700 }
606 701
607 return 0; 702 func->num_groups = npins;
703 return 1;
608} 704}
609 705
610/* 706static struct samsung_pmx_func *samsung_pinctrl_create_functions(
611 * Parse the information about all the available pin groups and pin functions 707 struct device *dev,
612 * from device node of the pin-controller. A pin group is formed with all 708 struct samsung_pinctrl_drv_data *drvdata,
613 * the pins listed in the "samsung,pins" property. 709 unsigned int *cnt)
614 */
615static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
616 struct samsung_pinctrl_drv_data *drvdata)
617{ 710{
618 struct device *dev = &pdev->dev; 711 struct samsung_pmx_func *functions, *func;
619 struct device_node *dev_np = dev->of_node; 712 struct device_node *dev_np = dev->of_node;
620 struct device_node *cfg_np; 713 struct device_node *cfg_np;
621 struct samsung_pin_group *groups, *grp; 714 unsigned int func_cnt = 0;
622 struct samsung_pmx_func *functions, *func;
623 unsigned *pin_list;
624 unsigned int npins, grp_cnt, func_idx = 0;
625 char *gname, *fname;
626 int ret; 715 int ret;
627 716
628 grp_cnt = of_get_child_count(dev_np); 717 /*
629 if (!grp_cnt) 718 * Iterate over all the child nodes of the pin controller node
630 return -EINVAL; 719 * and create pin groups and pin function lists.
720 */
721 for_each_child_of_node(dev_np, cfg_np) {
722 struct device_node *func_np;
631 723
632 groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL); 724 if (!of_get_child_count(cfg_np)) {
633 if (!groups) { 725 if (!of_find_property(cfg_np,
634 dev_err(dev, "failed allocate memory for ping group list\n"); 726 "samsung,pin-function", NULL))
635 return -EINVAL; 727 continue;
728 ++func_cnt;
729 continue;
730 }
731
732 for_each_child_of_node(cfg_np, func_np) {
733 if (!of_find_property(func_np,
734 "samsung,pin-function", NULL))
735 continue;
736 ++func_cnt;
737 }
636 } 738 }
637 grp = groups;
638 739
639 functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL); 740 functions = devm_kzalloc(dev, func_cnt * sizeof(*functions),
741 GFP_KERNEL);
640 if (!functions) { 742 if (!functions) {
641 dev_err(dev, "failed to allocate memory for function list\n"); 743 dev_err(dev, "failed to allocate memory for function list\n");
642 return -EINVAL; 744 return ERR_PTR(-EINVAL);
643 } 745 }
644 func = functions; 746 func = functions;
645 747
@@ -647,61 +749,68 @@ static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
647 * Iterate over all the child nodes of the pin controller node 749 * Iterate over all the child nodes of the pin controller node
648 * and create pin groups and pin function lists. 750 * and create pin groups and pin function lists.
649 */ 751 */
752 func_cnt = 0;
650 for_each_child_of_node(dev_np, cfg_np) { 753 for_each_child_of_node(dev_np, cfg_np) {
651 u32 function; 754 struct device_node *func_np;
652 if (!of_find_property(cfg_np, "samsung,pins", NULL)) 755
756 if (!of_get_child_count(cfg_np)) {
757 ret = samsung_pinctrl_create_function(dev, drvdata,
758 cfg_np, func);
759 if (ret < 0)
760 return ERR_PTR(ret);
761 if (ret > 0) {
762 ++func;
763 ++func_cnt;
764 }
653 continue; 765 continue;
766 }
654 767
655 ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np, 768 for_each_child_of_node(cfg_np, func_np) {
656 &drvdata->pctl, &pin_list, &npins); 769 ret = samsung_pinctrl_create_function(dev, drvdata,
657 if (ret) 770 func_np, func);
658 return ret; 771 if (ret < 0)
659 772 return ERR_PTR(ret);
660 /* derive pin group name from the node name */ 773 if (ret > 0) {
661 gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN, 774 ++func;
662 GFP_KERNEL); 775 ++func_cnt;
663 if (!gname) { 776 }
664 dev_err(dev, "failed to alloc memory for group name\n");
665 return -ENOMEM;
666 } 777 }
667 sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX); 778 }
668 779
669 grp->name = gname; 780 *cnt = func_cnt;
670 grp->pins = pin_list; 781 return functions;
671 grp->num_pins = npins; 782}
672 of_property_read_u32(cfg_np, "samsung,pin-function", &function);
673 grp->func = function;
674 grp++;
675 783
676 if (!of_find_property(cfg_np, "samsung,pin-function", NULL)) 784/*
677 continue; 785 * Parse the information about all the available pin groups and pin functions
786 * from device node of the pin-controller. A pin group is formed with all
787 * the pins listed in the "samsung,pins" property.
788 */
678 789
679 /* derive function name from the node name */ 790static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
680 fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN, 791 struct samsung_pinctrl_drv_data *drvdata)
681 GFP_KERNEL); 792{
682 if (!fname) { 793 struct device *dev = &pdev->dev;
683 dev_err(dev, "failed to alloc memory for func name\n"); 794 struct samsung_pin_group *groups;
684 return -ENOMEM; 795 struct samsung_pmx_func *functions;
685 } 796 unsigned int grp_cnt = 0, func_cnt = 0;
686 sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX); 797
687 798 groups = samsung_pinctrl_create_groups(dev, drvdata, &grp_cnt);
688 func->name = fname; 799 if (IS_ERR(groups)) {
689 func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL); 800 dev_err(dev, "failed to parse pin groups\n");
690 if (!func->groups) { 801 return PTR_ERR(groups);
691 dev_err(dev, "failed to alloc memory for group list " 802 }
692 "in pin function"); 803
693 return -ENOMEM; 804 functions = samsung_pinctrl_create_functions(dev, drvdata, &func_cnt);
694 } 805 if (IS_ERR(functions)) {
695 func->groups[0] = gname; 806 dev_err(dev, "failed to parse pin functions\n");
696 func->num_groups = 1; 807 return PTR_ERR(groups);
697 func++;
698 func_idx++;
699 } 808 }
700 809
701 drvdata->pin_groups = groups; 810 drvdata->pin_groups = groups;
702 drvdata->nr_groups = grp_cnt; 811 drvdata->nr_groups = grp_cnt;
703 drvdata->pmx_functions = functions; 812 drvdata->pmx_functions = functions;
704 drvdata->nr_functions = func_idx; 813 drvdata->nr_functions = func_cnt;
705 814
706 return 0; 815 return 0;
707} 816}
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index e2dce4731a01..2b882320e8e9 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -231,6 +231,7 @@ struct samsung_pmx_func {
231 const char *name; 231 const char *name;
232 const char **groups; 232 const char **groups;
233 u8 num_groups; 233 u8 num_groups;
234 u32 val;
234}; 235};
235 236
236/* list of all exported SoC specific data */ 237/* list of all exported SoC specific data */