diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2006-04-11 01:54:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-11 09:18:46 -0400 |
commit | 8a95b252d194ea57c3d2c16ec2a25b1b70e36cad (patch) | |
tree | 6e1b3ca9cbb913905f6065545aed06574dfd6967 | |
parent | 389ed39b9711bbe5210d5e118e1f1af36ca88b7c (diff) |
[PATCH] RTC subsystem: DS1672 oscillator handling
* Always enable the oscillator when we set the time
* If the oscillator is disable when we probe the RTC report back a warning
to the user
* Added sysfs attribute to represent the state of the oscillator
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/rtc/rtc-ds1672.c | 61 |
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) | |||
72 | static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | 73 | static 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 | ||
125 | static 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 */ | ||
144 | static 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 | |||
161 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); | ||
162 | |||
123 | static struct rtc_class_ops ds1672_rtc_ops = { | 163 | static 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 = { | |||
162 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | 202 | static 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 | ||
207 | exit_detach: | 262 | exit_detach: |