Commit 3be6f651 authored by Dong Aisheng's avatar Dong Aisheng Committed by Linus Walleij
Browse files

pinctrl: imx: make imx_pmx_ops.gpio_set_direction platform specific callbacks



Various IMX platforms may have different imx_pmx_ops.gpio_set_direction
implementations, so let's make it platform specific callbacks instead of
the fixed common one.

Currently only VF610 platform implements it. No function level changes.

Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Shawn Guo <shawnguo@kernel.org>
Acked-by: default avatarStefan Agner <stefan@agner.ch>
Signed-off-by: default avatarDong Aisheng <aisheng.dong@nxp.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent a5c771e6
Loading
Loading
Loading
Loading
+4 −44
Original line number Diff line number Diff line
@@ -35,18 +35,6 @@
#define IMX_NO_PAD_CTL	0x80000000	/* no pin config need */
#define IMX_PAD_SION 0x40000000		/* set SION */

/**
 * @dev: a pointer back to containing device
 * @base: the offset to the controller in virtual memory
 */
struct imx_pinctrl {
	struct device *dev;
	struct pinctrl_dev *pctl;
	void __iomem *base;
	void __iomem *input_sel_base;
	struct imx_pinctrl_soc_info *info;
};

static inline const struct group_desc *imx_pinctrl_find_group_by_name(
				struct pinctrl_dev *pctldev,
				const char *name)
@@ -255,42 +243,11 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
	return 0;
}

static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
	   struct pinctrl_gpio_range *range, unsigned offset, bool input)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg;
	u32 reg;

	/*
	 * Only Vybrid has the input/output buffer enable flags (IBE/OBE)
	 * They are part of the shared mux/conf register.
	 */
	if (!(info->flags & SHARE_MUX_CONF_REG))
		return 0;

	pin_reg = &info->pin_regs[offset];
	if (pin_reg->mux_reg == -1)
		return -EINVAL;

	/* IBE always enabled allows us to read the value "on the wire" */
	reg = readl(ipctl->base + pin_reg->mux_reg);
	if (input)
		reg &= ~0x2;
	else
		reg |= 0x2;
	writel(reg, ipctl->base + pin_reg->mux_reg);

	return 0;
}

static const struct pinmux_ops imx_pmx_ops = {
struct pinmux_ops imx_pmx_ops = {
	.get_functions_count = pinmux_generic_get_function_count,
	.get_function_name = pinmux_generic_get_function_name,
	.get_function_groups = pinmux_generic_get_function_groups,
	.set_mux = imx_pmx_set,
	.gpio_set_direction = imx_pmx_gpio_set_direction,
};

/* decode generic config into raw register values */
@@ -793,6 +750,9 @@ int imx_pinctrl_probe(struct platform_device *pdev,
	imx_pinctrl_desc->custom_params = info->custom_params;
	imx_pinctrl_desc->num_custom_params = info->num_custom_params;

	/* platform specific callback */
	imx_pmx_ops.gpio_set_direction = info->gpio_set_direction;

	mutex_init(&info->mutex);

	ipctl->info = info;
+20 −0
Original line number Diff line number Diff line
@@ -16,9 +16,12 @@
#define __DRIVERS_PINCTRL_IMX_H

#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>

struct platform_device;

extern struct pinmux_ops imx_pmx_ops;

/**
 * struct imx_pin - describes a single i.MX pin
 * @pin: the pin_id of this pin
@@ -76,6 +79,23 @@ struct imx_pinctrl_soc_info {
	unsigned int num_decodes;
	void (*fixup)(unsigned long *configs, unsigned int num_configs,
		      u32 *raw_config);

	int (*gpio_set_direction)(struct pinctrl_dev *pctldev,
				  struct pinctrl_gpio_range *range,
				  unsigned offset,
				  bool input);
};

/**
 * @dev: a pointer back to containing device
 * @base: the offset to the controller in virtual memory
 */
struct imx_pinctrl {
	struct device *dev;
	struct pinctrl_dev *pctl;
	void __iomem *base;
	void __iomem *input_sel_base;
	struct imx_pinctrl_soc_info *info;
};

#define IMX_CFG_PARAMS_DECODE(p, m, o) \
+25 −0
Original line number Diff line number Diff line
@@ -295,10 +295,35 @@ static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = {
	IMX_PINCTRL_PIN(VF610_PAD_PTA7),
};

static int vf610_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
					struct pinctrl_gpio_range *range,
					unsigned offset, bool input)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg;
	u32 reg;

	pin_reg = &info->pin_regs[offset];
	if (pin_reg->mux_reg == -1)
		return -EINVAL;

	/* IBE always enabled allows us to read the value "on the wire" */
	reg = readl(ipctl->base + pin_reg->mux_reg);
	if (input)
		reg &= ~0x2;
	else
		reg |= 0x2;
	writel(reg, ipctl->base + pin_reg->mux_reg);

	return 0;
}

static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
	.pins = vf610_pinctrl_pads,
	.npins = ARRAY_SIZE(vf610_pinctrl_pads),
	.flags = SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID,
	.gpio_set_direction = vf610_pmx_gpio_set_direction,
	.mux_mask = 0x700000,
	.mux_shift = 20,
};