gigneil, LDiego_Int
Good news, after working on this for a while, I finally got a breakthrough and I'm now able to get a PPS GPIO interrupt working in connecting an Adafruit Ultimate GPS logger shield to my Galileo Gen2 board and configuring and modifying the Linux kernel for PPS GPIO support.
The key breakthrough was that when it comes to the Galileo gen2 board, GPIOs and interrupt, the key thing I found was that I could not get this to work until I moved call to register the GPIO PPS device to the gen2 board platform code after all the other I2C and SPI devices were initialized. It appears that the way the Galileo GPIO and/or Interrupt setup code is structured, to get you own GPIO and/or interrupt, you have to request it after the Galileo is all done with its GPIO/Interrupt setup (probably due to some sequencing/loading/initialization).
In getting this up and running, for me these were the most useful links for help:
http://mythopoeic.org/pi-ntp/
http://rdlazaro.info/compu-Raspberry_Pi-RPi-stratum0.html
https://groups.google.com/forum/#!topic/beagleboard/bU_xZ9tWoiA
To get this to work I first had to do a bitbake linux-yocto-clanton -c menuconfig -f and go through the kernel menu and enable PPS and PPS GPIO support.
I then applied a similar set of changes (most useful for me was the beagle board info at Google Groups) to the Intel Gen2 platform driver code
For my case, I put all my Galileo Yocto source under a folder my home directory "bsp" and then use the convention of using "yocto_build" for the builds.
So for the Gailelo board platform source code, it is at:
~/bsp/meta-clanton_v1.0.1/yocto_build/tmp/work/clanton-poky-linux-uclibc/linux-yocto-clanton/3.8-r0/linux/drivers/platform/x86/quark
The file I modified (Gen2 board, I haven't looked nor do I plan to look at how to do this on a Gen1 board) is: intel_qrk_plat_galileo_gen2.c
Here is a summary of the modifications:
At the top of the file add the .h file for GPIO PPS
#include <linux/pps-gpio.h> // Added for PPS support
Add code for PPS structures and init function (for my case I added this right after thespi1_onboard_devs struct). NOTE: for my case I chose gpio_pin of 1 as due to the way the Galileo Linux code is structured and the way the actual board routes the GPIO, I wanted a real Quark GPIO (not one off of the expander chip), so I used real Quark GPIO_9 which maps to Digital IO pin IO6 on the Arduino connector and in linux software for some reason is setup as GPIO 1.
/* PPS GPIO data */
static struct pps_gpio_platform_data pps_gpio_info = {
.assert_falling_edge = false,
.capture_clear = false,
.gpio_pin = 1,
.gpio_label = "PPS",
};
static struct platform_device pps_gpio_device = {
.name = "pps-gpio",
.id = -1,
.dev = {
.platform_data = &pps_gpio_info
},
};
static void pps_init(void) {
int err;
pr_info("%s:\n",__func__);
err = platform_device_register(&pps_gpio_device);
if (err) {
pr_err("%s: Could not register PPS_GPIO device\n",__func__);
} else {
pr_info("%s: PPS_GPIO device registered OK\n",__func__);
}
}
Here is the important part (and got it to work for me), add the call to pps_init at the end of the restricted GPIO probe function:
/**
* intel_qrk_gpio_restrict_probe
*
* Make GPIOs pertaining to Firmware inaccessible by requesting them. The
* GPIOs are never released nor accessed by this driver.
*
* Registers devices which are dependent on this GPIO driver
*/
static int intel_qrk_gpio_restrict_probe(struct platform_device *pdev)
{
int ret = 0;
struct i2c_adapter *i2c_adap = NULL;
struct i2c_client *client = NULL;
// << OTHER CODE NOT SHOWN HERE >>
// << Added pps code at the end right before return >>
i2c_put_adapter(i2c_adap);
pr_info("%s: Calling pps_init\n", __func__);
pps_init();
pr_info("%s: PPS init completed\n",__func__);
return ret;
}
With that (and other changes I'm doing for my project), I then did a bitbake linux-yocto-clanton -c compile -f to get a clean compile, then a bitbake linux-yocto-clanton to do a full kernel build, and finally a bitbake image-full-galileo (actually in my project I have a custom bitbake recipe called bitbake-image-full-timeserver as I'm also building loading the GPS daemon, NTP and PTP software as well).
I then copied the image files to my SD card, loaded up on my Galileo GEN2 card and then booted, here are the key messages showing PPS/GPIO stuff loading OK (NOTE: In my case, I've added a lot of additional pr_info to multiple places my custom kernel as part of my debugging this over the last several weekends).
Text below from boot messages (also can be seen using the dmesg command), first the pps core is setup during platform init, this happens due to the fact the PPS driver was selected in the menu config options:
[ 4.005545] pps_core: pps_init
[ 4.065081] pps_core: pps_init: LinuxPPS API ver. 1 registered
[ 4.071045] pps_core: pps_init: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
Later in the boot, the GEN2 restricted GPIO probe executes (NOTE: My kernel has lots of pr_info added, you won't see all of these messages). At the end, the pps_init in the platform driver is called.
[ 10.070250] intel_qrk_gip_probe:
[ 10.073556] intel_qrk_gip 0000:00:15.2: enabling device (0000 -> 0002)
[ 10.230188] intel_qrk_gpio_probe:
[ 10.234546] intel_qrk_gpio_restrict_probe:
[ 10.238686] intel_qrk_gpio_restrict_probe: Getting I2C adapter
[ 10.623196] intel_qrk_gpio_restrict_probe: i2c adapter not ready yet. Deferring..
[ 10.760678] platform qrk-gpio-restrict-sc.0: Driver qrk-gpio-restrict-sc requests probe deferral
[ 10.987471] intel_qrk_gpio_probe UIO addr 0x90006000 internal_addr 0xd262c000 size 4096 memtype 1
[ 11.200571] sch_gpio_probe UIO port addr 0x1080 size 64 porttype 1
[ 11.206925] intel_qrk_gpio_restrict_probe:
[ 11.211146] intel_qrk_gpio_restrict_probe: Getting I2C adapter
[ 11.221741] intel_qrk_gip 0000:00:15.2: i2c speed set to 400kHz
[ 11.380116] intel_qrk_gpio_restrict_probe: i2c adapter not ready yet. Deferring..
[ 11.387699] platform qrk-gpio-restrict-sc.0: Driver qrk-gpio-restrict-sc requests probe deferral
[ 11.397153] intel_qrk_gip 0000:00:15.2: enabling bus mastering
[ 11.397206] intel_qrk_gip 0000:00:15.2: setting latency timer to 64
[ 11.397354] intel_qrk_gip 0000:00:15.2: irq 43 for MSI/MSI-X
[ 13.539455] pxa2xx-spi pxa2xx-spi.0: registered master spi0
[ 13.555749] spi_master spi0: will run message pump with realtime priority
[ 13.582953] intel_qrk_gpio_restrict_probe:
[ 13.587094] intel_qrk_gpio_restrict_probe: Getting I2C adapter
[ 13.593567] pxa2xx-spi pxa2xx-spi.1: registered master spi1
[ 13.600173] spi_master spi1: will run message pump with realtime priority
[ 13.625882] intel_qrk_gpio_restrict_probe: Reserving Gen2 specific GPIOs
[ 13.632723] intel_qrk_gpio_restrict_probe: Probing I2C devices
[ 13.711894] intel_qrk_gpio_restrict_probe: SPI: Add onboard devices
[ 13.718206] intel_qrk_spi_add_onboard_devs:
[ 13.786481] spi spi0.0: 1666666 Hz actual, PIO
[ 13.786543] spi spi0.0: setup mode 3, 8 bits/w, 16667000 Hz max --> 0
[ 13.786904] pxa2xx-spi pxa2xx-spi.0: registered child spi0.0
[ 13.787011] spi spi1.0: 5000000 Hz actual, PIO
[ 13.787056] spi spi1.0: setup mode 0, 8 bits/w, 50000000 Hz max --> 0
[ 13.787411] pxa2xx-spi pxa2xx-spi.1: registered child spi1.0
[ 13.787450] intel_qrk_gpio_restrict_probe: I2C devices' probes complete, releasing I2C bus
[ 13.795838] intel_qrk_gpio_restrict_probe: Calling pps_init
[ 13.801513] pps_init:
[ 13.890479] pps_init: PPS_GPIO device registered OK
[ 13.895400] intel_qrk_gpio_restrict_probe: PPS init completed
Then after boot, to test this I followed the guidelines in the other RPi and beaglebone "how to" posts, and I then did a modprobe pps_gpio to load and enable GPIO PPS driver which during the probes, sets up a PPS GPIO source and assigns the proper interrupt to it:
root@clanton:~# modprobe pps_gpio
[ 142.681622] pps-gpio: pps_gpio_probe: Pin: 1, Label:PPS
[ 142.686894] pps-gpio: pps_gpio_setup: Pin: 1, Label:PPS
[ 142.692264] pps-gpio: pps_gpio_probe: GPIO 1 mapped to IRQ 23
[ 142.706485] pps_core: pps_register_source: name: pps-gpio.-1, default_params: 17
[ 142.714674] pps_core: pps_register_cdev
[ 142.726165] pps_core: pps_register_source: pps_regigster_cdev for name: pps-gpio.-1 OK
[ 142.734238] pps pps0: new PPS source pps-gpio.-1
[ 142.746485] pps pps0: Registered IRQ 23 as PPS source
root@clanton:~#
To make sure it and the PPS core is loaded and running OK, I used the lsmod command and fgrep pps to get a list of all modules with "pps" in it. Note that now, there is both pps_gpio and pps_core running:
root@clanton:~# lsmod | fgrep pps
pps_gpio 12590 0 - Live 0xd26d7000
pps_core 13813 2 pps_gpio,ptp, Live 0xd261d000
root@clanton:~#
Now to test PPS, I first checked the schematic to make sure I wouldn't short anything by doing so (it was OK, there are several resistors on the GPIO lines of interest) and took a wire from 3.3V on the GPS shield to IO6 input and ran the command to make sure the PPS was interrupting and logging time when it occurs in the kernel.
First I ran the checked the pps0 assert with no triggers. In running it multiple times, the value is always 0.0
root@clanton:~# cat /sys/class/pps/pps0/assert
0.000000000#0
root@clanton:~#
Now I temporarily touched the 3.3V wire to IO6 and checked the assert. Now I'm getting interrupts and the PPS GPIO interrupt software gets
the time when they occur :-)
root@clanton:~# cat /sys/class/pps/pps0/assert
978310016.813620760#1
root@clanton:~#
root@clanton:~# cat /sys/class/pps/pps0/assert
978310030.491348967#2
root@clanton:~#
I then connected a wire connected from Adafruit shield PPS pin (output from real GPS module locked to time and position) to IO6 (real PPS) and I'm getting PPS interrupts :-)
You can see that the Galileo clock is running fast.
root@clanton:~# cat /sys/class/pps/pps0/assert
978311150.513781501#186
root@clanton:~# cat /sys/class/pps/pps0/assert
978311151.513850230#187
root@clanton:~# cat /sys/class/pps/pps0/assert
978311152.513913046#188
root@clanton:~# cat /sys/class/pps/pps0/assert
978311153.513976308#189
root@clanton:~# cat /sys/class/pps/pps0/assert
978311154.514036989#190
root@clanton:~# cat /sys/class/pps/pps0/assert
978311155.514100186#191
root@clanton:~# cat /sys/class/pps/pps0/assert
978311156.514142334#192
root@clanton:~#
So that is enough for me this weekend. Next weekend I'm going to try and connect PPS interrupts to NTP to hopefully get my Galileo GEN2 working as well (or preferably better) than a Raspberry PI can :-)
Hope this helps and best regards,
Alan