226 lines
6.8 KiB
Diff
226 lines
6.8 KiB
Diff
Index: linux-2.6.30.9/drivers/i2c/busses/Kconfig
|
|
===================================================================
|
|
--- linux-2.6.30.9.orig/drivers/i2c/busses/Kconfig 2009-11-24 21:00:21.000000000 +0100
|
|
+++ linux-2.6.30.9/drivers/i2c/busses/Kconfig 2009-11-24 21:00:23.000000000 +0100
|
|
@@ -326,6 +326,10 @@
|
|
devices such as DaVinci NIC.
|
|
For details please see http://www.ti.com/davinci
|
|
|
|
+config I2C_EP93XX
|
|
+ tristate "EP93XX I2C"
|
|
+ depends on I2C && ARCH_EP93XX
|
|
+
|
|
config I2C_GPIO
|
|
tristate "GPIO-based bitbanging I2C"
|
|
depends on GENERIC_GPIO
|
|
Index: linux-2.6.30.9/drivers/i2c/busses/Makefile
|
|
===================================================================
|
|
--- linux-2.6.30.9.orig/drivers/i2c/busses/Makefile 2009-11-24 21:00:21.000000000 +0100
|
|
+++ linux-2.6.30.9/drivers/i2c/busses/Makefile 2009-11-24 21:00:23.000000000 +0100
|
|
@@ -30,6 +30,7 @@
|
|
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
|
|
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
|
|
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
|
|
+obj-$(CONFIG_I2C_EP93XX) += i2c-ep93xx.o
|
|
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
|
|
obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
|
|
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
|
|
Index: linux-2.6.30.9/drivers/i2c/busses/i2c-ep93xx.c
|
|
===================================================================
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ linux-2.6.30.9/drivers/i2c/busses/i2c-ep93xx.c 2009-11-24 21:00:38.000000000 +0100
|
|
@@ -0,0 +1,193 @@
|
|
+/* ------------------------------------------------------------------------ *
|
|
+ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx *
|
|
+ * ------------------------------------------------------------------------ *
|
|
+
|
|
+ Copyright (C) 2004 Michael Burian
|
|
+
|
|
+ Based on i2c-parport-light.c
|
|
+ Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
|
|
+
|
|
+ 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/config.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/ioport.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/i2c.h>
|
|
+#include <linux/i2c-algo-bit.h>
|
|
+#include <asm/io.h>
|
|
+#include <mach/hardware.h>
|
|
+
|
|
+//1/(2*clockfrequency)
|
|
+#define EE_DELAY_USEC 50
|
|
+#define GPIOG_EECLK 1
|
|
+#define GPIOG_EEDAT 2
|
|
+
|
|
+/* ----- I2C algorithm call-back functions and structures ----------------- */
|
|
+
|
|
+// TODO: optimize
|
|
+static void ep93xx_setscl(void *data, int state)
|
|
+{
|
|
+ unsigned int uiPGDR, uiPGDDR;
|
|
+
|
|
+ uiPGDR = inl(GPIO_PGDR);
|
|
+ uiPGDDR = inl(GPIO_PGDDR);
|
|
+
|
|
+ /* Configure the clock line as output. */
|
|
+ uiPGDDR |= GPIOG_EECLK;
|
|
+ outl(uiPGDDR, GPIO_PGDDR);
|
|
+
|
|
+ /* Set clock line to state */
|
|
+ if(state)
|
|
+ uiPGDR |= GPIOG_EECLK;
|
|
+ else
|
|
+ uiPGDR &= ~GPIOG_EECLK;
|
|
+
|
|
+ outl(uiPGDR, GPIO_PGDR);
|
|
+}
|
|
+
|
|
+static void ep93xx_setsda(void *data, int state)
|
|
+{
|
|
+ unsigned int uiPGDR, uiPGDDR;
|
|
+
|
|
+ uiPGDR = inl(GPIO_PGDR);
|
|
+ uiPGDDR = inl(GPIO_PGDDR);
|
|
+
|
|
+ /* Configure the data line as output. */
|
|
+ uiPGDDR |= GPIOG_EEDAT;
|
|
+ outl(uiPGDDR, GPIO_PGDDR);
|
|
+
|
|
+ /* Set data line to state */
|
|
+ if(state)
|
|
+ uiPGDR |= GPIOG_EEDAT;
|
|
+ else
|
|
+ uiPGDR &= ~GPIOG_EEDAT;
|
|
+
|
|
+ outl(uiPGDR, GPIO_PGDR);
|
|
+}
|
|
+
|
|
+static int ep93xx_getscl(void *data)
|
|
+{
|
|
+ unsigned int uiPGDR, uiPGDDR;
|
|
+
|
|
+ uiPGDR = inl(GPIO_PGDR);
|
|
+ uiPGDDR = inl(GPIO_PGDDR);
|
|
+
|
|
+ /* Configure the clock line as input */
|
|
+ uiPGDDR &= ~GPIOG_EECLK;
|
|
+ outl(uiPGDDR, GPIO_PGDDR);
|
|
+
|
|
+ /* Return state of the clock line */
|
|
+ return (inl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0;
|
|
+}
|
|
+
|
|
+static int ep93xx_getsda(void *data)
|
|
+{
|
|
+ unsigned int uiPGDR, uiPGDDR;
|
|
+ uiPGDR = inl(GPIO_PGDR);
|
|
+ uiPGDDR = inl(GPIO_PGDDR);
|
|
+
|
|
+ /* Configure the data line as input */
|
|
+ uiPGDDR &= ~GPIOG_EEDAT;
|
|
+ outl(uiPGDDR, GPIO_PGDDR);
|
|
+
|
|
+ /* Return state of the data line */
|
|
+ return (inl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0;
|
|
+}
|
|
+
|
|
+/* ------------------------------------------------------------------------
|
|
+ * Encapsulate the above functions in the correct operations structure.
|
|
+ * This is only done when more than one hardware adapter is supported.
|
|
+ */
|
|
+
|
|
+/* last line (us, ms, timeout)
|
|
+ * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps)
|
|
+ * 10ms not known
|
|
+ * 100ms timeout
|
|
+ */
|
|
+static struct i2c_algo_bit_data ep93xx_data = {
|
|
+ .setsda = ep93xx_setsda,
|
|
+ .setscl = ep93xx_setscl,
|
|
+ .getsda = ep93xx_getsda,
|
|
+ .getscl = ep93xx_getscl,
|
|
+ .udelay = 10,
|
|
+ //.mdelay = 10,
|
|
+ .timeout = HZ,
|
|
+};
|
|
+
|
|
+/* ----- I2c structure ---------------------------------------------------- */
|
|
+static struct i2c_adapter ep93xx_adapter = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .class = I2C_CLASS_HWMON,
|
|
+ .algo_data = &ep93xx_data,
|
|
+ .name = "EP93XX I2C bit-bang interface",
|
|
+};
|
|
+
|
|
+/* ----- Module loading, unloading and information ------------------------ */
|
|
+
|
|
+static int __init i2c_ep93xx_init(void)
|
|
+{
|
|
+ unsigned long uiPGDR, uiPGDDR;
|
|
+
|
|
+ /* Read the current value of the GPIO data and data direction registers. */
|
|
+ uiPGDR = inl(GPIO_PGDR);
|
|
+ uiPGDDR = inl(GPIO_PGDDR);
|
|
+
|
|
+ /* If the GPIO pins have not been configured since reset, the data
|
|
+ * and clock lines will be set as inputs and with data value of 0.
|
|
+ * External pullup resisters are pulling them high.
|
|
+ * Set them both high before configuring them as outputs. */
|
|
+ uiPGDR |= (GPIOG_EEDAT | GPIOG_EECLK);
|
|
+ outl(uiPGDR, GPIO_PGDR);
|
|
+
|
|
+ /* Delay to meet the EE Interface timing specification. */
|
|
+ udelay(EE_DELAY_USEC);
|
|
+
|
|
+
|
|
+ /* Configure the EE data and clock lines as outputs. */
|
|
+ uiPGDDR |= (GPIOG_EEDAT | GPIOG_EECLK);
|
|
+ outl(uiPGDDR, GPIO_PGDDR);
|
|
+
|
|
+ /* Delay to meet the EE Interface timing specification. */
|
|
+ udelay(EE_DELAY_USEC);
|
|
+
|
|
+ /* Reset hardware to a sane state (SCL and SDA high) */
|
|
+ ep93xx_setsda(NULL, 1);
|
|
+ ep93xx_setscl(NULL, 1);
|
|
+
|
|
+ if (i2c_bit_add_bus(&ep93xx_adapter) > 0) {
|
|
+ printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void __exit i2c_ep93xx_exit(void)
|
|
+{
|
|
+ //i2c_bit_del_bus(&ep93xx_adapter);
|
|
+ i2c_del_adapter(&ep93xx_adapter);
|
|
+}
|
|
+
|
|
+MODULE_AUTHOR("Michael Burian");
|
|
+MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors");
|
|
+MODULE_LICENSE("GPL");
|
|
+
|
|
+module_init(i2c_ep93xx_init);
|
|
+module_exit(i2c_ep93xx_exit);
|