Device tree or driver settings for alternate RTC on BSP 5.0

I have a carrier with an MCP7940N RTC chip in i2c bus 1 at address 6f.

The device tree overlay includes:

&i2c1 {
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";

	/* real time clock on carrier board */
	rtc_i2c: rtc@6f {
		compatible = "microchip,mcp7940x";
		reg = <0x6f>;
		status = "okay";
	};
};

According to https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt, this string looks like the correct “compatible” for the driver to use the microchip part.

The reg statement is what changes the RTC’s i2c address. OK so far.

We soft reboot the board. Then we check the dmesg log (the kernel ring buffer). The system is clearly finding the RTC at address 6f (device tree above must be operative). All is well!

# dmesg | grep rtc
[    1.749502] rtc-ds1307 0-006f: registered as rtc0
[    1.751064] snvs_rtc 20cc000.snvs:snvs-rtc-lp: registered as rtc1
[    3.760173] rtc-ds1307 0-006f: setting system clock to 2021-04-17T15:18:09 UTC (1618672689)

But if we cold start. Then we check the dmesg log:

# dmesg | grep rtc
[    1.749499] rtc-ds1307 0-006f: registered as rtc0
[    1.751128] snvs_rtc 20cc000.snvs:snvs-rtc-lp: registered as rtc1
[    3.004759] rtc-ds1307 0-006f: setting system clock to 2000-01-01T00:00:00 UTC (946684800)

Note: BSP 2.8.6 works fine . I’m not sure where to look now. I’m assuming the overlay is working since the kernel is finding a clock at address 6f. I don’t understand why power on reset is different from soft reboot here.

Also, I know something is working because if I reboot the system cold, then soft-reboot without setting the RTC with /sbin/hwclock --systohc, the time is still 2000.

I’m sure the issue is a typing error in the overlay… but I can’t see it.

Check your defconfig. Is the MCP7940N enabled in the kernel?

I don’t see a config option for that either way, just MCP795.

The MCP7940N is served the DS1307 driver (see https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt)

I don’t see any conditional compiles in (linux/rtc-ds1307.c at master · torvalds/linux · GitHub) that would explain this.

And on the 2.8.6 BSP that works, it isn’t set either.

CONFIG_RTC_DRV_DS1307=y is set on both.

Here are the config entries set for the RTC.

CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_NVMEM=y
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_DRV_SNVS=y

This is why I think it’s something in the “compatible” line in the device tree overlay…

Ah, I didn’t realize this was compatible with the 1307 driver. So how does your battery backup circuit look? Are you sure it’s powered up right when the system is off? Or, if you’re using a supercap, have you kept the system on long enough to charge things up?

Otherwise it looks like the kernel is recognizing your part correctly. It’s just not keeping time when off.

Positive the hardware works. No issue with BSP 2.8.

It looks like the mcp7940N has a bit in a register enabling battery backup. If the kernel doesn’t recognize this variant it doesn’t set it. The issue I have is, why does the device tree overload snippet I included successfully change the i2c address to 6f but not properly set the device type to MCP7940x?

You’re probably going to have to dig into the driver source to see how it’s figuring out which part is actually connected.

FYI the DT overload text doesn’t change the I2C address, it just tells the kernel and drivers that there is a part sitting at address 6F. The driver itself needs to handshake with that address and do any internal configuration necessary to get going.

Greetings @dgribben!

Since your RTC is working fine on BSP 2.8.6, I’ll assume your hardware is correct.

Since the driver - and thus the logic - is the same for all ds1307-compatible RTCs, I can only assume there might be differences between the register settings on BSP 2.8.6 (downstream kernel 4.9) and BSP 5.0 (downstream or upstream kernel 5.4), so I would start looking into that.

Which exact BSP and kernel version are you using?

uname says “5.4.91-5.2.0-devel”

I got everything to work by forcing rtc-ds1307.c to use ‘mcp794xx’. I put some ps_info statements in the driver and learned that the first time ds1307_probe() was being called it was correctly setting up for the mcp7940x, but then it is mysteriously called a second time (not sure why) and was overwriting the type member with 0. My delivery schedule overwhelmed my curiosity and I hard-coded the assignments of ds1307->type and chip to match the ‘correct’ answer, successfully. (Since this kernel is only for my use, that’s a brute force solution). The root problem is the battery backup bit having to be set in the Microchip part by the driver; once that was set everything worked pefrectly.

Thanks for the update!