diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-ds1672.c | 114 |
1 files changed, 34 insertions, 80 deletions
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 6fa4556f5f5c..341d7a5b45a2 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -9,17 +9,10 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
15 | 14 | ||
16 | #define DRV_VERSION "0.3" | 15 | #define DRV_VERSION "0.4" |
17 | |||
18 | /* Addresses to scan: none. This chip cannot be detected. */ | ||
19 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
20 | |||
21 | /* Insmod parameters */ | ||
22 | I2C_CLIENT_INSMOD; | ||
23 | 16 | ||
24 | /* Registers */ | 17 | /* Registers */ |
25 | 18 | ||
@@ -29,8 +22,7 @@ I2C_CLIENT_INSMOD; | |||
29 | 22 | ||
30 | #define DS1672_REG_CONTROL_EOSC 0x80 | 23 | #define DS1672_REG_CONTROL_EOSC 0x80 |
31 | 24 | ||
32 | /* Prototypes */ | 25 | static struct i2c_driver ds1672_driver; |
33 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); | ||
34 | 26 | ||
35 | /* | 27 | /* |
36 | * In the routines that deal directly with the ds1672 hardware, we use | 28 | * In the routines that deal directly with the ds1672 hardware, we use |
@@ -44,8 +36,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
44 | unsigned char buf[4]; | 36 | unsigned char buf[4]; |
45 | 37 | ||
46 | struct i2c_msg msgs[] = { | 38 | struct i2c_msg msgs[] = { |
47 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 39 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
48 | { client->addr, I2C_M_RD, 4, buf }, /* read date */ | 40 | {client->addr, I2C_M_RD, 4, buf}, /* read date */ |
49 | }; | 41 | }; |
50 | 42 | ||
51 | /* read date registers */ | 43 | /* read date registers */ |
@@ -80,7 +72,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | |||
80 | buf[2] = (secs & 0x0000FF00) >> 8; | 72 | buf[2] = (secs & 0x0000FF00) >> 8; |
81 | buf[3] = (secs & 0x00FF0000) >> 16; | 73 | buf[3] = (secs & 0x00FF0000) >> 16; |
82 | buf[4] = (secs & 0xFF000000) >> 24; | 74 | buf[4] = (secs & 0xFF000000) >> 24; |
83 | buf[5] = 0; /* set control reg to enable counting */ | 75 | buf[5] = 0; /* set control reg to enable counting */ |
84 | 76 | ||
85 | xfer = i2c_master_send(client, buf, 6); | 77 | xfer = i2c_master_send(client, buf, 6); |
86 | if (xfer != 6) { | 78 | if (xfer != 6) { |
@@ -127,8 +119,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
127 | unsigned char addr = DS1672_REG_CONTROL; | 119 | unsigned char addr = DS1672_REG_CONTROL; |
128 | 120 | ||
129 | struct i2c_msg msgs[] = { | 121 | struct i2c_msg msgs[] = { |
130 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 122 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
131 | { client->addr, I2C_M_RD, 1, status }, /* read control */ | 123 | {client->addr, I2C_M_RD, 1, status}, /* read control */ |
132 | }; | 124 | }; |
133 | 125 | ||
134 | /* read control register */ | 126 | /* read control register */ |
@@ -141,7 +133,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
141 | } | 133 | } |
142 | 134 | ||
143 | /* following are the sysfs callback functions */ | 135 | /* following are the sysfs callback functions */ |
144 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf) | 136 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, |
137 | char *buf) | ||
145 | { | 138 | { |
146 | struct i2c_client *client = to_i2c_client(dev); | 139 | struct i2c_client *client = to_i2c_client(dev); |
147 | u8 control; | 140 | u8 control; |
@@ -152,85 +145,46 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c | |||
152 | return err; | 145 | return err; |
153 | 146 | ||
154 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) | 147 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) |
155 | ? "disabled" : "enabled"); | 148 | ? "disabled" : "enabled"); |
156 | } | 149 | } |
150 | |||
157 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); | 151 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); |
158 | 152 | ||
159 | static const struct rtc_class_ops ds1672_rtc_ops = { | 153 | static const struct rtc_class_ops ds1672_rtc_ops = { |
160 | .read_time = ds1672_rtc_read_time, | 154 | .read_time = ds1672_rtc_read_time, |
161 | .set_time = ds1672_rtc_set_time, | 155 | .set_time = ds1672_rtc_set_time, |
162 | .set_mmss = ds1672_rtc_set_mmss, | 156 | .set_mmss = ds1672_rtc_set_mmss, |
163 | }; | 157 | }; |
164 | 158 | ||
165 | static int ds1672_attach(struct i2c_adapter *adapter) | 159 | static int ds1672_remove(struct i2c_client *client) |
166 | { | 160 | { |
167 | return i2c_probe(adapter, &addr_data, ds1672_probe); | ||
168 | } | ||
169 | |||
170 | static int ds1672_detach(struct i2c_client *client) | ||
171 | { | ||
172 | int err; | ||
173 | struct rtc_device *rtc = i2c_get_clientdata(client); | 161 | struct rtc_device *rtc = i2c_get_clientdata(client); |
174 | 162 | ||
175 | if (rtc) | 163 | if (rtc) |
176 | rtc_device_unregister(rtc); | 164 | rtc_device_unregister(rtc); |
177 | 165 | ||
178 | if ((err = i2c_detach_client(client))) | ||
179 | return err; | ||
180 | |||
181 | kfree(client); | ||
182 | |||
183 | return 0; | 166 | return 0; |
184 | } | 167 | } |
185 | 168 | ||
186 | static struct i2c_driver ds1672_driver = { | 169 | static int ds1672_probe(struct i2c_client *client, |
187 | .driver = { | 170 | const struct i2c_device_id *id) |
188 | .name = "ds1672", | ||
189 | }, | ||
190 | .id = I2C_DRIVERID_DS1672, | ||
191 | .attach_adapter = &ds1672_attach, | ||
192 | .detach_client = &ds1672_detach, | ||
193 | }; | ||
194 | |||
195 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | ||
196 | { | 171 | { |
197 | int err = 0; | 172 | int err = 0; |
198 | u8 control; | 173 | u8 control; |
199 | struct i2c_client *client; | ||
200 | struct rtc_device *rtc; | 174 | struct rtc_device *rtc; |
201 | 175 | ||
202 | dev_dbg(&adapter->dev, "%s\n", __func__); | 176 | dev_dbg(&client->dev, "%s\n", __func__); |
203 | 177 | ||
204 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 178 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
205 | err = -ENODEV; | 179 | return -ENODEV; |
206 | goto exit; | ||
207 | } | ||
208 | |||
209 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
210 | err = -ENOMEM; | ||
211 | goto exit; | ||
212 | } | ||
213 | |||
214 | /* I2C client */ | ||
215 | client->addr = address; | ||
216 | client->driver = &ds1672_driver; | ||
217 | client->adapter = adapter; | ||
218 | |||
219 | strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); | ||
220 | |||
221 | /* Inform the i2c layer */ | ||
222 | if ((err = i2c_attach_client(client))) | ||
223 | goto exit_kfree; | ||
224 | 180 | ||
225 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 181 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
226 | 182 | ||
227 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, | 183 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, |
228 | &ds1672_rtc_ops, THIS_MODULE); | 184 | &ds1672_rtc_ops, THIS_MODULE); |
229 | 185 | ||
230 | if (IS_ERR(rtc)) { | 186 | if (IS_ERR(rtc)) |
231 | err = PTR_ERR(rtc); | 187 | return PTR_ERR(rtc); |
232 | goto exit_detach; | ||
233 | } | ||
234 | 188 | ||
235 | i2c_set_clientdata(client, rtc); | 189 | i2c_set_clientdata(client, rtc); |
236 | 190 | ||
@@ -241,7 +195,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
241 | 195 | ||
242 | if (control & DS1672_REG_CONTROL_EOSC) | 196 | if (control & DS1672_REG_CONTROL_EOSC) |
243 | dev_warn(&client->dev, "Oscillator not enabled. " | 197 | dev_warn(&client->dev, "Oscillator not enabled. " |
244 | "Set time to enable.\n"); | 198 | "Set time to enable.\n"); |
245 | 199 | ||
246 | /* Register sysfs hooks */ | 200 | /* Register sysfs hooks */ |
247 | err = device_create_file(&client->dev, &dev_attr_control); | 201 | err = device_create_file(&client->dev, &dev_attr_control); |
@@ -250,19 +204,19 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
250 | 204 | ||
251 | return 0; | 205 | return 0; |
252 | 206 | ||
253 | exit_devreg: | 207 | exit_devreg: |
254 | rtc_device_unregister(rtc); | 208 | rtc_device_unregister(rtc); |
255 | |||
256 | exit_detach: | ||
257 | i2c_detach_client(client); | ||
258 | |||
259 | exit_kfree: | ||
260 | kfree(client); | ||
261 | |||
262 | exit: | ||
263 | return err; | 209 | return err; |
264 | } | 210 | } |
265 | 211 | ||
212 | static struct i2c_driver ds1672_driver = { | ||
213 | .driver = { | ||
214 | .name = "rtc-ds1672", | ||
215 | }, | ||
216 | .probe = &ds1672_probe, | ||
217 | .remove = &ds1672_remove, | ||
218 | }; | ||
219 | |||
266 | static int __init ds1672_init(void) | 220 | static int __init ds1672_init(void) |
267 | { | 221 | { |
268 | return i2c_add_driver(&ds1672_driver); | 222 | return i2c_add_driver(&ds1672_driver); |