summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2017-12-02 06:23:09 -0500
committerLinus Walleij <linus.walleij@linaro.org>2017-12-07 03:59:26 -0500
commitad63da85f45fa55c270e5681e9b985605ec51f8d (patch)
tree004fb4c10fa490e08713dde7118cff5ed45e24b8
parent3881c4a56e5941c21c08d9476c68d2cc65005f68 (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.txt3
-rw-r--r--drivers/pinctrl/pinctrl-gemini.c81
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
18Supported configurations: 18Supported 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
21Example: 24Example:
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 */
71struct gemini_pin_group { 74struct 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
2410static 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
2397static const struct pinconf_ops gemini_pinconf_ops = { 2477static 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