diff options
Diffstat (limited to 'drivers/rtc/rtc-ds1672.c')
-rw-r--r-- | drivers/rtc/rtc-ds1672.c | 127 |
1 files changed, 36 insertions, 91 deletions
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index b1ebca099b0d..e9e8d02743ee 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -1,12 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * An rtc/i2c driver for the Dallas DS1672 | 3 | * An rtc/i2c driver for the Dallas DS1672 |
3 | * Copyright 2005-06 Tower Technologies | 4 | * Copyright 2005-06 Tower Technologies |
4 | * | 5 | * |
5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | 6 | * Author: Alessandro Zummo <a.zummo@towertech.it> |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 7 | */ |
11 | 8 | ||
12 | #include <linux/i2c.h> | 9 | #include <linux/i2c.h> |
@@ -21,17 +18,16 @@ | |||
21 | 18 | ||
22 | #define DS1672_REG_CONTROL_EOSC 0x80 | 19 | #define DS1672_REG_CONTROL_EOSC 0x80 |
23 | 20 | ||
24 | static struct i2c_driver ds1672_driver; | ||
25 | |||
26 | /* | 21 | /* |
27 | * In the routines that deal directly with the ds1672 hardware, we use | 22 | * In the routines that deal directly with the ds1672 hardware, we use |
28 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch | 23 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch |
29 | * Epoch is initialized as 2000. Time is set to UTC. | 24 | * Time is set to UTC. |
30 | */ | 25 | */ |
31 | static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | 26 | static int ds1672_read_time(struct device *dev, struct rtc_time *tm) |
32 | { | 27 | { |
28 | struct i2c_client *client = to_i2c_client(dev); | ||
33 | unsigned long time; | 29 | unsigned long time; |
34 | unsigned char addr = DS1672_REG_CNT_BASE; | 30 | unsigned char addr = DS1672_REG_CONTROL; |
35 | unsigned char buf[4]; | 31 | unsigned char buf[4]; |
36 | 32 | ||
37 | struct i2c_msg msgs[] = { | 33 | struct i2c_msg msgs[] = { |
@@ -43,11 +39,25 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
43 | {/* read date */ | 39 | {/* read date */ |
44 | .addr = client->addr, | 40 | .addr = client->addr, |
45 | .flags = I2C_M_RD, | 41 | .flags = I2C_M_RD, |
46 | .len = 4, | 42 | .len = 1, |
47 | .buf = buf | 43 | .buf = buf |
48 | }, | 44 | }, |
49 | }; | 45 | }; |
50 | 46 | ||
47 | /* read control register */ | ||
48 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | ||
49 | dev_warn(&client->dev, "Unable to read the control register\n"); | ||
50 | return -EIO; | ||
51 | } | ||
52 | |||
53 | if (buf[0] & DS1672_REG_CONTROL_EOSC) { | ||
54 | dev_warn(&client->dev, "Oscillator not enabled. Set time to enable.\n"); | ||
55 | return -EINVAL; | ||
56 | } | ||
57 | |||
58 | addr = DS1672_REG_CNT_BASE; | ||
59 | msgs[1].len = 4; | ||
60 | |||
51 | /* read date registers */ | 61 | /* read date registers */ |
52 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | 62 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { |
53 | dev_err(&client->dev, "%s: read error\n", __func__); | 63 | dev_err(&client->dev, "%s: read error\n", __func__); |
@@ -61,20 +71,19 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
61 | time = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | | 71 | time = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | |
62 | (buf[1] << 8) | buf[0]; | 72 | (buf[1] << 8) | buf[0]; |
63 | 73 | ||
64 | rtc_time_to_tm(time, tm); | 74 | rtc_time64_to_tm(time, tm); |
65 | 75 | ||
66 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | 76 | dev_dbg(&client->dev, "%s: tm is %ptR\n", __func__, tm); |
67 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
68 | __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
69 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
70 | 77 | ||
71 | return 0; | 78 | return 0; |
72 | } | 79 | } |
73 | 80 | ||
74 | static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | 81 | static int ds1672_set_time(struct device *dev, struct rtc_time *tm) |
75 | { | 82 | { |
83 | struct i2c_client *client = to_i2c_client(dev); | ||
76 | int xfer; | 84 | int xfer; |
77 | unsigned char buf[6]; | 85 | unsigned char buf[6]; |
86 | unsigned long secs = rtc_tm_to_time64(tm); | ||
78 | 87 | ||
79 | buf[0] = DS1672_REG_CNT_BASE; | 88 | buf[0] = DS1672_REG_CNT_BASE; |
80 | buf[1] = secs & 0x000000FF; | 89 | buf[1] = secs & 0x000000FF; |
@@ -92,71 +101,15 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | |||
92 | return 0; | 101 | return 0; |
93 | } | 102 | } |
94 | 103 | ||
95 | static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
96 | { | ||
97 | return ds1672_get_datetime(to_i2c_client(dev), tm); | ||
98 | } | ||
99 | |||
100 | static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
101 | { | ||
102 | return ds1672_set_mmss(to_i2c_client(dev), secs); | ||
103 | } | ||
104 | |||
105 | static int ds1672_get_control(struct i2c_client *client, u8 *status) | ||
106 | { | ||
107 | unsigned char addr = DS1672_REG_CONTROL; | ||
108 | |||
109 | struct i2c_msg msgs[] = { | ||
110 | {/* setup read ptr */ | ||
111 | .addr = client->addr, | ||
112 | .len = 1, | ||
113 | .buf = &addr | ||
114 | }, | ||
115 | {/* read control */ | ||
116 | .addr = client->addr, | ||
117 | .flags = I2C_M_RD, | ||
118 | .len = 1, | ||
119 | .buf = status | ||
120 | }, | ||
121 | }; | ||
122 | |||
123 | /* read control register */ | ||
124 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | ||
125 | dev_err(&client->dev, "%s: read error\n", __func__); | ||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | /* following are the sysfs callback functions */ | ||
133 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, | ||
134 | char *buf) | ||
135 | { | ||
136 | struct i2c_client *client = to_i2c_client(dev); | ||
137 | u8 control; | ||
138 | int err; | ||
139 | |||
140 | err = ds1672_get_control(client, &control); | ||
141 | if (err) | ||
142 | return err; | ||
143 | |||
144 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) | ||
145 | ? "disabled" : "enabled"); | ||
146 | } | ||
147 | |||
148 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); | ||
149 | |||
150 | static const struct rtc_class_ops ds1672_rtc_ops = { | 104 | static const struct rtc_class_ops ds1672_rtc_ops = { |
151 | .read_time = ds1672_rtc_read_time, | 105 | .read_time = ds1672_read_time, |
152 | .set_mmss = ds1672_rtc_set_mmss, | 106 | .set_time = ds1672_set_time, |
153 | }; | 107 | }; |
154 | 108 | ||
155 | static int ds1672_probe(struct i2c_client *client, | 109 | static int ds1672_probe(struct i2c_client *client, |
156 | const struct i2c_device_id *id) | 110 | const struct i2c_device_id *id) |
157 | { | 111 | { |
158 | int err = 0; | 112 | int err = 0; |
159 | u8 control; | ||
160 | struct rtc_device *rtc; | 113 | struct rtc_device *rtc; |
161 | 114 | ||
162 | dev_dbg(&client->dev, "%s\n", __func__); | 115 | dev_dbg(&client->dev, "%s\n", __func__); |
@@ -164,29 +117,21 @@ static int ds1672_probe(struct i2c_client *client, | |||
164 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | 117 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
165 | return -ENODEV; | 118 | return -ENODEV; |
166 | 119 | ||
167 | rtc = devm_rtc_device_register(&client->dev, ds1672_driver.driver.name, | 120 | rtc = devm_rtc_allocate_device(&client->dev); |
168 | &ds1672_rtc_ops, THIS_MODULE); | ||
169 | |||
170 | if (IS_ERR(rtc)) | 121 | if (IS_ERR(rtc)) |
171 | return PTR_ERR(rtc); | 122 | return PTR_ERR(rtc); |
172 | 123 | ||
173 | i2c_set_clientdata(client, rtc); | 124 | rtc->ops = &ds1672_rtc_ops; |
125 | rtc->range_max = U32_MAX; | ||
174 | 126 | ||
175 | /* read control register */ | 127 | err = rtc_register_device(rtc); |
176 | err = ds1672_get_control(client, &control); | 128 | if (err) |
177 | if (err) { | 129 | return err; |
178 | dev_warn(&client->dev, "Unable to read the control register\n"); | ||
179 | } | ||
180 | 130 | ||
181 | if (control & DS1672_REG_CONTROL_EOSC) | 131 | if (IS_ERR(rtc)) |
182 | dev_warn(&client->dev, "Oscillator not enabled. " | 132 | return PTR_ERR(rtc); |
183 | "Set time to enable.\n"); | ||
184 | 133 | ||
185 | /* Register sysfs hooks */ | 134 | i2c_set_clientdata(client, rtc); |
186 | err = device_create_file(&client->dev, &dev_attr_control); | ||
187 | if (err) | ||
188 | dev_err(&client->dev, "Unable to create sysfs entry: %s\n", | ||
189 | dev_attr_control.attr.name); | ||
190 | 135 | ||
191 | return 0; | 136 | return 0; |
192 | } | 137 | } |