Regulator configuration for RTC backup battery in i.MX6 PMIC - linux-device-driver

I'm switching with the phycore i.MX6 som from phytec's dev kit to an own board. The usermanuals for both the som and devkit can be found on phytec's page. Now I want to configure the rtc to keep the time during reboot's and poweroffs.
The battery (in my case supercap) is connected to the VDD_BAT pin of the phycore i.MX6 som (page 10). The internal PMIC is the da9062 connected via the i2c bus which is configured in the som dtsi file as rtc1.
imx6qdl-phytec-phycore-som.dtsi:
...
aliases {
rtc1 = &da9062_rtc;
};
...
&i2c3 {
pmic#58 {
da9062_rtc: rtc {
compatible = "dlg,da9062-rtc";
};
};
};
This file I didn't touch at all.
Next, I told the kernel to take his hwclock and systime time from rtc1 instead of rtc0:
CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
CONFIG_RTC_SYSTOHC_DEVICE="rtc1"
The driver is being loaded correctly as far as I can tell:
dmesg | grep rtc
[ 2.489836] da9063-rtc da9062-rtc: rtc core: registered da9063-rtc as rtc1
[ 2.499713] snvs_rtc 20cc000.snvs:snvs-rtc-lp: rtc core: registered 20cc000.snvs:snvs-rtc-lp as rtc2
[ 3.260348] da9063-rtc da9062-rtc: setting system clock to 2000-01-01 02:37:55 UTC (946694275)
and
cat /sys/class/rtc/rtc1/name
da9063-rtc da9062-rtc
Now, I can set the time via date and transfer it to the hwclock via
hwclock --systohc
.
After rebooting the system and hwclock is set to the previously set date which is fine. After cutting the power the clock gets reset.
I've measured the voltage of the supercap which is around 220mV. The datasheet of the da9062 tells me the chip does have an regulator for the battery which needs to be configured (Table 127: BBAT_CONT (0x0C5)).
As far as I understand the kernel/rtc subsystem, the driver for the rtc should take care of the charging of the battery or provide an userspace interface so I can do it myself. But I can't find anything on this topic.
I am using yocto to build the kernel/image for my board.
Is there something I'm missing or do I need to patch the driver myself in order to charge the supercap? Maybe there's an option in the devicetree to set the charging voltage and current for the cap?
I appreciate any ideas and suggestions, thanks.

Aparently the driver does not support charging a battery/supercap out of the box and it has exclusive access rights to the i2c device address which prevents userspace applications to access the device.
My solution to this problem is to set those values before the driver takes over:
Since this i2c bus is already configured in my barebox devicetree, I can access it before I boot the kernel (provided barebox is compiled with the i2c subsystem enabled in menuconfig). Here I can run a script which sets the BBAT and PD registers to enable charging the supercap.
Though, the cleaner solution would be to extend the driver and provide a userspace interface for this functionality.
Another possible solution I did not investigate would be to check if the driver can be compiled as a module, so I could unload the module, set the registers and load it again.

Related

Azure NetX Duo only provides the driver for LAN8742 compatible Ethernet PHYs. How can I manage other Ethernet PHYs?

