diff options
Diffstat (limited to 'drivers/rtc/rtc-ds1672.c')
| -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); |
