From patchwork Tue Feb 9 10:57:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Borleis X-Patchwork-Id: 580739 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-lf0-x23c.google.com (mail-lf0-x23c.google.com [IPv6:2a00:1450:4010:c07::23c]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 32C94140BA7 for ; Tue, 9 Feb 2016 21:57:37 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b=u14c1wvU; dkim-atps=neutral Received: by mail-lf0-x23c.google.com with SMTP id j99sf21140594lfi.1 for ; Tue, 09 Feb 2016 02:57:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=mime-version:from:to:cc:subject:date:message-id:in-reply-to :references:x-original-sender:x-original-authentication-results :reply-to:content-type:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive:sender :list-subscribe:list-unsubscribe; bh=xRAcJ/YRo80FoMA0ejB/Ld0U4kldkLnIBt344Oc1lYk=; b=u14c1wvU5JSDRGeZqK0mMIKJUxJVY950NZ/vGAHoTw54YZVK3M+YjNhGVmyxhtbhEi KFlEiiClv0WJ3J3kxTM1p2Y/IstVavL/E8ZrSHVTmDmXcaOyAkL0xuZd/19aeZyz4m8n 4GwYxelWUZKRLbwEcCrDLW16YEoOMAbBV88qU9WMJzS6d3ER4f+0lsK6mUWpWZP9xwgq O1JN3XP1jyaK5FflScBx9t+fjUE/tain5aLGjOXdcHvcdnm5fhqBRCtwoqEB2z0tuFdW +VlpRpzL9bB6oaY4V4EfKdGbSghvUi0lXto7qpLPXg+aE0tV1y4WXytOTZJlRZXGHuG7 PUtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:to:cc:subject:date:message-id :in-reply-to:references:x-original-sender :x-original-authentication-results:reply-to:content-type:precedence :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help :list-archive:sender:list-subscribe:list-unsubscribe; bh=xRAcJ/YRo80FoMA0ejB/Ld0U4kldkLnIBt344Oc1lYk=; b=IMUHVM1Bp+kxf5QmhM25jmct1jcy+brRLohHD8YcSNH2F5h0kUrEa9o8K4+7e72S67 3BtLRpQiDcCi5F47d8b6h5UUtZ0/uJxtnuVNc+H4nbhaOKMvhsisq+GgsaM98EK6S2Hh 2v0cs/0sPsl/4S2hH2rw0xf80ZhHk6HM11XNAv8qZkNUxkpsTjMYISutaEAxuEykkjVT Rb+MuKnjmhnSxMBfamQPV7EgJ/TEol3sdi3vpBYCllgnkXR/iPEoLxw+ARYg80Xoknmw fjVf12HVcskh4Vd8yWCsMW6nlWWDkUNDhpbV0+IpMDvuqNEEdIwc0GWhpRSyt0xzAn3S E2Mw== X-Gm-Message-State: AG10YOQhhqf6Nv41wvPo2WwN4uayGSimJy5hJyGUlCrKg76VY6/9EohBaXJfD8GpkATofA== X-Received: by 10.28.85.3 with SMTP id j3mr13136wmb.4.1455015452439; Tue, 09 Feb 2016 02:57:32 -0800 (PST) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.28.3.67 with SMTP id 64ls587569wmd.28.canary; Tue, 09 Feb 2016 02:57:31 -0800 (PST) X-Received: by 10.28.158.216 with SMTP id h207mr454079wme.4.1455015451947; Tue, 09 Feb 2016 02:57:31 -0800 (PST) Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de. [2001:67c:670:201:290:27ff:fe1d:cc33]) by gmr-mx.google.com with ESMTPS id w128si525337wmd.0.2016.02.09.02.57.31 for (version=TLS1_2 cipher=AES128-SHA bits=128/128); Tue, 09 Feb 2016 02:57:31 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of jbe@pengutronix.de designates 2001:67c:670:201:290:27ff:fe1d:cc33 as permitted sender) client-ip=2001:67c:670:201:290:27ff:fe1d:cc33; Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1aT5z9-0005oD-Fg; Tue, 09 Feb 2016 11:57:31 +0100 Received: from jbe by dude.hi.pengutronix.de with local (Exim 4.86) (envelope-from ) id 1aT5z7-0003rW-MU; Tue, 09 Feb 2016 11:57:29 +0100 From: Juergen Borleis To: rtc-linux@googlegroups.com Cc: Alessandro Zummo , Alexandre Belloni , linux-kernel@vger.kernel.org, kernel@pengutronix.de Subject: [rtc-linux] [PATCH v2 3/3] RTC/PCF85063: fix time/date setting Date: Tue, 9 Feb 2016 11:57:27 +0100 Message-Id: <1455015447-13886-4-git-send-email-jbe@pengutronix.de> X-Mailer: git-send-email 2.7.0.rc3 In-Reply-To: <1455015447-13886-1-git-send-email-jbe@pengutronix.de> References: <1455015447-13886-1-git-send-email-jbe@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: jbe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: rtc-linux@googlegroups.com X-Original-Sender: jbe@pengutronix.de X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: best guess record for domain of jbe@pengutronix.de designates 2001:67c:670:201:290:27ff:fe1d:cc33 as permitted sender) smtp.mailfrom=jbe@pengutronix.de Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: rtc-linux@googlegroups.com X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , When setting a new time/date the RTC's clock must be stopped first, in order to write the time/date registers in an atomic manner. So, this change stops the clock first and then writes the time/date registers and the clock control register (to re-enable the clock) in one turn. Signed-off-by: Juergen Borleis --- drivers/rtc/rtc-pcf85063.c | 78 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index e0343e6..c5db231 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -19,6 +19,7 @@ #define DRV_VERSION "0.0.1" #define PCF85063_REG_CTRL1 0x00 /* status */ +#define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL2 0x01 #define PCF85063_REG_SC 0x04 /* datetime */ @@ -40,6 +41,30 @@ struct pcf85063 { int voltage_low; /* indicates if a low_voltage was detected */ }; +static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1) +{ + s32 ret; + + ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1); + if (ret < 0) { + dev_err(&client->dev, "Failing to stop the clock\n"); + return -EIO; + } + + /* stop the clock */ + ret |= PCF85063_REG_CTRL1_STOP; + + ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&client->dev, "Failing to stop the clock\n"); + return -EIO; + } + + *ctrl1 = ret; + + return 0; +} + /* * In the routines that deal directly with the pcf85063 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. @@ -87,41 +112,48 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) { - int i = 0, err = 0; - unsigned char buf[11]; + int rc; + u8 regs[8]; - /* Control & status */ - buf[PCF85063_REG_CTRL1] = 0; - buf[PCF85063_REG_CTRL2] = 5; + /* + * to accurately set the time, reset the divider chain and keep it in + * reset state until all time/date registers are written + */ + rc = pcf85063_stop_clock(client, ®s[7]); + if (rc != 0) + return rc; /* hours, minutes and seconds */ - buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F; + regs[0] = bin2bcd(tm->tm_sec) & 0x7F; /* clear OS flag */ - buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min); - buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour); + regs[1] = bin2bcd(tm->tm_min); + regs[2] = bin2bcd(tm->tm_hour); /* Day of month, 1 - 31 */ - buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday); + regs[3] = bin2bcd(tm->tm_mday); /* Day, 0 - 6 */ - buf[PCF85063_REG_DW] = tm->tm_wday & 0x07; + regs[4] = tm->tm_wday & 0x07; /* month, 1 - 12 */ - buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1); + regs[5] = bin2bcd(tm->tm_mon + 1); /* year and century */ - buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100); - - /* write register's data */ - for (i = 0; i < sizeof(buf); i++) { - unsigned char data[2] = { i, buf[i] }; - - err = i2c_master_send(client, data, sizeof(data)); - if (err != sizeof(data)) { - dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n", - __func__, err, data[0], data[1]); - return -EIO; - } + regs[6] = bin2bcd(tm->tm_year % 100); + + /* + * after all time/date registers are written, let the 'address auto + * increment' feature wrap around and write register CTRL1 to re-enable + * the clock divider chain again + */ + regs[7] &= ~PCF85063_REG_CTRL1_STOP; + + /* write all registers at once */ + rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC, + sizeof(regs), regs); + if (rc < 0) { + dev_err(&client->dev, "date/time register write error\n"); + return rc; } return 0;