diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2017-12-02 06:23:09 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-12-07 03:59:26 -0500 |
commit | ad63da85f45fa55c270e5681e9b985605ec51f8d (patch) | |
tree | 004fb4c10fa490e08713dde7118cff5ed45e24b8 | |
parent | 3881c4a56e5941c21c08d9476c68d2cc65005f68 (diff) |
pinctrl: gemini: Support drive strength setting
The Gemini pin controller can set drive strength for a few
select groups of pins (not individually). Implement this
for GMAC0 and 1 (ethernet ports), IDE and PCI.
Cc: devicetree@vger.kernel.org
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt | 3 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-gemini.c | 81 |
2 files changed, 84 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt index d857b67fab72..4346ff2dd8e6 100644 --- a/Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt | |||
@@ -17,6 +17,9 @@ and generic pin config nodes. | |||
17 | 17 | ||
18 | Supported configurations: | 18 | Supported configurations: |
19 | - skew-delay is supported on the Ethernet pins | 19 | - skew-delay is supported on the Ethernet pins |
20 | - drive-strength with 4, 8, 12 or 16 mA as argument is supported for | ||
21 | entire groups on the groups "idegrp", "gmii_gmac0_grp", "gmii_gmac1_grp" | ||
22 | and "pcigrp". | ||
20 | 23 | ||
21 | Example: | 24 | Example: |
22 | 25 | ||
diff --git a/drivers/pinctrl/pinctrl-gemini.c b/drivers/pinctrl/pinctrl-gemini.c index 10f8f3a35fe1..5e789753f945 100644 --- a/drivers/pinctrl/pinctrl-gemini.c +++ b/drivers/pinctrl/pinctrl-gemini.c | |||
@@ -67,6 +67,9 @@ struct gemini_pmx { | |||
67 | * elements in .pins so we can iterate over that array | 67 | * elements in .pins so we can iterate over that array |
68 | * @mask: bits to clear to enable this when doing pin muxing | 68 | * @mask: bits to clear to enable this when doing pin muxing |
69 | * @value: bits to set to enable this when doing pin muxing | 69 | * @value: bits to set to enable this when doing pin muxing |
70 | * @driving_mask: bitmask for the IO Pad driving register for this | ||
71 | * group, if it supports altering the driving strength of | ||
72 | * its lines. | ||
70 | */ | 73 | */ |
71 | struct gemini_pin_group { | 74 | struct gemini_pin_group { |
72 | const char *name; | 75 | const char *name; |
@@ -74,12 +77,14 @@ struct gemini_pin_group { | |||
74 | const unsigned int num_pins; | 77 | const unsigned int num_pins; |
75 | u32 mask; | 78 | u32 mask; |
76 | u32 value; | 79 | u32 value; |
80 | u32 driving_mask; | ||
77 | }; | 81 | }; |
78 | 82 | ||
79 | /* Some straight-forward control registers */ | 83 | /* Some straight-forward control registers */ |
80 | #define GLOBAL_WORD_ID 0x00 | 84 | #define GLOBAL_WORD_ID 0x00 |
81 | #define GLOBAL_STATUS 0x04 | 85 | #define GLOBAL_STATUS 0x04 |
82 | #define GLOBAL_STATUS_FLPIN BIT(20) | 86 | #define GLOBAL_STATUS_FLPIN BIT(20) |
87 | #define GLOBAL_IODRIVE 0x10 | ||
83 | #define GLOBAL_GMAC_CTRL_SKEW 0x1c | 88 | #define GLOBAL_GMAC_CTRL_SKEW 0x1c |
84 | #define GLOBAL_GMAC0_DATA_SKEW 0x20 | 89 | #define GLOBAL_GMAC0_DATA_SKEW 0x20 |
85 | #define GLOBAL_GMAC1_DATA_SKEW 0x24 | 90 | #define GLOBAL_GMAC1_DATA_SKEW 0x24 |
@@ -738,6 +743,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = { | |||
738 | /* Conflict with all flash usage */ | 743 | /* Conflict with all flash usage */ |
739 | .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE | | 744 | .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE | |
740 | PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE, | 745 | PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE, |
746 | .driving_mask = GENMASK(21, 20), | ||
741 | }, | 747 | }, |
742 | { | 748 | { |
743 | .name = "satagrp", | 749 | .name = "satagrp", |
@@ -753,6 +759,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = { | |||
753 | .name = "gmii_gmac0_grp", | 759 | .name = "gmii_gmac0_grp", |
754 | .pins = gmii_gmac0_3512_pins, | 760 | .pins = gmii_gmac0_3512_pins, |
755 | .num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins), | 761 | .num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins), |
762 | .driving_mask = GENMASK(17, 16), | ||
756 | }, | 763 | }, |
757 | { | 764 | { |
758 | .name = "gmii_gmac1_grp", | 765 | .name = "gmii_gmac1_grp", |
@@ -760,6 +767,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = { | |||
760 | .num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins), | 767 | .num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins), |
761 | /* Bring out RGMII on the GMAC1 pins */ | 768 | /* Bring out RGMII on the GMAC1 pins */ |
762 | .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII, | 769 | .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII, |
770 | .driving_mask = GENMASK(19, 18), | ||
763 | }, | 771 | }, |
764 | { | 772 | { |
765 | .name = "pcigrp", | 773 | .name = "pcigrp", |
@@ -767,6 +775,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = { | |||
767 | .num_pins = ARRAY_SIZE(pci_3512_pins), | 775 | .num_pins = ARRAY_SIZE(pci_3512_pins), |
768 | /* Conflict only with GPIO2 */ | 776 | /* Conflict only with GPIO2 */ |
769 | .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE, | 777 | .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE, |
778 | .driving_mask = GENMASK(23, 22), | ||
770 | }, | 779 | }, |
771 | { | 780 | { |
772 | .name = "lpcgrp", | 781 | .name = "lpcgrp", |
@@ -1671,6 +1680,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = { | |||
1671 | /* Conflict with all flash usage */ | 1680 | /* Conflict with all flash usage */ |
1672 | .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE | | 1681 | .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE | |
1673 | PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE, | 1682 | PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE, |
1683 | .driving_mask = GENMASK(21, 20), | ||
1674 | }, | 1684 | }, |
1675 | { | 1685 | { |
1676 | .name = "satagrp", | 1686 | .name = "satagrp", |
@@ -1686,6 +1696,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = { | |||
1686 | .name = "gmii_gmac0_grp", | 1696 | .name = "gmii_gmac0_grp", |
1687 | .pins = gmii_gmac0_3516_pins, | 1697 | .pins = gmii_gmac0_3516_pins, |
1688 | .num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins), | 1698 | .num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins), |
1699 | .driving_mask = GENMASK(17, 16), | ||
1689 | }, | 1700 | }, |
1690 | { | 1701 | { |
1691 | .name = "gmii_gmac1_grp", | 1702 | .name = "gmii_gmac1_grp", |
@@ -1693,6 +1704,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = { | |||
1693 | .num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins), | 1704 | .num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins), |
1694 | /* Bring out RGMII on the GMAC1 pins */ | 1705 | /* Bring out RGMII on the GMAC1 pins */ |
1695 | .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII, | 1706 | .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII, |
1707 | .driving_mask = GENMASK(19, 18), | ||
1696 | }, | 1708 | }, |
1697 | { | 1709 | { |
1698 | .name = "pcigrp", | 1710 | .name = "pcigrp", |
@@ -1700,6 +1712,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = { | |||
1700 | .num_pins = ARRAY_SIZE(pci_3516_pins), | 1712 | .num_pins = ARRAY_SIZE(pci_3516_pins), |
1701 | /* Conflict only with GPIO2 */ | 1713 | /* Conflict only with GPIO2 */ |
1702 | .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE, | 1714 | .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE, |
1715 | .driving_mask = GENMASK(23, 22), | ||
1703 | }, | 1716 | }, |
1704 | { | 1717 | { |
1705 | .name = "lpcgrp", | 1718 | .name = "lpcgrp", |
@@ -2394,9 +2407,77 @@ static int gemini_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, | |||
2394 | return ret; | 2407 | return ret; |
2395 | } | 2408 | } |
2396 | 2409 | ||
2410 | static int gemini_pinconf_group_set(struct pinctrl_dev *pctldev, | ||
2411 | unsigned selector, | ||
2412 | unsigned long *configs, | ||
2413 | unsigned num_configs) | ||
2414 | { | ||
2415 | struct gemini_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
2416 | const struct gemini_pin_group *grp = NULL; | ||
2417 | enum pin_config_param param; | ||
2418 | u32 arg; | ||
2419 | u32 val; | ||
2420 | int i; | ||
2421 | |||
2422 | if (pmx->is_3512) | ||
2423 | grp = &gemini_3512_pin_groups[selector]; | ||
2424 | if (pmx->is_3516) | ||
2425 | grp = &gemini_3516_pin_groups[selector]; | ||
2426 | |||
2427 | /* First figure out if this group supports configs */ | ||
2428 | if (!grp->driving_mask) { | ||
2429 | dev_err(pmx->dev, "pin config group \"%s\" does " | ||
2430 | "not support drive strength setting\n", | ||
2431 | grp->name); | ||
2432 | return -EINVAL; | ||
2433 | } | ||
2434 | |||
2435 | for (i = 0; i < num_configs; i++) { | ||
2436 | param = pinconf_to_config_param(configs[i]); | ||
2437 | arg = pinconf_to_config_argument(configs[i]); | ||
2438 | |||
2439 | switch (param) { | ||
2440 | case PIN_CONFIG_DRIVE_STRENGTH: | ||
2441 | switch (arg) { | ||
2442 | case 4: | ||
2443 | val = 0; | ||
2444 | break; | ||
2445 | case 8: | ||
2446 | val = 1; | ||
2447 | break; | ||
2448 | case 12: | ||
2449 | val = 2; | ||
2450 | break; | ||
2451 | case 16: | ||
2452 | val = 3; | ||
2453 | break; | ||
2454 | default: | ||
2455 | dev_err(pmx->dev, | ||
2456 | "invalid drive strength %d mA\n", | ||
2457 | arg); | ||
2458 | return -ENOTSUPP; | ||
2459 | } | ||
2460 | val <<= (ffs(grp->driving_mask) - 1); | ||
2461 | regmap_update_bits(pmx->map, GLOBAL_IODRIVE, | ||
2462 | grp->driving_mask, | ||
2463 | val); | ||
2464 | dev_info(pmx->dev, | ||
2465 | "set group %s to %d mA drive strength mask %08x val %08x\n", | ||
2466 | grp->name, arg, grp->driving_mask, val); | ||
2467 | break; | ||
2468 | default: | ||
2469 | dev_err(pmx->dev, "invalid config param %04x\n", param); | ||
2470 | return -ENOTSUPP; | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | return 0; | ||
2475 | } | ||
2476 | |||
2397 | static const struct pinconf_ops gemini_pinconf_ops = { | 2477 | static const struct pinconf_ops gemini_pinconf_ops = { |
2398 | .pin_config_get = gemini_pinconf_get, | 2478 | .pin_config_get = gemini_pinconf_get, |
2399 | .pin_config_set = gemini_pinconf_set, | 2479 | .pin_config_set = gemini_pinconf_set, |
2480 | .pin_config_group_set = gemini_pinconf_group_set, | ||
2400 | .is_generic = true, | 2481 | .is_generic = true, |
2401 | }; | 2482 | }; |
2402 | 2483 | ||