[Letux-kernel] exact meaning of pinctrl-single masks and when and why are submasks invalid?

H. Nikolaus Schaller hns at goldelico.com
Thu May 31 17:59:36 CEST 2018

Hi Tony,
I have currently given up analysing the "ghost" issue with pwm_bl and focussed
on another issue about setting devconf registers through pinctrl-single masks.

First, I tried to understand the function mask and the pinmux masks by the documentation
but can't make any sense out of them.

Next, I tried to modify the control_devconf0 example from



	mcbsp1_pins: pinmux_mcbsp1_pins {
		pinctrl-single,bits = <
		//	0x00 0x18 0x18 /* FSR/CLKR signal from FSX/CLKX pin */
			0x00 0x08 0x1c /* FSR/CLKR signal from FSX/CLKX pin */

which I would read as: write 0x08 to the byte read at offset 0 and overwrite only bits at 0x1c.
This should clear two of them and set the middle one and leave all other bits untouched.

I.e. *addr = (*addr & ~0x1c) | (0x08 & 0x1c);

but just get a

[    0.726654] pinctrl-single 48002274.pinmux: Invalid submask 0x1c for pinmux_mcbsp1_devconf_pins at 0x0

If I use <0x00 0x08 0x5f> instead, it is accepted at boot time and does not seem to harm since other bits
are 0 anyways. My question here: how would I have to specify that the lower 2 bits are not to be touched?
If I make the function-mask = <0x5c> it doesn't work either.

So what I don't understand is the meaning of submask. It appears as if it either must be the same as the
value (as in the examples I find) or the same as pinctrl-single,function-mask.

And what about the function masks? It seems that the LSB must always be 1 or things get more strange.

Is there somewhere a description (better than the bindings doc), how the bits are distributed
into the 32 bit register? E.g. some simple C-style expression like above describing what happens?

Finally, I also have the need to set the TV bits in devconf1 and have no success. All experimentation
gave me either invalid submasks or the register is not changed at all...

Here is some full code (GTA04 / OMAP3630):

/ {
	/* pinmux for devconf0 */
	control_devconf0: pinmux at 48002274 {
		compatible = "pinctrl-single";
		reg = <0x48002274 4>;   /* CONTROL_DEVCONF0 */
		#address-cells = <1>;
		#size-cells = <0>;
		pinctrl-single,register-width = <32>;
		pinctrl-single,function-mask = <0x5f>;	/* MCBSP CLK */
		#pinctrl-cells = <2>;

	/* pinmux for devconf1 */
	control_devconf1: pinmux at 480022d8 {
		compatible = "pinctrl-single";
		reg = <0x480022d8 4>;	/* CONTROL_DEVCONF1 */
		#address-cells = <1>;
		#size-cells = <0>;
		pinctrl-single,register-width = <32>;
		pinctrl-single,function-mask = <0x81>;	/* TV control */
		#pinctrl-cells = <2>;

&control_devconf0 {
	pinctrl-names = "default";
	pinctrl-0 = <&mcbsp1_devconf_pins>;

	mcbsp1_devconf_pins: pinmux_mcbsp1_devconf_pins {
		/*                   offset bits mask */
		pinctrl-single,bits = <0x00 0x08 0x5f>;	/* set MCBSP1_CLKR_MASK */

&control_devconf1 {
	pinctrl-name = "default";
	pinctrl-0 = < &tv_acbias_pins>;

	tv_acbias_pins: pinmux_tv_acbias_pins {
		pinctrl-single,bits = <
		/*	offset	bits	mask */
		//	0	0x40800	0x40800
			0	0xfffff	0x40800

This variant shows no errors and sets the devconf0 but not the defconf1:

root at letux:~# dmesg|fgrep pinctrl
[    0.229858] pinctrl core: initialized pinctrl subsystem
[    0.721710] pinctrl-single 48002030.pinmux: 284 pins, size 568
[    0.722839] pinctrl-single 48002a00.pinmux: 46 pins, size 92
[    0.724456] pinctrl-single 480025a0.pinmux: 46 pins, size 92
[    0.725128] pinctrl-single 480022d8.pinmux: initialized with no interrupts
[    0.725158] pinctrl-single 480022d8.pinmux: 4 pins, size 4
[    0.725677] pinctrl-single 48002274.pinmux: initialized with no interrupts
[    0.725677] pinctrl-single 48002274.pinmux: 4 pins, size 4
root at letux:~# devmem2 0x48002274
/dev/mem opened.
Memory mapped at address 0xb6f34000.
Value at address 0x48002274 (0xb6f34274): 0x5000008
root at letux:~# devmem2 0x480022d8
/dev/mem opened.
Memory mapped at address 0xb6f1c000.
Value at address 0x480022D8 (0xb6f1c2d8): 0x40
root at letux:~# 

Or is there some SDIO2 code that sets the MMCSDIO2ADPCLKISEL in the defconf1 register
but clears everything else?

BR and thanks,

More information about the Letux-kernel mailing list