root/drivers/w1/slaves/w1_ds28e04.c

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

DEFINITIONS

This source file includes following definitions.
  1. w1_f1C_fix_count
  2. w1_f1C_refresh_block
  3. w1_f1C_read
  4. eeprom_read
  5. w1_f1C_write
  6. eeprom_write
  7. pio_read
  8. pio_write
  9. crccheck_show
  10. crccheck_store
  11. w1_f1C_add_slave
  12. w1_f1C_remove_slave

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

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