提交 55387764 编写于 作者: J Jason Cooper

Merge tag 'tags/for-mvebu-pinctrl-cleanup' into mvebu/pinctrl

Sign for-mvebu/pinctrl-cleanup
......@@ -23,6 +23,18 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
MPP_MODE(0,
MPP_FUNCTION(0x0, "gpio", NULL),
......@@ -373,7 +385,7 @@ static struct of_device_id armada_370_pinctrl_of_match[] = {
};
static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
MPP_REG_CTRL(0, 65),
MPP_FUNC_CTRL(0, 65, NULL, armada_370_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
......@@ -385,6 +397,12 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
static int armada_370_pinctrl_probe(struct platform_device *pdev)
{
struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = 0; /* no variants for Armada 370 */
soc->controls = mv88f6710_mpp_controls;
......
......@@ -33,6 +33,18 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
enum armada_xp_variant {
V_MV78230 = BIT(0),
V_MV78260 = BIT(1),
......@@ -366,7 +378,7 @@ static struct of_device_id armada_xp_pinctrl_of_match[] = {
};
static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
MPP_REG_CTRL(0, 48),
MPP_FUNC_CTRL(0, 48, NULL, armada_xp_mpp_ctrl),
};
static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
......@@ -375,7 +387,7 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
};
static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
MPP_REG_CTRL(0, 66),
MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
};
static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
......@@ -385,7 +397,7 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
};
static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
MPP_REG_CTRL(0, 66),
MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
};
static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
......@@ -399,10 +411,16 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
const struct of_device_id *match =
of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
struct resource *res;
if (!match)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = (unsigned) match->data & 0xff;
switch (soc->variant) {
......
......@@ -49,62 +49,64 @@
#define DOVE_SD1_GPIO_SEL BIT(1)
#define DOVE_SD0_GPIO_SEL BIT(0)
#define MPPS_PER_REG 8
#define MPP_BITS 4
#define MPP_MASK 0xf
#define CONFIG_PMU BIT(4)
static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
unsigned long *config)
static void __iomem *mpp_base;
static int dove_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int dove_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
unsigned long func;
if (pmu & (1 << ctrl->pid)) {
if ((pmu & BIT(pid)) == 0)
return default_mpp_ctrl_get(mpp_base, pid, config);
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
*config = (func >> shift) & MPP_MASK;
*config = (func >> shift) & MVEBU_MPP_MASK;
*config |= CONFIG_PMU;
} else {
func = readl(DOVE_MPP_VIRT_BASE + off);
*config = (func >> shift) & MPP_MASK;
}
return 0;
}
static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long config)
static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
{
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
unsigned long func;
if (config & CONFIG_PMU) {
writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
if ((config & CONFIG_PMU) == 0) {
writel(pmu & ~BIT(pid), DOVE_PMU_MPP_GENERAL_CTRL);
return default_mpp_ctrl_set(mpp_base, pid, config);
}
writel(pmu | BIT(pid), DOVE_PMU_MPP_GENERAL_CTRL);
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
func &= ~(MPP_MASK << shift);
func |= (config & MPP_MASK) << shift;
func &= ~(MVEBU_MPP_MASK << shift);
func |= (config & MVEBU_MPP_MASK) << shift;
writel(func, DOVE_PMU_SIGNAL_SELECT_0 + off);
} else {
writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
func = readl(DOVE_MPP_VIRT_BASE + off);
func &= ~(MPP_MASK << shift);
func |= (config & MPP_MASK) << shift;
writel(func, DOVE_MPP_VIRT_BASE + off);
}
return 0;
}
static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
unsigned long *config)
static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
unsigned long mask;
switch (ctrl->pid) {
switch (pid) {
case 24: /* mpp_camera */
mask = DOVE_CAM_GPIO_SEL;
break;
......@@ -129,13 +131,12 @@ static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long config)
static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
{
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
unsigned long mask;
switch (ctrl->pid) {
switch (pid) {
case 24: /* mpp_camera */
mask = DOVE_CAM_GPIO_SEL;
break;
......@@ -164,8 +165,7 @@ static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
unsigned long *config)
static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
......@@ -174,8 +174,7 @@ static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long config)
static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
{
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
......@@ -188,8 +187,7 @@ static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
unsigned long *config)
static int dove_audio0_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
......@@ -198,8 +196,7 @@ static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long config)
static int dove_audio0_ctrl_set(unsigned pid, unsigned long config)
{
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
......@@ -211,8 +208,7 @@ static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
unsigned long *config)
static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
......@@ -238,8 +234,7 @@ static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long config)
static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
{
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
......@@ -276,11 +271,11 @@ static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
* break other functions. If you require all mpps as gpio
* enforce gpio setting by pinctrl mapping.
*/
static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
static int dove_audio1_ctrl_gpio_req(unsigned pid)
{
unsigned long config;
dove_audio1_ctrl_get(ctrl, &config);
dove_audio1_ctrl_get(pid, &config);
switch (config) {
case 0x02: /* i2s1 : gpio[56:57] */
......@@ -303,16 +298,14 @@ static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
}
/* mpp[52:57] has gpio pins capable of in and out */
static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid,
bool input)
static int dove_audio1_ctrl_gpio_dir(unsigned pid, bool input)
{
if (pid < 52 || pid > 57)
return -ENOTSUPP;
return 0;
}
static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
unsigned long *config)
static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
......@@ -328,8 +321,7 @@ static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0;
}
static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long config)
static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
{
unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
......@@ -356,23 +348,8 @@ static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
}
static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
MPP_REG_CTRL(16, 23),
MPP_FUNC_CTRL(0, 15, NULL, dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(16, 23, NULL, dove_mpp_ctrl),
MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
......@@ -774,6 +751,7 @@ static struct of_device_id dove_pinctrl_of_match[] = {
static int dove_pinctrl_probe(struct platform_device *pdev)
{
struct resource *res;
const struct of_device_id *match =
of_match_device(dove_pinctrl_of_match, &pdev->dev);
pdev->dev.platform_data = (void *)match->data;
......@@ -789,6 +767,11 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
}
clk_prepare_enable(clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
return mvebu_pinctrl_probe(pdev);
}
......
......@@ -21,6 +21,18 @@
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int kirkwood_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int kirkwood_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
#define V(f6180, f6190, f6192, f6281, f6282, dx4122) \
((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
(f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
......@@ -359,7 +371,7 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
};
static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
MPP_REG_CTRL(0, 29),
MPP_FUNC_CTRL(0, 29, NULL, kirkwood_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
......@@ -367,7 +379,7 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
};
static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
MPP_REG_CTRL(0, 35),
MPP_FUNC_CTRL(0, 35, NULL, kirkwood_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
......@@ -376,7 +388,7 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
};
static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
MPP_REG_CTRL(0, 49),
MPP_FUNC_CTRL(0, 49, NULL, kirkwood_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
......@@ -456,9 +468,16 @@ static struct of_device_id kirkwood_pinctrl_of_match[] = {
static int kirkwood_pinctrl_probe(struct platform_device *pdev)
{
struct resource *res;
const struct of_device_id *match =
of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
pdev->dev.platform_data = (void *)match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
return mvebu_pinctrl_probe(pdev);
}
......
......@@ -50,7 +50,6 @@ struct mvebu_pinctrl {
struct device *dev;
struct pinctrl_dev *pctldev;
struct pinctrl_desc desc;
void __iomem *base;
struct mvebu_pinctrl_group *groups;
unsigned num_groups;
struct mvebu_pinctrl_function *functions;
......@@ -138,43 +137,6 @@ static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
return NULL;
}
/*
* Common mpp pin configuration registers on MVEBU are
* registers of eight 4-bit values for each mpp setting.
* Register offset and bit mask are calculated accordingly below.
*/
static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
struct mvebu_pinctrl_group *grp,
unsigned long *config)
{
unsigned pin = grp->gid;
unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
*config = readl(pctl->base + off);
*config >>= shift;
*config &= MPP_MASK;
return 0;
}
static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
struct mvebu_pinctrl_group *grp,
unsigned long config)
{
unsigned pin = grp->gid;
unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
unsigned long reg;
reg = readl(pctl->base + off);
reg &= ~(MPP_MASK << shift);
reg |= (config << shift);
writel(reg, pctl->base + off);
return 0;
}
static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
unsigned gid, unsigned long *config)
{
......@@ -184,10 +146,7 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
if (!grp->ctrl)
return -EINVAL;
if (grp->ctrl->mpp_get)
return grp->ctrl->mpp_get(grp->ctrl, config);
return mvebu_common_mpp_get(pctl, grp, config);
return grp->ctrl->mpp_get(grp->pins[0], config);
}
static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
......@@ -202,11 +161,7 @@ static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
return -EINVAL;
for (i = 0; i < num_configs; i++) {
if (grp->ctrl->mpp_set)
ret = grp->ctrl->mpp_set(grp->ctrl, configs[i]);
else
ret = mvebu_common_mpp_set(pctl, grp, configs[i]);
ret = grp->ctrl->mpp_set(grp->pins[0], configs[i]);
if (ret)
return ret;
} /* for each config */
......@@ -347,7 +302,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
return -EINVAL;
if (grp->ctrl->mpp_gpio_req)
return grp->ctrl->mpp_gpio_req(grp->ctrl, offset);
return grp->ctrl->mpp_gpio_req(offset);
setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
if (!setting)
......@@ -370,7 +325,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
return -EINVAL;
if (grp->ctrl->mpp_gpio_dir)
return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input);
return grp->ctrl->mpp_gpio_dir(offset, input);
setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
if (!setting)
......@@ -593,11 +548,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
int mvebu_pinctrl_probe(struct platform_device *pdev)
{
struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
struct resource *res;
struct mvebu_pinctrl *pctl;
void __iomem *base;
struct pinctrl_pin_desc *pdesc;
unsigned gid, n, k;
unsigned size, noname = 0;
char *noname_buf;
void *p;
int ret;
if (!soc || !soc->controls || !soc->modes) {
......@@ -605,11 +561,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
GFP_KERNEL);
if (!pctl) {
......@@ -623,7 +574,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->desc.pmxops = &mvebu_pinmux_ops;
pctl->desc.confops = &mvebu_pinconf_ops;
pctl->variant = soc->variant;
pctl->base = base;
pctl->dev = &pdev->dev;
platform_set_drvdata(pdev, pctl);
......@@ -633,33 +583,23 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->desc.npins = 0;
for (n = 0; n < soc->ncontrols; n++) {
struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
char *names;
pctl->desc.npins += ctrl->npins;
/* initial control pins */
/* initialize control's pins[] array */
for (k = 0; k < ctrl->npins; k++)
ctrl->pins[k] = ctrl->pid + k;
/* special soc specific control */
if (ctrl->mpp_get || ctrl->mpp_set) {
if (!ctrl->name || !ctrl->mpp_get || !ctrl->mpp_set) {
dev_err(&pdev->dev, "wrong soc control info\n");
return -EINVAL;
}
/*
* We allow to pass controls with NULL name that we treat
* as a range of one-pin groups with generic mvebu register
* controls.
*/
if (!ctrl->name) {
pctl->num_groups += ctrl->npins;
noname += ctrl->npins;
} else {
pctl->num_groups += 1;
continue;
}
/* generic mvebu register control */
names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
if (!names) {
dev_err(&pdev->dev, "failed to alloc mpp names\n");
return -ENOMEM;
}
for (k = 0; k < ctrl->npins; k++)
sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
ctrl->name = names;
pctl->num_groups += ctrl->npins;
}
pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
......@@ -673,12 +613,17 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pdesc[n].number = n;
pctl->desc.pins = pdesc;
pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups *
sizeof(struct mvebu_pinctrl_group), GFP_KERNEL);
if (!pctl->groups) {
dev_err(&pdev->dev, "failed to alloc pinctrl groups\n");
/*
* allocate groups and name buffers for unnamed groups.
*/
size = pctl->num_groups * sizeof(*pctl->groups) + noname * 8;
p = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!p) {
dev_err(&pdev->dev, "failed to alloc group data\n");
return -ENOMEM;
}
pctl->groups = p;
noname_buf = p + pctl->num_groups * sizeof(*pctl->groups);
/* assign mpp controls to groups */
gid = 0;
......@@ -690,17 +635,26 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->groups[gid].pins = ctrl->pins;
pctl->groups[gid].npins = ctrl->npins;
/* generic mvebu register control maps to a number of groups */
if (!ctrl->mpp_get && !ctrl->mpp_set) {
/*
* We treat unnamed controls as a range of one-pin groups
* with generic mvebu register controls. Use one group for
* each in this range and assign a default group name.
*/
if (!ctrl->name) {
pctl->groups[gid].name = noname_buf;
pctl->groups[gid].npins = 1;
sprintf(noname_buf, "mpp%d", ctrl->pid+0);
noname_buf += 8;
for (k = 1; k < ctrl->npins; k++) {
gid++;
pctl->groups[gid].gid = gid;
pctl->groups[gid].ctrl = ctrl;
pctl->groups[gid].name = &ctrl->name[8*k];
pctl->groups[gid].name = noname_buf;
pctl->groups[gid].pins = &ctrl->pins[k];
pctl->groups[gid].npins = 1;
sprintf(noname_buf, "mpp%d", ctrl->pid+k);
noname_buf += 8;
}
}
gid++;
......
......@@ -28,20 +28,19 @@
* between two or more different settings, e.g. assign mpp pin 13 to
* uart1 or sata.
*
* If optional mpp_get/_set functions are set these are used to get/set
* a specific mode. Otherwise it is assumed that the mpp control is based
* on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir
* functions can be used to allow pin settings with varying gpio pins.
* The mpp_get/_set functions are mandatory and are used to get/set a
* specific mode. The optional mpp_gpio_req/_dir functions can be used
* to allow pin settings with varying gpio pins.
*/
struct mvebu_mpp_ctrl {
const char *name;
u8 pid;
u8 npins;
unsigned *pins;
int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config);
int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config);
int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid);
int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input);
int (*mpp_get)(unsigned pid, unsigned long *config);
int (*mpp_set)(unsigned pid, unsigned long config);
int (*mpp_gpio_req)(unsigned pid);
int (*mpp_gpio_dir)(unsigned pid, bool input);
};
/**
......@@ -114,18 +113,6 @@ struct mvebu_pinctrl_soc_info {
int ngpioranges;
};
#define MPP_REG_CTRL(_idl, _idh) \
{ \
.name = NULL, \
.pid = _idl, \
.npins = _idh - _idl + 1, \
.pins = (unsigned[_idh - _idl + 1]) { }, \
.mpp_get = NULL, \
.mpp_set = NULL, \
.mpp_gpio_req = NULL, \
.mpp_gpio_dir = NULL, \
}
#define MPP_FUNC_CTRL(_idl, _idh, _name, _func) \
{ \
.name = _name, \
......@@ -186,6 +173,34 @@ struct mvebu_pinctrl_soc_info {
.npins = _npins, \
}
#define MVEBU_MPPS_PER_REG 8
#define MVEBU_MPP_BITS 4
#define MVEBU_MPP_MASK 0xf
static inline int default_mpp_ctrl_get(void __iomem *base, unsigned int pid,
unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
*config = (readl(base + off) >> shift) & MVEBU_MPP_MASK;
return 0;
}
static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
unsigned long config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long reg;
reg = readl(base + off) & ~(MVEBU_MPP_MASK << shift);
writel(reg | (config << shift), base + off);
return 0;
}
int mvebu_pinctrl_probe(struct platform_device *pdev);
int mvebu_pinctrl_remove(struct platform_device *pdev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册