linux/drivers/w1/slaves/w1_ds28e04.c
<<
>>
Prefs
   1/*
   2 *      w1_ds28e04.c - w1 family 1C (DS28E04) driver
   3 *
   4 * Copyright (c) 2012 Markus Franke <franke.m@sebakmt.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#include <linux/crc16.h>
  18#include <linux/uaccess.h>
  19
  20#define CRC16_INIT              0
  21#define CRC16_VALID             0xb001
  22
  23#include <linux/w1.h>
  24
  25#define W1_FAMILY_DS28E04       0x1C
  26
  27/* Allow the strong pullup to be disabled, but default to enabled.
  28 * If it was disabled a parasite powered device might not get the required
  29 * current to copy the data from the scratchpad to EEPROM.  If it is enabled
  30 * parasite powered devices have a better chance of getting the current
  31 * required.
  32 */
  33static int w1_strong_pullup = 1;
  34module_param_named(strong_pullup, w1_strong_pullup, int, 0);
  35
  36/* enable/disable CRC checking on DS28E04-100 memory accesses */
  37static char w1_enable_crccheck = 1;
  38
  39#define W1_EEPROM_SIZE          512
  40#define W1_PAGE_COUNT           16
  41#define W1_PAGE_SIZE            32
  42#define W1_PAGE_BITS            5
  43#define W1_PAGE_MASK            0x1F
  44
  45#define W1_F1C_READ_EEPROM      0xF0
  46#define W1_F1C_WRITE_SCRATCH    0x0F
  47#define W1_F1C_READ_SCRATCH     0xAA
  48#define W1_F1C_COPY_SCRATCH     0x55
  49#define W1_F1C_ACCESS_WRITE     0x5A
  50
  51#define W1_1C_REG_LOGIC_STATE   0x220
  52
  53struct w1_f1C_data {
  54        u8      memory[W1_EEPROM_SIZE];
  55        u32     validcrc;
  56};
  57
  58/**
  59 * Check the file size bounds and adjusts count as needed.
  60 * This would not be needed if the file size didn't reset to 0 after a write.
  61 */
  62static inline size_t w1_f1C_fix_count(loff_t off, size_t count, size_t size)
  63{
  64        if (off > size)
  65                return 0;
  66
  67        if ((off + count) > size)
  68                return size - off;
  69
  70        return count;
  71}
  72
  73static int w1_f1C_refresh_block(struct w1_slave *sl, struct w1_f1C_data *data,
  74                                int block)
  75{
  76        u8      wrbuf[3];
  77        int     off = block * W1_PAGE_SIZE;
  78
  79        if (data->validcrc & (1 << block))
  80                return 0;
  81
  82        if (w1_reset_select_slave(sl)) {
  83                data->validcrc = 0;
  84                return -EIO;
  85        }
  86
  87        wrbuf[0] = W1_F1C_READ_EEPROM;
  88        wrbuf[1] = off & 0xff;
  89        wrbuf[2] = off >> 8;
  90        w1_write_block(sl->master, wrbuf, 3);
  91        w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
  92
  93        /* cache the block if the CRC is valid */
  94        if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
  95                data->validcrc |= (1 << block);
  96
  97        return 0;
  98}
  99
 100static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data)
 101{
 102        u8 wrbuf[3];
 103
 104        /* read directly from the EEPROM */
 105        if (w1_reset_select_slave(sl))
 106                return -EIO;
 107
 108        wrbuf[0] = W1_F1C_READ_EEPROM;
 109        wrbuf[1] = addr & 0xff;
 110        wrbuf[2] = addr >> 8;
 111
 112        w1_write_block(sl->master, wrbuf, sizeof(wrbuf));
 113        return w1_read_block(sl->master, data, len);
 114}
 115
 116static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
 117                           struct bin_attribute *bin_attr, char *buf,
 118                           loff_t off, size_t count)
 119{
 120        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 121        struct w1_f1C_data *data = sl->family_data;
 122        int i, min_page, max_page;
 123
 124        count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE);
 125        if (count == 0)
 126                return 0;
 127
 128        mutex_lock(&sl->master->mutex);
 129
 130        if (w1_enable_crccheck) {
 131                min_page = (off >> W1_PAGE_BITS);
 132                max_page = (off + count - 1) >> W1_PAGE_BITS;
 133                for (i = min_page; i <= max_page; i++) {
 134                        if (w1_f1C_refresh_block(sl, data, i)) {
 135                                count = -EIO;
 136                                goto out_up;
 137                        }
 138                }
 139                memcpy(buf, &data->memory[off], count);
 140        } else {
 141                count = w1_f1C_read(sl, off, count, buf);
 142        }
 143
 144out_up:
 145        mutex_unlock(&sl->master->mutex);
 146
 147        return count;
 148}
 149
 150/**
 151 * Writes to the scratchpad and reads it back for verification.
 152 * Then copies the scratchpad to EEPROM.
 153 * The data must be on one page.
 154 * The master must be locked.
 155 *
 156 * @param sl    The slave structure
 157 * @param addr  Address for the write
 158 * @param len   length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
 159 * @param data  The data to write
 160 * @return      0=Success -1=failure
 161 */
 162static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data)
 163{
 164        u8 wrbuf[4];
 165        u8 rdbuf[W1_PAGE_SIZE + 3];
 166        u8 es = (addr + len - 1) & 0x1f;
 167        unsigned int tm = 10;
 168        int i;
 169        struct w1_f1C_data *f1C = sl->family_data;
 170
 171        /* Write the data to the scratchpad */
 172        if (w1_reset_select_slave(sl))
 173                return -1;
 174
 175        wrbuf[0] = W1_F1C_WRITE_SCRATCH;
 176        wrbuf[1] = addr & 0xff;
 177        wrbuf[2] = addr >> 8;
 178
 179        w1_write_block(sl->master, wrbuf, 3);
 180        w1_write_block(sl->master, data, len);
 181
 182        /* Read the scratchpad and verify */
 183        if (w1_reset_select_slave(sl))
 184                return -1;
 185
 186        w1_write_8(sl->master, W1_F1C_READ_SCRATCH);
 187        w1_read_block(sl->master, rdbuf, len + 3);
 188
 189        /* Compare what was read against the data written */
 190        if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
 191            (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0))
 192                return -1;
 193
 194        /* Copy the scratchpad to EEPROM */
 195        if (w1_reset_select_slave(sl))
 196                return -1;
 197
 198        wrbuf[0] = W1_F1C_COPY_SCRATCH;
 199        wrbuf[3] = es;
 200
 201        for (i = 0; i < sizeof(wrbuf); ++i) {
 202                /* issue 10ms strong pullup (or delay) on the last byte
 203                   for writing the data from the scratchpad to EEPROM */
 204                if (w1_strong_pullup && i == sizeof(wrbuf)-1)
 205                        w1_next_pullup(sl->master, tm);
 206
 207                w1_write_8(sl->master, wrbuf[i]);
 208        }
 209
 210        if (!w1_strong_pullup)
 211                msleep(tm);
 212
 213        if (w1_enable_crccheck) {
 214                /* invalidate cached data */
 215                f1C->validcrc &= ~(1 << (addr >> W1_PAGE_BITS));
 216        }
 217
 218        /* Reset the bus to wake up the EEPROM (this may not be needed) */
 219        w1_reset_bus(sl->master);
 220
 221        return 0;
 222}
 223
 224static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
 225                            struct bin_attribute *bin_attr, char *buf,
 226                            loff_t off, size_t count)
 227
 228{
 229        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 230        int addr, len, idx;
 231
 232        count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE);
 233        if (count == 0)
 234                return 0;
 235
 236        if (w1_enable_crccheck) {
 237                /* can only write full blocks in cached mode */
 238                if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
 239                        dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
 240                                (int)off, count);
 241                        return -EINVAL;
 242                }
 243
 244                /* make sure the block CRCs are valid */
 245                for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
 246                        if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE)
 247                                != CRC16_VALID) {
 248                                dev_err(&sl->dev, "bad CRC at offset %d\n",
 249                                        (int)off);
 250                                return -EINVAL;
 251                        }
 252                }
 253        }
 254
 255        mutex_lock(&sl->master->mutex);
 256
 257        /* Can only write data to one page at a time */
 258        idx = 0;
 259        while (idx < count) {
 260                addr = off + idx;
 261                len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
 262                if (len > (count - idx))
 263                        len = count - idx;
 264
 265                if (w1_f1C_write(sl, addr, len, &buf[idx]) < 0) {
 266                        count = -EIO;
 267                        goto out_up;
 268                }
 269                idx += len;
 270        }
 271
 272out_up:
 273        mutex_unlock(&sl->master->mutex);
 274
 275        return count;
 276}
 277
 278static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
 279
 280static ssize_t pio_read(struct file *filp, struct kobject *kobj,
 281                        struct bin_attribute *bin_attr, char *buf, loff_t off,
 282                        size_t count)
 283
 284{
 285        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 286        int ret;
 287
 288        /* check arguments */
 289        if (off != 0 || count != 1 || buf == NULL)
 290                return -EINVAL;
 291
 292        mutex_lock(&sl->master->mutex);
 293        ret = w1_f1C_read(sl, W1_1C_REG_LOGIC_STATE, count, buf);
 294        mutex_unlock(&sl->master->mutex);
 295
 296        return ret;
 297}
 298
 299static ssize_t pio_write(struct file *filp, struct kobject *kobj,
 300                         struct bin_attribute *bin_attr, char *buf, loff_t off,
 301                         size_t count)
 302
 303{
 304        struct w1_slave *sl = kobj_to_w1_slave(kobj);
 305        u8 wrbuf[3];
 306        u8 ack;
 307
 308        /* check arguments */
 309        if (off != 0 || count != 1 || buf == NULL)
 310                return -EINVAL;
 311
 312        mutex_lock(&sl->master->mutex);
 313
 314        /* Write the PIO data */
 315        if (w1_reset_select_slave(sl)) {
 316                mutex_unlock(&sl->master->mutex);
 317                return -1;
 318        }
 319
 320        /* set bit 7..2 to value '1' */
 321        *buf = *buf | 0xFC;
 322
 323        wrbuf[0] = W1_F1C_ACCESS_WRITE;
 324        wrbuf[1] = *buf;
 325        wrbuf[2] = ~(*buf);
 326        w1_write_block(sl->master, wrbuf, 3);
 327
 328        w1_read_block(sl->master, &ack, sizeof(ack));
 329
 330        mutex_unlock(&sl->master->mutex);
 331
 332        /* check for acknowledgement */
 333        if (ack != 0xAA)
 334                return -EIO;
 335
 336        return count;
 337}
 338
 339static BIN_ATTR_RW(pio, 1);
 340
 341static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr,
 342                             char *buf)
 343{
 344        if (put_user(w1_enable_crccheck + 0x30, buf))
 345                return -EFAULT;
 346
 347        return sizeof(w1_enable_crccheck);
 348}
 349
 350static ssize_t crccheck_store(struct device *dev, struct device_attribute *attr,
 351                              const char *buf, size_t count)
 352{
 353        char val;
 354
 355        if (count != 1 || !buf)
 356                return -EINVAL;
 357
 358        if (get_user(val, buf))
 359                return -EFAULT;
 360
 361        /* convert to decimal */
 362        val = val - 0x30;
 363        if (val != 0 && val != 1)
 364                return -EINVAL;
 365
 366        /* set the new value */
 367        w1_enable_crccheck = val;
 368
 369        return sizeof(w1_enable_crccheck);
 370}
 371
 372static DEVICE_ATTR_RW(crccheck);
 373
 374static struct attribute *w1_f1C_attrs[] = {
 375        &dev_attr_crccheck.attr,
 376        NULL,
 377};
 378
 379static struct bin_attribute *w1_f1C_bin_attrs[] = {
 380        &bin_attr_eeprom,
 381        &bin_attr_pio,
 382        NULL,
 383};
 384
 385static const struct attribute_group w1_f1C_group = {
 386        .attrs          = w1_f1C_attrs,
 387        .bin_attrs      = w1_f1C_bin_attrs,
 388};
 389
 390static const struct attribute_group *w1_f1C_groups[] = {
 391        &w1_f1C_group,
 392        NULL,
 393};
 394
 395static int w1_f1C_add_slave(struct w1_slave *sl)
 396{
 397        struct w1_f1C_data *data = NULL;
 398
 399        if (w1_enable_crccheck) {
 400                data = kzalloc(sizeof(struct w1_f1C_data), GFP_KERNEL);
 401                if (!data)
 402                        return -ENOMEM;
 403                sl->family_data = data;
 404        }
 405
 406        return 0;
 407}
 408
 409static void w1_f1C_remove_slave(struct w1_slave *sl)
 410{
 411        kfree(sl->family_data);
 412        sl->family_data = NULL;
 413}
 414
 415static struct w1_family_ops w1_f1C_fops = {
 416        .add_slave      = w1_f1C_add_slave,
 417        .remove_slave   = w1_f1C_remove_slave,
 418        .groups         = w1_f1C_groups,
 419};
 420
 421static struct w1_family w1_family_1C = {
 422        .fid = W1_FAMILY_DS28E04,
 423        .fops = &w1_f1C_fops,
 424};
 425module_w1_family(w1_family_1C);
 426
 427MODULE_AUTHOR("Markus Franke <franke.m@sebakmt.com>, <franm@hrz.tu-chemnitz.de>");
 428MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO");
 429MODULE_LICENSE("GPL");
 430MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E04));
 431