lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1238078818-25977-1-git-send-email-os@emlix.com>
Date:	Thu, 26 Mar 2009 15:46:58 +0100
From:	Oskar Schirmer <os@...ix.com>
To:	Ben Dooks <ben-linux@...ff.org>
Cc:	Chris Zankel <chris@...kel.net>, linux-i2c@...r.kernel.org,
	linux-kernel@...r.kernel.org, Oskar Schirmer <os@...ix.com>
Subject: [patch] add pca9543 driver

support pca9543 i2c bus switch chip

Signed-off-by: Oskar Schirmer <os@...ix.com>
---
 drivers/i2c/chips/Kconfig   |    3 +
 drivers/i2c/chips/Makefile  |    1 +
 drivers/i2c/chips/pca9543.c |  188 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 192 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/chips/pca9543.c

diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index c80312c..acfc46f 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -64,6 +64,9 @@ config SENSORS_PCA9539
 	  This driver is deprecated and will be dropped soon. Use
 	  drivers/gpio/pca953x.c instead.
 
+config PCA9543
+	tristate "Philips PCA9543 i2c bus switch"
+
 config SENSORS_PCF8591
 	tristate "Philips PCF8591"
 	depends on EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index d142f23..c7a7fe2 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -13,6 +13,7 @@
 obj-$(CONFIG_DS1682)		+= ds1682.o
 obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
 obj-$(CONFIG_SENSORS_PCA9539)	+= pca9539.o
+obj-$(CONFIG_PCA9543)		+= pca9543.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_PCF8575)		+= pcf8575.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
diff --git a/drivers/i2c/chips/pca9543.c b/drivers/i2c/chips/pca9543.c
new file mode 100644
index 0000000..ee59497
--- /dev/null
+++ b/drivers/i2c/chips/pca9543.c
@@ -0,0 +1,188 @@
+/*
+ *  pca9543.c - i2c channel switch
+ *
+ *  Copyright (C) 2008 Emlix GmbH <info@...ix.com>
+ *  Authors:	Fabian Godehardt <fg@...ix.com>
+ *		Oskar Schirmer <os@...ix.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+struct pca9543_data {
+	struct mutex lock;
+	struct i2c_client *client;
+};
+
+static ssize_t pca9543_read(struct pca9543_data *data, char *buf, size_t count)
+{
+	int stat;
+	struct i2c_msg msg;
+	mutex_lock(&data->lock);
+	msg.addr = data->client->addr;
+	msg.flags = I2C_M_RD;
+	msg.buf = buf;
+	msg.len = 1;
+	stat = i2c_transfer(data->client->adapter, &msg, 1);
+	mutex_unlock(&data->lock);
+	if ((stat >= 0) && (stat != 1))
+		stat = -EIO;
+	return stat;
+}
+
+static ssize_t pca9543_bin_read(struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct pca9543_data *data;
+	data = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (unlikely(!count))
+		return count;
+	if (off)
+		return -EINVAL;
+	return pca9543_read(data, buf, count);
+}
+
+static ssize_t pca9543_write(struct pca9543_data *data, char *buf, size_t count)
+{
+	int stat;
+	struct i2c_msg msg;
+	mutex_lock(&data->lock);
+	msg.addr = data->client->addr;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = 1;
+	stat = i2c_transfer(data->client->adapter, &msg, 1);
+	mutex_unlock(&data->lock);
+	if ((stat >= 0) && (stat != 1))
+		stat = -EIO;
+	return stat;
+}
+
+static ssize_t pca9543_bin_write(struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct pca9543_data *data;
+	data = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (unlikely(!count))
+		return count;
+	if (off)
+		return -EINVAL;
+	return pca9543_write(data, buf, count);
+}
+
+static struct bin_attribute pca9543_attr = {
+	.attr = {
+		.name = "switch",
+		.mode = S_IRUGO | S_IWUSR,
+	},
+	.size = 1,
+	.read = pca9543_bin_read,
+	.write = pca9543_bin_write,
+};
+
+int pca9543_set_switch(struct i2c_client *client, unsigned value)
+{
+	struct pca9543_data *data;
+	u8 buf;
+	int ret;
+	data = i2c_get_clientdata(client);
+	buf = value;
+	ret = pca9543_write(data, &buf, 1);
+	if (ret > 0)
+		ret = 0;
+	return ret;
+}
+EXPORT_SYMBOL(pca9543_set_switch);
+
+static int pca9543_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	int err;
+	struct pca9543_data *data;
+	void (*cbf)(struct i2c_client *, int(*)(struct i2c_client *, unsigned));
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		printk(KERN_ERR "pca9543 probe failure\n");
+		err = -EPFNOSUPPORT;
+		goto err;
+	}
+	data = kzalloc(sizeof(struct pca9543_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto err;
+	}
+	mutex_init(&data->lock);
+	data->client = client;
+	err = sysfs_create_bin_file(&client->dev.kobj, &pca9543_attr);
+	if (err)
+		goto errmem;
+	i2c_set_clientdata(client, data);
+	dev_info(&client->dev,
+		"pca9543 i2c switch @ x%02x\n", client->addr);
+	cbf = client->dev.platform_data;
+	if (cbf)
+		cbf(client, &pca9543_set_switch);
+	return 0;
+errmem:
+	kfree(data);
+err:
+	return err;
+}
+
+static int pca9543_remove(struct i2c_client *client)
+{
+	struct pca9543_data *data;
+	data = i2c_get_clientdata(client);
+	sysfs_remove_bin_file(&client->dev.kobj, &pca9543_attr);
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id pca9543_id[] = {
+	{ "pca9543", 0 },
+	{ }
+};
+
+static struct i2c_driver pca9543_driver = {
+	.driver = {
+		.name = "pca9543",
+		.owner = THIS_MODULE,
+	},
+	.probe = pca9543_probe,
+	.remove = pca9543_remove,
+	.id_table = pca9543_id,
+};
+
+static int __init pca9543_init(void)
+{
+	return i2c_add_driver(&pca9543_driver);
+}
+
+static void __exit pca9543_exit(void)
+{
+	i2c_del_driver(&pca9543_driver);
+}
+
+MODULE_AUTHOR("emlix GmbH <info@...ix.com>");
+MODULE_DESCRIPTION("pca9543 switch driver");
+MODULE_LICENSE("GPL");
+
+module_init(pca9543_init);
+module_exit(pca9543_exit);
-- 
1.6.2.107.ge47ee

--
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