This patch contains w1 sysfs slave driver and openwrt support for ds2423 
1-wire counter chipset. Same driver works at least with 2.6.32, 2.6.34 and 
2.6.36 
kernels. I have submitted the same driver to kernel mailing list and 
it's now in -mm patch series waiting for the 2.6.38 merge window to open.

I have tested the patch with openwrt trunk.

>From 3c3fe9d120a75d37276e8036288645db9865cc03 Mon Sep 17 00:00:00 2001
From: Mika Laitio <[email protected]>
Date: Mon, 8 Nov 2010 21:30:15 +0200
Subject: [PATCH 2/2] ds2423 1-wire counter support


Signed-off-by: Mika Laitio <[email protected]>
---
 package/kernel/modules/w1.mk                       |   15 ++
 target/linux/generic/config-2.6.34                 |    1 +
 ...s2423-w1-counter-driver-and-documentation.patch |  242 ++++++++++++++++++++
 3 files changed, 258 insertions(+), 0 deletions(-)
 create mode 100644 
target/linux/generic/patches-2.6.34/270-ds2423-w1-counter-driver-and-documentation.patch

diff --git a/package/kernel/modules/w1.mk b/package/kernel/modules/w1.mk
index c1c7665..c2f446f 100644
--- a/package/kernel/modules/w1.mk
+++ b/package/kernel/modules/w1.mk
@@ -98,6 +98,21 @@ endef
 $(eval $(call KernelPackage,w1-slave-smem))
 
 
+define KernelPackage/w1-slave-ds2423
+  TITLE:=1-Wire Counter device support (DS2423)
+  KCONFIG:= CONFIG_W1_SLAVE_DS2423
+  FILES:=$(W1_SLAVES_DIR)/w1_ds2423.ko
+  AUTOLOAD:=$(call AutoLoad,70,w1_ds2423)
+  $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-slave-ds2423/description
+  Kernel module for 1-wire counter(ds2423)
+endef
+
+$(eval $(call KernelPackage,w1-slave-ds2423))
+
+
 define KernelPackage/w1-slave-ds2433
   TITLE:=Simple 64bit memory family implementation
   KCONFIG:= \
diff --git a/target/linux/generic/config-2.6.34 
b/target/linux/generic/config-2.6.34
index bde140f..ef53f67 100644
--- a/target/linux/generic/config-2.6.34
+++ b/target/linux/generic/config-2.6.34
@@ -2903,6 +2903,7 @@ CONFIG_VMSPLIT_3G=y
 # CONFIG_W1_MASTER_GPIO is not set
 # CONFIG_W1_MASTER_MATROX is not set
 # CONFIG_W1_SLAVE_BQ27000 is not set
+# CONFIG_W1_SLAVE_DS2423 is not set
 # CONFIG_W1_SLAVE_DS2431 is not set
 # CONFIG_W1_SLAVE_DS2433 is not set
 # CONFIG_W1_SLAVE_DS2760 is not set
diff --git 
a/target/linux/generic/patches-2.6.34/270-ds2423-w1-counter-driver-and-documentation.patch
 
