Linux RTC
 help / color / mirror / Atom feed
* Re: [PATCH 2/4] rtc: moxart: convert to dev_err_probe()
From: Alexandre Mergnat @ 2026-06-30 17:10 UTC (permalink / raw)
  To: Balakrishnan Sambath
  Cc: Alexandre Belloni, Baolin Wang, Chunyan Zhang, Orson Zhai,
	linux-kernel, linux-rtc
In-Reply-To: <20260528-cleanup-dev-err-probe-rtc-v1-2-29dc9cb6c3f0@microchip.com>

On Thu, 28 May 2026 09:16:45 +0530, Balakrishnan Sambath <balakrishnan.s@microchip.com> wrote:
> Use dev_err_probe() in place of dev_err() and return, which
> communicates the error type and helps debugging hardware issues.
> 
> No functional change.

Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>

-- 
Alexandre Mergnat <amergnat@baylibre.com>

^ permalink raw reply

* Re: [PATCH 1/4] rtc: palmas: convert to dev_err_probe()
From: Alexandre Mergnat @ 2026-06-30 17:10 UTC (permalink / raw)
  To: Balakrishnan Sambath
  Cc: Alexandre Belloni, Baolin Wang, Chunyan Zhang, Orson Zhai,
	linux-kernel, linux-rtc
In-Reply-To: <20260528-cleanup-dev-err-probe-rtc-v1-1-29dc9cb6c3f0@microchip.com>

On Thu, 28 May 2026 09:16:44 +0530, Balakrishnan Sambath <balakrishnan.s@microchip.com> wrote:
> diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
> index aecada6bcf8b..25fe7a8b73a0 100644
> --- a/drivers/rtc/rtc-palmas.c
> +++ b/drivers/rtc/rtc-palmas.c
> @@ -280,10 +278,8 @@ static int palmas_rtc_probe(struct platform_device *pdev)
>  	ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
>  			PALMAS_RTC_CTRL_REG_STOP_RTC,
>  			PALMAS_RTC_CTRL_REG_STOP_RTC);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "RTC_CTRL write failed, err = %d\n", ret);
> -		return ret;
> -	}
> +	if (ret < 0)
> +		return dev_err_probe(&pdev->dev, ret, "RTC_CTRL write failed\n");

The enable_bb_charging block earlier in this function (the two
palmas_update_bits() / "BACKUP_BATTERY_CTRL update failed" error paths)
follows the same dev_err()+return ret pattern but is left unconverted.
Converting those too keeps the whole probe consistent.
It's purely about readability, not correctness, so I give my RB.

Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>

-- 
Alexandre Mergnat <amergnat@baylibre.com>

^ permalink raw reply

* Re: [PATCH v1] rtc: mpfs: fix counter upload completion condition
From: Geert Uytterhoeven @ 2026-06-30 15:18 UTC (permalink / raw)
  To: Conor Dooley
  Cc: linux-riscv, Conor Dooley, stable, Valentina.FernandezAlanis,
	Daire McNamara, Alexandre Belloni, linux-rtc, linux-kernel
In-Reply-To: <20260513-panhandle-ashy-70c6abf84d59@spud>

Hi Conor,

On Wed, 13 May 2026 at 20:04, Conor Dooley <conor@kernel.org> wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
>
> The condition that needs to be checked for upload completion is the
> UPLOAD bit in the completion register going low. The original iterations
> of this driver used a do-while and this was converted to a
> read_poll_timeout() during upstreaming without the condition being
> inverted as it should have been.
>
> I suspect that this went unnoticed until now because a) the first read
> was done when the bit was still set, immediately completing the
> read_poll_timeout() and b) because the RTC doesn't hold time when power
> is removed from the SoC reducing its utility (I for one keep it
> disabled). If my first suspicion was true when the driver was
> upstreamed, it's not true any longer though, hence the detection of the
> problem.
>
> Fixes: 0b31d703598dc ("rtc: Add driver for Microchip PolarFire SoC")
> CC: stable@vger.kernel.org
> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>

Thanks, this landed as commit 9792ff8afa9017fe ("rtc: mpfs: fix counter
upload completion condition") in v7.2-rc1, and finally the endless
stream of:

    mpfs_rtc 20124000.rtc: timed out uploading time to rtc

is gone!

And no, it didn't go unnoticed, at least not for me, but you couldn't
reproduce it reliably before:
https://lore.kernel.org/bce2ca405ef96b1363fd1370887409d9e8468422.1660659437.git.geert+renesas@glider.be/

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-30  2:07 UTC (permalink / raw)
  To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
  Cc: oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
	Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>

Hi Fredrik,

kernel test robot noticed the following build warnings:

[auto build test WARNING on dc59e4fea9d83f03bad6bddf3fa2e52491777482]

url:    https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base:   dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link:    https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: loongarch-randconfig-r132-20260630 (https://download.01.org/0day-ci/archive/20260630/202606301024.GdcSNC79-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 16.1.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606301024.GdcSNC79-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606301024.GdcSNC79-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/rtc/rtc-ds1307.c:2332:9: sparse: sparse: statement expected after case label

vim +2332 drivers/rtc/rtc-ds1307.c

  2066	
  2067	static int ds1307_probe(struct i2c_client *client)
  2068	{
  2069		const struct i2c_device_id *id = i2c_client_get_device_id(client);
  2070		struct ds1307		*ds1307;
  2071		const void		*match;
  2072		int			err = -ENODEV;
  2073		int			tmp;
  2074		const struct chip_desc	*chip;
  2075		bool			want_irq;
  2076		bool			ds1307_can_wakeup_device = false;
  2077		unsigned char		regs[8];
  2078		struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
  2079		int			trickle_charger_setup = 0;
  2080	
  2081		ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
  2082		if (!ds1307)
  2083			return -ENOMEM;
  2084	
  2085		dev_set_drvdata(&client->dev, ds1307);
  2086		ds1307->dev = &client->dev;
  2087		ds1307->name = client->name;
  2088	
  2089		ds1307->regmap = devm_regmap_init_i2c(client, &regmap_config);
  2090		if (IS_ERR(ds1307->regmap)) {
  2091			dev_err(ds1307->dev, "regmap allocation failed\n");
  2092			return PTR_ERR(ds1307->regmap);
  2093		}
  2094	
  2095		i2c_set_clientdata(client, ds1307);
  2096	
  2097		match = device_get_match_data(&client->dev);
  2098		if (match) {
  2099			ds1307->type = (uintptr_t)match;
  2100			chip = &chips[ds1307->type];
  2101		} else if (id) {
  2102			chip = &chips[id->driver_data];
  2103			ds1307->type = id->driver_data;
  2104		} else {
  2105			return -ENODEV;
  2106		}
  2107	
  2108		want_irq = client->irq > 0 && chip->alarm;
  2109	
  2110		if (!pdata)
  2111			trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
  2112		else if (pdata->trickle_charger_setup)
  2113			trickle_charger_setup = pdata->trickle_charger_setup;
  2114	
  2115		if (trickle_charger_setup < 0)
  2116			return trickle_charger_setup;
  2117	
  2118		if (trickle_charger_setup && chip->trickle_charger_reg) {
  2119			dev_dbg(ds1307->dev,
  2120				"writing trickle charger info 0x%x to 0x%x\n",
  2121				trickle_charger_setup, chip->trickle_charger_reg);
  2122			regmap_write(ds1307->regmap, chip->trickle_charger_reg,
  2123				     (u8)trickle_charger_setup);
  2124		}
  2125	
  2126	/*
  2127	 * For devices with no IRQ directly connected to the SoC, the RTC chip
  2128	 * can be forced as a wakeup source by stating that explicitly in
  2129	 * the device's .dts file using the "wakeup-source" boolean property.
  2130	 * If the "wakeup-source" property is set, don't request an IRQ.
  2131	 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
  2132	 * if supported by the RTC.
  2133	 */
  2134		if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
  2135			ds1307_can_wakeup_device = true;
  2136	
  2137		switch (ds1307->type) {
  2138		case ds_1337:
  2139		case ds_1339:
  2140		case ds_1341:
  2141		case ds_3231:
  2142			/* get registers that the "rtc" read below won't read... */
  2143			err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
  2144					       regs, 2);
  2145			if (err) {
  2146				dev_dbg(ds1307->dev, "read error %d\n", err);
  2147				goto exit;
  2148			}
  2149	
  2150			/* oscillator off?  turn it on, so clock can tick. */
  2151			if (regs[0] & DS1337_BIT_nEOSC)
  2152				regs[0] &= ~DS1337_BIT_nEOSC;
  2153	
  2154			/*
  2155			 * Using IRQ or defined as wakeup-source?
  2156			 * Disable the square wave and both alarms.
  2157			 * For some variants, be sure alarms can trigger when we're
  2158			 * running on Vbackup (BBSQI/BBSQW)
  2159			 */
  2160			if (want_irq || ds1307_can_wakeup_device)
  2161				regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
  2162	
  2163			regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
  2164				     regs[0]);
  2165	
  2166			/* oscillator fault? warn */
  2167			if (regs[1] & DS1337_BIT_OSF) {
  2168				dev_warn(ds1307->dev, "SET TIME!\n");
  2169			}
  2170			break;
  2171	
  2172		case rx_8025:
  2173			err = regmap_bulk_read(ds1307->regmap,
  2174					       RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
  2175			if (err) {
  2176				dev_dbg(ds1307->dev, "read error %d\n", err);
  2177				goto exit;
  2178			}
  2179	
  2180			/* oscillator off?  turn it on, so clock can tick. */
  2181			if (!(regs[1] & RX8025_BIT_XST)) {
  2182				regs[1] |= RX8025_BIT_XST;
  2183				regmap_write(ds1307->regmap,
  2184					     RX8025_REG_CTRL2 << 4 | 0x08,
  2185					     regs[1]);
  2186				dev_warn(ds1307->dev,
  2187					 "oscillator stop detected - SET TIME!\n");
  2188			}
  2189	
  2190			if (regs[1] & RX8025_BIT_PON) {
  2191				regs[1] &= ~RX8025_BIT_PON;
  2192				regmap_write(ds1307->regmap,
  2193					     RX8025_REG_CTRL2 << 4 | 0x08,
  2194					     regs[1]);
  2195				dev_warn(ds1307->dev, "power-on detected\n");
  2196			}
  2197	
  2198			if (regs[1] & RX8025_BIT_VDET) {
  2199				regs[1] &= ~RX8025_BIT_VDET;
  2200				regmap_write(ds1307->regmap,
  2201					     RX8025_REG_CTRL2 << 4 | 0x08,
  2202					     regs[1]);
  2203				dev_warn(ds1307->dev, "voltage drop detected\n");
  2204			}
  2205	
  2206			/* make sure we are running in 24hour mode */
  2207			if (!(regs[0] & RX8025_BIT_2412)) {
  2208				u8 hour;
  2209	
  2210				/* switch to 24 hour mode */
  2211				regmap_write(ds1307->regmap,
  2212					     RX8025_REG_CTRL1 << 4 | 0x08,
  2213					     regs[0] | RX8025_BIT_2412);
  2214	
  2215				err = regmap_bulk_read(ds1307->regmap,
  2216						       RX8025_REG_CTRL1 << 4 | 0x08,
  2217						       regs, 2);
  2218				if (err) {
  2219					dev_dbg(ds1307->dev, "read error %d\n", err);
  2220					goto exit;
  2221				}
  2222	
  2223				/* correct hour */
  2224				hour = bcd2bin(regs[DS1307_REG_HOUR]);
  2225				if (hour == 12)
  2226					hour = 0;
  2227				if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2228					hour += 12;
  2229	
  2230				regmap_write(ds1307->regmap,
  2231					     DS1307_REG_HOUR << 4 | 0x08, hour);
  2232			}
  2233			break;
  2234		case ds_1388:
  2235			err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
  2236			if (err) {
  2237				dev_dbg(ds1307->dev, "read error %d\n", err);
  2238				goto exit;
  2239			}
  2240	
  2241			/* oscillator off?  turn it on, so clock can tick. */
  2242			if (tmp & DS1388_BIT_nEOSC) {
  2243				tmp &= ~DS1388_BIT_nEOSC;
  2244				regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
  2245			}
  2246			break;
  2247		default:
  2248			break;
  2249		}
  2250	
  2251		/* read RTC registers */
  2252		err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
  2253				       sizeof(regs));
  2254		if (err) {
  2255			dev_dbg(ds1307->dev, "read error %d\n", err);
  2256			goto exit;
  2257		}
  2258	
  2259		if (ds1307->type == mcp794xx &&
  2260		    !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
  2261			regmap_write(ds1307->regmap, DS1307_REG_WDAY,
  2262				     regs[DS1307_REG_WDAY] |
  2263				     MCP794XX_BIT_VBATEN);
  2264		}
  2265	
  2266		tmp = regs[DS1307_REG_HOUR];
  2267		switch (ds1307->type) {
  2268		case ds_1340:
  2269		case m41t0:
  2270		case m41t00:
  2271		case m41t11:
  2272			/*
  2273			 * NOTE: ignores century bits; fix before deploying
  2274			 * systems that will run through year 2100.
  2275			 */
  2276			break;
  2277		case rx_8025:
  2278			break;
  2279		default:
  2280			if (!(tmp & DS1307_BIT_12HR))
  2281				break;
  2282	
  2283			/*
  2284			 * Be sure we're in 24 hour mode.  Multi-master systems
  2285			 * take note...
  2286			 */
  2287			tmp = bcd2bin(tmp & 0x1f);
  2288			if (tmp == 12)
  2289				tmp = 0;
  2290			if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2291				tmp += 12;
  2292			regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
  2293				     bin2bcd(tmp));
  2294		}
  2295	
  2296		ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
  2297		if (IS_ERR(ds1307->rtc))
  2298			return PTR_ERR(ds1307->rtc);
  2299	
  2300		if (want_irq || ds1307_can_wakeup_device)
  2301			device_set_wakeup_capable(ds1307->dev, true);
  2302		else
  2303			clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2304	
  2305		if (ds1307_can_wakeup_device && !want_irq) {
  2306			dev_info(ds1307->dev,
  2307				 "'wakeup-source' is set, request for an IRQ is disabled!\n");
  2308			/* We cannot support UIE mode if we do not have an IRQ line */
  2309			clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
  2310		}
  2311	
  2312		if (want_irq) {
  2313			err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
  2314							chip->irq_handler ?: ds1307_irq,
  2315							IRQF_SHARED | IRQF_ONESHOT,
  2316							ds1307->name, ds1307);
  2317			if (err) {
  2318				client->irq = 0;
  2319				device_set_wakeup_capable(ds1307->dev, false);
  2320				clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2321				dev_err(ds1307->dev, "unable to request IRQ!\n");
  2322			} else {
  2323				dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
  2324			}
  2325		}
  2326	
  2327		switch (ds1307->type) {
  2328		case rx_8901:
  2329			set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
  2330			break;
  2331		default:
> 2332		}
  2333	
  2334		ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
  2335		err = ds1307_add_frequency_test(ds1307);
  2336		if (err)
  2337			return err;
  2338	
  2339		err = devm_rtc_register_device(ds1307->rtc);
  2340		if (err)
  2341			return err;
  2342	
  2343		if (chip->nvram_size) {
  2344			struct nvmem_config nvmem_cfg = {
  2345				.name = "ds1307_nvram",
  2346				.word_size = 1,
  2347				.stride = 1,
  2348				.size = chip->nvram_size,
  2349				.reg_read = ds1307_nvram_read,
  2350				.reg_write = ds1307_nvram_write,
  2351				.priv = ds1307,
  2352			};
  2353	
  2354			devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
  2355		}
  2356	
  2357		ds1307_hwmon_register(ds1307);
  2358		ds1307_clks_register(ds1307);
  2359		ds1307_wdt_register(ds1307);
  2360	
  2361		return 0;
  2362	
  2363	exit:
  2364		return err;
  2365	}
  2366	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-29 21:10 UTC (permalink / raw)
  To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
  Cc: llvm, oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
	Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>

