RE: [PATCH 1/4] drivers: create a pinmux subsystem
From: Stephen Warren <hidden>
Date: 2011-05-02 20:52:15
Also in:
linux-arm-kernel, lkml
Linus Walleij wrote at Monday, May 02, 2011 1:16 PM:
From: Linus Walleij <redacted> 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.
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 hunk
diff --git a/Documentation/pinmux.txt b/Documentation/pinmux.txt... +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.
quoted hunk
diff --git a/include/linux/pinmux.h b/include/linux/pinmux.h new file mode 100644 index 0000000..9bdcc33 --- /dev/null +++ b/include/linux/pinmux.h
+/** + * struct pinmux_map - boards/machines shall provide this map for devices + * @node: list node - only for internal use
Node isn't in the structure.
+ * @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*
+ */
+struct pinmux_map {
+ const char *function;
+ 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 ?
+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
+ * @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.
+ 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); +}; + +/** + * 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.
+ * 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
+ */
+struct pinmux_desc {
+ 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?
+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. -- nvpublic