aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-ds1672.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-ds1672.c')
-rw-r--r--drivers/rtc/rtc-ds1672.c61
1 files changed, 58 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 358695a416f3..6d2dc7060652 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -23,6 +23,7 @@ I2C_CLIENT_INSMOD;
23 23
24#define DS1672_REG_CNT_BASE 0 24#define DS1672_REG_CNT_BASE 0
25#define DS1672_REG_CONTROL 4 25#define DS1672_REG_CONTROL 4
26#define DS1672_REG_CONTROL_EOSC 0x80
26#define DS1672_REG_TRICKLE 5 27#define DS1672_REG_TRICKLE 5
27 28
28 29
@@ -72,16 +73,17 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
72static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) 73static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
73{ 74{
74 int xfer; 75 int xfer;
75 unsigned char buf[5]; 76 unsigned char buf[6];
76 77
77 buf[0] = DS1672_REG_CNT_BASE; 78 buf[0] = DS1672_REG_CNT_BASE;
78 buf[1] = secs & 0x000000FF; 79 buf[1] = secs & 0x000000FF;
79 buf[2] = (secs & 0x0000FF00) >> 8; 80 buf[2] = (secs & 0x0000FF00) >> 8;
80 buf[3] = (secs & 0x00FF0000) >> 16; 81 buf[3] = (secs & 0x00FF0000) >> 16;
81 buf[4] = (secs & 0xFF000000) >> 24; 82 buf[4] = (secs & 0xFF000000) >> 24;
83 buf[5] = 0; /* set control reg to enable counting */
82 84
83 xfer = i2c_master_send(client, buf, 5); 85 xfer = i2c_master_send(client, buf, 6);
84 if (xfer != 5) { 86 if (xfer != 6) {
85 dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer); 87 dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
86 return -EIO; 88 return -EIO;
87 } 89 }
@@ -120,6 +122,44 @@ static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs)
120 return ds1672_set_mmss(to_i2c_client(dev), secs); 122 return ds1672_set_mmss(to_i2c_client(dev), secs);
121} 123}
122 124
125static int ds1672_get_control(struct i2c_client *client, u8 *status)
126{
127 unsigned char addr = DS1672_REG_CONTROL;
128
129 struct i2c_msg msgs[] = {
130 { client->addr, 0, 1, &addr }, /* setup read ptr */
131 { client->addr, I2C_M_RD, 1, status }, /* read control */
132 };
133
134 /* read control register */
135 if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
136 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
137 return -EIO;
138 }
139
140 return 0;
141}
142
143/* following are the sysfs callback functions */
144static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
145{
146 struct i2c_client *client = to_i2c_client(dev);
147 char *state = "enabled";
148 u8 control;
149 int err;
150
151 err = ds1672_get_control(client, &control);
152 if (err)
153 return err;
154
155 if (control & DS1672_REG_CONTROL_EOSC)
156 state = "disabled";
157
158 return sprintf(buf, "%s\n", state);
159}
160
161static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
162
123static struct rtc_class_ops ds1672_rtc_ops = { 163static struct rtc_class_ops ds1672_rtc_ops = {
124 .read_time = ds1672_rtc_read_time, 164 .read_time = ds1672_rtc_read_time,
125 .set_time = ds1672_rtc_set_time, 165 .set_time = ds1672_rtc_set_time,
@@ -162,6 +202,7 @@ static struct i2c_driver ds1672_driver = {
162static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) 202static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
163{ 203{
164 int err = 0; 204 int err = 0;
205 u8 control;
165 struct i2c_client *client; 206 struct i2c_client *client;
166 struct rtc_device *rtc; 207 struct rtc_device *rtc;
167 208
@@ -202,6 +243,20 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
202 243
203 i2c_set_clientdata(client, rtc); 244 i2c_set_clientdata(client, rtc);
204 245
246 /* read control register */
247 err = ds1672_get_control(client, &control);
248 if (err) {
249 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
250 goto exit_detach;
251 }
252
253 if (control & DS1672_REG_CONTROL_EOSC)
254 dev_warn(&client->dev, "Oscillator not enabled. "
255 "Set time to enable.\n");
256
257 /* Register sysfs hooks */
258 device_create_file(&client->dev, &dev_attr_control);
259
205 return 0; 260 return 0;
206 261
207exit_detach: 262exit_detach: