diff options
author | Jingchang Lu <b35083@freescale.com> | 2013-05-28 05:32:07 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-06-16 05:56:51 -0400 |
commit | bf5a530971afbe959348af4d84d17636108e6abf (patch) | |
tree | a40a88483b1d5210d8401636a83443b4b59a2c82 /drivers/pinctrl/pinctrl-imx.c | |
parent | 7bbc87b801fcaa817d828fdaa0ca8c6d223a1347 (diff) |
pinctrl: imx: add VF610 support to imx pinctrl framework
On some platforms such as VF610, offset of mux and pad ctrl register
may be zero, and the mux_mode and config_val are in one 32-bit register.
This patch adds support to imx core pinctrl framework to handle these
cases.
Signed-off-by: Jingchang Lu <b35083@freescale.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-imx.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-imx.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index 4fcfff9243be..57a4eb0add2e 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c | |||
@@ -221,13 +221,21 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, | |||
221 | pin_id = pins[i]; | 221 | pin_id = pins[i]; |
222 | pin_reg = &info->pin_regs[pin_id]; | 222 | pin_reg = &info->pin_regs[pin_id]; |
223 | 223 | ||
224 | if (!pin_reg->mux_reg) { | 224 | if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->mux_reg) { |
225 | dev_err(ipctl->dev, "Pin(%s) does not support mux function\n", | 225 | dev_err(ipctl->dev, "Pin(%s) does not support mux function\n", |
226 | info->pins[pin_id].name); | 226 | info->pins[pin_id].name); |
227 | return -EINVAL; | 227 | return -EINVAL; |
228 | } | 228 | } |
229 | 229 | ||
230 | writel(mux[i], ipctl->base + pin_reg->mux_reg); | 230 | if (info->flags & SHARE_MUX_CONF_REG) { |
231 | u32 reg; | ||
232 | reg = readl(ipctl->base + pin_reg->mux_reg); | ||
233 | reg &= ~(0x7 << 20); | ||
234 | reg |= (mux[i] << 20); | ||
235 | writel(reg, ipctl->base + pin_reg->mux_reg); | ||
236 | } else { | ||
237 | writel(mux[i], ipctl->base + pin_reg->mux_reg); | ||
238 | } | ||
231 | dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n", | 239 | dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n", |
232 | pin_reg->mux_reg, mux[i]); | 240 | pin_reg->mux_reg, mux[i]); |
233 | 241 | ||
@@ -287,7 +295,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev, | |||
287 | const struct imx_pinctrl_soc_info *info = ipctl->info; | 295 | const struct imx_pinctrl_soc_info *info = ipctl->info; |
288 | const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; | 296 | const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; |
289 | 297 | ||
290 | if (!pin_reg->conf_reg) { | 298 | if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) { |
291 | dev_err(info->dev, "Pin(%s) does not support config function\n", | 299 | dev_err(info->dev, "Pin(%s) does not support config function\n", |
292 | info->pins[pin_id].name); | 300 | info->pins[pin_id].name); |
293 | return -EINVAL; | 301 | return -EINVAL; |
@@ -295,6 +303,9 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev, | |||
295 | 303 | ||
296 | *config = readl(ipctl->base + pin_reg->conf_reg); | 304 | *config = readl(ipctl->base + pin_reg->conf_reg); |
297 | 305 | ||
306 | if (info->flags & SHARE_MUX_CONF_REG) | ||
307 | *config &= 0xffff; | ||
308 | |||
298 | return 0; | 309 | return 0; |
299 | } | 310 | } |
300 | 311 | ||
@@ -305,7 +316,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev, | |||
305 | const struct imx_pinctrl_soc_info *info = ipctl->info; | 316 | const struct imx_pinctrl_soc_info *info = ipctl->info; |
306 | const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; | 317 | const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; |
307 | 318 | ||
308 | if (!pin_reg->conf_reg) { | 319 | if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) { |
309 | dev_err(info->dev, "Pin(%s) does not support config function\n", | 320 | dev_err(info->dev, "Pin(%s) does not support config function\n", |
310 | info->pins[pin_id].name); | 321 | info->pins[pin_id].name); |
311 | return -EINVAL; | 322 | return -EINVAL; |
@@ -314,7 +325,15 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev, | |||
314 | dev_dbg(ipctl->dev, "pinconf set pin %s\n", | 325 | dev_dbg(ipctl->dev, "pinconf set pin %s\n", |
315 | info->pins[pin_id].name); | 326 | info->pins[pin_id].name); |
316 | 327 | ||
317 | writel(config, ipctl->base + pin_reg->conf_reg); | 328 | if (info->flags & SHARE_MUX_CONF_REG) { |
329 | u32 reg; | ||
330 | reg = readl(ipctl->base + pin_reg->conf_reg); | ||
331 | reg &= ~0xffff; | ||
332 | reg |= config; | ||
333 | writel(reg, ipctl->base + pin_reg->conf_reg); | ||
334 | } else { | ||
335 | writel(config, ipctl->base + pin_reg->conf_reg); | ||
336 | } | ||
318 | dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n", | 337 | dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n", |
319 | pin_reg->conf_reg, config); | 338 | pin_reg->conf_reg, config); |
320 | 339 | ||
@@ -381,19 +400,24 @@ static struct pinctrl_desc imx_pinctrl_desc = { | |||
381 | * 1 u32 CONFIG, so 24 types in total for each pin. | 400 | * 1 u32 CONFIG, so 24 types in total for each pin. |
382 | */ | 401 | */ |
383 | #define FSL_PIN_SIZE 24 | 402 | #define FSL_PIN_SIZE 24 |
403 | #define SHARE_FSL_PIN_SIZE 20 | ||
384 | 404 | ||
385 | static int imx_pinctrl_parse_groups(struct device_node *np, | 405 | static int imx_pinctrl_parse_groups(struct device_node *np, |
386 | struct imx_pin_group *grp, | 406 | struct imx_pin_group *grp, |
387 | struct imx_pinctrl_soc_info *info, | 407 | struct imx_pinctrl_soc_info *info, |
388 | u32 index) | 408 | u32 index) |
389 | { | 409 | { |
390 | int size; | 410 | int size, pin_size; |
391 | const __be32 *list; | 411 | const __be32 *list; |
392 | int i; | 412 | int i; |
393 | u32 config; | 413 | u32 config; |
394 | 414 | ||
395 | dev_dbg(info->dev, "group(%d): %s\n", index, np->name); | 415 | dev_dbg(info->dev, "group(%d): %s\n", index, np->name); |
396 | 416 | ||
417 | if (info->flags & SHARE_MUX_CONF_REG) | ||
418 | pin_size = SHARE_FSL_PIN_SIZE; | ||
419 | else | ||
420 | pin_size = FSL_PIN_SIZE; | ||
397 | /* Initialise group */ | 421 | /* Initialise group */ |
398 | grp->name = np->name; | 422 | grp->name = np->name; |
399 | 423 | ||
@@ -403,12 +427,12 @@ static int imx_pinctrl_parse_groups(struct device_node *np, | |||
403 | */ | 427 | */ |
404 | list = of_get_property(np, "fsl,pins", &size); | 428 | list = of_get_property(np, "fsl,pins", &size); |
405 | /* we do not check return since it's safe node passed down */ | 429 | /* we do not check return since it's safe node passed down */ |
406 | if (!size || size % FSL_PIN_SIZE) { | 430 | if (!size || size % pin_size) { |
407 | dev_err(info->dev, "Invalid fsl,pins property\n"); | 431 | dev_err(info->dev, "Invalid fsl,pins property\n"); |
408 | return -EINVAL; | 432 | return -EINVAL; |
409 | } | 433 | } |
410 | 434 | ||
411 | grp->npins = size / FSL_PIN_SIZE; | 435 | grp->npins = size / pin_size; |
412 | grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), | 436 | grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), |
413 | GFP_KERNEL); | 437 | GFP_KERNEL); |
414 | grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), | 438 | grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), |
@@ -421,10 +445,17 @@ static int imx_pinctrl_parse_groups(struct device_node *np, | |||
421 | GFP_KERNEL); | 445 | GFP_KERNEL); |
422 | for (i = 0; i < grp->npins; i++) { | 446 | for (i = 0; i < grp->npins; i++) { |
423 | u32 mux_reg = be32_to_cpu(*list++); | 447 | u32 mux_reg = be32_to_cpu(*list++); |
424 | u32 conf_reg = be32_to_cpu(*list++); | 448 | u32 conf_reg; |
425 | unsigned int pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4; | 449 | unsigned int pin_id; |
426 | struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; | 450 | struct imx_pin_reg *pin_reg; |
427 | 451 | ||
452 | if (info->flags & SHARE_MUX_CONF_REG) | ||
453 | conf_reg = mux_reg; | ||
454 | else | ||
455 | conf_reg = be32_to_cpu(*list++); | ||
456 | |||
457 | pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4; | ||
458 | pin_reg = &info->pin_regs[pin_id]; | ||
428 | grp->pins[i] = pin_id; | 459 | grp->pins[i] = pin_id; |
429 | pin_reg->mux_reg = mux_reg; | 460 | pin_reg->mux_reg = mux_reg; |
430 | pin_reg->conf_reg = conf_reg; | 461 | pin_reg->conf_reg = conf_reg; |