Help for 1-wire on Olimex's A64-OLinuXino-2Ge8G-IND: "pin already requested"

69 views
Skip to first unread message

Ilario Gelmetti

unread,
Oct 10, 2023, 10:26:41 AM10/10/23
to linux...@googlegroups.com
Dear all,
thanks for your work in supporting the Allwinner devices!!

I am trying to use the 1-wire instructions I found on the wiki here [1]
for connecting some DS18B20 1-wire thermometer to an
A64-OLinuXino-2Ge8G-IND [2]. This single board computer is running a
Debian 11 Bullseye image prepared by the Olimex people [3] and currently
I am running a 5.10.180-olimex kernel.

I understand that I have to create a DeviceTree overlay (that I never
did before), load this overlay in the /boot/uEnv.txt file (that's the
name on the OS I am using) and hope it works. Right?

My (failed) first attempt to write a DeviceTree overlay is described on
the Olimex forums here [4], but I suspect this is the proper channel for
asking for some help on this topic.

Following attempts also failed. I always got a "pin PB0 already
requested by onewire_device; cannot claim for 1c20800.pinctrl:32" error.
These attempts included writing the code directly in the kernel dtb file
(decompiled and compiled with dtc and included in the /boot/kernel.itb
command using mkimage -f kernel.its kernel.itb).

I copy and paste here the latest attempt of DeviceTree overlay here.

```
/dts-v1/;
/plugin/;

/ {
compatible = "allwinner,sun50i-a64",
"olimex,a64-olinuxino";
description = "Enable 1-Wire port";

fragment@0 {
target-path = "/";
__overlay__ {
onewire_device: onewire_device {
compatible = "w1-gpio";
gpios = <&pio 1 0 0>; /* 1: B of PB0; 0: 0 of PB0; 0:
GPIO_ACTIVE_HIGH */
pinctrl-names = "default";
pinctrl-0 = <&my_w1_pin>;
};
};
};

fragment@1 {
target = <&pio>;
__overlay__ {
my_w1_pin: my_w1_pin@0 {
allwinner,pins = "PB0";
allwinner,function = "gpio_in";
allwinner,drive = <0>; /*<SUN4I_PINCTRL_10_MA>*/
allwinner,pull = <1>; /*<SUN4I_PINCTRL_PULL_UP>*/
};
};
};
};
```

I cannot get rid of this error in the dmesg (unless I specify two
different pins in the two fragments, and then weird things happen, as
explained in [4]):

[] Driver for 1-wire Dallas network protocol.
[] sun50i-a64-pinctrl 1c20800.pinctrl: pin PB0 already requested by
onewire_device; cannot claim for 1c20800.pinctrl:32
[] sun50i-a64-pinctrl 1c20800.pinctrl: pin-32 (1c20800.pinctrl:32)
status -22
[] w1-gpio onewire_device: gpio_request (pin) failed
[] w1-gpio: probe of onewire_device failed with error -22

Thanks for your help!!!
Ilario

[1]: https://linux-sunxi.org/1-Wire
[2]:
https://www.olimex.com/Products/OLinuXino/A64/A64-OLinuXino/open-source-hardware
[3]: https://images.olimex.com/
[4]: https://www.olimex.com/forum/index.php?topic=9266.0

--
Ilario
ioche...@gmail.com
ila...@sindominio.net

Ilario Gelmetti

unread,
Oct 10, 2023, 11:22:42 AM10/10/23
to linux...@googlegroups.com
On 10/10/23 15:57, Ilario Gelmetti wrote:
> I cannot get rid of this error in the dmesg (unless I specify two
> different pins in the two fragments, and then weird things happen, as
> explained in [4]):
>
> [] Driver for 1-wire Dallas network protocol.
> [] sun50i-a64-pinctrl 1c20800.pinctrl: pin PB0 already requested by
> onewire_device; cannot claim for 1c20800.pinctrl:32
> [] sun50i-a64-pinctrl 1c20800.pinctrl: pin-32 (1c20800.pinctrl:32)
> status -22
> [] w1-gpio onewire_device: gpio_request (pin) failed
> [] w1-gpio: probe of onewire_device failed with error -22

