[U-Boot] [RFC PATCH 1/7] pinctrl: add pinctrl framework

Albert ARIBAUD albert.u.boot at aribaud.net
Wed Jul 15 10:53:46 CEST 2015


Hello Masahiro,

On Wed, 15 Jul 2015 17:16:16 +0900, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Now, a simple pinctrl patch is being proposed by Simon.
> http://patchwork.ozlabs.org/patch/487801/
> 
> In the design above, as you see, the uclass is just like a wrapper layer
> to invoke .request and .get_periph_id of low-level drivers.
> In other words, it is Do-It-Yourself thing, so it is up to you how to identify
> which peripheral is being handled in your .get_periph_id().
> 
> And here is one example for how a low-level pinctrl driver could be implemented.
> http://patchwork.ozlabs.org/patch/487874/
> 
> As you see in the thread, honestly, I do not like this approach.
> 
> It is true that you can implement .get_periph_id in your driver
> better than parsing "interrupts" properties, but I guess
> many drivers would follow the rockchip implmentation because
> no helpful infrastructure is provided by the uclass (at least now).
> 
> Device trees describe hardwares in a way independent of software
> that they are used with.  So, identical device trees can be (should be)
> used with U-Boot as well as Linux or whatever.
> 
> Thus, I want the pinctrl can be controllable by device trees in the same way
> of Linux, that is, by parsing "pinctrl-names" and "pinctrl-<N>" properties.
> 
> Of course, it would be possible to do it in my own .get_periph_id,
> but "pinctrl-names" and "pinctrl-<N>" are too generic to be done in each
> low-level driver.
> 
> In this series, I'd like to propose to support it in the uclass, so that
> we can easily reuse device trees for pinctrl.
> Please put it on the table for discussion.
> 
> Let me explain how it works.
> 
> The basic idea is pretty much like Linux, but it has been much simplified
> because full-support of the Linux's pinctrl is too much a burden for a boot-loader.
> 
>  Device Tree
>  -----------
> 
> To use pinctrl from each peripheral, add some properties in the device node.
> 
> "pinctrl-names" is a list of pin states.  The "default" state is mandatory,
> and it would probably be enough for U-Boot.  But, in order to show how it works,
> say the example device supports two states: "default" and "sleep".
> In this case, the properties should be like this.
> 
>    pinctrl-names = "default", "sleep";
> 
> And then, add as many "pinctrl-<N>" properties as the number of states.
> 
>    pinctrl-0 = <phandle to default config node>;
>    pinctrl-1 = <phandle to sleep config node>;
> 
> Here, pinctrl-0, pinctrl-1 corresponds to "default", "sleep", respectively.
> 
> The config nodes are (direct or indirect) children of a pinctrl device.
> 
> To sum up, the device tree would be like this:
> 
>    foo {
>         compatible = "...";
>         reg = <...>;
>         pinctrl-names = "default", "sleep";
> 	pinctrl-0 = <&foo_default_pin>;
> 	pinctrl-1 = <&foo_sleep_pin>;
> 	...
>    };
> 
>    pinctrl {
>          compatible = "...";
> 	 reg = <...>;
>          foo_default_pin: foo_default {
> 	      groups = "...";
> 	      functions = "...";
>          };
>          foo_sleep_pin: foo_sleep {
> 	      groups = "...";
> 	      functions = "...";
>          };
>    };
> 
>  API
>  ---
> 
> 
> To set a device into a particular pin state, call
> int pinctrl_set_state(struct udevice *dev, const char *state_name).
> 
> For example, if you want to set the foo device into the sleep state,
> you can do like this:
> 
>    struct udevice *foo_dev;
> 
>    (device_get or whatever)
> 
>    pinctrl_set_state(foo_dev, "sleep");
> 
> When each device is probed, pinctrl_init() is invoked,
> which initializes some pinctrl-specific parameters and set it into "default"
> pin state.  Because it is automatically done by the core of driver model,
> when a device is probed, its pins are in the "default" state.
> 
>  Implementation of low-level driver
>  ----------------------------------
> 
> Currently, two methods are supported in the pinctrl operation:
>   struct pinctrl_ops {
>         int (*pinmux_set) (struct udevice *dev, const char *group,
>                            const char *function);
>         int (*pinconf_set) (struct udevice *dev, const char *group,
>                             const char *conf_param, unsigned conf_arg);
>   };
> 
> They are used to change pin-mux, pin-conf, respectively.
> 
> If the pin-config node for the target pin-state is like this,
>          i2c_default_pin: i2c_default {
> 	      groups = "i2c-0a";
> 	      functions = "i2c-0";
>          };
> 
> Your pinmux_set() is called with "i2c-0a" for the group and "i2c-0"
> for the function.
> 
> It is totally up to you what you do for each group & function.
> 
>  Difference from Linux pinctrl (limitation)
>  -----------------------------------------
> 
> As you can see in pinctrl drivers in Linux (drivers/pinctrl/*),
> the drivers usually contain huge tables for pins, groups, functions,...
> But I do not want to force that for U-Boot.
> 
> In Linux, "group" represents a group of pins although a group sometimes
> consists of a signle pin (like GPIO).  Pin-muxing is available only against
> groups, while pin-conf is supported for both pins and groups.
> 
> In contrast, in U-Boot, "pins" and "groups" are handled exactly in the same way,
> so you can use either to specify the target of pin-mux or pin-conf.
> 
> Pin/group tables are not required for U-boot pinctrl drivers, so
> we never know which pins belong to which group, function, that is,
> we can not avoid conflicts on pins.
> 
> For example, let's say some pins are shared between UART0 and I2C0.
> In this case, Linux pinctrl does not allow to use them simultaneously,
> while U-boot pinctrl does not (can not) care about it.
> 
> If you want to use multiple functions that share the same pins,
> you must make sure pin-muxing is correctly set with pinctrl_set_state().
> 
>  TODO
>  ----
> 
> [1] Pinctrl drivers are usually used with device trees (or ACPI), but
>     not all the boards in U-boot support device tree.
>     I will add board file support (plat data) later.
>     (we will need some function to register pin settings array)
> 
> [2] SPL support is not completed.   Tweak Kconfig and Makefile a little.
>     This should be easy.
> 
> [3] Currently, properties other than "function" are assumed
>     as pin-conf parameters.  Perhaps, should we filter out
>     unsupported properties?  A table for supported properties
>     such "bias-pull-up", "driver-strength", etc. ?
> 
> [4] For "function", "groups" should be able to be omitted.
> 
> Comments are welcome.

A very general comment for now: the above is absolutely too long for a
commit message. It should be a patman commit or series note, or better
yet, a cover letter, or, better still, rewritten into a doc/README.*
file (except for the comparison with Simon's patch, which should not be
in a README but remain a commit note).

Amicalement,
-- 
Albert.


More information about the U-Boot mailing list