Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp1789361imm; Wed, 16 May 2018 03:09:05 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqSWAL85y/G8qO9uhNdMYhX8cJNI3vAvIBQb9u4afuX0P97lanPzOpN4Oq5X7nXcxCqWiz+ X-Received: by 2002:a17:902:7d87:: with SMTP id a7-v6mr273645plm.264.1526465345337; Wed, 16 May 2018 03:09:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526465345; cv=none; d=google.com; s=arc-20160816; b=v98UlZsy8vU1hLGmo8EnUqvsTXX7WviIbmozGyBpQEyEFbKt7GSOI7Jz1nSy5MQlO9 OlC4W8ZiuhgH9qFJyqReqEJ0Lv815Z40gW5W5TZbTu1llP2lj8UgcmP8nahI7N6HOwt9 8UK/r7Mcg3scZwGLZW5ycvjBweDIvPa99Dml7Ip5qgQsEo672LRMobRZj2KnjTumzfsU 2kqyZBywus3DmFTs913c4FvRSOZnbYXmK1LSL8kTnB1qeFAtdkEU+qelAntsnOJpcrLe 3OSdp/GjBFXKvovW9/aTv3OaBEaqZAjmglX/dflqStSa0u5kM6fcO/qErfcyVY2wgSW4 tJIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=sTOzGa8/8yHFNxKKJ/xm7ziZ+KmYUuiV2xE1zLTrgyY=; b=KuDR9BXv+5yiYrNoxqv8kPEfyHEjqZC6ueXdwAjLVoyPOV1VTPMzSWsu8pXJp0EZYU 4cD3GWIJ/b+cwn2THK2/kAHvzHBjH7rra3FjDvDfYs0quf3kJDwefAueCMaabFB03JD7 +Gvp9j9/zIJdkCoAloRFuQt7XrVz5xb4eM6E5BR9V1H7cyoC1mdxwueRTy4JVj6dg2Jq Eos7CiX8fgY0eOf9RyoIn+NdxIVO58hVyNh9duIH3yxnBvUjLTpzuP1ry/Ks3j75mquD IHVq7LDQiqxLU2Jg7mla7/bMNoFkVIv9CpM0ukPK5cOpUBDl2H5tvfrkD9UtoyIy8a0L jA1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=temperror (no key for signature) header.i=@micronovasrl.com header.s=dkim header.b=Zp0UrBe3; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w18-v6si2373123pfl.359.2018.05.16.03.08.50; Wed, 16 May 2018 03:09:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=temperror (no key for signature) header.i=@micronovasrl.com header.s=dkim header.b=Zp0UrBe3; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753493AbeEPKIC (ORCPT + 99 others); Wed, 16 May 2018 06:08:02 -0400 Received: from mail.micronovasrl.com ([212.103.203.10]:57542 "EHLO mail.micronovasrl.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753144AbeEPKFn (ORCPT ); Wed, 16 May 2018 06:05:43 -0400 Received: from mail.micronovasrl.com (mail.micronovasrl.com [127.0.0.1]) by mail.micronovasrl.com (Postfix) with ESMTP id 65C49B00BA8 for ; Wed, 16 May 2018 12:05:40 +0200 (CEST) Authentication-Results: mail.micronovasrl.com (amavisd-new); dkim=pass reason="pass (just generated, assumed good)" header.d=micronovasrl.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=micronovasrl.com; h=references:in-reply-to:x-mailer:message-id:date:date:subject :subject:to:from:from; s=dkim; t=1526465139; x=1527329140; bh=2C qMI9I1FrIX8PFM4PXSbi7iXFMK34w6q8YAFVUgdWw=; b=Zp0UrBe3xkzBKwd5fk /sDmhbJkmfxkvqbvBYZLZL4p7jftlyMZlou3H8kedrEl254vbUY/YClOwco0Lz1E mtPAGsFUpDi9hOcWNfrA/l0dp+I5V4WQS4fd7GUqjL1unWD96dR7YKVF71GPIYAE s4lQ//BmWMDzC20zFospW3eR8= X-Virus-Scanned: Debian amavisd-new at mail.micronovasrl.com X-Spam-Flag: NO X-Spam-Score: -2.9 X-Spam-Level: X-Spam-Status: No, score=-2.9 tagged_above=-10 required=4.5 tests=[ALL_TRUSTED=-1, BAYES_00=-1.9] autolearn=unavailable autolearn_force=no Received: from mail.micronovasrl.com ([127.0.0.1]) by mail.micronovasrl.com (mail.micronovasrl.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id aDFE8wqo4GrW for ; Wed, 16 May 2018 12:05:39 +0200 (CEST) Received: from localhost.localdomain (62-11-51-166.dialup.tiscali.it [62.11.51.166]) by mail.micronovasrl.com (Postfix) with ESMTPSA id 721B9B00B70; Wed, 16 May 2018 12:05:33 +0200 (CEST) From: Giulio Benetti To: a.zummo@towertech.it, alexandre.belloni@bootlin.com Cc: robh+dt@kernel.org, mark.rutland@arm.com, linux-rtc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Giulio Benetti Subject: [PATCH v4 3/4] rtc: ds1307: add offset sysfs for mt41txx chips. Date: Wed, 16 May 2018 12:05:25 +0200 Message-Id: <20180516100526.73549-3-giulio.benetti@micronovasrl.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180516100526.73549-1-giulio.benetti@micronovasrl.com> References: <20180516100526.73549-1-giulio.benetti@micronovasrl.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org m41txx chips can hold a calibration value to get correct clock bias. Add offset handling (ranging between -63ppm and 126ppm) via sysfs. Signed-off-by: Giulio Benetti --- V3 => V4: * use ppm as offset input according to documentation instead of raw ic offset values. * use regmap_update_bits instead of regmap_write to update ic registers * sysfs_remove_group if devm_add_action_or_reset fails * rtc_device_unregister if ds1307_add_frequency_test fails on m41txx series drivers/rtc/rtc-ds1307.c | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 0ab0c166da83..2797d01bfa1d 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -114,6 +114,20 @@ enum ds_type { # define RX8025_BIT_VDET 0x40 # define RX8025_BIT_XST 0x20 +#define M41TXX_REG_CONTROL 0x07 +# define M41TXX_BIT_OUT 0x80 +# define M41TXX_BIT_FT 0x40 +# define M41TXX_BIT_CALIB_SIGN 0x20 +# define M41TXX_M_CALIBRATION 0x1f + +/* negative offset step is -2.034ppm */ +#define M41TXX_NEG_OFFSET_STEP_PPM 2034 +/* positive offset step is +4.068ppm */ +#define M41TXX_POS_OFFSET_STEP_PPM 4068 +/* Min and max values supported with 'offset' interface by M41TXX */ +#define M41TXX_MIN_OFFSET (((-31) * M41TXX_NEG_OFFSET_STEP_PPM) / 1000) +#define M41TXX_MAX_OFFSET (((31) * M41TXX_POS_OFFSET_STEP_PPM) / 1000) + struct ds1307 { enum ds_type type; unsigned long flags; @@ -146,6 +160,9 @@ struct chip_desc { static int ds1307_get_time(struct device *dev, struct rtc_time *t); static int ds1307_set_time(struct device *dev, struct rtc_time *t); +static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t); +static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t); +static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled); static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode); static irqreturn_t rx8130_irq(int irq, void *dev_id); static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t); @@ -155,6 +172,8 @@ static irqreturn_t mcp794xx_irq(int irq, void *dev_id); static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t); static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t); static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled); +static int m41txx_rtc_read_offset(struct device *dev, long *offset); +static int m41txx_rtc_set_offset(struct device *dev, long offset); static const struct rtc_class_ops rx8130_rtc_ops = { .read_time = ds1307_get_time, @@ -172,6 +191,16 @@ static const struct rtc_class_ops mcp794xx_rtc_ops = { .alarm_irq_enable = mcp794xx_alarm_irq_enable, }; +static const struct rtc_class_ops m41txx_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, + .read_alarm = ds1337_read_alarm, + .set_alarm = ds1337_set_alarm, + .alarm_irq_enable = ds1307_alarm_irq_enable, + .read_offset = m41txx_rtc_read_offset, + .set_offset = m41txx_rtc_set_offset, +}; + static const struct chip_desc chips[last_ds_type] = { [ds_1307] = { .nvram_offset = 8, @@ -227,10 +256,17 @@ static const struct chip_desc chips[last_ds_type] = { .irq_handler = rx8130_irq, .rtc_ops = &rx8130_rtc_ops, }, + [m41t0] = { + .rtc_ops = &m41txx_rtc_ops, + }, + [m41t00] = { + .rtc_ops = &m41txx_rtc_ops, + }, [m41t11] = { /* this is battery backed SRAM */ .nvram_offset = 8, .nvram_size = 56, + .rtc_ops = &m41txx_rtc_ops, }, [mcp794xx] = { .alarm = 1, @@ -972,6 +1008,51 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled) enabled ? MCP794XX_BIT_ALM0_EN : 0); } +static int m41txx_rtc_read_offset(struct device *dev, long *offset) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + u8 val; + + regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg); + + val = ctrl_reg & M41TXX_M_CALIBRATION; + + /* check if positive */ + if (ctrl_reg & M41TXX_BIT_CALIB_SIGN) + *offset = (val * M41TXX_POS_OFFSET_STEP_PPM); + else + *offset = -(val * M41TXX_NEG_OFFSET_STEP_PPM); + + *offset = DIV_ROUND_CLOSEST(*offset, 1000); + + return 0; +} + +static int m41txx_rtc_set_offset(struct device *dev, long offset) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + + if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET)) + return -ERANGE; + + offset *= 1000; + + if (offset >= 0) { + ctrl_reg = DIV_ROUND_CLOSEST(offset, + M41TXX_POS_OFFSET_STEP_PPM); + ctrl_reg |= M41TXX_BIT_CALIB_SIGN; + } else { + ctrl_reg = DIV_ROUND_CLOSEST(abs(offset), + M41TXX_NEG_OFFSET_STEP_PPM); + } + + return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, + M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN, + ctrl_reg); +} + /*----------------------------------------------------------------------*/ static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, -- 2.17.0