Commit 55387764 authored by Jason Cooper's avatar Jason Cooper

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

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