diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 3b4ee5328868..a1cd2f9428d7 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -1193,4 +1193,6 @@ foo_switch() ... } -The above has to be done from process context. +The above has to be done from process context. The reservation of the pins +will be done when the state is activated, so in effect one specific pin +can be used by different functions at different times on a running system. diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index d96caefd914a..011133772d2a 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -188,27 +188,7 @@ config PINCTRL_EXYNOS4 depends on OF && GPIOLIB select PINCTRL_SAMSUNG -config PINCTRL_MVEBU - bool - depends on ARCH_MVEBU - select PINMUX - select PINCONF - -config PINCTRL_DOVE - bool - select PINCTRL_MVEBU - -config PINCTRL_KIRKWOOD - bool - select PINCTRL_MVEBU - -config PINCTRL_ARMADA_370 - bool - select PINCTRL_MVEBU - -config PINCTRL_ARMADA_XP - bool - select PINCTRL_MVEBU +source "drivers/pinctrl/mvebu/Kconfig" source "drivers/pinctrl/spear/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f395ba5cec25..3cb6a0a668a8 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -36,12 +36,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o -obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o -obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o -obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o -obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o -obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o +obj-$(CONFIG_PLAT_ORION) += mvebu/ obj-$(CONFIG_PLAT_SPEAR) += spear/ diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 2e39c04fc16b..cec6072cd7c1 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -563,6 +563,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) return -EPROBE_DEFER; } + setting->dev_name = map->dev_name; + switch (map->type) { case PIN_MAP_TYPE_MUX_GROUP: ret = pinmux_map_to_setting(map, setting); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 1f40ff68a8c4..12f5694f3d5d 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -105,12 +105,14 @@ struct pinctrl_setting_configs { * @type: the type of setting * @pctldev: pin control device handling to be programmed. Not used for * PIN_MAP_TYPE_DUMMY_STATE. + * @dev_name: the name of the device using this state * @data: Data specific to the setting type */ struct pinctrl_setting { struct list_head node; enum pinctrl_map_type type; struct pinctrl_dev *pctldev; + const char *dev_name; union { struct pinctrl_setting_mux mux; struct pinctrl_setting_configs configs; diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig new file mode 100644 index 000000000000..366fa541ee91 --- /dev/null +++ b/drivers/pinctrl/mvebu/Kconfig @@ -0,0 +1,24 @@ +if PLAT_ORION + +config PINCTRL_MVEBU + bool + select PINMUX + select PINCONF + +config PINCTRL_DOVE + bool + select PINCTRL_MVEBU + +config PINCTRL_KIRKWOOD + bool + select PINCTRL_MVEBU + +config PINCTRL_ARMADA_370 + bool + select PINCTRL_MVEBU + +config PINCTRL_ARMADA_XP + bool + select PINCTRL_MVEBU + +endif diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile new file mode 100644 index 000000000000..37c253297af0 --- /dev/null +++ b/drivers/pinctrl/mvebu/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o +obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o +obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o +obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o +obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c similarity index 100% rename from drivers/pinctrl/pinctrl-armada-370.c rename to drivers/pinctrl/mvebu/pinctrl-armada-370.c diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c similarity index 100% rename from drivers/pinctrl/pinctrl-armada-xp.c rename to drivers/pinctrl/mvebu/pinctrl-armada-xp.c diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c similarity index 100% rename from drivers/pinctrl/pinctrl-dove.c rename to drivers/pinctrl/mvebu/pinctrl-dove.c diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c similarity index 100% rename from drivers/pinctrl/pinctrl-kirkwood.c rename to drivers/pinctrl/mvebu/pinctrl-kirkwood.c diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c similarity index 99% rename from drivers/pinctrl/pinctrl-mvebu.c rename to drivers/pinctrl/mvebu/pinctrl-mvebu.c index 8e6266c6249a..6c44b7e8964c 100644 --- a/drivers/pinctrl/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -24,7 +24,6 @@ #include #include -#include "core.h" #include "pinctrl-mvebu.h" #define MPPS_PER_REG 8 diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h similarity index 100% rename from drivers/pinctrl/pinctrl-mvebu.h rename to drivers/pinctrl/mvebu/pinctrl-mvebu.h diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 9301a7a95eff..0ef01ee2835f 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, { struct pinctrl_dev *pctldev = setting->pctldev; const struct pinmux_ops *pmxops = pctldev->desc->pmxops; - const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; char const * const *groups; unsigned num_groups; int ret; const char *group; int i; - const unsigned *pins; - unsigned num_pins; if (!pmxops) { dev_err(pctldev->dev, "does not support mux function\n"); @@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, } setting->data.mux.group = ret; - ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins, - &num_pins); - if (ret) { - dev_err(pctldev->dev, - "could not get pins for device %s group selector %d\n", - pinctrl_dev_get_name(pctldev), setting->data.mux.group); - return -ENODEV; - } - - /* Try to allocate all pins in this group, one by one */ - for (i = 0; i < num_pins; i++) { - ret = pin_request(pctldev, pins[i], map->dev_name, NULL); - if (ret) { - dev_err(pctldev->dev, - "could not request pin %d on device %s\n", - pins[i], pinctrl_dev_get_name(pctldev)); - /* On error release all taken pins */ - i--; /* this pin just failed */ - for (; i >= 0; i--) - pin_free(pctldev, pins[i], NULL); - return -ENODEV; - } - } - return 0; } void pinmux_free_setting(struct pinctrl_setting const *setting) { - struct pinctrl_dev *pctldev = setting->pctldev; - const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - const unsigned *pins; - unsigned num_pins; - int ret; - int i; - - ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, - &pins, &num_pins); - if (ret) { - dev_err(pctldev->dev, - "could not get pins for device %s group selector %d\n", - pinctrl_dev_get_name(pctldev), setting->data.mux.group); - return; - } - - for (i = 0; i < num_pins; i++) - pin_free(pctldev, pins[i], NULL); + /* This function is currently unused */ } int pinmux_enable_setting(struct pinctrl_setting const *setting) @@ -446,6 +402,22 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) num_pins = 0; } + /* Try to allocate all pins in this group, one by one */ + for (i = 0; i < num_pins; i++) { + ret = pin_request(pctldev, pins[i], setting->dev_name, NULL); + if (ret) { + dev_err(pctldev->dev, + "could not request pin %d on device %s\n", + pins[i], pinctrl_dev_get_name(pctldev)); + /* On error release all taken pins */ + i--; /* this pin just failed */ + for (; i >= 0; i--) + pin_free(pctldev, pins[i], NULL); + return -ENODEV; + } + } + + /* Now that we have acquired the pins, encode the mux setting */ for (i = 0; i < num_pins; i++) { desc = pin_desc_get(pctldev, pins[i]); if (desc == NULL) { @@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) num_pins = 0; } + /* Flag the descs that no setting is active */ for (i = 0; i < num_pins; i++) { desc = pin_desc_get(pctldev, pins[i]); if (desc == NULL) { @@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) desc->mux_setting = NULL; } + /* And release the pins */ + for (i = 0; i < num_pins; i++) + pin_free(pctldev, pins[i], NULL); + if (ops->disable) ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group); }