
-----Original Message----- From: Roman Bacik roman.bacik@broadcom.com Sent: Friday, October 1, 2021 3:40 PM To: U-Boot Mailing List u-boot@lists.denx.de Cc: Bharat Gooty bharat.gooty@broadcom.com; Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com; Roman Bacik roman.bacik@broadcom.com; Dario Binacchi dariobin@libero.it; Pratyush Yadav p.yadav@ti.com; Simon Glass sjg@chromium.org; Vignesh Raghavendra vigneshr@ti.com Subject: [PATCH v2 1/2] pinctrl: single: Parse gpio details from dt
From: Bharat Gooty bharat.gooty@broadcom.com
Parse different gpio properties from dt as part of probe function. This detail is required to enable pinctrl pad later when gpio lines are requested.
Signed-off-by: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com Signed-off-by: Bharat Gooty bharat.gooty@broadcom.com Acked-by: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com Signed-off-by: Roman Bacik roman.bacik@broadcom.com
- modified comment before struct single_fpiofunc_range
- add pinctrl-single binding from Linux
- return error from single-probe()
- there is no test to be updated
I will add tests to dm_test_pinctrl_single() in test/dm/pinmux.c and add a test node to arch/sandbox/dts/test.dts in version 3.
.../pinctrl/pinctrl-single.txt | 255 ++++++++++++++++++ drivers/pinctrl/pinctrl-single.c | 56 ++++ 2 files changed, 311 insertions(+) create mode 100644 doc/device-tree-bindings/pinctrl/pinctrl-single.txt
diff --git a/doc/device-tree-bindings/pinctrl/pinctrl-single.txt
b/doc/device-
tree-bindings/pinctrl/pinctrl-single.txt new file mode 100644 index 000000000000..e705acd3612c --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/pinctrl-single.txt @@ -0,0 +1,255 @@ +One-register-per-pin type device tree based pinctrl driver
+Required properties: +- compatible : "pinctrl-single" or "pinconf-single".
- "pinctrl-single" means that pinconf isn't supported.
- "pinconf-single" means that generic pinconf is supported.
+- reg : offset and length of the register set for the mux registers
+- #pinctrl-cells : number of cells in addition to the index, set to 1
- for pinctrl-single,pins and 2 for pinctrl-single,bits
+- pinctrl-single,register-width : pinmux register access width in bits
+- pinctrl-single,function-mask : mask of allowed pinmux function bits
- in the pinmux register
+Optional properties: +- pinctrl-single,function-off : function off mode for disabled state if
- available and same for all registers; if not specified, disabling of
- pin functions is ignored
+- pinctrl-single,bit-per-mux : boolean to indicate that one register
controls
- more than one pin, for which "pinctrl-single,function-mask" property
specifies
- position mask of pin.
+- pinctrl-single,drive-strength : array of value that are used to
configure
- drive strength in the pinmux register. They're value of drive
strength
- current and drive strength mask.
/* drive strength current, mask */
pinctrl-single,power-source = <0x30 0xf0>;
+- pinctrl-single,bias-pullup : array of value that are used to
configure the
- input bias pullup in the pinmux register.
/* input, enabled pullup bits, disabled pullup bits, mask
*/
pinctrl-single,bias-pullup = <0 1 0 1>;
+- pinctrl-single,bias-pulldown : array of value that are used to
configure the
- input bias pulldown in the pinmux register.
/* input, enabled pulldown bits, disabled pulldown bits,
mask
*/
pinctrl-single,bias-pulldown = <2 2 0 2>;
- Two bits to control input bias pullup and pulldown: User should use
- pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. One bit
means
- pullup, and the other one bit means pulldown.
- Three bits to control input bias enable, pullup and pulldown. User
should
- use pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown.
Input bias
- enable bit should be included in pullup or pulldown bits.
- Although driver could set PIN_CONFIG_BIAS_DISABLE, there's no
property as
- pinctrl-single,bias-disable. Because pinctrl single driver could
implement
- it by calling pulldown, pullup disabled.
+- pinctrl-single,input-schmitt : array of value that are used to
configure
- input schmitt in the pinmux register. In some silicons, there're two
input
- schmitt value (rising-edge & falling-edge) in the pinmux register.
/* input schmitt value, mask */
pinctrl-single,input-schmitt = <0x30 0x70>;
+- pinctrl-single,input-schmitt-enable : array of value that are used to
- configure input schmitt enable or disable in the pinmux register.
/* input, enable bits, disable bits, mask */
pinctrl-single,input-schmitt-enable = <0x30 0x40 0 0x70>;
+- pinctrl-single,low-power-mode : array of value that are used to
configure
- low power mode of this pin. For some silicons, the low power mode
will
- control the output of the pin when the pad including the pin enter
low
- power mode.
/* low power mode value, mask */
pinctrl-single,low-power-mode = <0x288 0x388>;
+- pinctrl-single,gpio-range : list of value that are used to configure
a GPIO
- range. They're value of subnode phandle, pin base in pinctrl device,
pin
- number in this range, GPIO function value of this GPIO range.
- The number of parameters is depend on
#pinctrl-single,gpio-range-cells
- property.
/* pin base, nr pins & gpio function */
pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
+- interrupt-controller : standard interrupt controller binding if using
- interrupts for wake-up events for example. In this case
pinctrl-single
- is set up as a chained interrupt controller and the wake-up
interrupts
- can be requested by the drivers using request_irq().
+- #interrupt-cells : standard interrupt binding if using interrupts
+This driver assumes that there is only one register for each pin
(unless the
+pinctrl-single,bit-per-mux is set), and uses the common pinctrl
bindings as
+specified in the pinctrl-bindings.txt document in this directory.
+The pin configuration nodes for pinctrl-single are specified as pinctrl +register offset and value pairs using pinctrl-single,pins. Only the
bits
+specified in pinctrl-single,function-mask are updated. For example,
setting
+a pin for a device could be done with:
- pinctrl-single,pins = <0xdc 0x118>;
+Where 0xdc is the offset from the pinctrl register base address for the +device pinctrl register, and 0x118 contains the desired value of the +pinctrl register. See the device example and static board pins example +below for more information.
+In case when one register changes more than one pin's mux the +pinctrl-single,bits need to be used which takes three parameters:
- pinctrl-single,bits = <0xdc 0x18 0xff>;
+Where 0xdc is the offset from the pinctrl register base address for the +device pinctrl register, 0x18 is the desired value, and 0xff is the sub
mask to
+be used when applying this change to the register.
+Optional sub-node: In case some pins could be configured as GPIO in the pinmux +register, those pins could be defined as a GPIO range. This sub-node is required +by pinctrl-single,gpio-range property.
+Required properties in sub-node: +- #pinctrl-single,gpio-range-cells : the number of parameters after
phandle
in
- pinctrl-single,gpio-range property.
- range: gpio-range {
#pinctrl-single,gpio-range-cells = <3>;
- };
+Example:
+/* SoC common file */
+/* first controller instance for pins in core domain */ +pmx_core: pinmux@4a100040 {
- compatible = "pinctrl-single";
- reg = <0x4a100040 0x0196>;
- #address-cells = <1>;
- #size-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-controller;
- pinctrl-single,register-width = <16>;
- pinctrl-single,function-mask = <0xffff>;
+};
+/* second controller instance for pins in wkup domain */ +pmx_wkup: pinmux@4a31e040 {
- compatible = "pinctrl-single";
- reg = <0x4a31e040 0x0038>;
- #address-cells = <1>;
- #size-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-controller;
- pinctrl-single,register-width = <16>;
- pinctrl-single,function-mask = <0xffff>;
+};
+control_devconf0: pinmux@48002274 {
- compatible = "pinctrl-single";
- reg = <0x48002274 4>; /* Single register */
- #address-cells = <1>;
- #size-cells = <0>;
- pinctrl-single,bit-per-mux;
- pinctrl-single,register-width = <32>;
- pinctrl-single,function-mask = <0x5F>;
+};
+/* third controller instance for pins in gpio domain */ +pmx_gpio: pinmux@d401e000 {
- compatible = "pinconf-single";
- reg = <0xd401e000 0x0330>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- pinctrl-single,register-width = <32>;
- pinctrl-single,function-mask = <7>;
- /* sparse GPIO range could be supported */
- pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
&range 12 1 0 &range 13 29 1
&range 43 1 0 &range 44 49 1
&range 94 1 1 &range 96 2 1>;
- range: gpio-range {
#pinctrl-single,gpio-range-cells = <3>;
- };
+};
+/* board specific .dts file */
+&pmx_core {
- /*
* map all board specific static pins enabled by the pinctrl
driver
* itself during the boot (or just set them up in the bootloader)
*/
- pinctrl-names = "default";
- pinctrl-0 = <&board_pins>;
- board_pins: pinmux_board_pins {
pinctrl-single,pins = <
0x6c 0xf
0x6e 0xf
0x70 0xf
0x72 0xf
>;
- };
- uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
0x208 0 /* UART0_RXD (IOCFG138) */
0x20c 0 /* UART0_TXD (IOCFG139) */
>;
pinctrl-single,bias-pulldown = <0 2 2>;
pinctrl-single,bias-pullup = <0 1 1>;
- };
- /* map uart2 pins */
- uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
0xd8 0x118
0xda 0
0xdc 0x118
0xde 0
>;
- };
+};
+&control_devconf0 {
- mcbsp1_pins: pinmux_mcbsp1_pins {
pinctrl-single,bits = <
0x00 0x18 0x18 /* FSR/CLKR signal from FSX/CLKX
pin
*/
>;
- };
- mcbsp2_clks_pins: pinmux_mcbsp2_clks_pins {
pinctrl-single,bits = <
0x00 0x40 0x40 /* McBSP2 CLKS from McBSP_CLKS
pin */
>;
- };
+};
+&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
+};
+&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
+}; diff --git a/drivers/pinctrl/pinctrl-single.c
b/drivers/pinctrl/pinctrl-single.c
index 7af6c5f0b037..c68d48d7fbcc 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -8,6 +8,7 @@ #include <dm.h> #include <dm/device_compat.h> #include <dm/devres.h> +#include <dm/of_access.h> #include <dm/pinctrl.h> #include <linux/libfdt.h> #include <linux/list.h> @@ -44,11 +45,27 @@ struct single_func { unsigned int *pins; };
+/**
- struct single_gpiofunc_range - pin ranges with same mux value
- @offset: offset base of pins
- @npins: number pins with the same mux value of gpio function
- @gpiofunc: mux value of gpio function
- @node: list node
- */
+struct single_gpiofunc_range {
- u32 offset;
- u32 npins;
- u32 gpiofunc;
- struct list_head node;
+};
/**
- struct single_priv - private data
- @bits_per_pin: number of bits per pin
- @npins: number of selectable pins
- @pin_name: temporary buffer to store the pin name
- @functions: list pin functions
*/
- @gpiofuncs: list gpio functions
struct single_priv { #if (IS_ENABLED(CONFIG_SANDBOX)) @@ -58,6 +75,7 @@ struct single_priv { unsigned int npins; char pin_name[PINNAME_SIZE]; struct list_head functions;
- struct list_head gpiofuncs;
};
/** @@ -454,13 +472,45 @@ static int single_get_pins_count(struct udevice *dev) return priv->npins; }
+static int single_add_gpio_func(struct udevice *dev) +{
- struct single_priv *priv = dev_get_priv(dev);
- const char *propname = "pinctrl-single,gpio-range";
- const char *cellname = "#pinctrl-single,gpio-range-cells";
- struct single_gpiofunc_range *range;
- struct ofnode_phandle_args gpiospec;
- int ret, i;
- for (i = 0; ; i++) {
ret = ofnode_parse_phandle_with_args(dev_ofnode(dev),
propname,
cellname, 0, i,
&gpiospec);
/* Do not treat it as error. Only treat it as end
condition. */
if (ret) {
ret = 0;
break;
}
range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
if (!range) {
ret = -ENOMEM;
break;
}
range->offset = gpiospec.args[0];
range->npins = gpiospec.args[1];
range->gpiofunc = gpiospec.args[2];
list_add_tail(&range->node, &priv->gpiofuncs);
- }
- return ret;
+}
static int single_probe(struct udevice *dev) { struct single_pdata *pdata = dev_get_plat(dev); struct single_priv *priv = dev_get_priv(dev); u32 size;
int ret;
INIT_LIST_HEAD(&priv->functions);
INIT_LIST_HEAD(&priv->gpiofuncs);
size = pdata->offset + pdata->width / BITS_PER_BYTE; #if (CONFIG_IS_ENABLED(SANDBOX))
@@ -482,6 +532,12 @@ static int single_probe(struct udevice *dev) priv->npins *= (pdata->width / priv->bits_per_pin); }
- ret = single_add_gpio_func(dev);
- if (ret) {
dev_dbg(dev, "gpio functions are not added\n");
return ret;
- }
- dev_dbg(dev, "%d pins\n", priv->npins); return 0;
}
2.17.1