1 /* 2 * w1_ds2408.c - w1 family 29 (DS2408) driver 3 * 4 * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com> 5 * 6 * This source code is licensed under the GNU General Public License, 7 * Version 2. See the file COPYING for more details. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/moduleparam.h> 13 #include <linux/device.h> 14 #include <linux/types.h> 15 #include <linux/delay.h> 16 #include <linux/slab.h> 17 18 #include <linux/w1.h> 19 20 #define W1_FAMILY_DS2408 0x29 21 22 #define W1_F29_RETRIES 3 23 24 #define W1_F29_REG_LOGIG_STATE 0x88 /* R */ 25 #define W1_F29_REG_OUTPUT_LATCH_STATE 0x89 /* R */ 26 #define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A /* R */ 27 #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */ 28 #define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C /* RW */ 29 #define W1_F29_REG_CONTROL_AND_STATUS 0x8D /* RW */ 30 31 #define W1_F29_FUNC_READ_PIO_REGS 0xF0 32 #define W1_F29_FUNC_CHANN_ACCESS_READ 0xF5 33 #define W1_F29_FUNC_CHANN_ACCESS_WRITE 0x5A 34 /* also used to write the control/status reg (0x8D): */ 35 #define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC 36 #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3 37 38 #define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA 39 40 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) 41 { 42 u8 wrbuf[3]; 43 dev_dbg(&sl->dev, 44 "Reading with slave: %p, reg addr: %0#4x, buff addr: %p", 45 sl, (unsigned int)address, buf); 46 47 if (!buf) 48 return -EINVAL; 49 50 mutex_lock(&sl->master->bus_mutex); 51 dev_dbg(&sl->dev, "mutex locked"); 52 53 if (w1_reset_select_slave(sl)) { 54 mutex_unlock(&sl->master->bus_mutex); 55 return -EIO; 56 } 57 58 wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS; 59 wrbuf[1] = address; 60 wrbuf[2] = 0; 61 w1_write_block(sl->master, wrbuf, 3); 62 *buf = w1_read_8(sl->master); 63 64 mutex_unlock(&sl->master->bus_mutex); 65 dev_dbg(&sl->dev, "mutex unlocked"); 66 return 1; 67 } 68 69 static ssize_t state_read(struct file *filp, struct kobject *kobj, 70 struct bin_attribute *bin_attr, char *buf, loff_t off, 71 size_t count) 72 { 73 dev_dbg(&kobj_to_w1_slave(kobj)->dev, 74 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", 75 bin_attr->attr.name, kobj, (unsigned int)off, count, buf); 76 if (count != 1 || off != 0) 77 return -EFAULT; 78 return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf); 79 } 80 81 static ssize_t output_read(struct file *filp, struct kobject *kobj, 82 struct bin_attribute *bin_attr, char *buf, 83 loff_t off, size_t count) 84 { 85 dev_dbg(&kobj_to_w1_slave(kobj)->dev, 86 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", 87 bin_attr->attr.name, kobj, (unsigned int)off, count, buf); 88 if (count != 1 || off != 0) 89 return -EFAULT; 90 return _read_reg(kobj_to_w1_slave(kobj), 91 W1_F29_REG_OUTPUT_LATCH_STATE, buf); 92 } 93 94 static ssize_t activity_read(struct file *filp, struct kobject *kobj, 95 struct bin_attribute *bin_attr, char *buf, 96 loff_t off, size_t count) 97 { 98 dev_dbg(&kobj_to_w1_slave(kobj)->dev, 99 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", 100 bin_attr->attr.name, kobj, (unsigned int)off, count, buf); 101 if (count != 1 || off != 0) 102 return -EFAULT; 103 return _read_reg(kobj_to_w1_slave(kobj), 104 W1_F29_REG_ACTIVITY_LATCH_STATE, buf); 105 } 106 107 static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj, 108 struct bin_attribute *bin_attr, char *buf, 109 loff_t off, size_t count) 110 { 111 dev_dbg(&kobj_to_w1_slave(kobj)->dev, 112 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", 113 bin_attr->attr.name, kobj, (unsigned int)off, count, buf); 114 if (count != 1 || off != 0) 115 return -EFAULT; 116 return _read_reg(kobj_to_w1_slave(kobj), 117 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf); 118 } 119 120 static ssize_t cond_search_polarity_read(struct file *filp, 121 struct kobject *kobj, 122 struct bin_attribute *bin_attr, 123 char *buf, loff_t off, size_t count) 124 { 125 if (count != 1 || off != 0) 126 return -EFAULT; 127 return _read_reg(kobj_to_w1_slave(kobj), 128 W1_F29_REG_COND_SEARCH_POL_SELECT, buf); 129 } 130 131 static ssize_t status_control_read(struct file *filp, struct kobject *kobj, 132 struct bin_attribute *bin_attr, char *buf, 133 loff_t off, size_t count) 134 { 135 if (count != 1 || off != 0) 136 return -EFAULT; 137 return _read_reg(kobj_to_w1_slave(kobj), 138 W1_F29_REG_CONTROL_AND_STATUS, buf); 139 } 140 141 static ssize_t output_write(struct file *filp, struct kobject *kobj, 142 struct bin_attribute *bin_attr, char *buf, 143 loff_t off, size_t count) 144 { 145 struct w1_slave *sl = kobj_to_w1_slave(kobj); 146 u8 w1_buf[3]; 147 u8 readBack; 148 unsigned int retries = W1_F29_RETRIES; 149 150 if (count != 1 || off != 0) 151 return -EFAULT; 152 153 dev_dbg(&sl->dev, "locking mutex for write_output"); 154 mutex_lock(&sl->master->bus_mutex); 155 dev_dbg(&sl->dev, "mutex locked"); 156 157 if (w1_reset_select_slave(sl)) 158 goto error; 159 160 while (retries--) { 161 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE; 162 w1_buf[1] = *buf; 163 w1_buf[2] = ~(*buf); 164 w1_write_block(sl->master, w1_buf, 3); 165 166 readBack = w1_read_8(sl->master); 167 168 if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) { 169 if (w1_reset_resume_command(sl->master)) 170 goto error; 171 /* try again, the slave is ready for a command */ 172 continue; 173 } 174 175 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK 176 /* here the master could read another byte which 177 would be the PIO reg (the actual pin logic state) 178 since in this driver we don't know which pins are 179 in and outs, there's no value to read the state and 180 compare. with (*buf) so end this command abruptly: */ 181 if (w1_reset_resume_command(sl->master)) 182 goto error; 183 184 /* go read back the output latches */ 185 /* (the direct effect of the write above) */ 186 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; 187 w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; 188 w1_buf[2] = 0; 189 w1_write_block(sl->master, w1_buf, 3); 190 /* read the result of the READ_PIO_REGS command */ 191 if (w1_read_8(sl->master) == *buf) 192 #endif 193 { 194 /* success! */ 195 mutex_unlock(&sl->master->bus_mutex); 196 dev_dbg(&sl->dev, 197 "mutex unlocked, retries:%d", retries); 198 return 1; 199 } 200 } 201 error: 202 mutex_unlock(&sl->master->bus_mutex); 203 dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); 204 205 return -EIO; 206 } 207 208 209 /** 210 * Writing to the activity file resets the activity latches. 211 */ 212 static ssize_t activity_write(struct file *filp, struct kobject *kobj, 213 struct bin_attribute *bin_attr, char *buf, 214 loff_t off, size_t count) 215 { 216 struct w1_slave *sl = kobj_to_w1_slave(kobj); 217 unsigned int retries = W1_F29_RETRIES; 218 219 if (count != 1 || off != 0) 220 return -EFAULT; 221 222 mutex_lock(&sl->master->bus_mutex); 223 224 if (w1_reset_select_slave(sl)) 225 goto error; 226 227 while (retries--) { 228 w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); 229 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { 230 mutex_unlock(&sl->master->bus_mutex); 231 return 1; 232 } 233 if (w1_reset_resume_command(sl->master)) 234 goto error; 235 } 236 237 error: 238 mutex_unlock(&sl->master->bus_mutex); 239 return -EIO; 240 } 241 242 static ssize_t status_control_write(struct file *filp, struct kobject *kobj, 243 struct bin_attribute *bin_attr, char *buf, 244 loff_t off, size_t count) 245 { 246 struct w1_slave *sl = kobj_to_w1_slave(kobj); 247 u8 w1_buf[4]; 248 unsigned int retries = W1_F29_RETRIES; 249 250 if (count != 1 || off != 0) 251 return -EFAULT; 252 253 mutex_lock(&sl->master->bus_mutex); 254 255 if (w1_reset_select_slave(sl)) 256 goto error; 257 258 while (retries--) { 259 w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG; 260 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; 261 w1_buf[2] = 0; 262 w1_buf[3] = *buf; 263 264 w1_write_block(sl->master, w1_buf, 4); 265 if (w1_reset_resume_command(sl->master)) 266 goto error; 267 268 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; 269 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; 270 w1_buf[2] = 0; 271 272 w1_write_block(sl->master, w1_buf, 3); 273 if (w1_read_8(sl->master) == *buf) { 274 /* success! */ 275 mutex_unlock(&sl->master->bus_mutex); 276 return 1; 277 } 278 } 279 error: 280 mutex_unlock(&sl->master->bus_mutex); 281 282 return -EIO; 283 } 284 285 /* 286 * This is a special sequence we must do to ensure the P0 output is not stuck 287 * in test mode. This is described in rev 2 of the ds2408's datasheet 288 * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under 289 * "APPLICATION INFORMATION/Power-up timing". 290 */ 291 static int w1_f29_disable_test_mode(struct w1_slave *sl) 292 { 293 int res; 294 u8 magic[10] = {0x96, }; 295 u64 rn = le64_to_cpu(*((u64*)&sl->reg_num)); 296 297 memcpy(&magic[1], &rn, 8); 298 magic[9] = 0x3C; 299 300 mutex_lock(&sl->master->bus_mutex); 301 302 res = w1_reset_bus(sl->master); 303 if (res) 304 goto out; 305 w1_write_block(sl->master, magic, ARRAY_SIZE(magic)); 306 307 res = w1_reset_bus(sl->master); 308 out: 309 mutex_unlock(&sl->master->bus_mutex); 310 return res; 311 } 312 313 static BIN_ATTR_RO(state, 1); 314 static BIN_ATTR_RW(output, 1); 315 static BIN_ATTR_RW(activity, 1); 316 static BIN_ATTR_RO(cond_search_mask, 1); 317 static BIN_ATTR_RO(cond_search_polarity, 1); 318 static BIN_ATTR_RW(status_control, 1); 319 320 static struct bin_attribute *w1_f29_bin_attrs[] = { 321 &bin_attr_state, 322 &bin_attr_output, 323 &bin_attr_activity, 324 &bin_attr_cond_search_mask, 325 &bin_attr_cond_search_polarity, 326 &bin_attr_status_control, 327 NULL, 328 }; 329 330 static const struct attribute_group w1_f29_group = { 331 .bin_attrs = w1_f29_bin_attrs, 332 }; 333 334 static const struct attribute_group *w1_f29_groups[] = { 335 &w1_f29_group, 336 NULL, 337 }; 338 339 static struct w1_family_ops w1_f29_fops = { 340 .add_slave = w1_f29_disable_test_mode, 341 .groups = w1_f29_groups, 342 }; 343 344 static struct w1_family w1_family_29 = { 345 .fid = W1_FAMILY_DS2408, 346 .fops = &w1_f29_fops, 347 }; 348 module_w1_family(w1_family_29); 349 350 MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>"); 351 MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); 352 MODULE_LICENSE("GPL"); 353 MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408)); 354