Message ID | 20221215150214.1109074-12-hugo@hugovil.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:e747:0:0:0:0:0 with SMTP id c7csp421177wrn; Thu, 15 Dec 2022 07:19:44 -0800 (PST) X-Google-Smtp-Source: AA0mqf7ZoDxOBT4I0zwHEMgWmm+jGiqiRJTVBdvwMFU9Y5bEff6f0Uk+fW8qJ+/LIr8k8OxIqufp X-Received: by 2002:a05:6a20:930f:b0:a7:866d:40b5 with SMTP id r15-20020a056a20930f00b000a7866d40b5mr25172042pzh.6.1671117583868; Thu, 15 Dec 2022 07:19:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671117583; cv=none; d=google.com; s=arc-20160816; b=rNx4s+BWQsS3Afw4swdp3RCBY+3EAAYKpOPiAHl11jqc5EiA1CW9i5AGlxqDNxebwc CDvXfH4Bj4FCrceJc5lEwiIIcGI/s7sm7rceZOKGHjXNjfj6rC8qNYD0ZmgO4IZDqcgZ qjHn0laKz/R3tXH7jlDYoJX4jaTiV+k/3et584IG0LOxqCeyP/dck8DLxcMjN9AzLMoQ eAofJ+ymwOimAGgmwfIX1e1wSl/j91F6lxKj19imU8K+Y38rrfIaRUYGWjMdj5agAbwV 9j3IEGQOnYsJ+tKZ6pb0wr4/HWG41/TmLZoaXmnWIs8kSxU6P7f0g44Vv9J0sRfG0DxI 9rUw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:subject:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:cc:to:from:dkim-signature; bh=cCTf1P1Ro/N5X79I1I290rP6Jh7qh0U4wx0QBzSmYMQ=; b=0+sIeARTHL+OCV+7tc7/Avmtymwf+6Pm2R3hL4Ok+lSNrpqIrZKKdMSz0v1ExhsC0D rAZI5ldGy71WhSRQGh87t8gpwO4XQxMQIpSQN+0L2xk9CBUxA35s9pWBE2jAJ9vSbrDL KytYKe1Or+fUsXs4VV7H2kTUcqVg8LRKvcVODZCNK3tLrAojcvcvJg1f1X2lIiiKC5HY IS2sz4CrDcxCFGWTRs6i1Ht1xQhJ4Q2ZdnuNmZhr/t5rFXoyoQ73c6AOZdNKKGL8bOrI wO5qwKik+OY/sinaNI9GpM+YLEblI/weab+fRQkYzU6oNbyriB6Tp4ECjnW/UBu6SBr6 gbng== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@hugovil.com header.s=x header.b=FJAEF2V4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id m22-20020a635816000000b00479079b77a6si3027108pgb.105.2022.12.15.07.19.30; Thu, 15 Dec 2022 07:19:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=fail header.i=@hugovil.com header.s=x header.b=FJAEF2V4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229926AbiLOPSP (ORCPT <rfc822;jeantsuru.cumc.mandola@gmail.com> + 99 others); Thu, 15 Dec 2022 10:18:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229722AbiLOPSH (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 15 Dec 2022 10:18:07 -0500 Received: from mail.hugovil.com (mail.hugovil.com [162.243.120.170]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC7FF19F; Thu, 15 Dec 2022 07:18:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=hugovil.com ; s=x; h=Subject:Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Cc:To:From:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=cCTf1P1Ro/N5X79I1I290rP6Jh7qh0U4wx0QBzSmYMQ=; b=FJAEF2V4u9/V8aWleuoaeHIMnh YiumC9kpOionkUuDn3/3wSBvR3+mOIl91bpx291TIvTjg0RMth2l7ZmG4uh0HH3w4LSL8AQVWvdJ9 K2qkLCtmbSfqkOKFE7vFtsiJU85o56xjKD+/etsOa2nYYH0fOkr3i4/abN/otikFaI3Q=; Received: from modemcable168.174-80-70.mc.videotron.ca ([70.80.174.168]:48102 helo=pettiford.lan) by mail.hugovil.com with esmtpa (Exim 4.92) (envelope-from <hugo@hugovil.com>) id 1p5pmN-0000EC-1u; Thu, 15 Dec 2022 10:04:11 -0500 From: Hugo Villeneuve <hugo@hugovil.com> To: a.zummo@towertech.it, alexandre.belloni@bootlin.com, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org Cc: linux-rtc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, hugo@hugovil.com, Hugo Villeneuve <hvilleneuve@dimonoff.com> Date: Thu, 15 Dec 2022 10:02:12 -0500 Message-Id: <20221215150214.1109074-12-hugo@hugovil.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221215150214.1109074-1-hugo@hugovil.com> References: <20221215150214.1109074-1-hugo@hugovil.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 70.80.174.168 X-SA-Exim-Mail-From: hugo@hugovil.com X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 Subject: [PATCH v3 11/14] rtc: pcf2127: adapt time/date registers write sequence for PCF2131 X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.hugovil.com) Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1752293791196414261?= X-GMAIL-MSGID: =?utf-8?q?1752293791196414261?= |
Series |
rtc: pcf2127: add PCF2131 driver
|
|
Commit Message
Hugo Villeneuve
Dec. 15, 2022, 3:02 p.m. UTC
From: Hugo Villeneuve <hvilleneuve@dimonoff.com> The sequence for updating the time/date registers is slightly different between PCF2127/29 and PCF2131. For PCF2127/29, during write operations, the time counting circuits (memory locations 03h through 09h) are automatically blocked. For PCF2131, time/date registers write access requires setting the STOP bit and sending the clear prescaler instruction (CPR). STOP then needs to be released once write operation is completed. Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> --- drivers/rtc/rtc-pcf2127.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
Comments
Den tor. 15. dec. 2022 kl. 16.19 skrev Hugo Villeneuve <hugo@hugovil.com>: > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > The sequence for updating the time/date registers is slightly > different between PCF2127/29 and PCF2131. > > For PCF2127/29, during write operations, the time counting > circuits (memory locations 03h through 09h) are automatically blocked. > > For PCF2131, time/date registers write access requires setting the > STOP bit and sending the clear prescaler instruction (CPR). STOP then > needs to be released once write operation is completed. > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> > --- > drivers/rtc/rtc-pcf2127.c | 38 +++++++++++++++++++++++++++++++++++++- > 1 file changed, 37 insertions(+), 1 deletion(-) > > diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c > index e4b78b9c03f9..11fbdab6bf01 100644 > --- a/drivers/rtc/rtc-pcf2127.c > +++ b/drivers/rtc/rtc-pcf2127.c > @@ -39,6 +39,7 @@ > #define PCF2127_REG_CTRL1 0x00 > #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) > #define PCF2127_BIT_CTRL1_TSF1 BIT(4) > +#define PCF2127_BIT_CTRL1_STOP BIT(5) > /* Control register 2 */ > #define PCF2127_REG_CTRL2 0x01 > #define PCF2127_BIT_CTRL2_AIE BIT(1) > @@ -70,6 +71,7 @@ > #define PCF2131_REG_SR_RESET 0x05 > #define PCF2131_SR_RESET_READ_PATTERN 0b00100100 /* Fixed pattern. */ > #define PCF2131_SR_RESET_RESET_CMD 0x2C /* SR is bit 3. */ > +#define PCF2131_SR_RESET_CPR_CMD 0xA4 /* CPR is bit 7. */ Replace 0xA4 with (BIT(2) | BIT(5) | BIT(7)) or (PCF2131_SR_RESET_READ_PATTERN | BIT(7)) > /* Time and date registers */ > #define PCF2127_REG_TIME_DATE_BASE 0x03 > #define PCF2131_REG_TIME_DATE_BASE 0x07 /* Register 0x06 is 100th seconds, > @@ -307,7 +309,31 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > /* year */ > buf[i++] = bin2bcd(tm->tm_year - 100); > > - /* write register's data */ > + /* Write access to time registers: > + * PCF2127/29: no special action required. > + * PCF2131: requires setting the STOP bit. STOP bit needs to > + * be cleared after time registers are updated. > + * It is also recommended to set CPR bit, although > + * write access will work without it. > + */ > + if (pcf2127->cfg->has_reset_reg) { > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > + PCF2127_BIT_CTRL1_STOP, > + PCF2127_BIT_CTRL1_STOP); > + if (err) { > + dev_err(dev, "setting STOP bit failed\n"); > + return err; > + } > + > + err = regmap_write(pcf2127->regmap, pcf2127->cfg->reg_reset, > + PCF2131_SR_RESET_CPR_CMD); > + if (err) { > + dev_err(dev, "sending CPR cmd failed\n"); > + return err; > + } > + } > + > + /* write time register's data */ > err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i); > if (err) { > dev_err(dev, > @@ -315,6 +341,16 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > return err; > } > > + if (pcf2127->cfg->has_reset_reg) { > + /* Clear STOP bit (PCF2131 only) after write is completed. */ > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > + PCF2127_BIT_CTRL1_STOP, 0); > + if (err) { > + dev_err(dev, "clearing STOP bit failed\n"); > + return err; > + } > + } > + > return 0; > } > > -- > 2.30.2 >
On 15/12/2022 10:02:12-0500, Hugo Villeneuve wrote: > From: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > The sequence for updating the time/date registers is slightly > different between PCF2127/29 and PCF2131. > > For PCF2127/29, during write operations, the time counting > circuits (memory locations 03h through 09h) are automatically blocked. > > For PCF2131, time/date registers write access requires setting the > STOP bit and sending the clear prescaler instruction (CPR). STOP then > needs to be released once write operation is completed. > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> > --- > drivers/rtc/rtc-pcf2127.c | 38 +++++++++++++++++++++++++++++++++++++- > 1 file changed, 37 insertions(+), 1 deletion(-) > > diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c > index e4b78b9c03f9..11fbdab6bf01 100644 > --- a/drivers/rtc/rtc-pcf2127.c > +++ b/drivers/rtc/rtc-pcf2127.c > @@ -39,6 +39,7 @@ > #define PCF2127_REG_CTRL1 0x00 > #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) > #define PCF2127_BIT_CTRL1_TSF1 BIT(4) > +#define PCF2127_BIT_CTRL1_STOP BIT(5) > /* Control register 2 */ > #define PCF2127_REG_CTRL2 0x01 > #define PCF2127_BIT_CTRL2_AIE BIT(1) > @@ -70,6 +71,7 @@ > #define PCF2131_REG_SR_RESET 0x05 > #define PCF2131_SR_RESET_READ_PATTERN 0b00100100 /* Fixed pattern. */ > #define PCF2131_SR_RESET_RESET_CMD 0x2C /* SR is bit 3. */ > +#define PCF2131_SR_RESET_CPR_CMD 0xA4 /* CPR is bit 7. */ > /* Time and date registers */ > #define PCF2127_REG_TIME_DATE_BASE 0x03 > #define PCF2131_REG_TIME_DATE_BASE 0x07 /* Register 0x06 is 100th seconds, > @@ -307,7 +309,31 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > /* year */ > buf[i++] = bin2bcd(tm->tm_year - 100); > > - /* write register's data */ > + /* Write access to time registers: > + * PCF2127/29: no special action required. > + * PCF2131: requires setting the STOP bit. STOP bit needs to > + * be cleared after time registers are updated. > + * It is also recommended to set CPR bit, although > + * write access will work without it. > + */ > + if (pcf2127->cfg->has_reset_reg) { This should probably be tied to the actual rtc model rather than the presence of the reset register. You MUST clear CPR to be able to set the time precisely. > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > + PCF2127_BIT_CTRL1_STOP, > + PCF2127_BIT_CTRL1_STOP); > + if (err) { > + dev_err(dev, "setting STOP bit failed\n"); This really needs to be less verbose. There is nothing a user can really do after having seen this message. Having an error in userspace will anyway prompt the user to retry the operation which is the only action it can do. > + return err; > + } > + > + err = regmap_write(pcf2127->regmap, pcf2127->cfg->reg_reset, > + PCF2131_SR_RESET_CPR_CMD); > + if (err) { > + dev_err(dev, "sending CPR cmd failed\n"); > + return err; > + } > + } > + > + /* write time register's data */ > err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i); > if (err) { > dev_err(dev, > @@ -315,6 +341,16 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > return err; > } > > + if (pcf2127->cfg->has_reset_reg) { > + /* Clear STOP bit (PCF2131 only) after write is completed. */ > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > + PCF2127_BIT_CTRL1_STOP, 0); > + if (err) { > + dev_err(dev, "clearing STOP bit failed\n"); > + return err; > + } > + } > + > return 0; > } > > -- > 2.30.2 >
On Sat, 7 Jan 2023 19:44:23 +0100 Bruno Thomsen <bruno.thomsen@gmail.com> wrote: > Den tor. 15. dec. 2022 kl. 16.19 skrev Hugo Villeneuve <hugo@hugovil.com>: > > > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > > > The sequence for updating the time/date registers is slightly > > different between PCF2127/29 and PCF2131. > > > > For PCF2127/29, during write operations, the time counting > > circuits (memory locations 03h through 09h) are automatically blocked. > > > > For PCF2131, time/date registers write access requires setting the > > STOP bit and sending the clear prescaler instruction (CPR). STOP then > > needs to be released once write operation is completed. > > > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > --- > > drivers/rtc/rtc-pcf2127.c | 38 +++++++++++++++++++++++++++++++++++++- > > 1 file changed, 37 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c > > index e4b78b9c03f9..11fbdab6bf01 100644 > > --- a/drivers/rtc/rtc-pcf2127.c > > +++ b/drivers/rtc/rtc-pcf2127.c > > @@ -39,6 +39,7 @@ > > #define PCF2127_REG_CTRL1 0x00 > > #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) > > #define PCF2127_BIT_CTRL1_TSF1 BIT(4) > > +#define PCF2127_BIT_CTRL1_STOP BIT(5) > > /* Control register 2 */ > > #define PCF2127_REG_CTRL2 0x01 > > #define PCF2127_BIT_CTRL2_AIE BIT(1) > > @@ -70,6 +71,7 @@ > > #define PCF2131_REG_SR_RESET 0x05 > > #define PCF2131_SR_RESET_READ_PATTERN 0b00100100 /* Fixed pattern. */ > > #define PCF2131_SR_RESET_RESET_CMD 0x2C /* SR is bit 3. */ > > +#define PCF2131_SR_RESET_CPR_CMD 0xA4 /* CPR is bit 7. */ > > Replace 0xA4 with (BIT(2) | BIT(5) | BIT(7)) or > (PCF2131_SR_RESET_READ_PATTERN | BIT(7)) Done. > > /* Time and date registers */ > > #define PCF2127_REG_TIME_DATE_BASE 0x03 > > #define PCF2131_REG_TIME_DATE_BASE 0x07 /* Register 0x06 is 100th seconds, > > @@ -307,7 +309,31 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > > /* year */ > > buf[i++] = bin2bcd(tm->tm_year - 100); > > > > - /* write register's data */ > > + /* Write access to time registers: > > + * PCF2127/29: no special action required. > > + * PCF2131: requires setting the STOP bit. STOP bit needs to > > + * be cleared after time registers are updated. > > + * It is also recommended to set CPR bit, although > > + * write access will work without it. > > + */ > > + if (pcf2127->cfg->has_reset_reg) { > > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > > + PCF2127_BIT_CTRL1_STOP, > > + PCF2127_BIT_CTRL1_STOP); > > + if (err) { > > + dev_err(dev, "setting STOP bit failed\n"); > > + return err; > > + } > > + > > + err = regmap_write(pcf2127->regmap, pcf2127->cfg->reg_reset, > > + PCF2131_SR_RESET_CPR_CMD); > > + if (err) { > > + dev_err(dev, "sending CPR cmd failed\n"); > > + return err; > > + } > > + } > > + > > + /* write time register's data */ > > err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i); > > if (err) { > > dev_err(dev, > > @@ -315,6 +341,16 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > > return err; > > } > > > > + if (pcf2127->cfg->has_reset_reg) { > > + /* Clear STOP bit (PCF2131 only) after write is completed. */ > > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > > + PCF2127_BIT_CTRL1_STOP, 0); > > + if (err) { > > + dev_err(dev, "clearing STOP bit failed\n"); > > + return err; > > + } > > + } > > + > > return 0; > > } > > > > -- > > 2.30.2 > > >
On Fri, 20 Jan 2023 18:09:41 +0100 Alexandre Belloni <alexandre.belloni@bootlin.com> wrote: > On 15/12/2022 10:02:12-0500, Hugo Villeneuve wrote: > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > > > The sequence for updating the time/date registers is slightly > > different between PCF2127/29 and PCF2131. > > > > For PCF2127/29, during write operations, the time counting > > circuits (memory locations 03h through 09h) are automatically blocked. > > > > For PCF2131, time/date registers write access requires setting the > > STOP bit and sending the clear prescaler instruction (CPR). STOP then > > needs to be released once write operation is completed. > > > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > --- > > drivers/rtc/rtc-pcf2127.c | 38 +++++++++++++++++++++++++++++++++++++- > > 1 file changed, 37 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c > > index e4b78b9c03f9..11fbdab6bf01 100644 > > --- a/drivers/rtc/rtc-pcf2127.c > > +++ b/drivers/rtc/rtc-pcf2127.c > > @@ -39,6 +39,7 @@ > > #define PCF2127_REG_CTRL1 0x00 > > #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) > > #define PCF2127_BIT_CTRL1_TSF1 BIT(4) > > +#define PCF2127_BIT_CTRL1_STOP BIT(5) > > /* Control register 2 */ > > #define PCF2127_REG_CTRL2 0x01 > > #define PCF2127_BIT_CTRL2_AIE BIT(1) > > @@ -70,6 +71,7 @@ > > #define PCF2131_REG_SR_RESET 0x05 > > #define PCF2131_SR_RESET_READ_PATTERN 0b00100100 /* Fixed pattern. */ > > #define PCF2131_SR_RESET_RESET_CMD 0x2C /* SR is bit 3. */ > > +#define PCF2131_SR_RESET_CPR_CMD 0xA4 /* CPR is bit 7. */ > > /* Time and date registers */ > > #define PCF2127_REG_TIME_DATE_BASE 0x03 > > #define PCF2131_REG_TIME_DATE_BASE 0x07 /* Register 0x06 is 100th seconds, > > @@ -307,7 +309,31 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > > /* year */ > > buf[i++] = bin2bcd(tm->tm_year - 100); > > > > - /* write register's data */ > > + /* Write access to time registers: > > + * PCF2127/29: no special action required. > > + * PCF2131: requires setting the STOP bit. STOP bit needs to > > + * be cleared after time registers are updated. > > + * It is also recommended to set CPR bit, although > > + * write access will work without it. > > + */ > > + if (pcf2127->cfg->has_reset_reg) { > > This should probably be tied to the actual rtc model rather than the > presence of the reset register. > You MUST clear CPR to be able to set the time precisely. In fact you must actually SET the CPR bit to clear the prescaler, confusing! I was already setting the CPR bit (clearing prescaler), so I modified the confusing comment. The CPR bit is only present IF the reset register is also present, that is why I simply used the presence of the reset register to take the correct action. This avoids to define a new bit or matching on a device model for that functionality (adding newer models could potentially mean modifying the model match). But if you absolutely want to match on the model, I would like to know how you would like to practically do it (maybe an example)? > > > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > > + PCF2127_BIT_CTRL1_STOP, > > + PCF2127_BIT_CTRL1_STOP); > > + if (err) { > > + dev_err(dev, "setting STOP bit failed\n"); > > This really needs to be less verbose. There is nothing a user can really > do after having seen this message. Having an error in userspace will > anyway prompt the user to retry the operation which is the only action > it can do. I converted the dev_err messages to dev_dbg. In the original driver and in the same function, there is also a dev_err to handle regmap_bulk_write() failure. Do you suggest that we also make it less verbose: err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, i); if (err) { dev_err(dev, ??? > > + return err; > > + } > > + > > + err = regmap_write(pcf2127->regmap, pcf2127->cfg->reg_reset, > > + PCF2131_SR_RESET_CPR_CMD); > > + if (err) { > > + dev_err(dev, "sending CPR cmd failed\n"); > > + return err; > > + } > > + } > > + > > + /* write time register's data */ > > err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i); > > if (err) { > > dev_err(dev, > > @@ -315,6 +341,16 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > > return err; > > } > > > > + if (pcf2127->cfg->has_reset_reg) { > > + /* Clear STOP bit (PCF2131 only) after write is completed. */ > > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > > + PCF2127_BIT_CTRL1_STOP, 0); > > + if (err) { > > + dev_err(dev, "clearing STOP bit failed\n"); > > + return err; > > + } > > + } > > + > > return 0; > > } > > > > -- > > 2.30.2 > > > > -- > Alexandre Belloni, co-owner and COO, Bootlin > Embedded Linux and Kernel engineering > https://bootlin.com >
On 23/01/2023 16:57:41-0500, Hugo Villeneuve wrote: > On Fri, 20 Jan 2023 18:09:41 +0100 > Alexandre Belloni <alexandre.belloni@bootlin.com> wrote: > > > On 15/12/2022 10:02:12-0500, Hugo Villeneuve wrote: > > > From: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > > > > > The sequence for updating the time/date registers is slightly > > > different between PCF2127/29 and PCF2131. > > > > > > For PCF2127/29, during write operations, the time counting > > > circuits (memory locations 03h through 09h) are automatically blocked. > > > > > > For PCF2131, time/date registers write access requires setting the > > > STOP bit and sending the clear prescaler instruction (CPR). STOP then > > > needs to be released once write operation is completed. > > > > > > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com> > > > --- > > > drivers/rtc/rtc-pcf2127.c | 38 +++++++++++++++++++++++++++++++++++++- > > > 1 file changed, 37 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c > > > index e4b78b9c03f9..11fbdab6bf01 100644 > > > --- a/drivers/rtc/rtc-pcf2127.c > > > +++ b/drivers/rtc/rtc-pcf2127.c > > > @@ -39,6 +39,7 @@ > > > #define PCF2127_REG_CTRL1 0x00 > > > #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) > > > #define PCF2127_BIT_CTRL1_TSF1 BIT(4) > > > +#define PCF2127_BIT_CTRL1_STOP BIT(5) > > > /* Control register 2 */ > > > #define PCF2127_REG_CTRL2 0x01 > > > #define PCF2127_BIT_CTRL2_AIE BIT(1) > > > @@ -70,6 +71,7 @@ > > > #define PCF2131_REG_SR_RESET 0x05 > > > #define PCF2131_SR_RESET_READ_PATTERN 0b00100100 /* Fixed pattern. */ > > > #define PCF2131_SR_RESET_RESET_CMD 0x2C /* SR is bit 3. */ > > > +#define PCF2131_SR_RESET_CPR_CMD 0xA4 /* CPR is bit 7. */ > > > /* Time and date registers */ > > > #define PCF2127_REG_TIME_DATE_BASE 0x03 > > > #define PCF2131_REG_TIME_DATE_BASE 0x07 /* Register 0x06 is 100th seconds, > > > @@ -307,7 +309,31 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > > > /* year */ > > > buf[i++] = bin2bcd(tm->tm_year - 100); > > > > > > - /* write register's data */ > > > + /* Write access to time registers: > > > + * PCF2127/29: no special action required. > > > + * PCF2131: requires setting the STOP bit. STOP bit needs to > > > + * be cleared after time registers are updated. > > > + * It is also recommended to set CPR bit, although > > > + * write access will work without it. > > > + */ > > > + if (pcf2127->cfg->has_reset_reg) { > > > > This should probably be tied to the actual rtc model rather than the > > presence of the reset register. > > You MUST clear CPR to be able to set the time precisely. > > In fact you must actually SET the CPR bit to clear the prescaler, confusing! > > I was already setting the CPR bit (clearing prescaler), so I modified the confusing comment. > > The CPR bit is only present IF the reset register is also present, that is why I simply used the presence of the reset register to take the correct action. This avoids to define a new bit or matching on a device model for that functionality (adding newer models could potentially mean modifying the model match). > > But if you absolutely want to match on the model, I would like to know how you would like to practically do it (maybe an example)? > You can keep pcf21xx_type around, in pcf21xx_config for example. > > > > > > > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > > > + PCF2127_BIT_CTRL1_STOP, > > > + PCF2127_BIT_CTRL1_STOP); > > > + if (err) { > > > + dev_err(dev, "setting STOP bit failed\n"); > > > > This really needs to be less verbose. There is nothing a user can really > > do after having seen this message. Having an error in userspace will > > anyway prompt the user to retry the operation which is the only action > > it can do. > > I converted the dev_err messages to dev_dbg. > > In the original driver and in the same function, there is also a dev_err to handle regmap_bulk_write() failure. Do you suggest that we also make it less verbose: > > err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, i); > if (err) { > dev_err(dev, > > ??? yes, you can remove it as part of your previous patches. > > > > > + return err; > > > + } > > > + > > > + err = regmap_write(pcf2127->regmap, pcf2127->cfg->reg_reset, > > > + PCF2131_SR_RESET_CPR_CMD); > > > + if (err) { > > > + dev_err(dev, "sending CPR cmd failed\n"); > > > + return err; > > > + } > > > + } > > > + > > > + /* write time register's data */ > > > err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i); > > > if (err) { > > > dev_err(dev, > > > @@ -315,6 +341,16 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) > > > return err; > > > } > > > > > > + if (pcf2127->cfg->has_reset_reg) { > > > + /* Clear STOP bit (PCF2131 only) after write is completed. */ > > > + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, > > > + PCF2127_BIT_CTRL1_STOP, 0); > > > + if (err) { > > > + dev_err(dev, "clearing STOP bit failed\n"); > > > + return err; > > > + } > > > + } > > > + > > > return 0; > > > } > > > > > > -- > > > 2.30.2 > > > > > > > -- > > Alexandre Belloni, co-owner and COO, Bootlin > > Embedded Linux and Kernel engineering > > https://bootlin.com > > > > > -- > Hugo Villeneuve <hugo@hugovil.com>
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index e4b78b9c03f9..11fbdab6bf01 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -39,6 +39,7 @@ #define PCF2127_REG_CTRL1 0x00 #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) #define PCF2127_BIT_CTRL1_TSF1 BIT(4) +#define PCF2127_BIT_CTRL1_STOP BIT(5) /* Control register 2 */ #define PCF2127_REG_CTRL2 0x01 #define PCF2127_BIT_CTRL2_AIE BIT(1) @@ -70,6 +71,7 @@ #define PCF2131_REG_SR_RESET 0x05 #define PCF2131_SR_RESET_READ_PATTERN 0b00100100 /* Fixed pattern. */ #define PCF2131_SR_RESET_RESET_CMD 0x2C /* SR is bit 3. */ +#define PCF2131_SR_RESET_CPR_CMD 0xA4 /* CPR is bit 7. */ /* Time and date registers */ #define PCF2127_REG_TIME_DATE_BASE 0x03 #define PCF2131_REG_TIME_DATE_BASE 0x07 /* Register 0x06 is 100th seconds, @@ -307,7 +309,31 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) /* year */ buf[i++] = bin2bcd(tm->tm_year - 100); - /* write register's data */ + /* Write access to time registers: + * PCF2127/29: no special action required. + * PCF2131: requires setting the STOP bit. STOP bit needs to + * be cleared after time registers are updated. + * It is also recommended to set CPR bit, although + * write access will work without it. + */ + if (pcf2127->cfg->has_reset_reg) { + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, + PCF2127_BIT_CTRL1_STOP, + PCF2127_BIT_CTRL1_STOP); + if (err) { + dev_err(dev, "setting STOP bit failed\n"); + return err; + } + + err = regmap_write(pcf2127->regmap, pcf2127->cfg->reg_reset, + PCF2131_SR_RESET_CPR_CMD); + if (err) { + dev_err(dev, "sending CPR cmd failed\n"); + return err; + } + } + + /* write time register's data */ err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_td_base, buf, i); if (err) { dev_err(dev, @@ -315,6 +341,16 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) return err; } + if (pcf2127->cfg->has_reset_reg) { + /* Clear STOP bit (PCF2131 only) after write is completed. */ + err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, + PCF2127_BIT_CTRL1_STOP, 0); + if (err) { + dev_err(dev, "clearing STOP bit failed\n"); + return err; + } + } + return 0; }