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

H. Nikolaus Schaller hns at goldelico.com
Fri Jun 1 10:48:48 CEST 2018


Hi,

> Am 31.05.2018 um 17:59 schrieb H. Nikolaus Schaller <hns at goldelico.com>:
> 
> 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.

Well, finally I have reverse engineered the code...

-------------- next part --------------
A non-text attachment was scrubbed...
Name: PinCtrl-Single.pdf
Type: application/pdf
Size: 34961 bytes
Desc: not available
URL: <http://lists.goldelico.com/pipermail/letux-kernel/attachments/20180601/58ee4362/attachment-0001.pdf>
-------------- next part --------------


and that explains some of the effects.

> 
> Next, I tried to modify the control_devconf0 example from
> 
> https://www.kernel.org/doc/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> 
> to
> 
> 	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.

This is an invalid mask because the code tries to deduce the mask position (bit_pos, pin_num_from_lsb)
from the least significant bit. If I specify 0x1c it takes bit 2 instead of bit 0 from 0x5f.

> 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.

Function mask 0x5c doesn't work because that should result into an fshift = 2 and fmax = 0x17
but calculating bits_per_pin or setting the pins do not use fmax!

Therefore, the LSB of the fmask must always be 1 so that bits_per_pin is correct.

> 
> 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.

That is the fshift/fmax thing.

> 
> 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,bit-per-mux;
> 		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,bit-per-mux;
> 		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 fails to work because the bit_pos is derived by __ffs(mask) and the mask does not have the LSB set.
Therefore the fmask is shifted to the wrong position.

It does not fail by Invalid (sub)mask because shifting the fmask by the wrong bit_pos seems to return something
that passes the checks.

> 		>;
> 	};
> };
> 
> 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,
> Nikolaus

Next I'll try to find out how to correctly dupe the pinctrl-single to do it as I need...

Well, from the analysis

	fmask=0x7, mask=0x1c, val=0x08 and
	fmask=0x81, mask=0x40800, val=0x40800 (which is what I had tried)

should work. But setting the defconf1 doesn't...

If it works we should also rename the control_devconf nodes to specific ones,
e.g. control_devconf1_tv_acbias because it is tuned to handle the tv_acbias only.

BR,
Nikolaus



More information about the Letux-kernel mailing list