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 /drivers/rtc | |
| 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>
Diffstat (limited to 'drivers/rtc')
| -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: |
