Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3163359pxf; Sun, 28 Mar 2021 14:31:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzl4MKz5S6WDdZw+lZe1pOooluJjzUNCohCPdHLFiOornnGdG6VuyG0ZnMperlRrg2z6xHV X-Received: by 2002:a17:906:1113:: with SMTP id h19mr25098345eja.478.1616967075690; Sun, 28 Mar 2021 14:31:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616967075; cv=none; d=google.com; s=arc-20160816; b=KsPW2Ka3weYGON4i56JdR5Wz8xSRke4gvB+aoP0Rd1A0EIh1PMJBUkrN3cMEte0URy dDKYssS14i6QY92ZR2KT2DqumMTMMzHV+rwhvG7In7bl8mt3xF7TGZhJHzu6fm+V2Oz9 ASrK5TJCVLwiWsARTkW4ZLei9HXl5zfRP5fACauPItGA0SqXSbNDQcTtMYycvr773NCN tT6d3PYpSAzvCrLbUvyFzW62ywXwrmdAViLUPwSmHhtSZjlcpzGoXOKPq5HkzYIpAq5w /5hfCMuKhM3PX7c2RvhT0iryUEIX7JVP53PKp8SEsWYMWuhSOp1H7zDZOKnsGFWDhG/v dbhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=22Un9gd2PgkZBPv+BYVi0DXZk+QTxlLliL/DmO35WYc=; b=K49nyaWB4i7YNg/jgfmtyk98eStnRGDpDOTEn5kl0PDgwLvWMP4MR95NGndGDDG1h9 2vZBQQLFByQ1Sh6SS0Y+xwR81da6YwbEC71VmrY5t0yITJtdRXnkSjlSJcpj4SkayHku aYE+JKpvVz1mm3e9I4m7tpkEtymxcUYd0iwTQgpkcGIKau7MgtSYSV0ycqouqCmjtTGu +Nd1ldIxDGXVLK/JGWUw/GpMZg4DHl+oFNo9uDBsm5SNQsidWv0zNno3UHZyAu2jNytg dVVeEvl59uXdYhBHvvvVImG0w4fzIrxagz94z662Gt/I/TogpkCr1trye6v0Oij5+WBz IgCA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id i17si14376641ejo.365.2021.03.28.14.30.53; Sun, 28 Mar 2021 14:31:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231366AbhC1V3e (ORCPT + 99 others); Sun, 28 Mar 2021 17:29:34 -0400 Received: from clab.compulab.co.il ([66.147.238.35]:44316 "EHLO clab.compulab.co.il" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231228AbhC1V3S (ORCPT ); Sun, 28 Mar 2021 17:29:18 -0400 X-Greylist: delayed 1591 seconds by postgrey-1.27 at vger.kernel.org; Sun, 28 Mar 2021 17:29:17 EDT Received: from [37.142.126.90] (port=46476 helo=zimbra01.compulab.co.il) by clab.compulab.co.il with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94) (envelope-from ) id 1lQcYc-0033Oa-Ov; Sun, 28 Mar 2021 17:02:51 -0400 Received: from localhost (localhost [127.0.0.1]) by zimbra01.compulab.co.il (Postfix) with ESMTP id 982C1E81CB001; Mon, 29 Mar 2021 00:02:49 +0300 (IDT) Received: from zimbra01.compulab.co.il ([127.0.0.1]) by localhost (zimbra01.compulab.co.il [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id Jm5APFot9XNg; Mon, 29 Mar 2021 00:02:49 +0300 (IDT) Received: from localhost (localhost [127.0.0.1]) by zimbra01.compulab.co.il (Postfix) with ESMTP id 524A2E81CB017; Mon, 29 Mar 2021 00:02:49 +0300 (IDT) X-Virus-Scanned: amavisd-new at zimbra01.compulab.co.il Received: from zimbra01.compulab.co.il ([127.0.0.1]) by localhost (zimbra01.compulab.co.il [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id uOalATY9TEXk; Mon, 29 Mar 2021 00:02:49 +0300 (IDT) Received: from kkk.compulab.local (lifshitz-linux.compulab.local [192.168.11.10]) by zimbra01.compulab.co.il (Postfix) with ESMTP id 40FF9E81CB001; Mon, 29 Mar 2021 00:02:49 +0300 (IDT) From: Kirill Kapranov To: a.zummo@towertech.it, alexandre.belloni@bootlin.com, phdm@macqel.be, linux-rtc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Kirill Kapranov Subject: [PATCH 2/4] rtc: abx80x: Enable SQW output Date: Mon, 29 Mar 2021 00:02:30 +0300 Message-Id: <20210328210232.10395-3-kirill.kapranov@compulab.co.il> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20210328210232.10395-1-kirill.kapranov@compulab.co.il> References: <20210328210232.10395-1-kirill.kapranov@compulab.co.il> X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - clab.compulab.co.il X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - compulab.co.il X-Get-Message-Sender-Via: clab.compulab.co.il: mailgid no entry from get_recent_authed_mail_ips_entry X-Authenticated-Sender: clab.compulab.co.il: X-Source: X-Source-Args: X-Source-Dir: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The RTCs of the family are able to produce square wave output for RTC calibration purposes or for an external usage. Signed-off-by: Kirill Kapranov --- drivers/rtc/rtc-abx80x.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 9b0138d07232..153d89b56da9 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -51,6 +51,9 @@ #define ABX8XX_IRQ_AIE BIT(2) #define ABX8XX_IRQ_IM_1_4 (0x3 << 5) +#define ABX8XX_REG_SQW 0x13 +#define ABX8XX_SQW_MODE_BITS 5 + #define ABX8XX_REG_CD_TIMER_CTL 0x18 #define ABX8XX_REG_OSC 0x1c @@ -117,6 +120,15 @@ struct abx80x_priv { struct watchdog_device wdog; }; +union abx8xx_reg_sqw { + struct { + unsigned int sqws:5; + int:2; + unsigned int sqwe:2; + }; + int val; +} __packed; + static int abx80x_write_config_key(struct i2c_client *client, u8 key) { if (i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY, key) < 0) { @@ -486,9 +498,119 @@ static ssize_t oscillator_show(struct device *dev, static DEVICE_ATTR_RW(oscillator); +#define SQFS_COUNT (1 << ABX8XX_SQW_MODE_BITS) +/* The index of the array is the value to be written to the 'Square Wave Function + * Select' register to make the RTC generate the required square wave. + */ +static const char *const sqfs[SQFS_COUNT] = { + "1_century", "32768_Hz", "8192_Hz", "4096_Hz", + "2048_Hz", "1024_Hz", "512_Hz", "256_Hz", + "128_Hz", "64_Hz", "32_Hz", "16_Hz", + "8_Hz", "4_Hz", "2_Hz", "1_Hz", + "1/2_Hz", "1/4_Hz", "1/8_Hz", "1/16_Hz", + "1/32_Hz", "1_min", "16384_Hz", "100_Hz", + "1_hour", "1_day", "TIRQ", "nTIRQ", + "1_year", "1_Hz_to_Counters", "1/32_Hz_from_Acal", "1/8_Hz_from_Acal", +}; + +static const bool valid_for_rc_mode[SQFS_COUNT] = { + true, false, false, false, + false, false, false, false, + true, true, true, true, + true, true, true, true, + true, true, true, true, + true, true, false, false, + true, true, true, true, + true, true, true, true, +}; + +static int sqw_set(struct i2c_client *client, const char *buf) +{ + union abx8xx_reg_sqw reg_sqw; + int retval; + + reg_sqw.val = i2c_smbus_read_byte_data(client, ABX8XX_REG_SQW); + if (reg_sqw.val < 0) + goto err; + + if (sysfs_streq(buf, "none")) { + reg_sqw.sqwe = 0; + dev_info(&client->dev, "sqw output disabled\n"); + } else { + int idx = __sysfs_match_string(sqfs, SQFS_COUNT, buf); + + if (idx < 0) + return idx; + + if (abx80x_is_rc_mode(client) && !valid_for_rc_mode[idx]) + dev_warn(&client->dev, "sqw frequency %s valid only in xt mode\n", + sqfs[idx]); + + dev_info(&client->dev, "sqw output enabled @ %s\n", sqfs[idx]); + reg_sqw.sqwe = 1; + reg_sqw.sqws = idx; + } + + retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_SQW, reg_sqw.val); + if (retval < 0) + goto err; + + return 0; +err: + dev_err(&client->dev, "Failed to set SQW\n"); + return retval; + +} + +static ssize_t sqw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int retval; + + retval = sqw_set(to_i2c_client(dev->parent), buf); + if (retval) + return retval; + else + return count; +} + +static ssize_t sqw_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + union abx8xx_reg_sqw reg_sqw; + int len = 0; + int i; + + reg_sqw.val = i2c_smbus_read_byte_data(client, ABX8XX_REG_SQW); + if (reg_sqw.val < 0) { + dev_err(dev, "Failed to read SQW\n"); + sprintf(buf, "\n"); + return reg_sqw.val; + } + + if (reg_sqw.sqwe) + len += scnprintf(buf+len, PAGE_SIZE - len, "none "); + else + len += scnprintf(buf+len, PAGE_SIZE - len, "[none] "); + + for (i = 0; i < SQFS_COUNT; ++i) { + if (reg_sqw.sqwe && i == reg_sqw.sqws) + len += scnprintf(buf+len, PAGE_SIZE - len, "[%s] ", sqfs[i]); + else + len += scnprintf(buf+len, PAGE_SIZE - len, "%s ", sqfs[i]); + } + + return len; +} + +static DEVICE_ATTR_RW(sqw); + static struct attribute *rtc_calib_attrs[] = { &dev_attr_autocalibration.attr, &dev_attr_oscillator.attr, + &dev_attr_sqw.attr, NULL, }; @@ -686,6 +808,7 @@ static int abx80x_probe(struct i2c_client *client, unsigned int lot; unsigned int wafer; unsigned int uid; + const char *sqw_mode_name; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; @@ -800,6 +923,9 @@ static int abx80x_probe(struct i2c_client *client, abx80x_enable_trickle_charger(client, trickle_cfg); } + if (!of_property_read_string(np, "sqw", &sqw_mode_name)) + sqw_set(client, sqw_mode_name); + err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CD_TIMER_CTL, BIT(2)); if (err) -- 2.11.0