patch-2.4.13 linux/drivers/i2c/i2c-elektor.c

Next file: linux/drivers/i2c/i2c-elv.c
Previous file: linux/drivers/i2c/i2c-dev.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.12/linux/drivers/i2c/i2c-elektor.c linux/drivers/i2c/i2c-elektor.c
@@ -22,7 +22,8 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-elektor.c,v 1.19 2000/07/25 23:52:17 frodo Exp $ */
+/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of 
+   for Alpha Processor Inc. UP-2000(+) boards */
 
 #include <linux/kernel.h>
 #include <linux/ioport.h>
@@ -31,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/init.h>
+#include <linux/pci.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 
@@ -39,17 +41,20 @@
 #include <linux/i2c-elektor.h>
 #include "i2c-pcf8584.h"
 
-#define DEFAULT_BASE 0x300
-#define DEFAULT_IRQ      0
-#define DEFAULT_CLOCK 0x1c
-#define DEFAULT_OWN   0x55
-
-static int base  = 0;
-static int irq   = 0;
-static int clock = 0;
-static int own   = 0;
-static int i2c_debug=0;
-static struct i2c_pcf_isa gpi;
+#define DEFAULT_BASE 0x330
+
+static int base   = 0;
+static int irq    = 0;
+static int clock  = 0x1c;
+static int own    = 0x55;
+static int mmapped = 0;
+static int i2c_debug = 0;
+
+/* vdovikin: removed static struct i2c_pcf_isa gpi; code - 
+  this module in real supports only one device, due to missing arguments
+  in some functions, called from the algo-pcf module. Sometimes it's
+  need to be rewriten - but for now just remove this for simpler reading */
+
 #if (LINUX_VERSION_CODE < 0x020301)
 static struct wait_queue *pcf_wait = NULL;
 #else
@@ -63,81 +68,63 @@
 #define DEB3(x) if (i2c_debug>=3) x
 #define DEBE(x)	x	/* error messages 				*/
 
