Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Oskar Schirmer <os-QdrG9jWwCLEAvxtiuMwx3w <at> public.gmane.org>
Subject: [patch] add pca9543 driver
Newsgroups: gmane.linux.kernel
Date: Thursday 26th March 2009 14:46:58 UTC (over 7 years ago)
support pca9543 i2c bus switch chip

Signed-off-by: Oskar Schirmer 
---
 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

+ *  Authors:	Fabian Godehardt 
+ *		Oskar Schirmer 
+ *
+ *  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 
+#include 
+#include 
+#include 
+#include 
+
+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
");
+MODULE_DESCRIPTION("pca9543 switch driver");
+MODULE_LICENSE("GPL");
+
+module_init(pca9543_init);
+module_exit(pca9543_exit);
-- 
1.6.2.107.ge47ee
 
CD: 3ms