I forgot to specify:
the PB0 pin is not used by anything else.

# cat /sys/kernel/debug/pinctrl/1c20800.pinctrl/pinmux-pins
Pinmux settings per pin
Format: pin (name): mux_owner|gpio_owner (strict) hog?
pin 32 (PB0): UNCLAIMED
pin 33 (PB1): UNCLAIMED
[...]

And if I use other unclaimed pins (e.g. I tried with PC4 and PC7) the
same message appears.

Thanks!
Ilario


--
Ilario
ioche...@gmail.com
ila...@sindominio.net

Samuel Holland

unread,
Oct 28, 2023, 1:32:22 PM10/28/23
to ioche...@gmail.com, linux...@googlegroups.com
Hi Ilario,
You need GPIO_PULL_UP in the flags cell here.

>                 pinctrl-names = "default";
>                 pinctrl-0 = <&my_w1_pin>;
>             };
>         };
>     };
>
>     fragment@1 {

And drop this entire fragment. See if it works with those two changes.

>         target = <&pio>;
>          __overlay__ {
>             my_w1_pin: my_w1_pin@0 {
>                 allwinner,pins = "PB0";
>                 allwinner,function = "gpio_in";
>                 allwinner,drive = <0>; /*<SUN4I_PINCTRL_10_MA>*/
>                 allwinner,pull = <1>; /*<SUN4I_PINCTRL_PULL_UP>*/
>             };
>         };
>     };
> };
> ```
>
> I cannot get rid of this error in the dmesg (unless I specify two
> different pins in the two fragments, and then weird things happen, as
> explained in [4]):
>
> [] Driver for 1-wire Dallas network protocol.
> [] sun50i-a64-pinctrl 1c20800.pinctrl: pin PB0 already requested by
> onewire_device; cannot claim for 1c20800.pinctrl:32
> [] sun50i-a64-pinctrl 1c20800.pinctrl: pin-32 (1c20800.pinctrl:32)
> status -22
> [] w1-gpio onewire_device: gpio_request (pin) failed
> [] w1-gpio: probe of onewire_device failed with error -22

The problem is that the GPIO reference and the pinctrl reference for the
same pin conflict. In this case, the only thing you need the pinctrl
reference for is the pull-up, which you can achieve with a GPIO flag.
However, for the more general case, you may need to apply some other
pinconf setting to a GPIO pin, so we may need to fix this.

Regards,
Samuel

Ilario Gelmetti

unread,
Oct 30, 2023, 11:43:35 AM10/30/23
to Samuel Holland, linux...@googlegroups.com
Dear Samuel,
Many thanks, now it works!
In case anyone is interested, see below in-line for more detailed info
on the DTS and hardware connections:

On 10/28/23 19:32, Samuel Holland wrote:
> On 10/10/23 08:57, Ilario Gelmetti wrote:
>>                 gpios = <&pio 1 0 0>; /* 1: B of PB0; 0: 0 of PB0; 0:
>> GPIO_ACTIVE_HIGH */
>
> You need GPIO_PULL_UP in the flags cell here.

Many thanks! I did not have idea that it was possible to set that here!

For people that read this and do not know how to set GPIO_PULL_UP here,
I report what I found about it.
I found some documentation in the first part of this document: [1] and
here: [2].

So I understand that the third parameter of the gpios = <&pio X Y ZZ>
(the first and the second indicate the pin I want to use PB0: X=1 means
"B" and Y=0 means 0) has to be:
bit 0 = 0 for GPIO_ACTIVE_HIGH
and
bit 4 = 1 for GPIO_PULL_UP
so: 0b10000 which in decimal is the number 16.

>>                 pinctrl-names = "default";
>>                 pinctrl-0 = <&my_w1_pin>;
>>             };
>>         };
>>     };
>>
>>     fragment@1 {
>
> And drop this entire fragment. See if it works with those two changes.

Great, dropped the second part.

Many thanks for your help, now it works!!!
Until today I was completely stuck, and I was going to try compiling
w1-gpio-cl [3] that was also promising.

So, the final DTS file looks like this:

```
/dts-v1/;
/plugin/;