I'm developing an application for STM32F4 with Azure RTOS Netx Duo. In particular I'm trying to adapt the example Nx_TCP_Echo_Server application for my board where is present the Ethernet Phy ADIN1200 produced by Analog Devices.
Note about example Nx_TCP_Echo_Server
The Nx_TCP_Echo_Server example application has been made for a STM32F429ZI-NUCLEO demo board (code of Nx_TCP_Echo_Server on github).
In the demo board STM32F429ZI-NUCLEO the Ethernet Phy is compatible with the lan8742 driver (see the lan8742 driver code on GitHub). Unfortunately the Ethernet PHY ADIN1200 present on my board is not compatible with that driver.
I have noted that the sixth parameter of the function nx_ip_create() is the pointer function nx_stm32_eth_driver.
This pointer function points to lan8742 driver.
Below I show the invocation of the function nx_ip_create() present in the file app_netxduo.c (code of app_netxduo.c) of the Nx_TCP_Echo_Server example application:
/* Create the main NX_IP instance */
ret = nx_ip_create(&IpInstance, "Main Ip instance", NULL_ADDRESS, NULL_ADDRESS, &AppPool, nx_stm32_eth_driver,
pointer, 2 * DEFAULT_MEMORY_SIZE, DEFAULT_PRIORITY);
The documentation of NetX Duo reports the following info:
The NX_IP structure contains everything to manage a single IP instance. This includes general TCP/IP protocol information as well as the application-specific physical network driver's entry routine. The driver's entry routine is defined during the nx_ip_create service. Additional devices may be added to the IP instance via the nx_ip_interface_attach service.
My development environment
My development environment is composed by:
STM32CubeMX version 6.7.0
In the STM32CubeMX I have installed the Package STM32F4 version 1.27.1
To use ThreadX I have added to CubeMX the software pack X-CUBE-AZRTOS-F4 version 1.1.0
By the previous environment I can find only the driver for LAN8742.
My question
How can I find other Ethernet PHY drivers for NetX Duo other than the one for lan8742?
EDIT
I have found this driver for ADIN1200 but it is very far from the driver lan8742.c provided by my development tool (see the code of lan8742).
In fact the API of the 2 drivers are very different; for example NetX Duo (and before it: LwIP) needs a function like LAN8742_RegisterBusIO() (present in the LAN8742 driver) to init a structure with pointer functions useful to write and read registers of the Ethernet PHY, but in this driver this function and its data structures are not present.
You can find different phy drivers from https://github.com/azure-rtos/samples.
mimxrt1060:KSZ8081RNB
same54:KSZ8091RNA 
stm32f746:LAN8742A-CZ-TR
rx65n rsk:DP83620SQE
For others, you will need to develop the driver by yourself, based on existing ones.

How to find out who loads specific Linux kernel module?

I built a certain driver as module (m) for Linux, the spi-imx by NXP. Nontheless, Linux probes this driver when booting. I'm struggling to find out what process/other module/driver requests this spi-imx driver. A depmod does not show any dependencies between the spi-imx an other modules (except for the spidev as submodule).
After some research, I found out that Linux automatically (?) calls modprobe when it detects a new device. So does Linux actually call modprobe because the ecSPI'S status in the device tree as "okay"? If so, how can I prevent this? I would like to dynamically load the spi-imx from a user space application via modprobe. The story behind it: a coprocessor uses this SPI line in parallel to the Linux boot process. This interferes of course and interrupts the coprocessor's use of the SPI line. When the coprocessor has finished its transfer via SPI (a boot mechanism as well), it should hand over the SPI line to Linux.
I'm very thankful for any kind of tips, links, hints and comments on this.
Thanks a lot for the answers. As you guys mentioned, I also found out that Linux itself probes the device if present ("okay").
One possible solution is to complete cut off the modprobe call via an entry like "install spi-imx /bin/false" in the *.conf file. But that makes it impossible to load the driver via modprobe, for Linux and for user space.
"blacklist spi-imx" inside a *.conf located at /etc/modprobe.d/ is the way to prevent Linux from probing the driver when booting. After that, a modprobe from user space can successfully load the driver afterwards.
Thanks again & best regards

Application not loading after DFU:Leave

I am trying to program the STM32F401 flash on our board in DFU mode. I am using the dfu-util tool in my linux computer.For my project requirements the BOOT 0 pin is always kept high throughout the process.
I am using the following command to flash and jump to application code.
dfu-util -a 0 -s 0x08000000:leave -D <location-to-binary>.bin
After the flashing is done I can see through 'lsusb' command that sometimes the MCU is not out of DFU boot loader, and sometimes out of it. Either way the application does not start.
When I further try to use the leave command when it's in bootloader, it shows the following log and the above situation continues,
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
Opening DFU capable USB device...
Device ID 0483:df11
Device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Interface #0 ...
Determining device status...
DFU state(10) = dfuERROR, status(10) = Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations
Clearing status
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash "
DfuSe command mode
Submitting leave request...
Transitioning to dfuMANIFEST state
Thanks in advance for any advice or help.
I found the issue. I had to uncomment the define USER_VECT_TAB_ADDRESS in the system_stm32f4xx.c file.
Basically what was happening was that bootloader was looking for a loadable vector address from the flash application. With the USER_VECT_TAB_ADDRESS commented the pointer to the vector address kept pointing to the bootloader vector table effectively crashing the flash application resetting the controller. With the BOOT 0 pin high it kept loading into bootloader with each reset.
More information about this is available in this similar question:
STM32G474 bootloader exit

CodeSys killing eth0 on Raspberry Pi 4?