Hi Fredrik,

kernel test robot noticed the following build warnings:

[auto build test WARNING on dc59e4fea9d83f03bad6bddf3fa2e52491777482]

url:    https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base:   dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link:    https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20260630/202606300521.DkMaPRKi-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 6cc609bb250b21b47fc7d394b4019101e9983597)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606300521.DkMaPRKi-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606300521.DkMaPRKi-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/rtc/rtc-ds1307.c:2332:2: warning: label at end of compound statement is a C23 extension [-Wc23-extensions]
    2332 |         }
         |         ^
   1 warning generated.


vim +2332 drivers/rtc/rtc-ds1307.c

  2066	
  2067	static int ds1307_probe(struct i2c_client *client)
  2068	{
  2069		const struct i2c_device_id *id = i2c_client_get_device_id(client);
  2070		struct ds1307		*ds1307;
  2071		const void		*match;
  2072		int			err = -ENODEV;
  2073		int			tmp;
  2074		const struct chip_desc	*chip;
  2075		bool			want_irq;
  2076		bool			ds1307_can_wakeup_device = false;
  2077		unsigned char		regs[8];
  2078		struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
  2079		int			trickle_charger_setup = 0;
  2080	
  2081		ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
  2082		if (!ds1307)
  2083			return -ENOMEM;
  2084	
  2085		dev_set_drvdata(&client->dev, ds1307);
  2086		ds1307->dev = &client->dev;
  2087		ds1307->name = client->name;
  2088	
  2089		ds1307->regmap = devm_regmap_init_i2c(client, &regmap_config);
  2090		if (IS_ERR(ds1307->regmap)) {
  2091			dev_err(ds1307->dev, "regmap allocation failed\n");
  2092			return PTR_ERR(ds1307->regmap);
  2093		}
  2094	
  2095		i2c_set_clientdata(client, ds1307);
  2096	
  2097		match = device_get_match_data(&client->dev);
  2098		if (match) {
  2099			ds1307->type = (uintptr_t)match;
  2100			chip = &chips[ds1307->type];
  2101		} else if (id) {
  2102			chip = &chips[id->driver_data];
  2103			ds1307->type = id->driver_data;
  2104		} else {
  2105			return -ENODEV;
  2106		}
  2107	
  2108		want_irq = client->irq > 0 && chip->alarm;
  2109	
  2110		if (!pdata)
  2111			trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
  2112		else if (pdata->trickle_charger_setup)
  2113			trickle_charger_setup = pdata->trickle_charger_setup;
  2114	
  2115		if (trickle_charger_setup < 0)
  2116			return trickle_charger_setup;
  2117	
  2118		if (trickle_charger_setup && chip->trickle_charger_reg) {
  2119			dev_dbg(ds1307->dev,
  2120				"writing trickle charger info 0x%x to 0x%x\n",
  2121				trickle_charger_setup, chip->trickle_charger_reg);
  2122			regmap_write(ds1307->regmap, chip->trickle_charger_reg,
  2123				     (u8)trickle_charger_setup);
  2124		}
  2125	
  2126	/*
  2127	 * For devices with no IRQ directly connected to the SoC, the RTC chip
  2128	 * can be forced as a wakeup source by stating that explicitly in
  2129	 * the device's .dts file using the "wakeup-source" boolean property.
  2130	 * If the "wakeup-source" property is set, don't request an IRQ.
  2131	 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
  2132	 * if supported by the RTC.
  2133	 */
  2134		if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
  2135			ds1307_can_wakeup_device = true;
  2136	
  2137		switch (ds1307->type) {
  2138		case ds_1337:
  2139		case ds_1339:
  2140		case ds_1341:
  2141		case ds_3231:
  2142			/* get registers that the "rtc" read below won't read... */
  2143			err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
  2144					       regs, 2);
  2145			if (err) {
  2146				dev_dbg(ds1307->dev, "read error %d\n", err);
  2147				goto exit;
  2148			}
  2149	
  2150			/* oscillator off?  turn it on, so clock can tick. */
  2151			if (regs[0] & DS1337_BIT_nEOSC)
  2152				regs[0] &= ~DS1337_BIT_nEOSC;
  2153	
  2154			/*
  2155			 * Using IRQ or defined as wakeup-source?
  2156			 * Disable the square wave and both alarms.
  2157			 * For some variants, be sure alarms can trigger when we're
  2158			 * running on Vbackup (BBSQI/BBSQW)
  2159			 */
  2160			if (want_irq || ds1307_can_wakeup_device)
  2161				regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
  2162	
  2163			regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
  2164				     regs[0]);
  2165	
  2166			/* oscillator fault? warn */
  2167			if (regs[1] & DS1337_BIT_OSF) {
  2168				dev_warn(ds1307->dev, "SET TIME!\n");
  2169			}
  2170			break;
  2171	
  2172		case rx_8025:
  2173			err = regmap_bulk_read(ds1307->regmap,
  2174					       RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
  2175			if (err) {
  2176				dev_dbg(ds1307->dev, "read error %d\n", err);
  2177				goto exit;
  2178			}
  2179	
  2180			/* oscillator off?  turn it on, so clock can tick. */
  2181			if (!(regs[1] & RX8025_BIT_XST)) {
  2182				regs[1] |= RX8025_BIT_XST;
  2183				regmap_write(ds1307->regmap,
  2184					     RX8025_REG_CTRL2 << 4 | 0x08,
  2185					     regs[1]);
  2186				dev_warn(ds1307->dev,
  2187					 "oscillator stop detected - SET TIME!\n");
  2188			}
  2189	
  2190			if (regs[1] & RX8025_BIT_PON) {
  2191				regs[1] &= ~RX8025_BIT_PON;
  2192				regmap_write(ds1307->regmap,
  2193					     RX8025_REG_CTRL2 << 4 | 0x08,
  2194					     regs[1]);
  2195				dev_warn(ds1307->dev, "power-on detected\n");
  2196			}
  2197	
  2198			if (regs[1] & RX8025_BIT_VDET) {
  2199				regs[1] &= ~RX8025_BIT_VDET;
  2200				regmap_write(ds1307->regmap,
  2201					     RX8025_REG_CTRL2 << 4 | 0x08,
  2202					     regs[1]);
  2203				dev_warn(ds1307->dev, "voltage drop detected\n");
  2204			}
  2205	
  2206			/* make sure we are running in 24hour mode */
  2207			if (!(regs[0] & RX8025_BIT_2412)) {
  2208				u8 hour;
  2209	
  2210				/* switch to 24 hour mode */
  2211				regmap_write(ds1307->regmap,
  2212					     RX8025_REG_CTRL1 << 4 | 0x08,
  2213					     regs[0] | RX8025_BIT_2412);
  2214	
  2215				err = regmap_bulk_read(ds1307->regmap,
  2216						       RX8025_REG_CTRL1 << 4 | 0x08,
  2217						       regs, 2);
  2218				if (err) {
  2219					dev_dbg(ds1307->dev, "read error %d\n", err);
  2220					goto exit;
  2221				}
  2222	
  2223				/* correct hour */
  2224				hour = bcd2bin(regs[DS1307_REG_HOUR]);
  2225				if (hour == 12)
  2226					hour = 0;
  2227				if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2228					hour += 12;
  2229	
  2230				regmap_write(ds1307->regmap,
  2231					     DS1307_REG_HOUR << 4 | 0x08, hour);
  2232			}
  2233			break;
  2234		case ds_1388:
  2235			err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
  2236			if (err) {
  2237				dev_dbg(ds1307->dev, "read error %d\n", err);
  2238				goto exit;
  2239			}
  2240	
  2241			/* oscillator off?  turn it on, so clock can tick. */
  2242			if (tmp & DS1388_BIT_nEOSC) {
  2243				tmp &= ~DS1388_BIT_nEOSC;
  2244				regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
  2245			}
  2246			break;
  2247		default:
  2248			break;
  2249		}
  2250	
  2251		/* read RTC registers */
  2252		err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
  2253				       sizeof(regs));
  2254		if (err) {
  2255			dev_dbg(ds1307->dev, "read error %d\n", err);
  2256			goto exit;
  2257		}
  2258	
  2259		if (ds1307->type == mcp794xx &&
  2260		    !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
  2261			regmap_write(ds1307->regmap, DS1307_REG_WDAY,
  2262				     regs[DS1307_REG_WDAY] |
  2263				     MCP794XX_BIT_VBATEN);
  2264		}
  2265	
  2266		tmp = regs[DS1307_REG_HOUR];
  2267		switch (ds1307->type) {
  2268		case ds_1340:
  2269		case m41t0:
  2270		case m41t00:
  2271		case m41t11:
  2272			/*
  2273			 * NOTE: ignores century bits; fix before deploying
  2274			 * systems that will run through year 2100.
  2275			 */
  2276			break;
  2277		case rx_8025:
  2278			break;
  2279		default:
  2280			if (!(tmp & DS1307_BIT_12HR))
  2281				break;
  2282	
  2283			/*
  2284			 * Be sure we're in 24 hour mode.  Multi-master systems
  2285			 * take note...
  2286			 */
  2287			tmp = bcd2bin(tmp & 0x1f);
  2288			if (tmp == 12)
  2289				tmp = 0;
  2290			if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2291				tmp += 12;
  2292			regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
  2293				     bin2bcd(tmp));
  2294		}
  2295	
  2296		ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
  2297		if (IS_ERR(ds1307->rtc))
  2298			return PTR_ERR(ds1307->rtc);
  2299	
  2300		if (want_irq || ds1307_can_wakeup_device)
  2301			device_set_wakeup_capable(ds1307->dev, true);
  2302		else
  2303			clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2304	
  2305		if (ds1307_can_wakeup_device && !want_irq) {
  2306			dev_info(ds1307->dev,
  2307				 "'wakeup-source' is set, request for an IRQ is disabled!\n");
  2308			/* We cannot support UIE mode if we do not have an IRQ line */
  2309			clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
  2310		}
  2311	
  2312		if (want_irq) {
  2313			err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
  2314							chip->irq_handler ?: ds1307_irq,
  2315							IRQF_SHARED | IRQF_ONESHOT,
  2316							ds1307->name, ds1307);
  2317			if (err) {
  2318				client->irq = 0;
  2319				device_set_wakeup_capable(ds1307->dev, false);
  2320				clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2321				dev_err(ds1307->dev, "unable to request IRQ!\n");
  2322			} else {
  2323				dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
  2324			}
  2325		}
  2326	
  2327		switch (ds1307->type) {
  2328		case rx_8901:
  2329			set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
  2330			break;
  2331		default:
> 2332		}
  2333	
  2334		ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
  2335		err = ds1307_add_frequency_test(ds1307);
  2336		if (err)
  2337			return err;
  2338	
  2339		err = devm_rtc_register_device(ds1307->rtc);
  2340		if (err)
  2341			return err;
  2342	
  2343		if (chip->nvram_size) {
  2344			struct nvmem_config nvmem_cfg = {
  2345				.name = "ds1307_nvram",
  2346				.word_size = 1,
  2347				.stride = 1,
  2348				.size = chip->nvram_size,
  2349				.reg_read = ds1307_nvram_read,
  2350				.reg_write = ds1307_nvram_write,
  2351				.priv = ds1307,
  2352			};
  2353	
  2354			devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
  2355		}
  2356	
  2357		ds1307_hwmon_register(ds1307);
  2358		ds1307_clks_register(ds1307);
  2359		ds1307_wdt_register(ds1307);
  2360	
  2361		return 0;
  2362	
  2363	exit:
  2364		return err;
  2365	}
  2366	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-29 21:10 UTC (permalink / raw)
  To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
  Cc: oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
	Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>

Hi Fredrik,

kernel test robot noticed the following build errors:

[auto build test ERROR on dc59e4fea9d83f03bad6bddf3fa2e52491777482]

url:    https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base:   dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link:    https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: sparc64-randconfig-002-20260630 (https://download.01.org/0day-ci/archive/20260630/202606300522.9EnurYvY-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606300522.9EnurYvY-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606300522.9EnurYvY-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/rtc/rtc-ds1307.c: In function 'ds1307_probe':
>> drivers/rtc/rtc-ds1307.c:2331:2: error: label at end of compound statement
     default:
     ^~~~~~~


vim +2331 drivers/rtc/rtc-ds1307.c

  2066	
  2067	static int ds1307_probe(struct i2c_client *client)
  2068	{
  2069		const struct i2c_device_id *id = i2c_client_get_device_id(client);
  2070		struct ds1307		*ds1307;
  2071		const void		*match;
  2072		int			err = -ENODEV;
  2073		int			tmp;
  2074		const struct chip_desc	*chip;
  2075		bool			want_irq;
  2076		bool			ds1307_can_wakeup_device = false;
  2077		unsigned char		regs[8];
  2078		struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
  2079		int			trickle_charger_setup = 0;
  2080	
  2081		ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
  2082		if (!ds1307)
  2083			return -ENOMEM;
  2084	
  2085		dev_set_drvdata(&client->dev, ds1307);
  2086		ds1307->dev = &client->dev;
  2087		ds1307->name = client->name;
  2088	
  2089		ds1307->regmap = devm_regmap_init_i2c(client, &regmap_config);
  2090		if (IS_ERR(ds1307->regmap)) {
  2091			dev_err(ds1307->dev, "regmap allocation failed\n");
  2092			return PTR_ERR(ds1307->regmap);
  2093		}
  2094	
  2095		i2c_set_clientdata(client, ds1307);
  2096	
  2097		match = device_get_match_data(&client->dev);
  2098		if (match) {
  2099			ds1307->type = (uintptr_t)match;
  2100			chip = &chips[ds1307->type];
  2101		} else if (id) {
  2102			chip = &chips[id->driver_data];
  2103			ds1307->type = id->driver_data;
  2104		} else {
  2105			return -ENODEV;
  2106		}
  2107	
  2108		want_irq = client->irq > 0 && chip->alarm;
  2109	
  2110		if (!pdata)
  2111			trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
  2112		else if (pdata->trickle_charger_setup)
  2113			trickle_charger_setup = pdata->trickle_charger_setup;
  2114	
  2115		if (trickle_charger_setup < 0)
  2116			return trickle_charger_setup;
  2117	
  2118		if (trickle_charger_setup && chip->trickle_charger_reg) {
  2119			dev_dbg(ds1307->dev,
  2120				"writing trickle charger info 0x%x to 0x%x\n",
  2121				trickle_charger_setup, chip->trickle_charger_reg);
  2122			regmap_write(ds1307->regmap, chip->trickle_charger_reg,
  2123				     (u8)trickle_charger_setup);
  2124		}
  2125	
  2126	/*
  2127	 * For devices with no IRQ directly connected to the SoC, the RTC chip
  2128	 * can be forced as a wakeup source by stating that explicitly in
  2129	 * the device's .dts file using the "wakeup-source" boolean property.
  2130	 * If the "wakeup-source" property is set, don't request an IRQ.
  2131	 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
  2132	 * if supported by the RTC.
  2133	 */
  2134		if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
  2135			ds1307_can_wakeup_device = true;
  2136	
  2137		switch (ds1307->type) {
  2138		case ds_1337:
  2139		case ds_1339:
  2140		case ds_1341:
  2141		case ds_3231:
  2142			/* get registers that the "rtc" read below won't read... */
  2143			err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
  2144					       regs, 2);
  2145			if (err) {
  2146				dev_dbg(ds1307->dev, "read error %d\n", err);
  2147				goto exit;
  2148			}
  2149	
  2150			/* oscillator off?  turn it on, so clock can tick. */
  2151			if (regs[0] & DS1337_BIT_nEOSC)
  2152				regs[0] &= ~DS1337_BIT_nEOSC;
  2153	
  2154			/*
  2155			 * Using IRQ or defined as wakeup-source?
  2156			 * Disable the square wave and both alarms.
  2157			 * For some variants, be sure alarms can trigger when we're
  2158			 * running on Vbackup (BBSQI/BBSQW)
  2159			 */
  2160			if (want_irq || ds1307_can_wakeup_device)
  2161				regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
  2162	
  2163			regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
  2164				     regs[0]);
  2165	
  2166			/* oscillator fault? warn */
  2167			if (regs[1] & DS1337_BIT_OSF) {
  2168				dev_warn(ds1307->dev, "SET TIME!\n");
  2169			}
  2170			break;
  2171	
  2172		case rx_8025:
  2173			err = regmap_bulk_read(ds1307->regmap,
  2174					       RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
  2175			if (err) {
  2176				dev_dbg(ds1307->dev, "read error %d\n", err);
  2177				goto exit;
  2178			}
  2179	
  2180			/* oscillator off?  turn it on, so clock can tick. */
  2181			if (!(regs[1] & RX8025_BIT_XST)) {
  2182				regs[1] |= RX8025_BIT_XST;
  2183				regmap_write(ds1307->regmap,
  2184					     RX8025_REG_CTRL2 << 4 | 0x08,
  2185					     regs[1]);
  2186				dev_warn(ds1307->dev,
  2187					 "oscillator stop detected - SET TIME!\n");
  2188			}
  2189	
  2190			if (regs[1] & RX8025_BIT_PON) {
  2191				regs[1] &= ~RX8025_BIT_PON;
  2192				regmap_write(ds1307->regmap,
  2193					     RX8025_REG_CTRL2 << 4 | 0x08,
  2194					     regs[1]);
  2195				dev_warn(ds1307->dev, "power-on detected\n");
  2196			}
  2197	
  2198			if (regs[1] & RX8025_BIT_VDET) {
  2199				regs[1] &= ~RX8025_BIT_VDET;
  2200				regmap_write(ds1307->regmap,
  2201					     RX8025_REG_CTRL2 << 4 | 0x08,
  2202					     regs[1]);
  2203				dev_warn(ds1307->dev, "voltage drop detected\n");
  2204			}
  2205	
  2206			/* make sure we are running in 24hour mode */
  2207			if (!(regs[0] & RX8025_BIT_2412)) {
  2208				u8 hour;
  2209	
  2210				/* switch to 24 hour mode */
  2211				regmap_write(ds1307->regmap,
  2212					     RX8025_REG_CTRL1 << 4 | 0x08,
  2213					     regs[0] | RX8025_BIT_2412);
  2214	
  2215				err = regmap_bulk_read(ds1307->regmap,
  2216						       RX8025_REG_CTRL1 << 4 | 0x08,
  2217						       regs, 2);
  2218				if (err) {
  2219					dev_dbg(ds1307->dev, "read error %d\n", err);
  2220					goto exit;
  2221				}
  2222	
  2223				/* correct hour */
  2224				hour = bcd2bin(regs[DS1307_REG_HOUR]);
  2225				if (hour == 12)
  2226					hour = 0;
  2227				if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2228					hour += 12;
  2229	
  2230				regmap_write(ds1307->regmap,
  2231					     DS1307_REG_HOUR << 4 | 0x08, hour);
  2232			}
  2233			break;
  2234		case ds_1388:
  2235			err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
  2236			if (err) {
  2237				dev_dbg(ds1307->dev, "read error %d\n", err);
  2238				goto exit;
  2239			}
  2240	
  2241			/* oscillator off?  turn it on, so clock can tick. */
  2242			if (tmp & DS1388_BIT_nEOSC) {
  2243				tmp &= ~DS1388_BIT_nEOSC;
  2244				regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
  2245			}
  2246			break;
  2247		default:
  2248			break;
  2249		}
  2250	
  2251		/* read RTC registers */
  2252		err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
  2253				       sizeof(regs));
  2254		if (err) {
  2255			dev_dbg(ds1307->dev, "read error %d\n", err);
  2256			goto exit;
  2257		}
  2258	
  2259		if (ds1307->type == mcp794xx &&
  2260		    !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
  2261			regmap_write(ds1307->regmap, DS1307_REG_WDAY,
  2262				     regs[DS1307_REG_WDAY] |
  2263				     MCP794XX_BIT_VBATEN);
  2264		}
  2265	
  2266		tmp = regs[DS1307_REG_HOUR];
  2267		switch (ds1307->type) {
  2268		case ds_1340:
  2269		case m41t0:
  2270		case m41t00:
  2271		case m41t11:
  2272			/*
  2273			 * NOTE: ignores century bits; fix before deploying
  2274			 * systems that will run through year 2100.
  2275			 */
  2276			break;
  2277		case rx_8025:
  2278			break;
  2279		default:
  2280			if (!(tmp & DS1307_BIT_12HR))
  2281				break;
  2282	
  2283			/*
  2284			 * Be sure we're in 24 hour mode.  Multi-master systems
  2285			 * take note...
  2286			 */
  2287			tmp = bcd2bin(tmp & 0x1f);
  2288			if (tmp == 12)
  2289				tmp = 0;
  2290			if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2291				tmp += 12;
  2292			regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
  2293				     bin2bcd(tmp));
  2294		}
  2295	
  2296		ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
  2297		if (IS_ERR(ds1307->rtc))
  2298			return PTR_ERR(ds1307->rtc);
  2299	
  2300		if (want_irq || ds1307_can_wakeup_device)
  2301			device_set_wakeup_capable(ds1307->dev, true);
  2302		else
  2303			clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2304	
  2305		if (ds1307_can_wakeup_device && !want_irq) {
  2306			dev_info(ds1307->dev,
  2307				 "'wakeup-source' is set, request for an IRQ is disabled!\n");
  2308			/* We cannot support UIE mode if we do not have an IRQ line */
  2309			clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
  2310		}
  2311	
  2312		if (want_irq) {
  2313			err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
  2314							chip->irq_handler ?: ds1307_irq,
  2315							IRQF_SHARED | IRQF_ONESHOT,
  2316							ds1307->name, ds1307);
  2317			if (err) {
  2318				client->irq = 0;
  2319				device_set_wakeup_capable(ds1307->dev, false);
  2320				clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2321				dev_err(ds1307->dev, "unable to request IRQ!\n");
  2322			} else {
  2323				dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
  2324			}
  2325		}
  2326	
  2327		switch (ds1307->type) {
  2328		case rx_8901:
  2329			set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
  2330			break;
> 2331		default:
  2332		}
  2333	
  2334		ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
  2335		err = ds1307_add_frequency_test(ds1307);
  2336		if (err)
  2337			return err;
  2338	
  2339		err = devm_rtc_register_device(ds1307->rtc);
  2340		if (err)
  2341			return err;
  2342	
  2343		if (chip->nvram_size) {
  2344			struct nvmem_config nvmem_cfg = {
  2345				.name = "ds1307_nvram",
  2346				.word_size = 1,
  2347				.stride = 1,
  2348				.size = chip->nvram_size,
  2349				.reg_read = ds1307_nvram_read,
  2350				.reg_write = ds1307_nvram_write,
  2351				.priv = ds1307,
  2352			};
  2353	
  2354			devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
  2355		}
  2356	
  2357		ds1307_hwmon_register(ds1307);
  2358		ds1307_clks_register(ds1307);
  2359		ds1307_wdt_register(ds1307);
  2360	
  2361		return 0;
  2362	
  2363	exit:
  2364		return err;
  2365	}
  2366	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-29 20:15 UTC (permalink / raw)
  To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
  Cc: llvm, oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
	Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>

Hi Fredrik,

kernel test robot noticed the following build warnings:

[auto build test WARNING on dc59e4fea9d83f03bad6bddf3fa2e52491777482]

url:    https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base:   dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link:    https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: um-randconfig-002-20260630 (https://download.01.org/0day-ci/archive/20260630/202606300447.wDrgfpSn-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606300447.wDrgfpSn-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606300447.wDrgfpSn-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/rtc/rtc-ds1307.c:2332:2: warning: label at end of compound statement is a C2x extension [-Wc2x-extensions]
    2332 |         }
         |         ^
   1 warning generated.


vim +2332 drivers/rtc/rtc-ds1307.c

  2066	
  2067	static int ds1307_probe(struct i2c_client *client)
  2068	{
  2069		const struct i2c_device_id *id = i2c_client_get_device_id(client);
  2070		struct ds1307		*ds1307;
  2071		const void		*match;
  2072		int			err = -ENODEV;
  2073		int			tmp;
  2074		const struct chip_desc	*chip;
  2075		bool			want_irq;
  2076		bool			ds1307_can_wakeup_device = false;
  2077		unsigned char		regs[8];
  2078		struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
  2079		int			trickle_charger_setup = 0;
  2080	
  2081		ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
  2082		if (!ds1307)
  2083			return -ENOMEM;
  2084	
  2085		dev_set_drvdata(&client->dev, ds1307);
  2086		ds1307->dev = &client->dev;
  2087		ds1307->name = client->name;
  2088	
  2089		ds1307->regmap = devm_regmap_init_i2c(client, &regmap_config);
  2090		if (IS_ERR(ds1307->regmap)) {
  2091			dev_err(ds1307->dev, "regmap allocation failed\n");
  2092			return PTR_ERR(ds1307->regmap);
  2093		}
  2094	
  2095		i2c_set_clientdata(client, ds1307);
  2096	
  2097		match = device_get_match_data(&client->dev);
  2098		if (match) {
  2099			ds1307->type = (uintptr_t)match;
  2100			chip = &chips[ds1307->type];
  2101		} else if (id) {
  2102			chip = &chips[id->driver_data];
  2103			ds1307->type = id->driver_data;
  2104		} else {
  2105			return -ENODEV;
  2106		}
  2107	
  2108		want_irq = client->irq > 0 && chip->alarm;
  2109	
  2110		if (!pdata)
  2111			trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
  2112		else if (pdata->trickle_charger_setup)
  2113			trickle_charger_setup = pdata->trickle_charger_setup;
  2114	
  2115		if (trickle_charger_setup < 0)
  2116			return trickle_charger_setup;
  2117	
  2118		if (trickle_charger_setup && chip->trickle_charger_reg) {
  2119			dev_dbg(ds1307->dev,
  2120				"writing trickle charger info 0x%x to 0x%x\n",
  2121				trickle_charger_setup, chip->trickle_charger_reg);
  2122			regmap_write(ds1307->regmap, chip->trickle_charger_reg,
  2123				     (u8)trickle_charger_setup);
  2124		}
  2125	
  2126	/*
  2127	 * For devices with no IRQ directly connected to the SoC, the RTC chip
  2128	 * can be forced as a wakeup source by stating that explicitly in
  2129	 * the device's .dts file using the "wakeup-source" boolean property.
  2130	 * If the "wakeup-source" property is set, don't request an IRQ.
  2131	 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
  2132	 * if supported by the RTC.
  2133	 */
  2134		if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
  2135			ds1307_can_wakeup_device = true;
  2136	
  2137		switch (ds1307->type) {
  2138		case ds_1337:
  2139		case ds_1339:
  2140		case ds_1341:
  2141		case ds_3231:
  2142			/* get registers that the "rtc" read below won't read... */
  2143			err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
  2144					       regs, 2);
  2145			if (err) {
  2146				dev_dbg(ds1307->dev, "read error %d\n", err);
  2147				goto exit;
  2148			}
  2149	
  2150			/* oscillator off?  turn it on, so clock can tick. */
  2151			if (regs[0] & DS1337_BIT_nEOSC)
  2152				regs[0] &= ~DS1337_BIT_nEOSC;
  2153	
  2154			/*
  2155			 * Using IRQ or defined as wakeup-source?
  2156			 * Disable the square wave and both alarms.
  2157			 * For some variants, be sure alarms can trigger when we're
  2158			 * running on Vbackup (BBSQI/BBSQW)
  2159			 */
  2160			if (want_irq || ds1307_can_wakeup_device)
  2161				regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
  2162	
  2163			regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
  2164				     regs[0]);
  2165	
  2166			/* oscillator fault? warn */
  2167			if (regs[1] & DS1337_BIT_OSF) {
  2168				dev_warn(ds1307->dev, "SET TIME!\n");
  2169			}
  2170			break;
  2171	
  2172		case rx_8025:
  2173			err = regmap_bulk_read(ds1307->regmap,
  2174					       RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
  2175			if (err) {
  2176				dev_dbg(ds1307->dev, "read error %d\n", err);
  2177				goto exit;
  2178			}
  2179	
  2180			/* oscillator off?  turn it on, so clock can tick. */
  2181			if (!(regs[1] & RX8025_BIT_XST)) {
  2182				regs[1] |= RX8025_BIT_XST;
  2183				regmap_write(ds1307->regmap,
  2184					     RX8025_REG_CTRL2 << 4 | 0x08,
  2185					     regs[1]);
  2186				dev_warn(ds1307->dev,
  2187					 "oscillator stop detected - SET TIME!\n");
  2188			}
  2189	
  2190			if (regs[1] & RX8025_BIT_PON) {
  2191				regs[1] &= ~RX8025_BIT_PON;
  2192				regmap_write(ds1307->regmap,
  2193					     RX8025_REG_CTRL2 << 4 | 0x08,
  2194					     regs[1]);
  2195				dev_warn(ds1307->dev, "power-on detected\n");
  2196			}
  2197	
  2198			if (regs[1] & RX8025_BIT_VDET) {
  2199				regs[1] &= ~RX8025_BIT_VDET;
  2200				regmap_write(ds1307->regmap,
  2201					     RX8025_REG_CTRL2 << 4 | 0x08,
  2202					     regs[1]);
  2203				dev_warn(ds1307->dev, "voltage drop detected\n");
  2204			}
  2205	
  2206			/* make sure we are running in 24hour mode */
  2207			if (!(regs[0] & RX8025_BIT_2412)) {
  2208				u8 hour;
  2209	
  2210				/* switch to 24 hour mode */
  2211				regmap_write(ds1307->regmap,
  2212					     RX8025_REG_CTRL1 << 4 | 0x08,
  2213					     regs[0] | RX8025_BIT_2412);
  2214	
  2215				err = regmap_bulk_read(ds1307->regmap,
  2216						       RX8025_REG_CTRL1 << 4 | 0x08,
  2217						       regs, 2);
  2218				if (err) {
  2219					dev_dbg(ds1307->dev, "read error %d\n", err);
  2220					goto exit;
  2221				}
  2222	
  2223				/* correct hour */
  2224				hour = bcd2bin(regs[DS1307_REG_HOUR]);
  2225				if (hour == 12)
  2226					hour = 0;
  2227				if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2228					hour += 12;
  2229	
  2230				regmap_write(ds1307->regmap,
  2231					     DS1307_REG_HOUR << 4 | 0x08, hour);
  2232			}
  2233			break;
  2234		case ds_1388:
  2235			err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
  2236			if (err) {
  2237				dev_dbg(ds1307->dev, "read error %d\n", err);
  2238				goto exit;
  2239			}
  2240	
  2241			/* oscillator off?  turn it on, so clock can tick. */
  2242			if (tmp & DS1388_BIT_nEOSC) {
  2243				tmp &= ~DS1388_BIT_nEOSC;
  2244				regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
  2245			}
  2246			break;
  2247		default:
  2248			break;
  2249		}
  2250	
  2251		/* read RTC registers */
  2252		err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
  2253				       sizeof(regs));
  2254		if (err) {
  2255			dev_dbg(ds1307->dev, "read error %d\n", err);
  2256			goto exit;
  2257		}
  2258	
  2259		if (ds1307->type == mcp794xx &&
  2260		    !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
  2261			regmap_write(ds1307->regmap, DS1307_REG_WDAY,
  2262				     regs[DS1307_REG_WDAY] |
  2263				     MCP794XX_BIT_VBATEN);
  2264		}
  2265	
  2266		tmp = regs[DS1307_REG_HOUR];
  2267		switch (ds1307->type) {
  2268		case ds_1340:
  2269		case m41t0:
  2270		case m41t00:
  2271		case m41t11:
  2272			/*
  2273			 * NOTE: ignores century bits; fix before deploying
  2274			 * systems that will run through year 2100.
  2275			 */
  2276			break;
  2277		case rx_8025:
  2278			break;
  2279		default:
  2280			if (!(tmp & DS1307_BIT_12HR))
  2281				break;
  2282	
  2283			/*
  2284			 * Be sure we're in 24 hour mode.  Multi-master systems
  2285			 * take note...
  2286			 */
  2287			tmp = bcd2bin(tmp & 0x1f);
  2288			if (tmp == 12)
  2289				tmp = 0;
  2290			if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  2291				tmp += 12;
  2292			regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
  2293				     bin2bcd(tmp));
  2294		}
  2295	
  2296		ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
  2297		if (IS_ERR(ds1307->rtc))
  2298			return PTR_ERR(ds1307->rtc);
  2299	
  2300		if (want_irq || ds1307_can_wakeup_device)
  2301			device_set_wakeup_capable(ds1307->dev, true);
  2302		else
  2303			clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2304	
  2305		if (ds1307_can_wakeup_device && !want_irq) {
  2306			dev_info(ds1307->dev,
  2307				 "'wakeup-source' is set, request for an IRQ is disabled!\n");
  2308			/* We cannot support UIE mode if we do not have an IRQ line */
  2309			clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
  2310		}
  2311	
  2312		if (want_irq) {
  2313			err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
  2314							chip->irq_handler ?: ds1307_irq,
  2315							IRQF_SHARED | IRQF_ONESHOT,
  2316							ds1307->name, ds1307);
  2317			if (err) {
  2318				client->irq = 0;
  2319				device_set_wakeup_capable(ds1307->dev, false);
  2320				clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
  2321				dev_err(ds1307->dev, "unable to request IRQ!\n");
  2322			} else {
  2323				dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
  2324			}
  2325		}
  2326	
  2327		switch (ds1307->type) {
  2328		case rx_8901:
  2329			set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
  2330			break;
  2331		default:
> 2332		}
  2333	
  2334		ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
  2335		err = ds1307_add_frequency_test(ds1307);
  2336		if (err)
  2337			return err;
  2338	
  2339		err = devm_rtc_register_device(ds1307->rtc);
  2340		if (err)
  2341			return err;
  2342	
  2343		if (chip->nvram_size) {
  2344			struct nvmem_config nvmem_cfg = {
  2345				.name = "ds1307_nvram",
  2346				.word_size = 1,
  2347				.stride = 1,
  2348				.size = chip->nvram_size,
  2349				.reg_read = ds1307_nvram_read,
  2350				.reg_write = ds1307_nvram_write,
  2351				.priv = ds1307,
  2352			};
  2353	
  2354			devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
  2355		}
  2356	
  2357		ds1307_hwmon_register(ds1307);
  2358		ds1307_clks_register(ds1307);
  2359		ds1307_wdt_register(ds1307);
  2360	
  2361		return 0;
  2362	
  2363	exit:
  2364		return err;
  2365	}
  2366	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v2 2/6] clk: sunxi-ng: sun6i-rtc: clean up DT usage
From: Chen-Yu Tsai @ 2026-06-29 15:37 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jernej Skrabec, Samuel Holland, Michael Turquette,
	Stephen Boyd, Maxime Ripard, linux-rtc, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk
In-Reply-To: <20260629-a733-rtc-v2-2-7b72112784f8@baylibre.com>

On Mon, Jun 29, 2026 at 8:42 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> With sun6i-rtc compatible devices, the "ext-osc32k" clock input
> is optional for the devices that support this input (r329 and onward).
>
> Probably preparing for older SoC support, the driver does something funny
> when parsing DT. It check if "ext-osc32k" is present in the clock-names and
> if it is not, it uses the first clock as "ext-osc32k". This clock will
> actually be the rtc bus clock so what the driver does is wrong.
>
> At the moment, the driver does not support the older SoCs that would have
> an external 32k clock provided on index #0 so just remove this quirk.
>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>

^ permalink raw reply

* Re: [PATCH v2 3/6] clk: sunxi-ng: sun6i-rtc: Add feature bit for IOSC calibration
From: Chen-Yu Tsai @ 2026-06-29 15:25 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jernej Skrabec, Samuel Holland, Michael Turquette,
	Stephen Boyd, Maxime Ripard, linux-rtc, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk
In-Reply-To: <20260629-a733-rtc-v2-3-7b72112784f8@baylibre.com>

On Mon, Jun 29, 2026 at 8:42 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> From: Junhui Liu <junhui.liu@pigmoral.tech>
>
> The sun6i-rtc CCU driver currently uses a global static variable to
> denote whether calibration is supported, which makes IOSC operations
> tightly coupled to this file.
>
> Convert this into a feature bit to decouple the logic. This allows the
> IOSC clock code to be moved into a shared module for reuse by other SoCs.
>
> Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
> Signed-off-by: Jerome Brunet<jbrunet@baylibre.com>

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>

^ permalink raw reply

* [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: Fredrik M Olsson @ 2026-06-29 15:13 UTC (permalink / raw)
  To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Nobuhiro Iwamatsu
  Cc: linux-rtc, devicetree, linux-kernel, kernel, Fredrik M Olsson

Adds support for:
- Reading and writing time to/from the RTC.
- Changing Backup Switch Mode (BSM) to DISABLED/DIRECT/LEVEL using the
  RTC_PARAM_SET ioctl.
- Optionally enabling battery charging.
- Reading the battery voltage low status using the RTC_VL_READ ioctl
  (only supported in LEVEL BSM), which also reports invalid time
  information if the VLF flag is set.

Signed-off-by: Fredrik M Olsson <fredrik.m.olsson@axis.com>
---
Add basic support for the Epson RX8901CE RTC.
Datasheet: https://download.epsondevice.com/td/pdf/app/RX8901CE_en.pdf

Also includes a bug fix for an issue with reading the weekday from the
RTC which affects both the existing rx8130 and this rx8901 driver.
---
Changes in v3:
- Clear CHGEN when trickle battery charging is disabled.
- Link to v2: https://lore.kernel.org/r/20260520-ds1307-rx8901-add-v2-0-e069ea32e1db@axis.com

Changes in v2:
- Squashed the Voltage Low status patch into the driver patch
- Switch from dev_err to dev_dbg
- Implement Backup Switch Mode (BSM) ioctl instead of hard coding
  switching mode.
- Change the prototype for the do_trickle_setup function pointer in
  order to make it possible to propagate error codes from the added
  PWSW_CFG register read operation. This read operation is added so not
  to override previously set register fields.
- Link to v1: https://lore.kernel.org/r/20251219-ds1307-rx8901-add-v1-0-b13f346ebe93@axis.com
---
 drivers/rtc/rtc-ds1307.c | 218 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 209 insertions(+), 9 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 0707ded5368b..488fd1d8d8e3 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/bcd.h>
+#include <linux/bitfield.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/kstrtox.h>
@@ -48,6 +49,7 @@ enum ds_type {
 	mcp794xx,
 	rx_8025,
 	rx_8130,
+	rx_8901,
 	last_ds_type /* always last */
 	/* rs5c372 too?  different address... */
 };
@@ -129,6 +131,18 @@ enum ds_type {
 #define RX8130_REG_CONTROL1_INIEN	BIT(4)
 #define RX8130_REG_CONTROL1_CHGEN	BIT(5)
 
+#define RX8901_REG_INTF			0x0e
+#define RX8901_REG_INTF_VLF		BIT(1)
+#define RX8901_REG_PWSW_CFG		0x37
+#define RX8901_REG_PWSW_CFG_SWSEL	GENMASK(3, 2)
+#define RX8901_REG_PWSW_CFG_VBATLDETEN	BIT(4)
+#define RX8901_REG_PWSW_CFG_INIEN	BIT(6)
+#define RX8901_REG_PWSW_CFG_CHGEN	BIT(7)
+#define RX8901_REG_BUF_INTF		0x46
+#define RX8901_REG_BUF_INTF_VBATLF	BIT(3)
+#define RX8901_SWSEL_PRIMARY_BACKUP	0x1
+#define RX8901_SWSEL_PRIMARY		0x2
+
 #define MCP794XX_REG_CONTROL		0x07
 #	define MCP794XX_BIT_ALM0_EN	0x10
 #	define MCP794XX_BIT_ALM1_EN	0x20
@@ -192,8 +206,8 @@ struct chip_desc {
 	irq_handler_t		irq_handler;
 	const struct rtc_class_ops *rtc_ops;
 	u16			trickle_charger_reg;
-	u8			(*do_trickle_setup)(struct ds1307 *, u32,
-						    bool);
+	int			(*do_trickle_setup)(struct ds1307 *ds1307, u32 ohms,
+						    bool diode);
 	/* Does the RTC require trickle-resistor-ohms to select the value of
 	 * the resistor between Vcc and Vbackup?
 	 */
@@ -216,6 +230,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 
 	if (ds1307->type == rx_8130) {
 		unsigned int regflag;
+
 		ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, &regflag);
 		if (ret) {
 			dev_err(dev, "%s error %d\n", "read", ret);
@@ -226,6 +241,19 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 			dev_warn_once(dev, "oscillator failed, set time!\n");
 			return -EINVAL;
 		}
+	} else if (ds1307->type == rx_8901) {
+		unsigned int regflag;
+
+		ret = regmap_read(ds1307->regmap, RX8901_REG_INTF, &regflag);
+		if (ret) {
+			dev_dbg(dev, "%s error %d\n", "read", ret);
+			return ret;
+		}
+
+		if (regflag & RX8901_REG_INTF_VLF) {
+			dev_warn_once(dev, "oscillator failed, set time!\n");
+			return -EINVAL;
+		}
 	}
 
 	/* read the RTC date and time registers all at once */
@@ -310,7 +338,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 	tmp = regs[DS1307_REG_HOUR] & 0x3f;
 	t->tm_hour = bcd2bin(tmp);
 	/* rx8130 is bit position, not BCD */
-	if (ds1307->type == rx_8130)
+	if (ds1307->type == rx_8130 || ds1307->type == rx_8901)
 		t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f) - 1;
 	else
 		t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
@@ -361,7 +389,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
 	regs[DS1307_REG_MIN] = bin2bcd(t->tm_min);
 	regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
 	/* rx8130 is bit position, not BCD */
-	if (ds1307->type == rx_8130)
+	if (ds1307->type == rx_8130 || ds1307->type == rx_8901)
 		regs[DS1307_REG_WDAY] = 1 << t->tm_wday;
 	else
 		regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
@@ -428,11 +456,132 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
 			dev_err(dev, "%s error %d\n", "write", result);
 			return result;
 		}
+	} else if (ds1307->type == rx_8901) {
+		/*
+		 * clear Voltage Loss Flag as data is available now (writing 1
+		 * to the other bits in the INTF register has no effect)
+		 */
+		result = regmap_write(ds1307->regmap, RX8901_REG_INTF,
+				      0xff ^ RX8901_REG_INTF_VLF);
+		if (result) {
+			dev_dbg(dev, "%s error %d\n", "write", result);
+			return result;
+		}
 	}
 
 	return 0;
 }
 
+#ifdef CONFIG_RTC_INTF_DEV
+static int rx8901_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	unsigned int regflag, tmp = 0;
+	int ret = 0;
+
+	switch (cmd) {
+	case RTC_VL_READ:
+		ret = regmap_read(ds1307->regmap, RX8901_REG_INTF, &regflag);
+		if (ret)
+			return ret;
+
+		if (regflag & RX8901_REG_INTF_VLF)
+			tmp |= RTC_VL_DATA_INVALID;
+
+		ret = regmap_read(ds1307->regmap, RX8901_REG_BUF_INTF, &regflag);
+		if (ret)
+			return ret;
+
+		if (regflag & RX8901_REG_BUF_INTF_VBATLF)
+			tmp |= RTC_VL_BACKUP_LOW;
+
+		return put_user(tmp, (unsigned int __user *)arg);
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static int rx8901_param_get(struct device *dev, struct rtc_param *param)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	unsigned int regflag;
+	int ret;
+
+	switch (param->param) {
+	case RTC_PARAM_BACKUP_SWITCH_MODE:
+		ret = regmap_read(ds1307->regmap, RX8901_REG_PWSW_CFG, &regflag);
+		if (ret)
+			return ret;
+
+		if (regflag & RX8901_REG_PWSW_CFG_INIEN) {
+			param->uvalue = RTC_BSM_LEVEL;
+		} else {
+			unsigned int swsel = FIELD_GET(RX8901_REG_PWSW_CFG_SWSEL, regflag);
+
+			if (swsel == RX8901_SWSEL_PRIMARY_BACKUP)
+				param->uvalue = RTC_BSM_DIRECT;
+			else
+				param->uvalue = RTC_BSM_DISABLED;
+		}
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return ret;
+}
+
+static int rx8901_param_set(struct device *dev, struct rtc_param *param)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	unsigned int regmask;
+	unsigned int regval;
+	int ret;
+
+	switch (param->param) {
+	case RTC_PARAM_BACKUP_SWITCH_MODE:
+
+		switch (param->uvalue) {
+		case RTC_BSM_DISABLED:
+			/* Only main power supply is used */
+			regmask = RX8901_REG_PWSW_CFG_INIEN |
+				  RX8901_REG_PWSW_CFG_SWSEL;
+			regval = FIELD_PREP(RX8901_REG_PWSW_CFG_SWSEL,
+					    RX8901_SWSEL_PRIMARY) |
+				 FIELD_PREP(RX8901_REG_PWSW_CFG_INIEN, 0);
+			break;
+		case RTC_BSM_DIRECT:
+			/* Main and battery power supply is put in parallel (default) */
+			regmask = RX8901_REG_PWSW_CFG_INIEN |
+				  RX8901_REG_PWSW_CFG_SWSEL;
+			regval = FIELD_PREP(RX8901_REG_PWSW_CFG_SWSEL,
+					    RX8901_SWSEL_PRIMARY_BACKUP) |
+				 FIELD_PREP(RX8901_REG_PWSW_CFG_INIEN, 0);
+			break;
+		case RTC_BSM_LEVEL:
+			/* Enable auto power switching between main and backup power supply */
+			regmask = RX8901_REG_PWSW_CFG_INIEN;
+			regval = FIELD_PREP(RX8901_REG_PWSW_CFG_INIEN, 1);
+			break;
+		default:
+			return -EINVAL;
+		}
+		ret = regmap_update_bits(ds1307->regmap, RX8901_REG_PWSW_CFG, regmask, regval);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+#else
+#define rx8901_ioctl NULL
+#define rx8901_param_get NULL
+#define rx8901_param_set NULL
+#endif
+
 static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
 {
 	struct ds1307		*ds1307 = dev_get_drvdata(dev);
@@ -539,7 +688,7 @@ static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)
 				  enabled ? DS1337_BIT_A1IE : 0);
 }
 
-static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
+static int do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
 {
 	u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
 		DS1307_TRICKLE_CHARGER_NO_DIODE;
@@ -564,7 +713,7 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
 	return setup;
 }
 
-static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
+static int do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
 {
 	/* make sure that the backup battery is enabled */
 	u8 setup = RX8130_REG_CONTROL1_INIEN;
@@ -574,6 +723,28 @@ static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
 	return setup;
 }
 
+static int do_trickle_setup_rx8901(struct ds1307 *ds1307, u32 ohms __always_unused, bool diode)
+{
+	int ret;
+	unsigned int setup;
+
+	ret = regmap_read(ds1307->regmap, RX8901_REG_PWSW_CFG, &setup);
+	if (ret) {
+		dev_err(ds1307->dev, "Failed to read PWSW_CFG register\n");
+		return ret;
+	}
+
+	/* Enable low battery voltage detection */
+	setup |= RX8901_REG_PWSW_CFG_VBATLDETEN;
+
+	if (diode)
+		setup |= RX8901_REG_PWSW_CFG_CHGEN;
+	else
+		setup &= ~RX8901_REG_PWSW_CFG_CHGEN;
+
+	return setup;
+}
+
 static irqreturn_t rx8130_irq(int irq, void *dev_id)
 {
 	struct ds1307           *ds1307 = dev_id;
@@ -966,6 +1137,14 @@ static const struct rtc_class_ops rx8130_rtc_ops = {
 	.alarm_irq_enable = rx8130_alarm_irq_enable,
 };
 
+static const struct rtc_class_ops rx8901_rtc_ops = {
+	.read_time      = ds1307_get_time,
+	.set_time       = ds1307_set_time,
+	.ioctl          = rx8901_ioctl,
+	.param_get      = rx8901_param_get,
+	.param_set      = rx8901_param_set,
+};
+
 static const struct rtc_class_ops mcp794xx_rtc_ops = {
 	.read_time      = ds1307_get_time,
 	.set_time       = ds1307_set_time,
@@ -1046,6 +1225,12 @@ static const struct chip_desc chips[last_ds_type] = {
 		.trickle_charger_reg = RX8130_REG_CONTROL1,
 		.do_trickle_setup = &do_trickle_setup_rx8130,
 	},
+	[rx_8901] = {
+		.offset		= 0x0,
+		.rtc_ops = &rx8901_rtc_ops,
+		.trickle_charger_reg = RX8901_REG_PWSW_CFG,
+		.do_trickle_setup = &do_trickle_setup_rx8901,
+	},
 	[m41t0] = {
 		.rtc_ops	= &m41txx_rtc_ops,
 	},
@@ -1087,6 +1272,7 @@ static const struct i2c_device_id ds1307_id[] = {
 	{ .name = "rx8025", .driver_data = rx_8025 },
 	{ .name = "isl12057", .driver_data = ds_1337 },
 	{ .name = "rx8130", .driver_data = rx_8130 },
+	{ .name = "rx8901", .driver_data = rx_8901 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ds1307_id);
@@ -1164,6 +1350,10 @@ static const struct of_device_id ds1307_of_match[] = {
 		.compatible = "epson,rx8130",
 		.data = (void *)rx_8130
 	},
+	{
+		.compatible = "epson,rx8901",
+		.data = (void *)rx_8901
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ds1307_of_match);
@@ -1298,7 +1488,7 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
 
 /*----------------------------------------------------------------------*/
 
-static u8 ds1307_trickle_init(struct ds1307 *ds1307,
+static int ds1307_trickle_init(struct ds1307 *ds1307,
 			      const struct chip_desc *chip)
 {
 	u32 ohms, chargeable;
@@ -1886,7 +2076,7 @@ static int ds1307_probe(struct i2c_client *client)
 	bool			ds1307_can_wakeup_device = false;
 	unsigned char		regs[8];
 	struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
-	u8			trickle_charger_setup = 0;
+	int			trickle_charger_setup = 0;
 
 	ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
 	if (!ds1307)
@@ -1922,12 +2112,15 @@ static int ds1307_probe(struct i2c_client *client)
 	else if (pdata->trickle_charger_setup)
 		trickle_charger_setup = pdata->trickle_charger_setup;
 
+	if (trickle_charger_setup < 0)
+		return trickle_charger_setup;
+
 	if (trickle_charger_setup && chip->trickle_charger_reg) {
 		dev_dbg(ds1307->dev,
 			"writing trickle charger info 0x%x to 0x%x\n",
 			trickle_charger_setup, chip->trickle_charger_reg);
 		regmap_write(ds1307->regmap, chip->trickle_charger_reg,
-			     trickle_charger_setup);
+			     (u8)trickle_charger_setup);
 	}
 
 /*
@@ -2131,6 +2324,13 @@ static int ds1307_probe(struct i2c_client *client)
 		}
 	}
 
+	switch (ds1307->type) {
+	case rx_8901:
+		set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
+		break;
+	default:
+	}
+
 	ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
 	err = ds1307_add_frequency_test(ds1307);
 	if (err)

---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20251126-ds1307-rx8901-add-a0fe173093e3

Best regards,
-- 
Fredrik M Olsson <fredrik.m.olsson@axis.com>


^ permalink raw reply related

* Re: [PATCH v2 3/3] rtc: ds1307: Add driver for Epson RX8901CE
From: Fredrik M Olsson @ 2026-06-29 15:07 UTC (permalink / raw)
  To: Alexandre Belloni, Fredrik M Olsson
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu,
	linux-rtc, devicetree, linux-kernel, kernel
In-Reply-To: <20260624213847b0e6c315@mail.local>

On 6/24/26 23:38, Alexandre Belloni wrote:
> [Some people who received this message don't often get email from alexandre.belloni@bootlin.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> 
> On 20/05/2026 16:48:55+0200, Fredrik M Olsson wrote:
>> +static int do_trickle_setup_rx8901(struct ds1307 *ds1307, u32 ohms __always_unused, bool diode)
>> +{
>> +     int ret;
>> +     unsigned int setup;
>> +
>> +     ret = regmap_read(ds1307->regmap, RX8901_REG_PWSW_CFG, &setup);
>> +     if (ret) {
>> +             dev_err(ds1307->dev, "Failed to read PWSW_CFG register\n");
>> +             return ret;
>> +     }
>> +
>> +     /* Enable low battery voltage detection */
>> +     setup |= RX8901_REG_PWSW_CFG_VBATLDETEN;
>> +
>> +     if (diode)
>> +             setup |= RX8901_REG_PWSW_CFG_CHGEN;
> 
> When diode is false, you need to explicitly clear
> RX8901_REG_PWSW_CFG_CHGEN so it is possible to actually disable trickle
> charging once it has been enabled has the register is battery backed.

Okay thanks I will update that in v3.


-- 
/Fredrik

^ permalink raw reply

* [PATCH v2 6/6] clk: sunxi-ng: sun6i-rtc: add a733 support
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>

Add support for the sun60i a733 CCU RTC.

Compared to the a523, this SoC has a different input oscillator divider
which auto-detects the oscillator rate and select a divider to provide
a fixed 32768Hz clock. It also provides several phy reference clocks
with dedicated clock gates.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 74 ++++++++++++++++++++++++++++++++++--
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.h |  2 +-
 2 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 25dd87e78eb7..2ec09e346472 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -42,11 +42,16 @@
 #define LOSC_OUT_GATING_REG		0x60
 
 #define DCXO_CTRL_REG			0x160
+#define DCXO_CTRL_DCXO_EN		BIT(1)
 #define DCXO_CTRL_CLK16M_RC_EN		BIT(0)
 
+#define DCXO_GATING_REG			0x16c
+
 struct sun6i_rtc_match_data {
 	bool				have_ext_osc32k		: 1;
 	bool				have_iosc_calibration	: 1;
+	bool				have_dcxo_status	: 1;
+	bool				have_phy_ref_gates	: 1;
 	bool				rtc_32k_single_parent	: 1;
 	const struct clk_parent_data	*osc32k_fanout_parents;
 	u8				osc32k_fanout_nparents;
@@ -213,7 +218,12 @@ static struct ccu_mux osc32k_clk = {
 	},
 };
 
-/* This falls back to the global name for fwnodes without a named reference. */
+/*
+ * This falls back to the global name for fwnodes without a named reference.
+ * NOTE: osc24M name might be misleading the oscillator could also be a 26MHz
+ * or a 19.2MHz one starting with the a733. The original name is kept anyway
+ * in case anything is relying on it.
+ */
 static const struct clk_parent_data osc24M[] = {
 	{ .fw_name = "hosc", .name = "osc24M" }
 };
@@ -227,8 +237,28 @@ static struct clk_fixed_factor osc24M_32k_div_clk = {
 					    0),
 };
 
-static SUNXI_CCU_GATE_HW(osc24M_32k_clk, "osc24M-32k", &osc24M_32k_div_clk.hw,
-			 LOSC_OUT_GATING_REG, BIT(16), 0);
+static struct clk_div_table osc24M_32k_div_a733_table[] = {
+	{ .val = 0, .div = 732 },
+	{ .val = 1, .div = 586 },
+	{ .val = 2, .div = 793 },
+	{ .val = 3, .div = 732 },
+	{ /* Sentinel */ },
+};
+
+static struct ccu_div osc24M_32k_div_a733_clk = {
+	.enable = BIT(1),
+	.div	= _SUNXI_CCU_DIV_TABLE(14, 2, osc24M_32k_div_a733_table),
+	.common	= {
+		.reg		= DCXO_CTRL_REG,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("osc24M-32k-div",
+							   osc24M,
+							   &ccu_rodiv_ops,
+							   0),
+	},
+};
+
+static SUNXI_CCU_GATE(osc24M_32k_clk, "osc24M-32k", "osc24M-32k-div",
+		      LOSC_OUT_GATING_REG, BIT(16), 0);
 
 static const struct clk_hw *rtc_32k_parents[] = {
 	&osc32k_clk.common.hw,
@@ -267,6 +297,15 @@ static struct ccu_mux osc32k_fanout_clk = {
 	},
 };
 
+static SUNXI_CCU_GATE_FW(hosc_serdes1_clk, "hosc-serdes1", "hosc",
+		      DCXO_GATING_REG, BIT(5), 0);
+static SUNXI_CCU_GATE_FW(hosc_serdes0_clk, "hosc-serdes0", "hosc",
+		      DCXO_GATING_REG, BIT(4), 0);
+static SUNXI_CCU_GATE_FW(hosc_hdmi_clk, "hosc-hdmi", "hosc",
+		      DCXO_GATING_REG, BIT(1), 0);
+static SUNXI_CCU_GATE_FW(hosc_ufs_clk, "hosc-ufs", "hosc",
+		      DCXO_GATING_REG, BIT(0), 0);
+
 static struct ccu_common *sun6i_rtc_ccu_clks[] = {
 	&iosc_clk,
 	&iosc_32k_clk,
@@ -275,6 +314,11 @@ static struct ccu_common *sun6i_rtc_ccu_clks[] = {
 	&osc24M_32k_clk.common,
 	&rtc_32k_clk.common,
 	&osc32k_fanout_clk.common,
+	&osc24M_32k_div_a733_clk.common,
+	&hosc_serdes1_clk.common,
+	&hosc_serdes0_clk.common,
+	&hosc_hdmi_clk.common,
+	&hosc_ufs_clk.common,
 };
 
 static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
@@ -288,6 +332,10 @@ static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
 		[CLK_OSC24M_32K]	= &osc24M_32k_clk.common.hw,
 		[CLK_RTC_32K]		= &rtc_32k_clk.common.hw,
 		[CLK_OSC24M_32K_DIV]	= &osc24M_32k_div_clk.hw,
+		[CLK_HOSC_UFS]		= &hosc_ufs_clk.common.hw,
+		[CLK_HOSC_HDMI]		= &hosc_hdmi_clk.common.hw,
+		[CLK_HOSC_SERDES0]	= &hosc_serdes0_clk.common.hw,
+		[CLK_HOSC_SERDES1]	= &hosc_serdes1_clk.common.hw,
 	},
 };
 
@@ -330,6 +378,15 @@ static const struct sun6i_rtc_match_data sun55i_a523_rtc_ccu_data = {
 	.osc32k_fanout_nparents	= ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
 };
 
+static const struct sun6i_rtc_match_data sun60i_a733_rtc_ccu_data = {
+	.have_ext_osc32k	= true,
+	.have_iosc_calibration	= true,
+	.have_dcxo_status	= true,
+	.have_phy_ref_gates	= true,
+	.osc32k_fanout_parents	= sun50i_r329_osc32k_fanout_parents,
+	.osc32k_fanout_nparents	= ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
+};
+
 static const struct of_device_id sun6i_rtc_ccu_match[] = {
 	{
 		.compatible	= "allwinner,sun50i-h616-rtc",
@@ -343,6 +400,10 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = {
 		.compatible	= "allwinner,sun55i-a523-rtc",
 		.data		= &sun55i_a523_rtc_ccu_data,
 	},
+	{
+		.compatible	= "allwinner,sun60i-a733-rtc",
+		.data		= &sun60i_a733_rtc_ccu_data,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match);
@@ -375,6 +436,13 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 	osc32k_fanout_init_data.parent_data = data->osc32k_fanout_parents;
 	osc32k_fanout_init_data.num_parents = data->osc32k_fanout_nparents;
 
+	if (data->have_dcxo_status)
+		sun6i_rtc_ccu_hw_clks.hws[CLK_OSC24M_32K_DIV] =
+			&osc24M_32k_div_a733_clk.common.hw;
+
+	if (!data->have_phy_ref_gates)
+		sun6i_rtc_ccu_hw_clks.num = CLK_OSC24M_32K_DIV + 1;
+
 	return devm_sunxi_ccu_probe(dev, reg, &sun6i_rtc_ccu_desc);
 }
 
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
index ab7b92b47f59..4f4f4cb00f1d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
@@ -11,6 +11,6 @@
 #define CLK_RTC_32K		6
 #define CLK_OSC24M_32K_DIV	7
 
-#define CLK_NUMBER		(CLK_OSC24M_32K_DIV + 1)
+#define CLK_NUMBER		(CLK_HOSC_SERDES1 + 1)
 
 #endif /* _CCU_SUN6I_RTC_H */

-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 5/6] clk: sunxi-ng: sun6i-rtc: split main oscillator div and gate.
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>

On the a733 the "osc24M-32k" clock has the same gate bits as the previously
supported SoC but a different divider implementation.

Instead of a fixed 750 divider, the divider is selected based on the
rate of the oscillator. It can be seen as a simple read-only divider.

To easily replace the divider part depending the SoC, split the divider
and gate into two separate clock entities.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 20 +++++++++++---------
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.h |  3 ++-
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index b24c8b196e66..25dd87e78eb7 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -218,17 +218,18 @@ static const struct clk_parent_data osc24M[] = {
 	{ .fw_name = "hosc", .name = "osc24M" }
 };
 
-static struct ccu_gate osc24M_32k_clk = {
-	.enable	= BIT(16),
-	.common	= {
-		.reg		= LOSC_OUT_GATING_REG,
-		.prediv		= 750,
-		.features	= CCU_FEATURE_ALL_PREDIV,
-		.hw.init	= CLK_HW_INIT_PARENTS_DATA("osc24M-32k", osc24M,
-							   &ccu_gate_ops, 0),
-	},
+static struct clk_fixed_factor osc24M_32k_div_clk = {
+	.mult = 1,
+	.div = 750,
+	.hw.init = CLK_HW_INIT_PARENTS_DATA("osc24M-32k-div",
+					    osc24M,
+					    &clk_fixed_factor_ops,
+					    0),
 };
 
+static SUNXI_CCU_GATE_HW(osc24M_32k_clk, "osc24M-32k", &osc24M_32k_div_clk.hw,
+			 LOSC_OUT_GATING_REG, BIT(16), 0);
+
 static const struct clk_hw *rtc_32k_parents[] = {
 	&osc32k_clk.common.hw,
 	&osc24M_32k_clk.common.hw
@@ -286,6 +287,7 @@ static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
 		[CLK_EXT_OSC32K_GATE]	= &ext_osc32k_gate_clk.common.hw,
 		[CLK_OSC24M_32K]	= &osc24M_32k_clk.common.hw,
 		[CLK_RTC_32K]		= &rtc_32k_clk.common.hw,
+		[CLK_OSC24M_32K_DIV]	= &osc24M_32k_div_clk.hw,
 	},
 };
 
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
index 9ae821fc2599..ab7b92b47f59 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
@@ -9,7 +9,8 @@
 #define CLK_EXT_OSC32K_GATE	4
 #define CLK_OSC24M_32K		5
 #define CLK_RTC_32K		6
+#define CLK_OSC24M_32K_DIV	7
 
-#define CLK_NUMBER		(CLK_RTC_32K + 1)
+#define CLK_NUMBER		(CLK_OSC24M_32K_DIV + 1)
 
 #endif /* _CCU_SUN6I_RTC_H */

-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 4/6] clk: sunxi-ng: div: add read-only operation support
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>

Add support for sunxi-ng read-only dividers. This will be
useful to the a733 oscillator detection logic.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu_div.c | 11 +++++++++++
 drivers/clk/sunxi-ng/ccu_div.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 62d680ccb524..0e3d9e6e30fb 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -143,3 +143,14 @@ const struct clk_ops ccu_div_ops = {
 	.set_rate	= ccu_div_set_rate,
 };
 EXPORT_SYMBOL_NS_GPL(ccu_div_ops, "SUNXI_CCU");
+
+const struct clk_ops ccu_rodiv_ops = {
+	.disable	= ccu_div_disable,
+	.enable		= ccu_div_enable,
+	.is_enabled	= ccu_div_is_enabled,
+
+	.get_parent	= ccu_div_get_parent,
+
+	.recalc_rate	= ccu_div_recalc_rate,
+};
+EXPORT_SYMBOL_NS_GPL(ccu_rodiv_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index be00b3277e97..a30a92780a05 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -300,5 +300,6 @@ static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
 }
 
 extern const struct clk_ops ccu_div_ops;
+extern const struct clk_ops ccu_rodiv_ops;
 
 #endif /* _CCU_DIV_H_ */

-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 3/6] clk: sunxi-ng: sun6i-rtc: Add feature bit for IOSC calibration
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>

