root/drivers/w1/slaves/w1_ds2408.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _read_reg
  2. state_read
  3. output_read
  4. activity_read
  5. cond_search_mask_read
  6. cond_search_polarity_read
  7. status_control_read
  8. optional_read_back_valid
  9. optional_read_back_valid
  10. output_write
  11. activity_write
  12. status_control_write
  13. w1_f29_disable_test_mode

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *      w1_ds2408.c - w1 family 29 (DS2408) driver
   4  *
   5  * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/moduleparam.h>
  11 #include <linux/device.h>
  12 #include <linux/types.h>
  13 #include <linux/delay.h>
  14 #include <linux/slab.h>
  15 
  16 #include <linux/w1.h>
  17 
  18 #define W1_FAMILY_DS2408        0x29
  19 
  20 #define W1_F29_RETRIES          3
  21 
  22 #define W1_F29_REG_LOGIG_STATE             0x88 /* R */
  23 #define W1_F29_REG_OUTPUT_LATCH_STATE      0x89 /* R */
  24 #define W1_F29_REG_ACTIVITY_LATCH_STATE    0x8A /* R */
  25 #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
  26 #define W1_F29_REG_COND_SEARCH_POL_SELECT  0x8C /* RW */
  27 #define W1_F29_REG_CONTROL_AND_STATUS      0x8D /* RW */
  28 
  29 #define W1_F29_FUNC_READ_PIO_REGS          0xF0
  30 #define W1_F29_FUNC_CHANN_ACCESS_READ      0xF5
  31 #define W1_F29_FUNC_CHANN_ACCESS_WRITE     0x5A
  32 /* also used to write the control/status reg (0x8D): */
  33 #define W1_F29_FUNC_WRITE_COND_SEARCH_REG  0xCC
  34 #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
  35 
  36 #define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA
  37 
  38 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
  39 {
  40         u8 wrbuf[3];
  41         dev_dbg(&sl->dev,
  42                         "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
  43                         sl, (unsigned int)address, buf);
  44 
  45         if (!buf)
  46                 return -EINVAL;
  47 
  48         mutex_lock(&sl->master->bus_mutex);
  49         dev_dbg(&sl->dev, "mutex locked");
  50 
  51         if (w1_reset_select_slave(sl)) {
  52                 mutex_unlock(&sl->master->bus_mutex);
  53                 return -EIO;
  54         }
  55 
  56         wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
  57         wrbuf[1] = address;
  58         wrbuf[2] = 0;
  59         w1_write_block(sl->master, wrbuf, 3);
  60         *buf = w1_read_8(sl->master);
  61 
  62         mutex_unlock(&sl->master->bus_mutex);
  63         dev_dbg(&sl->dev, "mutex unlocked");
  64         return 1;
  65 }
  66 
  67 static ssize_t state_read(struct file *filp, struct kobject *kobj,
  68                           struct bin_attribute *bin_attr, char *buf, loff_t off,
  69                           size_t count)
  70 {
  71         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
  72                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
  73                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
  74         if (count != 1 || off != 0)
  75                 return -EFAULT;
  76         return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
  77 }
  78 
  79 static ssize_t output_read(struct file *filp, struct kobject *kobj,
  80                            struct bin_attribute *bin_attr, char *buf,
  81                            loff_t off, size_t count)
  82 {
  83         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
  84                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
  85                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
  86         if (count != 1 || off != 0)
  87                 return -EFAULT;
  88         return _read_reg(kobj_to_w1_slave(kobj),
  89                                          W1_F29_REG_OUTPUT_LATCH_STATE, buf);
  90 }
  91 
  92 static ssize_t activity_read(struct file *filp, struct kobject *kobj,
  93                              struct bin_attribute *bin_attr, char *buf,
  94                              loff_t off, size_t count)
  95 {
  96         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
  97                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
  98                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
  99         if (count != 1 || off != 0)
 100                 return -EFAULT;
 101         return _read_reg(kobj_to_w1_slave(kobj),
 102                                          W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
 103 }
 104 
 105 static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
 106                                      struct bin_attribute *bin_attr, char *buf,
 107                                      loff_t off, size_t count)
 108 {
 109         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 110                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
 111                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
 112         if (count != 1 || off != 0)
 113                 return -EFAULT;
 114         return _read_reg(kobj_to_w1_slave(kobj),
 115                 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
 116 }
 117 
 118 static ssize_t cond_search_polarity_read(struct file *filp,
 119                                          struct kobject *kobj,
 120                                          struct bin_attribute *bin_attr,
 121                                          char *buf, loff_t off, size_t count)
 122 {
 123         if (count != 1 || off != 0)
 124                 return -EFAULT;
 125         return _read_reg(kobj_to_w1_slave(kobj),
 126                 W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
 127 }
 128 
 129 static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
 130                                    struct bin_attribute *bin_attr, char *buf,
 131                                    loff_t off, size_t count)
 132 {
 133         if (count != 1 || off != 0)
 134                 return -EFAULT;
 135         return _read_reg(kobj_to_w1_slave(kobj),
 136                 W1_F29_REG_CONTROL_AND_STATUS, buf);
 137 }
 138 
 139 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK
 140 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
 141 {
 142         u8 w1_buf[3];
 143 
 144         if (w1_reset_resume_command(sl->master))
 145                 return false;
 146 
 147         w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
 148         w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
 149         w1_buf[2] = 0;
 150 
 151         w1_write_block(sl->master, w1_buf, 3);
 152 
 153         return (w1_read_8(sl->master) == expected);
 154 }
 155 #else
 156 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
 157 {
 158         return true;
 159 }
 160 #endif
 161 
 162 static ssize_t output_write(struct file *filp, struct kobject *kobj,
 163                             struct bin_attribute *bin_attr, char *buf,
 164                             loff_t off, size_t count)
 165 {
 166         struct w1_slave *sl = kobj_to_w1_slave(kobj);
 167         u8 w1_buf[3];
 168         unsigned int retries = W1_F29_RETRIES;
 169         ssize_t bytes_written = -EIO;
 170 
 171         if (count != 1 || off != 0)
 172                 return -EFAULT;
 173 
 174         dev_dbg(&sl->dev, "locking mutex for write_output");
 175         mutex_lock(&sl->master->bus_mutex);
 176         dev_dbg(&sl->dev, "mutex locked");
 177 
 178         if (w1_reset_select_slave(sl))
 179                 goto out;
 180 
 181         do {
 182                 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
 183                 w1_buf[1] = *buf;
 184                 w1_buf[2] = ~(*buf);
 185 
 186                 w1_write_block(sl->master, w1_buf, 3);
 187 
 188                 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
 189                     optional_read_back_valid(sl, *buf)) {
 190                         bytes_written = 1;
 191                         goto out;
 192                 }
 193 
 194                 if (w1_reset_resume_command(sl->master))
 195                         goto out; /* unrecoverable error */
 196                 /* try again, the slave is ready for a command */
 197         } while (--retries);
 198 
 199 out:
 200         mutex_unlock(&sl->master->bus_mutex);
 201 
 202         dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
 203                 (bytes_written > 0) ? "succeeded" : "error", retries);
 204 
 205         return bytes_written;
 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));

/* [<][>][^][v][top][bottom][index][help] */