[i2c] problem with DS1337 RTC connected to Cirrus Logic EP93XX
Lennert Buytenhek
buytenh at wantstofly.org
Mon Apr 30 15:12:59 CEST 2007
On Mon, Apr 30, 2007 at 03:07:34PM +0200, Jean Delvare wrote:
> i2c-algo-bit is a software thing only. You need an I2C bus driver to
> bind it to the physical EEDAT & EECLK lines. I seem to remember a
> driver named i2c-ep93xx, except that it is not in mainline. I found
> this:
> https://dev.contec.at/dev/micro/micro9/LINUX/trunk/kernel/linux-2.6/patches/ep93xx-i2c-bus.diff
> But I don't know how up-to-date it is. You may want to contact Lennert
> Buytenhek for a status update.
The latest one I have is:
http://svn.wantstofly.org/kernel/ep93xx-i2c-bus.diff
This seems like a nice opportunity to pimp the driver for
upstream inclusion. I've attached it below. How does it look?
thanks,
Lennert
I2C bus driver using ep93xx GPIOs.
Signed-off-by: Lennert Buytenhek <buytenh at wantstofly.org>
Index: linux-2.6.21-rc5/drivers/i2c/busses/Kconfig
===================================================================
--- linux-2.6.21-rc5.orig/drivers/i2c/busses/Kconfig
+++ linux-2.6.21-rc5/drivers/i2c/busses/Kconfig
@@ -583,4 +583,16 @@ config I2C_PNX
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
+config I2C_EP93XX
+ tristate "Cirrus Logic EP93XX GPIO-based I2C interface"
+ depends on I2C && ARCH_EP93XX
+ select I2C_ALGOBIT
+ help
+ Say Y here if you have an Cirrus Logic EP93XX based
+ system and are using GPIO lines for an I2C bus.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-ep93xx.
+
+
endmenu
Index: linux-2.6.21-rc5/drivers/i2c/busses/Makefile
===================================================================
--- linux-2.6.21-rc5.orig/drivers/i2c/busses/Makefile
+++ linux-2.6.21-rc5/drivers/i2c/busses/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
+obj-$(CONFIG_I2C_EP93XX) += i2c-ep93xx.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
EXTRA_CFLAGS += -DDEBUG
Index: linux-2.6.21-rc5/drivers/i2c/busses/i2c-ep93xx.c
===================================================================
--- /dev/null
+++ linux-2.6.21-rc5/drivers/i2c/busses/i2c-ep93xx.c
@@ -0,0 +1,159 @@
+/*
+ * EP93XX I2C bus driver.
+ * Copyright (C) 2007 Lennert Buytenhek <buytenh at wantstofly.org>
+ *
+ * An I2C bus driver for the Cirrus Logic EP93xx SoC.
+ *
+ * Based on an earlier version by Alessandro Zummo.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <asm/hardware.h>
+#include <asm/arch/gpio.h>
+
+struct ep93xx_i2c_priv {
+ struct ep93xx_i2c_data *data;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo_data;
+ int sda;
+ int scl;
+};
+
+
+static void ep93xx_bit_setsda(void *cookie, int val)
+{
+ struct ep93xx_i2c_priv *priv = cookie;
+
+ if (val) {
+ gpio_line_config(priv->data->sda_pin, GPIO_IN);
+ if (priv->scl && !priv->sda && priv->data->stop != NULL)
+ priv->data->stop(priv->data->cookie);
+ priv->sda = 1;
+ } else {
+ if (priv->scl && priv->sda && priv->data->start != NULL)
+ priv->data->start(priv->data->cookie);
+ gpio_line_config(priv->data->sda_pin, GPIO_OUT);
+ gpio_line_set(priv->data->sda_pin, 0);
+ priv->sda = 0;
+ }
+}
+
+static void ep93xx_bit_setscl(void *cookie, int val)
+{
+ struct ep93xx_i2c_priv *priv = cookie;
+
+ if (val) {
+ gpio_line_config(priv->data->scl_pin, GPIO_IN);
+ priv->scl = 1;
+ } else {
+ gpio_line_config(priv->data->scl_pin, GPIO_OUT);
+ gpio_line_set(priv->data->scl_pin, 0);
+ priv->scl = 0;
+ }
+}
+
+static int ep93xx_bit_getsda(void *cookie)
+{
+ struct ep93xx_i2c_priv *priv = cookie;
+
+ if (priv->sda == 0)
+ BUG();
+
+ return gpio_line_get(priv->data->sda_pin);
+}
+
+static int ep93xx_bit_getscl(void *cookie)
+{
+ struct ep93xx_i2c_priv *priv = cookie;
+
+ if (priv->scl == 0)
+ BUG();
+
+ return gpio_line_get(priv->data->scl_pin);
+}
+
+
+static int ep93xx_i2c_probe(struct platform_device *pdev)
+{
+ struct ep93xx_i2c_priv *priv;
+ int err;
+
+ priv = kzalloc(sizeof(struct ep93xx_i2c_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ priv->data = pdev->dev.platform_data;
+
+ strlcpy(priv->adapter.name, pdev->dev.driver->name, I2C_NAME_SIZE);
+ priv->adapter.algo_data = &priv->algo_data;
+ priv->adapter.class = I2C_CLASS_ALL;
+ priv->adapter.dev.parent = &pdev->dev;
+
+ priv->algo_data.data = priv;
+ priv->algo_data.setsda = ep93xx_bit_setsda;
+ priv->algo_data.setscl = ep93xx_bit_setscl;
+ priv->algo_data.getsda = ep93xx_bit_getsda;
+ priv->algo_data.getscl = ep93xx_bit_getscl;
+ priv->algo_data.udelay = 10;
+ priv->algo_data.timeout = 100;
+
+ priv->sda = 1;
+ gpio_line_config(priv->data->sda_pin, GPIO_IN);
+
+ priv->scl = 1;
+ gpio_line_config(priv->data->scl_pin, GPIO_IN);
+
+ err = i2c_bit_add_bus(&priv->adapter);
+ if (err) {
+ printk(KERN_ERR "ERROR: Could not install %s\n",
+ pdev->dev.bus_id);
+ kfree(priv);
+ return err;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+}
+
+static int ep93xx_i2c_remove(struct platform_device *pdev)
+{
+ struct ep93xx_i2c_priv *priv;
+
+ priv = platform_get_drvdata(pdev);
+ i2c_del_adapter(&priv->adapter);
+ platform_set_drvdata(pdev, NULL);
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver ep93xx_i2c_driver = {
+ .probe = ep93xx_i2c_probe,
+ .remove = ep93xx_i2c_remove,
+ .driver = {
+ .name = "ep93xx-i2c",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ep93xx_i2c_init(void)
+{
+ return platform_driver_register(&ep93xx_i2c_driver);
+}
+
+static void __exit ep93xx_i2c_exit(void)
+{
+ platform_driver_unregister(&ep93xx_i2c_driver);
+}
+
+module_init(ep93xx_i2c_init);
+module_exit(ep93xx_i2c_exit);
+
+MODULE_AUTHOR("Lennert Buytenhek <buytenh at wantstofly.org>");
+MODULE_DESCRIPTION("GPIO-based I2C adapter for EP93XX systems");
+MODULE_LICENSE("GPL");
Index: linux-2.6.21-rc5/include/asm-arm/arch-ep93xx/platform.h
===================================================================
--- linux-2.6.21-rc5.orig/include/asm-arm/arch-ep93xx/platform.h
+++ linux-2.6.21-rc5/include/asm-arm/arch-ep93xx/platform.h
@@ -22,5 +22,13 @@ struct ep93xx_eth_data
unsigned char phy_id;
};
+struct ep93xx_i2c_data {
+ int sda_pin;
+ int scl_pin;
+ void *cookie;
+ void (*start)(void *);
+ void (*stop)(void *);
+};
+
#endif
More information about the i2c
mailing list