lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Wed, 29 Nov 2017 16:15:22 +0530
From:   venkat.prashanth2498@...il.com
To:     a.zummo@...ertech.it, alexandre.belloni@...e-electrons.com
Cc:     rtc-linux@...glegroups.com, linux-kernel@...r.kernel.org,
        kumba@...too.org,
        Venkat Prashanth B U <venkat.prashanth2498@...il.com>
Subject: [PATCH] rtc: rtc-ds1683 Maxim/Dallas I2C compatible

From: Venkat Prashanth B U <venkat.prashanth2498@...il.com>

This is a patch to add support for
maxim/dallas I2C rtc ds1683 chip.

Signed-off-by: Venkat Prashanth B U <venkat.prashanth2498@...il.com>
---
 drivers/rtc/Kconfig      |   9 +++
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-ds1683.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 213 insertions(+)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e0e58f3..2528b79 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -294,6 +294,15 @@ config RTC_DRV_DS1672
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1672.

+config RTC_DRV_DS1683
+	tristate "Dallas/Maxim DS1683"
+	help
+	  If you say yes here you get support for the
+	  Dallas/Maxim DS1683 I2C timekeeping chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds1683.
+
 config RTC_DRV_HYM8563
 	tristate "Haoyu Microelectronics HYM8563"
 	depends on OF
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 0bf1fc0..a6f4419 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_RTC_DRV_DS1390)	+= rtc-ds1390.o
 obj-$(CONFIG_RTC_DRV_DS1511)	+= rtc-ds1511.o
 obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
+obj-$(CONFIG_RTC_DRV_DS1683)	+= rtc-ds1683.o
 obj-$(CONFIG_RTC_DRV_DS1685_FAMILY)	+= rtc-ds1685.o
 obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
 obj-$(CONFIG_RTC_DRV_DS2404)	+= rtc-ds2404.o
diff --git a/drivers/rtc/rtc-ds1683.c b/drivers/rtc/rtc-ds1683.c
index e69de29..7b6dac3 100644
--- a/drivers/rtc/rtc-ds1683.c
+++ b/drivers/rtc/rtc-ds1683.c
@@ -0,0 +1,203 @@
+/* rtc-ds1683.c
+ *
+ * Driver for Maxim/Dallas ds1683, I2C Compatible
+ * Real Time Clock
+ *
+ * Author : Venkat Prashanth B U <venkat.prashanth2498@...il.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/module.h>
+
+/* Registers */
+
+#define ds1683_REG_CNT_BASE	0
+#define ds1683_REG_EVENT	4
+
+#define ds1683_REG_CONTROL_EOSC	0x80
+
+static struct i2c_driver ds1683_driver;
+
+static int ds1683_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+	unsigned long time;
+	unsigned char addr = ds1683_REG_CNT_BASE;
+	unsigned char buf[4];
+
+	struct i2c_msg msgs[] = {
+		{	/* setup read pointer */
+			.addr = client->addr,
+			.len = 1,
+			.buf = &addr
+		},
+		{/* read date */
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 4,
+			.buf = buf
+		},
+	};
+
+	/* read date registers */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __func__);
+		return -EIO;
+	}
+
+	time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+	rtc_time_to_tm(time, tm);
+
+	return 0;
+}
+
+static int ds1683_set_mmss(struct i2c_client *client, unsigned long secs)
+{
+	int xfer;
+	unsigned char buf[6];
+
+	buf[0] = ds1683_REG_CNT_BASE;
+	buf[1] = secs & 0x000000FF;
+	buf[2] = (secs & 0x0000FF00) >> 8;
+	buf[3] = (secs & 0x00FF0000) >> 16;
+	buf[4] = (secs & 0xFF000000) >> 24;
+	buf[5] = 0;		/* set control reg to enable counting */
+
+	xfer = i2c_master_send(client, buf, 6);
+	if (xfer != 6) {
+		dev_err(&client->dev, "%s: send: %d\n", __func__, xfer);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int ds1683_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	return ds1683_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int ds1683_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+	return ds1683_set_mmss(to_i2c_client(dev), secs);
+}
+
+static int ds1683_get_control(struct i2c_client *client, u8 *status)
+{
+	unsigned char addr = ds1683_REG_CONTROL;
+
+	struct i2c_msg msgs[] = {
+		{/* setup read pointer */
+			.addr = client->addr,
+			.len = 1,
+			.buf = &addr
+		},
+		{/* read control */
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = status
+		},
+	};
+
+	/* read control register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* sysfs callback functions */
+static ssize_t show_control(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 control;
+	int err;
+
+	err = ds1683_get_control(client, &control);
+	if (err)
+		return err;
+
+	return sprintf(buf, "%s\n", (control & ds1683_REG_CONTROL_EOSC)
+		       ? "disabled" : "enabled");
+}
+
+static DEVICE_ATTR(control, 0444, show_control, NULL);
+
+static const struct rtc_class_ops ds1683_rtc_ops = {
+	.read_time = ds1683_rtc_read_time,
+	.set_mmss = ds1683_rtc_set_mmss,
+};
+
+static int ds1683_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int err = 0;
+	u8 control;
+	struct rtc_device *rtc;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -ENODEV;
+
+	rtc = devm_rtc_device_register(&client->dev, ds1683_driver.driver.name,
+			&ds1683_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	i2c_set_clientdata(client, rtc);
+
+	/* read control register */
+	err = ds1683_get_control(client, &control);
+	if (err)
+		dev_warn(&client->dev, "Unable to read the control register\n");
+
+	if (control & ds1683_REG_CONTROL_EOSC)
+		dev_warn(&client->dev, "Oscillator not enabled Set time to enable.\n");
+
+	/* Register sysfs hooks */
+	err = device_create_file(&client->dev, &dev_attr_control);
+	if (err)
+		dev_err(&client->dev, "Unable to create sysfs entry: %s\n",
+			dev_attr_control.attr.name);
+
+	return 0;
+}
+
+static const struct i2c_device_id ds1683_id[] = {
+	{ "ds1683", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ds1683_id);
+
+static const struct of_device_id ds1683_of_match[] = {
+	{ "dallas,ds1683", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ds1683_of_match);
+
+static struct i2c_driver ds1683_driver = {
+	.driver = {
+		   .name = "rtc-ds1683",
+		   .of_match_table = of_match_ptr(ds1683_of_match),
+	},
+	.probe = &ds1683_probe,
+	.id_table = ds1683_id,
+};
+
+module_i2c_driver(ds1683_driver);
+
+MODULE_AUTHOR("Venkat Prashanth B U <venkat.prashanth2498@...il.com>");
+MODULE_DESCRIPTION("Dallas/Maxim ds1683 I2C driver");
+MODULE_LICENSE("GPL");
--
1.9.1

Powered by blists - more mailing lists