Linux6.16では全般的に大きな変更はないですが、SHプロセッサに限っては大幅な改変がRTCドライバにありました。

これまでのRTCドライバは、アラーム、桁上げ、周期割り込みの3つの割り込みを扱っていましたが、今回の改変でアラーム割り込みのみに限定され、それに伴う大幅改変であり、ついでにそれと関係ない部分も大幅改変がなされました。

それらの大幅改変は基本的には問題ないようですが、どうやら実機での確認をしていないようなので、そのままでは正常に動作しません。

そのため、大幅改変されたソースコードのうち、問題のある部分をバグ修正しないといけません。

大きな問題は、桁上げ割り込みを廃止したにもかかわらず、時刻読み出しをする sh_rtc_read_time関数では、桁上げ割り込みを前提とした下記のソースコードとなっています。

static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct sh_rtc *rtc = dev_get_drvdata(dev);
	unsigned int sec128, sec2, yr, yr100, cf_bit;

	if (!(readb(rtc->regbase + RCR2) & RCR2_RTCEN))
		return -EINVAL;

	do {
		unsigned int tmp;

		spin_lock_irq(&rtc->lock);

		tmp = readb(rtc->regbase + RCR1);
		tmp &= ~RCR1_CF; /* Clear CF-bit */
		tmp |= RCR1_CIE;
		writeb(tmp, rtc->regbase + RCR1);

		sec128 = readb(rtc->regbase + R64CNT);

		tm->tm_sec	= bcd2bin(readb(rtc->regbase + RSECCNT));
		tm->tm_min	= bcd2bin(readb(rtc->regbase + RMINCNT));
		tm->tm_hour	= bcd2bin(readb(rtc->regbase + RHRCNT));
		tm->tm_wday	= bcd2bin(readb(rtc->regbase + RWKCNT));
		tm->tm_mday	= bcd2bin(readb(rtc->regbase + RDAYCNT));
		tm->tm_mon	= bcd2bin(readb(rtc->regbase + RMONCNT)) - 1;

		if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
			yr  = readw(rtc->regbase + RYRCNT);
			yr100 = bcd2bin(yr >> 8);
			yr &= 0xff;
		} else {
			yr  = readb(rtc->regbase + RYRCNT);
			yr100 = bcd2bin((yr == 0x99) ? 0x19 : 0x20);
		}

		tm->tm_year = (yr100 * 100 + bcd2bin(yr)) - 1900;

		sec2 = readb(rtc->regbase + R64CNT);
		cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;

		spin_unlock_irq(&rtc->lock);
	} while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);

#if RTC_BIT_INVERTED != 0
	if ((sec128 & RTC_BIT_INVERTED))
		tm->tm_sec--;
#endif

	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
		__func__, tm->tm_sec, tm->tm_min, tm->tm_hour,
		tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);

	return 0;
}

SHのハードウェアマニュアルでは下記のようなフローが記載されています。

桁上げ割り込みを廃止した場合、(a)の手順で処理をしないといけないですが、実際の改変では、(b)となったままですので、(a)の手順で処理するようにしなければなりません。

また、ドライバ初期化部分では、アラーム割り込み番号がplatform_get_irq関数で取得できたら、そのまま割り込み番号をセットすればいいですが、下記コードではそうなっていません。

static int __init sh_rtc_probe(struct platform_device *pdev)
{

------- 中略 --------

	ret = platform_get_irq(pdev, 0);
	if (unlikely(ret <= 0)) {
		dev_err(&pdev->dev, "No IRQ resource\n");
		return -ENOENT;
	}

	if (!pdev->dev.of_node)
		rtc->alarm_irq = platform_get_irq(pdev, 2);
	else
		rtc->alarm_irq = ret;

これを下記のように修正します。

static int __init sh_rtc_probe(struct platform_device *pdev)
{

------- 中略 --------

	ret = platform_get_irq(pdev, 0);
	if (unlikely(ret <= 0)) {
		dev_err(&pdev->dev, "No IRQ resource\n");
		return -ENOENT;
	}
    rtc->alarm_irq = ret;