xref: /linux/drivers/rtc/rtc-ds1672.c (revision 31b0cecb4042d2676fd48f09379a19bc8b16eadd)
169468320SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0
2edf1aaa3SAlessandro Zummo /*
3edf1aaa3SAlessandro Zummo  * An rtc/i2c driver for the Dallas DS1672
43903586aSAlessandro Zummo  * Copyright 2005-06 Tower Technologies
53903586aSAlessandro Zummo  *
63903586aSAlessandro Zummo  * Author: Alessandro Zummo <a.zummo@towertech.it>
7edf1aaa3SAlessandro Zummo  */
8edf1aaa3SAlessandro Zummo 
9edf1aaa3SAlessandro Zummo #include <linux/i2c.h>
10edf1aaa3SAlessandro Zummo #include <linux/rtc.h>
112113852bSPaul Gortmaker #include <linux/module.h>
12edf1aaa3SAlessandro Zummo 
13edf1aaa3SAlessandro Zummo /* Registers */
14edf1aaa3SAlessandro Zummo 
15edf1aaa3SAlessandro Zummo #define DS1672_REG_CNT_BASE	0
16edf1aaa3SAlessandro Zummo #define DS1672_REG_CONTROL	4
17edf1aaa3SAlessandro Zummo #define DS1672_REG_TRICKLE	5
18edf1aaa3SAlessandro Zummo 
193903586aSAlessandro Zummo #define DS1672_REG_CONTROL_EOSC	0x80
20edf1aaa3SAlessandro Zummo 
21edf1aaa3SAlessandro Zummo /*
22edf1aaa3SAlessandro Zummo  * In the routines that deal directly with the ds1672 hardware, we use
23edf1aaa3SAlessandro Zummo  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
24d1fbe695SAlexandre Belloni  * Time is set to UTC.
25edf1aaa3SAlessandro Zummo  */
267a5670c7SAlexandre Belloni static int ds1672_read_time(struct device *dev, struct rtc_time *tm)
27edf1aaa3SAlessandro Zummo {
287a5670c7SAlexandre Belloni 	struct i2c_client *client = to_i2c_client(dev);
29edf1aaa3SAlessandro Zummo 	unsigned long time;
3010e3efc1SAlexandre Belloni 	unsigned char addr = DS1672_REG_CONTROL;
31edf1aaa3SAlessandro Zummo 	unsigned char buf[4];
32edf1aaa3SAlessandro Zummo 
33edf1aaa3SAlessandro Zummo 	struct i2c_msg msgs[] = {
342bfc37dfSShubhrajyoti D 		{/* setup read ptr */
352bfc37dfSShubhrajyoti D 			.addr = client->addr,
362bfc37dfSShubhrajyoti D 			.len = 1,
372bfc37dfSShubhrajyoti D 			.buf = &addr
382bfc37dfSShubhrajyoti D 		},
392bfc37dfSShubhrajyoti D 		{/* read date */
402bfc37dfSShubhrajyoti D 			.addr = client->addr,
412bfc37dfSShubhrajyoti D 			.flags = I2C_M_RD,
4210e3efc1SAlexandre Belloni 			.len = 1,
432bfc37dfSShubhrajyoti D 			.buf = buf
442bfc37dfSShubhrajyoti D 		},
45edf1aaa3SAlessandro Zummo 	};
46edf1aaa3SAlessandro Zummo 
4710e3efc1SAlexandre Belloni 	/* read control register */
4810e3efc1SAlexandre Belloni 	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
4910e3efc1SAlexandre Belloni 		dev_warn(&client->dev, "Unable to read the control register\n");
5010e3efc1SAlexandre Belloni 		return -EIO;
5110e3efc1SAlexandre Belloni 	}
5210e3efc1SAlexandre Belloni 
5310e3efc1SAlexandre Belloni 	if (buf[0] & DS1672_REG_CONTROL_EOSC) {
5410e3efc1SAlexandre Belloni 		dev_warn(&client->dev, "Oscillator not enabled. Set time to enable.\n");
5510e3efc1SAlexandre Belloni 		return -EINVAL;
5610e3efc1SAlexandre Belloni 	}
5710e3efc1SAlexandre Belloni 
5810e3efc1SAlexandre Belloni 	addr = DS1672_REG_CNT_BASE;
5910e3efc1SAlexandre Belloni 	msgs[1].len = 4;
6010e3efc1SAlexandre Belloni 
61edf1aaa3SAlessandro Zummo 	/* read date registers */
62edf1aaa3SAlessandro Zummo 	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
632a4e2b87SHarvey Harrison 		dev_err(&client->dev, "%s: read error\n", __func__);
64edf1aaa3SAlessandro Zummo 		return -EIO;
65edf1aaa3SAlessandro Zummo 	}
66edf1aaa3SAlessandro Zummo 
67edf1aaa3SAlessandro Zummo 	dev_dbg(&client->dev,
6811966adcSJeff Garzik 		"%s: raw read data - counters=%02x,%02x,%02x,%02x\n",
692a4e2b87SHarvey Harrison 		__func__, buf[0], buf[1], buf[2], buf[3]);
70edf1aaa3SAlessandro Zummo 
71f0c04c27SColin Ian King 	time = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |
72f0c04c27SColin Ian King 	       (buf[1] << 8) | buf[0];
73edf1aaa3SAlessandro Zummo 
74520d6516SAlexandre Belloni 	rtc_time64_to_tm(time, tm);
75edf1aaa3SAlessandro Zummo 
76e3a76913SAlexandre Belloni 	dev_dbg(&client->dev, "%s: tm is %ptR\n", __func__, tm);
77edf1aaa3SAlessandro Zummo 
78edf1aaa3SAlessandro Zummo 	return 0;
79edf1aaa3SAlessandro Zummo }
80edf1aaa3SAlessandro Zummo 
81219219d9SAlexandre Belloni static int ds1672_set_time(struct device *dev, struct rtc_time *tm)
82edf1aaa3SAlessandro Zummo {
837a5670c7SAlexandre Belloni 	struct i2c_client *client = to_i2c_client(dev);
84edf1aaa3SAlessandro Zummo 	int xfer;
858a95b252SKumar Gala 	unsigned char buf[6];
86219219d9SAlexandre Belloni 	unsigned long secs = rtc_tm_to_time64(tm);
87edf1aaa3SAlessandro Zummo 
88edf1aaa3SAlessandro Zummo 	buf[0] = DS1672_REG_CNT_BASE;
89edf1aaa3SAlessandro Zummo 	buf[1] = secs & 0x000000FF;
90edf1aaa3SAlessandro Zummo 	buf[2] = (secs & 0x0000FF00) >> 8;
91edf1aaa3SAlessandro Zummo 	buf[3] = (secs & 0x00FF0000) >> 16;
92edf1aaa3SAlessandro Zummo 	buf[4] = (secs & 0xFF000000) >> 24;
938a95b252SKumar Gala 	buf[5] = 0;		/* set control reg to enable counting */
94edf1aaa3SAlessandro Zummo 
958a95b252SKumar Gala 	xfer = i2c_master_send(client, buf, 6);
968a95b252SKumar Gala 	if (xfer != 6) {
972a4e2b87SHarvey Harrison 		dev_err(&client->dev, "%s: send: %d\n", __func__, xfer);
98edf1aaa3SAlessandro Zummo 		return -EIO;
99edf1aaa3SAlessandro Zummo 	}
100edf1aaa3SAlessandro Zummo 
101edf1aaa3SAlessandro Zummo 	return 0;
102edf1aaa3SAlessandro Zummo }
103edf1aaa3SAlessandro Zummo 
104ff8371acSDavid Brownell static const struct rtc_class_ops ds1672_rtc_ops = {
1057a5670c7SAlexandre Belloni 	.read_time = ds1672_read_time,
106219219d9SAlexandre Belloni 	.set_time = ds1672_set_time,
107edf1aaa3SAlessandro Zummo };
108edf1aaa3SAlessandro Zummo 
1093f4a3322SStephen Kitt static int ds1672_probe(struct i2c_client *client)
110edf1aaa3SAlessandro Zummo {
111edf1aaa3SAlessandro Zummo 	int err = 0;
112edf1aaa3SAlessandro Zummo 	struct rtc_device *rtc;
113edf1aaa3SAlessandro Zummo 
1141716b0feSAlessandro Zummo 	dev_dbg(&client->dev, "%s\n", __func__);
115edf1aaa3SAlessandro Zummo 
1161716b0feSAlessandro Zummo 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
1171716b0feSAlessandro Zummo 		return -ENODEV;
118edf1aaa3SAlessandro Zummo 
119d1fbe695SAlexandre Belloni 	rtc = devm_rtc_allocate_device(&client->dev);
120d1fbe695SAlexandre Belloni 	if (IS_ERR(rtc))
121d1fbe695SAlexandre Belloni 		return PTR_ERR(rtc);
122d1fbe695SAlexandre Belloni 
123d1fbe695SAlexandre Belloni 	rtc->ops = &ds1672_rtc_ops;
124d1fbe695SAlexandre Belloni 	rtc->range_max = U32_MAX;
125d1fbe695SAlexandre Belloni 
126fdcfd854SBartosz Golaszewski 	err = devm_rtc_register_device(rtc);
127d1fbe695SAlexandre Belloni 	if (err)
128d1fbe695SAlexandre Belloni 		return err;
129edf1aaa3SAlessandro Zummo 
130edf1aaa3SAlessandro Zummo 	i2c_set_clientdata(client, rtc);
131edf1aaa3SAlessandro Zummo 
132edf1aaa3SAlessandro Zummo 	return 0;
133edf1aaa3SAlessandro Zummo }
134edf1aaa3SAlessandro Zummo 
13545a63518SArvind Yadav static const struct i2c_device_id ds1672_id[] = {
136fe102c71SAlessandro Zummo 	{ "ds1672", 0 },
137fe102c71SAlessandro Zummo 	{ }
138fe102c71SAlessandro Zummo };
1398ad0f5b6SAxel Lin MODULE_DEVICE_TABLE(i2c, ds1672_id);
140fe102c71SAlessandro Zummo 
141fb38b5daSAlexandre Belloni static const __maybe_unused struct of_device_id ds1672_of_match[] = {
14223194ac0SJavier Martinez Canillas 	{ .compatible = "dallas,ds1672" },
14323194ac0SJavier Martinez Canillas 	{ }
14423194ac0SJavier Martinez Canillas };
14523194ac0SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ds1672_of_match);
14623194ac0SJavier Martinez Canillas 
1471716b0feSAlessandro Zummo static struct i2c_driver ds1672_driver = {
1481716b0feSAlessandro Zummo 	.driver = {
1491716b0feSAlessandro Zummo 		   .name = "rtc-ds1672",
15023194ac0SJavier Martinez Canillas 		   .of_match_table = of_match_ptr(ds1672_of_match),
1511716b0feSAlessandro Zummo 	},
152*31b0cecbSUwe Kleine-König 	.probe = ds1672_probe,
153fe102c71SAlessandro Zummo 	.id_table = ds1672_id,
1541716b0feSAlessandro Zummo };
1551716b0feSAlessandro Zummo 
1560abc9201SAxel Lin module_i2c_driver(ds1672_driver);
157edf1aaa3SAlessandro Zummo 
158edf1aaa3SAlessandro Zummo MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
159edf1aaa3SAlessandro Zummo MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver");
160edf1aaa3SAlessandro Zummo MODULE_LICENSE("GPL");
161