From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D8031C433EF for ; Wed, 4 May 2022 13:11:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=MCPOJTJzhRmGZoL0XQO2n39hB72tQrhJD8sKKmqbAak=; b=cNIA9P39Njq9ok parHL0Dp+v7CeOdIq4pugxMR7EwJtcOQzUz33AMupIQWNkzhkL8Po65vROx/NoxPRGXKg/2jirz5v eZo54wEXXGVXzsr4YY7wolSnHlBUQNGxij+5o54bkAGqyXzcT00mx8lhzztN8glSYdoYWFzre6j7H +gJDinYqEVTofe/lyNJ3RbsI2ViwylsI5somn+Vqj2tu/cGKid0k3+7fiShyP8EJ/OaIdL/ogGU77 suXy3jlB/wbrerUE+IU30GLButCCJYLzWGRYhx/EtlSLc5grFzcjRSGNE5NV9g/CI/JslIPjQM64a ruY9macxQjHTQy7GBfZw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nmElo-00Awx4-Nf; Wed, 04 May 2022 13:10:21 +0000 Received: from mx07-00178001.pphosted.com ([185.132.182.106]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nmEiL-00Auje-GE for linux-arm-kernel@lists.infradead.org; Wed, 04 May 2022 13:06:49 +0000 Received: from pps.filterd (m0288072.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 244ALwSj018222; Wed, 4 May 2022 15:06:38 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=selector1; bh=xlADDDAYf7bLutWTVCq2qRcVqVGLfJSifwbAguzb0gc=; b=HmCIJQCrZDeDppLqlB5AYEhWMgfGoOmSt7ACGIv+gmuJCipK4Ac8ozCcT9SovDNRRENh 92UEDE/8m+0Thd6/S5+j0kMDadtE5cUq+GzD04QPYHEZy20U/8eibHFMKP8dSqyxnI29 MS505Tmn1LyaBw/hYloTU4xOBj0F0LB8gtymgogYfWutfaZNL2j4nuZDfpEdIMXU7fDq uv9mnJp1ssWdZ6+Z3NzCSCfcxuqCxZ1qiei93Ci3tFK3BmqU909NXIVqyLaFW1GHu3bc gfEmbQCEL+ul7OOWLKVEQfPqiKXbb4UD9cgxOpZHCZldoO2jAOonW4rI3M/3kLfRYNAv oQ== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3frthjvfg3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 04 May 2022 15:06:38 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0C7DC100034; Wed, 4 May 2022 15:06:38 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 026C321FEAA; Wed, 4 May 2022 15:06:38 +0200 (CEST) Received: from localhost (10.75.127.44) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.26; Wed, 4 May 2022 15:06:37 +0200 From: Valentin Caron To: Alessandro Zummo , Alexandre Belloni , Rob Herring , Krzysztof Kozlowski , Alexandre Torgue CC: Gabriel Fernandez , Amelie Delaunay , Valentin Caron , , , , , Subject: [PATCH 3/6] rtc: stm32: add Low Speed Clock Output (LSCO) support Date: Wed, 4 May 2022 15:06:14 +0200 Message-ID: <20220504130617.331290-2-valentin.caron@foss.st.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220504130233.330983-1-valentin.caron@foss.st.com> References: <20220504130233.330983-1-valentin.caron@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.44] X-ClientProxiedBy: SFHDAG2NODE2.st.com (10.75.127.5) To SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.858,Hydra:6.0.486,FMLib:17.11.64.514 definitions=2022-05-04_04,2022-05-04_01,2022-02-23_01 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220504_060645_918116_3AD9C406 X-CRM114-Status: GOOD ( 28.52 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Amelie Delaunay STM32 RTC is now registered as a clock provider. It provides rtc_lsco clock, that means RTC_LSCO is output on either RTC_OUT1 or RTC_OUT2_RMP, depending on st,lsco DT property (PC13 or PI8 on stm32mp15), (PC13 or PI1 on stm32mp13). Signed-off-by: Amelie Delaunay Signed-off-by: Valentin Caron --- drivers/rtc/Kconfig | 1 + drivers/rtc/rtc-stm32.c | 133 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 41c65b4d2baf..2e8021d7c98a 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1888,6 +1888,7 @@ config RTC_DRV_R7301 config RTC_DRV_STM32 tristate "STM32 RTC" select REGMAP_MMIO + depends on COMMON_CLK depends on ARCH_STM32 || COMPILE_TEST help If you say yes here you get support for the STM32 On-Chip diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index ac9e228b56d0..ace041eb44b8 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -15,6 +16,8 @@ #include #include +#include + #define DRIVER_NAME "stm32_rtc" /* STM32_RTC_TR bit fields */ @@ -39,6 +42,11 @@ #define STM32_RTC_CR_FMT BIT(6) #define STM32_RTC_CR_ALRAE BIT(8) #define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_CR_COSEL BIT(19) +#define STM32_RTC_CR_OSEL GENMASK(22, 21) +#define STM32_RTC_CR_COE BIT(23) +#define STM32_RTC_CR_TAMPOE BIT(26) +#define STM32_RTC_CR_OUT2EN BIT(31) /* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */ #define STM32_RTC_ISR_ALRAWF BIT(0) @@ -75,6 +83,12 @@ /* STM32_RTC_SR/_SCR bit fields */ #define STM32_RTC_SR_ALRA BIT(0) +/* STM32_RTC_CFGR bit fields */ +#define STM32_RTC_CFGR_OUT2_RMP BIT(0) +#define STM32_RTC_CFGR_LSCOEN GENMASK(2, 1) +#define STM32_RTC_CFGR_LSCOEN_OUT1 1 +#define STM32_RTC_CFGR_LSCOEN_OUT2_RMP 2 + /* STM32_RTC_VERR bit fields */ #define STM32_RTC_VERR_MINREV_SHIFT 0 #define STM32_RTC_VERR_MINREV GENMASK(3, 0) @@ -89,6 +103,9 @@ /* Max STM32 RTC register offset is 0x3FC */ #define UNDEF_REG 0xFFFF +/* Frequency of HSE clock (Hz) */ +#define STM32_RTC_HSE_FREQ 32768 + struct stm32_rtc; struct stm32_rtc_registers { @@ -101,6 +118,7 @@ struct stm32_rtc_registers { u16 wpr; u16 sr; u16 scr; + u16 cfgr; u16 verr; }; @@ -115,6 +133,7 @@ struct stm32_rtc_data { bool has_pclk; bool need_dbp; bool has_wakeirq; + bool has_lsco; }; struct stm32_rtc { @@ -128,8 +147,88 @@ struct stm32_rtc { const struct stm32_rtc_data *data; int irq_alarm; int wakeirq_alarm; + int lsco; + struct clk *clk_lsco; }; +/* + * ------------------------------------------------------------------------- + * | TAMPOE | OSEL[1:0] | COE | OUT2EN | RTC_OUT1 | RTC_OUT2 | + * | | | | | | or RTC_OUT2_RMP | + * |-------------------------------------------------------------------------| + * | 0 | 00 | 0 | 0 or 1 | - | - | + * |--------|-----------|-----|--------|------------------|------------------| + * | 0 | 00 | 1 | 0 | CALIB | - | + * |--------|-----------|-----|--------|------------------|------------------| + * | 0 or 1 | !=00 | 0 | 0 | TAMPALRM | - | + * |--------|-----------|-----|--------|------------------|------------------| + * | 0 | 00 | 1 | 1 | - | CALIB | + * |--------|-----------|-----|--------|------------------|------------------| + * | 0 or 1 | !=00 | 0 | 1 | - | TAMPALRM | + * |--------|-----------|-----|--------|------------------|------------------| + * | 0 or 1 | !=00 | 1 | 1 | TAMPALRM | CALIB | + * ------------------------------------------------------------------------- + */ +static int stm32_rtc_clk_lsco_check_availability(struct stm32_rtc *rtc) +{ + struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cr = readl_relaxed(rtc->base + regs.cr); + unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); + unsigned int calib = STM32_RTC_CR_COE; + unsigned int tampalrm = STM32_RTC_CR_TAMPOE | STM32_RTC_CR_OSEL; + + switch (rtc->lsco) { + case RTC_OUT1: + if ((!(cr & STM32_RTC_CR_OUT2EN) && + ((cr & calib) || cr & tampalrm)) || + ((cr & calib) && (cr & tampalrm))) + return -EBUSY; + break; + case RTC_OUT2_RMP: + if ((cr & STM32_RTC_CR_OUT2EN) && + (cfgr & STM32_RTC_CFGR_OUT2_RMP) && + ((cr & calib) || (cr & tampalrm))) + return -EBUSY; + break; + default: + return -EINVAL; + } + + /* LSCO can only work if RTC clock source is HSE */ + if (clk_get_rate(rtc->rtc_ck) != STM32_RTC_HSE_FREQ) + return -ERANGE; + + return 0; +} + +static int stm32_rtc_clk_lsco_register(struct platform_device *pdev) +{ + struct stm32_rtc *rtc = platform_get_drvdata(pdev); + struct stm32_rtc_registers regs = rtc->data->regs; + u8 lscoen; + int ret; + + ret = stm32_rtc_clk_lsco_check_availability(rtc); + if (ret) + return ret; + + lscoen = (rtc->lsco == RTC_OUT1) ? STM32_RTC_CFGR_LSCOEN_OUT1 : + STM32_RTC_CFGR_LSCOEN_OUT2_RMP; + + rtc->clk_lsco = clk_register_gate(&pdev->dev, "rtc_lsco", + __clk_get_name(rtc->rtc_ck), + CLK_IS_CRITICAL, + rtc->base + regs.cfgr, lscoen, + 0, NULL); + if (IS_ERR(rtc->clk_lsco)) + return PTR_ERR(rtc->clk_lsco); + + of_clk_add_provider(pdev->dev.of_node, + of_clk_src_simple_get, rtc->clk_lsco); + + return 0; +} + static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc) { const struct stm32_rtc_registers *regs = &rtc->data->regs; @@ -145,6 +244,15 @@ static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc) writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr); } +static void stm32_rtc_clk_lsco_disable(struct platform_device *pdev) +{ + struct stm32_rtc *rtc = platform_get_drvdata(pdev); + struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); + + writel_relaxed(cfgr &= ~STM32_RTC_CFGR_LSCOEN, rtc->base + regs.cfgr); +} + static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc) { const struct stm32_rtc_registers *regs = &rtc->data->regs; @@ -548,6 +656,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, .has_wakeirq = false, + .has_lsco = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -558,6 +667,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { .wpr = 0x24, .sr = 0x0C, /* set to ISR offset to ease alarm management */ .scr = UNDEF_REG, + .cfgr = UNDEF_REG, .verr = UNDEF_REG, }, .events = { @@ -570,6 +680,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, .has_wakeirq = false, + .has_lsco = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -580,6 +691,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .wpr = 0x24, .sr = 0x0C, /* set to ISR offset to ease alarm management */ .scr = UNDEF_REG, + .cfgr = UNDEF_REG, .verr = UNDEF_REG, }, .events = { @@ -601,6 +713,7 @@ static const struct stm32_rtc_data stm32mp1_data = { .has_pclk = true, .need_dbp = false, .has_wakeirq = true, + .has_lsco = true, .regs = { .tr = 0x00, .dr = 0x04, @@ -611,6 +724,7 @@ static const struct stm32_rtc_data stm32mp1_data = { .wpr = 0x24, .sr = 0x50, .scr = 0x5C, + .cfgr = 0x60, .verr = 0x3F4, }, .events = { @@ -814,6 +928,22 @@ static int stm32_rtc_probe(struct platform_device *pdev) goto err; } + if (rtc->data->has_lsco) { + ret = of_property_read_s32(pdev->dev.of_node, + "st,lsco", &rtc->lsco); + if (!ret) { + ret = stm32_rtc_clk_lsco_register(pdev); + if (ret) + dev_warn(&pdev->dev, + "LSCO clock registration failed: %d\n", + ret); + } else { + stm32_rtc_clk_lsco_disable(pdev); + rtc->lsco = ret; + dev_dbg(&pdev->dev, "No LSCO clock: %d\n", ret); + } + } + /* * If INITS flag is reset (calendar year field set to 0x00), calendar * must be initialized @@ -852,6 +982,9 @@ static int stm32_rtc_remove(struct platform_device *pdev) const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int cr; + if (!IS_ERR_OR_NULL(rtc->clk_lsco)) + clk_unregister_gate(rtc->clk_lsco); + /* Disable interrupts */ stm32_rtc_wpr_unlock(rtc); cr = readl_relaxed(rtc->base + regs->cr); -- 2.25.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel