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

Commit bf5a5309 authored by Jingchang Lu's avatar Jingchang Lu Committed by Linus Walleij
Browse files

pinctrl: imx: add VF610 support to imx pinctrl framework



On some platforms such as VF610, offset of mux and pad ctrl register
may be zero, and the mux_mode and config_val are in one 32-bit register.
This patch adds support to imx core pinctrl framework to handle these
cases.

Signed-off-by: default avatarJingchang Lu <b35083@freescale.com>
Acked-by: default avatarShawn Guo <shawn.guo@linaro.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 7bbc87b8
Loading
Loading
Loading
Loading
+42 −11
Original line number Original line Diff line number Diff line
@@ -221,13 +221,21 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
		pin_id = pins[i];
		pin_id = pins[i];
		pin_reg = &info->pin_regs[pin_id];
		pin_reg = &info->pin_regs[pin_id];


		if (!pin_reg->mux_reg) {
		if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->mux_reg) {
			dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
			dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
				info->pins[pin_id].name);
				info->pins[pin_id].name);
			return -EINVAL;
			return -EINVAL;
		}
		}


		if (info->flags & SHARE_MUX_CONF_REG) {
			u32 reg;
			reg = readl(ipctl->base + pin_reg->mux_reg);
			reg &= ~(0x7 << 20);
			reg |= (mux[i] << 20);
			writel(reg, ipctl->base + pin_reg->mux_reg);
		} else {
			writel(mux[i], ipctl->base + pin_reg->mux_reg);
			writel(mux[i], ipctl->base + pin_reg->mux_reg);
		}
		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
			pin_reg->mux_reg, mux[i]);
			pin_reg->mux_reg, mux[i]);


@@ -287,7 +295,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];


	if (!pin_reg->conf_reg) {
	if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
		dev_err(info->dev, "Pin(%s) does not support config function\n",
		dev_err(info->dev, "Pin(%s) does not support config function\n",
			info->pins[pin_id].name);
			info->pins[pin_id].name);
		return -EINVAL;
		return -EINVAL;
@@ -295,6 +303,9 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,


	*config = readl(ipctl->base + pin_reg->conf_reg);
	*config = readl(ipctl->base + pin_reg->conf_reg);


	if (info->flags & SHARE_MUX_CONF_REG)
		*config &= 0xffff;

	return 0;
	return 0;
}
}


@@ -305,7 +316,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];


	if (!pin_reg->conf_reg) {
	if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
		dev_err(info->dev, "Pin(%s) does not support config function\n",
		dev_err(info->dev, "Pin(%s) does not support config function\n",
			info->pins[pin_id].name);
			info->pins[pin_id].name);
		return -EINVAL;
		return -EINVAL;
@@ -314,7 +325,15 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
	dev_dbg(ipctl->dev, "pinconf set pin %s\n",
	dev_dbg(ipctl->dev, "pinconf set pin %s\n",
		info->pins[pin_id].name);
		info->pins[pin_id].name);


	if (info->flags & SHARE_MUX_CONF_REG) {
		u32 reg;
		reg = readl(ipctl->base + pin_reg->conf_reg);
		reg &= ~0xffff;
		reg |= config;
		writel(reg, ipctl->base + pin_reg->conf_reg);
	} else {
		writel(config, ipctl->base + pin_reg->conf_reg);
		writel(config, ipctl->base + pin_reg->conf_reg);
	}
	dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
	dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
		pin_reg->conf_reg, config);
		pin_reg->conf_reg, config);


@@ -381,19 +400,24 @@ static struct pinctrl_desc imx_pinctrl_desc = {
 * 1 u32 CONFIG, so 24 types in total for each pin.
 * 1 u32 CONFIG, so 24 types in total for each pin.
 */
 */
#define FSL_PIN_SIZE 24
#define FSL_PIN_SIZE 24
#define SHARE_FSL_PIN_SIZE 20


static int imx_pinctrl_parse_groups(struct device_node *np,
static int imx_pinctrl_parse_groups(struct device_node *np,
				    struct imx_pin_group *grp,
				    struct imx_pin_group *grp,
				    struct imx_pinctrl_soc_info *info,
				    struct imx_pinctrl_soc_info *info,
				    u32 index)
				    u32 index)
{
{
	int size;
	int size, pin_size;
	const __be32 *list;
	const __be32 *list;
	int i;
	int i;
	u32 config;
	u32 config;


	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);


	if (info->flags & SHARE_MUX_CONF_REG)
		pin_size = SHARE_FSL_PIN_SIZE;
	else
		pin_size = FSL_PIN_SIZE;
	/* Initialise group */
	/* Initialise group */
	grp->name = np->name;
	grp->name = np->name;


@@ -403,12 +427,12 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
	 */
	 */
	list = of_get_property(np, "fsl,pins", &size);
	list = of_get_property(np, "fsl,pins", &size);
	/* we do not check return since it's safe node passed down */
	/* we do not check return since it's safe node passed down */
	if (!size || size % FSL_PIN_SIZE) {
	if (!size || size % pin_size) {
		dev_err(info->dev, "Invalid fsl,pins property\n");
		dev_err(info->dev, "Invalid fsl,pins property\n");
		return -EINVAL;
		return -EINVAL;
	}
	}


	grp->npins = size / FSL_PIN_SIZE;
	grp->npins = size / pin_size;
	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
				GFP_KERNEL);
				GFP_KERNEL);
	grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
	grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
@@ -421,10 +445,17 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
				GFP_KERNEL);
				GFP_KERNEL);
	for (i = 0; i < grp->npins; i++) {
	for (i = 0; i < grp->npins; i++) {
		u32 mux_reg = be32_to_cpu(*list++);
		u32 mux_reg = be32_to_cpu(*list++);
		u32 conf_reg = be32_to_cpu(*list++);
		u32 conf_reg;
		unsigned int pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
		unsigned int pin_id;
		struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
		struct imx_pin_reg *pin_reg;


		if (info->flags & SHARE_MUX_CONF_REG)
			conf_reg = mux_reg;
		else
			conf_reg = be32_to_cpu(*list++);

		pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
		pin_reg = &info->pin_regs[pin_id];
		grp->pins[i] = pin_id;
		grp->pins[i] = pin_id;
		pin_reg->mux_reg = mux_reg;
		pin_reg->mux_reg = mux_reg;
		pin_reg->conf_reg = conf_reg;
		pin_reg->conf_reg = conf_reg;
+4 −0
Original line number Original line Diff line number Diff line
@@ -74,8 +74,12 @@ struct imx_pinctrl_soc_info {
	unsigned int ngroups;
	unsigned int ngroups;
	struct imx_pmx_func *functions;
	struct imx_pmx_func *functions;
	unsigned int nfunctions;
	unsigned int nfunctions;
	unsigned int flags;
};
};


#define ZERO_OFFSET_VALID	0x1
#define SHARE_MUX_CONF_REG	0x2

#define NO_MUX		0x0
#define NO_MUX		0x0
#define NO_PAD		0x0
#define NO_PAD		0x0