Each GPIO18A/GPIO18B ball has its own IO control register starting at SCU 0x480, providing a 4-bit drive strength selector (3 mA to 41 mA in hardware-defined steps), a bias enable bit and a pull direction bit.
Extend the group table with the pin members of the ball-backed groups so bias-disable, bias-pull-down, bias-pull-up and drive-strength properties can be applied per group as well as per pin. The routing groups (USB, JTAG, PCIe RC) have no package balls and reject pin configuration with -ENOTSUPP. Select PINCONF so the generic pinctrl framework parses the pin configuration properties. Signed-off-by: Billy Tsai <[email protected]> --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/aspeed/pinctrl_ast2700_soc0.c | 205 +++++++++++++++++++++----- 2 files changed, 172 insertions(+), 34 deletions(-) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 35b3f3afa66..254da75d144 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -381,6 +381,7 @@ config ASPEED_AST2600_PINCTRL config ASPEED_AST2700_SOC0_PINCTRL bool "Aspeed AST2700 SoC0 pin control driver" depends on DM && PINCTRL_GENERIC && ASPEED_AST2700 + select PINCONF default y help Support pin multiplexing control on Aspeed ast2700 SoC0. The driver diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2700_soc0.c b/drivers/pinctrl/aspeed/pinctrl_ast2700_soc0.c index 9a973285b0b..b5111d7ee15 100644 --- a/drivers/pinctrl/aspeed/pinctrl_ast2700_soc0.c +++ b/drivers/pinctrl/aspeed/pinctrl_ast2700_soc0.c @@ -18,6 +18,24 @@ #define SCU404 0x404 #define SCU408 0x408 #define SCU410 0x410 +/* One IO control register per ball, GPIO18A0..GPIO18B3 */ +#define SCU480 0x480 + +/* Indexes into ast2700_soc0_pins[], in GPIO18A0..GPIO18B3 order */ +enum { + AC14, + AE15, + AD14, + AE14, + AF14, + AB13, + AB14, + AF15, + AF13, + AC13, + AD13, + AE13, +}; #define USB_PORTA_ROUTE BIT(9) #define USB_PORTB_ROUTE BIT(10) @@ -62,38 +80,72 @@ struct ast2700_soc0_pinctrl_priv { void __iomem *base; }; -static const char * const ast2700_soc0_groups[] = { - "EMMCG1", - "EMMCG4", - "EMMCG8", - "EMMCWPN", - "EMMCCDN", - "VGADDC", - "VB1", - "VB0", - "TSPRSTN", - "UFSCLKI", - "USB3A", - "USB3AAP", - "USB3ABP", - "USB3B", - "USB3BAP", - "USB3BBP", - "USB2A", - "USB2AAP", - "USB2ABP", - "USB2ADAP", - "USB2AH", - "USB2AHAP", - "USB2B", - "USB2BBP", - "USB2BAP", - "USB2BDBP", - "USB2BH", - "USB2BHBP", - "JTAG0", - "PCIERC0PERST", - "PCIERC1PERST", +struct ast2700_soc0_group { + const char *name; + const u8 *pins; + unsigned int npins; +}; + +static const u8 ast2700_soc0_emmcg1_pins[] = { AC14, AE15, AD14 }; +static const u8 ast2700_soc0_emmcg4_pins[] = { + AC14, AE15, AD14, AE14, AF14, AB13, +}; + +static const u8 ast2700_soc0_emmcg8_pins[] = { + AC14, AE15, AD14, AE14, AF14, AB13, AF13, AC13, AD13, AE13, +}; + +static const u8 ast2700_soc0_emmcwpn_pins[] = { AF15 }; +static const u8 ast2700_soc0_emmccdn_pins[] = { AB14 }; +static const u8 ast2700_soc0_vgaddc_pins[] = { AD13, AE13 }; +static const u8 ast2700_soc0_vb1_pins[] = { AC14, AE15, AD14, AE14 }; +static const u8 ast2700_soc0_vb0_pins[] = { AF15, AB14, AF13, AC13 }; +static const u8 ast2700_soc0_tsprstn_pins[] = { AF13 }; +static const u8 ast2700_soc0_ufsclki_pins[] = { AC13 }; + +#define AST2700_SOC0_GROUP(_name, _pins) \ + { \ + .name = _name, \ + .pins = _pins, \ + .npins = ARRAY_SIZE(_pins), \ + } + +/* + * The USB, JTAG and PCIe RC groups control internal routing only; they + * have no package balls, hence no group pins to configure. + */ +static const struct ast2700_soc0_group ast2700_soc0_groups[] = { + AST2700_SOC0_GROUP("EMMCG1", ast2700_soc0_emmcg1_pins), + AST2700_SOC0_GROUP("EMMCG4", ast2700_soc0_emmcg4_pins), + AST2700_SOC0_GROUP("EMMCG8", ast2700_soc0_emmcg8_pins), + AST2700_SOC0_GROUP("EMMCWPN", ast2700_soc0_emmcwpn_pins), + AST2700_SOC0_GROUP("EMMCCDN", ast2700_soc0_emmccdn_pins), + AST2700_SOC0_GROUP("VGADDC", ast2700_soc0_vgaddc_pins), + AST2700_SOC0_GROUP("VB1", ast2700_soc0_vb1_pins), + AST2700_SOC0_GROUP("VB0", ast2700_soc0_vb0_pins), + AST2700_SOC0_GROUP("TSPRSTN", ast2700_soc0_tsprstn_pins), + AST2700_SOC0_GROUP("UFSCLKI", ast2700_soc0_ufsclki_pins), + { "USB3A" }, + { "USB3AAP" }, + { "USB3ABP" }, + { "USB3B" }, + { "USB3BAP" }, + { "USB3BBP" }, + { "USB2A" }, + { "USB2AAP" }, + { "USB2ABP" }, + { "USB2ADAP" }, + { "USB2AH" }, + { "USB2AHAP" }, + { "USB2B" }, + { "USB2BBP" }, + { "USB2BAP" }, + { "USB2BDBP" }, + { "USB2BH" }, + { "USB2BHBP" }, + { "JTAG0" }, + { "PCIERC0PERST" }, + { "PCIERC1PERST" }, }; static const char * const ast2700_soc0_functions[] = { @@ -354,7 +406,7 @@ static int ast2700_soc0_pinctrl_get_groups_count(struct udevice *dev) static const char *ast2700_soc0_pinctrl_get_group_name(struct udevice *dev, unsigned int selector) { - return ast2700_soc0_groups[selector]; + return ast2700_soc0_groups[selector].name; } static int ast2700_soc0_pinctrl_get_functions_count(struct udevice *dev) @@ -383,7 +435,7 @@ static int ast2700_soc0_pinctrl_group_set(struct udevice *dev, return -EINVAL; function = ast2700_soc0_functions[func_selector]; - group = ast2700_soc0_groups[group_selector]; + group = ast2700_soc0_groups[group_selector].name; for (i = 0; i < ARRAY_SIZE(ast2700_soc0_pinmuxes); i++) { pinmux = &ast2700_soc0_pinmuxes[i]; @@ -458,6 +510,87 @@ static int ast2700_soc0_pinctrl_get_pin_muxing(struct udevice *dev, return 0; } +/* Drive strength in mA selectable by the IO control register [3:0] */ +static const u8 ast2700_soc0_drv_ma[] = { + 3, 6, 8, 11, 16, 18, 20, 23, 30, 32, 33, 35, 37, 38, 39, 41, +}; + +static const struct pinconf_param ast2700_soc0_pinconf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 }, + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, +}; + +static int ast2700_soc0_pinctrl_pinconf_set(struct udevice *dev, + unsigned int selector, + unsigned int param, + unsigned int arg) +{ + struct ast2700_soc0_pinctrl_priv *priv = dev_get_priv(dev); + u32 mask, val, i; + + if (selector >= ARRAY_SIZE(ast2700_soc0_pins)) + return -EINVAL; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + mask = BIT(5); + val = 0; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + mask = GENMASK(5, 4); + val = 2 << 4; + break; + case PIN_CONFIG_BIAS_PULL_UP: + mask = GENMASK(5, 4); + val = 3 << 4; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + for (i = 0; i < ARRAY_SIZE(ast2700_soc0_drv_ma); i++) { + if (ast2700_soc0_drv_ma[i] == arg) + break; + } + if (i == ARRAY_SIZE(ast2700_soc0_drv_ma)) + return -EINVAL; + mask = GENMASK(3, 0); + val = i; + break; + default: + return -ENOTSUPP; + } + + clrsetbits_le32(priv->base + SCU480 + selector * 4, mask, val); + + return 0; +} + +static int ast2700_soc0_pinctrl_pinconf_group_set(struct udevice *dev, + unsigned int selector, + unsigned int param, + unsigned int arg) +{ + const struct ast2700_soc0_group *group; + u32 i; + int ret; + + if (selector >= ARRAY_SIZE(ast2700_soc0_groups)) + return -EINVAL; + + group = &ast2700_soc0_groups[selector]; + if (!group->npins) + return -ENOTSUPP; + + for (i = 0; i < group->npins; i++) { + ret = ast2700_soc0_pinctrl_pinconf_set(dev, group->pins[i], + param, arg); + if (ret) + return ret; + } + + return 0; +} + static const struct pinctrl_ops ast2700_soc0_pinctrl_ops = { .set_state = pinctrl_generic_set_state, .get_pins_count = ast2700_soc0_pinctrl_get_pins_count, @@ -469,6 +602,10 @@ static const struct pinctrl_ops ast2700_soc0_pinctrl_ops = { .get_function_name = ast2700_soc0_pinctrl_get_function_name, .pinmux_group_set = ast2700_soc0_pinctrl_group_set, .gpio_request_enable = ast2700_soc0_pinctrl_gpio_request_enable, + .pinconf_num_params = ARRAY_SIZE(ast2700_soc0_pinconf_params), + .pinconf_params = ast2700_soc0_pinconf_params, + .pinconf_set = ast2700_soc0_pinctrl_pinconf_set, + .pinconf_group_set = ast2700_soc0_pinctrl_pinconf_group_set, }; static const struct udevice_id ast2700_soc0_pinctrl_ids[] = { -- 2.34.1

