| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- From f147cf49ef39f5e87d5df9ef1fab52683bc75c63 Mon Sep 17 00:00:00 2001
- From: Linus Walleij <[email protected]>
- Date: Sat, 2 Dec 2017 12:23:09 +0100
- Subject: [PATCH 11/31] 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: [email protected]
- Reviewed-by: Rob Herring <[email protected]>
- Signed-off-by: Linus Walleij <[email protected]>
- ---
- .../bindings/pinctrl/cortina,gemini-pinctrl.txt | 3 +
- drivers/pinctrl/pinctrl-gemini.c | 81 ++++++++++++++++++++++
- 2 files changed, 84 insertions(+)
- --- 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.
-
- Supported configurations:
- - skew-delay is supported on the Ethernet pins
- +- drive-strength with 4, 8, 12 or 16 mA as argument is supported for
- + entire groups on the groups "idegrp", "gmii_gmac0_grp", "gmii_gmac1_grp"
- + and "pcigrp".
-
- Example:
-
- --- a/drivers/pinctrl/pinctrl-gemini.c
- +++ b/drivers/pinctrl/pinctrl-gemini.c
- @@ -67,6 +67,9 @@ struct gemini_pmx {
- * elements in .pins so we can iterate over that array
- * @mask: bits to clear to enable this when doing pin muxing
- * @value: bits to set to enable this when doing pin muxing
- + * @driving_mask: bitmask for the IO Pad driving register for this
- + * group, if it supports altering the driving strength of
- + * its lines.
- */
- struct gemini_pin_group {
- const char *name;
- @@ -74,12 +77,14 @@ struct gemini_pin_group {
- const unsigned int num_pins;
- u32 mask;
- u32 value;
- + u32 driving_mask;
- };
-
- /* Some straight-forward control registers */
- #define GLOBAL_WORD_ID 0x00
- #define GLOBAL_STATUS 0x04
- #define GLOBAL_STATUS_FLPIN BIT(20)
- +#define GLOBAL_IODRIVE 0x10
- #define GLOBAL_GMAC_CTRL_SKEW 0x1c
- #define GLOBAL_GMAC0_DATA_SKEW 0x20
- #define GLOBAL_GMAC1_DATA_SKEW 0x24
- @@ -738,6 +743,7 @@ static const struct gemini_pin_group gem
- /* Conflict with all flash usage */
- .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
- PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
- + .driving_mask = GENMASK(21, 20),
- },
- {
- .name = "satagrp",
- @@ -753,6 +759,7 @@ static const struct gemini_pin_group gem
- .name = "gmii_gmac0_grp",
- .pins = gmii_gmac0_3512_pins,
- .num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins),
- + .driving_mask = GENMASK(17, 16),
- },
- {
- .name = "gmii_gmac1_grp",
- @@ -760,6 +767,7 @@ static const struct gemini_pin_group gem
- .num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins),
- /* Bring out RGMII on the GMAC1 pins */
- .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
- + .driving_mask = GENMASK(19, 18),
- },
- {
- .name = "pcigrp",
- @@ -767,6 +775,7 @@ static const struct gemini_pin_group gem
- .num_pins = ARRAY_SIZE(pci_3512_pins),
- /* Conflict only with GPIO2 */
- .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
- + .driving_mask = GENMASK(23, 22),
- },
- {
- .name = "lpcgrp",
- @@ -1671,6 +1680,7 @@ static const struct gemini_pin_group gem
- /* Conflict with all flash usage */
- .value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
- PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
- + .driving_mask = GENMASK(21, 20),
- },
- {
- .name = "satagrp",
- @@ -1686,6 +1696,7 @@ static const struct gemini_pin_group gem
- .name = "gmii_gmac0_grp",
- .pins = gmii_gmac0_3516_pins,
- .num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins),
- + .driving_mask = GENMASK(17, 16),
- },
- {
- .name = "gmii_gmac1_grp",
- @@ -1693,6 +1704,7 @@ static const struct gemini_pin_group gem
- .num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins),
- /* Bring out RGMII on the GMAC1 pins */
- .value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
- + .driving_mask = GENMASK(19, 18),
- },
- {
- .name = "pcigrp",
- @@ -1700,6 +1712,7 @@ static const struct gemini_pin_group gem
- .num_pins = ARRAY_SIZE(pci_3516_pins),
- /* Conflict only with GPIO2 */
- .value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
- + .driving_mask = GENMASK(23, 22),
- },
- {
- .name = "lpcgrp",
- @@ -2394,9 +2407,77 @@ static int gemini_pinconf_set(struct pin
- return ret;
- }
-
- +static int gemini_pinconf_group_set(struct pinctrl_dev *pctldev,
- + unsigned selector,
- + unsigned long *configs,
- + unsigned num_configs)
- +{
- + struct gemini_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- + const struct gemini_pin_group *grp = NULL;
- + enum pin_config_param param;
- + u32 arg;
- + u32 val;
- + int i;
- +
- + if (pmx->is_3512)
- + grp = &gemini_3512_pin_groups[selector];
- + if (pmx->is_3516)
- + grp = &gemini_3516_pin_groups[selector];
- +
- + /* First figure out if this group supports configs */
- + if (!grp->driving_mask) {
- + dev_err(pmx->dev, "pin config group \"%s\" does "
- + "not support drive strength setting\n",
- + grp->name);
- + return -EINVAL;
- + }
- +
- + for (i = 0; i < num_configs; i++) {
- + param = pinconf_to_config_param(configs[i]);
- + arg = pinconf_to_config_argument(configs[i]);
- +
- + switch (param) {
- + case PIN_CONFIG_DRIVE_STRENGTH:
- + switch (arg) {
- + case 4:
- + val = 0;
- + break;
- + case 8:
- + val = 1;
- + break;
- + case 12:
- + val = 2;
- + break;
- + case 16:
- + val = 3;
- + break;
- + default:
- + dev_err(pmx->dev,
- + "invalid drive strength %d mA\n",
- + arg);
- + return -ENOTSUPP;
- + }
- + val <<= (ffs(grp->driving_mask) - 1);
- + regmap_update_bits(pmx->map, GLOBAL_IODRIVE,
- + grp->driving_mask,
- + val);
- + dev_info(pmx->dev,
- + "set group %s to %d mA drive strength mask %08x val %08x\n",
- + grp->name, arg, grp->driving_mask, val);
- + break;
- + default:
- + dev_err(pmx->dev, "invalid config param %04x\n", param);
- + return -ENOTSUPP;
- + }
- + }
- +
- + return 0;
- +}
- +
- static const struct pinconf_ops gemini_pinconf_ops = {
- .pin_config_get = gemini_pinconf_get,
- .pin_config_set = gemini_pinconf_set,
- + .pin_config_group_set = gemini_pinconf_group_set,
- .is_generic = true,
- };
-
|