Commit f4f8e563 authored by Viresh Kumar's avatar Viresh Kumar Committed by Linus Walleij

pinctrl: SPEAr: Add gpio ranges support

Most of SPEAr SoCs, which support pinctrl, can configure & use pads as gpio.
This patch gpio enable support for SPEAr pinctrl drivers.
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 50309a9c
......@@ -25,21 +25,25 @@ config PINCTRL_SPEAR310
bool "ST Microelectronics SPEAr310 SoC pin controller driver"
depends on MACH_SPEAR310
select PINCTRL_SPEAR3XX
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR320
bool "ST Microelectronics SPEAr320 SoC pin controller driver"
depends on MACH_SPEAR320
select PINCTRL_SPEAR3XX
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR1310
bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
depends on MACH_SPEAR1310
select PINCTRL_SPEAR
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR1340
bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
depends on MACH_SPEAR1340
select PINCTRL_SPEAR
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR_PLGPIO
bool "SPEAr SoC PLGPIO Controller"
......
......@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
......@@ -38,6 +39,28 @@ static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
writel_relaxed(val, pmx->vbase + reg);
}
static void muxregs_endisable(struct spear_pmx *pmx,
struct spear_muxreg *muxregs, u8 count, bool enable)
{
struct spear_muxreg *muxreg;
u32 val, temp, j;
for (j = 0; j < count; j++) {
muxreg = &muxregs[j];
val = pmx_readl(pmx, muxreg->reg);
val &= ~muxreg->mask;
if (enable)
temp = muxreg->val;
else
temp = ~muxreg->val;
val |= muxreg->mask & temp;
pmx_writel(pmx, val, muxreg->reg);
}
}
static int set_mode(struct spear_pmx *pmx, int mode)
{
struct spear_pmx_mode *pmx_mode = NULL;
......@@ -70,6 +93,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
return 0;
}
void __devinit
pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
unsigned count, u16 reg)
{
int i = 0, j = 0;
for (; i < count; i++)
for (; j < gpio_pingroup[i].nmuxregs; j++)
gpio_pingroup[i].muxregs[j].reg = reg;
}
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
{
struct spear_pingroup *pgroup;
......@@ -216,9 +250,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
const struct spear_pingroup *pgroup;
const struct spear_modemux *modemux;
struct spear_muxreg *muxreg;
u32 val, temp;
int i, j;
int i;
bool found = false;
pgroup = pmx->machdata->groups[group];
......@@ -233,20 +265,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
}
found = true;
for (j = 0; j < modemux->nmuxregs; j++) {
muxreg = &modemux->muxregs[j];
val = pmx_readl(pmx, muxreg->reg);
val &= ~muxreg->mask;
if (enable)
temp = muxreg->val;
else
temp = ~muxreg->val;
val |= muxreg->mask & temp;
pmx_writel(pmx, val, muxreg->reg);
}
muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
enable);
}
if (!found) {
......@@ -270,12 +290,65 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
spear_pinctrl_endisable(pctldev, function, group, false);
}
/* gpio with pinmux */
static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
unsigned pin)
{
struct spear_gpio_pingroup *gpio_pingroup;
int i = 0, j;
if (!pmx->machdata->gpio_pingroups)
return NULL;
for (; i < pmx->machdata->ngpio_pingroups; i++) {
gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
for (j = 0; j < gpio_pingroup->npins; j++) {
if (gpio_pingroup->pins[j] == pin)
return gpio_pingroup;
}
}
return ERR_PTR(-EINVAL);
}
static int gpio_request_endisable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset, bool enable)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
struct spear_gpio_pingroup *gpio_pingroup;
gpio_pingroup = get_gpio_pingroup(pmx, offset);
if (IS_ERR(gpio_pingroup))
return PTR_ERR(gpio_pingroup);
if (gpio_pingroup)
muxregs_endisable(pmx, gpio_pingroup->muxregs,
gpio_pingroup->nmuxregs, enable);
return 0;
}
static int gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
{
return gpio_request_endisable(pctldev, range, offset, true);
}
static void gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
{
gpio_request_endisable(pctldev, range, offset, false);
}
static struct pinmux_ops spear_pinmux_ops = {
.get_functions_count = spear_pinctrl_get_funcs_count,
.get_function_name = spear_pinctrl_get_func_name,
.get_function_groups = spear_pinctrl_get_func_groups,
.enable = spear_pinctrl_enable,
.disable = spear_pinctrl_disable,
.gpio_request_enable = gpio_request_enable,
.gpio_disable_free = gpio_disable_free,
};
static struct pinctrl_desc spear_pinctrl_desc = {
......
......@@ -12,6 +12,7 @@
#ifndef __PINMUX_SPEAR_H__
#define __PINMUX_SPEAR_H__
#include <linux/gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/types.h>
......@@ -46,6 +47,44 @@ struct spear_muxreg {
u32 val;
};
struct spear_gpio_pingroup {
const unsigned *pins;
unsigned npins;
struct spear_muxreg *muxregs;
u8 nmuxregs;
};
/* ste: set to enable */
#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste) \
static struct spear_muxreg __pins##_muxregs[] = { \
{ \
.reg = __muxreg, \
.mask = __mask, \
.val = __ste ? __mask : 0, \
}, \
}
#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \
static struct spear_muxreg __pins##_muxregs[] = { \
{ \
.reg = __muxreg1, \
.mask = __mask, \
.val = __ste1 ? __mask : 0, \
}, { \
.reg = __muxreg2, \
.mask = __mask, \
.val = __ste2 ? __mask : 0, \
}, \
}
#define GPIO_PINGROUP(__pins) \
{ \
.pins = __pins, \
.npins = ARRAY_SIZE(__pins), \
.muxregs = __pins##_muxregs, \
.nmuxregs = ARRAY_SIZE(__pins##_muxregs), \
}
/**
* struct spear_modemux - SPEAr mode mux configuration
* @modes: mode ids supported by this group of muxregs
......@@ -100,6 +139,8 @@ struct spear_function {
* @nfunctions: The numbmer of entries in @functions.
* @groups: An array describing all pin groups the pin SoC supports.
* @ngroups: The numbmer of entries in @groups.
* @gpio_pingroups: gpio pingroups
* @ngpio_pingroups: gpio pingroups count
*
* @modes_supported: Does SoC support modes
* @mode: mode configured from probe
......@@ -113,6 +154,8 @@ struct spear_pinctrl_machdata {
unsigned nfunctions;
struct spear_pingroup **groups;
unsigned ngroups;
struct spear_gpio_pingroup *gpio_pingroups;
unsigned ngpio_pingroups;
bool modes_supported;
u16 mode;
......@@ -136,6 +179,9 @@ struct spear_pmx {
/* exported routines */
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
void __devinit
pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
unsigned count, u16 reg);
int __devinit spear_pinctrl_probe(struct platform_device *pdev,
struct spear_pinctrl_machdata *machdata);
int __devexit spear_pinctrl_remove(struct platform_device *pdev);
......
This diff is collapsed.
......@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
spear3xx_machdata.functions = spear300_functions;
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
spear3xx_machdata.gpio_pingroups = NULL;
spear3xx_machdata.ngpio_pingroups = 0;
spear3xx_machdata.modes_supported = true;
spear3xx_machdata.pmx_modes = spear300_pmx_modes;
......
......@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
spear3xx_machdata.modes_supported = false;
......
......@@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
if (ret)
......
......@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
.ngroups = ARRAY_SIZE(timer_2_3_grps),
};
/* Define muxreg arrays */
DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0);
DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0);
DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0);
DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0);
DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0);
DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0);
DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0);
DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0);
DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0);
DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0);
DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0);
DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0);
DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0);
DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0);
DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0);
static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
GPIO_PINGROUP(firda_pins),
GPIO_PINGROUP(i2c_pins),
GPIO_PINGROUP(ssp_cs_pins),
GPIO_PINGROUP(ssp_pins),
GPIO_PINGROUP(mii_pins),
GPIO_PINGROUP(gpio0_pin0_pins),
GPIO_PINGROUP(gpio0_pin1_pins),
GPIO_PINGROUP(gpio0_pin2_pins),
GPIO_PINGROUP(gpio0_pin3_pins),
GPIO_PINGROUP(gpio0_pin4_pins),
GPIO_PINGROUP(gpio0_pin5_pins),
GPIO_PINGROUP(uart0_ext_pins),
GPIO_PINGROUP(uart0_pins),
GPIO_PINGROUP(timer_0_1_pins),
GPIO_PINGROUP(timer_2_3_pins),
};
struct spear_pinctrl_machdata spear3xx_machdata = {
.pins = spear3xx_pins,
.npins = ARRAY_SIZE(spear3xx_pins),
.gpio_pingroups = spear3xx_gpio_pingroup,
.ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
};
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