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