/ {
compatible = "allwinner,sun50i-a64",
"olimex,a64-olinuxino";
description = "Enable 1-Wire port";

fragment@0 {
target-path="/";
__overlay__ {
onewire {
compatible = "w1-gpio";
pinctrl-names = "default";
gpios = <&pio 1 0 16>;
/* 1: B of PB0; 0: 0 of PB0;
16 = (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)
= (0 bitwise OR 16)
0 in the bit 0 means GPIO_ACTIVE_HIGH
1 in the bit 4 = 16 means GPIO_PULL_UP
0b10000 = 16 */
status = "okay";
};
};
};
};
```

It has been compiled with:

```
dtc -I dts -O dtb sun50i-a64-w1-gpio.dts -o sun50i-a64-w1-gpio.dtbo
```

Loaded adding the compiled file path to the spaces-separated list of
fdtoverlays in the /boot/uEnv.txt file and rebooting:

```
fdtoverlays=/root/sun50i-a64-w1-gpio.dtbo
```

Here is the output of some interesting debugging commands, just for
documenting the working status of the system:

```
# dmesg | grep -i wire
[] Driver for 1-wire Dallas network protocol.
[] gpio-32 (onewire): enforced open drain please flag it properly in
DT/ACPI DSDT/board file
[] w1_master_driver w1_bus_master1: Attaching one wire slave
28.00000e21e158 crc 8d
```

Strangely, even if I also set Bit 2 = 1 in the DTS gpios cell, which
corresponds to GPIO_LINE_OPEN_DRAIN [2], the second line in the dmesg
filtered output does not disappear.

```
# cat /sys/kernel/debug/gpio
gpiochip1: GPIOs 0-255, parent: platform/1c20800.pinctrl, 1c20800.pinctrl:
gpio-32 ( |onewire ) out hi
gpio-166 ( |cd ) in lo ACTIVE LOW
gpio-201 ( |usb1-vbus ) out hi
gpio-230 ( |usb0_vbus_det ) in lo IRQ
gpio-233 ( |usb0_id_det ) in hi IRQ

gpiochip0: GPIOs 352-383, parent: platform/1f02c00.pinctrl, 1f02c00.pinctrl:

