• Content Count

  • Joined

  • Last visited

About Dennboy

  • Rank

Profile Information

  • Gender
  • Location
    The Netherlands
  • Interests
    high speed sensing, ADC, SPI, DMA, GPIO, hardware interrupts

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. A way to disable hardware is by setting its status to disabled in the device tree, take a look at " dtc -I fs -O dts /sys/firmware/devicetree/base|less" to see the runtime devicetree. For instance for sound and video this would look like below, which you can convert to dtb with something like "dtc -I dts -O dtb youroverlay.dts > youroverlay.dtb" and add as a user-overlay (place dtb file in /boot/overlay-user) and add "user-overlays=youroverlay" line in /boot/armbianEnv.txt. /dts-v1/; / { compatible = "allwinner,sun8i-h3","allwinner,sun50i-h5","friendlyarm,nanopi-neo2"; fragment@0 { target-path = "/soc"; __overlay__ { hdmi@1ee0000 { status = "disabled"; }; mixer@1100000 { status = "disabled"; }; sound { status = "disabled"; }; }; }; fragment@1 { target-path = [2f 00]; __overlay__ { sound { status = "disabled"; }; }; }; };
  2. Hi Robert, I recently looked at the spi controller driver and discovered that the DMA configuration is not used by the SPI controller. It found that dma_set_mask_and_coherent only gives a result until kernel version 4.13.3 (and maybe a bit later), and fails after kernel version 4.14.39 and later). The result is that the DMA configured for SPI is silently ignored, and regular SPI transfers are done instead. Can you confirm that you don't see any performance improvement with DMA enabled? Kind regards, Dennis
  3. I digged further into the kernel code and had a look at spi.c and spi-sun6i.c. It appears that can_dma is a function pointer that is checked while setting up DMA for a transaction. This function pointer is not assigned in spi-sun6i.c (and spi-sun4i.c for that matter). This would explain why I don't see performance improvements when I try to use DMA for with kernel 4.13.3, since the DMA ignored because can_dma=0x0. I compared the behavior with the spi-stm32.c in the 4.14.67 kernel, and this driver reads the controller DMA addresses and sets the can_dma function pointer when they are set: spi->dma_tx = dma_request_slave_channel(spi->dev, "tx"); if (!spi->dma_tx) dev_warn(&pdev->dev, "failed to request tx dma channel\n"); else master->dma_tx = spi->dma_tx; spi->dma_rx = dma_request_slave_channel(spi->dev, "rx"); if (!spi->dma_rx) dev_warn(&pdev->dev, "failed to request rx dma channel\n"); else master->dma_rx = spi->dma_rx; if (spi->dma_tx || spi->dma_rx) master->can_dma = stm32_spi_can_dma; The assigned function stm32_spi_can_dma mainly checks if it makes sense to do dma, i.e. is the transfer size bigger than the fifo (I believe the fifo is 64 bits for the H3 SPI Controller, so that may pay off for most SPI transactions): return (transfer->len > spi->fifo_size); Bottom line, the SPI controller does not yet take the configured DMA configuration into account, and it could be fixed using a similar approach to the spi-stm32.c. The
  4. Dear Ohms, Many thanks for your feedback. Indeed, the dma_set_mask_and_coherent call does no longer work with the same driver code and device tree. Regarding the sunxi modifications, I cannot easily find release notes of the modifications between kernel 4.13.3 and newer. The change could also be in the mainline kernel updates, e.g. stricter checks in the DMA or SPI driver. The strange thing is that independent of kernel version spi->controller->can_dma is 0x0, which is supposed to tell whether the controller supports DMA according to spi.h. @can_dma: determine whether this controller supports DMA Could it be that the DMA part of the SPI controller is not completely configured from the information in the device tree? Furthermore, I don't notice any performance gain when I have DMA enabled in the older 4.13.3 kernel and allocate coherent memory for rx_dma and tx_dma in the spi_transfer struct (using dmam_alloc_coherent).
  5. Dennboy


  6. Hi user283746, Thanks for your suggestion, it could indeed be better to change the defaults, but then with the userspace governor. I initially placed the my cpufreq command in /etc/rc.local to make it persistent. cpufreq-info tells me the available frequencies and governers (e.g. on H5): available frequency steps: 408 MHz, 648 MHz, 816 MHz, 912 MHz, 960 MHz, 1.01 GHz, 1.06 GHz, 1.10 GHz, 1.15 GHz available cpufreq governors: conservative, userspace, powersave, ondemand, performance, schedutil I have no clue how to underclock RAM, didn't find hints in the devicetree or boot commands.
  7. Dear mainline developers, I'm writing a (mainline) SPI driver for de ads131 from TI which I would like to make use of DMA, on the orangePIzero H2, zero+ H3/H5 and nanopi NEO2+. On the 4.13.3-sunxi kernel (armbian 5.33), this works fine, the driver is automatically loaded when the associated devicetree overlay is loaded, and the DMA can be allocated. However, when I compile the same driver for newer kernels (4.14.17-sunxi, 4.14.39-sunxi, 4.14.67-sunxi armbian 5.59), the dma allocation no longer appears to work, while the SPI part of the devicetree is identical except for the phandle (checked with dtc -I fs /sys/firmware/devicetree/base on newest 4.14.67-sunxi kernel, since 4.14.65 headers were not available in newest 5.59 stretch mainline H3 image) and does specify the DMA addresses for the SPI controller: spi@01c69000 { compatible = "allwinner,sun8i-h3-spi"; clocks = <0x6 0x1f 0x6 0x53>; resets = <0x6 0x10>; clock-names = "ahb", "mod"; status = "okay"; #address-cells = <0x1>; interrupts = <0x0 0x42 0x4>; #size-cells = <0x0>; dma-names = "rx", "tx"; phandle = <0x5e>; reg = <0x1c69000 0x1000>; pinctrl-0 = <0x21>; dmas = <0x1f 0x18 0x1f 0x18>; linux,phandle = <0x5e>; pinctrl-names = "default"; ads131a04@0 { compatible = "ti,ads131a04"; status = "okay"; reg = <0x0>; spi-max-frequency = <0x1e84800>; }; }; I use the following DMA calls that appear to fail in newer kernels, and the driver reverts to non-DMA spi transfers: static int ads131_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); int ret; ret=spi_setup(spi); if (ret!=0) { printk("ads131: Problem setting up spi-device, ret=%d",ret); return ret; } printk("ads131: spi->controller->can_dma=0x%lx",(unsigned long)spi->controller->can_dma); ... if (!dma_set_mask_and_coherent(&spi->dev, DMA_BIT_MASK(64))) { printk("ads131: dma 64 bit"); } else if (!dma_set_mask_and_coherent(&spi->dev, DMA_BIT_MASK(32))) { printk("ads131: dma 32 bit"); } else if (dma_set_mask_and_coherent(&spi->dev, DMA_BIT_MASK(24))) { dev_warn(&spi->dev, "ads131: No suitable DMA available\n"); goto dma_ignore; } else { printk("ads131: dma 24 bit"); } ... I get the following output from my driver in kernel 4.14.67-sunxi: dennis@orangepizeroplus2:~$ dmesg |grep -i dma [ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool [ 0.091893] DMA: preallocated 2048 KiB pool for atomic coherent allocations [ 5.254126] ads131: spi->controller->can_dma=0x0 [ 5.255134] ads131a04 spi0.0: ads131: No suitable DMA available I get the following with the older 4.13.3-sunxi kernel (armbian 5.33): [ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool [ 19.848567] ads131: spi->controller->can_dma=0x0 [ 19.849538] ads131: dma 64 bit [ 19.849544] ads131: dma_mask=18446744073709551615 [ 19.849564] xfer dma memory allocated with 16 buffers Do I need to specify additional information in the devicetree for DMA to work in SPI drivers with newer kernels, or do I need to add something to my driver before trying to use DMA with newer kernels? Kind regards, Dennis
  8. Dear all, I discovered that the leds section is missing in the devicetree of orangepizeroplus2 H5 (at least upto kernel 4.14.39), and had to write an overlay to get them to work. The overlay has been attached. I've added this overlay file to /boot/overlay-user/ and added the overlay in /boot/armbianEnv.txt as follows: Kind regards, Dennis sun50i-h5-orangepi-zeroplus-leds.dts
  9. The frequency scaling seems to be working a bit better on OrangePI zeroplus2 H3 / H5 and NanoPi now (kernel 4.14.39). We discovered however that the frequency scaling severely impacts the SPI communication, resulting in SPI failures during the frequency change. It could be that SPI communication fails because it uses the same clock as the CPU. In certain cases you may want to pre-set the frequency to a conservative fixed frequency for better reliability of especially SPI communication ( sudo cpufreq-set -f 816MHz) and add a heat-sink.
  10. Attached is the kernel patch for sunxi-pinctrl.c on the 4.14.13 kernel, created in the cache/sources/linux-mainline/linux-4.14.y/drivers/pinctrl/sunxi directory from the armbian cached source. pinctrl-sunxi.c.patch
  11. I just updated my test program with the patch to verify its workings, the main change is: if (debounce<=16) { writel((((debounce-1)/2)<<4)+1,sunxi_irq_debounce_reg_from_bank(i,pctl->desc->irq_bank_base)); continue; } Here is a further zoomed plot of the previous test program, showing the devicetree input-debounce for a pinctrl bank on x-axis versus the calculated debounce register entry. Here is the plot for the new test program (see attached source), showing the devicetree input-debounce for the pinctrl bank on x-axis versus the calculated debounce register entry. One can clearly see that we now cover all debounce register values. pinctr-sunxi-test2.c
  12. A small update. The proposed fix removes low frequenty timer with prescaling 2^0. Probably better to mainly change the first 9 register values, so low frequenty timer stays mostly the same as before. if (debounce<=16) { writel(((debounce/2-1))<<4+1,sunxi_irq_debounce_reg_from_bank(i,pctl->desc->irq_bank_base)); continue; }
  13. I have done some tests with the input-debounce devicetree settings under the pinctrl on H5 (nanopi, kernel Linux nplus2 4.14.12-sunxi64). I discovered the following behaviour: when I set the input-debounce to <0x1 0x3 0x4>, I read back the following with devmem2: Value at address 0x1C20A18 (0xffff90bf6a18): 0x51, debounce on prescale=2^5, using HOSC timer Value at address 0x1C20A38 (0xffffbc512a38): 0x61, debounce on prescale=2^6, using HOSC timer Value at address 0x1C20A58 (0xffff9cbb4a58): 0x71, debounce on prescale=2^7, using HOSC timer However, I would really like to enable the HOSC timer without any debounce. So I rewrote the setup_debounce kernel code to run in user-space (see attached), and analysed what is going on. The figure below shows the value written to the debounce register with increasing input-debounce value in the device tree. It appears that the HOSC timer is only used for input-debounce 1 upto 9 with written register values 0x51, 0x61, and 0x71. For input-debounce 10 upto 40 the register is set to 0, and after that it is gradually increased using the LOSC timer upto register value 0x70. This behavior is probably not what was intended with this code. And it would be great if all debounce registry settings (7 values for HOSC timer plus 7 values for LOSC timer) can all be used from the device tree input-debounce field. I propose to change the behavior for the first 40 values to the following: input-debouce 0: keep default value input-debouce 1..5: use HOSC with value 0, writing 0x1 to debounce register input-debouce 6..10: use HOSC with value 1, writing 0x11 to debounce register input-debouce 11..15..: use HOSC with value 2, writing 0x21 to debounce register input-debouce 16..20: use HOSC with value 3, writing 0x31 to debounce register input-debouce 21..25: use HOSC with value 4, writing 0x41 to debounce register input-debouce 26..30: use HOSC with value 5, writing 0x51 to debounce register input-debouce 31..35: use HOSC with value 6, writing 0x61 to debounce register input-debouce 36..40: use HOSC with value 7, writing 0x71 to debounce register This could be easily done using something like below instead of the hosc_freq&hosc_div code: if (debounce<=40) { writel(((debounce-1)/5)<<4+1,sunxi_irq_debounce_reg_from_bank(i,pctl->desc->irq_bank_base)); continue; } pinctr-sunxi-test.c
  14. Looks like nanopi neo plus2 is almost there, great work! I also stumbled on this Ethernet issue with the next kernel, in the Armbian_5.37_Nanopineoplus2_Debian_stretch_next_4.14.5.img I build yesterday with the Armbian build script. I need custom kernel to get some more Industrial I/O features like standalone triggers enabled, so the older 4.13.14 packages are unfortunately not enough. I guess I have to use wifi until there is a fix. If there is anything I can do to help (e.g. testing an initial fix), please let me know. I also noticed some other minor issues in the image, otherwise it seems to be working fine: - kernel headers are not installed in the image (but may not be needed by all) - the /boot/overlay-user folder does not exist - had to run ldconfig a few times to get my libs in /usr/local/lib working
  15. When I understand correctly, the interrupts you are sending have a rather short duration, i.e. within a microsecond. It could be that the interrupt is polled by the Allwinner and/or kernel. Are you using the right clock source, I read somewhere that there is also a higher precision clock. Not sure how to set that up, hopefully someone in this forum can help you with that. Another issue could be the input-debouncer, that is mainly useful when you attach a key/switch to the GPIO pin not with fast hardware. When this is set to a long value, it may average your interrupt signal away. I've played a bit with this debouncer (via gpio include file) , but got errors trying to set it directly on a GPIO pin.