[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1302706264-25815-6-git-send-email-haojian.zhuang@marvell.com>
Date: Wed, 13 Apr 2011 22:50:56 +0800
From: Haojian Zhuang <haojian.zhuang@...vell.com>
To: sameo@...ux.intel.com, haojian.zhuang@...il.com,
linux-kernel@...r.kernel.org
Cc: Haojian Zhuang <haojian.zhuang@...vell.com>,
Evgeniy Polyakov <johnpol@....mipt.ru>
Subject: [PATCH 05/13] w1: add DS278x slave driver
Append DS278x slave driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@...vell.com>
Cc: Evgeniy Polyakov <johnpol@....mipt.ru>
---
drivers/w1/slaves/Kconfig | 13 +++
drivers/w1/slaves/Makefile | 1 +
drivers/w1/slaves/w1_ds278x.c | 184 +++++++++++++++++++++++++++++++++++++++++
drivers/w1/w1_family.h | 3 +
4 files changed, 201 insertions(+), 0 deletions(-)
create mode 100644 drivers/w1/slaves/w1_ds278x.c
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index f0c9096..d737aa9 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -61,6 +61,19 @@ config W1_SLAVE_DS2760
If you are unsure, say N.
+config W1_SLAVE_DS278x
+ tristate "Dallas 278x battery monitor chip"
+ depends on W1
+ help
+ If you enable this you will have the DS278x battery monitor
+ chip support.
+
+ The battery monitor chip is used in many batteries/devices
+ as the one who is responsible for charging/discharging/monitoring
+ Li+ batteries.
+
+ If you are unsure, say N.
+
config W1_SLAVE_BQ27000
tristate "BQ27000 slave support"
depends on W1
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 3c76350..bcc134b 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o
obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o
obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
+obj-$(CONFIG_W1_SLAVE_DS278x) += w1_ds278x.o
obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o
diff --git a/drivers/w1/slaves/w1_ds278x.c b/drivers/w1/slaves/w1_ds278x.c
new file mode 100644
index 0000000..9da94bb
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds278x.c
@@ -0,0 +1,184 @@
+/*
+ * w1_ds278x.c - w1 family 27 (DS2780/DS2781) driver
+ *
+ * Copyright (c) Intel 2006 Stanley Cai <stanley.cai@...el.com>
+ * Copyright (c) Marvell 2007 Paul Shen <bo.a.shen@...vell.com>
+ *
+ * Modified from w1_ds2433 driver
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@...tec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#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 "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+
+#define W1_REG_SIZE 256
+
+#define W1_F27_READ_REG 0x69
+#define W1_F27_WRITE_REG 0x6C
+#define W1_F27_COPY_REG 0x48
+#define W1_F27_RECALL_REG 0xB8
+#define W1_F27_LOCK_REG 0x6A
+
+struct w1_f27_data {
+ u8 memory[W1_REG_SIZE];
+ u32 validcrc;
+};
+
+/**
+ * Check the file size bounds and adjusts count as needed.
+ * This would not be needed if the file size didn't reset to 0 after a write.
+ */
+static inline size_t w1_f27_fix_count(loff_t off, size_t count,
+ size_t size)
+{
+ if (off > size)
+ return 0;
+
+ if ((off + count) > size)
+ return (size - off);
+
+ return count;
+}
+
+static ssize_t w1_f27_read_bin(struct file *fp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ u8 wrbuf[2];
+
+ count = w1_f27_fix_count(off, count, W1_REG_SIZE);
+ if (count == 0)
+ return 0;
+
+ atomic_inc(&sl->refcnt);
+ mutex_lock(&sl->master->mutex);
+
+ /* read directly from the REG */
+ if (w1_reset_select_slave(sl)) {
+ count = -EIO;
+ goto out_mutex_unlock;
+ }
+
+ wrbuf[0] = W1_F27_READ_REG;
+ wrbuf[1] = off & 0xff;
+ w1_write_block(sl->master, wrbuf, 2);
+ w1_read_block(sl->master, buf, count);
+
+out_mutex_unlock:
+ mutex_unlock(&sl->master->mutex);
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+static ssize_t w1_f27_write_bin(struct file *fp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ char wrbuf[2];
+
+ count = w1_f27_fix_count(off, count, W1_REG_SIZE);
+ if (count == 0)
+ return 0;
+
+ atomic_inc(&sl->refcnt);
+ mutex_lock(&sl->master->mutex);
+
+ if (w1_reset_select_slave(sl)) {
+ count = -EIO;
+ goto out_mutex_unlock;
+ }
+
+ wrbuf[0] = W1_F27_WRITE_REG;
+ wrbuf[1] = off & 0xff;
+ w1_write_block(sl->master, wrbuf, 2);
+ w1_write_block(sl->master, buf, count);
+
+out_mutex_unlock:
+ mutex_unlock(&sl->master->mutex);
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+static struct bin_attribute w1_f27_bin_attr = {
+ .attr = {
+ .name = "registers",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = W1_REG_SIZE,
+ .read = w1_f27_read_bin,
+ .write = w1_f27_write_bin,
+};
+
+static int w1_f27_add_slave(struct w1_slave *sl)
+{
+ int err;
+
+ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f27_bin_attr);
+
+ return err;
+}
+
+static void w1_f27_remove_slave(struct w1_slave *sl)
+{
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f27_bin_attr);
+}
+
+static struct w1_family_ops w1_f27_fops = {
+ .add_slave = w1_f27_add_slave,
+ .remove_slave = w1_f27_remove_slave,
+};
+
+static struct w1_family w1_family_2780 = {
+ .fid = W1_BATTMON_DS2780,
+ .fops = &w1_f27_fops,
+};
+
+static struct w1_family w1_family_2781 = {
+ .fid = W1_BATTMON_DS2781,
+ .fops = &w1_f27_fops,
+};
+
+static struct w1_family w1_family_2783 = {
+ .fid = W1_BATTMON_DS2783,
+ .fops = &w1_f27_fops,
+};
+
+
+static int __init w1_f27_init(void)
+{
+ pr_info("1-Wire driver for the DS278x battery monitor...\n");
+ return (w1_register_family(&w1_family_2780) |
+ w1_register_family(&w1_family_2781) |
+ w1_register_family(&w1_family_2783));
+}
+
+static void __exit w1_f27_fini(void)
+{
+ w1_unregister_family(&w1_family_2781);
+ w1_unregister_family(&w1_family_2780);
+ w1_unregister_family(&w1_family_2783);
+}
+
+module_init(w1_f27_init);
+module_exit(w1_f27_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Shen <bo.a.shen@...vell.com>");
+MODULE_DESCRIPTION("w1 family 27 driver for DS2780 & DS2781,"
+ " Stand-Alone Fuel Gauge IC");
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index f3b636d..0f0b58c 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -36,6 +36,9 @@
#define W1_THERM_DS18B20 0x28
#define W1_EEPROM_DS2431 0x2D
#define W1_FAMILY_DS2760 0x30
+#define W1_BATTMON_DS2780 0x32
+#define W1_BATTMON_DS2781 0x3D
+#define W1_BATTMON_DS2783 0x34
#define MAXNAMELEN 32
--
1.5.6.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists