sysfs issue, high numbered digital input port does not get updated (di_3_16)



  • Hi,

    I have a unipi L203 and I am trying to use the sysfs interface for polling the digital inputs. At first try I was thinking I was doing something wrong, as I've connected a signal to di_3_16, but its di_value is never updated.

    then I've switched to di_3_12 and that worked flawlessly. The kernel module seems to have detected the number of digital inputs properly:

    [    7.023285] UNIPISPI: UniPi Board E_16Di_U_14Ro (L:3 U:2 C:8) at CS3 (nspi2 12000kHz) detected.
                   			Fw: v5.5 Uarts:0, reg1001-4: 100e 0000 0810 0310
    [    7.133637] UNIPISPI: UniPi Board E_16Di_U_14Ro (L:3 U:2 C:8) at CS2 (nspi1 12000kHz) detected.
                   			Fw: v5.5 Uarts:0, reg1001-4: 100e 0000 0810 0310
    [    7.169587] UNIPISPI: UniPi Board B_1000 (L:0 U:0 C:0) at CS1 (nspi0 12000kHz) detected.
                   			Fw: v5.5 Uarts:1, reg1001-4: 0404 0311 0010 0010
    [    7.172370] UNIPISPI: Detected UniPi board combination corresponding to Axon L205
    [    7.172781] UNIPISPI: 16 User LEDs detected at nspi0
    [    7.205848] UNIPISPI: SPI Driver Registered, Major Version: Version 1.28:2019:08:22
    [    7.213648] UNIPISPI: ModBus/SPI interface /dev/unipispi (240:0) created.
    [    7.224392] UNIPIUART: Serial port ttyNS0 on UniPi Board nspi0 port:0 created
    

    ie, nspi2 has 16 Di ports and 14 Ros which seems correct. I am trying to troubleshoot using the kernel sources but ideas are welcome.

    Bazsi



  • I've noticed that the driver identifies my unipi as an Axon L205, wheras it is a Neuron L203, but looking through the data structures the two devices are equivalent in configuration and only the printout seems to be misleading.

    I've also tried the same issue in iogroup2 and the same applies, di_2_12 works whereas di_2_16 doesn't.

    I've also connected my signal to a different pin and di_2_15 WORKS. So only the last bit doesn't seem to work in that register.



  • I don't get it, when issuing this command:

    # perf_4.18 trace  --no-syscalls -e regmap:* cat /sys/devices/platform/unipi_plc/io_group2/di_2_16/di_value
    0
         0.000 regmap:regmap_hw_read_start:spi0.2 reg=0 count=1
         0.215 regmap:regmap_hw_read_done:spi0.2 reg=0 count=1
         0.227 regmap:regmap_reg_read:spi0.2 reg=0 val=8000
    

    I can see that regmap_reg_read() returned 0x8000, e.g. the MSB of the 16 bit register set, at least when the input is on. When turning off the voltage, the same says:

    # perf_4.18 trace  --no-syscalls -e regmap:* cat /sys/devices/platform/unipi_plc/io_group2/di_2_16/di_value
    0
         0.000 regmap:regmap_hw_read_start:spi0.2 reg=0 count=1
         0.215 regmap:regmap_hw_read_done:spi0.2 reg=0 count=1
         0.226 regmap:regmap_reg_read:spi0.2 reg=0 val=0
    
    

    which means that the input was properly reported by the underlying hardware. The code that seemingly triggers this regmap_reg_read() is as follows:

    static ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf)
    {
            # ... setup code deleted ...
                
            int val;
    
            # ... setup code deleted ...
            if (n_spi && n_spi->combination_id != 0xFF && n_spi->features && n_spi->features->di_count > n_di->io_index) {
                    regmap_read(n_spi->reg_map, n_spi->regstart_table->di_val_reg + (n_di->io_index / 16), &val);
                    val &= 0x1 << (n_di->io_index % 15);
                    val = val >> (n_di->io_index % 15);
                    ret = scnprintf(buf, 255, "%d\n", val);
            }
            return ret;
    }
    

    I originally wanted to write that I can't see the issue, but I just realized:

    The remainder function is using modulo 15 instead of 16. The io_index is of course 15 for di_2_16, which will result in "0" to be used, thus di_2_16 would yield the input value of the first input, that is di_2_01. Let me check.

    Bingo, results with di_2_01 set:

    root@L203-sn190:/usr/src/unipi-1.32/unipi/src# perf_4.18 trace  --no-syscalls -e regmap:* cat /sys/devices/platform/unipi_plc/io_group2/di_2_16/di_value 
    1
         0.000 regmap:regmap_hw_read_start:spi0.2 reg=0 count=1
         0.199 regmap:regmap_hw_read_done:spi0.2 reg=0 count=1
         0.208 regmap:regmap_reg_read:spi0.2 reg=0 val=1
    


  • I have just pushed a fix to https://github.com/bazsi/unipi-kernel/tree/sysfs-fix-to-correctly-query-the-last-input

    BTW: perhaps it would make sense to mirror unipi-kernel to github, would make such contributions much easier.



  • I have added another patch on the gpio path, which also seems problematic with the "u8" variable bit-indexed into the high-order bits.


  • administrators

    Hello @bazsi77 ,

    thanks for the extensive report and for providing the patch. It will be part of the next stable release. Let us know if/when you plan to purchase any of our products so we can give you a "thank you" discount.


  • administrators

    Implemented in kernel modules 1.33.test.20190926173405 available in the test repository.



  • Thanks a lot. I am planning some extensions to my system, so I might want to use the discount you promised :)

    Btw, any reason why DI/DO lines are registered as separate GPIO chips, instead of using a smaller number of chips each with 16/14 lines?