@@ -972,6 +972,19 @@ pinmux core.
Pin control requests from drivers
=================================
+When a device driver is about to probe on the platform or AMBA (PrimeCell)
+bus, the pinctrl core will automatically attempt to issue
+pinctrl_get_select_default() on these devices using the bus notification
+mechanism. This way driver writers do not need to add any of the
+boilerplate code of the type found below. However when doing fine-grained
+state selection and not using the "default" state, you may have to do
+some device driver handling of the pinctrl handles and states.
+
+So if you just want to put the pins for a certain platform or AMBA device
+into the default state and be done with it, there is nothing you need to
+do besides providing the proper mapping table. The device core will take
+care of the rest.
+
Generally it is discouraged to let individual drivers get and enable pin
control. So if possible, handle the pin control in platform code or some other
place where you have access to all the affected struct device * pointers. In
@@ -1097,8 +1110,8 @@ situations that can be electrically unpleasant, you will certainly want to
mux in and bias pins in a certain way before the GPIO subsystems starts to
deal with them.
-The above can be hidden: using pinctrl hogs, the pin control driver may be
-setting up the config and muxing for the pins when it is probing,
+The above can be hidden: using device notifiers, the pinctrl core may be
+setting up the config and muxing for the pins when the device is probing,
nevertheless orthogonal to the GPIO subsystem.
But there are also situations where it makes sense for the GPIO subsystem
@@ -1144,6 +1157,13 @@ PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-foo", NULL /* group */, "power_func")
This gives the exact same result as the above construction.
+This should not be used for any kind of device which is represented in
+the device model. For platform and AMBA (PrimeCell) devices, such as found
+in many SoC:s, the pinctrl core will listen to notifications from these
+buses and attempt to do pinctrl_get_select_default() for these devices
+right before their device drivers are probed, so hogging these will just
+make the model look strange.
+
Runtime pinmuxing
=================
@@ -26,6 +26,9 @@
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/machine.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
#include "core.h"
#include "devicetree.h"
#include "pinmux.h"
@@ -684,9 +687,16 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev)
if (WARN_ON(!dev))
return ERR_PTR(-EINVAL);
+ /*
+ * See if somebody else (such as the pinctrl core, using the
+ * notifiers) has already obtained a handle to the pinctrl for
+ * this device. In that case, return another pointer to it.
+ */
p = find_pinctrl(dev);
- if (p != NULL)
- return ERR_PTR(-EBUSY);
+ if (p != NULL) {
+ dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
+ return p;
+ }
return create_pinctrl(dev);
}
@@ -1026,6 +1036,52 @@ void pinctrl_unregister_map(struct pinctrl_map const *map)
}
}
+static int pinctrl_device_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct pinctrl *p;
+
+ switch (action) {
+ case BUS_NOTIFY_BIND_DRIVER:
+ /*
+ * Hog pins right before a driver is about to be bound to
+ * the device
+ */
+ p = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR_OR_NULL(p)) {
+ dev_dbg(dev, "no pinctrl handle or default state\n");
+ return 0;
+ }
+ dev_dbg(dev, "pinctrl core obtained default pinctrl\n");
+ break;
+ case BUS_NOTIFY_UNBOUND_DRIVER:
+ break;
+ }
+
+ return 0;
+}
+
+static struct notifier_block pinctrl_device_nb = {
+ .notifier_call = pinctrl_device_notify,
+};
+
+static int __init pinctrl_notifiers_init(void)
+{
+ bus_register_notifier(&platform_bus_type, &pinctrl_device_nb);
+#ifdef CONFIG_ARM_AMBA
+ bus_register_notifier(&amba_bustype, &pinctrl_device_nb);
+#endif
+ return 0;
+}
+
+/*
+ * The AMBA bus registers in the postcore_initcall() so we need to
+ * register our notifiers right after that so we can fetch pins for
+ * e.g. TTY drivers that will be registered in the arch_initcall() next.
+ */
+postcore_initcall_sync(pinctrl_notifiers_init);
+
#ifdef CONFIG_DEBUG_FS
static int pinctrl_pins_show(struct seq_file *s, void *what)