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

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
...@@ -221,13 +221,21 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -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;
} }
writel(mux[i], ipctl->base + pin_reg->mux_reg); 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);
}
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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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);
writel(config, ipctl->base + pin_reg->conf_reg); 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);
}
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 = { ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -74,8 +74,12 @@ struct imx_pinctrl_soc_info { ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment