summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJernej Skrabec <jernej.skrabec@siol.net>2020-03-08 14:58:48 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-11 16:44:12 +0100
commit728b047f4ca3b2f5ee930485dfc6837ba24b208d (patch)
tree121b61ec2eaeff6b3a8214939916ab1b290bb1ed
parent9c7c1cf29fc31aad36c855157a1e90fdfb754ff6 (diff)
downloadlinux-728b047f4ca3b2f5ee930485dfc6837ba24b208d.tar.gz
linux-728b047f4ca3b2f5ee930485dfc6837ba24b208d.tar.bz2
linux-728b047f4ca3b2f5ee930485dfc6837ba24b208d.zip
rtc: sun6i: Make external 32k oscillator optional
[ Upstream commit ec98a87509f40324807dc179a7e3163d40709eba ] Some boards, like OrangePi PC2 (H5), OrangePi Plus 2E (H3) and Tanix TX6 (H6) don't have external 32kHz oscillator. Till H6, it didn't really matter if external oscillator was enabled because HW detected error and fall back to internal one. H6 has same functionality but it's the first SoC which have "auto switch bypass" bit documented and always enabled in driver. This prevents RTC to work correctly if external crystal is not present on board. There are other side effects - all peripherals which depends on this clock also don't work (HDMI CEC for example). Make clocks property optional. If it is present, select external oscillator. If not, stay on internal. Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> Acked-by: Maxime Ripard <mripard@kernel.org> Link: https://lore.kernel.org/r/20200308135849.106333-2-jernej.skrabec@siol.net Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Stable-dep-of: 344f4030f6c5 ("rtc: sun6i: Always export the internal oscillator") Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/rtc/rtc-sun6i.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index c41bc8084d7c..b13af0368ef6 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -251,19 +251,17 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
writel(reg, rtc->base + SUN6I_LOSC_CTRL);
}
- /* Switch to the external, more precise, oscillator */
- reg |= SUN6I_LOSC_CTRL_EXT_OSC;
- if (rtc->data->has_losc_en)
- reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+ /* Switch to the external, more precise, oscillator, if present */
+ if (of_get_property(node, "clocks", NULL)) {
+ reg |= SUN6I_LOSC_CTRL_EXT_OSC;
+ if (rtc->data->has_losc_en)
+ reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+ }
writel(reg, rtc->base + SUN6I_LOSC_CTRL);
/* Yes, I know, this is ugly. */
sun6i_rtc = rtc;
- /* Deal with old DTs */
- if (!of_get_property(node, "clocks", NULL))
- goto err;
-
/* Only read IOSC name from device tree if it is exported */
if (rtc->data->export_iosc)
of_property_read_string_index(node, "clock-output-names", 2,
@@ -280,11 +278,13 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
}
parents[0] = clk_hw_get_name(rtc->int_osc);
+ /* If there is no external oscillator, this will be NULL and ... */
parents[1] = of_clk_get_parent_name(node, 0);
rtc->hw.init = &init;
init.parent_names = parents;
+ /* ... number of clock parents will be 1. */
init.num_parents = of_clk_get_parent_count(node) + 1;
of_property_read_string_index(node, "clock-output-names", 0,
&init.name);