linux/drivers/w1/slaves/w1_therm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *      w1_therm.c
   4 *
   5 * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
   6 */
   7
   8#include <asm/types.h>
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/moduleparam.h>
  13#include <linux/sched.h>
  14#include <linux/device.h>
  15#include <linux/types.h>
  16#include <linux/slab.h>
  17#include <linux/delay.h>
  18#include <linux/hwmon.h>
  19
  20#include <linux/w1.h>
  21
  22#define W1_THERM_DS18S20        0x10
  23#define W1_THERM_DS1822         0x22
  24#define W1_THERM_DS18B20        0x28
  25#define W1_THERM_DS1825         0x3B
  26#define W1_THERM_DS28EA00       0x42
  27
  28/* Allow the strong pullup to be disabled, but default to enabled.
  29 * If it was disabled a parasite powered device might not get the require
  30 * current to do a temperature conversion.  If it is enabled parasite powered
  31 * devices have a better chance of getting the current required.
  32 * In case the parasite power-detection is not working (seems to be the case
  33 * for some DS18S20) the strong pullup can also be forced, regardless of the
  34 * power state of the devices.
  35 *
  36 * Summary of options:
  37 * - strong_pullup = 0  Disable strong pullup completely
  38 * - strong_pullup = 1  Enable automatic strong pullup detection
  39 * - strong_pullup = 2  Force strong pullup
  40 */
  41static int w1_strong_pullup = 1;
  42module_param_named(strong_pullup, w1_strong_pullup, int, 0);
  43
  44struct w1_therm_family_data {
  45        uint8_t rom[9];
  46        atomic_t refcnt;
  47};
  48
  49struct therm_info {
  50        u8 rom[9];
  51        u8 crc;
  52        u8 verdict;
  53};
  54
  55/* return the address of the refcnt in the family data */
  56#define THERM_REFCNT(family_data) \
  57        (&((struct w1_therm_family_data *)family_data)->refcnt)
  58
  59static int w1_therm_add_slave(struct w1_slave *sl)
  60{
  61        sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
  62                GFP_KERNEL);
  63        if (!sl->family_data)
  64                return -ENOMEM;
  65        atomic_set(THERM_REFCNT(sl->family_data), 1);
  66        return 0;
  67}
  68
  69static void w1_therm_remove_slave(struct w1_slave *sl)
  70{
  71        int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
  72
  73        while (refcnt) {
  74                msleep(1000);
  75                refcnt = atomic_read(THERM_REFCNT(sl->family_data));
  76        }
  77        kfree(sl->family_data);
  78        sl->family_data = NULL;
  79}
  80
  81static ssize_t w1_slave_show(struct device *device,
  82        struct device_attribute *attr, char *buf);
  83
  84static ssize_t w1_slave_store(struct device *device,
  85        struct device_attribute *attr, const char *buf, size_t size);
  86
  87static ssize_t w1_seq_show(struct device *device,
  88        struct device_attribute *attr, char *buf);
  89
  90static DEVICE_ATTR_RW(w1_slave);
  91static DEVICE_ATTR_RO(w1_seq);
  92
  93static struct attribute *w1_therm_attrs[] = {
  94        &dev_attr_w1_slave.attr,
  95        NULL,
  96};
  97
  98static struct attribute *w1_ds28ea00_attrs[] = {
  99        &dev_attr_w1_slave.attr,
 100        &dev_attr_w1_seq.attr,
 101        NULL,
 102};
 103
 104ATTRIBUTE_GROUPS(w1_therm);
 105ATTRIBUTE_GROUPS(w1_ds28ea00);
 106
 107#if IS_REACHABLE(CONFIG_HWMON)
 108static int w1_read_temp(struct device *dev, u32 attr, int channel,
 109                        long *val);
 110
 111static umode_t w1_is_visible(const void *_data, enum hwmon_sensor_types type,
 112                             u32 attr, int channel)
 113{
 114        return attr == hwmon_temp_input ? 0444 : 0;
 115}
 116
 117static int w1_read(struct device *dev, enum hwmon_sensor_types type,
 118                   u32 attr, int channel, long *val)
 119{
 120        switch (type) {
 121        case hwmon_temp:
 122                return w1_read_temp(dev, attr, channel, val);
 123        default:
 124                return -EOPNOTSUPP;
 125        }
 126}
 127
 128static const u32 w1_temp_config[] = {
 129        HWMON_T_INPUT,
 130        0
 131};
 132
 133static const struct hwmon_channel_info w1_temp = {
 134        .type = hwmon_temp,
 135        .config = w1_temp_config,
 136};
 137
 138static const struct hwmon_channel_info *w1_info[] = {
 139        &w1_temp,
 140        NULL
 141};
 142
 143static const struct hwmon_ops w1_hwmon_ops = {
 144        .is_visible = w1_is_visible,
 145        .read = w1_read,
 146};
 147
 148static const struct hwmon_chip_info w1_chip_info = {
 149        .ops = &w1_hwmon_ops,
 150        .info = w1_info,
 151};
 152#define W1_CHIPINFO     (&w1_chip_info)
 153#else
 154#define W1_CHIPINFO     NULL
 155#endif
 156
 157static struct w1_family_ops w1_therm_fops = {
 158        .add_slave      = w1_therm_add_slave,
 159        .remove_slave   = w1_therm_remove_slave,
 160        .groups         = w1_therm_groups,
 161        .chip_info      = W1_CHIPINFO,
 162};
 163
 164static struct w1_family_ops w1_ds28ea00_fops = {
 165        .add_slave      = w1_therm_add_slave,
 166        .remove_slave   = w1_therm_remove_slave,
 167        .groups         = w1_ds28ea00_groups,
 168        .chip_info      = W1_CHIPINFO,
 169};
 170
 171static struct w1_family w1_therm_family_DS18S20 = {
 172        .fid = W1_THERM_DS18S20,
 173        .fops = &w1_therm_fops,
 174};
 175
 176static struct w1_family w1_therm_family_DS18B20 = {
 177        .fid = W1_THERM_DS18B20,
 178        .fops = &w1_therm_fops,
 179};
 180
 181static struct w1_family w1_therm_family_DS1822 = {
 182        .fid = W1_THERM_DS1822,
 183        .fops = &w1_therm_fops,
 184};
 185
 186static struct w1_family w1_therm_family_DS28EA00 = {
 187        .fid = W1_THERM_DS28EA00,
 188        .fops = &w1_ds28ea00_fops,
 189};
 190
 191static struct w1_family w1_therm_family_DS1825 = {
 192        .fid = W1_THERM_DS1825,
 193        .fops = &w1_therm_fops,
 194};
 195
 196struct w1_therm_family_converter {
 197        u8                      broken;
 198        u16                     reserved;
 199        struct w1_family        *f;
 200        int                     (*convert)(u8 rom[9]);
 201        int                     (*precision)(struct device *device, int val);
 202        int                     (*eeprom)(struct device *device);
 203};
 204
 205/* write configuration to eeprom */
 206static inline int w1_therm_eeprom(struct device *device);
 207
 208/* Set precision for conversion */
 209static inline int w1_DS18B20_precision(struct device *device, int val);
 210static inline int w1_DS18S20_precision(struct device *device, int val);
 211
 212/* The return value is millidegrees Centigrade. */
 213static inline int w1_DS18B20_convert_temp(u8 rom[9]);
 214static inline int w1_DS18S20_convert_temp(u8 rom[9]);
 215
 216static struct w1_therm_family_converter w1_therm_families[] = {
 217        {
 218                .f              = &w1_therm_family_DS18S20,
 219                .convert        = w1_DS18S20_convert_temp,
 220                .precision      = w1_DS18S20_precision,
 221                .eeprom         = w1_therm_eeprom
 222        },
 223        {
 224                .f              = &w1_therm_family_DS1822,
 225                .convert        = w1_DS18B20_convert_temp,
 226                .precision      = w1_DS18S20_precision,
 227                .eeprom         = w1_therm_eeprom
 228        },
 229        {
 230                .f              = &w1_therm_family_DS18B20,
 231                .convert        = w1_DS18B20_convert_temp,
 232                .precision      = w1_DS18B20_precision,
 233                .eeprom         = w1_therm_eeprom
 234        },
 235        {
 236                .f              = &w1_therm_family_DS28EA00,
 237                .convert        = w1_DS18B20_convert_temp,
 238                .precision      = w1_DS18S20_precision,
 239                .eeprom         = w1_therm_eeprom
 240        },
 241        {
 242                .f              = &w1_therm_family_DS1825,
 243                .convert        = w1_DS18B20_convert_temp,
 244                .precision      = w1_DS18S20_precision,
 245                .eeprom         = w1_therm_eeprom
 246        }
 247};
 248
 249static inline int w1_therm_eeprom(struct device *device)
 250{
 251        struct w1_slave *sl = dev_to_w1_slave(device);
 252        struct w1_master *dev = sl->master;
 253        u8 rom[9], external_power;
 254        int ret, max_trying = 10;
 255        u8 *family_data = sl->family_data;
 256
 257        if (!sl->family_data) {
 258                ret = -ENODEV;
 259                goto error;
 260        }
 261
 262        /* prevent the slave from going away in sleep */
 263        atomic_inc(THERM_REFCNT(family_data));
 264
 265        ret = mutex_lock_interruptible(&dev->bus_mutex);
 266        if (ret != 0)
 267                goto dec_refcnt;
 268
 269        memset(rom, 0, sizeof(rom));
 270
 271        while (max_trying--) {
 272                if (!w1_reset_select_slave(sl)) {
 273                        unsigned int tm = 10;
 274                        unsigned long sleep_rem;
 275
 276                        /* check if in parasite mode */
 277                        w1_write_8(dev, W1_READ_PSUPPLY);
 278                        external_power = w1_read_8(dev);
 279
 280                        if (w1_reset_select_slave(sl))
 281                                continue;
 282
 283                        /* 10ms strong pullup/delay after the copy command */
 284                        if (w1_strong_pullup == 2 ||
 285                            (!external_power && w1_strong_pullup))
 286                                w1_next_pullup(dev, tm);
 287
 288                        w1_write_8(dev, W1_COPY_SCRATCHPAD);
 289
 290                        if (external_power) {
 291                                mutex_unlock(&dev->bus_mutex);
 292
 293                                sleep_rem = msleep_interruptible(tm);
 294                                if (sleep_rem != 0) {
 295                                        ret = -EINTR;
 296                                        goto dec_refcnt;
 297                                }
 298
 299                                ret = mutex_lock_interruptible(&dev->bus_mutex);
 300                                if (ret != 0)
 301                                        goto dec_refcnt;
 302                        } else if (!w1_strong_pullup) {
 303                                sleep_rem = msleep_interruptible(tm);
 304                                if (sleep_rem != 0) {
 305                                        ret = -EINTR;
 306                                        goto mt_unlock;
 307                                }
 308                        }
 309
 310                        break;
 311                }
 312        }
 313
 314mt_unlock:
 315        mutex_unlock(&dev->bus_mutex);
 316dec_refcnt:
 317        atomic_dec(THERM_REFCNT(family_data));
 318error:
 319        return ret;
 320}
 321
 322/* DS18S20 does not feature configuration register */
 323static inline int w1_DS18S20_precision(struct device *device, int val)
 324{
 325        return 0;
 326}
 327
 328static inline int w1_DS18B20_precision(struct device *device, int val)
 329{
 330        struct w1_slave *sl = dev_to_w1_slave(device);
 331        struct w1_master *dev = sl->master;
 332        u8 rom[9], crc;
 333        int ret, max_trying = 10;
 334        u8 *family_data = sl->family_data;
 335        uint8_t precision_bits;
 336        uint8_t mask = 0x60;
 337
 338        if (val > 12 || val < 9) {
 339                pr_warn("Unsupported precision\n");
 340                ret = -EINVAL;
 341                goto error;
 342        }
 343
 344        if (!sl->family_data) {
 345                ret = -ENODEV;
 346                goto error;
 347        }
 348
 349        /* prevent the slave from going away in sleep */
 350        atomic_inc(THERM_REFCNT(family_data));
 351
 352        ret = mutex_lock_interruptible(&dev->bus_mutex);
 353        if (ret != 0)
 354                goto dec_refcnt;
 355
 356        memset(rom, 0, sizeof(rom));
 357
 358        /* translate precision to bitmask (see datasheet page 9) */
 359        switch (val) {
 360        case 9:
 361                precision_bits = 0x00;
 362                break;
 363        case 10:
 364                precision_bits = 0x20;
 365                break;
 366        case 11:
 367                precision_bits = 0x40;
 368                break;
 369        case 12:
 370        default:
 371                precision_bits = 0x60;
 372                break;
 373        }
 374
 375        while (max_trying--) {
 376                crc = 0;
 377
 378                if (!w1_reset_select_slave(sl)) {
 379                        int count = 0;
 380
 381                        /* read values to only alter precision bits */
 382                        w1_write_8(dev, W1_READ_SCRATCHPAD);
 383                        count = w1_read_block(dev, rom, 9);
 384                        if (count != 9)
 385                                dev_warn(device, "w1_read_block() returned %u instead of 9.\n", count);
 386
 387                        crc = w1_calc_crc8(rom, 8);
 388                        if (rom[8] == crc) {
 389                                rom[4] = (rom[4] & ~mask) | (precision_bits & mask);
 390
 391                                if (!w1_reset_select_slave(sl)) {
 392                                        w1_write_8(dev, W1_WRITE_SCRATCHPAD);
 393                                        w1_write_8(dev, rom[2]);
 394                                        w1_write_8(dev, rom[3]);
 395                                        w1_write_8(dev, rom[4]);
 396
 397                                        break;
 398                                }
 399                        }
 400                }
 401        }
 402
 403        mutex_unlock(&dev->bus_mutex);
 404dec_refcnt:
 405        atomic_dec(THERM_REFCNT(family_data));
 406error:
 407        return ret;
 408}
 409
 410static inline int w1_DS18B20_convert_temp(u8 rom[9])
 411{
 412        s16 t = le16_to_cpup((__le16 *)rom);
 413
 414        return t*1000/16;
 415}
 416
 417static inline int w1_DS18S20_convert_temp(u8 rom[9])
 418{
 419        int t, h;
 420
 421        if (!rom[7])
 422                return 0;
 423
 424        if (rom[1] == 0)
 425                t = ((s32)rom[0] >> 1)*1000;
 426        else
 427                t = 1000*(-1*(s32)(0x100-rom[0]) >> 1);
 428
 429        t -= 250;
 430        h = 1000*((s32)rom[7] - (s32)rom[6]);
 431        h /= (s32)rom[7];
 432        t += h;
 433
 434        return t;
 435}
 436
 437static inline int w1_convert_temp(u8 rom[9], u8 fid)
 438{
 439        int i;
 440
 441        for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
 442                if (w1_therm_families[i].f->fid == fid)
 443                        return w1_therm_families[i].convert(rom);
 444
 445        return 0;
 446}
 447
 448static ssize_t w1_slave_store(struct device *device,
 449                              struct device_attribute *attr, const char *buf,
 450                              size_t size)
 451{
 452        int val, ret;
 453        struct w1_slave *sl = dev_to_w1_slave(device);
 454        int i;
 455
 456        ret = kstrtoint(buf, 0, &val);
 457        if (ret)
 458                return ret;
 459
 460        for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
 461                if (w1_therm_families[i].f->fid == sl->family->fid) {
 462                        /* zero value indicates to write current configuration to eeprom */
 463                        if (val == 0)
 464                                ret = w1_therm_families[i].eeprom(device);
 465                        else
 466                                ret = w1_therm_families[i].precision(device, val);
 467                        break;
 468                }
 469        }
 470        return ret ? : size;
 471}
 472
 473static ssize_t read_therm(struct device *device,
 474                          struct w1_slave *sl, struct therm_info *info)
 475{
 476        struct w1_master *dev = sl->master;
 477        u8 external_power;
 478        int ret, max_trying = 10;
 479        u8 *family_data = sl->family_data;
 480
 481        if (!family_data) {
 482                ret = -ENODEV;
 483                goto error;
 484        }
 485
 486        /* prevent the slave from going away in sleep */
 487        atomic_inc(THERM_REFCNT(family_data));
 488
 489        ret = mutex_lock_interruptible(&dev->bus_mutex);
 490        if (ret != 0)
 491                goto dec_refcnt;
 492
 493        memset(info->rom, 0, sizeof(info->rom));
 494
 495        while (max_trying--) {
 496
 497                info->verdict = 0;
 498                info->crc = 0;
 499
 500                if (!w1_reset_select_slave(sl)) {
 501                        int count = 0;
 502                        unsigned int tm = 750;
 503                        unsigned long sleep_rem;
 504
 505                        w1_write_8(dev, W1_READ_PSUPPLY);
 506                        external_power = w1_read_8(dev);
 507
 508                        if (w1_reset_select_slave(sl))
 509                                continue;
 510
 511                        /* 750ms strong pullup (or delay) after the convert */
 512                        if (w1_strong_pullup == 2 ||
 513                                        (!external_power && w1_strong_pullup))
 514                                w1_next_pullup(dev, tm);
 515
 516                        w1_write_8(dev, W1_CONVERT_TEMP);
 517
 518                        if (external_power) {
 519                                mutex_unlock(&dev->bus_mutex);
 520
 521                                sleep_rem = msleep_interruptible(tm);
 522                                if (sleep_rem != 0) {
 523                                        ret = -EINTR;
 524                                        goto dec_refcnt;
 525                                }
 526
 527                                ret = mutex_lock_interruptible(&dev->bus_mutex);
 528                                if (ret != 0)
 529                                        goto dec_refcnt;
 530                        } else if (!w1_strong_pullup) {
 531                                sleep_rem = msleep_interruptible(tm);
 532                                if (sleep_rem != 0) {
 533                                        ret = -EINTR;
 534                                        goto mt_unlock;
 535                                }
 536                        }
 537
 538                        if (!w1_reset_select_slave(sl)) {
 539
 540                                w1_write_8(dev, W1_READ_SCRATCHPAD);
 541                                count = w1_read_block(dev, info->rom, 9);
 542                                if (count != 9) {
 543                                        dev_warn(device, "w1_read_block() "
 544                                                "returned %u instead of 9.\n",
 545                                                count);
 546                                }
 547
 548                                info->crc = w1_calc_crc8(info->rom, 8);
 549
 550                                if (info->rom[8] == info->crc)
 551                                        info->verdict = 1;
 552                        }
 553                }
 554
 555                if (info->verdict)
 556                        break;
 557        }
 558
 559mt_unlock:
 560        mutex_unlock(&dev->bus_mutex);
 561dec_refcnt:
 562        atomic_dec(THERM_REFCNT(family_data));
 563error:
 564        return ret;
 565}
 566
 567static ssize_t w1_slave_show(struct device *device,
 568                             struct device_attribute *attr, char *buf)
 569{
 570        struct w1_slave *sl = dev_to_w1_slave(device);
 571        struct therm_info info;
 572        u8 *family_data = sl->family_data;
 573        int ret, i;
 574        ssize_t c = PAGE_SIZE;
 575        u8 fid = sl->family->fid;
 576
 577        ret = read_therm(device, sl, &info);
 578        if (ret)
 579                return ret;
 580
 581        for (i = 0; i < 9; ++i)
 582                c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", info.rom[i]);
 583        c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
 584                      info.crc, (info.verdict) ? "YES" : "NO");
 585        if (info.verdict)
 586                memcpy(family_data, info.rom, sizeof(info.rom));
 587        else
 588                dev_warn(device, "Read failed CRC check\n");
 589
 590        for (i = 0; i < 9; ++i)
 591                c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ",
 592                              ((u8 *)family_data)[i]);
 593
 594        c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
 595                        w1_convert_temp(info.rom, fid));
 596        ret = PAGE_SIZE - c;
 597        return ret;
 598}
 599
 600#if IS_REACHABLE(CONFIG_HWMON)
 601static int w1_read_temp(struct device *device, u32 attr, int channel,
 602                        long *val)
 603{
 604        struct w1_slave *sl = dev_get_drvdata(device);
 605        struct therm_info info;
 606        u8 fid = sl->family->fid;
 607        int ret;
 608
 609        switch (attr) {
 610        case hwmon_temp_input:
 611                ret = read_therm(device, sl, &info);
 612                if (ret)
 613                        return ret;
 614
 615                if (!info.verdict) {
 616                        ret = -EIO;
 617                        return ret;
 618                }
 619
 620                *val = w1_convert_temp(info.rom, fid);
 621                ret = 0;
 622                break;
 623        default:
 624                ret = -EOPNOTSUPP;
 625                break;
 626        }
 627
 628        return ret;
 629}
 630#endif
 631
 632#define W1_42_CHAIN     0x99
 633#define W1_42_CHAIN_OFF 0x3C
 634#define W1_42_CHAIN_OFF_INV     0xC3
 635#define W1_42_CHAIN_ON  0x5A
 636#define W1_42_CHAIN_ON_INV      0xA5
 637#define W1_42_CHAIN_DONE 0x96
 638#define W1_42_CHAIN_DONE_INV 0x69
 639#define W1_42_COND_READ 0x0F
 640#define W1_42_SUCCESS_CONFIRM_BYTE 0xAA
 641#define W1_42_FINISHED_BYTE 0xFF
 642static ssize_t w1_seq_show(struct device *device,
 643        struct device_attribute *attr, char *buf)
 644{
 645        struct w1_slave *sl = dev_to_w1_slave(device);
 646        ssize_t c = PAGE_SIZE;
 647        int rv;
 648        int i;
 649        u8 ack;
 650        u64 rn;
 651        struct w1_reg_num *reg_num;
 652        int seq = 0;
 653
 654        mutex_lock(&sl->master->bus_mutex);
 655        /* Place all devices in CHAIN state */
 656        if (w1_reset_bus(sl->master))
 657                goto error;
 658        w1_write_8(sl->master, W1_SKIP_ROM);
 659        w1_write_8(sl->master, W1_42_CHAIN);
 660        w1_write_8(sl->master, W1_42_CHAIN_ON);
 661        w1_write_8(sl->master, W1_42_CHAIN_ON_INV);
 662        msleep(sl->master->pullup_duration);
 663
 664        /* check for acknowledgment */
 665        ack = w1_read_8(sl->master);
 666        if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
 667                goto error;
 668
 669        /* In case the bus fails to send 0xFF, limit*/
 670        for (i = 0; i <= 64; i++) {
 671                if (w1_reset_bus(sl->master))
 672                        goto error;
 673
 674                w1_write_8(sl->master, W1_42_COND_READ);
 675                rv = w1_read_block(sl->master, (u8 *)&rn, 8);
 676                reg_num = (struct w1_reg_num *) &rn;
 677                if (reg_num->family == W1_42_FINISHED_BYTE)
 678                        break;
 679                if (sl->reg_num.id == reg_num->id)
 680                        seq = i;
 681
 682                w1_write_8(sl->master, W1_42_CHAIN);
 683                w1_write_8(sl->master, W1_42_CHAIN_DONE);
 684                w1_write_8(sl->master, W1_42_CHAIN_DONE_INV);
 685                w1_read_block(sl->master, &ack, sizeof(ack));
 686
 687                /* check for acknowledgment */
 688                ack = w1_read_8(sl->master);
 689                if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
 690                        goto error;
 691
 692        }
 693
 694        /* Exit from CHAIN state */
 695        if (w1_reset_bus(sl->master))
 696                goto error;
 697        w1_write_8(sl->master, W1_SKIP_ROM);
 698        w1_write_8(sl->master, W1_42_CHAIN);
 699        w1_write_8(sl->master, W1_42_CHAIN_OFF);
 700        w1_write_8(sl->master, W1_42_CHAIN_OFF_INV);
 701
 702        /* check for acknowledgment */
 703        ack = w1_read_8(sl->master);
 704        if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
 705                goto error;
 706        mutex_unlock(&sl->master->bus_mutex);
 707
 708        c -= snprintf(buf + PAGE_SIZE - c, c, "%d\n", seq);
 709        return PAGE_SIZE - c;
 710error:
 711        mutex_unlock(&sl->master->bus_mutex);
 712        return -EIO;
 713}
 714
 715static int __init w1_therm_init(void)
 716{
 717        int err, i;
 718
 719        for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
 720                err = w1_register_family(w1_therm_families[i].f);
 721                if (err)
 722                        w1_therm_families[i].broken = 1;
 723        }
 724
 725        return 0;
 726}
 727
 728static void __exit w1_therm_fini(void)
 729{
 730        int i;
 731
 732        for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
 733                if (!w1_therm_families[i].broken)
 734                        w1_unregister_family(w1_therm_families[i].f);
 735}
 736
 737module_init(w1_therm_init);
 738module_exit(w1_therm_fini);
 739
 740MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 741MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 742MODULE_LICENSE("GPL");
 743MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18S20));
 744MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1822));
 745MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18B20));
 746MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1825));
 747MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00));
 748