I'm running into a very strange issue attempting to run CodeSys on a 4GB RasPi-4. Long story short, the Pi works fine right up until I start running the CodeSys project. When I do, within 60sec, eth0 goes down and cannot be brought back up. Even rebooting the Pi has no effect. The only way I've found to recover eth0 is to re-burn RasPiOS from the source image from Raspberrypi.org (which I've done about 30 times over the past few days, trying to trial-and-error my way out of this).
Linux raspberrypi 5.4.79-v7l+ #1373 SMP Mon Nov 23 13:27:40 GMT 2020 armv7l GNU/Linux
I have eth0 set to a static IP using /etc/dhcpcd.conf. Whatever is causing this issue is not altering my settings there. Attempts to use ifconfig eth0 up/down have no effect -- no errors, no feedback, just nothing. Checking eth0's state shows "waiting for carrier," despite being connected to an active switch (I've also swapped out all the cables and the switch to eliminate them as the source of the problem).
When I re-burn the Pi and install CodeSys, eth0 stays up indefinitely (24hrs+ in my longest test). It's starting the CodeSys project that kills eth0. A reboot after etho "dies" gives a series of bcmgenet messages that appear to be related:
pi#raspberrypi:~ $ dmesg | grep bcmg
[ 1.033665] bcmgenet fd580000.ethernet: failed to get enet clock
[ 1.033685] bcmgenet fd580000.ethernet: GENET 5.0 EPHY: 0x0000
[ 1.033709] bcmgenet fd580000.ethernet: failed to get enet-wol clock
[ 1.033730] bcmgenet fd580000.ethernet: failed to get enet-eee clock
[ 1.044648] libphy: bcmgenet MII bus: probed
[ 9.528502] bcmgenet fd580000.ethernet: configuring instance for external RGMII
[ 9.535175] bcmgenet fd580000.ethernet eth0: Link is Down
I also tried creating a new CodeSys project from scratch that had no eth0 drivers (ModBus, Ethernet/IP) installed, only the GPIO driver. That didn't help either -- eth0 dies within 60sec.
The strangest part is, only eth0 seems to be affected. The GPIO pins keep cycling as controlled by the CodeSys project (I have a simple LED-blinking program running), and I can still SSH into the Pi using wifi. But since my main reason for setting this Pi up is to use Ethernet/IP and ModBus....
This thread: at GitHub is the only place I've found anyone describing anything similar to what I'm experiencing, but in that case CodeSys is not installed. I did try adding genet.skip_umac_reset=n to my cmdline.txt as suggested in the thread, but it had no effect.
So, it turned out this was an issue configuring the GPIO pins.
CodeSys has two difference "device" files for adding the GPIO pins to the project device tree. The default selection is for older Pi models, and the alternate choice (labelled only for B+ and Pi2) is the correct one for the Pi4.
As it turns out, the outdated GPIO device file will work on a Pi4, mostly. But using the wrong device file allows CodeSys to try configuring GPIO pins that shouldn't be tampered with. In this case, GPIO 28 and 29. Setting either of them to Output mode killed eth0.
Using the correct device file removes 28&29 from the list of configurable GPIO pins. It also gives the correct list of available GPIO pins for the newer Pi models, hopefully avoiding other potential config issues that I didn't trip over.
In CodeSys, right-clicking on the GPIOs element in the device tree offers the option to "Update the Device." Select this option to get the list of available device files, and select the correct one before using the "Update Device" button in the bottom of the window.

iMX6: MSI-X not working in Linux PCIe device driver

I'm trying to get MSI-X working on an iMX6 (Freescale/NXP/Qualcomm) CPU in Linux v4.1 for a PCIe character device driver. Whenever I call either pci_enable_msix() or pci_enable_msix_range() or pci_enable_msix_exact() I get an EINVAL value returned. I do have the CONFIG_PCI_MSI option selected in the kernel configuration and I am also able to get single MSI working with pci_enable_msi(), but I cannot get multiple MSI working either.
I have tested my driver code on an Intel i7 running kernel v3 with the same PCIe hardware attached and I was able to get MSI-X working without any problems so I know my code is correctly written and the hardware is correctly functioning.
When running on the iMX6 I can use lspci -v to view that the hardware has MSI-X capabilities and see the number of IRQs it allows. I can even get the same correct number in my driver when calling pci_msix_vec_count().Questions
Are there any other kernel configuration flags I need to set?
Is there anything specific to the iMX6 CPU I need to consider?
Does anyone have any experience with the iMX6 and either MSI-X or
multiple MSI?