b/target/linux/generic/patches-2.6.34/270-ds2423-w1-counter-driver-and-documentation.patch
new file mode 100644
index 0000000..5d2010f
--- /dev/null
+++ 
b/target/linux/generic/patches-2.6.34/270-ds2423-w1-counter-driver-and-documentation.patch
@@ -0,0 +1,242 @@
+From 01a34a50eb40a27dfc52a0c802c0003269d9c2d6 Mon Sep 17 00:00:00 2001
+From: Mika Laitio <[email protected]>
+Date: Fri, 5 Nov 2010 16:31:39 +0200
+Subject: [PATCH] w1 driver for DS2423
+
+
+Signed-off-by: Mika Laitio <[email protected]>
+---
+ Documentation/w1/slaves/w1_ds2423 |   47 +++++++++++
+ drivers/w1/slaves/w1_ds2423.c     |  166 +++++++++++++++++++++++++++++++++++++
+ 2 files changed, 213 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/w1/slaves/w1_ds2423
+ create mode 100644 drivers/w1/slaves/w1_ds2423.c
+
+diff --git a/Documentation/w1/slaves/w1_ds2423 
b/Documentation/w1/slaves/w1_ds2423
+new file mode 100644
+index 0000000..90a65d2
+--- /dev/null
++++ b/Documentation/w1/slaves/w1_ds2423
+@@ -0,0 +1,47 @@
++Kernel driver w1_ds2423
++=======================
++
++Supported chips:
++  * Maxim DS2423 based counter devices.
++
++supported family codes:
++      W1_THERM_DS2423 0x1D
++
++Author: Mika Laitio <[email protected]>
++
++Description
++-----------
++
++Support is provided through the sysfs w1_slave file. Each opening and
++read sequence of w1_slave file initiates the read of counters and ram
++available in DS2423 pages 12 - 15.
++
++Result of each page is provided as an ASCII output where each counter
++value and associated ram buffer is outpputed to own line.
++
++Each lines will contain the values of 42 bytes read from the counter and
++memory page along the crc=YES or NO for indicating whether the read operation
++was successfull and CRC matched.
++If the operation was successfull, there is also in the end of each line
++a counter value expressed as an integer after c=
++
++Meaning of 42 bytes represented is following:
++ - 1 byte from ram page
++ - 4 bytes for the counter value
++ - 4 zero bytes
++ - 2 bytes for crc16 which was calculated from the data read since the 
previous crc bytes
++ - 31 remaining bytes from the ram page
++ - crc=YES/NO indicating whether read was ok and crc matched
++ - c=<int> current counter value
++
++example from the successfull read:
++00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 
00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
++00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 
00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
++00 29 c6 5d 18 00 00 00 00 04 37 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 
00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408798761
++00 05 00 00 00 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=YES c=5
++
++example from the read with crc errors:
++00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 
00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
++00 02 00 00 22 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 
00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO
++00 e1 61 5d 19 00 00 00 00 df 0b 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 
00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=NO
++00 05 00 00 20 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=NO
+diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c
+new file mode 100644
+index 0000000..7a7dbe5
+--- /dev/null
++++ b/drivers/w1/slaves/w1_ds2423.c
+@@ -0,0 +1,166 @@
++/*
++ *    w1_ds2423.c
++ *
++ * Copyright (c) 2010 Mika Laitio <[email protected]>
++ *
++ * This driver will read and write the value of 4 counters to w1_slave file in
++ * sys filesystem.
++ * Inspired by the w1_therm and w1_ds2431 drivers.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the therms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/crc16.h>
++
++#include "../w1.h"
++#include "../w1_int.h"
++#include "../w1_family.h"
++
++#define CRC16_VALID   0xb001
++#define CRC16_INIT    0
++
++#define COUNTER_COUNT 4
++#define READ_BYTE_COUNT 42
++
++static ssize_t w1_counter_read(struct device *device,
++      struct device_attribute *attr, char *buf);
++
++static struct device_attribute w1_counter_attr =
++      __ATTR(w1_slave, S_IRUGO, w1_counter_read, NULL);
++
++static ssize_t w1_counter_read(struct device *device,
++      struct device_attribute *attr, char *out_buf)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      struct w1_master *dev = sl->master;
++      u8 rbuf[COUNTER_COUNT * READ_BYTE_COUNT];
++      u8 wrbuf[3];
++      int rom_addr;
++      int read_byte_count;
++      int result;
++      ssize_t c;
++      int ii;
++      int p;
++      int crc;
++
++      c               = PAGE_SIZE;
++      rom_addr        = (12 << 5) + 31;
++      wrbuf[0]        = 0xA5;
++      wrbuf[1]        = rom_addr & 0xFF;
++      wrbuf[2]        = rom_addr >> 8;
++      mutex_lock(&dev->mutex);
++      if (!w1_reset_select_slave(sl)) {
++              w1_write_block(dev, wrbuf, 3);
++              read_byte_count = 0;
++              for (p = 0; p < 4; p++) {
++                      /*
++                       * 1 byte for first bytes in ram page read
++                       * 4 bytes for counter
++                       * 4 bytes for zero bits
++                       * 2 bytes for crc
++                       * 31 remaining bytes from the ram page
++                       */
++                      read_byte_count += w1_read_block(dev,
++                              rbuf + (p * READ_BYTE_COUNT), READ_BYTE_COUNT);
++                      for (ii = 0; ii < READ_BYTE_COUNT; ++ii)
++                              c -= snprintf(out_buf + PAGE_SIZE - c,
++                                      c, "%02x ",
++                                      rbuf[(p * READ_BYTE_COUNT) + ii]);
++                      if (read_byte_count != (p + 1) * READ_BYTE_COUNT) {
++                              dev_warn(device,
++                                      "w1_counter_read() returned %u bytes "
++                                      "instead of %d bytes wanted.\n",
++                                      read_byte_count,
++                                      READ_BYTE_COUNT);
++                              c -= snprintf(out_buf + PAGE_SIZE - c,
++                                      c, "crc=NO\n");
++                      } else {
++                              if (p == 0) {
++                                      crc = crc16(CRC16_INIT, wrbuf, 3);
++                                      crc = crc16(crc, rbuf, 11);
++                              } else {
++                                      /*
++                                       * DS2423 calculates crc from all bytes
++                                       * read after the previous crc bytes.
++                                       */
++                                      crc = crc16(CRC16_INIT,
++                                              (rbuf + 11) +
++                                              ((p - 1) * READ_BYTE_COUNT),
++                                              READ_BYTE_COUNT);
++                              }
++                              if (crc == CRC16_VALID) {
++                                      result = 0;
++                                      for (ii = 4; ii > 0; ii--) {
++                                              result <<= 8;
++                                              result |= rbuf[(p *
++                                                      READ_BYTE_COUNT) + ii];
++                                      }
++                                      c -= snprintf(out_buf + PAGE_SIZE - c,
++                                              c, "crc=YES c=%d\n", result);
++                              } else {
++                                      c -= snprintf(out_buf + PAGE_SIZE - c,
++                                              c, "crc=NO\n");
++                              }
++                      }
++              }
++      } else {
++              c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error");
++      }
++      mutex_unlock(&dev->mutex);
++      return PAGE_SIZE - c;
++}
++
++static int w1_f1d_add_slave(struct w1_slave *sl)
++{
++      return device_create_file(&sl->dev, &w1_counter_attr);
++}
++
++static void w1_f1d_remove_slave(struct w1_slave *sl)
++{
++      device_remove_file(&sl->dev, &w1_counter_attr);
++}
++
++static struct w1_family_ops w1_f1d_fops = {
++      .add_slave      = w1_f1d_add_slave,
++      .remove_slave   = w1_f1d_remove_slave,
++};
++
++static struct w1_family w1_family_1d = {
++      .fid = W1_COUNTER_DS2423,
++      .fops = &w1_f1d_fops,
++};
++
++static int __init w1_f1d_init(void)
++{
++      return w1_register_family(&w1_family_1d);
++}
++
++static void __exit w1_f1d_exit(void)
++{
++      w1_unregister_family(&w1_family_1d);
++}
++
++module_init(w1_f1d_init);
++module_exit(w1_f1d_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Mika Laitio <[email protected]>");
++MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram");
+-- 
+1.7.1
+
-- 
1.7.1


-- 
Mika
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to