Pps-gpio for s905x

Same problem for me too.

The overlay is incorrect. You cannot just create a root pps node. Take a look at other overlays.

@librecomputer Thank you for the reply. This is how Armbian handles a rockchip board and is what I used as my model.

/dts-v1/;
/plugin/;

/ {
  compatible = "pine64,rock64", "rockchip,rk3328";

  fragment@0 {
    target-path = "/";
    __overlay__ {
      pps: pps@0 {
        compatible = "pps-gpio";
        gpios = <&gpio GPIOAO_6 GPIO_ACTIVE_HIGH>;
      };
    };
  };
};

And this is how Armbian handles a H5 board.

/dts-v1/;
/plugin/;

/ {
	compatible = "allwinner,sun50i-h5";

	fragment@0 {
		target = <&pio>;
		__overlay__ {
			pps_pins: pps_pins {
				pins = "PD14";
				function = "gpio_in";
			};
		};
	};

	fragment@1 {
		target-path = "/";
		__overlay__ {
			pps@0 {
				compatible = "pps-gpio";
				pinctrl-names = "default";
				pinctrl-0 = <&pps_pins>;
				gpios = <&pio 3 14 0>; /* PD14 */
				status = "okay";
			};
		};
	};
};

Which .dts examples should I be looking at for pps-gpio on s905x? I have looked at the overlays here:

