--- /dev/null
+From 1c9977b263475373b31bbf86af94a5c9ae2be42c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Tue, 20 May 2025 17:15:58 -0400
+Subject: pinctrl: mediatek: eint: Fix invalid pointer dereference for v1 platforms
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+
+commit 1c9977b263475373b31bbf86af94a5c9ae2be42c upstream.
+
+Commit 3ef9f710efcb ("pinctrl: mediatek: Add EINT support for multiple
+addresses") introduced an access to the 'soc' field of struct
+mtk_pinctrl in mtk_eint_do_init() and for that an include of
+pinctrl-mtk-common-v2.h.
+
+However, pinctrl drivers relying on the v1 common driver include
+pinctrl-mtk-common.h instead, which provides another definition of
+struct mtk_pinctrl that does not contain an 'soc' field.
+
+Since mtk_eint_do_init() can be called both by v1 and v2 drivers, it
+will now try to dereference an invalid pointer when called on v1
+platforms. This has been observed on Genio 350 EVK (MT8365), which
+crashes very early in boot (the kernel trace can only be seen with
+earlycon).
+
+In order to fix this, since 'struct mtk_pinctrl' was only needed to get
+a 'struct mtk_eint_pin', make 'struct mtk_eint_pin' a parameter
+of mtk_eint_do_init() so that callers need to supply it, removing
+mtk_eint_do_init()'s dependency on any particular 'struct mtk_pinctrl'.
+
+Fixes: 3ef9f710efcb ("pinctrl: mediatek: Add EINT support for multiple addresses")
+Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Link: https://lore.kernel.org/20250520-genio-350-eint-null-ptr-deref-fix-v2-1-6a3ca966a7ba@collabora.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+[ukleinek: backport to 6.15.y]
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pinctrl/mediatek/mtk-eint.c | 26 +++++++++--------------
+ drivers/pinctrl/mediatek/mtk-eint.h | 5 ++--
+ drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 2 -
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 -
+ 4 files changed, 16 insertions(+), 19 deletions(-)
+
+--- a/drivers/pinctrl/mediatek/mtk-eint.c
++++ b/drivers/pinctrl/mediatek/mtk-eint.c
+@@ -22,7 +22,6 @@
+ #include <linux/platform_device.h>
+
+ #include "mtk-eint.h"
+-#include "pinctrl-mtk-common-v2.h"
+
+ #define MTK_EINT_EDGE_SENSITIVE 0
+ #define MTK_EINT_LEVEL_SENSITIVE 1
+@@ -505,10 +504,9 @@ int mtk_eint_find_irq(struct mtk_eint *e
+ }
+ EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
+
+-int mtk_eint_do_init(struct mtk_eint *eint)
++int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
+ {
+ unsigned int size, i, port, inst = 0;
+- struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;
+
+ /* If clients don't assign a specific regs, let's use generic one */
+ if (!eint->regs)
+@@ -519,7 +517,15 @@ int mtk_eint_do_init(struct mtk_eint *ei
+ if (!eint->base_pin_num)
+ return -ENOMEM;
+
+- if (eint->nbase == 1) {
++ if (eint_pin) {
++ eint->pins = eint_pin;
++ for (i = 0; i < eint->hw->ap_num; i++) {
++ inst = eint->pins[i].instance;
++ if (inst >= eint->nbase)
++ continue;
++ eint->base_pin_num[inst]++;
++ }
++ } else {
+ size = eint->hw->ap_num * sizeof(struct mtk_eint_pin);
+ eint->pins = devm_kmalloc(eint->dev, size, GFP_KERNEL);
+ if (!eint->pins)
+@@ -533,16 +539,6 @@ int mtk_eint_do_init(struct mtk_eint *ei
+ }
+ }
+
+- if (hw && hw->soc && hw->soc->eint_pin) {
+- eint->pins = hw->soc->eint_pin;
+- for (i = 0; i < eint->hw->ap_num; i++) {
+- inst = eint->pins[i].instance;
+- if (inst >= eint->nbase)
+- continue;
+- eint->base_pin_num[inst]++;
+- }
+- }
+-
+ eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
+ if (!eint->pin_list)
+ goto err_pin_list;
+@@ -610,7 +606,7 @@ err_cur_mask:
+ err_wake_mask:
+ devm_kfree(eint->dev, eint->pin_list);
+ err_pin_list:
+- if (eint->nbase == 1)
++ if (!eint_pin)
+ devm_kfree(eint->dev, eint->pins);
+ err_pins:
+ devm_kfree(eint->dev, eint->base_pin_num);
+--- a/drivers/pinctrl/mediatek/mtk-eint.h
++++ b/drivers/pinctrl/mediatek/mtk-eint.h
+@@ -88,7 +88,7 @@ struct mtk_eint {
+ };
+
+ #if IS_ENABLED(CONFIG_EINT_MTK)
+-int mtk_eint_do_init(struct mtk_eint *eint);
++int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin);
+ int mtk_eint_do_suspend(struct mtk_eint *eint);
+ int mtk_eint_do_resume(struct mtk_eint *eint);
+ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
+@@ -96,7 +96,8 @@ int mtk_eint_set_debounce(struct mtk_ein
+ int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
+
+ #else
+-static inline int mtk_eint_do_init(struct mtk_eint *eint)
++static inline int mtk_eint_do_init(struct mtk_eint *eint,
++ struct mtk_eint_pin *eint_pin)
+ {
+ return -EOPNOTSUPP;
+ }
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+@@ -416,7 +416,7 @@ int mtk_build_eint(struct mtk_pinctrl *h
+ hw->eint->pctl = hw;
+ hw->eint->gpio_xlate = &mtk_eint_xt;
+
+- ret = mtk_eint_do_init(hw->eint);
++ ret = mtk_eint_do_init(hw->eint, hw->soc->eint_pin);
+ if (ret)
+ goto err_free_eint;
+
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -1039,7 +1039,7 @@ static int mtk_eint_init(struct mtk_pinc
+ pctl->eint->pctl = pctl;
+ pctl->eint->gpio_xlate = &mtk_eint_xt;
+
+- return mtk_eint_do_init(pctl->eint);
++ return mtk_eint_do_init(pctl->eint, NULL);
+ }
+
+ /* This is used as a common probe function */
--- /dev/null
+From fe9f5f96cfe8b82d0f24cbfa93718925560f4f8d Mon Sep 17 00:00:00 2001
+From: Alexandre Mergnat <amergnat@baylibre.com>
+Date: Mon, 28 Apr 2025 12:06:48 +0200
+Subject: rtc: Fix offset calculation for .start_secs < 0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexandre Mergnat <amergnat@baylibre.com>
+
+commit fe9f5f96cfe8b82d0f24cbfa93718925560f4f8d upstream.
+
+The comparison
+
+ rtc->start_secs > rtc->range_max
+
+has a signed left-hand side and an unsigned right-hand side.
+So the comparison might become true for negative start_secs which is
+interpreted as a (possibly very large) positive value.
+
+As a negative value can never be bigger than an unsigned value
+the correct representation of the (mathematical) comparison
+
+ rtc->start_secs > rtc->range_max
+
+in C is:
+
+ rtc->start_secs >= 0 && rtc->start_secs > rtc->range_max
+
+Use that to fix the offset calculation currently used in the
+rtc-mt6397 driver.
+
+Fixes: 989515647e783 ("rtc: Add one offset seconds to expand RTC range")
+Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
+Link: https://lore.kernel.org/r/20250428-enable-rtc-v4-2-2b2f7e3f9349@baylibre.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/rtc/class.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/rtc/class.c
++++ b/drivers/rtc/class.c
+@@ -326,7 +326,7 @@ static void rtc_device_get_offset(struct
+ *
+ * Otherwise the offset seconds should be 0.
+ */
+- if (rtc->start_secs > rtc->range_max ||
++ if ((rtc->start_secs >= 0 && rtc->start_secs > rtc->range_max) ||
+ rtc->start_secs + range_secs - 1 < rtc->range_min)
+ rtc->offset_secs = rtc->start_secs - rtc->range_min;
+ else if (rtc->start_secs > rtc->range_min)
--- /dev/null
+From 7df4cfef8b351fec3156160bedfc7d6d29de4cce Mon Sep 17 00:00:00 2001
+From: Alexandre Mergnat <amergnat@baylibre.com>
+Date: Mon, 28 Apr 2025 12:06:47 +0200
+Subject: rtc: Make rtc_time64_to_tm() support dates before 1970
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexandre Mergnat <amergnat@baylibre.com>
+
+commit 7df4cfef8b351fec3156160bedfc7d6d29de4cce upstream.
+
+Conversion of dates before 1970 is still relevant today because these
+dates are reused on some hardwares to store dates bigger than the
+maximal date that is representable in the device's native format.
+This prominently and very soon affects the hardware covered by the
+rtc-mt6397 driver that can only natively store dates in the interval
+1900-01-01 up to 2027-12-31. So to store the date 2028-01-01 00:00:00
+to such a device, rtc_time64_to_tm() must do the right thing for
+time=-2208988800.
+
+Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
+Link: https://lore.kernel.org/r/20250428-enable-rtc-v4-1-2b2f7e3f9349@baylibre.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/rtc/lib.c | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+--- a/drivers/rtc/lib.c
++++ b/drivers/rtc/lib.c
+@@ -46,24 +46,38 @@ EXPORT_SYMBOL(rtc_year_days);
+ * rtc_time64_to_tm - converts time64_t to rtc_time.
+ *
+ * @time: The number of seconds since 01-01-1970 00:00:00.
+- * (Must be positive.)
++ * Works for values since at least 1900
+ * @tm: Pointer to the struct rtc_time.
+ */
+ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
+ {
+- unsigned int secs;
+- int days;
++ int days, secs;
+
+ u64 u64tmp;
+ u32 u32tmp, udays, century, day_of_century, year_of_century, year,
+ day_of_year, month, day;
+ bool is_Jan_or_Feb, is_leap_year;
+
+- /* time must be positive */
++ /*
++ * Get days and seconds while preserving the sign to
++ * handle negative time values (dates before 1970-01-01)
++ */
+ days = div_s64_rem(time, 86400, &secs);
+
++ /*
++ * We need 0 <= secs < 86400 which isn't given for negative
++ * values of time. Fixup accordingly.
++ */
++ if (secs < 0) {
++ days -= 1;
++ secs += 86400;
++ }
++
+ /* day of the week, 1970-01-01 was a Thursday */
+ tm->tm_wday = (days + 4) % 7;
++ /* Ensure tm_wday is always positive */
++ if (tm->tm_wday < 0)
++ tm->tm_wday += 7;
+
+ /*
+ * The following algorithm is, basically, Proposition 6.3 of Neri
+@@ -93,7 +107,7 @@ void rtc_time64_to_tm(time64_t time, str
+ * thus, is slightly different from [1].
+ */
+
+- udays = ((u32) days) + 719468;
++ udays = days + 719468;
+
+ u32tmp = 4 * udays + 3;
+ century = u32tmp / 146097;