1 /* 2 * An rtc/i2c driver for the Dallas DS1672 3 * Copyright 2005 Alessandro Zummo 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/i2c.h> 12 #include <linux/rtc.h> 13 14 #define DRV_VERSION "0.2" 15 16 /* Addresses to scan: none. This chip cannot be detected. */ 17 static unsigned short normal_i2c[] = { I2C_CLIENT_END }; 18 19 /* Insmod parameters */ 20 I2C_CLIENT_INSMOD; 21 22 /* Registers */ 23 24 #define DS1672_REG_CNT_BASE 0 25 #define DS1672_REG_CONTROL 4 26 #define DS1672_REG_TRICKLE 5 27 28 29 /* Prototypes */ 30 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); 31 32 /* 33 * In the routines that deal directly with the ds1672 hardware, we use 34 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch 35 * Epoch is initialized as 2000. Time is set to UTC. 36 */ 37 static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) 38 { 39 unsigned long time; 40 unsigned char addr = DS1672_REG_CNT_BASE; 41 unsigned char buf[4]; 42 43 struct i2c_msg msgs[] = { 44 { client->addr, 0, 1, &addr }, /* setup read ptr */ 45 { client->addr, I2C_M_RD, 4, buf }, /* read date */ 46 }; 47 48 /* read date registers */ 49 if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { 50 dev_err(&client->dev, "%s: read error\n", __FUNCTION__); 51 return -EIO; 52 } 53 54 dev_dbg(&client->dev, 55 "%s: raw read data - counters=%02x,%02x,%02x,%02x\n" 56 __FUNCTION__, 57 buf[0], buf[1], buf[2], buf[3]); 58 59 time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; 60 61 rtc_time_to_tm(time, tm); 62 63 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " 64 "mday=%d, mon=%d, year=%d, wday=%d\n", 65 __FUNCTION__, 66 tm->tm_sec, tm->tm_min, tm->tm_hour, 67 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 68 69 return 0; 70 } 71 72 static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) 73 { 74 int xfer; 75 unsigned char buf[5]; 76 77 buf[0] = DS1672_REG_CNT_BASE; 78 buf[1] = secs & 0x000000FF; 79 buf[2] = (secs & 0x0000FF00) >> 8; 80 buf[3] = (secs & 0x00FF0000) >> 16; 81 buf[4] = (secs & 0xFF000000) >> 24; 82 83 xfer = i2c_master_send(client, buf, 5); 84 if (xfer != 5) { 85 dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer); 86 return -EIO; 87 } 88 89 return 0; 90 } 91 92 static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm) 93 { 94 unsigned long secs; 95 96 dev_dbg(&client->dev, 97 "%s: secs=%d, mins=%d, hours=%d, ", 98 "mday=%d, mon=%d, year=%d, wday=%d\n", 99 __FUNCTION__, 100 tm->tm_sec, tm->tm_min, tm->tm_hour, 101 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 102 103 rtc_tm_to_time(tm, &secs); 104 105 return ds1672_set_mmss(client, secs); 106 } 107 108 static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm) 109 { 110 return ds1672_get_datetime(to_i2c_client(dev), tm); 111 } 112 113 static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm) 114 { 115 return ds1672_set_datetime(to_i2c_client(dev), tm); 116 } 117 118 static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs) 119 { 120 return ds1672_set_mmss(to_i2c_client(dev), secs); 121 } 122 123 static struct rtc_class_ops ds1672_rtc_ops = { 124 .read_time = ds1672_rtc_read_time, 125 .set_time = ds1672_rtc_set_time, 126 .set_mmss = ds1672_rtc_set_mmss, 127 }; 128 129 static int ds1672_attach(struct i2c_adapter *adapter) 130 { 131 dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); 132 return i2c_probe(adapter, &addr_data, ds1672_probe); 133 } 134 135 static int ds1672_detach(struct i2c_client *client) 136 { 137 int err; 138 struct rtc_device *rtc = i2c_get_clientdata(client); 139 140 dev_dbg(&client->dev, "%s\n", __FUNCTION__); 141 142 if (rtc) 143 rtc_device_unregister(rtc); 144 145 if ((err = i2c_detach_client(client))) 146 return err; 147 148 kfree(client); 149 150 return 0; 151 } 152 153 static struct i2c_driver ds1672_driver = { 154 .driver = { 155 .name = "ds1672", 156 }, 157 .id = I2C_DRIVERID_DS1672, 158 .attach_adapter = &ds1672_attach, 159 .detach_client = &ds1672_detach, 160 }; 161 162 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) 163 { 164 int err = 0; 165 struct i2c_client *client; 166 struct rtc_device *rtc; 167 168 dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); 169 170 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { 171 err = -ENODEV; 172 goto exit; 173 } 174 175 if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { 176 err = -ENOMEM; 177 goto exit; 178 } 179 180 /* I2C client */ 181 client->addr = address; 182 client->driver = &ds1672_driver; 183 client->adapter = adapter; 184 185 strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); 186 187 /* Inform the i2c layer */ 188 if ((err = i2c_attach_client(client))) 189 goto exit_kfree; 190 191 dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); 192 193 rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, 194 &ds1672_rtc_ops, THIS_MODULE); 195 196 if (IS_ERR(rtc)) { 197 err = PTR_ERR(rtc); 198 dev_err(&client->dev, 199 "unable to register the class device\n"); 200 goto exit_detach; 201 } 202 203 i2c_set_clientdata(client, rtc); 204 205 return 0; 206 207 exit_detach: 208 i2c_detach_client(client); 209 210 exit_kfree: 211 kfree(client); 212 213 exit: 214 return err; 215 } 216 217 static int __init ds1672_init(void) 218 { 219 return i2c_add_driver(&ds1672_driver); 220 } 221 222 static void __exit ds1672_exit(void) 223 { 224 i2c_del_driver(&ds1672_driver); 225 } 226 227 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); 228 MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); 229 MODULE_LICENSE("GPL"); 230 MODULE_VERSION(DRV_VERSION); 231 232 module_init(ds1672_init); 233 module_exit(ds1672_exit); 234