Skip to contentSkip to conversation

drivers: create a pinmux subsystem

PATCH In review Linus Walleij 12 participants 23 messages May 2, 2011 – May 27, 2011

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/4 drivers: create a pinmux subsystem

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

---
 Documentation/ABI/testing/sysfs-class-pinmux |   11 +
 Documentation/pinmux.txt                     |  306 +++++++++++
 MAINTAINERS                                  |    5 +
 drivers/Kconfig                              |    4 +
 drivers/Makefile                             |    2 +
 drivers/pinmux/Kconfig                       |   26 +
 drivers/pinmux/Makefile                      |    5 +
 drivers/pinmux/core.c                        |  740 ++++++++++++++++++++++++++
 include/linux/pinmux.h                       |  224 ++++++++
 9 files changed, 1323 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-pinmux
 create mode 100644 Documentation/pinmux.txt
 create mode 100644 drivers/pinmux/Kconfig
 create mode 100644 drivers/pinmux/Makefile
 create mode 100644 drivers/pinmux/core.c
 create mode 100644 include/linux/pinmux.h
Documentation/ABI/testing/sysfs-class-pinmux new file +11 -0
new file mode 100644
index 0000000..f2a0ba8
@@ -0,0 +1,11 @@
+What:		/sys/class/pinmux/.../name
+Date:		May 2011
+KernelVersion:	2.6.40
+Contact:	Linus Walleij <[email protected]>
+Description:
+		Each pinmux directory will contain a field called
+		name. This holds a string identifying the pinmux for
+		display purposes.
+
+		NOTE: this will be empty if no suitable name is provided
+		by platform or pinmux drivers.
Documentation/pinmux.txt new file +306 -0

306 lines not on this page · raw message

MAINTAINERS +5 -0
index 1380312..3eacca8 100644
@@ -4899,6 +4899,11 @@ L:	linux-mtd at lists.infradead.org
 S:	Maintained
 F:	drivers/mtd/devices/phram.c
 
+PINMUX SUBSYSTEM
+M:	Linus Walleij <[email protected]>
+S:	Maintained
+F:	drivers/pinmux/
+
 PKTCDVD DRIVER
 M:	Peter Osterlund <[email protected]>
 S:	Maintained
drivers/Kconfig +4 -0
index 177c7d1..28d13b3 100644
@@ -54,6 +54,10 @@ source "drivers/spi/Kconfig"
 
 source "drivers/pps/Kconfig"
 
+# pinmux before gpio - gpio drivers may need it
+
+source "drivers/pinmux/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/w1/Kconfig"
drivers/Makefile +2 -0
index 3f135b6..cb7ae50 100644
@@ -5,6 +5,8 @@
 # Rewritten to use lists instead of if-statements.
 #
 
+# GPIO must come after pinmux as gpios may need to mux pins
+obj-y				+= pinmux/
 obj-y				+= gpio/
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
drivers/pinmux/Kconfig new file +26 -0
new file mode 100644
index 0000000..3073ccc
@@ -0,0 +1,26 @@
+#
+# PINMUX infrastructure and drivers
+#
+
+config MACH_HAS_PINMUX
+       bool
+
+menuconfig PINMUX
+	bool "PINMUX Support"
+	default y if MACH_HAS_PINMUX
+	depends on SYSFS && EXPERIMENTAL
+	help
+	  This enables the PINMUX subsystem for multiplexing pins
+	  on primarily PGA and BGA packages for systems on chip.
+
+	  If unsure, say N.
+
+if PINMUX
+
+config DEBUG_PINMUX
+	bool "Debug PINMUX calls"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to add some extra checks and diagnostics to PINMUX calls.
+
+endif
drivers/pinmux/Makefile new file +5 -0
new file mode 100644
index 0000000..c0ea542
@@ -0,0 +1,5 @@
+# generic pinmux support
+
+ccflags-$(CONFIG_DEBUG_PINMUX)	+= -DDEBUG
+
+obj-$(CONFIG_PINMUX)		+= core.o
drivers/pinmux/core.c new file +740 -0

740 lines not on this page · raw message

include/linux/pinmux.h new file +224 -0

224 lines not on this page · raw message

Signature · 1 line
1.7.3.2
#1 lore raw

drivers/pinmux/core.c

Quoted 2 lines · Linus Walleij

From: Linus Walleij <[email protected]>

drivers/pinmux/core.c +0 -0

Trivial comments follow

[]

drivers/pinmux/core.c line 82

Quoted 7 lines
drivers/pinmux/core.c +7 -0
+static ssize_t pinmux_name_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct pinmux_dev *pmxdev = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", pmxdev_get_name(pmxdev));
+}

Unsized buffer, maybe snprintf?

drivers/pinmux/core.c line 118