But there aren’t any pps examples. I realize now my pps { line should probably be pps@0 { but that didn’t work either. Any suggestion of an example would be appreciated.

GPIO_AO is part of the gpio_ao and not part of the gpio handle.

Has there been any progress made here? One of the best use cases for these ARM single board computers is to deploy them with a GNSS receiver to create a small and cost effective network time server - but PPS is absolutely required.

Does Libre Computer offer any sort of bug bounty program? I know that I would gladly contribute to having this issue be resolved…

1 Like

@librecomputer Thank you for the suggestion. This version:

/*
 * Overlay to enable PPS on GPIOAO_6
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/meson-gic.h>

/ {
        compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";

        fragment@0 {
                target-path = "/";
                __overlay__ {
                        pps@0 {
                                compatible = "pps-gpio";
                                gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>;
                        };
                };
        };
};

After make && sudo make install && ldto merge pps-new and reboot I get this in my dmesg:

jeff@potato:~/git/libretech-wiring-tool/libre-computer/aml-s905x-cc/dt$ dmesg |grep pps
[    0.664522] pps_core: LinuxPPS API ver. 1 registered
[    0.664536] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    8.085724] pps-gpio pps@0: failed to map GPIO to IRQ: -6
[    8.085744] pps-gpio: probe of pps@0 failed with error -22
jeff@potato:~/git/libretech-wiring-tool/libre-computer/aml-s905x-cc/dt$

What is the proper way to assign an IRQ to a GPIO pin on this board?

An NTP server with PPS discipline is something I’m very interested in as well. Per some of the other posts and suggestions I’ve run the command dtc -I dtb -O dts pps-gpio.dtbo -o pps-gpio.dts on the raspberry pi device tree overlay located in /boot/overlays on the le potatoe current raspbian I’ve got on my board. This is the output, I’m not sure how to translate this -

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2708";
	fragment@0 {
		target-path = "/";
		__overlay__ {
			pps: pps@12 {
				compatible = "pps-gpio";
				pinctrl-names = "default";
				pinctrl-0 = <&pps_pins>;
				gpios = <&gpio 18 0>;
				status = "okay";
			};
		};
	};

	fragment@1 {
		target = <&gpio>;
		__overlay__ {
			pps_pins: pps_pins@12 {
				brcm,pins =     <18>;
				brcm,function = <0>;    // in
				brcm,pull =     <0>;    // off
			};
		};
	};

	__overrides__ {
		gpiopin = <&pps>,"gpios:4",
			  <&pps>,"reg:0",
			  <&pps_pins>,"brcm,pins:0",
			  <&pps_pins>,"reg:0";
		assert_falling_edge = <&pps>,"assert-falling-edge?";
		capture_clear = <&pps>,"capture-clear?";
	};
};

Do you guys have a device for us to purchase, test, and integrate into the wiring tool?

1 Like

This is the module I’m looking at, but any similiar device should do. It has a UBLOX neo 6 module I believe.

GT-U7 GPS module
UBLOX Datasheet

One thing I’m considering at this point is applying the dt overlay that makes uarta include RTS and CTS. Then feeding the pps into CTS. The old school way of making an NTP server applied the PPS to the DCD of the UART. This would require using gpsd to interface between the gps and ntp/chrony. The ppscheck utility included with gpsd indicates will sense pps applied to a UART CTS, so hopefully gpsd would as well. It really all boils down to getting the pps pulse to generate an interrupt somehow.

No sucess yet. I’ve added the uarta cts-rts dt overlay (sudo ldto merge uart-a-rts-cts). The GT-U7 listed above is connected -

Potatoe ----- GPS
pin 4 5v — gps v in
pin 6 gnd — gps gnd
pin 8 uarta tx — gps rx
pin10 uarta rx — gps tx
pin12 uarta cts — gps pps (100 ms pulse at start of each second)

The gpsd daemon is started (sudo gpsd -D 5 -N -n /dev/ttyAML6). gpsd connects via uarta and controls and configures the gps device. However the pps is not received via uarta cts.
gpsd messages --------
gpsd:INFO: gpsd_activate(2): activated GPS (fd 5)
gpsd:PROG: NTP:PPS: using SHM(0)
gpsd:PROG: NTP:PPS: using SHM(1)
gpsd:PROG: PPS:/dev/ttyAML6 chrony socket /run/chrony.ttyAML6.sock doesn’t exist
gpsd:PROG: KPPS:/dev/ttyAML6 checking /sys/devices/virtual/pps/pps0/path, /dev/ttyAML6
gpsd:INFO: KPPS:/dev/ttyAML6 RFC2783 path:/dev/pps0, fd is 6
gpsd:INFO: KPPS:/dev/ttyAML6 pps_caps 0x1133
gpsd:INFO: KPPS:/dev/ttyAML6 have PPS_CANWAIT
gpsd:INFO: KPPS:/dev/ttyAML6 kernel PPS will be used
gpsd:PROG: PPS:/dev/ttyAML6 thread launched
gpsd:INFO: PPS: activated /dev/ttyAML6 ntpshm_link_activate(): Clock
gpsd:INFO: KPPS:/dev/ttyAML6 kernel PPS timeout unknown error
gpsd:INFO: KPPS:/dev/ttyAML6 kernel PPS timeout unknown error
gpsd:INFO: KPPS:/dev/ttyAML6 kernel PPS timeout unknown error
gpsd:INFO: running with effective group ID 20
gpsd:INFO: running with effective user ID 115

pps is still not received by gpsd. Don’t know why. I’ve modded the python gpio getter script to sample 20 times a second for 5 seconds. (sudo python3 mygpioget.py 1 93) chip1-93 is the cts pin 12. You can see the 100 ms pulses are there, -

pi@libre-two:~/gpio $ sudo python3 mygpioget.py 1 93
0011000000000000000000110000000000000000011000000000000000000110000000000000000001100000000000000000

Gpsd does receive the serial messages from the gps on uarta and can generate the time, but no pps. Gpsd monitors RI, CD and CTS for pulses, not sure why there is a disconnect.

So that is it, I’ve used “sudo stty -F /dev/ttyAML6 crtscts” to turn on hardware flow control for the uart as well but no joy.


So I’m back to looking to enable a gpio pin with an interrupt to setup a pps-gpio device at /dev/pps0. Going to look at the existing overlays for a pin with an interrupt and try temp merging them to see if the pps pulses generate the interrups required on the pin.

It clearly indicates the problem. You have to specify the interrupt explicitly in the device tree overlay. You cannot assume the platform can figure out which IRQ it is based on the GPIO as this platform has no gpio_to_irq function. There are other overlays with interrupts and you can copy them verbatim as long as the interrupt controller is correct and the interrupt line number is correct.

Here is my latest attempt, still no joy. dmesg error here -

[   57.774241] pps-gpio 0.pps: error -ENOENT: failed to request PPS GPIO
[   57.774266] pps-gpio: probe of 0.pps failed with error -2

//setup pps-gpio on pin 11, chip0-pin8 -- GPIOAO_8

/dts-v1/;
/plugin/;

#include "dt-bindings/gpio/gpio.h"
#include "dt-bindings/gpio/meson-gxl-gpio.h"
#include "dt-bindings/interrupt-controller/irq.h"
#include "meson-gic.h"

/ {
        compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";


                fragment@0 {
                  target-path = "/";            
                __overlay__ {

                        pps: pps@0 {
                                compatible = "pps-gpio";
                                reg = <0>;
                                interrupt-parent = <&gpio_intc>;
                                interrupts = <MESON_GIC_GXL_GPIOAO_8 IRQ_TYPE_EDGE_RISING>;
                                pps-gpio = <&gpio_ao GPIOAO_8 GPIO_ACTIVE_HIGH>;
                                status = "okay";
                        };
                };
        };
};
dmesg gives - 

At this point think I can say pps-gpio is not compatible with a le potato. If you need a precision ntp server with pps discipline you will need to find another soc.

Just took a look at the pps-gpio driver. It uses the gpiod_to_irq function exclusively and does not look for interrupts. As this platform does not have a gpiod_to_irq function, it’s unable to grab the right interrupt.

This will require a kernel patch to add feeding the interrupt directly to the driver instead of the driver failing to map a GPIO to interrupt. We have added this to our engineering task list.

You need to install our GPIO to IRQ enabled kernel:

sudo apt update
sudo apt install linux-image-6.1.y-lts-irq-arm64

Then use this overlay: libretech-wiring-tool/pps-gpio-7j1-12.dts at master · libre-computer-project/libretech-wiring-tool · GitHub

Thank you! I’ve updated with the modded kernel and applied the overlay and am getting the time pulses recognized.

One issue with the overlay, think … IRQ_TYPE_EDGE_FALLING>;
assert-falling-edge; …
both FALLING/falling should be RISING/rising as the rising edge of the time pulse corresponds to the start of the second. That is the only change I’ve made. Need to do more testing and get the Chrony configuration sorted for the best operation. Hope to get out a post soon with the working setup for everything.

Please test it and report any changes needed to the overlay. We have emables GPIO to IRQ on our standard LTS kernel.

Yes, this working great, here are the overlay rising edge changes -

/*
 * Copyright (c) 2022 Da Xue
 * Author: Da Xue <da@libre.computer>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */
 
/*
 * Overlay aimed to create pps-gpio on 7J1 pin 12 (GPIOAO_6)
 * This requires an GPIO to IRQ enabled kernel and will not work without one.
 */

/*
 * Edited to switch interrupt to rising edge
 *
/

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/meson-gxl-gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/meson-gic.h>

/ {
	compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";

	fragment@0 {
		target-path = "/";
		__overlay__ {
			pps_gpio: pps-gpio {
				compatible = "pps-gpio";
				pinctrl-names = "default";
				pinctrl-o = <&spdif_out_ao_6_pins>;
				gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>;
				interrupts = <&gpio_intc MESON_GIC_GXL_GPIOAO_6 IRQ_TYPE_EDGE_RISING>;
				assert-rising-edge;
				status = "okay";
			};
		};
	};
};

This is the version I used, have trouble with the includes -

/*
 * Copyright (c) 2022 Da Xue
 * Author: Da Xue <da@libre.computer>
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */
 
/*
 * Overlay aimed to create pps-gpio on 7J1 pin 12 (GPIOAO_6)
 * This requires an GPIO to IRQ enabled kernel and will not work without one.
 */

/*
 * Modified to switch to rising edge interrupt and
 * Modified to remove symbols so can be compiled without includes
*/


/dts-v1/;
/plugin/;

/*
#include "/boot/mydt/dt-bindings/gpio/gpio.h"
#include "/boot/mydt/dt-bindings/gpio/meson-gxl-gpio.h"
#include "/boot/mydt/dt-bindings/interrupt-controller/irq.h"
#include "/boot/mydt/dt-bindings/interrupt-controller/meson-gic.h"
*/

/ {
	compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";

	fragment@0 {
		target-path = "/";
		__overlay__ {
			pps_gpio: pps-gpio {
				compatible = "pps-gpio";
				pinctrl-names = "default";
				pinctrl-o = <&spdif_out_ao_6_pins>;
				gpios = <&gpio_ao 6 0>; /*  =<&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; */
				interrupts = <&gpio_intc 6 1>; /* =<&gpio_intc MESON_GIC_GXL_GPIOAO_6 IRQ_TYPE_EDGE_RISING>;  */
				assert-rising-edge;
				status = "okay";
			};
		};
	};
};

Compile the above with this command -

#dtc -I dts -O dtb pps-gpio-7j1-12-rising.dts -o pps-gpio-7j1-12-rising.dtbo

Copy into place prior to merge where ever your overlays are located ??libretech-wiring-tool/libre-computer/aml-s905x-cc/dt/

Here is a quick synopsis of the procedure I used to get this working -

Physical Connection to the GT-U7 gps module.
5v in, 3.3v pps and serial signals

GPS     7j1 Pin 
Vin ----- 4, 5volts
Gnd ----- 6, Ground
Tx  ----- 5, UART_RX_AO_B
Rx  ----- 7, UART_TX_AO_B
PPS ----- 12, GPIOAO_6 -The magic interrupt



Pre req - Le Potato running - 2022-09-22-raspbian-bullseye-arm64+aml-s905x-cc.img
        - pps-gpio modified for rising edge see post above 

Here we go - 
#apt update
#apt upgrade
#apt install linux-image-6.1.y-lts-irq-arm64
#apt install gpsd
#apt install chronyc
#apt install pps-tools
#git clone https://github.com/libre-computer-project/libretech-wiring-tool.git
#cd libretech-wiring-tool/
#./install.sh
//Overlay modified to use rising edge if interrupt
#ldto merge pps-gpio-7j1-12-rising
#ldto merge uart-ao-b

#reboot

//well lookee here !!
pi@raspberrypi:~ $ dmesg|grep pps
[    0.663946] pps_core: LinuxPPS API ver. 1 registered
[    0.663960] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    8.733323] pps pps0: new PPS source pps-gpio.-1
[    8.733399] pps pps0: Registered IRQ 42 as PPS source
pi@raspberrypi:~ $ 

---------- chrony.conf ------------------
//add the follwing lines, optionally delete unneeded servers/pools
#nano /etc/chrony/chrony.conf 

# PPS from the pps-gpio interrupts
refclock PPS /dev/pps0 refid PPS0 prefer precision 1e-5

# Serial data from ttyAML2.  offset is the estimate of the fraction of
# a second the serial data arrives behind the pps.  Found experimentally. 
refclock SHM 0 refid AML2 offset 0.126 precision 1e-1

-------------------------------------------

-----------gpsd.service file---------------

#nano /usr/lib/systemd/system/gpsd.service 

//Change the Exec line to - 
ExecStart=/usr/sbin/gpsd -n -s 9600 /dev/ttyAML2

--------------------------------------------

#reboot

Hopefully you are golden in 5 or 30 minutes - 

pi@raspberrypi:~ $ chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
#* PPS0                          0   4   377    14   +547ns[ +639ns] +/-   10us
#- AML2                          0   4   377    15  -4707us[-4707us] +/-  100ms
^- time2.google.com              1   8   377   172  -3059us[-3058us] +/-   15ms
^- time-d-b.nist.gov             1   8   377   171  -2999us[-2998us] +/-   12ms
pi@raspberrypi:~ $ 

Thats under 1 us accuracy stratum 1 ntp server for about $50 (Le Potato=$35 + GT-U7=$10)! (Does fluctuate up to 2 or 3 us occasionally)

2 Likes

Thanks. We have updated the overlay in the repo.

2 Likes