patch-2.4.23 linux-2.4.23/drivers/usb/host/sl811.c

Next file: linux-2.4.23/drivers/usb/host/uhci-debug.h
Previous file: linux-2.4.23/drivers/usb/host/hc_sl811_rh.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/drivers/usb/host/sl811.c linux-2.4.23/drivers/usb/host/sl811.c
@@ -3,18 +3,43 @@
  *
  * Copyright (c) 2003/06, Courage Co., Ltd.
  *
- * Based on: 
+ * Based on:
  *	1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
  * 	  Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
  * 	  Adam Richter, Gregory P. Smith;
-  	2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
+ * 	2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
+ *	3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
  *
- * It's now support isosynchronous mode and more effective than hc_sl811.o
+ * It's now support isochornous mode and more effective than hc_sl811.o
+ * Support x86 architecture now.
+ *
+ * 19.09.2003 (05.06.2003) HNE
+ * sl811_alloc_hc: Set "bus->bus_name" at init.
+ * sl811_reg_test (hc_reset,regTest):
+ *   Stop output at first failed pattern.
+ * Down-Grade for Kernel 2.4.20 and from 2.4.22
+ * Splitt hardware depens into file sl811-x86.h and sl811-arm.h.
+ *
+ * 22.09.2003 HNE
+ * sl811_found_hc: First patterntest, than interrupt enable.
+ * Do nothing, if patterntest failed. Release io, if failed.
+ * Stop Interrupts first, than remove handle. (Old blocked Shred IRQ)
+ * Alternate IO-Base for second Controller (CF/USB1).
+ *
+ * 24.09.2003 HNE
+ * Remove all arm specific source (moved into include/asm/sl811-hw.h).
+ *
+ * 03.10.2003 HNE
+ * Low level only for port io into hardware-include.
+
  *
  * To do:
  *	1.Modify the timeout part, it's some messy
  *	2.Use usb-a and usb-b set in Ping-Pong mode
- 	
+ *	o Floppy do not work.
+ *	o driver crash, if io region can't register
+ * 	o Only as module tested! Compiled in Version not tested!
+
  * 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
@@ -41,13 +66,10 @@
 #include "../hub.h"
 #include "sl811.h"
 
-#define DRIVER_VERSION "v0.28"
-#define DRIVER_AUTHOR "Yin Aihua <yinah@couragetech.com.cn>"
-#define DRIVER_DESC "Sl811 USB Host Controller Driver"
-
-static int sl811_addr_io = 0xf100000e;
-static int sl811_data_io = 0xf100000f;
-static int sl811_irq = 44;
+#define DRIVER_VERSION "v0.30"
+#define MODNAME "SL811"
+#define DRIVER_AUTHOR "Yin Aihua <yinah@couragetech.com.cn>, Henry Nestler <hne@ist1.de>"
+#define DRIVER_DESC "Sl811 USB Host Controller Alternate Driver"
 
 static LIST_HEAD(sl811_hcd_list);
 
@@ -57,70 +79,53 @@
  * 2, error maybe occur in normal
  * 3, useful and detail debug information
  * 4, function level enter and level inforamtion
- * 5, endless information will output because of timer function or interrupt 
+ * 5, endless information will output because of timer function or interrupt
  */
 static int debug = 0;
-
-MODULE_PARM(sl811_addr_io,"i");
-MODULE_PARM_DESC(sl811_addr_io,"sl811 address io port 0xf100000e");
-MODULE_PARM(sl811_data_io,"i");
-MODULE_PARM_DESC(sl811_data_io,"sl811 data io port 0xf100000f");
-MODULE_PARM(sl811_irq,"i");
-MODULE_PARM_DESC(sl811_irq,"sl811 irq 44(default)");
 MODULE_PARM(debug,"i");
 MODULE_PARM_DESC(debug,"debug level");
 
+#include <asm/sl811-hw.h>	/* Include hardware and board depens */
+
 static void sl811_rh_int_timer_do(unsigned long ptr);
-static void sl811_transfer_done(struct sl811_hc *hc, int sof); 
+static void sl811_transfer_done(struct sl811_hc *hc, int sof);
 
 /*
  * Read	a byte of data from the	SL811H/SL11H
  */
-static __u8 sl811_read(struct sl811_hc *hc,	__u8 offset)
+static __u8 inline sl811_read(struct sl811_hc *hc, __u8 offset)
 {
-	__u8 data;
-
-	writeb(offset, hc->addr_io);
-	wmb();
-	data = readb(hc->data_io);
-	rmb();
-
-	return data;
+	sl811_write_index (hc, offset);
+	return (sl811_read_data (hc));
 }
 
 /*
  * Write a byte	of data	to the SL811H/SL11H
  */