Quoted 9 lines
drivers/pinmux/core.c +9 -0
+static int pin_request(int pin, const char *function, bool gpio)
+{
+	struct pin_desc *desc;
+	struct pinmux_dev *pmxdev;
+	struct pinmux_ops *ops;
+	int status = -EINVAL;
+	unsigned long flags;
+
+	pr_debug("pin_request: request pin %d for %s\n", pin, function);

pr_debug("%s: request pin...", __func__?

drivers/pinmux/core.c line 120

Quoted 1 line
drivers/pinmux/core.c +1 -0
+		pr_err("pin_request: pin is invalid\n");

same here, etc...

drivers/pinmux/core.c line 137

Quoted 2 lines
drivers/pinmux/core.c +2 -0
+	if (!pmxdev) {
+		pr_warning("pin_warning: no pinmux device is handling %d!\n",

You use both pr_warning and pr_warn. Please just use pr_warn. Why use "pin_warning: "?

Maybe it'd be better to add

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
or
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__

if you really want __func__.
I suggest that __func__ isn't useful.

drivers/pinmux/core.c line 180

Quoted 4 lines
drivers/pinmux/core.c +4 -0
+	spin_unlock_irqrestore(&pin_desc_lock, flags);
+	if (status)
+		pr_err("pinmux pin_request: pin-%d (%s) status %d\n",
+		       pin, function ? : "?", status);

"pinmux_pin_request: "?

drivers/pinmux/core.c line 591

Quoted 7 lines
drivers/pinmux/core.c +7 -0
+static int pinmux_devices_show(struct seq_file *s, void *what)
+{
+	struct pinmux_dev *pmxdev;
+
+	seq_printf(s, "Available pinmux settings per pinmux device:\n");
+	list_for_each_entry(pmxdev, &pinmuxdev_list, node) {
+		struct pinmux_ops *ops = pmxdev->desc->ops;

const struct pinmux_ops?

drivers/pinmux/core.c line 594

Quoted 3 lines
drivers/pinmux/core.c +3 -0
+		unsigned selector = 0;
+
+		seq_printf(s, "\nDevice %s:\n", pmxdev->desc->name);

I think the initial newline isn't necessary.

Quoted 10 lines
drivers/pinmux/core.c +10 -0
+		while (ops->list_functions(pmxdev, selector) >= 0) {
+			unsigned *pins;
+			unsigned num_pins;
+			const char *func = ops->get_function_name(pmxdev,
+								  selector);
+			int ret;
+			int i;
+
+			ret = ops->get_function_pins(pmxdev, selector,
+						     &pins, &num_pins);

drivers/pinmux/core.c line 614

Quoted 10 lines
drivers/pinmux/core.c +10 -0
+
+			if (ret)
+				seq_printf(s, "%s [ERROR GETTING PINS]\n",
+					   func);
+
+			else {
+				seq_printf(s, "function: %s, pins = [ ", func);
+				for (i = 0; i < num_pins; i++)
+					seq_printf(s, "%d ", pins[i]);
+				seq_printf(s, "]\n");

seq_printf used without additional arguments could be seq_puts

drivers/pinmux/core.c line 707

Quoted 1 line
drivers/pinmux/core.c +1 -0
+		pr_warn("pinmux: failed to create debugfs directory\n");

[]

drivers/pinmux/core.c line 717

Quoted 6 lines
drivers/pinmux/core.c +6 -0
+	(void) debugfs_create_file("devices", S_IFREG | S_IRUGO,
+				   debugfs_root, NULL, &pinmux_devices_ops);
+	(void) debugfs_create_file("maps", S_IFREG | S_IRUGO,
+				   debugfs_root, NULL, &pinmux_maps_ops);
+	(void) debugfs_create_file("pins", S_IFREG | S_IRUGO,
+				   debugfs_root, NULL, &pinmux_pins_ops);

Unnecessary casts to (void)?

drivers/pinmux/core.c line 733

Quoted 6 lines
drivers/pinmux/core.c +6 -0
+static int __init pinmux_init(void)
+{
+	int ret;
+
+	ret = class_register(&pinmux_class);
+	pr_info("pinmux framwork: handle up to %d pins\n", MACH_NR_PINS);

framework?

include/linux/pinmux.h

Quoted 1 line
include/linux/pinmux.h +0 -0

[]

include/linux/pinmux.h line 74

Quoted 8 lines
include/linux/pinmux.h +8 -0
+/*
+ * Valid pin numbers are nonnegative and < MACH_NR_PINS. Invalid numbers can
+ * be used to indicate no-such-pin.
+ */
+static inline int pin_is_valid(int pin)
+{
+	return ((unsigned)pin) < MACH_NR_PINS;
+}

Couldn't pin just be declared unsigned or maybe u32?

#2 lore raw

2011/5/2 Joe Perches <[email protected]>:

Quoted 7 lines · Linus Walleij

drivers/pinmux/core.c

Quoted 2 lines

From: Linus Walleij <[email protected]>

drivers/pinmux/core.c +0 -0

Trivial comments follow

[]

Quoted 9 lines

drivers/pinmux/core.c line 82

Quoted 7 lines
drivers/pinmux/core.c +7 -0
+static ssize_t pinmux_name_show(struct device *dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct device_attribute *attr, char *buf)
+{
+ ? ? struct pinmux_dev *pmxdev = dev_get_drvdata(dev);
+
+ ? ? return sprintf(buf, "%s\n", pmxdev_get_name(pmxdev));
+}

Unsized buffer, maybe snprintf?

This is the idiomatic way of providing sysfs strings (compare e.g. *_show() in drivers/regulator/core.c), the char *buf comes from the sysfs core in struct device_attribute in <linus/device.h> with this prototype:

ssize_t (*show)(struct device *dev, struct device_attribute *attr,

                        char *buf);

and I have no way of knowing how large that buffer is. Migrating all of sysfs to provide the size of its buffers may help but do you really mean I should do that as part of this patchset? It will require refactoring the entire kernel :-(

Quoted 12 lines

drivers/pinmux/core.c

Quoted 9 lines
drivers/pinmux/core.c +9 -0
+static int pin_request(int pin, const char *function, bool gpio)
+{
+ ? ? struct pin_desc *desc;
+ ? ? struct pinmux_dev *pmxdev;
+ ? ? struct pinmux_ops *ops;
+ ? ? int status = -EINVAL;
+ ? ? unsigned long flags;
+
+ ? ? pr_debug("pin_request: request pin %d for %s\n", pin, function);

pr_debug("%s: request pin...", __func__?

Quoted 3 lines
Quoted 1 line

+ ? ? ? ? ? ? pr_err("pin_request: pin is invalid\n");

same here, etc...

What I am referring to here is not the name of the C function being executed but the function that this group of pins is performing, so a different ontology altogether.

But the prefix is indeed the function name so I get what you mean, fixing it!

Quoted 4 lines
Quoted 2 lines

+ ? ? if (!pmxdev) {
+ ? ? ? ? ? ? pr_warning("pin_warning: no pinmux device is handling %d!\n",

You use both pr_warning and pr_warn. ?Please just use pr_warn.

Sure.

Quoted 1 line

Why use "pin_warning: "?

I was drunk.

Quoted 8 lines

Maybe it'd be better to add

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
or
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__

if you really want __func__.
I suggest that __func__ isn't useful.

Yep, I'll use the first one and replace all prefixes with pure meaningful messages instead.

(Omitting such comments below - all fixed.)

Quoted 9 lines

drivers/pinmux/core.c

Quoted 7 lines
drivers/pinmux/core.c +7 -0
+static int pinmux_devices_show(struct seq_file *s, void *what)
+{
+ ? ? struct pinmux_dev *pmxdev;
+
+ ? ? seq_printf(s, "Available pinmux settings per pinmux device:\n");
+ ? ? list_for_each_entry(pmxdev, &pinmuxdev_list, node) {
+ ? ? ? ? ? ? struct pinmux_ops *ops = pmxdev->desc->ops;

const struct pinmux_ops?

Yepps, const:ed it everywhere!

Quoted 5 lines
Quoted 3 lines

+ ? ? ? ? ? ? unsigned selector = 0;
+
+ ? ? ? ? ? ? seq_printf(s, "\nDevice %s:\n", pmxdev->desc->name);

I think the initial newline isn't necessary.

Nope. Leftover.

Quoted 14 lines
Quoted 14 lines

+ ? ? ? ? ? ? while (ops->list_functions(pmxdev, selector) >= 0) {
+ ? ? ? ? ? ? ? ? ? ? unsigned *pins;
+ ? ? ? ? ? ? ? ? ? ? unsigned num_pins;
+ ? ? ? ? ? ? ? ? ? ? const char *func = ops->get_function_name(pmxdev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? selector);
+ ? ? ? ? ? ? ? ? ? ? int ret;
+ ? ? ? ? ? ? ? ? ? ? int i;

drivers/pinmux/core.c +7 -0
+
+ ? ? ? ? ? ? ? ? ? ? ret = ops->get_function_pins(pmxdev, selector,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&pins, &num_pins);
+
+ ? ? ? ? ? ? ? ? ? ? if (ret)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? seq_printf(s, "%s [ERROR GETTING PINS]\n",
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?func);
Quoted 8 lines
Quoted 6 lines

+
+ ? ? ? ? ? ? ? ? ? ? else {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? seq_printf(s, "function: %s, pins = [ ", func);
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (i = 0; i < num_pins; i++)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? seq_printf(s, "%d ", pins[i]);
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? seq_printf(s, "]\n");

seq_printf used without additional arguments could be seq_puts

Yep, fixed everywhere I sent in a non-argumented string.

Quoted 8 lines
Quoted 6 lines

+ ? ? (void) debugfs_create_file("devices", S_IFREG | S_IRUGO,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?debugfs_root, NULL, &pinmux_devices_ops);
+ ? ? (void) debugfs_create_file("maps", S_IFREG | S_IRUGO,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?debugfs_root, NULL, &pinmux_maps_ops);
+ ? ? (void) debugfs_create_file("pins", S_IFREG | S_IRUGO,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?debugfs_root, NULL, &pinmux_pins_ops);

Unnecessary casts to (void)?

Yep lost them.

Quoted 8 lines

drivers/pinmux/core.c

Quoted 6 lines
drivers/pinmux/core.c +6 -0
+static int __init pinmux_init(void)
+{
+ ? ? int ret;
+
+ ? ? ret = class_register(&pinmux_class);
+ ? ? pr_info("pinmux framwork: handle up to %d pins\n", MACH_NR_PINS);

framework?

Should be subsystem. Fixed it.

Quoted 12 lines

include/linux/pinmux.h

Quoted 1 line
include/linux/pinmux.h +0 -0

[]

include/linux/pinmux.h line 74

Quoted 8 lines
include/linux/pinmux.h +8 -0
+/*
+ * Valid pin numbers are nonnegative and < MACH_NR_PINS. Invalid numbers can
+ * be used to indicate no-such-pin.
+ */
+static inline int pin_is_valid(int pin)
+{
+ ? ? return ((unsigned)pin) < MACH_NR_PINS;
+}

Couldn't pin just be declared unsigned or maybe u32?

No, because like in the GPIO subsystem you *may* want to send in invalid pins, and those are identified by negative numbers.

Thanks a *lot* for your detailed review Joe, please supply your Reviewed-by:
on the next (v2) patch set if you think it looks alright.

Yours,
Linus Walleij

#3 lore raw
Quoted 5 lines · Linus Walleij

2011/5/2 Joe Perches <[email protected]>:

Quoted 4 lines · Linus Walleij

drivers/pinmux/core.c

Quoted 2 lines

From: Linus Walleij <[email protected]>

drivers/pinmux/core.c +0 -0

Trivial comments follow

Quoted 7 lines
Quoted 5 lines

drivers/pinmux/core.c

Quoted 4 lines
drivers/pinmux/core.c +4 -0
+static inline int pin_is_valid(int pin)
+{
+     return ((unsigned)pin) < MACH_NR_PINS;
+}

Couldn't pin just be declared unsigned or maybe u32?

No, because like in the GPIO subsystem you *may* want to send in invalid pins, and those are identified by negative numbers.

Then I think this is clearer and the compiler
should produce the same code.

static inline bool pin_is_valid(int pin)

{ 
	return pin >= 0 && pin < MACH_NR_PINS;
}

cheers, Joe

#4 lore raw

2011/5/11 Joe Perches <[email protected]>:

Quoted 14 lines · Linus Walleij
Quoted 5 lines

2011/5/2 Joe Perches <[email protected]>:

Quoted 4 lines · Linus Walleij

drivers/pinmux/core.c

Quoted 2 lines

From: Linus Walleij <[email protected]>

drivers/pinmux/core.c +0 -0

Trivial comments follow

Quoted 7 lines
Quoted 5 lines

drivers/pinmux/core.c

Quoted 4 lines
drivers/pinmux/core.c +4 -0
+static inline int pin_is_valid(int pin)
+{
+ ? ? return ((unsigned)pin) < MACH_NR_PINS;
+}

Couldn't pin just be declared unsigned or maybe u32?

No, because like in the GPIO subsystem you *may* want to send in invalid pins, and those are identified by negative numbers.

Quoted 7 lines

Then I think this is clearer and the compiler
should produce the same code.

static inline bool pin_is_valid(int pin)
{
? ? ? ?return pin >= 0 && pin < MACH_NR_PINS;
}

Yes indeed, I'll fix. Can you propose a patch to the same pattern found in include/asm-generic/gpio.h? It would bring equal clarity there I believe.

Thanks!
Linus Walleij

#5 lore raw

PATCH 1/1 gpio: Convert gpio_is_valid to return bool

Make the code a bit more readable.

Instead of casting an int to an unsigned then comparing to MAX_NR_GPIOS, add a >= 0 test and let the compiler optimizer do the conversion to unsigned.

The generated code should be the same.

---

This came up because of a new pinmux subsystem that used a style copied from gpio and a request from Linus Walleij.

Quoted 20 lines · Linus Walleij

2011/5/11 Joe Perches <[email protected]>:

Quoted 11 lines · Linus Walleij
Quoted 10 lines

2011/5/2 Joe Perches <[email protected]>:

Quoted 9 lines · Linus Walleij

drivers/pinmux/core.c

Quoted 2 lines

From: Linus Walleij <[email protected]>

drivers/pinmux/core.c +0 -0

Trivial comments follow

drivers/pinmux/core.c

Quoted 4 lines
drivers/pinmux/core.c +4 -0
+static inline int pin_is_valid(int pin)
+{
+     return ((unsigned)pin) < MACH_NR_PINS;
+}

Couldn't pin just be declared unsigned or maybe u32?

Quoted 8 lines
Quoted 2 lines

No, because like in the GPIO subsystem you *may* want to send in invalid pins, and those are identified by negative numbers.

Then I think this is clearer and the compiler
should produce the same code.
static inline bool pin_is_valid(int pin)

{
       return pin >= 0 && pin < MACH_NR_PINS;
}
Quoted 3 lines

Yes indeed, I'll fix. Can you propose a patch to the same pattern found in include/asm-generic/gpio.h? It would bring equal clarity there I believe.

 include/asm-generic/gpio.h |    6 +++---
 include/linux/gpio.h       |    4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)
include/asm-generic/gpio.h +3 -3
index ce16e70..315ecb7 100644
@@ -35,9 +35,9 @@
  * platform data and other tables.
  */
 
-static inline int gpio_is_valid(int number)
+static inline bool gpio_is_valid(int number)
 {
-	return ((unsigned)number) < ARCH_NR_GPIOS;
+	return number >= 0 && number < ARCH_NR_GPIOS;
 }
 
 struct device;
@@ -216,7 +216,7 @@ extern void gpio_unexport(unsigned gpio);
 
 #else	/* !CONFIG_GPIOLIB */
 
-static inline int gpio_is_valid(int number)
+static inline bool gpio_is_valid(int number)
 {
 	/* only non-negative numbers are valid */
 	return number >= 0;
include/linux/gpio.h +2 -2
index fa92e50..0af3bca 100644
@@ -79,9 +79,9 @@ struct gpio_chip;
  * warning when something is wrongly called.
  */
 
-static inline int gpio_is_valid(int number)
+static inline bool gpio_is_valid(int number)
 {
-	return 0;
+	return false;
 }
 
 static inline int gpio_request(unsigned gpio, const char *label)
Acked-by on v1 1/1
#6 lore raw

Re: [PATCH] gpio: Convert gpio_is_valid to return bool

2011/5/11 Joe Perches <[email protected]>:

Quoted 9 lines

Make the code a bit more readable.

Instead of casting an int to an unsigned then comparing to MAX_NR_GPIOS, add a >= 0 test and let the compiler optimizer do the conversion to unsigned.

The generated code should be the same.

Thanks Joe!
Linus Walleij

Applied
#7 lore raw

Re: [PATCH] gpio: Convert gpio_is_valid to return bool

In reply to Joe Perches
Quoted 9 lines · Joe Perches

Make the code a bit more readable.

Instead of casting an int to an unsigned then comparing to MAX_NR_GPIOS, add a >= 0 test and let the compiler optimizer do the conversion to unsigned.

The generated code should be the same.

Applied, thanks.

g.

#8 lore raw
In reply to Linus Walleij
Quoted 9 lines · Linus Walleij

This is the idiomatic way of providing sysfs strings (compare e.g. *_show() in drivers/regulator/core.c), the char *buf comes from the sysfs core in struct device_attribute in <linus/device.h> with this prototype:

ssize_t (*show)(struct device *dev, struct device_attribute *attr,

                        char *buf);

and I have no way of knowing how large that buffer is. Migrating all

It's implicitly PAGE_SIZE. In pretty much all users the buffer is constrained to well below that by the inputs (sometimes with some help from users not using insanely long names for things) and the sysfs semantics which mean you probably got something badly wrong if you get anywhere near PAGE_SIZE.

#9 lore raw
In reply to Linus Walleij

Linus Walleij wrote at Monday, May 02, 2011 1:16 PM:

Quoted 5 lines

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

I would avoid any references to particular package types; I've seen pinmuxing applied to PLCC and DIP/DIL too, and in general, it's possible irrespective of package type.

Documentation/pinmux.txt line 76

Quoted 12 lines

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

Documentation/pinmux.txt +5 -0
...
+The mux settings are:
+
+- Oriented around enumerated physical pins or pads denoted by unsigned
+  integers in the range 0..MAX_INT. Every pin on your system (or atleast
+  every pin that can be muxed) should have a unique number. The numberspace

Does this imply a model where each pin's "special function" can be controlled independently? I think reading through the document that isn't the case, but I just wanted to be sure.

In particular, NVIDIA Tegra has a setup where:

* Pinmux configuration for "special functions" is at a "pad-group" level, where there may be 1..N pins in a pad-group, and there is a single register field that defines the current special function routed to/from all pins in that pad-group at once.

* Each pad group can be assigned 1 of N special functions (none might be an option in some/all cases too)

* Some special functions may be assignable to multiple pad groups, although obviously only 1 pad group per function at a time.

* GPIO selection is at per-pin granularity; individual pins may be used as a GPIO irrespective of what SFR is selected for the pad group containing the pin.

* There are also other configurations associated with pinmuxing, such as drive strength, pull up/down enables, etc.

Also, some of our drivers use "dynamic pinmuxing". For example, our downstream I2C driver exposes N I2C busses and reprograms the pinmux at runtime to attach the actual I2C controller to different sets of pins, essentially multi-plexing the control across N physical busses.

include/linux/pinmux.h line 22

Quoted 9 lines
include/linux/pinmux.h new file +3 -0
new file mode 100644
index 0000000..9bdcc33
 
+/**
+ * struct pinmux_map - boards/machines shall provide this map for devices
+ * @node: list node - only for internal use

Node isn't in the structure.

Quoted 10 lines

+ * @function: a functional name for this mapping so it can be passed down
+ * to the driver to invoke that function and be referenced by this ID
+ * in e.g. pinmux_get()
+ * @dev: the device using this specific mapping, may be NULL if you provide
+ * .dev_name instead (this is more common)
+ * @dev_name: the name of the device using this specific mapping, the name
+ * must be the same that will return your struct device*
+ */

include/linux/pinmux.h new file +2 -0
+struct pinmux_map {
+	const char *function;

include/linux/pinmux.h line 55

Quoted 10 lines
include/linux/pinmux.h new file +9 -0
+	struct device *dev;
+	const char *dev_name;
+};
 
+/*
+ * The pin number is a global pin number space, nominally the arch shall define
+ * the number of pins in *total* across all chips in the arch/system.
+ *
+ * Example: if your arch has two chips with 64 pins each, you have
+ * 8*3 = 24 MACH_NR_PINS.

2*64 = 128 MACH_NR_PINS ?

Quoted 18 lines
include/linux/pinmux.h new file +18 -0
+struct pinmux_dev;
+
+/**
+ * struct pinmux_ops - pinmux operations, to be implemented by drivers
+ * @request: called by the core to see if a certain pin can be muxed in
+ *	and made available in a certain mux setting The driver is allowed
+ *	to answer "no" by returning a negative error code
+ * @list_functions: list the number of selectable named functions available
+ *	in this pinmux driver, the core will begin on 0 and call this
+ *	repeatedly as long as it returns >= 0 to enumerate mux settings
+ * @get_function_name: return the function name of the muxing selector,
+ *	called by the core to figure out which mux setting it shall map a
+ *	certain device to
+ * @get_function_pins: return an array of pins corresponding to a certain
+ *	function selector in @pins, and the size of the array in @num_pins
+ * @enable: enable a certain muxing enumerator. The driver does not need to
+ *	figure out whether enabling this function conflicts some other use
+ *	of the pins, such collisions are handled by the pinmux subsystem

include/linux/pinmux.h line 103

Quoted 10 lines
include/linux/pinmux.h new file +10 -0
+ * @disable: disable a certain muxing enumerator
+ * @gpio_request_enable: requests and enables GPIO on a certain pin.
+ *	Implement this only if you can mux every pin individually as GPIO. If
+ *	your gpio assignments are grouped, so you cannot control the GPIO
+ *	muxing of every indvidual pin.
+ * @dbg_show: optional debugfs display hook that will provide per-device
+ *	info for a certain pin in debugfs
+ */
+struct pinmux_ops {
+	int (*request) (struct pinmux_dev *pmxdev, unsigned offset);

s/offset/pin/? I assume that's what it means. Same for gpio_request_enable below too.

Quoted 12 lines
include/linux/pinmux.h new file +12 -0
+	int (*free) (struct pinmux_dev *pmxdev, unsigned offset);
+	int (*list_functions) (struct pinmux_dev *pmxdev, unsigned selector);
+	const char *(*get_function_name) (struct pinmux_dev *pmxdev,
+					unsigned selector);
+	int (*get_function_pins) (struct pinmux_dev *pmxdev, unsigned selector,
+			unsigned ** const pins, unsigned * const num_pins);
+	int (*enable) (struct pinmux_dev *pmxdev, unsigned selector);
+	void (*disable) (struct pinmux_dev *pmxdev, unsigned selector);
+	int (*gpio_request_enable) (struct pinmux_dev *pmxdev, unsigned offset);
+	void (*dbg_show) (struct pinmux_dev *pmxdev, struct seq_file *s,
+			  unsigned offset);
+};

include/linux/pinmux.h line 125

Quoted 10 lines
include/linux/pinmux.h new file +10 -0
+
+/**
+ * struct pinmux_desc - pinmux descriptor, register this to pinmux subsystem
+ * @name: name for the pinmux
+ * @ops: pinmux operation table
+ * @owner: module providing the pinmux, used for refcounting
+ * @base: the number of the first pin handled by this pinmux, in the global
+ *	pin space, subtracted from a given pin to get the offset into the range
+ *	of a certain pinmux
+ * @no_pin_settings: the number of pins handled by this pinmux - note that

That's npins below.

Quoted 5 lines

+ * this is the number of possible pin settings, if your driver handles
+ * 8 pins that each can be muxed in 3 different ways, you reserve 24
+ * pins in the global pin space and set this to 24
+ */

include/linux/pinmux.h new file +1 -0
+struct pinmux_desc {

include/linux/pinmux.h line 171

Quoted 10 lines
include/linux/pinmux.h new file +9 -0
+	const char *name;
+	struct pinmux_ops *ops;
+	struct module *owner;
+	int base;
+	int npins;
+};
 
+/* External interface to pinmux */
+extern int pinmux_request_gpio(int pin, unsigned gpio);
+extern void pinmux_free_gpio(int pin);

Is there (or should there be) any automatic interaction with gpiolib?

include/linux/pinmux.h line 174

Quoted 3 lines
include/linux/pinmux.h new file +3 -0
+extern int pinmux_register_mappings(struct pinmux_map const *map,
+				    unsigned num_maps);
+extern struct pinmux *pinmux_get(struct device *dev, const char *func);

I feel slightly uneasy tying the pinmux API to devices rather than Letting it be more free-form. I've seen this pattern for clocks too, but IIRC there is an override there allowing specification of a NULL device in order to look up a clock by raw clock name instead of device + sub-clock-name right?

Still, I'm a relative neophyte regarding internal Linux kernel APIs, so my opinion here may not be particularly relevant.

Signature · 1 line
nvpublic
#10 lore raw
Quoted 45 lines · Stephen Warren

Linus Walleij wrote at Monday, May 02, 2011 1:16 PM:

Quoted 5 lines

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

I would avoid any references to particular package types; I've seen pinmuxing applied to PLCC and DIP/DIL too, and in general, it's possible irrespective of package type.

Documentation/pinmux.txt

Quoted 12 lines

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

Documentation/pinmux.txt +5 -0
...
+The mux settings are:
+
+- Oriented around enumerated physical pins or pads denoted by unsigned
+ ?integers in the range 0..MAX_INT. Every pin on your system (or atleast
+ ?every pin that can be muxed) should have a unique number. The numberspace

Does this imply a model where each pin's "special function" can be controlled independently? I think reading through the document that isn't the case, but I just wanted to be sure.

In particular, NVIDIA Tegra has a setup where:

* Pinmux configuration for "special functions" is at a "pad-group" ?level, where there may be 1..N pins in a pad-group, and there is a ?single register field that defines the current special function routed ?to/from all pins in that pad-group at once.

* Each pad group can be assigned 1 of N special functions (none might be ?an option in some/all cases too)

* Some special functions may be assignable to multiple pad groups, ?although obviously only 1 pad group per function at a time.

* GPIO selection is at per-pin granularity; individual pins may be used ?as a GPIO irrespective of what SFR is selected for the pad group ?containing the pin.

Quoted 7 lines

* There are also other configurations associated with pinmuxing, such ?as drive strength, pull up/down enables, etc.

Also, some of our drivers use "dynamic pinmuxing". For example, our downstream I2C driver exposes N I2C busses and reprograms the pinmux at runtime to attach the actual I2C controller to different sets of pins, essentially multi-plexing the control across N physical busses.

Tegra has more fun pinmux quirks than just those :)

* Drive strength is also controlled through groups of pins, but different groups than pinmux. Most of the drive strength groups are collections of pad mux groups, but there are a few pins that are in the same pad mux group but a different drive strength group.
* Setting a pin as a GPIO overrides its group's mux setting, except for the group's tristate. You must untristate the entire group to use a single pin as a GPIO.
* Each group has a "safe mode", but which mux id to select to enter the safe mode is completely random.

In the end, we determined that there was no way to sanely handle setting up Tegra's pinmux programatically, and instead required each board to pass in a table of pinmux settings.

#11 lore raw
Quoted 11 lines · Colin Cross

On Mon, May 2, 2011 at 1:52 PM, Stephen Warren <[email protected]> wrote:

* Drive strength is also controlled through groups of pins, but different groups than pinmux. Most of the drive strength groups are collections of pad mux groups, but there are a few pins that are in the same pad mux group but a different drive strength group.
* Setting a pin as a GPIO overrides its group's mux setting, except for the group's tristate. You must untristate the entire group to use a single pin as a GPIO.
* Each group has a "safe mode", but which mux id to select to enter the safe mode is completely random.

Just posted something in this thread regarding using standard data and standard read and write functions, then allow setting platform specific custom flags as needed. Care to see if that works for you too?

Quoted 3 lines

In the end, we determined that there was no way to sanely handle setting up Tegra's pinmux programatically, and instead required each board to pass in a table of pinmux settings.

Eventually we should get the package specific table of available pins and the board specific settings in devicetree data. And then it's easy to set the pins as desired while being able to debug it.

Regards,

Tony

#12 lore raw
Quoted 13 lines · Tony Lindgren
Quoted 11 lines · Colin Cross

On Mon, May 2, 2011 at 1:52 PM, Stephen Warren <[email protected]> wrote:

* Drive strength is also controlled through groups of pins, but different groups than pinmux. ?Most of the drive strength groups are collections of pad mux groups, but there are a few pins that are in the same pad mux group but a different drive strength group.
* Setting a pin as a GPIO overrides its group's mux setting, except for the group's tristate. ?You must untristate the entire group to use a single pin as a GPIO.
* Each group has a "safe mode", but which mux id to select to enter the safe mode is completely random.

Quoted 3 lines

Just posted something in this thread regarding using standard data and standard read and write functions, then allow setting platform specific custom flags as needed. Care to see if that works for you too?

Tegra does not allow pin muxing on the pin by pin basis. And, registers that define mux config differ from those that define flags (pull, driver strength, safe mode etc).

Quoted 17 lines
Quoted 3 lines

In the end, we determined that there was no way to sanely handle setting up Tegra's pinmux programatically, and instead required each board to pass in a table of pinmux settings.

Eventually we should get the package specific table of available pins and the board specific settings in devicetree data. And then it's easy to set the pins as desired while being able to debug it.

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html Please read the FAQ at ?http://www.tux.org/lkml/

Signature · 2 lines
? ? Sincerely Yours,
? ? ? ? Mike.
#13 lore raw
Quoted 14 lines · Mike Rapoport
Quoted 13 lines · Tony Lindgren
Quoted 11 lines · Colin Cross

On Mon, May 2, 2011 at 1:52 PM, Stephen Warren <[email protected]> wrote:

* Drive strength is also controlled through groups of pins, but different groups than pinmux. ?Most of the drive strength groups are collections of pad mux groups, but there are a few pins that are in the same pad mux group but a different drive strength group.
* Setting a pin as a GPIO overrides its group's mux setting, except for the group's tristate. ?You must untristate the entire group to use a single pin as a GPIO.
* Each group has a "safe mode", but which mux id to select to enter the safe mode is completely random.

Quoted 7 lines
Quoted 3 lines

Just posted something in this thread regarding using standard data and standard read and write functions, then allow setting platform specific custom flags as needed. Care to see if that works for you too?

Tegra does not allow pin muxing on the pin by pin basis. And, registers that define mux config differ from those that define flags (pull, driver strength, safe mode etc).

Hmm well the separate config register could be added easily. But the grouping of pins might be tricky then :)

Tony

#14 lore raw
In reply to Stephen Warren
Quoted 16 lines · Stephen Warren

Linus Walleij wrote at Monday, May 02, 2011 1:16 PM:

Quoted 5 lines

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

I would avoid any references to particular package types; I've seen pinmuxing applied to PLCC and DIP/DIL too, and in general, it's possible irrespective of package type.

Quoted 4 lines

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

Quoted 11 lines

Documentation/pinmux.txt line 76

Quoted 7 lines
Documentation/pinmux.txt +5 -0
...
+The mux settings are:
+
+- Oriented around enumerated physical pins or pads denoted by unsigned
+  integers in the range 0..MAX_INT. Every pin on your system (or atleast
+  every pin that can be muxed) should have a unique number. The numberspace

Does this imply a model where each pin's "special function" can be controlled independently? I think reading through the document that isn't the case, but I just wanted to be sure.

The relevant driver can /request/ each special function independently but if the pinmux driver can't implement it for whatever reason, including being batshit-crazy like Tegra, it can just return an error. It's still up to the board designer to ensure the requested setup is physically possible.

Quoted 8 lines

In particular, NVIDIA Tegra has a setup where:

* Pinmux configuration for "special functions" is at a "pad-group" level, where there may be 1..N pins in a pad-group, and there is a single register field that defines the current special function routed to/from all pins in that pad-group at once.

Quoted 5 lines

* Each pad group can be assigned 1 of N special functions (none might be an option in some/all cases too)

* Some special functions may be assignable to multiple pad groups, although obviously only 1 pad group per function at a time.

To me that all looks like it can be encapsulated by this interface

Quoted 7 lines

* GPIO selection is at per-pin granularity; individual pins may be used as a GPIO irrespective of what SFR is selected for the pad group containing the pin.

* There are also other configurations associated with pinmuxing, such as drive strength, pull up/down enables, etc.

This pin configuration stuff should be bunted to gpiolib gpio_config() callbacks which Linus implemented last week.

Quoted 5 lines

Also, some of our drivers use "dynamic pinmuxing". For example, our downstream I2C driver exposes N I2C busses and reprograms the pinmux at runtime to attach the actual I2C controller to different sets of pins, essentially multi-plexing the control across N physical busses.

Neat! Should be a perfect use-case for this pinmux subsystem. Perhaps, if you've got time, you could try and implement a pinmux driver for your chip and make sure all bases are covered? Nothing like taking a madhouse chip and actually trying to code for it to shake down a new interface like this one :)

	--Ben.
#15 lore raw
In reply to Stephen Warren

2011/5/2 Stephen Warren <[email protected]>:

Quoted 10 lines

Linus Walleij wrote at Monday, May 02, 2011 1:16 PM:

Quoted 5 lines

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

I would avoid any references to particular package types; I've seen pinmuxing applied to PLCC and DIP/DIL too, and in general, it's possible irrespective of package type.

Sure dropping parts of that. I'll try to reify the package concept a bit. However since I have this nice chessboard example I have to say what I'm talking about, the topology of this 2D PGA field is pretty fun.

Quoted 8 lines

Documentation/pinmux.txt

Quoted 5 lines
Documentation/pinmux.txt new file +5 -0
+The mux settings are:
+
+- Oriented around enumerated physical pins or pads denoted by unsigned
+ ?integers in the range 0..MAX_INT. Every pin on your system (or atleast
+ ?every pin that can be muxed) should have a unique number. The numberspace

Does this imply a model where each pin's "special function" can be controlled independently?

No not at all. This is defining the terms.

Quoted 6 lines

In particular, NVIDIA Tegra has a setup where:

* Pinmux configuration for "special functions" is at a "pad-group" ?level, where there may be 1..N pins in a pad-group, and there is a ?single register field that defines the current special function routed ?to/from all pins in that pad-group at once.

Perfect fit with this pinmux API.

Quoted 2 lines

* Each pad group can be assigned 1 of N special functions (none might be ?an option in some/all cases too)

Perfect fit with this pinmux API.

Quoted 2 lines

* Some special functions may be assignable to multiple pad groups, ?although obviously only 1 pad group per function at a time.

Perfect fit with this pinmux API.

Quoted 3 lines

* GPIO selection is at per-pin granularity; individual pins may be used ?as a GPIO irrespective of what SFR is selected for the pad group ?containing the pin.

Perfect fit with this pinmux API. The Nomadik pinmux is basically the same.

Note that the pinmux API makes sure you haven't used a single pin for GPIO at the same time as you're using a group containing the same pin.

Quoted 2 lines

* There are also other configurations associated with pinmuxing, such ?as drive strength, pull up/down enables, etc.

I am currently contemplating whether to include a control function for this stuff in the pinmux API. I probably will, and then make sure the enumerators match those I have just defined for GPIO (since there may be systems with such settings for just GPIO pins (which cannot be muxed) and vice versa for muxable pins that cannot be used for GPIO but still driven low if unused for example.

Quoted 4 lines

Also, some of our drivers use "dynamic pinmuxing". For example, our downstream I2C driver exposes N I2C busses and reprograms the pinmux at runtime to attach the actual I2C controller to different sets of pins, essentially multi-plexing the control across N physical busses.

Just pinmux_get()/pinmux_put()/pinmux_get()/pinmux_put() to switch these functions in/out at runtime. (Described in reply to Russell in patch 0.)

Quoted 5 lines
Quoted 3 lines

+/**
+ * struct pinmux_map - boards/machines shall provide this map for devices
+ * @node: list node - only for internal use

Node isn't in the structure.

Thanks, leftover, removed it.

Quoted 8 lines
Quoted 6 lines

+/*
+ * The pin number is a global pin number space, nominally the arch shall define
+ * the number of pins in *total* across all chips in the arch/system.
+ *
+ * Example: if your arch has two chips with 64 pins each, you have
+ * 8*3 = 24 MACH_NR_PINS.

2*64 = 128 MACH_NR_PINS ?

Yeah :-P thanks.

Quoted 5 lines
Quoted 2 lines

+struct pinmux_ops {
+ ? ? int (*request) (struct pinmux_dev *pmxdev, unsigned offset);

s/offset/pin/? I assume that's what it means. Same for gpio_request_enable below too.

No not at all. Like in the case with the gpiolib, we may have several muxes on the system (e.g. in the U8500 we have alternate functions not only on the SoC package but also on the AB8500 mixsig circuit). The offset refers to the pin inside the pin range handled by that specific driver.

If you have only *one* pinmux driver on your system it will be the same thing, but not in the general case.

Quoted 11 lines
Quoted 9 lines

+/**
+ * struct pinmux_desc - pinmux descriptor, register this to pinmux subsystem
+ * @name: name for the pinmux
+ * @ops: pinmux operation table
+ * @owner: module providing the pinmux, used for refcounting
+ * @base: the number of the first pin handled by this pinmux, in the global
+ * ? pin space, subtracted from a given pin to get the offset into the range
+ * ? of a certain pinmux
+ * @no_pin_settings: the number of pins handled by this pinmux - note that

That's npins below.

Good catch, thanks!

Quoted 5 lines

include/linux/pinmux.h line 171

Quoted 3 lines
include/linux/pinmux.h new file +3 -0
+/* External interface to pinmux */
+extern int pinmux_request_gpio(int pin, unsigned gpio);
+extern void pinmux_free_gpio(int pin);

Is there (or should there be) any automatic interaction with gpiolib?

My idea is that if a certain gpiolib driver may need to request a pin that is muxed, it will translate the GPIO pin number into a pinmux pin and call pinmux_request_gpio() on that pin. So in my head only gpiolib driver under drivers/gpio() would nominally be calling this to reserve pins.

Since not all GPIOs are muxable, it'll need to be on a per-driver basis.

Quoted 9 lines

include/linux/pinmux.h line 174

Quoted 3 lines
include/linux/pinmux.h new file +3 -0
+extern int pinmux_register_mappings(struct pinmux_map const *map,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned num_maps);
+extern struct pinmux *pinmux_get(struct device *dev, const char *func);

I feel slightly uneasy tying the pinmux API to devices rather than Letting it be more free-form. I've seen this pattern for clocks too, but IIRC there is an override there allowing specification of a NULL device in order to look up a clock by raw clock name instead of device + sub-clock-name right?

Yes and that is possible with pinmux_get() too, you can specify a function not tied to a particular device.

Quoted 2 lines

Still, I'm a relative neophyte regarding internal Linux kernel APIs, so my opinion here may not be particularly relevant.

It's relevant.

Thanks a lot Stephen! Once/if you like the API, please ACK it. Linus Walleij

#16 lore raw
In reply to Linus Walleij
Quoted 10 lines · Linus Walleij

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

Haven't reviewed the actual code but at an interface level it seems sane. It'd be nice to actually implement a driver for some nutbars SoC and make sure it all shakes out but in the first instance I can't see any problems.

Leaving it orthogonal to gpio is a great move conceptually and if it does need to be tied back to the gpio_request() interface later then, well, we'll cross that bridge when we come to it.

Thanks for your work in this area, looking good.

	--Ben.
#17 lore raw
In reply to Linus Walleij

* Linus Walleij <[email protected]> [110502 12:13]:

Good to see this, looks like this should work for omaps too.

The numbering solves the issue where we have multiple pinmux domains (base + offset for each domain).

Then I would assume that for most cases the pin access can be described with:

unsigned long pinmux_base; /* Can have multiple pinux domains */
u16 pinmux_reg_offset; /* Register offset from pinmux_base */
u16 flags; /* Register width etc */

Which can be accessed with read[bwl] and write[bwl], so we can have default access functions in the pinux framework and don't necessarily have to implement them for each platform.

Does this work for you? If so, then we can have the data in the same format for all the architectures for devicetree.

And then we can have pin_get and pin_set functions, so platforms can implement their custom flags like wake-up trigger etc with just read[bwl] and write[bwl].

Also noticed one typo:

drivers/pinmux/core.c line 47

Quoted 3 lines
drivers/pinmux/core.c new file +3 -0
+/* Plobal array of descriptors, one for each physical pin */
+static DEFINE_SPINLOCK(pin_desc_lock);
+static struct pin_desc pin_desc[MACH_NR_PINS];

s/Plobal/Global/

Regards,

Tony

#18 lore raw
Quoted 10 lines · Tony Lindgren

* Linus Walleij <[email protected]> [110502 12:13]:

Good to see this, looks like this should work for omaps too.

The numbering solves the issue where we have multiple pinmux domains (base + offset for each domain).

Then I would assume that for most cases the pin access can be described with:

Quoted 7 lines

unsigned long pinmux_base; ? ? ?/* Can have multiple pinux domains */ u16 pinmux_reg_offset; ? ? ? ? ?/* Register offset from pinmux_base */ u16 flags; ? ? ? ? ? ? ? ? ? ? ?/* Register width etc */

Which can be accessed with read[bwl] and write[bwl], so we can have default access functions in the pinux framework and don't necessarily have to implement them for each platform.

On some platforms setting the pin configuration won't require to keep that lot of data, see, e.g. Orion and it's successors.

Quoted 25 lines

Does this work for you? If so, then we can have the data in the same format for all the architectures for devicetree.

And then we can have pin_get and pin_set functions, so platforms can implement their custom flags like wake-up trigger etc with just read[bwl] and write[bwl].

Also noticed one typo:

drivers/pinmux/core.c line 47

Quoted 3 lines
drivers/pinmux/core.c new file +3 -0
+/* Plobal array of descriptors, one for each physical pin */
+static DEFINE_SPINLOCK(pin_desc_lock);
+static struct pin_desc pin_desc[MACH_NR_PINS];

s/Plobal/Global/

Regards,

Tony

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html Please read the FAQ at ?http://www.tux.org/lkml/

Signature · 2 lines
? ? Sincerely Yours,
? ? ? ? Mike.
#19 lore raw
Quoted 15 lines · Mike Rapoport
Quoted 14 lines · Tony Lindgren

* Linus Walleij <[email protected]> [110502 12:13]:

Good to see this, looks like this should work for omaps too.

The numbering solves the issue where we have multiple pinmux domains (base + offset for each domain).

Then I would assume that for most cases the pin access can be described with:

unsigned long pinmux_base; ? ? ?/* Can have multiple pinux domains */ u16 pinmux_reg_offset; ? ? ? ? ?/* Register offset from pinmux_base */ u16 flags; ? ? ? ? ? ? ? ? ? ? ?/* Register width etc */

Quoted 6 lines
Quoted 3 lines

Which can be accessed with read[bwl] and write[bwl], so we can have default access functions in the pinux framework and don't necessarily have to implement them for each platform.

On some platforms setting the pin configuration won't require to keep that lot of data, see, e.g. Orion and it's successors.

Yeah but if we can figure out some common data format the wasted memory won't matter compared to having common code.

I guess if we plan on passing the mux registers in devicetree data, we actually should just have something like this for each mux entry:

address
muxmodes
flags

Don't know how well that would work for tegra, can you calculate the configuration registers from some base address maybe?

Regards,

Tony

#20 lore raw

PATCH 1/4 drivers: create a pinmux subsystem

In reply to Linus Walleij

Hi Linus,

Quoted 306 lines · Linus Walleij

From: Linus Walleij<[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

---
  Documentation/ABI/testing/sysfs-class-pinmux |   11 +
  Documentation/pinmux.txt                     |  306 +++++++++++
  MAINTAINERS                                  |    5 +
  drivers/Kconfig                              |    4 +
  drivers/Makefile                             |    2 +
  drivers/pinmux/Kconfig                       |   26 +
  drivers/pinmux/Makefile                      |    5 +
  drivers/pinmux/core.c                        |  740 ++++++++++++++++++++++++++
  include/linux/pinmux.h                       |  224 ++++++++
  9 files changed, 1323 insertions(+), 0 deletions(-)

create mode 100644 Documentation/ABI/testing/sysfs-class-pinmux create mode 100644 Documentation/pinmux.txt
create mode 100644 drivers/pinmux/Kconfig
create mode 100644 drivers/pinmux/Makefile
create mode 100644 drivers/pinmux/core.c
create mode 100644 include/linux/pinmux.h

Documentation/ABI/testing/sysfs-class-pinmux new file +11 -0
new file mode 100644
index 0000000..f2a0ba8
@@ -0,0 +1,11 @@
+What:		/sys/class/pinmux/.../name
+Date:		May 2011
+KernelVersion:	2.6.40
+Contact:	Linus Walleij<[email protected]>
+Description:
+		Each pinmux directory will contain a field called
+		name. This holds a string identifying the pinmux for
+		display purposes.
+
+		NOTE: this will be empty if no suitable name is provided
+		by platform or pinmux drivers.
Documentation/pinmux.txt new file +253 -0
new file mode 100644
index 0000000..d9850db
@@ -0,0 +1,306 @@
+PINMUX interfaces
+
+This document outlines the pin muliplexer (pinmux) subsystem in Linux
+
+These calls use the pinmux_* naming prefix.  No other calls should use that
+prefix.
+
+
+What is pinmuxing?
+==================
+
+Pinmux, also known as padmux, ballmux or alternate functions, is a way for
+chip vendors producing mainly PGA (pin grid array) and BGA (ball grid array)
+packages of using a certain physical bin (ball, pad) for multiple mutually
+exclusive functions, depending on the application.
+
+Here is an example of a chip seen from underneath:
+
+        A   B   C   D   E   F   G   H
+      +---+
+   8  | o | o   o   o   o   o   o   o
+      |   |
+   7  | o | o   o   o   o   o   o   o
+      |   |
+   6  | o | o   o   o   o   o   o   o
+      +---+---+
+   5  | o | o | o   o   o   o   o   o
+      +---+---+               +---+
+   4    o   o   o   o   o   o | o | o
+                              |   |
+   3    o   o   o   o   o   o | o | o
+                              |   |
+   2    o   o   o   o   o   o | o | o
+                              |   |
+   1    o   o   o   o   o   o | o | o
+                              +---+
+
+This is not tetris. The game to think of is chess. Not all PGA/BGA packages
+are chessboard-like, big ones have "holes" in some arrangement according to
+different design patterns, but we're using this as a simple example. Of the
+pins you see some will be taken by things like a few VCC and GND to feed power
+to the chip, and quite a few will be taken by large ports like an external
+memory interface. The remaining pins will often be subject to pin multiplexing.
+
+In this 8x8 BGA package the pins { A8, A7, A6, A5 } can be used as an SPI port
+(these are four pins: CLK, RXD, TXD, FRM). In that case, pin B5 can be used as
+some general-purpose GPIO pin. However, in another setting, pins { A5, B5 } can
+be used as an I2C port (these are just two pins: SCL, SDA). Needless to say,
+we cannot use the SPI port and I2C port at the same time. However in the inside
+of the package the silicon performing the SPI logic can alternatively be routed
+out on pins { G4, G3, G2, G1 }.
+
+This way the silicon blocks present inside the chip can be multiplexed "muxed"
+out on different pin ranges. Often contemporary SoC (systems on chip) will
+contain several I2C, SPI, SDIO/MMC, etc silicon blocks that can be routed to
+different pins by pinmux settings.
+
+Since general-purpose I/O pins (GPIO) are typically always in shortage, it is
+common to be able to use almost any pin as a GPIO pin if it is not currently
+in use by some other I/O port.
+
+
+Pinmux conventions
+==================
+
+The purpose of the pinmux subsystem is to abstract and provide pinmux settings
+to the devices you choose to instantiate in your machine configuration. It is
+inspired by the clk, GPIO and regulator subsystems, so devices will request
+their mux setting, but it's also possible to request a single pin for e.g.
+GPIO.
+
+The mux settings are:
+
+- Oriented around enumerated physical pins or pads denoted by unsigned
+  integers in the range 0..MAX_INT. Every pin on your system (or atleast
+  every pin that can be muxed) should have a unique number. The numberspace
+  can span several chips if you have more chips on your system that can be
+  subject to muxing. The example 8x8 array above will have pin numbers 0 thru
+  63 assigned to its physical pins.
+
+- Switched in and out by a driver residing with the pinmux subsystem in the
+  drivers/pinmux/* directory of the kernel. The pinmux driver knows the
+  possible function settings. In the example above you can identify three
+  pinmux functions, two for spi and one for i2c.
+
+- Assumed to be enumerable from zero in a one-dimensional array. In this
+  case the array could be something like: { spi0-0, spi0-1, i2c0-0 } for
+  the three available settings. The knowledge of this one-dimensional array
+  and it's machine-specific particulars is kept inside the pinmux driver,
+  from the outside only these enumerators are known, and the driver core
+  can request the name or the list of pins belonging to a certain enumerator.
+
+- Mapped to a certain device by the board file, device tree or similar
+  machine setup configuration mechanism, similar to how regulators are
+  connected to devices, usually by name. In the example case we can define
+  that this particular machine shall use device spi0 with pinmux setting
+  spi0-1 and i2c0 on i2c0-1, something like the two-tuple:
+  { {spi0, spi0-1}, {i2c0, i2c0-1}}
+
+- Provided on a first-come first-serve basis, so if some other device mux
+  setting or GPIO pin request has already taken your physical pin, you will
+  be denied the use of it. To get (activate) a new setting, the old one has
+  to be put (deactivated) first.
+
+Sometimes the documentation and hardware registers will be oriented around
+pads (or "fingers") rather than pins - these are the soldering surfaces on the
+silicon inside the package, and may or may not match the actual number of
+pins/balls underneath the capsule. Pick some enumeration that makes sense to
+you. Define enumerators only for the pins you can control if that makes sense.
+
+
+Pinmux drivers
+==============
+
+The driver will for all calls be provided an offset pin number into its own
+pin range. If you have 2 chips with 8x8 pins, the first chips pins will have
+numbers 0 thru 63 and the second one pins 64 thru 127, but the driver for the
+second chip will be passed numbers in the range 0 thru 63 anyway, base offset
+subtracted.
+
+Pinmux drivers are required to supply a few callback functions, some are
+optional. Usually the enable() and disable() functions are implemented,
+writing values into some certain registers to activate a certain mux setting
+for a certain pin.
+
+A simple driver for the above example will work by setting bits 0, 1 or 2
+into some register mamed MUX, so it enumerates its available settings and
+their pin assignments, and expose them like this:
+
+struct foo_pmx_func {
+	char *name;
+	const unsigned int *pins;
+	const unsigned num_pins;
+};
+
+static unsigned int spi0_0_pins[] = { 0, 8, 16, 24 };
+static unsigned int i2c0_pins[] = { 24, 25 };
+static unsigned int spi0_1_pins[] = { 38, 46, 54, 62 };
+
+static struct foo_pmx_func myfuncs[] = {
+	{
+		.name = "spi0-0",
+		.pins = spi0_0_pins,
+		.num_pins = ARRAY_SIZE(spi0_1_pins),
+	},
+	{
+		.name = "i2c0",
+		.pins = i2c0_pins,
+		.num_pins = ARRAY_SIZE(i2c0_pins),
+	},
+	{
+		.name = "spi0-1",
+		.pins = spi0_1_pins,
+		.num_pins = ARRAY_SIZE(spi0_1_pins),
+	},
+};
+
+int foo_list(struct pinmux_dev *pmxdev, unsigned selector)
+{
+	if (selector>= ARRAY_SIZE(myfuncs))
+		return -EINVAL;
+	return 0;
+}
+
+const char *foo_get_fname(struct pinmux_dev *pmxdev, unsigned selector)
+{
+	if (selector>= ARRAY_SIZE(myfuncs))
+		return NULL;
+	return myfuncs[selector].name;
+}
+
+static int foo_get_pins(struct pinmux_dev *pmxdev, unsigned selector,
+	   		unsigned ** const pins, unsigned * const num_pins)
+{
+	if (selector>= ARRAY_SIZE(myfuncs))
+		return -EINVAL;
+	*pins = myfuncs[selector].pins;
+	*num_pins = myfuncs[selector].num_pins;
+	return 0;
+}
+
+
+int foo_enable(struct pinmux_dev *pmxdev, unsigned selector)
+{
+	if (selector<  ARRAY_SIZE(myfuncs))
+		write((read(MUX)|(1<<selector)), MUX)
+		return 0;
+	}
+	return -EINVAL;
+}
+
+int foo_disable(struct pinmux_dev *pmxdev, unsigned selector)
+{
+	if (selector<  ARRAY_SIZE(myfuncs))
+		write((read(MUX)&  ~(1<<selector)), MUX)
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct pinmux_ops ops = {
+	.list_functions = foo_list,
+	.get_function_name = foo_get_fname,
+	.get_function_pins = foo_get_pins,
+	.enable = foo_enable,
+	.disable = foo_disable,
+};
+
+Now the able reader will say: "wait - the driver needs to make sure it
+can set this and that bit at the same time, because else it will collide
+and wreak havoc in my electronics, and make sure noone else is using the
+other setting that it's incompatible with".
+
+In the example activating muxing 0 and 1 at the same time setting bits
+0 and 1, uses one pin in common so they would collide.
+
+The beauty of the pinmux subsystem is that since it keeps track of all
+pins and who is using them, it will already have denied an impossible
+request like that, so the driver does not need to worry about such
+things - when it gets a selector passed in, the pinmux subsystem makes
+sure no other device or GPIO assignment is already using the selected
+pins.
+
+The above functions are mandatory to implement for a pinmux driver.
+
+The function list can become long, especially if you can convert every
+individual pin into a GPIO pin independent of any other pins, then your
+function array can become 64 entries for each GPIO setting and then the
+device functions. For this reason there is an additional function you
+can implement to enable only GPIO on an individual pin: gpio_enable().
+
+
+Board/machine configuration
+===========================
+
+Boards and machines define how a certain complete running system is put
+together, including how GPIOs and devices are muxed, how regulators are
+constrained and how the clock tree looks. Of course pinmux settings are also
+part of this.
+
+A pinmux config for a machine looks pretty much like a simple regulator
+configuration, so for the example array above we want to enable i2c and
+spi on the second function mapping:
+
+static struct pinmux_map pmx_mapping[] = {
+	{
+		.function = "spi0-1",
+		.dev_name = "foo-spi.0",
+	},
+	{
+		.function = "i2c0",
+		.dev_name = "foo-i2c.0",
+	},

Documentation/pinmux.txt line 263

Quoted 10 lines
Documentation/pinmux.txt new file +10 -0
+};
+
+Since the above construct is pretty common there is a helper macro to make
+it even more compact:
+
+static struct pinmux_map pmx_mapping[] = {
+       PINMUX_MAP("spi0-1", "foo-spi.0"),
+       PINMUX_MAP("i2c0", "foo-i2c.0"),
+};
+

This is great effort and provides a meaningful way for drivers to request for an entire group of pin configs rather than individual pin settings.
But, the msm tree has a bit more configurations options.
1) For power management we need to specify multiple configs for a particular pin. When we boot we have these low power settings for each pin. Once the driver needs to use a particular device - it can call to
install the active/enable settings for that pin.
Also, sometimes a pin needs to be configured for alternate usage.
How can we use this patch to have multiple configs that can be stored in the pinmux_map and apply it as needed?
From your previous gpio_config patch - we could pass in a setting
for a pin and have it routed through gpiolib.

2) Currently writing the settings (map) for each pin involves just a register address and the bits to be toggled.
But for the msm - we have different options and possibly different
register bits to be toggled for selecting a FUNC_SEL , changing the Drive Strength and the PULL and for setting the pin as an output line etc. Is there a way we can accomplish this using this patch ?

3) Each board has upto 200 pins - and with a slight modification to each board in hardware, our pinmuxes are modified. So, most likely our pin configurations originate (maintained) at the board level. Would it stay same in this implementation or we would have to migrate all the config information into drivers/pinmux ?

Attached are the patches that we had submitted upstream for this effort. Going forward, we would like to use this generic library, but is there a way we can bridge this gap?

Documentation/pinmux.txt line 270

Quoted 7 lines
Documentation/pinmux.txt new file +7 -0
+The dev_name here matches to the unique device name that can be used to look
+up the device struct (just like with clockdev or regulators). The function name
+must match a function provided by the pinmux driver handling this pin range.
+You register this pinmux mapping to the pinmux subsystem by simply:
+
+       ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
+

Thanks,
Rohit Vaswani

Signature · 17 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

-------------- next part --------------
An embedded message was scrubbed...
From: Rohit Vaswani <[email protected]>
Subject: [PATCH] msm: gpiomux: decentralize and modularize gpiomux init.
Date: Thu, 10 Feb 2011 15:45:00 -0800
Size: 18771
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110504/76b3bc0f/attachment-0002.mht>
-------------- next part --------------
An embedded message was scrubbed...
From: Rohit Vaswani <[email protected]>
Subject: [PATCH] msm: gpiomux: Remove GPIOMUX_VALID and merge config enums
Date: Fri, 25 Feb 2011 12:19:58 -0800
Size: 21313
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110504/76b3bc0f/attachment-0003.mht>
#21 lore raw
In reply to Linus Walleij

Hi Linus,

(modified re-send - previous email bounced off lkml)

Quoted 13 lines · Linus Walleij

From: Linus Walleij<[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

---

[snip]

Quoted 9 lines
Documentation/pinmux.txt new file +9 -0
+static struct pinmux_map pmx_mapping[] = {
+	{
+		.function = "spi0-1",
+		.dev_name = "foo-spi.0",
+	},
+	{
+		.function = "i2c0",
+		.dev_name = "foo-i2c.0",
+	},

Documentation/pinmux.txt line 263

Quoted 10 lines
Documentation/pinmux.txt new file +10 -0
+};
+
+Since the above construct is pretty common there is a helper macro to make
+it even more compact:
+
+static struct pinmux_map pmx_mapping[] = {
+       PINMUX_MAP("spi0-1", "foo-spi.0"),
+       PINMUX_MAP("i2c0", "foo-i2c.0"),
+};
+

This is great effort and provides a meaningful way for drivers to request for an entire group of pin configs rather than individual pin settings.
But, the msm tree has a bit more configurations options.
1) For power management we need to specify multiple configs for a particular pin. When we boot we have these low power settings for each pin. Once the driver needs to use a particular device - it can call to
install the active/enable settings for that pin.
Also, sometimes a pin needs to be configured for alternate usage.
How can we use this patch to have multiple configs that can be stored in the pinmux_map and apply it as needed?
From your previous gpio_config patch - we could pass in a setting
for a pin and have it routed through gpiolib.

2) Currently writing the settings (map) for each pin involves just a register address and the bits to be toggled. (is this right, or am I missing something ?)
But for the msm - we have different options and possibly different
register bits to be toggled for selecting a FUNC_SEL , changing the Drive Strength and the PULL and for setting the pin as an output/input line etc.
How do we specify a meaningful setting and accomplish multiple
register writes using your patch ?

3) Each board has upto 200 pins - and with a slight modification to each board in hardware, our pinmuxes are modified. So, most likely our pin configurations originate (maintained) at the board level. Would it stay same in this implementation or we would have to migrate all the config information into drivers/pinmux ?

I had upstreamed some patches related to msm gpiomux which provide an idea on what we were moving to. Going forward, we would like to use this generic library, but is there a way we can bridge this gap?

Documentation/pinmux.txt line 271

Quoted 8 lines
Documentation/pinmux.txt new file +8 -0
+The dev_name here matches to the unique device name that can be used to look
+up the device struct (just like with clockdev or regulators). The function name
+must match a function provided by the pinmux driver handling this pin range.
+You register this pinmux mapping to the pinmux subsystem by simply:
+
+       ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
+
+

Thanks,
Rohit Vaswani

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#22 lore raw
In reply to Linus Walleij
Quoted 12 lines · Linus Walleij

From: Linus Walleij <[email protected]>

This creates a subsystem for handling of pinmux devices. These are devices that enable and disable groups of pins on primarily PGA and BGA type of chip packages and common in embedded systems.

This is being done to depopulate the arch/arm/* directory of such custom drivers and try to abstract the infrastructure they all need. See the Documentation/pinmux.txt file that is part of this patch for more details.

Quoted 12 lines
---
 Documentation/ABI/testing/sysfs-class-pinmux |   11 +
 Documentation/pinmux.txt                     |  306 +++++++++++
 MAINTAINERS                                  |    5 +
 drivers/Kconfig                              |    4 +
 drivers/Makefile                             |    2 +
 drivers/pinmux/Kconfig                       |   26 +
 drivers/pinmux/Makefile                      |    5 +
 drivers/pinmux/core.c                        |  740 ++++++++++++++++++++++++++
 include/linux/pinmux.h                       |  224 ++++++++
 9 files changed, 1323 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-pinmux

As someone who constantly has to harp on adding documentation for sysfs files that are added to the kernel tree, it's nice to see this done correctly.

Good job,

greg k-h