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>
This commit is contained in:
parent
3881c4a56e
commit
ad63da85f4
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue