Commit 368b62f2 authored by Thierry Reding's avatar Thierry Reding Committed by Linus Walleij
Browse files

pinctrl: tegra: Add SFIO/GPIO programming on Tegra194



Prior to Tegra186, the selection of SFIO vs. GPIO modes was done as part
of the GPIO controller's register programming. Starting with Tegra186, a
pin is configured as GPIO or SFIO with a bit in a configuration register
of the pin controller.

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20200319122737.3063291-10-thierry.reding@gmail.com


Tested-by: default avatarVidya Sagar <vidyas@nvidia.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 103afc8e
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -275,11 +275,57 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev,
	return 0;
}

static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
					     struct pinctrl_gpio_range *range,
					     unsigned int offset)
{
	struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
	const struct tegra_pingroup *group;
	u32 value;

	if (!pmx->soc->sfsel_in_mux)
		return 0;

	group = &pmx->soc->groups[offset];

	if (group->mux_reg < 0 || group->sfsel_bit < 0)
		return -EINVAL;

	value = pmx_readl(pmx, group->mux_bank, group->mux_reg);
	value &= ~BIT(group->sfsel_bit);
	pmx_writel(pmx, value, group->mux_bank, group->mux_reg);

	return 0;
}

static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev,
					    struct pinctrl_gpio_range *range,
					    unsigned int offset)
{
	struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
	const struct tegra_pingroup *group;
	u32 value;

	if (!pmx->soc->sfsel_in_mux)
		return;

	group = &pmx->soc->groups[offset];

	if (group->mux_reg < 0 || group->sfsel_bit < 0)
		return;

	value = pmx_readl(pmx, group->mux_bank, group->mux_reg);
	value |= BIT(group->sfsel_bit);
	pmx_writel(pmx, value, group->mux_bank, group->mux_reg);
}

static const struct pinmux_ops tegra_pinmux_ops = {
	.get_functions_count = tegra_pinctrl_get_funcs_count,
	.get_function_name = tegra_pinctrl_get_func_name,
	.get_function_groups = tegra_pinctrl_get_func_groups,
	.set_mux = tegra_pinctrl_set_mux,
	.gpio_request_enable = tegra_pinctrl_gpio_request_enable,
	.gpio_disable_free = tegra_pinctrl_gpio_disable_free,
};

static int tegra_pinconf_reg(struct tegra_pmx *pmx,
+3 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct tegra_function {
 *			drvup, slwr, slwf, and drvtype parameters.
 * @drv_bank:		Drive fields register bank.
 * @hsm_bit:		High Speed Mode register bit.
 * @sfsel_bit:		GPIO/SFIO selection register bit.
 * @schmitt_bit:	Schmitt register bit.
 * @lpmd_bit:		Low Power Mode register bit.
 * @drvdn_bit:		Drive Down register bit.
@@ -153,6 +154,7 @@ struct tegra_pingroup {
	s32 ioreset_bit:6;
	s32 rcv_sel_bit:6;
	s32 hsm_bit:6;
	s32 sfsel_bit:6;
	s32 schmitt_bit:6;
	s32 lpmd_bit:6;
	s32 drvdn_bit:6;
@@ -192,6 +194,7 @@ struct tegra_pinctrl_soc_data {
	bool hsm_in_mux;
	bool schmitt_in_mux;
	bool drvtype_in_mux;
	bool sfsel_in_mux;
};

extern const struct dev_pm_ops tegra_pinctrl_pm;
+2 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ static struct tegra_function tegra194_functions[] = {
		.tri_bit = 4,					\
		.einput_bit = e_input,				\
		.odrain_bit = e_od,				\
		.sfsel_bit = 10,				\
		.schmitt_bit = schmitt_b,			\
		.drvtype_bit = 13,				\
		.drv_reg = -1,					\
@@ -140,6 +141,7 @@ static const struct tegra_pinctrl_soc_data tegra194_pinctrl = {
	.hsm_in_mux = true,
	.schmitt_in_mux = true,
	.drvtype_in_mux = true,
	.sfsel_in_mux = true,
};

static int tegra194_pinctrl_probe(struct platform_device *pdev)