-static void sl811_write(struct sl811_hc *hc, __u8 offset, __u8 data)
+static void inline sl811_write(struct sl811_hc *hc, __u8 offset, __u8 data)
 {
-	writeb(offset, hc->addr_io);
-	writeb(data, hc->data_io);
-	wmb();
+	sl811_write_index_data (hc, offset, data);
 }
 
 /*
  * Read	consecutive bytes of data from the SL811H/SL11H	buffer
  */
-static void sl811_read_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size)
+static void inline sl811_read_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size)
 {
-	writeb(offset, hc->addr_io);
-	wmb();
+	sl811_write_index (hc, offset);
 	while (size--) {
-		*buf++ = readb(hc->data_io);
-		rmb();
+		*buf++ = sl811_read_data(hc);
 	}
 }
 
 /*
  * Write consecutive bytes of data to the SL811H/SL11H buffer
  */
-static void sl811_write_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size)
+static void inline sl811_write_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size)
 {
-	writeb(offset, hc->addr_io);
-	wmb();
+	sl811_write_index (hc, offset);
 	while (size--) {
-		writeb(*buf, hc->data_io);
-		wmb();
+		sl811_write_data (hc, *buf);
 		buf++;
 	}
 }
@@ -147,6 +152,10 @@
 		if (data != i) {
 			PDEBUG(1, "Pattern test failed!! value = 0x%x, s/b 0x%x", data, i);
 			result = -1;
+
+			/* If no Debug, show only first failed Address */
+			if (!debug)
+			    break;
 		}
 	}
 
@@ -160,6 +169,7 @@
 /*
  * Display all SL811HS register	values
  */
+#if 0 /* unused (hne) */
 static void sl811_reg_show(struct sl811_hc *hc)
 {
 	int i;
@@ -167,6 +177,7 @@
 	for (i = 0; i <	256; i++)
 		PDEBUG(4, "offset %d: 0x%x", i, sl811_read(hc, i));
 }
+#endif
 
 /*
  * This	function enables SL811HS interrupts
@@ -796,9 +807,9 @@
 
 static void sl811_print_td(int level, struct sl811_td *td)
 {
-	 PDEBUG(level, "td = %p, ctrl = %x, addr = %x, len = %x, pidep = %x\n 
-		dev = %x, status = %x, left = %x, errcnt = %x, done = %x\n 
-		buf = %p, bustime = %d, td_status = %d\n", 
+	 PDEBUG(level, "td = %p, ctrl = %x, addr = %x, len = %x, pidep = %x\n "
+		"dev = %x, status = %x, left = %x, errcnt = %x, done = %x\n "
+		"buf = %p, bustime = %d, td_status = %d\n", 
 		td, td->ctrl, td->addr, td->len, td->pidep,
 		td->dev, td->status, td->left, td->errcnt, td->done,
 		td->buf, td->bustime, td->td_status);
@@ -845,7 +856,7 @@
 		if (urbp->cur_td == NULL)
 			urbp->cur_td = urbp->first_td = td;	
 	}
-	
+
 	urbp->last_td = td;	
 	
 	PDEBUG(4, "leave success");
@@ -2397,7 +2408,7 @@
 	struct sl811_td *next_td;
 #ifdef SL811_DEBUG
 	static struct sl811_td *repeat_td = NULL;
-	static repeat_cnt = 1;
+	static int repeat_cnt = 1;
 #endif	
 	if (++hc->frame_number > 1024)
 		hc->frame_number = 0;
@@ -2464,7 +2475,7 @@
 
 	mdelay(20);
 	
-	// Disable hardware SOF generation.
+	// Disable hardware SOF generation, clear all irq status.
 	sl811_write(hc,	SL811_CTRL1, 0);
 	mdelay(2);
 	sl811_write(hc, SL811_INTRSTS, 0xff); 
@@ -2532,7 +2543,7 @@
 
 	status = sl811_read(hc, SL811_INTRSTS);
 	if (status == 0)
-		return ;
+		return ; /* Not me */
 
 	sl811_write(hc,	SL811_INTRSTS, 0xff);
 
@@ -2603,6 +2614,7 @@
 	}
 
 	hc->bus	= bus;
+	bus->bus_name = MODNAME;
 	bus->hcpriv = hc;
 
 	return hc;
@@ -2619,14 +2631,23 @@
 	if (hc->bus->root_hub)
 		usb_disconnect(&hc->bus->root_hub);
 
-	if (hc->addr_io)
-		release_region(hc->addr_io, 1);
-
-	if (hc->data_io)
-		release_region(hc->data_io, 1);
-
+	// Stop interrupt handle
 	if (hc->irq)
 		free_irq(hc->irq, hc);
