diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-04-23 12:05:22 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2012-04-25 17:21:47 -0400 |
commit | aef7704c6cc36db9618603b22194def441d30432 (patch) | |
tree | d560e29b90c0fcfadaeb1d41e3ba39a379e8496c /drivers/pinctrl | |
parent | b5badbaad16b44f1d5508701295fa682308da701 (diff) |
pinctrl: tegra: error reporting cleanup
Print an explicit error message in various failure cases to allow
easier diagnosis.
WARN_ON() some internal failures that users/clients shouldn't be able to
trigger.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/pinctrl-tegra.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index df52d75c0db0..b6934867d8d3 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c | |||
@@ -92,8 +92,9 @@ static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, | |||
92 | } | 92 | } |
93 | #endif | 93 | #endif |
94 | 94 | ||
95 | static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, | 95 | static int reserve_map(struct device *dev, struct pinctrl_map **map, |
96 | unsigned *num_maps, unsigned reserve) | 96 | unsigned *reserved_maps, unsigned *num_maps, |
97 | unsigned reserve) | ||
97 | { | 98 | { |
98 | unsigned old_num = *reserved_maps; | 99 | unsigned old_num = *reserved_maps; |
99 | unsigned new_num = *num_maps + reserve; | 100 | unsigned new_num = *num_maps + reserve; |
@@ -103,8 +104,10 @@ static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, | |||
103 | return 0; | 104 | return 0; |
104 | 105 | ||
105 | new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); | 106 | new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); |
106 | if (!new_map) | 107 | if (!new_map) { |
108 | dev_err(dev, "krealloc(map) failed\n"); | ||
107 | return -ENOMEM; | 109 | return -ENOMEM; |
110 | } | ||
108 | 111 | ||
109 | memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); | 112 | memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); |
110 | 113 | ||
@@ -118,7 +121,7 @@ static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps, | |||
118 | unsigned *num_maps, const char *group, | 121 | unsigned *num_maps, const char *group, |
119 | const char *function) | 122 | const char *function) |
120 | { | 123 | { |
121 | if (*num_maps == *reserved_maps) | 124 | if (WARN_ON(*num_maps == *reserved_maps)) |
122 | return -ENOSPC; | 125 | return -ENOSPC; |
123 | 126 | ||
124 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; | 127 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; |
@@ -129,19 +132,22 @@ static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps, | |||
129 | return 0; | 132 | return 0; |
130 | } | 133 | } |
131 | 134 | ||
132 | static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps, | 135 | static int add_map_configs(struct device *dev, struct pinctrl_map **map, |
133 | unsigned *num_maps, const char *group, | 136 | unsigned *reserved_maps, unsigned *num_maps, |
134 | unsigned long *configs, unsigned num_configs) | 137 | const char *group, unsigned long *configs, |
138 | unsigned num_configs) | ||
135 | { | 139 | { |
136 | unsigned long *dup_configs; | 140 | unsigned long *dup_configs; |
137 | 141 | ||
138 | if (*num_maps == *reserved_maps) | 142 | if (WARN_ON(*num_maps == *reserved_maps)) |
139 | return -ENOSPC; | 143 | return -ENOSPC; |
140 | 144 | ||
141 | dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), | 145 | dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), |
142 | GFP_KERNEL); | 146 | GFP_KERNEL); |
143 | if (!dup_configs) | 147 | if (!dup_configs) { |
148 | dev_err(dev, "kmemdup(configs) failed\n"); | ||
144 | return -ENOMEM; | 149 | return -ENOMEM; |
150 | } | ||
145 | 151 | ||
146 | (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP; | 152 | (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP; |
147 | (*map)[*num_maps].data.configs.group_or_pin = group; | 153 | (*map)[*num_maps].data.configs.group_or_pin = group; |
@@ -152,8 +158,8 @@ static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps, | |||
152 | return 0; | 158 | return 0; |
153 | } | 159 | } |
154 | 160 | ||
155 | static int add_config(unsigned long **configs, unsigned *num_configs, | 161 | static int add_config(struct device *dev, unsigned long **configs, |
156 | unsigned long config) | 162 | unsigned *num_configs, unsigned long config) |
157 | { | 163 | { |
158 | unsigned old_num = *num_configs; | 164 | unsigned old_num = *num_configs; |
159 | unsigned new_num = old_num + 1; | 165 | unsigned new_num = old_num + 1; |
@@ -161,8 +167,10 @@ static int add_config(unsigned long **configs, unsigned *num_configs, | |||
161 | 167 | ||
162 | new_configs = krealloc(*configs, sizeof(*new_configs) * new_num, | 168 | new_configs = krealloc(*configs, sizeof(*new_configs) * new_num, |
163 | GFP_KERNEL); | 169 | GFP_KERNEL); |
164 | if (!new_configs) | 170 | if (!new_configs) { |
171 | dev_err(dev, "krealloc(configs) failed\n"); | ||
165 | return -ENOMEM; | 172 | return -ENOMEM; |
173 | } | ||
166 | 174 | ||
167 | new_configs[old_num] = config; | 175 | new_configs[old_num] = config; |
168 | 176 | ||
@@ -203,7 +211,8 @@ static const struct cfg_param { | |||
203 | {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, | 211 | {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, |
204 | }; | 212 | }; |
205 | 213 | ||
206 | int tegra_pinctrl_dt_subnode_to_map(struct device_node *np, | 214 | int tegra_pinctrl_dt_subnode_to_map(struct device *dev, |
215 | struct device_node *np, | ||
207 | struct pinctrl_map **map, | 216 | struct pinctrl_map **map, |
208 | unsigned *reserved_maps, | 217 | unsigned *reserved_maps, |
209 | unsigned *num_maps) | 218 | unsigned *num_maps) |
@@ -219,16 +228,25 @@ int tegra_pinctrl_dt_subnode_to_map(struct device_node *np, | |||
219 | const char *group; | 228 | const char *group; |
220 | 229 | ||
221 | ret = of_property_read_string(np, "nvidia,function", &function); | 230 | ret = of_property_read_string(np, "nvidia,function", &function); |
222 | if (ret < 0) | 231 | if (ret < 0) { |
232 | /* EINVAL=missing, which is fine since it's optional */ | ||
233 | if (ret != -EINVAL) | ||
234 | dev_err(dev, | ||
235 | "could not parse property nvidia,function\n"); | ||
223 | function = NULL; | 236 | function = NULL; |
237 | } | ||
224 | 238 | ||
225 | for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { | 239 | for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { |
226 | ret = of_property_read_u32(np, cfg_params[i].property, &val); | 240 | ret = of_property_read_u32(np, cfg_params[i].property, &val); |
227 | if (!ret) { | 241 | if (!ret) { |
228 | config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); | 242 | config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); |
229 | ret = add_config(&configs, &num_configs, config); | 243 | ret = add_config(dev, &configs, &num_configs, config); |
230 | if (ret < 0) | 244 | if (ret < 0) |
231 | goto exit; | 245 | goto exit; |
246 | /* EINVAL=missing, which is fine since it's optional */ | ||
247 | } else if (ret != -EINVAL) { | ||
248 | dev_err(dev, "could not parse property %s\n", | ||
249 | cfg_params[i].property); | ||
232 | } | 250 | } |
233 | } | 251 | } |
234 | 252 | ||
@@ -238,11 +256,13 @@ int tegra_pinctrl_dt_subnode_to_map(struct device_node *np, | |||
238 | if (num_configs) | 256 | if (num_configs) |
239 | reserve++; | 257 | reserve++; |
240 | ret = of_property_count_strings(np, "nvidia,pins"); | 258 | ret = of_property_count_strings(np, "nvidia,pins"); |
241 | if (ret < 0) | 259 | if (ret < 0) { |
260 | dev_err(dev, "could not parse property nvidia,pins\n"); | ||
242 | goto exit; | 261 | goto exit; |
262 | } | ||
243 | reserve *= ret; | 263 | reserve *= ret; |
244 | 264 | ||
245 | ret = reserve_map(map, reserved_maps, num_maps, reserve); | 265 | ret = reserve_map(dev, map, reserved_maps, num_maps, reserve); |
246 | if (ret < 0) | 266 | if (ret < 0) |
247 | goto exit; | 267 | goto exit; |
248 | 268 | ||
@@ -255,8 +275,9 @@ int tegra_pinctrl_dt_subnode_to_map(struct device_node *np, | |||
255 | } | 275 | } |
256 | 276 | ||
257 | if (num_configs) { | 277 | if (num_configs) { |
258 | ret = add_map_configs(map, reserved_maps, num_maps, | 278 | ret = add_map_configs(dev, map, reserved_maps, |
259 | group, configs, num_configs); | 279 | num_maps, group, configs, |
280 | num_configs); | ||
260 | if (ret < 0) | 281 | if (ret < 0) |
261 | goto exit; | 282 | goto exit; |
262 | } | 283 | } |
@@ -282,8 +303,8 @@ int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, | |||
282 | *num_maps = 0; | 303 | *num_maps = 0; |
283 | 304 | ||
284 | for_each_child_of_node(np_config, np) { | 305 | for_each_child_of_node(np_config, np) { |
285 | ret = tegra_pinctrl_dt_subnode_to_map(np, map, &reserved_maps, | 306 | ret = tegra_pinctrl_dt_subnode_to_map(pctldev->dev, np, map, |
286 | num_maps); | 307 | &reserved_maps, num_maps); |
287 | if (ret < 0) { | 308 | if (ret < 0) { |
288 | tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps); | 309 | tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps); |
289 | return ret; | 310 | return ret; |
@@ -342,14 +363,14 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function, | |||
342 | 363 | ||
343 | g = &pmx->soc->groups[group]; | 364 | g = &pmx->soc->groups[group]; |
344 | 365 | ||
345 | if (g->mux_reg < 0) | 366 | if (WARN_ON(g->mux_reg < 0)) |
346 | return -EINVAL; | 367 | return -EINVAL; |
347 | 368 | ||
348 | for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { | 369 | for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { |
349 | if (g->funcs[i] == function) | 370 | if (g->funcs[i] == function) |
350 | break; | 371 | break; |
351 | } | 372 | } |
352 | if (i == ARRAY_SIZE(g->funcs)) | 373 | if (WARN_ON(i == ARRAY_SIZE(g->funcs))) |
353 | return -EINVAL; | 374 | return -EINVAL; |
354 | 375 | ||
355 | val = pmx_readl(pmx, g->mux_bank, g->mux_reg); | 376 | val = pmx_readl(pmx, g->mux_bank, g->mux_reg); |
@@ -369,7 +390,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev, | |||
369 | 390 | ||
370 | g = &pmx->soc->groups[group]; | 391 | g = &pmx->soc->groups[group]; |
371 | 392 | ||
372 | if (g->mux_reg < 0) | 393 | if (WARN_ON(g->mux_reg < 0)) |
373 | return; | 394 | return; |
374 | 395 | ||
375 | val = pmx_readl(pmx, g->mux_bank, g->mux_reg); | 396 | val = pmx_readl(pmx, g->mux_bank, g->mux_reg); |
@@ -490,12 +511,14 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, | |||
490 | static int tegra_pinconf_get(struct pinctrl_dev *pctldev, | 511 | static int tegra_pinconf_get(struct pinctrl_dev *pctldev, |
491 | unsigned pin, unsigned long *config) | 512 | unsigned pin, unsigned long *config) |
492 | { | 513 | { |
514 | dev_err(pctldev->dev, "pin_config_get op not supported\n"); | ||
493 | return -ENOTSUPP; | 515 | return -ENOTSUPP; |
494 | } | 516 | } |
495 | 517 | ||
496 | static int tegra_pinconf_set(struct pinctrl_dev *pctldev, | 518 | static int tegra_pinconf_set(struct pinctrl_dev *pctldev, |
497 | unsigned pin, unsigned long config) | 519 | unsigned pin, unsigned long config) |
498 | { | 520 | { |
521 | dev_err(pctldev->dev, "pin_config_set op not supported\n"); | ||
499 | return -ENOTSUPP; | 522 | return -ENOTSUPP; |
500 | } | 523 | } |
501 | 524 | ||
@@ -550,8 +573,10 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, | |||
550 | 573 | ||
551 | /* LOCK can't be cleared */ | 574 | /* LOCK can't be cleared */ |
552 | if (param == TEGRA_PINCONF_PARAM_LOCK) { | 575 | if (param == TEGRA_PINCONF_PARAM_LOCK) { |
553 | if ((val & BIT(bit)) && !arg) | 576 | if ((val & BIT(bit)) && !arg) { |
577 | dev_err(pctldev->dev, "LOCK bit cannot be cleared\n"); | ||
554 | return -EINVAL; | 578 | return -EINVAL; |
579 | } | ||
555 | } | 580 | } |
556 | 581 | ||
557 | /* Special-case Boolean values; allow any non-zero as true */ | 582 | /* Special-case Boolean values; allow any non-zero as true */ |
@@ -560,8 +585,12 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, | |||
560 | 585 | ||
561 | /* Range-check user-supplied value */ | 586 | /* Range-check user-supplied value */ |
562 | mask = (1 << width) - 1; | 587 | mask = (1 << width) - 1; |
563 | if (arg & ~mask) | 588 | if (arg & ~mask) { |
589 | dev_err(pctldev->dev, | ||
590 | "config %lx: %x too big for %d bit register\n", | ||
591 | config, arg, width); | ||
564 | return -EINVAL; | 592 | return -EINVAL; |
593 | } | ||
565 | 594 | ||
566 | /* Update register */ | 595 | /* Update register */ |
567 | val &= ~(mask << bit); | 596 | val &= ~(mask << bit); |