From: Junhui Liu <junhui.liu@pigmoral.tech>

The sun6i-rtc CCU driver currently uses a global static variable to
denote whether calibration is supported, which makes IOSC operations
tightly coupled to this file.

Convert this into a feature bit to decouple the logic. This allows the
IOSC clock code to be moved into a shared module for reuse by other SoCs.

Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
Signed-off-by: Jerome Brunet<jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 17 +++++++++--------
 drivers/clk/sunxi-ng/ccu_common.h    |  1 +
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 0f528bfaed00..b24c8b196e66 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -52,8 +52,6 @@ struct sun6i_rtc_match_data {
 	u8				osc32k_fanout_nparents;
 };
 
-static bool have_iosc_calibration;
-
 static int ccu_iosc_enable(struct clk_hw *hw)
 {
 	struct ccu_common *cm = hw_to_ccu_common(hw);
@@ -80,7 +78,7 @@ static unsigned long ccu_iosc_recalc_rate(struct clk_hw *hw,
 {
 	struct ccu_common *cm = hw_to_ccu_common(hw);
 
-	if (have_iosc_calibration) {
+	if (cm->features & CCU_FEATURE_IOSC_CALIBRATION) {
 		u32 reg = readl(cm->base + IOSC_CLK_CALI_REG);
 
 		/*
@@ -119,7 +117,7 @@ static int ccu_iosc_32k_prepare(struct clk_hw *hw)
 	struct ccu_common *cm = hw_to_ccu_common(hw);
 	u32 val;
 
-	if (!have_iosc_calibration)
+	if (!(cm->features & CCU_FEATURE_IOSC_CALIBRATION))
 		return 0;
 
 	val = readl(cm->base + IOSC_CLK_CALI_REG);
@@ -134,7 +132,7 @@ static void ccu_iosc_32k_unprepare(struct clk_hw *hw)
 	struct ccu_common *cm = hw_to_ccu_common(hw);
 	u32 val;
 
-	if (!have_iosc_calibration)
+	if (!(cm->features & CCU_FEATURE_IOSC_CALIBRATION))
 		return;
 
 	val = readl(cm->base + IOSC_CLK_CALI_REG);
@@ -148,7 +146,7 @@ static unsigned long ccu_iosc_32k_recalc_rate(struct clk_hw *hw,
 	struct ccu_common *cm = hw_to_ccu_common(hw);
 	u32 val;
 
-	if (have_iosc_calibration) {
+	if (cm->features & CCU_FEATURE_IOSC_CALIBRATION) {
 		val = readl(cm->base + IOSC_CLK_CALI_REG);
 
 		/* Assume the calibrated 32k clock is accurate. */
@@ -167,7 +165,7 @@ static unsigned long ccu_iosc_32k_recalc_accuracy(struct clk_hw *hw,
 	struct ccu_common *cm = hw_to_ccu_common(hw);
 	u32 val;
 
-	if (have_iosc_calibration) {
+	if (cm->features & CCU_FEATURE_IOSC_CALIBRATION) {
 		val = readl(cm->base + IOSC_CLK_CALI_REG);
 
 		/* Assume the calibrated 32k clock is accurate. */
@@ -358,7 +356,10 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 		return 0;
 
 	data = match->data;
-	have_iosc_calibration = data->have_iosc_calibration;
+	if (data->have_iosc_calibration) {
+		iosc_clk.features |= CCU_FEATURE_IOSC_CALIBRATION;
+		iosc_32k_clk.features |= CCU_FEATURE_IOSC_CALIBRATION;
+	}
 
 	if (!data->have_ext_osc32k) {
 		/* ext-osc32k-gate is an orphan, so do not register it. */
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index bbec283b9d99..d9dc24ad5503 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -21,6 +21,7 @@
 #define CCU_FEATURE_CLOSEST_RATE	BIT(9)
 #define CCU_FEATURE_DUAL_DIV		BIT(10)
 #define CCU_FEATURE_UPDATE_BIT		BIT(11)
+#define CCU_FEATURE_IOSC_CALIBRATION	BIT(12)
 
 /* MMC timing mode switch bit */
 #define CCU_MMC_NEW_TIMING_MODE		BIT(30)

-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 2/6] clk: sunxi-ng: sun6i-rtc: clean up DT usage
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>

With sun6i-rtc compatible devices, the "ext-osc32k" clock input
is optional for the devices that support this input (r329 and onward).

Probably preparing for older SoC support, the driver does something funny
when parsing DT. It check if "ext-osc32k" is present in the clock-names and
if it is not, it uses the first clock as "ext-osc32k". This clock will
actually be the rtc bus clock so what the driver does is wrong.

At the moment, the driver does not support the older SoCs that would have
an external 32k clock provided on index #0 so just remove this quirk.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 23 +++--------------------
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index f6bfeba009e8..0f528bfaed00 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -191,10 +191,8 @@ static struct ccu_common iosc_32k_clk = {
 					 CLK_GET_RATE_NOCACHE),
 };
 
-static const struct clk_hw *ext_osc32k[] = { NULL }; /* updated during probe */
-
-static SUNXI_CCU_GATE_HWS(ext_osc32k_gate_clk, "ext-osc32k-gate",
-			  ext_osc32k, 0x0, BIT(4), 0);
+static SUNXI_CCU_GATE_FW(ext_osc32k_gate_clk, "ext-osc32k-gate",
+			  "ext-osc32k", 0x0, BIT(4), 0);
 
 static const struct clk_hw *osc32k_parents[] = {
 	&iosc_32k_clk.hw,
@@ -352,7 +350,6 @@ MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match);
 int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 {
 	const struct sun6i_rtc_match_data *data;
-	struct clk *ext_osc32k_clk = NULL;
 	const struct of_device_id *match;
 
 	/* This driver is only used for newer variants of the hardware. */
@@ -363,21 +360,7 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 	data = match->data;
 	have_iosc_calibration = data->have_iosc_calibration;
 
-	if (data->have_ext_osc32k) {
-		const char *fw_name;
-
-		/* ext-osc32k was the only input clock in the old binding. */
-		fw_name = of_property_present(dev->of_node, "clock-names")
-			? "ext-osc32k" : NULL;
-		ext_osc32k_clk = devm_clk_get_optional(dev, fw_name);
-		if (IS_ERR(ext_osc32k_clk))
-			return PTR_ERR(ext_osc32k_clk);
-	}
-
-	if (ext_osc32k_clk) {
-		/* Link ext-osc32k-gate to its parent. */
-		*ext_osc32k = __clk_get_hw(ext_osc32k_clk);
-	} else {
+	if (!data->have_ext_osc32k) {
 		/* ext-osc32k-gate is an orphan, so do not register it. */
 		sun6i_rtc_ccu_hw_clks.hws[CLK_EXT_OSC32K_GATE] = NULL;
 		osc32k_init_data.num_parents = 1;

-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 1/6] dt-bindings: rtc: sun6i: add sun60i-a733 support
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>

Add a new rtc compatible for the sun60i-a733 SoC and new IDs for the
peripheral oscillator clock gates of this SoC.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 1 +
 include/dt-bindings/clock/sun6i-rtc.h                              | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index 9df5cdb6f63f..197a6f67b180 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -33,6 +33,7 @@ properties:
           - enum:
               - allwinner,sun20i-d1-rtc
               - allwinner,sun55i-a523-rtc
+              - allwinner,sun60i-a733-rtc
           - const: allwinner,sun50i-r329-rtc
 
   reg:
diff --git a/include/dt-bindings/clock/sun6i-rtc.h b/include/dt-bindings/clock/sun6i-rtc.h
index 3bd3aa3d57ce..5132a393ca4b 100644
--- a/include/dt-bindings/clock/sun6i-rtc.h
+++ b/include/dt-bindings/clock/sun6i-rtc.h
@@ -6,5 +6,9 @@
 #define CLK_OSC32K		0
 #define CLK_OSC32K_FANOUT	1
 #define CLK_IOSC		2
+#define CLK_HOSC_UFS		8
+#define CLK_HOSC_HDMI		9
+#define CLK_HOSC_SERDES0	10
+#define CLK_HOSC_SERDES1	11
 
 #endif /* _DT_BINDINGS_CLK_SUN6I_RTC_H_ */

-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 0/6] clk: sun6i-rtc: Add support for Allwinner A733 SoC
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet

Add support for the Allwinner A733 RTC and its internal Clock Control
Unit (CCU). Reuse the rtc-sun6i rtc driver while introducing a new
SoC-specific RTC CCU driver to handle the hardware's evolved clock
structure.

The A733 implementation supports hardware detection of three external
crystal frequencies (19.2MHz, 24MHz and 26MHz), which is represented in
the driver via read-only divider operations. Implement logic to derive a
normalized 32kHz reference from these DCXO sources using fixed
pre-dividers. Additionally, provide several new DCXO gate clocks for
peripherals, including SerDes, HDMI, and UFS.

This was tested on a Raxda Cubie A7A.

Changes in v2:
* Changed DT bindings as suggested. Those have changed significantly
  since v1 so I did not pick up Rob's review trailer
* Support added in the existing RTC CCU driver rather than a separate driver
* Added DT parsing clean up of the existing driver
* Xtal detection exposed by RO divider rather than a MUX.
* Dropped conversion to aux device for now. This is not strictly related
  the a733 support and will submitted again later on.
* Link to v1: https://lore.kernel.org/r/20260121-a733-rtc-v1-0-d359437f23a7@pigmoral.tech

---
Jerome Brunet (5):
      dt-bindings: rtc: sun6i: add sun60i-a733 support
      clk: sunxi-ng: sun6i-rtc: clean up DT usage
      clk: sunxi-ng: div: add read-only operation support
      clk: sunxi-ng: sun6i-rtc: split main oscillator div and gate.
      clk: sunxi-ng: sun6i-rtc: add a733 support

Junhui Liu (1):
      clk: sunxi-ng: sun6i-rtc: Add feature bit for IOSC calibration

 .../bindings/rtc/allwinner,sun6i-a31-rtc.yaml      |   1 +
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c               | 124 +++++++++++++++------
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.h               |   3 +-
 drivers/clk/sunxi-ng/ccu_common.h                  |   1 +
 drivers/clk/sunxi-ng/ccu_div.c                     |  11 ++
 drivers/clk/sunxi-ng/ccu_div.h                     |   1 +
 include/dt-bindings/clock/sun6i-rtc.h              |   4 +
 7 files changed, 109 insertions(+), 36 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20251226-a733-rtc-c5167df14e6e

Best regards,
--  
Jerome


^ permalink raw reply

* RE: [EXTERNAL] Re: [PATCH] drivers: rtc: handle OTF clock changes
From: Elad Nachman @ 2026-06-28 17:34 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: linux-rtc@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260624153123af6b28e3@mail.local>

Hi Alexandre,

> 
> 
> From: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Sent: Wednesday, June 24, 2026 6:31 PM
> To: Elad Nachman <enachman@marvell.com>
> Cc: linux-rtc@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [EXTERNAL] Re: [PATCH] drivers: rtc: handle OTF clock changes
> 
> > From: Elad Nachman <mailto:enachman@marvell.com>
> >
> > When processing expired RTC events and rearming them, use now
> > instead of expiry to prevent endless loops.
> > Issue seen with Armada 385 SOC.
> 
> The loop is not endless, it may be long however. How do you reproduce

48 seconds are long enough to trigger RCU related watchdog which eventually causes NOS reboot...

> this? Or maybe the question is what is enabling PIE on your system?

Not only PIE but also UIE enablement leads to this behavior.
UIE is enabled by Chrony, and that is activated by SONIC NOS.
SONIC NOS was introduced a time modification test (forward/backward)
which triggers this issue, causing the following kernel soft lockup:

[  409.188746] rcu: blocking rcu_node structures (internal RCU debug):
[  436.242391] watchdog: BUG: soft lockup - CPU#1 stuck for 48s! [kworker/1:3:432]
[  436.250173] Kernel panic - not syncing: softlockup: hung tasks
[  436.256032] CPU: 1 PID: 432 Comm: kworker/1:3 Tainted: G           O L     6.1.0-29-2-armmp
[  436.272194] Workqueue: events rtc_timer_do_work
[  436.377383]  __irq_svc from _raw_spin_unlock_irqrestore+0x24/0x28
[  436.383510]  _raw_spin_unlock_irqrestore from __wake_up_common_lock+0x8c/0xc0
[  436.390685]  __wake_up_common_lock from __wake_up+0x20/0x28
[  436.396286]  __wake_up from rtc_handle_legacy_irq+0x58/0x6c
[  436.401890]  rtc_handle_legacy_irq from rtc_timer_do_work+0xe0/0x37c
[  436.408275]  rtc_timer_do_work from process_one_work+0x1f8/0x4b4
[  436.414317]  process_one_work from worker_thread+0x54/0x50c
[  436.419924]  worker_thread from kthread+0xd8/0xf4

> 
> Your patch breaks existing code because it will expect to get one event
> per elapsed period while your patch will cause events to be skipped.

I realize that, but the alternative of having soft lockup followed by reboot is worse in my opinion...

If you have any better idea, I am more than open to suggestions...

> 
> >
> > Fixes commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events")
> > Signed-off-by: Elad Nachman <mailto:enachman@marvell.com>
> > ---
> >  drivers/rtc/interface.c | 14 +++++++++++++-
> >  1 file changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
> > index 96626f8068f9..c32ef95a07d4 100644
> > --- a/drivers/rtc/interface.c
> > +++ b/drivers/rtc/interface.c
> > @@ -126,6 +126,7 @@ EXPORT_SYMBOL_GPL(rtc_read_time);
> >  int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
> >  {
> >  	int err, uie;
> > +	struct rtc_time new_tm;
> >
> >  	err = rtc_valid_tm(tm);
> >  	if (err != 0)
> > @@ -159,6 +160,17 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
> >  	else
> >  		err = -EINVAL;
> >
> > +	if (rtc && rtc->ops && rtc->ops->read_time) {
> > +		if (!rtc->ops->read_time(rtc->dev.parent, &new_tm)) {
> > +			pr_debug("new rtc time secs %d mins %d hours %d mday %d mon %d year %d way %d yday %d dst %d\n",
> > +					new_tm.tm_sec, new_tm.tm_min,
> > +					new_tm.tm_hour, new_tm.tm_mday,
> > +					new_tm.tm_mon, new_tm.tm_year,
> > +					new_tm.tm_wday, new_tm.tm_yday,
> > +					new_tm.tm_isdst);
> > +		}
> > +	}
> > +
> 
> 
> This is unrelated to the patch.

I can remove this easily once we find a solution to the main issue above...

> 
> >  	pm_stay_awake(rtc->dev.parent);
> >  	mutex_unlock(&rtc->ops_lock);
> >  	/* A timer might have just expired */
> > @@ -999,7 +1011,7 @@ void rtc_timer_do_work(struct work_struct *work)
> >  		trace_rtc_timer_fired(timer);
> >  		/* Re-add/fwd periodic timers */
> >  		if (ktime_to_ns(timer->period)) {
> > -			timer->node.expires = ktime_add(timer->node.expires,
> > +			timer->node.expires = ktime_add(now,
> >  							timer->period);
> >  			timer->enabled = 1;
> >  			timerqueue_add(&rtc->timerqueue, &timer->node);
> > --
> > 2.25.1
> >
> 
> --
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://urldefense.proofpoint.com/v2/url?u=https-3A__bootlin.com&d=DwIBAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=eTeNTLEK5-TxXczjOcKPhANIFtlB9pP4lq9qhdlFrwQ&m=6PDPbjuCmjWGjRiUxkS5sPKd4lHU_NypV7pVhoFdBcLnksTSMiVrFYs7blEViGJR&s=IQM9cBpCUzoV4ONJnQs4yjzbjygO7zRYDW1jpJL3zWM&e=

Thanks,

Elad.

^ permalink raw reply

* Re: [PATCH v1] rtc: m41t80: clean up watchdog on probe failure
From: 최유호 @ 2026-06-28 15:41 UTC (permalink / raw)
  To: Alexandre Mergnat; +Cc: Alexandre Belloni, linux-rtc, linux-kernel
In-Reply-To: <178252038524.1704966.578320083174571195.b4-review@b4>

On Fri, 26 Jun 2026 at 20:33, Alexandre Mergnat <amergnat@baylibre.com> wrote:
> IMHO the right fix is to move the watchdog to the watchdog core.
>
> The leak comes from the watchdog being built on three non-devres
> save_client. A probe failure strands all three, after which the watchdog
> dereferences freed driver state (wdt_ping() reads
> i2c_get_clientdata(save_client), i.e. the devres-freed m41t80_data).
>
> Built on the watchdog core (CONFIG_WATCHDOG_CORE), none of that
> machinery is needed:
>
> - devm_watchdog_register_device() unregisters automatically on any probe
>   failure and on unbind.
> - watchdog_stop_on_reboot() replaces the reboot notifier.
> - watchdog_set/get_drvdata() replaces the global save_client, closing
>   the use-after-free surface itself.
> - m41t80_remove() does nothing but watchdog teardown today, so it goes
>   away too.
>
> This is exactly what was done for the sibling driver rtc-ds1374, which
> carried the same legacy pattern: d3de4beb14a8 ("rtc: ds1374: wdt: Use
> watchdog core for watchdog part"), net -135 lines, adding "select
> WATCHDOG_CORE" in Kconfig. It is a usable template.
>
> primitives: a misc device, a reboot notifier, and the global

Thanks for the detailed suggestion, Alexandre.

Moving to the watchdog core sounds like a better approach. I will
rework this based on the rtc-ds1374 example and send v2.

Thanks,
Yuho

^ permalink raw reply

* Re: [PATCH v2 1/2] rtc: m5441x: add MCF5441x on-chip RTC driver
From: Alexandre Belloni @ 2026-06-28 12:40 UTC (permalink / raw)
  To: Jean-Michel Hautbois
  Cc: Greg Ungerer, Geert Uytterhoeven, linux-kernel, linux-rtc,
	linux-m68k
In-Reply-To: <20260607-jmh-upstream-coldfire-rtc-v2-1-948d2b1ed146@yoseli.org>

Hello,

On 07/06/2026 11:00:40+0200, Jean-Michel Hautbois wrote:
> +static int m5441x_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct m5441x_rtc *p = dev_get_drvdata(dev);
> +	u16 yearmon, days, hourmin, seconds;
> +	unsigned int tries = 3;
> +	unsigned long flags;
> +	int ret;
> +
> +	/*
> +	 * Without a running oscillator the counters are frozen; refuse the
> +	 * read rather than hand userspace a stale time that hwclock --hctosys
> +	 * would propagate into the system clock.
> +	 */
> +	if (p->osc_dead)
> +		return -ENODATA;

While not ideal, the current standard is to return -EINVAL in this case.

> +
> +static int m5441x_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct m5441x_rtc *p = dev_get_drvdata(dev);
> +	s8 yoff = (tm->tm_year + 1900) - M5441X_RTC_YEAR_BASE;
> +	unsigned int tries = 3;
> +	unsigned long flags;
> +	int ret;
> +
> +	/* A frozen oscillator would never latch the new time; reject it. */
> +	if (p->osc_dead)
> +		return -ENODATA;

set_time is a good location to actually restart the oscillator instead
of failing.


> +
> +	/*
> +	 * Writes are nullified while INVAL is asserted. wait_valid() clears
> +	 * the path before the burst, but the knock plus four writes can cross
> +	 * a second boundary on a slow RTC bus, silently dropping fields.
> +	 * Re-check INVAL afterwards and rewrite on observed re-entry.
> +	 */
> +	spin_lock_irqsave(&p->lock, flags);
> +	do {
> +		ret = m5441x_rtc_wait_valid(p);
> +		if (ret)
> +			break;
> +		m5441x_rtc_unlock(p);
> +		rtc_wr(p, M5441X_RTC_YEARMON,
> +		       ((u16)((u8)yoff) << 8) | ((tm->tm_mon + 1) & 0xff));
> +		rtc_wr(p, M5441X_RTC_DAYS,
> +		       ((tm->tm_wday & 0x7) << 8) | (tm->tm_mday & 0x1f));
> +		rtc_wr(p, M5441X_RTC_HOURMIN,
> +		       ((tm->tm_hour & 0x1f) << 8) | (tm->tm_min & 0x3f));
> +		rtc_wr(p, M5441X_RTC_SECONDS, tm->tm_sec & 0x3f);
> +		/* No boundary crossed mid-burst -> the writes all took. */
> +		if (!(rtc_rd(p, M5441X_RTC_SR) & M5441X_RTC_SR_INVAL))
> +			break;
> +		ret = -EAGAIN;
> +	} while (--tries);
> +	spin_unlock_irqrestore(&p->lock, flags);
> +
> +	return ret;
> +}
> +
> +



> +static int m5441x_rtc_probe(struct platform_device *pdev)
> +{
> +	struct nvmem_config nvmem_cfg = {
> +		.name		= "m5441x_rtc_sram",
> +		.type		= NVMEM_TYPE_BATTERY_BACKED,
> +		.word_size	= 1,
> +		.stride		= 1,
> +		.size		= M5441X_RTC_SRAM_SIZE,
> +		.reg_read	= m5441x_rtc_nvram_read,
> +		.reg_write	= m5441x_rtc_nvram_write,
> +	};
> +	struct m5441x_rtc *p;
> +	unsigned long flags;
> +	bool osc_dead = false;
> +	int irq, ret;
> +	u16 cr, cfg;
> +
> +	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
> +	if (!p)
> +		return -ENOMEM;
> +	spin_lock_init(&p->lock);
> +
> +	p->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(p->base))
> +		return PTR_ERR(p->base);
> +
> +	platform_set_drvdata(pdev, p);
> +
> +	/* Enable the oscillator if needed and mask/clear stale interrupts. */
> +	spin_lock_irqsave(&p->lock, flags);
> +	m5441x_rtc_unlock(p);
> +	/*
> +	 * Force binary, DST-free time/date encoding. The driver does not
> +	 * handle the BCD format, and Linux expects the RTC to keep monotonic
> +	 * time with local-time/DST conversion done in userspace, so clear
> +	 * BCDEN and DSTEN in case a bootloader or prior OS left them set. Also
> +	 * default the alarm match field to a full one-shot match: the reset
> +	 * value (AM=00) is a daily hh:mm:ss match, which would fire on the
> +	 * wrong day if userspace enables the alarm via RTC_AIE_ON without
> +	 * first programming it through set_alarm().
> +	 */
> +	cr = rtc_rd(p, M5441X_RTC_CR);
> +	cr &= ~(M5441X_RTC_CR_BCDEN | M5441X_RTC_CR_DSTEN | M5441X_RTC_CR_AM_MASK);
> +	cr |= M5441X_RTC_CR_AM_FULL;
> +	m5441x_rtc_write_cr(p, cr);

You must not enable the oscillator in probe as then you lose the
important information of whether the RTC has ever been set. Also,
forcefully setting DST here may destroy the existing date/time, don't do
this unless you know what is the current time (i.e. in set_time)

> +
> +	/*
> +	 * The alarm registers are battery-backed and survive a power cycle,
> +	 * so a previously armed match could re-fire before set_alarm() runs.
> +	 * Clear them now (the write window is open).
> +	 */
> +	rtc_wr(p, M5441X_RTC_ALM_YRMON, 0);
> +	rtc_wr(p, M5441X_RTC_ALM_DAYS, 0);
> +	rtc_wr(p, M5441X_RTC_ALM_HM, 0);
> +	rtc_wr(p, M5441X_RTC_ALM_SEC, 0);

Why wouldn't you want an existing alarm to fire? The registers are
battery backed exactly for this purpose.

> +
> +	/*
> +	 * Enable the 32kHz oscillator that drives the time counters. This only
> +	 * checks that the OSCEN enable bit latches: when it reads back clear
> +	 * the oscillator block rejected the enable, which in practice means no
> +	 * RTC crystal is fitted and the counters will never advance. It cannot
> +	 * tell a dead crystal from one still starting up, so it is a best-
> +	 * effort hint, not a liveness guarantee. Warn but keep probing, since
> +	 * the battery-backed standby RAM stays usable without the oscillator.
> +	 */
> +	cfg = rtc_rd(p, M5441X_RTC_CFG_DATA);
> +	if (!(cfg & M5441X_RTC_CFG_OSCEN)) {
> +		rtc_wr(p, M5441X_RTC_CFG_DATA, cfg | M5441X_RTC_CFG_OSCEN);
> +		if (!(rtc_rd(p, M5441X_RTC_CFG_DATA) & M5441X_RTC_CFG_OSCEN))
> +			osc_dead = true;
> +	}
> +
> +	/* Mask every source but keep the reserved bit 0 set as required. */
> +	rtc_wr(p, M5441X_RTC_IER, M5441X_RTC_IER_RSVD);
> +	rtc_wr(p, M5441X_RTC_ISR, rtc_rd(p, M5441X_RTC_ISR));

An existing alarm needs to be kept enabled.

> +	spin_unlock_irqrestore(&p->lock, flags);

I'm pretty sure locking here is useless until you register the interrupt.

> +
> +	/*
> +	 * Keep the device (and its standby-RAM nvmem) usable, but record the
> +	 * dead oscillator so read_time/set_time refuse to expose a clock that
> +	 * cannot tick.
> +	 */
> +	p->osc_dead = osc_dead;
> +	if (osc_dead)
> +		dev_warn(&pdev->dev,
> +			 "RTC oscillator enable did not latch; timekeeping unavailable (no 32kHz crystal?)\n");
> +
> +	p->rtc = devm_rtc_allocate_device(&pdev->dev);
> +	if (IS_ERR(p->rtc))
> +		return PTR_ERR(p->rtc);
> +
> +	p->rtc->ops = &m5441x_rtc_ops;
> +	p->rtc->range_min = mktime64(1984, 1, 1, 0, 0, 0);
> +	p->rtc->range_max = mktime64(2239, 12, 31, 23, 59, 59);
> +
> +	irq = platform_get_irq_optional(pdev, 0);
> +	if (irq > 0) {
> +		ret = devm_request_irq(&pdev->dev, irq, m5441x_rtc_irq, 0,
> +				       dev_name(&pdev->dev), p);

If this interrupt can be threaded, the spinlock becomes useless as long
as you lock the RTC with rtc_lock/rtc_unlock in the interrupt handler.

> +		if (ret) {
> +			dev_err(&pdev->dev,
> +				"failed to request IRQ %d: %d, alarm disabled\n",
> +				irq, ret);
> +			clear_bit(RTC_FEATURE_ALARM, p->rtc->features);
> +		} else {
> +			/*
> +			 * The alarm comparator runs on standby power, so let it
> +			 * wake a suspended system. The PM core keeps the IRQ
> +			 * enabled across suspend once it is the device's wake
> +			 * IRQ; both are device-managed.
> +			 */
> +			devm_device_init_wakeup(&pdev->dev);
> +			devm_pm_set_wake_irq(&pdev->dev, irq);
> +		}
> +	} else {
> +		clear_bit(RTC_FEATURE_ALARM, p->rtc->features);
> +	}
> +
> +	/*
> +	 * Register the RTC device before the nvmem provider:
> +	 * devm_rtc_nvmem_register() copies rtc->owner into the nvmem config,
> +	 * and that field is only assigned by devm_rtc_register_device().
> +	 * Registering nvmem first would leave its owner NULL and fail to pin
> +	 * this module while standby-RAM consumers hold references.
> +	 */
> +	ret = devm_rtc_register_device(p->rtc);
> +	if (ret)
> +		return ret;
> +
> +	nvmem_cfg.priv = p;
> +	ret = devm_rtc_nvmem_register(p->rtc, &nvmem_cfg);
> +	if (ret)
> +		dev_warn(&pdev->dev, "standby RAM nvmem unavailable: %d\n", ret);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver m5441x_rtc_driver = {
> +	.driver = {
> +		.name = "rtc-m5441x",
> +	},
> +	.probe = m5441x_rtc_probe,
> +};
> +module_platform_driver(m5441x_rtc_driver);
> +
> +MODULE_DESCRIPTION("Freescale MCF5441x on-chip RTC driver");
> +MODULE_AUTHOR("Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:rtc-m5441x");
> 
> -- 
> 2.39.5
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* Re: [GIT PULL] RTC for 7.2
From: pr-tracker-bot @ 2026-06-27 21:13 UTC (permalink / raw)
  To: Alexandre Belloni; +Cc: Linus Torvalds, linux-rtc, linux-kernel
In-Reply-To: <20260626220226c3609b27@mail.local>

The pull request you sent on Sat, 27 Jun 2026 00:02:26 +0200:

> git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-7.2

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/da7ca04e331e3e83f661e29c30d381a91e6ca245

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html

^ permalink raw reply

* Re: [PATCH v1] rtc: m41t80: clean up watchdog on probe failure
From: Alexandre Mergnat @ 2026-06-27  0:33 UTC (permalink / raw)
  To: Yuho Choi; +Cc: Alexandre Belloni, linux-rtc, linux-kernel
In-Reply-To: <20260601194615.1979101-1-dbgh9129@gmail.com>

On Mon, 01 Jun 2026 15:46:15 -0400, Yuho Choi <dbgh9129@gmail.com> wrote:
> diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
> index b26afef37d9c..f4a30320c6ed 100644
> --- a/drivers/rtc/rtc-m41t80.c
> +++ b/drivers/rtc/rtc-m41t80.c
> @@ -1009,9 +1009,17 @@ static int m41t80_probe(struct i2c_client *client)
>  
>  	rc = devm_rtc_register_device(m41t80_data->rtc);
>  	if (rc)
> -		return rc;
> +		goto err_wdt;

IMHO the right fix is to move the watchdog to the watchdog core.

The leak comes from the watchdog being built on three non-devres
save_client. A probe failure strands all three, after which the watchdog
dereferences freed driver state (wdt_ping() reads
i2c_get_clientdata(save_client), i.e. the devres-freed m41t80_data).

Built on the watchdog core (CONFIG_WATCHDOG_CORE), none of that
machinery is needed:

- devm_watchdog_register_device() unregisters automatically on any probe
  failure and on unbind.
- watchdog_stop_on_reboot() replaces the reboot notifier.
- watchdog_set/get_drvdata() replaces the global save_client, closing
  the use-after-free surface itself.
- m41t80_remove() does nothing but watchdog teardown today, so it goes
  away too.

This is exactly what was done for the sibling driver rtc-ds1374, which
carried the same legacy pattern: d3de4beb14a8 ("rtc: ds1374: wdt: Use
watchdog core for watchdog part"), net -135 lines, adding "select
WATCHDOG_CORE" in Kconfig. It is a usable template.

primitives: a misc device, a reboot notifier, and the global

primitives: a misc device, a reboot notifier, and the global

-- 
Alexandre Mergnat <amergnat@baylibre.com>

^ permalink raw reply

* [GIT PULL] RTC for 7.2
From: Alexandre Belloni @ 2026-06-26 22:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-rtc, linux-kernel

Hello Linus,

Here is the RTC subsystem pull request for 7.2. Most of the work and
improvements are for features of the m41t93. The ds1307 also gets
support for OSF for new variants. The pcap driver is being removed as
the Motorola EZX support was removed a while ago.

The following changes since commit 254f49634ee16a731174d2ae34bc50bd5f45e731:

  Linux 7.1-rc1 (2026-04-26 14:19:00 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-7.2

for you to fetch changes up to 3c8f28578a0d68bc7fb91d881b832d55f734270c:

  rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON (2026-06-25 14:44:39 +0200)

----------------------------------------------------------------
RTC for 7.2

Subsystem:
 - add rtc_read_next_alarm() to read next expiring timer

Drivers:
 - ds1307: handle OSF for ds1337/ds1339/ds3231, add clock provider for ds1307,
   fix wday for rx8130
 - m41t93: DT support, alarm, clock provider, watchdog support
 - mv: add suspend/resume support for wakeup
 - pcap: remove driver
 - renesas-rtca3: many fixes

----------------------------------------------------------------
Adriana Stancu (1):
      rtc: bq32000: add delay between RTC reads

Akhilesh Patil (7):
      rtc: ds1307: add support for clock provider in ds1307
      dt-bindings: rtc: Add ST m41t93
      rtc: m41t93: add device tree support
      rtc: m41t93: migrate to regmap api for register access
      rtc: m41t93: Add alarm support
      rtc: m41t93: Add square wave clock provider support
      rtc: m41t93: Add watchdog support

Alexandre Belloni (1):
      rtc: s35390a: fix typo in comment

Antoni Pokusinski (1):
      rtc: abx80x: fix the RTC_VL_CLR clearing all status flags

Arnd Bergmann (1):
      rtc: remove unused pcap driver

Conor Dooley (1):
      rtc: mpfs: fix counter upload completion condition

Ethan Nelson-Moore (1):
      rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON

Fredrik M Olsson (2):
      dt-bindings: rtc: ds1307: Add epson,rx8901
      rtc: ds1307: Fix off-by-one issue with wday for rx8130

Haoxiang Li (1):
      rtc: cmos: unregister HPET IRQ handler on probe failure

John Madieu (1):
      rtc: isl1208: Balance enable_irq_wake() with disable_irq_wake() on cleanup

Lad Prabhakar (5):
      rtc: renesas-rtca3: Fix PIE clear polling condition in alarm setup error path
      rtc: renesas-rtca3: Check RADJ poll result during initial setup
      rtc: renesas-rtca3: Fix incorrect error message for reset assert
      rtc: renesas-rtca3: Fix typo in rtca3_ppb_per_cycle documentation
      rtc: renesas-rtca3: Factor out year decoding helper

Mario Limonciello (2):
      rtc: interface: Add rtc_read_next_alarm() to read next expiring timer
      platform/x86: amd-pmc: Fix S0i3 wakeup with alarmtimer

Maxwell Doose (1):
      rtc: ab8500: replace sprintf() with sysfs_emit()

Ronan Dalton (1):
      rtc: ds1307: handle oscillator stop flag for ds1337/ds1339/ds3231

Stepan Ionichev (1):
      rtc: msc313: fix NULL deref in shared IRQ handler at probe

Tommy Huang (2):
      dt-bindings: rtc: add ASPEED AST2700 compatible
      rtc: aspeed: add AST2700 compatible

Udaya Kiran Challa (1):
      dt-bindings: rtc: epson,rx6110: Convert to DT Schema

Uwe Kleine-König (The Capable Hub) (4):
      rtc: Use named initializers for arrays of i2c_device_data
      rtc: Drop unused assignment of platform_device_id driver data
      rtc: ab8500: Simplify driver_data handling
      rtc: Use named initializers for platform_device_id arrays

Xue Lei (1):
      rtc: mv: add suspend/resume support for wakeup

Yahya Saqban (1):
      rtc: interface: fix typos in rtc_handle_legacy_irq() documentation

 .../devicetree/bindings/rtc/epson,rx6110.txt       |  39 --
 .../devicetree/bindings/rtc/epson,rx6110.yaml      |  68 +++
 .../devicetree/bindings/rtc/rtc-ds1307.yaml        |   1 +
 .../devicetree/bindings/rtc/st,m41t93.yaml         |  50 +++
 .../devicetree/bindings/rtc/trivial-rtc.yaml       |   2 +
 drivers/platform/x86/amd/pmc/pmc.c                 |   9 +-
 drivers/rtc/Kconfig                                |   7 -
 drivers/rtc/Makefile                               |   1 -
 drivers/rtc/interface.c                            |  44 +-
 drivers/rtc/rtc-88pm886.c                          |   2 +-
 drivers/rtc/rtc-ab-b5ze-s3.c                       |   2 +-
 drivers/rtc/rtc-ab-eoz9.c                          |   2 +-
 drivers/rtc/rtc-ab8500.c                           |   8 +-
 drivers/rtc/rtc-abx80x.c                           |  23 +-
 drivers/rtc/rtc-aspeed.c                           |   1 +
 drivers/rtc/rtc-bd70528.c                          |   8 +-
 drivers/rtc/rtc-bq32k.c                            |  11 +-
 drivers/rtc/rtc-cmos.c                             |   6 +
 drivers/rtc/rtc-cros-ec.c                          |   4 +-
 drivers/rtc/rtc-ds1307.c                           | 207 +++++++--
 drivers/rtc/rtc-ds1374.c                           |   2 +-
 drivers/rtc/rtc-ds1672.c                           |   2 +-
 drivers/rtc/rtc-ds3232.c                           |   2 +-
 drivers/rtc/rtc-em3027.c                           |   2 +-
 drivers/rtc/rtc-fm3130.c                           |   2 +-
 drivers/rtc/rtc-hym8563.c                          |   4 +-
 drivers/rtc/rtc-isl12022.c                         |   2 +-
 drivers/rtc/rtc-isl12026.c                         |   4 +-
 drivers/rtc/rtc-isl1208.c                          |  25 +-
 drivers/rtc/rtc-m41t80.c                           |  22 +-
 drivers/rtc/rtc-m41t93.c                           | 488 ++++++++++++++++++---
 drivers/rtc/rtc-max31335.c                         |   4 +-
 drivers/rtc/rtc-max6900.c                          |   2 +-
 drivers/rtc/rtc-max77686.c                         |  10 +-
 drivers/rtc/rtc-max8997.c                          |   4 +-
 drivers/rtc/rtc-max8998.c                          |   4 +-
 drivers/rtc/rtc-mpfs.c                             |   2 +-
 drivers/rtc/rtc-msc313.c                           |   4 +-
 drivers/rtc/rtc-mv.c                               |  23 +
 drivers/rtc/rtc-nct3018y.c                         |   2 +-
 drivers/rtc/rtc-pcap.c                             | 179 --------
 drivers/rtc/rtc-pcf2127.c                          |   8 +-
 drivers/rtc/rtc-pcf85063.c                         |  12 +-
 drivers/rtc/rtc-pcf8523.c                          |   2 +-
 drivers/rtc/rtc-pcf8563.c                          |   6 +-
 drivers/rtc/rtc-pcf8583.c                          |   2 +-
 drivers/rtc/rtc-renesas-rtca3.c                    |  26 +-
 drivers/rtc/rtc-rs5c372.c                          |  12 +-
 drivers/rtc/rtc-rv3029c2.c                         |   4 +-
 drivers/rtc/rtc-rv8803.c                           |   8 +-
 drivers/rtc/rtc-rx6110.c                           |   2 +-
 drivers/rtc/rtc-rx8010.c                           |   2 +-
 drivers/rtc/rtc-rx8025.c                           |   4 +-
 drivers/rtc/rtc-rx8581.c                           |   2 +-
 drivers/rtc/rtc-s35390a.c                          |   4 +-
 drivers/rtc/rtc-s5m.c                              |  12 +-
 drivers/rtc/rtc-sd2405al.c                         |   2 +-
 drivers/rtc/rtc-sd3078.c                           |   2 +-
 drivers/rtc/rtc-tps6594.c                          |   4 +-
 drivers/rtc/rtc-x1205.c                            |   2 +-
 include/linux/rtc.h                                |   2 +
 61 files changed, 961 insertions(+), 441 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/rtc/epson,rx6110.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/epson,rx6110.yaml
 create mode 100644 Documentation/devicetree/bindings/rtc/st,m41t93.yaml
 delete mode 100644 drivers/rtc/rtc-pcap.c

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* Re: [PATCH] rtc: zynqmp: Return optional clock lookup errors
From: Michal Simek @ 2026-06-26 12:42 UTC (permalink / raw)
  To: Pengpeng Hou, Alexandre Belloni; +Cc: linux-rtc, linux-arm-kernel, linux-kernel
In-Reply-To: <20260624055524.38522-1-pengpeng@iscas.ac.cn>



On 6/24/26 07:55, Pengpeng Hou wrote:
> devm_clk_get_optional() returns NULL when the optional clock is absent,
> but returns an ERR_PTR when the clock provider lookup fails.  Probe
> currently keeps the ERR_PTR and then passes it to clk_get_rate().
> 
> Return the lookup error instead.  A truly absent optional clock still
> reaches the existing calibration fallback through clk_get_rate(NULL).
> 
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
>   drivers/rtc/rtc-zynqmp.c | 7 +++----
>   1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
> index 2ae54804b87a..5bcb7536e973 100644
> --- a/drivers/rtc/rtc-zynqmp.c
> +++ b/drivers/rtc/rtc-zynqmp.c
> @@ -334,10 +334,9 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
>   
>   	/* Getting the rtc info */
>   	xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc");
> -	if (IS_ERR(xrtcdev->rtc_clk)) {
> -		if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER)
> -			dev_warn(&pdev->dev, "Device clock not found.\n");
> -	}
> +	if (IS_ERR(xrtcdev->rtc_clk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(xrtcdev->rtc_clk),
> +				     "Failed to get rtc clock\n");
>   	xrtcdev->freq = clk_get_rate(xrtcdev->rtc_clk);
>   	if (!xrtcdev->freq) {
>   		ret = of_property_read_u32(pdev->dev.of_node, "calibration",


Fixes: 07dcc6f9c762 ("rtc: zynqmp: Add calibration set and get support")
cc: stable@kernel.org

Reviewed-by: Michal Simek <michal.simek@amd.com>

Thanks,
Michal

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox