Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad63da85 authored by Linus Walleij's avatar Linus Walleij
Browse files

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: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 3881c4a5
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,9 @@ and generic pin config nodes.


Supported configurations:
Supported configurations:
- skew-delay is supported on the Ethernet pins
- 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:
Example:


+81 −0
Original line number Original line Diff line number Diff line
@@ -67,6 +67,9 @@ struct gemini_pmx {
 *	elements in .pins so we can iterate over that array
 *	elements in .pins so we can iterate over that array
 * @mask: bits to clear to enable this when doing pin muxing
 * @mask: bits to clear to enable this when doing pin muxing
 * @value: bits to set 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 {
struct gemini_pin_group {
	const char *name;
	const char *name;
@@ -74,12 +77,14 @@ struct gemini_pin_group {
	const unsigned int num_pins;
	const unsigned int num_pins;
	u32 mask;
	u32 mask;
	u32 value;
	u32 value;
	u32 driving_mask;
};
};


/* Some straight-forward control registers */
/* Some straight-forward control registers */
#define GLOBAL_WORD_ID		0x00
#define GLOBAL_WORD_ID		0x00
#define GLOBAL_STATUS		0x04
#define GLOBAL_STATUS		0x04
#define GLOBAL_STATUS_FLPIN	BIT(20)
#define GLOBAL_STATUS_FLPIN	BIT(20)
#define GLOBAL_IODRIVE		0x10
#define GLOBAL_GMAC_CTRL_SKEW	0x1c
#define GLOBAL_GMAC_CTRL_SKEW	0x1c
#define GLOBAL_GMAC0_DATA_SKEW	0x20
#define GLOBAL_GMAC0_DATA_SKEW	0x20
#define GLOBAL_GMAC1_DATA_SKEW	0x24
#define GLOBAL_GMAC1_DATA_SKEW	0x24
@@ -738,6 +743,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
		/* Conflict with all flash usage */
		/* Conflict with all flash usage */
		.value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
		.value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
			PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
			PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
		.driving_mask = GENMASK(21, 20),
	},
	},
	{
	{
		.name = "satagrp",
		.name = "satagrp",
@@ -753,6 +759,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
		.name = "gmii_gmac0_grp",
		.name = "gmii_gmac0_grp",
		.pins = gmii_gmac0_3512_pins,
		.pins = gmii_gmac0_3512_pins,
		.num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins),
		.num_pins = ARRAY_SIZE(gmii_gmac0_3512_pins),
		.driving_mask = GENMASK(17, 16),
	},
	},
	{
	{
		.name = "gmii_gmac1_grp",
		.name = "gmii_gmac1_grp",
@@ -760,6 +767,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
		.num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins),
		.num_pins = ARRAY_SIZE(gmii_gmac1_3512_pins),
		/* Bring out RGMII on the GMAC1 pins */
		/* Bring out RGMII on the GMAC1 pins */
		.value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
		.value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
		.driving_mask = GENMASK(19, 18),
	},
	},
	{
	{
		.name = "pcigrp",
		.name = "pcigrp",
@@ -767,6 +775,7 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
		.num_pins = ARRAY_SIZE(pci_3512_pins),
		.num_pins = ARRAY_SIZE(pci_3512_pins),
		/* Conflict only with GPIO2 */
		/* Conflict only with GPIO2 */
		.value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
		.value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
		.driving_mask = GENMASK(23, 22),
	},
	},
	{
	{
		.name = "lpcgrp",
		.name = "lpcgrp",
@@ -1671,6 +1680,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
		/* Conflict with all flash usage */
		/* Conflict with all flash usage */
		.value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
		.value = IDE_PADS_ENABLE | NAND_PADS_DISABLE |
			PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
			PFLASH_PADS_DISABLE | SFLASH_PADS_DISABLE,
		.driving_mask = GENMASK(21, 20),
	},
	},
	{
	{
		.name = "satagrp",
		.name = "satagrp",
@@ -1686,6 +1696,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
		.name = "gmii_gmac0_grp",
		.name = "gmii_gmac0_grp",
		.pins = gmii_gmac0_3516_pins,
		.pins = gmii_gmac0_3516_pins,
		.num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins),
		.num_pins = ARRAY_SIZE(gmii_gmac0_3516_pins),
		.driving_mask = GENMASK(17, 16),
	},
	},
	{
	{
		.name = "gmii_gmac1_grp",
		.name = "gmii_gmac1_grp",
@@ -1693,6 +1704,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
		.num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins),
		.num_pins = ARRAY_SIZE(gmii_gmac1_3516_pins),
		/* Bring out RGMII on the GMAC1 pins */
		/* Bring out RGMII on the GMAC1 pins */
		.value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
		.value = GEMINI_GMAC_IOSEL_GMAC0_GMAC1_RGMII,
		.driving_mask = GENMASK(19, 18),
	},
	},
	{
	{
		.name = "pcigrp",
		.name = "pcigrp",
@@ -1700,6 +1712,7 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
		.num_pins = ARRAY_SIZE(pci_3516_pins),
		.num_pins = ARRAY_SIZE(pci_3516_pins),
		/* Conflict only with GPIO2 */
		/* Conflict only with GPIO2 */
		.value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
		.value = PCI_PADS_ENABLE | PCI_CLK_PAD_ENABLE,
		.driving_mask = GENMASK(23, 22),
	},
	},
	{
	{
		.name = "lpcgrp",
		.name = "lpcgrp",
@@ -2394,9 +2407,77 @@ static int gemini_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
	return ret;
	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 = {
static const struct pinconf_ops gemini_pinconf_ops = {
	.pin_config_get = gemini_pinconf_get,
	.pin_config_get = gemini_pinconf_get,
	.pin_config_set = gemini_pinconf_set,
	.pin_config_set = gemini_pinconf_set,
	.pin_config_group_set = gemini_pinconf_group_set,
	.is_generic = true,
	.is_generic = true,
};
};