-
-/* --- Convenience defines for the i2c port:			*/
-#define BASE	((struct i2c_pcf_isa *)(data))->pi_base
-#define DATA	BASE			/* Adapter data port		*/
-#define CTRL	(BASE+1)		/* Adapter control port	        */
-
 /* ----- local functions ----------------------------------------------	*/
 
 static void pcf_isa_setbyte(void *data, int ctl, int val)
 {
-        unsigned long j = jiffies + 10;
+	int address = ctl ? (base + 1) : base;
 
-        if (ctl) {
-		if (gpi.pi_irq > 0) {
-			DEB3(printk("i2c-elektor.o: Write Ctrl 0x%02X\n",
-			     val|I2C_PCF_ENI));
-                        DEB3({while (jiffies < j) schedule();})
-			outb(val | I2C_PCF_ENI, CTRL);
-		} else {
-			 DEB3(printk("i2c-elektor.o: Write Ctrl 0x%02X\n", val|I2C_PCF_ENI));
-                         DEB3({while (jiffies < j) schedule();})
-			 outb(val|I2C_PCF_ENI, CTRL);
-		}
-	} else {
-		DEB3(printk("i2c-elektor.o: Write Data 0x%02X\n", val&0xff));
-                DEB3({while (jiffies < j) schedule();})
-		outb(val, DATA);
+	if (ctl && irq) {
+		val |= I2C_PCF_ENI;
+	}
+
+	DEB3(printk("i2c-elektor.o: Write 0x%X 0x%02X\n", address, val & 255));
+
+	switch (mmapped) {
+	case 0: /* regular I/O */
+		outb(val, address);
+		break;
+	case 2: /* double mapped I/O needed for UP2000 board,
+                   I don't know why this... */
+		writeb(val, address);
+		/* fall */
+	case 1: /* memory mapped I/O */
+		writeb(val, address);
+		break;
 	}
 }
 
 static int pcf_isa_getbyte(void *data, int ctl)
 {
-	int val;
+	int address = ctl ? (base + 1) : base;
+	int val = mmapped ? readb(address) : inb(address);
+
+	DEB3(printk("i2c-elektor.o: Read 0x%X 0x%02X\n", address, val));
 
-	if (ctl) {
-		val = inb(CTRL);
-		DEB3(printk("i2c-elektor.o: Read Ctrl 0x%02X\n", val));
-	} else {
-		val = inb(DATA);
-		DEB3(printk("i2c-elektor.o: Read Data 0x%02X\n", val));
-	}
 	return (val);
 }
 
 static int pcf_isa_getown(void *data)
 {
-	return (gpi.pi_own);
+	return (own);
 }
 
 
 static int pcf_isa_getclock(void *data)
 {
-	return (gpi.pi_clock);
-}
-
-
-
-#if 0
-static void pcf_isa_sleep(unsigned long timeout)
-{
-	schedule_timeout( timeout * HZ);
+	return (clock);
 }
-#endif
-
 
 static void pcf_isa_waitforpin(void) {
 
 	int timeout = 2;
 
-	if (gpi.pi_irq > 0) {
+	if (irq > 0) {
 		cli();
-	if (pcf_pending == 0) {
-		interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
-	} else
-		pcf_pending = 0;
+		if (pcf_pending == 0) {
+			interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
+		} else
+			pcf_pending = 0;
 		sti();
 	} else {
 		udelay(100);
@@ -153,30 +140,34 @@
 
 static int pcf_isa_init(void)
 {
-	if (check_region(gpi.pi_base, 2) < 0 ) {
-		return -ENODEV;
-	} else {
-		request_region(gpi.pi_base, 2, "i2c (isa bus adapter)");
+	if (!mmapped) {
+		if (check_region(base, 2) < 0 ) {
+			printk("i2c-elektor.o: requested I/O region (0x%X:2) is in use.\n", base);
+			return -ENODEV;
+		} else {
+			request_region(base, 2, "i2c (isa bus adapter)");
+		}
 	}
-	if (gpi.pi_irq > 0) {
-		if (request_irq(gpi.pi_irq, pcf_isa_handler, 0, "PCF8584", 0)
-		    < 0) {
-		printk("i2c-elektor.o: Request irq%d failed\n", gpi.pi_irq);
-		gpi.pi_irq = 0;
-	} else
-		enable_irq(gpi.pi_irq);
+	if (irq > 0) {
+		if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) {
+			printk("i2c-elektor.o: Request irq%d failed\n", irq);
+			irq = 0;
+		} else
+			enable_irq(irq);
 	}
 	return 0;
 }
 
 
-static void pcf_isa_exit(void)
+static void __exit pcf_isa_exit(void)
 {
-	if (gpi.pi_irq > 0) {
-		disable_irq(gpi.pi_irq);
-		free_irq(gpi.pi_irq, 0);
+	if (irq > 0) {
+		disable_irq(irq);
+		free_irq(irq, 0);
+	}
+	if (!mmapped) {
+		release_region(base , 2);
 	}
-	release_region(gpi.pi_base , 2);
 }
 
 
@@ -217,7 +208,7 @@
 	pcf_isa_getown,
 	pcf_isa_getclock,
 	pcf_isa_waitforpin,
-	80, 80, 100,		/*	waits, timeout */
+	10, 10, 100,		/*	waits, timeout */
 };
 
 static struct i2c_adapter pcf_isa_ops = {
@@ -233,31 +224,61 @@
 
 int __init i2c_pcfisa_init(void) 
 {
+#ifdef __alpha__
+	/* check to see we have memory mapped PCF8584 connected to the 
+	Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
+	if ((base == 0) && pci_present()) {
+		
+		struct pci_dev *cy693_dev =
+                    pci_find_device(PCI_VENDOR_ID_CONTAQ, 
+		                    PCI_DEVICE_ID_CONTAQ_82C693, NULL);
+
+		if (cy693_dev) {
+			char config;
+			/* yeap, we've found cypress, let's check config */
+			if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
+				
+				DEB3(printk("i2c-elektor.o: found cy82c693, config register 0x47 = 0x%02x.\n", config));
+
+				/* UP2000 board has this register set to 0xe1,
+                                   but the most significant bit as seems can be 
+				   reset during the proper initialisation
+                                   sequence if guys from API decides to do that
+                                   (so, we can even enable Tsunami Pchip
+                                   window for the upper 1 Gb) */
+
+				/* so just check for ROMCS at 0xe0000,
+                                   ROMCS enabled for writes
+				   and external XD Bus buffer in use. */
+				if ((config & 0x7f) == 0x61) {
+					/* seems to be UP2000 like board */
+					base = 0xe0000;
+                                        /* I don't know why we need to
+                                           write twice */
+					mmapped = 2;
+                                        /* UP2000 drives ISA with
+					   8.25 MHz (PCI/4) clock
+					   (this can be read from cypress) */
+					clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
+					printk("i2c-elektor.o: found API UP2000 like board, will probe PCF8584 later.\n");
+				}
+			}
+		}
+	}
+#endif
 
-	struct i2c_pcf_isa *pisa = &gpi;
+	/* sanity checks for mmapped I/O */
+	if (mmapped && base < 0xc8000) {
+		printk("i2c-elektor.o: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
+		return -ENODEV;
+	}
 
 	printk("i2c-elektor.o: i2c pcf8584-isa adapter module\n");
-	if (base == 0)
-		pisa->pi_base = DEFAULT_BASE;
-	else
-		pisa->pi_base = base;
-
-	if (irq == 0)
-		pisa->pi_irq = DEFAULT_IRQ;
-	else
-		pisa->pi_irq = irq;
-
-	if (clock == 0)
-		pisa->pi_clock = DEFAULT_CLOCK;
-	else
-		pisa->pi_clock = clock;
-
-	if (own == 0)
-		pisa->pi_own = DEFAULT_OWN;
-	else
-		pisa->pi_own = own;
 
-	pcf_isa_data.data = (void *)pisa;
+	if (base == 0) {
+		base = DEFAULT_BASE;
+	}
+
 #if (LINUX_VERSION_CODE >= 0x020301)
 	init_waitqueue_head(&pcf_wait);
 #endif
@@ -267,7 +288,9 @@
 	} else {
 		return -ENODEV;
 	}
-	printk("i2c-elektor.o: found device at %#x.\n", pisa->pi_base);
+	
+	printk("i2c-elektor.o: found device at %#x.\n", base);
+
 	return 0;
 }
 
@@ -283,7 +306,8 @@
 MODULE_PARM(irq, "i");
 MODULE_PARM(clock, "i");
 MODULE_PARM(own, "i");
-MODULE_PARM(i2c_debug,"i");
+MODULE_PARM(mmapped, "i");
+MODULE_PARM(i2c_debug, "i");
 
 int init_module(void) 
 {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)