gpiochip2: GPIOs 510-511, parent: platform/axp20x-gpio, axp20x-gpio, can
sleep:
```

It is surprising to me that it works even if the pin 32 (PB0 on
Allwinner A64) is marked as output :)

```
# cat /sys/kernel/debug/pinctrl/1c20800.pinctrl/pinmux-pins
Pinmux settings per pin
Format: pin (name): mux_owner|gpio_owner (strict) hog?
pin 32 (PB0): GPIO 1c20800.pinctrl:32
pin 33 (PB1): UNCLAIMED
[...]
```

I had to try a few different hardware connections, that were not obvious
to me (noob writing). The final working one can be seen here [4] and is:

* external 5V power supply connected to GND of thermometer and VCC of
thermometer
* A64-olinuxino's 5V pin from GPIO1 port connected to VCC of thermometer
* 10 kOhm (did not try other resistors, 4.7 kOhm should also be ok)
connected from VCC of thermometer and Data of thermometer
* A64-olinuxino's PB0 pin (the one configured using the DTS file)
connected to Data of thermometer

I am not sure these connections are the most meaningful ones (e.g. it
would have been more common to connect the ground of the SBC and of the
external power supplies, instead I had to connect the VCC. I suppose
this happens due to some open-drain configuration?) and it could be they
depend on the DTS configuration, but they are the only one that I found
working.

The position of the PB0 and 5V pins in the GPIO1 port of the
A64-olinuxino rev. G is reported here [5].

As I am using some Maxim DS18B20 thermometers [6], I added w1_therm in
the /etc/modules file to have it loaded at boot.
Without that module loaded, the important file
/sys/bus/w1/devices/28-00000???????/w1_slave
does not appear.

>> [] Driver for 1-wire Dallas network protocol.
>> [] sun50i-a64-pinctrl 1c20800.pinctrl: pin PB0 already requested by
>> onewire_device; cannot claim for 1c20800.pinctrl:32
>> [] sun50i-a64-pinctrl 1c20800.pinctrl: pin-32 (1c20800.pinctrl:32)
>> status -22
>> [] w1-gpio onewire_device: gpio_request (pin) failed
>> [] w1-gpio: probe of onewire_device failed with error -22
>
> The problem is that the GPIO reference and the pinctrl reference for the
> same pin conflict. In this case, the only thing you need the pinctrl
> reference for is the pull-up, which you can achieve with a GPIO flag.
> However, for the more general case, you may need to apply some other
> pinconf setting to a GPIO pin, so we may need to fix this.
For me, it is surprising how other people do not have my same issue.
For example, in the instructions on the wiki [7], in the DTS from
Armbian [8] and in the one used by RaspberryPi (on Broadcom) [9] they
all use the same pin in two fragments. I tried using all of these and
always got the "already requested by" error.

> Regards,
> Samuel

Many thanks!!!
Ilario

[1]:
https://www.kernel.org/doc/Documentation/devicetree/bindings/gpio/gpio.txt
[2]:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/dt-bindings/gpio/gpio.h
[3]: https://github.com/pstolarz/w1-gpio-cl
[4]: https://uz.sns.it/~ilario/20231030-1wire-A64-hardware_connections.jpg
https://web.archive.org/web/20231030154013/https://uz.sns.it/~ilario/20231030-1wire-A64-hardware_connections.jpg
[5]:
https://github.com/OLIMEX/OLINUXINO/blob/master/HARDWARE/A64-OLinuXino/1.%20Latest%20hardware%20revision/A64-OLinuXino%20hardware%20revision%20G/A64-OlinuXino_Rev_G.pdf
[6]:
https://www.olimex.com/Products/Components/Sensors/Temperature/SNS-TMP-DS18B20/
[7]: https://linux-sunxi.org/1-Wire#Device_Tree
[8]:
https://github.com/armbian/sunxi-DT-overlays/blob/master/sun50i-a64/sun50i-a64-w1-gpio.dts
[9]:
https://github.com/raspberrypi/linux/blob/rpi-6.1.y/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts

Maxime Ripard

unread,
Oct 30, 2023, 1:08:46 PM10/30/23
to Ilario Gelmetti, Samuel Holland, linux...@googlegroups.com
On Mon, Oct 30, 2023 at 04:43:28PM +0100, Ilario Gelmetti wrote:
> So, the final DTS file looks like this:
>
> ```
> /dts-v1/;
> /plugin/;
>
> / {
> compatible = "allwinner,sun50i-a64",
> "olimex,a64-olinuxino";
> description = "Enable 1-Wire port";
>
> fragment@0 {
> target-path="/";
> __overlay__ {
> onewire {
> compatible = "w1-gpio";
> pinctrl-names = "default";
> gpios = <&pio 1 0 16>;
> /* 1: B of PB0; 0: 0 of PB0;
> 16 = (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)
> = (0 bitwise OR 16)
> 0 in the bit 0 means GPIO_ACTIVE_HIGH
> 1 in the bit 4 = 16 means GPIO_PULL_UP
> 0b10000 = 16 */
> status = "okay";
> };
> };
> };
> };
> ```

A syntax probably more straightforward would be

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>

&{/} {
onewire {
compatible = "w1-gpio";
gpios = <&pio 1 0 GPIO_PULL_UP>;
status = "okay";
};
};

> It has been compiled with:
>
> ```
> dtc -I dts -O dtb sun50i-a64-w1-gpio.dts -o sun50i-a64-w1-gpio.dtbo
> ```

And if you put that file under

> ```
> # cat /sys/kernel/debug/gpio
> gpiochip1: GPIOs 0-255, parent: platform/1c20800.pinctrl, 1c20800.pinctrl:
> gpio-32 ( |onewire ) out hi
> gpio-166 ( |cd ) in lo ACTIVE LOW
> gpio-201 ( |usb1-vbus ) out hi
> gpio-230 ( |usb0_vbus_det ) in lo IRQ
> gpio-233 ( |usb0_id_det ) in hi IRQ
>
> gpiochip0: GPIOs 352-383, parent: platform/1f02c00.pinctrl, 1f02c00.pinctrl:
>
> gpiochip2: GPIOs 510-511, parent: platform/axp20x-gpio, axp20x-gpio, can
> sleep:
> ```
>
> It is surprising to me that it works even if the pin 32 (PB0 on Allwinner
> A64) is marked as output :)

The GPIO controller doesn't support simultaneous input and output and
1-wire needs to do both so it flips back and forth between input and
output.

> > > [] Driver for 1-wire Dallas network protocol.
> > > [] sun50i-a64-pinctrl 1c20800.pinctrl: pin PB0 already requested by
> > > onewire_device; cannot claim for 1c20800.pinctrl:32
> > > [] sun50i-a64-pinctrl 1c20800.pinctrl: pin-32 (1c20800.pinctrl:32)
> > > status -22
> > > [] w1-gpio onewire_device: gpio_request (pin) failed
> > > [] w1-gpio: probe of onewire_device failed with error -22
> >
> > The problem is that the GPIO reference and the pinctrl reference for the
> > same pin conflict. In this case, the only thing you need the pinctrl
> > reference for is the pull-up, which you can achieve with a GPIO flag.
> > However, for the more general case, you may need to apply some other
> > pinconf setting to a GPIO pin, so we may need to fix this.
>
> For me, it is surprising how other people do not have my same issue.
> For example, in the instructions on the wiki [7], in the DTS from Armbian
> [8] and in the one used by RaspberryPi (on Broadcom) [9] they all use the
> same pin in two fragments. I tried using all of these and always got the
> "already requested by" error.

It also depends on the general design of the GPIO controller. Ours
doesn't support both GPIO and some other feature at the same time, they
are exclusive, some do.

The GPIO framework support both though, and by default will allow to
request a GPIO and another pin muxing at the same time. This was fixed
in 2017, so the wiki might be older than that and have never been
updated. armbian is probably in the same case.

The RaspberryPi driver might have a bug or a different design that
allows what we can't do.

Maxime
signature.asc

Ilario Gelmetti

unread,
Oct 31, 2023, 12:09:41 PM10/31/23
to Maxime Ripard, linux...@googlegroups.com, Samuel Holland
On 10/30/23 18:08, Maxime Ripard wrote:
> A syntax probably more straightforward would be
>
> /dts-v1/;
> /plugin/;
>
> #include <dt-bindings/gpio/gpio.h>
>
> &{/} {
> onewire {
> compatible = "w1-gpio";
> gpios = <&pio 1 0 GPIO_PULL_UP>;
> status = "okay";
> };
> };

Thanks!
Much nicer actually :D

Just the #include does not work for me, unless I preprocess the dts file
with:

cpp -nostdinc -undef -x assembler-with-cpp -I
/usr/src/linux-headers-5.10.180-olimex/include/ sun50i-a64-w1-gpio.dts
sun50i-a64-w1-gpio.preprocessed

>> It is surprising to me that it works even if the pin 32 (PB0 on Allwinner
>> A64) is marked as output :)
>
> The GPIO controller doesn't support simultaneous input and output and
> 1-wire needs to do both so it flips back and forth between input and
> output.

Ok, thanks!
Ok, I will try to report this to the Armbian people.

A partially unrelated question, feel free to ignore me if I go off-topic:
I am going to use this 1-wire connection for measuring a chain of 12
DS18B20 thermometers. Currently, I am still using only 1 thermometer, I
am using an external pull up (10 kOhm) and an external 5V power supply,
connecting the 5V from the A64-olinuxino to the 5V of the power supply
(otherwise it was not working).
So the question is: if I use the external pull up, should I also keep
GPIO_PULL_UP in the DTS?

Many thanks for your help!
Reply all
Reply to author
Forward
0 new messages