How to resolve communication issues affecting Sealevel’s XR17V35X based serial devices (7xxxec serial cards, 7106e, Relio R1)?

Posted on   •  Updated on

The following devices are based on the XR17V35X and are known to be impacted by the GPIO configuration issue described in this article:

  • 7xxxec serial cards
  • 7106e
  • Relio R1

The article applies to the following kernel versions:

  • 4.11.0-4.14.189
  • 4.15.0-4.19.134
  • 4.20.0-5.4.53
  • 5.4.0-5.7.8

The kernel patch titled “serial: exar: Fix GPIO configuration for cards based on XR17V35X” (commit ID 5fdbe136ae19ab751daaa4d08d9a42f3e30d17f9) resolves this issue discussed throughout article. This patch is known to be included in 4.14.190, 4.19.135, 5.4.54, and all kernels above 5.7.9.

Symptoms of this issue:

  • On the card, D1-D4 status LEDs are blinking.
  • All serial ports (/dev/ttyS* devices) appear on the system.
  • dmesg reports no errors related to 8250_exar, XR17C35X, or the /dev/ttyS* devices.
  • Unable to communicate on any port, loopback test fails, etc.

Linux supports direct use of XR17V35X UART based serial devices with the drivers included in the kernel. However, kernel version 4.11 includes a change to the GPIO configuration of the UART that renders Sealevel XR17V35X based devices inoperable.

Notice to Red Hat 8 users: Neither option below is able to be used on Red Hat 8 (Confirmed on 8.0, 8.2, and 8.5) because of changes made by Red Hat.

  • Option 1 cannot be used because libgpiod is unable to detect the relevant gpiochip on Red Hat 8. This has been verified with multiple versions of libgpiod.
  • Option 2 cannot be used because Red Hat 8 builds the 8250_exar driver into the kernel, rather than loading it as a module. This means that you cannot patch the 8250_exar driver individually or separately from the whole kernel. The only known workaround for this is to install a custom kernel which includes the patch mentioned earlier in the article.
  • Similar distributions, such as Fedora 28, do not have either of these issues. We highly recommend contacting Red Hat to make them aware of this issue and to encourage them to implement the aforementioned patch.

Option 1: Configure the GPIO through the gpioset utility

  1. Install the libgpiod utility (https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/about/). 
    • It may be available as a package in your distribution. If not, it must be compiled manually using the build procedure outlined in the link above.
  1. After the utility is installed, run the following commands:
    • gpioset gpiochip0 12=0
    • gpioset gpiochip0 13=0
    • gpioset gpiochip0 14=0
    • gpioset gpiochip0 15=0
  1. Your Sealevel asynchronous serial card should now be functional. Please note that you will need to run the commands in step 2 on every boot. You might consider automating this using common Linux utilities like cron, service files, etc

Option 2: Apply a patch to your kernel module/driver and load the patched kernel module

For convenience, an example auto-patching script has been created to assist with compiling the kernel module. It can be downloaded from here. For more information on how to use the script and how to perform the steps manually please see the readme.txt file in the download.

NOTES: 

  • This script may need slight modifications to work with the kernel version you have. It has been tested on kernel versions 4.11.0, 4.12.0, 4.13.0, 4.15.0, and 5.3.0 in Linux Mint.
  • Always examine the source code before applying a patched driver to your system. 

Verify functionality of the serial device

You can verify the GPIO configuration is correct and that the card is working by using a loopback adapter and following the steps below.

  1. Get the current ttyS for the serial card by running sudo cat /proc/tty/driver/serial
    • The ports on the card should identify as “uart:XR17V35X”
  2. Run sudo stty -F /dev/ttyS* raw -echo -onlcr on each port, where * is the number provided by the command in the previous step. This will clean up the output we see later but isn’t required for the card to function.
  3. Run sudo cat /dev/ttyS* where * is the number we have been using. We are now listening for data on this port.
  4. Open up another terminal. On this terminal, enter the command sudo echo 'hello' > /dev/ttyS* where * is the same number used in step 3.
  5. You should see hello printed in the terminal window from step 3.