+	hc->irq = 0;
+
+	/* Stop interrupt for sharing, but only, if PatternTest ok */
+	if (hc->addr_io) {
+		/* Disable Interrupts */
+		sl811_write(hc,	SL811_INTR, 0);
+
+		/* Remove all Interrupt events */
+		mdelay(2);
+		sl811_write(hc,	SL811_INTRSTS, 0xff);
+	}
+
+	/* free io regions */
+	sl811_release_regions(hc);
 
 	usb_deregister_bus(hc->bus);
 	usb_free_bus(hc->bus);
@@ -2638,16 +2659,6 @@
 }
 
 /*
- * This	function is board specific.  It	sets up	the interrupt to
- * be an edge trigger and trigger on the rising	edge
- */
-static void sl811_init_irq(void)
-{
-	GPDR &=	~(1<<23);
-	set_GPIO_IRQ_edge(1<<23, GPIO_RISING_EDGE);
-}
-
-/*
  * This	function request IO memory regions, request IRQ, and
  * allocate all	other resources.
  *
@@ -2667,40 +2678,47 @@
 	if (!hc)
 		return -ENOMEM;
 
-	sl811_init_irq();
-
-	if (!request_region(addr_io, 1, "SL811 USB HOST")) {
-		PDEBUG(1, "request address %d failed", addr_io);
+	if (sl811_request_regions (hc, addr_io, data_io, MODNAME)) {
+		PDEBUG(1, "ioport %X,%X is in use!", addr_io, data_io);
 		sl811_release_hc(hc);
 		return -EBUSY;
 	}
-	hc->addr_io =	addr_io;
 
-	if (!request_region(data_io, 1, "SL811 USB HOST")) {
-		PDEBUG(1, "request address %d failed", data_io);
-		sl811_release_hc (hc);
-		return -EBUSY;
+	if (sl811_reg_test(hc)) {
+		PDEBUG(1, "SL811 register test failed!");
+		sl811_release_hc(hc);
+		return -ENODEV;
+	}
+	
+#ifdef SL811_DEBUG_VERBOSE
+	{
+	    __u8 u = SL811Read (hci, SL11H_HWREVREG);
+	    
+	    // Show the hardware revision of chip
+	    PDEBUG(1, "SL811 HW: %02Xh", u);
+	    switch (u & 0xF0) {
+	    case 0x00: PDEBUG(1, "SL11H");		break;
+	    case 0x10: PDEBUG(1, "SL811HS rev1.2");	break;
+	    case 0x20: PDEBUG(1, "SL811HS rev1.5");	break;
+	    default:   PDEBUG(1, "Revision unknown!");
+	    }
 	}
-	hc->data_io =	data_io;
+#endif // SL811_DEBUG_VERBOSE
+
+	sl811_init_irq();
 
 	usb_register_bus(hc->bus);
 
-	if (request_irq(irq, sl811_interrupt, 0, "SL811", hc)) {
+	if (request_irq(irq, sl811_interrupt, SA_SHIRQ, MODNAME, hc)) {
 		PDEBUG(1, "request interrupt %d failed", irq);
 		sl811_release_hc(hc);
 		return -EBUSY;
 	}
 	hc->irq	= irq;
 
-	printk(KERN_INFO __FILE__ ": USB SL811 at %x, addr2 = %x, IRQ %d\n",
+	printk(KERN_INFO __FILE__ ": USB SL811 at %x,%x, IRQ %d\n",
 		addr_io, data_io, irq);
 
-	if (sl811_reg_test(hc)) {
-		PDEBUG(1, "SL811 register test failed!");
-		sl811_release_hc(hc);
-		return -ENODEV;
-	}
-	
 	sl811_hc_reset(hc);
 	sl811_connect_rh(hc);
 	
@@ -2714,13 +2732,21 @@
  */
 static int __init sl811_hcd_init(void)
 {
-	int ret;
-
-	PDEBUG(5, "etner");
+	int ret = -ENODEV;
+        int count;
+	
+	PDEBUG(5, "enter");
 
 	info(DRIVER_VERSION " : " DRIVER_DESC);
-	
-	ret = sl811_found_hc(sl811_addr_io, sl811_data_io, sl811_irq);
+
+        // registering some instance
+	for (count = 0; count < MAX_CONTROLERS; count++) {
+		if (io[count]) {
+			ret = sl811_found_hc(io[count], io[count]+OFFSET_DATA_REG, irq[count]);
+			if (ret)
+				return (ret);
+		}
+	}
 
 	return ret;
 }

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