All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: MPC5200,PSC in uart mode, receiving problem
@ 2005-10-11  6:55 Derycke, Johan
  2005-10-11  7:18 ` Wolfgang Denk
  0 siblings, 1 reply; 5+ messages in thread
From: Derycke, Johan @ 2005-10-11  6:55 UTC (permalink / raw)
  To: achim.machura; +Cc: Linuxppc-Embedded (E-Mail)

[-- Attachment #1: Type: text/plain, Size: 1811 bytes --]

Hi Achim,

I also have the problem with uart blocking.
Could you please send me your changes to the driver so I can see if it works
for me.

Best regards,

Johan

-----Original Message-----
From: linuxppc-embedded-bounces@ozlabs.org
[mailto:linuxppc-embedded-bounces@ozlabs.org] On Behalf Of Achim Machura
Sent: maandag 10 oktober 2005 15:14
To: 'Tomasz Prochownik'
Cc: Linuxppc-Embedded (E-Mail)
Subject: AW: MPC5200,PSC in uart mode, receiving problem

Hello Tomasz

> blocks (there is no response in the console).

perhaps we have the same problem a few times ago.
When we connect devices on ttySx which have wrong level on the lines the
uart stay in break mode.

I have made some fixes on the psc-driver. With these fixes the uart works,
but i don't know how efficient.
(clear breakmode and clear buffer)

If you want, i can send the code


best regards
achim

_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
- - - - - - - DISCLAIMER- - - - - - - -
Unless indicated otherwise, the information contained in this message is
privileged and confidential, and is intended only for the use of the
addressee(s) named above and others who have been specifically authorized to
receive it. If you are not the intended recipient, you are hereby notified
that any dissemination, distribution or copying of this message and/or
attachments is strictly prohibited. The company accepts no liability for any
damage caused by any virus transmitted by this email. Furthermore, the
company does not warrant a proper and complete transmission of this
information, nor does it accept liability for any delays. If you have
received this message in error, please contact the sender and delete the
message. Thank you.

[-- Attachment #2: Type: text/html, Size: 3044 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: MPC5200,PSC in uart mode, receiving problem
  2005-10-11  6:55 MPC5200,PSC in uart mode, receiving problem Derycke, Johan
@ 2005-10-11  7:18 ` Wolfgang Denk
  2005-10-11  8:10   ` AW: " Achim Machura
  0 siblings, 1 reply; 5+ messages in thread
From: Wolfgang Denk @ 2005-10-11  7:18 UTC (permalink / raw)
  To: achim.machura, Linuxppc-Embedded (E-Mail)

In message <81A66F72DCACD511B0600002A551BFCB08EE8AD4@kuumex05.barco.com> you wrote:
> 
> This message is in MIME format. Since your mail reader does not understand
> this format, some or all of this message may not be legible.

Even better, post a patch here on the list so we all can benefit.

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
The only time the world beats a path to your door is when you are  in
the bathroom.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* AW: MPC5200,PSC in uart mode, receiving problem
  2005-10-11  7:18 ` Wolfgang Denk
@ 2005-10-11  8:10   ` Achim Machura
  2006-02-02 18:22     ` Frank Bodammer
  0 siblings, 1 reply; 5+ messages in thread
From: Achim Machura @ 2005-10-11  8:10 UTC (permalink / raw)
  To: 'Wolfgang Denk'; +Cc: Linuxppc-Embedded (E-Mail)

[-- Attachment #1: Type: text/plain, Size: 108 bytes --]


Here the patch
 
> Even better, post a patch here on the list so we all can benefit.
 
Best regards,

Achim

[-- Attachment #2: patch_linuxppc_2_4_develLABEL_2004_04_30_1320_psc --]
[-- Type: application/octet-stream, Size: 7506 bytes --]

Index: psc.c
===================================================================
--- psc.c	(.../kernel/linux/arch/ppc/5xxx_io/psc.c)	(Revision 777)
+++ psc.c	(.../firmware/kernel/linux/arch/ppc/5xxx_io/psc.c)	(Arbeitskopie)
@@ -29,6 +29,7 @@
 #include <linux/serial.h>
 #include <linux/serialP.h>
 #include <linux/generic_serial.h>
+#include <linux/proc_fs.h>
 #ifdef CONFIG_UBOOT
 #include <asm/ppcboot.h>
 #endif
@@ -37,7 +38,7 @@
  * This driver can spew a whole lot of debugging output at you. If you
  * need maximum performance, you should disable the DEBUG define.
  */
-#undef MPC5xxx_PSC_DEBUG 
+#undef MPC5xxx_PSC_DEBUG
 
 #ifdef MPC5xxx_PSC_DEBUG
 #define MPC5xxx_PSC_DEBUG_OPEN		0x00000001
@@ -55,6 +56,7 @@
 #define MPC5xxx_PSC_DEBUG_FIRMWARE	0x00001000
 #define MPC5xxx_PSC_DEBUG_MEMTEST	0x00002000
 #define MPC5xxx_PSC_DEBUG_THROTTLE	0x00004000
+#define MPC5xxx_PSC_DEBUG_CLEARERR	0x00008000
 #define MPC5xxx_PSC_DEBUG_ALL		0xffffffff
 
 int rs_debug = MPC5xxx_PSC_DEBUG_ALL & ~MPC5xxx_PSC_DEBUG_TRANSMIT;
@@ -150,13 +152,23 @@
 int rs_refcount;
 int rs_initialized = 0;
 
+
 /*
+ * proc stuff
+ */
+static int sio_read_info(char * buf, char ** start, off_t offset, int count, int  *eof, void * data );
+static int sio_clear_err(struct file *file,  const char *buffer,  unsigned long count,   void *data);
+static struct proc_dir_entry  *pProcEntry = NULL;
+
+
+void clear_err(struct mpc5xxx_psc * psc);
+/*
  * ----------------------------------------------------------------------
  *
  * Here starts the interrupt handling routines.  All of the following
  * subroutines are declared as inline and are folded into
  * rs_interrupt().  They were separated out for readability's sake.
- *
+ *MPC5xxx_PSC_DEBUG_RECEIVE
  * Note: rs_interrupt() is a "fast" interrupt, which means that it
  * runs with interrupts turned off.  People who may want to modify
  * rs_interrupt() should try to keep the interrupt handler as fast as
@@ -294,19 +306,36 @@
 
 static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct rs_port * port;
+	struct rs_port * port = (struct rs_port *)dev_id;
+	struct mpc5xxx_psc *psc = port->psc;
 	unsigned long flags;
+	u16 status;
 
 	spin_lock_irqsave(&mpc5xxx_serial_lock, flags);
 
-	port = (struct rs_port *)dev_id;
+
 	rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS,
 			"rs_interrupt (port %p)...", port);
 
+	if (!port || !port->gs.tty) {
+		printk( KERN_DEBUG"%s(%d): port=%p tty=%p\n", __FUNCTION__, __LINE__,
+				port, port?port->gs.tty:NULL );
+		goto out;
+	}
+
+	status = in_be16(&psc->mpc5xxx_psc_status);
+	/* RB-Bit is set ?  */
+	if(status & MPC5xxx_PSC_SR_RB)
+	{
+		clear_err(psc);
+		rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "clear err in isr nach status %d.\n", status);
+		goto out;
+	}
+
 	receive_char(port);
 
 	transmit_char(port);
-
+out:
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
 
 	rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "end.\n");
@@ -318,7 +347,7 @@
  *		interface with the generic_serial driver		*
  ************************************************************************
  */
-static void rs_disable_tx_interrupts(void * ptr) 
+static void rs_disable_tx_interrupts(void * ptr)
 {
 	struct rs_port *port = ptr; 
 	struct mpc5xxx_psc *psc = port->psc;
@@ -360,7 +389,7 @@
 
 	port->imr &= ~MPC5xxx_PSC_IMR_RXRDY;
 	out_be16(&psc->mpc5xxx_psc_imr, port->imr);
-
+	rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE,"disable RxInt\n");
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
 }
 
@@ -382,7 +411,7 @@
 	 * while (in_be16(&psc->mpc5xxx_psc_status) & MPC5xxx_PSC_SR_RXRDY)
 	 *	in_8(&psc->mpc5xxx_psc_buffer_8);
 	 */
-
+	rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE,"enable RxInt\n");
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
 
 }
@@ -442,9 +471,15 @@
 	val32 |= (MPC5xxx_GPIO_PSC_CONFIG_UART_WITHOUT_CD << (4*line));
 	out_be32(&gpio->port_config, val32);
 	/* reset and enable PSC */
-	out_8(&psc->command, MPC5xxx_PSC_RST_TX
-		  | MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE);
-	out_8(&psc->command, MPC5xxx_PSC_RST_RX);
+//	out_8(&psc->command, MPC5xxx_PSC_RST_TX
+//		  | MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE);
+//	out_8(&psc->command, MPC5xxx_PSC_RST_RX);
+
+	/* neu */
+		/* reset and enable PSC */
+	out_8(&psc->command, MPC5xxx_PSC_RST_TX  |  MPC5xxx_PSC_TX_ENABLE);
+ 	//out_8(&psc->command, MPC5xxx_PSC_RST_RX);
+	/* ende neu*/
 	/* Set PSC operation mode as 'UART, DCD ignored' */
 	out_be32(&psc->sicr, 0x0);
 	/* Set clocking */
@@ -539,7 +574,7 @@
 
 	line = minor(tty->device) - tty->driver.minor_start;
 	rs_dprintk(MPC5xxx_PSC_DEBUG_OPEN,
-			"%d: opening line %d. tty=%p ctty=%p)\n", 
+			"%d: opening line %d. tty=%p ctty=%p)\n",
 			(int) current->pid, line, tty, current->tty);
 
 	if ((line < 0) || (line >= RS_TABLE_SIZE))
@@ -813,6 +848,7 @@
 #endif
 		rs_dprintk(MPC5xxx_PSC_DEBUG_INIT, "psc base 0x%08lx\n",
 				(unsigned long)port->psc);
+		clear_err(port->psc);
 		port++;
 	}
 
@@ -878,6 +914,11 @@
 		return 1;
 	}
 
+	//pProcEntry =  create_proc_read_entry("driver/sio0",0444,NULL,sio_read_info,NULL);
+	pProcEntry =  create_proc_entry("driver/sio0",0444,NULL);
+	pProcEntry->read_proc = sio_read_info;
+	pProcEntry->write_proc = sio_clear_err;
+	pProcEntry->owner = THIS_MODULE;
 	func_exit();
 	return 0;
 }
@@ -1094,3 +1135,61 @@
 }
 
 #endif
+static int sio_read_info(char * buf, char ** start, off_t offset, int count, int  *eof, void * data )
+{
+
+	int len = 0;
+	struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *) MPC5xxx_PSC1;
+	u16 nStat;
+
+	*eof = 1;
+	*buf = 0;
+	nStat = in_be16(&psc->mpc5xxx_psc_status);
+	if(count > len + 120)
+	{
+		len += sprintf(buf+len, "\n Status PSC 1: %d",nStat);
+		len += sprintf(buf+len, "\n RB: %d",(nStat & MPC5xxx_PSC_SR_RB) ? 1 : 0);
+		len += sprintf(buf+len, "\n FE: %d",(nStat & MPC5xxx_PSC_SR_FE) ? 1 : 0);
+		len += sprintf(buf+len, "\n PE: %d",(nStat & MPC5xxx_PSC_SR_PE) ? 1 : 0);
+		len += sprintf(buf+len, "\n OR: %d",(nStat & MPC5xxx_PSC_SR_OE) ? 1 : 0);
+		len += sprintf(buf+len, "\n TxEMP: %d",(nStat & MPC5xxx_PSC_SR_TXEMP) ? 1 : 0);
+		len += sprintf(buf+len, "\n TxRDY: %d",(nStat & MPC5xxx_PSC_SR_TXRDY) ? 1 : 0);
+		len += sprintf(buf+len, "\n RXFULL: %d",(nStat & MPC5xxx_PSC_SR_RXFULL) ? 1 : 0);
+		len += sprintf(buf+len, "\n RxRDY: %d",(nStat & MPC5xxx_PSC_SR_RXRDY) ? 1 : 0);
+		len += sprintf(buf+len, "\n CDE: %d\n",(nStat & MPC5xxx_PSC_SR_CDE) ? 1 : 0);
+
+	}
+	return len;
+
+}
+static int sio_clear_err(struct file *file,  const char *buffer,  unsigned long count,   void *data)
+{
+
+	struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *) MPC5xxx_PSC1;
+
+	clear_err(psc);
+	return (int)count;
+}
+
+void clear_err(struct mpc5xxx_psc * psc)
+{
+    u8 byCmd;
+	u16 i;
+	unsigned int status, nBytes;
+
+	nBytes = in_be16(&psc->rfnum) & MPC5xxx_PSC_RFNUM_MASK;
+	for(i=0; i< nBytes;i++)
+	{
+		byCmd = in_8(&psc->mpc5xxx_psc_buffer_8);
+		rs_dprintk(MPC5xxx_PSC_DEBUG_CLEARERR,"loesche Byte %d von %d Bytes\n",i+1,nBytes);
+	}
+	status = in_be16(&psc->mpc5xxx_psc_status);
+	rs_dprintk(MPC5xxx_PSC_DEBUG_CLEARERR,"status Start %d\n",status);
+	byCmd = (u8) MPC5xxx_PSC_RST_ERR_STAT;
+	out_8(&psc->command, byCmd);
+	wmb();
+	status = in_be16(&psc->mpc5xxx_psc_status);
+	rmb();
+	rs_dprintk(MPC5xxx_PSC_DEBUG_CLEARERR,"status clear %d\n",status);
+}
+

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: AW: MPC5200,PSC in uart mode, receiving problem
  2005-10-11  8:10   ` AW: " Achim Machura
@ 2006-02-02 18:22     ` Frank Bodammer
  0 siblings, 0 replies; 5+ messages in thread
From: Frank Bodammer @ 2006-02-02 18:22 UTC (permalink / raw)
  To: Linuxppc-Embedded

[-- Attachment #1: Type: text/plain, Size: 1145 bytes --]

Achim Machura wrote:
> Here the patch
>  
> 
>>Even better, post a patch here on the list so we all can benefit.

I experienced similar problems with the serial ports on mpc5200 PSCs
and so i was happy to find your patch, which solved some problem, but
not all. The overrun flag still wasn´t reset after an input overrun
error, so this error was reported persistent for each received character.
I fixed this by adding an command to reset the psc error flags in
receive_char() where the overrun flag is checked. Maybe this isn't
the best solution, but it seems to work.

To reset the overrun error flag, i tried the following statement:

	out_8(&psc->command, MPC5xxx_PSC_RST_ERR_STAT);

but i got unpredictable behaviour in some cases ending in a reset.
Doing the same this way:

	psc->command = MPC5xxx_PSC_RST_ERR_STAT;

always worked as expected. Does someone know what may be wrong with
'out_8' on mpc5200 with kernel 2.4.25 or is that a configuration problem.

By the way, i improved some other parts of the code, especially the
/proc output and the portconfig stuff, so i also attach a patch here,
even not all of it may be useful.

Frank

[-- Attachment #2: patch_linuxppc_2_4_psc-060202.diff --]
[-- Type: text/plain, Size: 18129 bytes --]

--- psc-orig.c	2006-02-02 10:41:45.000000000 +0100
+++ psc.c	2006-02-02 17:30:59.000000000 +0100
@@ -29,6 +29,7 @@
 #include <linux/serial.h>
 #include <linux/serialP.h>
 #include <linux/generic_serial.h>
+#include <linux/proc_fs.h>
 #ifdef CONFIG_UBOOT
 #include <asm/ppcboot.h>
 #endif
@@ -37,7 +38,8 @@
  * This driver can spew a whole lot of debugging output at you. If you
  * need maximum performance, you should disable the DEBUG define.
  */
-#undef MPC5xxx_PSC_DEBUG 
+#undef MPC5xxx_PSC_DEBUG
+//#define MPC5xxx_PSC_DEBUG		1
 
 #ifdef MPC5xxx_PSC_DEBUG
 #define MPC5xxx_PSC_DEBUG_OPEN		0x00000001
@@ -55,6 +57,7 @@
 #define MPC5xxx_PSC_DEBUG_FIRMWARE	0x00001000
 #define MPC5xxx_PSC_DEBUG_MEMTEST	0x00002000
 #define MPC5xxx_PSC_DEBUG_THROTTLE	0x00004000
+#define MPC5xxx_PSC_DEBUG_CLEARERR	0x00008000
 #define MPC5xxx_PSC_DEBUG_ALL		0xffffffff
 
 int rs_debug = MPC5xxx_PSC_DEBUG_ALL & ~MPC5xxx_PSC_DEBUG_TRANSMIT;
@@ -73,7 +76,7 @@
 /*
  * Number of serial ports
  */
-#define MPC5xxx_PSC_NPORTS	3
+#define MPC5xxx_PSC_NPORTS	4
 
 #ifdef CONFIG_PPC_5xxx_PSC_CONSOLE
 #ifndef CONFIG_PPC_5xxx_PSC_CONSOLE_PORT
@@ -89,7 +92,7 @@
 /*
  * Hardware specific serial port structure
  */
-struct rs_port { 	
+struct rs_port {
 	struct gs_port		gs;		/* Must be first field! */
 
 	struct mpc5xxx_psc	*psc;
@@ -121,7 +124,7 @@
 /*
  * Used by generic serial driver to access hardware
  */
-static struct real_driver rs_real_driver = { 
+static struct real_driver rs_real_driver = {
 	.disable_tx_interrupts	= rs_disable_tx_interrupts, 
 	.enable_tx_interrupts	= rs_enable_tx_interrupts, 
 	.disable_rx_interrupts	= rs_disable_rx_interrupts, 
@@ -134,9 +137,15 @@
 	.hungup			= rs_hungup,
 }; 
 
+#ifdef CONFIG_PS2MULT
+struct serial_state rs_table[RS_TABLE_SIZE] = {
+	SERIAL_PORT_DFNS	/* Defined in serial.h */
+};
+#else
 static struct serial_state rs_table[RS_TABLE_SIZE] = {
 	SERIAL_PORT_DFNS	/* Defined in serial.h */
 };
+#endif
 
 /*
  * Structures and such for TTY sessions and usage counts
@@ -151,6 +160,14 @@
 int rs_initialized = 0;
 
 /*
+ * proc stuff
+ */
+static int sio_read_info(char * buf, char ** start, off_t offset, int count, int  *eof, void * data);
+
+static struct proc_dir_entry 	*proc_psc_dir,
+				*proc_psc[MPC5xxx_PSC_NPORTS];
+
+/*
  * ----------------------------------------------------------------------
  *
  * Here starts the interrupt handling routines.  All of the following
@@ -180,11 +197,11 @@
 
 	/* While there are characters, get them ... */
 	while (--count >= 0) {
-		status = in_be16(&psc->mpc5xxx_psc_status);
+		status = psc->mpc5xxx_psc_status;
 		if (!(status & MPC5xxx_PSC_SR_RXRDY))
 			break;
 
-		ch = in_8(&psc->mpc5xxx_psc_buffer_8);
+		ch = psc->mpc5xxx_psc_buffer_8;
 
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			continue;
@@ -215,6 +232,9 @@
 					tty->flip.count++;
 				}
 				*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+				rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE, "reset psc overrun error status: 0x%04x\n", status);
+				/* Reset PSC error status */
+				psc->command = MPC5xxx_PSC_RST_ERR_STAT;
 			}
 		}
 
@@ -234,7 +254,7 @@
 
 	/* While I'm able to transmit ... */
 	while (--count >= 0) {
-		status = in_be16(&psc->mpc5xxx_psc_status);
+		status = psc->mpc5xxx_psc_status;
 		/*
 		 * XXX -df
 		 * check_modem_status(status);
@@ -243,7 +263,7 @@
 			break;
 
 		if (port->x_char) {
-			out_8(&psc->mpc5xxx_psc_buffer_8, port->x_char);
+			psc->mpc5xxx_psc_buffer_8 = port->x_char;
 			port->icount.tx++;
 			port->x_char = 0;
 		}
@@ -252,8 +272,7 @@
 			break;
 		}
 		else {
-			out_8(&psc->mpc5xxx_psc_buffer_8,
-				port->gs.xmit_buf[port->gs.xmit_tail++]);
+			psc->mpc5xxx_psc_buffer_8 = port->gs.xmit_buf[port->gs.xmit_tail++];
 			port->icount.tx++;
 			port->gs.xmit_tail &= SERIAL_XMIT_SIZE-1;
 			if (--port->gs.xmit_cnt <= 0) {
@@ -266,7 +285,7 @@
 			 port->gs.tty->hw_stopped) {
 		rs_disable_tx_interrupts(port);
 	}
-	
+
 	if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
 		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 				port->gs.tty->ldisc.write_wakeup)
@@ -275,7 +294,7 @@
 				"Waking up.... ldisc (%d)....\n",
 				port->gs.wakeup_chars); 
 		wake_up_interruptible(&port->gs.tty->write_wait);
-	}	
+	}
 }
 
 
@@ -294,19 +313,35 @@
 
 static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct rs_port * port;
+	struct rs_port * port = (struct rs_port *)dev_id;
+	struct mpc5xxx_psc *psc = port->psc;
 	unsigned long flags;
+	u16 status;
 
 	spin_lock_irqsave(&mpc5xxx_serial_lock, flags);
 
-	port = (struct rs_port *)dev_id;
 	rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS,
 			"rs_interrupt (port %p)...", port);
 
+	if (!port || !port->gs.tty) {
+		printk( KERN_DEBUG"%s(%d): port=%p tty=%p\n", __FUNCTION__, __LINE__,
+				port, port?port->gs.tty:NULL );
+		goto out;
+	}
+
+	status = psc->mpc5xxx_psc_status;
+	/* RB-Bit is set ?  */
+	if (status & MPC5xxx_PSC_SR_RB)
+	{
+		rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "reset psc error status: 0x%04x\n", status);
+		psc->command = MPC5xxx_PSC_RST_ERR_STAT;
+		goto out;
+	}
+
 	receive_char(port);
 
 	transmit_char(port);
-
+out:
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
 
 	rs_dprintk(MPC5xxx_PSC_DEBUG_INTERRUPTS, "end.\n");
@@ -318,7 +353,7 @@
  *		interface with the generic_serial driver		*
  ************************************************************************
  */
-static void rs_disable_tx_interrupts(void * ptr) 
+static void rs_disable_tx_interrupts(void *ptr)
 {
 	struct rs_port *port = ptr; 
 	struct mpc5xxx_psc *psc = port->psc;
@@ -328,7 +363,7 @@
 	port->gs.flags &= ~GS_TX_INTEN;
 
 	port->imr &= ~MPC5xxx_PSC_IMR_TXRDY;
-	out_be16(&psc->mpc5xxx_psc_imr, port->imr);
+	psc->mpc5xxx_psc_imr = port->imr;
 
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
 }
@@ -342,7 +377,7 @@
 	spin_lock_irqsave(&mpc5xxx_serial_lock, flags);
 
 	port->imr |= MPC5xxx_PSC_IMR_TXRDY;
-	out_be16(&psc->mpc5xxx_psc_imr, port->imr);
+	psc->mpc5xxx_psc_imr = port->imr;
 
 	/* Send a char to start TX interrupts happening */
 	transmit_char(port);
@@ -359,7 +394,8 @@
 	spin_lock_irqsave(&mpc5xxx_serial_lock, flags);
 
 	port->imr &= ~MPC5xxx_PSC_IMR_RXRDY;
-	out_be16(&psc->mpc5xxx_psc_imr, port->imr);
+	psc->mpc5xxx_psc_imr = port->imr;
+	rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE,"disable RxInt\n");
 
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
 }
@@ -373,18 +409,10 @@
 	spin_lock_irqsave(&mpc5xxx_serial_lock, flags);
 
 	port->imr |= MPC5xxx_PSC_IMR_RXRDY;
-	out_be16(&psc->mpc5xxx_psc_imr, port->imr);
-
-	/* Empty the input buffer - apparently this is *vital* */
-	/*
-	 * XXXX add this back in if needed, -df
-	 *
-	 * while (in_be16(&psc->mpc5xxx_psc_status) & MPC5xxx_PSC_SR_RXRDY)
-	 *	in_8(&psc->mpc5xxx_psc_buffer_8);
-	 */
+	psc->mpc5xxx_psc_imr = port->imr;
+	rs_dprintk(MPC5xxx_PSC_DEBUG_RECEIVE,"enable RxInt\n");
 
 	spin_unlock_irqrestore(&mpc5xxx_serial_lock, flags);
-
 }
 
 static int rs_get_CD(void * ptr) 
@@ -394,7 +422,7 @@
 	func_enter();
 
 	func_exit();
-	return (in_8(&port->psc->mpc5xxx_psc_ipcr) & MPC5xxx_PSC_DCD) != 0;
+	return (port->psc->mpc5xxx_psc_ipcr & MPC5xxx_PSC_DCD) != 0;
 }
 
 static void rs_shutdown_port(void * ptr) 
@@ -432,34 +460,67 @@
 
 	divisor = ((port->gs.baud_base / (port->gs.baud * 16)) + 1) >> 1;
 	if (port->gs.baud < 50 || divisor == 0) {
-		printk(KERN_NOTICE "MPC5xxx PSC: Bad speed requested, %d\n",
-				port->gs.baud);
+		printk(KERN_NOTICE "MPC5xxx PSC: Bad speed requested, %d, %d\n",
+				port->gs.baud, divisor);
 		return 0;
 	}
 	/* Configure the PSC for UART mode */
 	line = minor(port->gs.tty->device) - port->gs.tty->driver.minor_start;
+
+#if 0
+	/* This works only for PSC1..PSC3 and assumes that the ports are assigned  */
+	/* in this order. In other configurations it affects functions like usb    */
+	/* or ethernet. It isn't needed, when portconfig is done by the bootloader */
 	val32 = in_be32(&gpio->port_config);
 	val32 |= (MPC5xxx_GPIO_PSC_CONFIG_UART_WITHOUT_CD << (4*line));
 	out_be32(&gpio->port_config, val32);
+#else
+	switch ((int) port->psc) {
+		case MPC5xxx_PSC1: {
+			rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "Setup portconfig for PSC1\n");
+			gpio->port_config |= MPC5xxx_GPIO_PSC_CONFIG_UART_WITHOUT_CD;
+			break;
+		}
+		case MPC5xxx_PSC2: {
+			rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "Setup portconfig for PSC2\n");
+			gpio->port_config |= (MPC5xxx_GPIO_PSC_CONFIG_UART_WITHOUT_CD << 4);
+			break;
+		}
+		case MPC5xxx_PSC3: {
+			rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "Setup portconfig for PSC3\n");
+			gpio->port_config |= (MPC5xxx_GPIO_PSC_CONFIG_UART_WITHOUT_CD << 8);
+			break;
+		}
+		case MPC5xxx_PSC4: {
+			rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "Setup portconfig for PSC4\n");
+			break;
+		}
+		case MPC5xxx_PSC5: {
+			rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "Setup portconfig for PSC5\n");
+			break;
+		}
+		case MPC5xxx_PSC6: {
+			rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "Setup portconfig for PSC6\n");
+			break;
+		}
+	}
+#endif
+
 	/* reset and enable PSC */
-	out_8(&psc->command, MPC5xxx_PSC_RST_TX
-		  | MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE);
-	out_8(&psc->command, MPC5xxx_PSC_RST_RX);
+	psc->command = MPC5xxx_PSC_RST_TX | MPC5xxx_PSC_TX_ENABLE;
+
 	/* Set PSC operation mode as 'UART, DCD ignored' */
-	out_be32(&psc->sicr, 0x0);
+	psc->sicr = 0x0;
 	/* Set clocking */
-	out_be16(&psc->mpc5xxx_psc_clock_select, 0xdd00);
+	psc->mpc5xxx_psc_clock_select = 0xdd00;
 	/* Set tx FIFO alarm level */
-	out_be16(&psc->tfalarm, 0xf8);
+	psc->tfalarm = 0xf8;
 	/* Put PSC into the operation */
-	out_8(&psc->command, MPC5xxx_PSC_SEL_MODE_REG_1
-		  | MPC5xxx_PSC_RX_ENABLE
-		  | MPC5xxx_PSC_TX_ENABLE);
-
-	rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "calculated divisor: %d\n",
-			divisor);
-	out_8(&psc->ctur, divisor>>8);
-	out_8(&psc->ctlr, divisor);
+	psc->command = MPC5xxx_PSC_SEL_MODE_REG_1 | MPC5xxx_PSC_RX_ENABLE | MPC5xxx_PSC_TX_ENABLE;
+
+	rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS, "calculated divisor: %d\n", divisor);
+	psc->ctur = divisor >> 8;
+	psc->ctlr = divisor;
 
 	/* Program hardware for parity, data bits, stop bits */
 	if ((CFLAG & CSIZE)==CS5)
@@ -496,19 +557,20 @@
 	rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS,
 			"baud_base: %d\n", port->gs.baud_base);
 #ifdef MPC5xxx_PSC_DEBUG
-	if (rs_debug & MPC5xxx_PSC_DEBUG_TERMIOS)
-		out_8(&psc->command, MPC5xxx_PSC_SEL_MODE_REG_1);
+	if (rs_debug & MPC5xxx_PSC_DEBUG_TERMIOS) {
+		psc->command = MPC5xxx_PSC_SEL_MODE_REG_1;
+	}
 #endif
 	rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS,
 			"mode 1 register was: %08x, now: %08x\n",
-			in_8(&psc->mode), mode1);
+			psc->mode, mode1);
 	rs_dprintk(MPC5xxx_PSC_DEBUG_TERMIOS,
 			"mode 2 register was: %08x, now: %08x\n",
-			in_8(&psc->mode), mode2);
+			psc->mode, mode2);
 
-	out_8(&psc->command, MPC5xxx_PSC_SEL_MODE_REG_1);
-	out_8(&psc->mode, mode1);
-	out_8(&psc->mode, mode2);
+	psc->command = MPC5xxx_PSC_SEL_MODE_REG_1;
+	psc->mode = mode1;
+	psc->mode = mode2;
 
 	func_exit();
 	return 0;
@@ -539,7 +601,7 @@
 
 	line = minor(tty->device) - tty->driver.minor_start;
 	rs_dprintk(MPC5xxx_PSC_DEBUG_OPEN,
-			"%d: opening line %d. tty=%p ctty=%p)\n", 
+			"%d: opening line %d. tty=%p ctty=%p)\n",
 			(int) current->pid, line, tty, current->tty);
 
 	if ((line < 0) || (line >= RS_TABLE_SIZE))
@@ -728,7 +790,7 @@
 #endif
 
 	func_enter();
-	
+
 	if (I_IXOFF(tty)) {
 		if (port->x_char)
 			port->x_char = 0;
@@ -763,6 +825,7 @@
 static int rs_init_portstructs(void)
 {
 	struct rs_port *port;
+	struct mpc5xxx_psc *psc;
 	int i;
 #ifdef CONFIG_UBOOT
 	extern unsigned char __res[];
@@ -789,7 +852,7 @@
 	rs_driver.termios_locked = rs_termios_locked;
 
 	port = rs_ports;
-	for (i=0; i < MPC5xxx_PSC_NPORTS;i++) {
+	for (i = 0; i < MPC5xxx_PSC_NPORTS; i++) {
 		rs_dprintk(MPC5xxx_PSC_DEBUG_INIT, "initing port %d\n", i);
 		port->gs.callout_termios = tty_std_termios;
 		port->gs.normal_termios	= tty_std_termios;
@@ -813,6 +876,8 @@
 #endif
 		rs_dprintk(MPC5xxx_PSC_DEBUG_INIT, "psc base 0x%08lx\n",
 				(unsigned long)port->psc);
+		psc = port->psc;
+		psc->command = MPC5xxx_PSC_RST_ERR_STAT;
 		port++;
 	}
 
@@ -822,7 +887,9 @@
 
 static int rs_init_drivers(void)
 {
-	int error;
+	struct rs_port *port;
+	char proc_psc_name[8];
+	int i, error;
 
 	func_enter();
 
@@ -878,6 +945,19 @@
 		return 1;
 	}
 
+	/* Create /proc entries */
+	proc_psc_dir = proc_mkdir("driver/psc_mpc52xx", NULL);
+	if (proc_psc_dir != NULL) {
+		for (i=0; i < MPC5xxx_PSC_NPORTS; i++) {
+			sprintf(proc_psc_name, "ttyS%1d", i);
+			proc_psc[i] = create_proc_entry(proc_psc_name, 0444, proc_psc_dir);
+			proc_psc[i]->read_proc = sio_read_info;
+			proc_psc[i]->write_proc = NULL;
+			proc_psc[i]->data = &rs_ports[i];
+			proc_psc[i]->owner = THIS_MODULE;
+		}
+	}
+
 	func_exit();
 	return 0;
 }
@@ -888,6 +968,7 @@
 	int rc;
 	int i;
 	struct rs_port *port;
+	char name[6];
 
 	func_enter();
 	rs_dprintk(MPC5xxx_PSC_DEBUG_INIT,
@@ -896,20 +977,29 @@
 	rc = rs_init_portstructs();
 	rs_init_drivers();
 	port = rs_ports;
-	for (i=0; i < MPC5xxx_PSC_NPORTS;i++) {
-		rs_disable_rx_interrupts(port); 
-		rs_disable_tx_interrupts(port); 
+	for (i=0; i < MPC5xxx_PSC_NPORTS; i++) {
+		rs_disable_rx_interrupts(port);
+		rs_disable_tx_interrupts(port);
+		switch ((int) port->psc) {
+			case MPC5xxx_PSC1: { sprintf(name, "PSC1"); break; }
+			case MPC5xxx_PSC2: { sprintf(name, "PSC2"); break; }
+			case MPC5xxx_PSC3: { sprintf(name, "PSC3"); break; }
+			case MPC5xxx_PSC4: { sprintf(name, "PSC4"); break; }
+			case MPC5xxx_PSC5: { sprintf(name, "PSC5"); break; }
+			case MPC5xxx_PSC6: { sprintf(name, "PSC6"); break; }
+			default: { sprintf(name, "PSC?"); break; }
+		}
+
 		if (request_irq(port->irq, rs_interrupt,
 			SA_SHIRQ | SA_INTERRUPT, "serial", port)) {
-			printk(KERN_ERR
-				"rs: Cannot allocate irq for PSC%d.\n", i+1);
+			printk(KERN_ERR "rs: Cannot allocate irq for %s (ttyS%d).\n", name, i);
 			rc = 0;
 			continue;
 		}
 		rs_dprintk(MPC5xxx_PSC_DEBUG_INIT,
 				"requested irq for port[%d] = %08x\n",
 				i, (u32)port);
-		printk(KERN_INFO "ttyS%d on PSC%d\n", i, i+1);
+		printk(KERN_INFO "ttyS%d on %s\n", i, name);
 		port++;
 	}
 
@@ -940,25 +1030,27 @@
 	/*
 	 * Turn PSC interrupts off
 	 */
-	out_be16(&psc->mpc5xxx_psc_imr, 0);
+	psc->mpc5xxx_psc_imr = 0;
 
 	/*
 	 * Wait for the Tx register to become empty
 	 */
 	i = BUSY_WAIT;
-	while (!(in_be16(&psc->mpc5xxx_psc_status) & MPC5xxx_PSC_SR_TXEMP) &&
-			i--)
+	while (!(psc->mpc5xxx_psc_status & MPC5xxx_PSC_SR_TXEMP) && i--) {
 		udelay(1);
-	out_8(&psc->mpc5xxx_psc_buffer_8, c);
+	}
+
+	psc->mpc5xxx_psc_buffer_8 = c;
+
 	i = BUSY_WAIT;
-	while (!(in_be16(&psc->mpc5xxx_psc_status) & MPC5xxx_PSC_SR_TXEMP) &&
-			i--)
+	while (!(psc->mpc5xxx_psc_status & MPC5xxx_PSC_SR_TXEMP) && i--) {
 		udelay(1);
+	}
 
 	/*
 	 * Turn PSC interrupts back on
 	 */
-	out_be16(&psc->mpc5xxx_psc_imr, port->imr);
+	psc->mpc5xxx_psc_imr = port->imr;
 }
 
 static void serial_console_write(struct console *co, const char *s,
@@ -1050,17 +1142,14 @@
 		break;
 	}
 
-	out_8(&psc->command, MPC5xxx_PSC_RST_TX
-			| MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE);
-	out_8(&psc->command, MPC5xxx_PSC_RST_RX);
-
-	out_be32(&psc->sicr, 0x0);
-	out_be16(&psc->mpc5xxx_psc_clock_select, 0xdd00);
-	out_be16(&psc->tfalarm, 0xf8);
-
-	out_8(&psc->command, MPC5xxx_PSC_SEL_MODE_REG_1
-			| MPC5xxx_PSC_RX_ENABLE
-			| MPC5xxx_PSC_TX_ENABLE);
+	psc->command = MPC5xxx_PSC_RST_TX | MPC5xxx_PSC_RX_DISABLE | MPC5xxx_PSC_TX_ENABLE;
+	psc->command = MPC5xxx_PSC_RST_RX;
+
+	psc->sicr = 0x0;
+	psc->mpc5xxx_psc_clock_select = 0xdd00;
+	psc->tfalarm = 0xf8;
+
+	psc->command = MPC5xxx_PSC_SEL_MODE_REG_1 | MPC5xxx_PSC_RX_ENABLE | MPC5xxx_PSC_TX_ENABLE;
 
 #ifdef CONFIG_UBOOT
 	divisor = ((bd->bi_ipbfreq / (baud * 16)) + 1) >> 1;	/* round up */
@@ -1071,11 +1160,11 @@
 	mode1 = bits | parity | MPC5xxx_PSC_MODE_ERR;
 	mode2 = MPC5xxx_PSC_MODE_ONE_STOP;
 
-	out_8(&psc->ctur, divisor>>8);
-	out_8(&psc->ctlr, divisor);
-	out_8(&psc->command, MPC5xxx_PSC_SEL_MODE_REG_1);
-	out_8(&psc->mode, mode1);
-	out_8(&psc->mode, mode2);
+	psc->ctur = divisor >> 8;
+	psc->ctlr = divisor;
+	psc->command = MPC5xxx_PSC_SEL_MODE_REG_1;
+	psc->mode = mode1;
+	psc->mode = mode2;
 
 	return 0;
 }
@@ -1095,3 +1184,51 @@
 }
 
 #endif
+
+static int sio_read_info(char *buf, char **start, off_t offset, int count, int  *eof, void *data)
+{
+	struct rs_port *port;
+	struct mpc5xxx_psc *psc;
+	u16 nStat;
+	int len = 0;
+
+	port = (struct rs_port *) data;
+	psc = port->psc;
+	nStat = psc->mpc5xxx_psc_status;
+
+	switch ((int) psc) {
+		case MPC5xxx_PSC1: { len += sprintf(buf+len, "PSC1: "); break; }
+		case MPC5xxx_PSC2: { len += sprintf(buf+len, "PSC2: "); break; }
+		case MPC5xxx_PSC3: { len += sprintf(buf+len, "PSC3: "); break; }
+		case MPC5xxx_PSC4: { len += sprintf(buf+len, "PSC4: "); break; }
+		case MPC5xxx_PSC5: { len += sprintf(buf+len, "PSC5: "); break; }
+		case MPC5xxx_PSC6: { len += sprintf(buf+len, "PSC6: "); break; }
+		default: { len += sprintf(buf+len, "PSC?: "); break; }
+	}
+	len += sprintf(buf+len, "Baudrate=%d, ", port->baud);
+	len += sprintf(buf+len, "Flags=0x%04x, ", port->cflag);
+	len += sprintf(buf+len, "Status=0x%04x ", nStat);
+	len += sprintf(buf+len, "Irq=%d, ", port->irq);
+	len += sprintf(buf+len, "Base=0x%08x\n      ", port->psc);
+	len += sprintf(buf+len, "RB:%d, ",(nStat & MPC5xxx_PSC_SR_RB) ? 1 : 0);
+	len += sprintf(buf+len, "FE:%d, ",(nStat & MPC5xxx_PSC_SR_FE) ? 1 : 0);
+	len += sprintf(buf+len, "PE:%d, ",(nStat & MPC5xxx_PSC_SR_PE) ? 1 : 0);
+	len += sprintf(buf+len, "OR:%d, ",(nStat & MPC5xxx_PSC_SR_OE) ? 1 : 0);
+	len += sprintf(buf+len, "TxEMP:%d, ",(nStat & MPC5xxx_PSC_SR_TXEMP) ? 1 : 0);
+	len += sprintf(buf+len, "TxRDY:%d, ",(nStat & MPC5xxx_PSC_SR_TXRDY) ? 1 : 0);
+	len += sprintf(buf+len, "RXFULL:%d, ",(nStat & MPC5xxx_PSC_SR_RXFULL) ? 1 : 0);
+	len += sprintf(buf+len, "RxRDY:%d, ",(nStat & MPC5xxx_PSC_SR_RXRDY) ? 1 : 0);
+	len += sprintf(buf+len, "CDE:%d\n",(nStat & MPC5xxx_PSC_SR_CDE) ? 1 : 0);
+
+	if (len <= offset + count)
+		*eof = 1;
+	*start = buf + offset;
+	len -= offset;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+

^ permalink raw reply	[flat|nested] 5+ messages in thread

* AW: MPC5200,PSC in uart mode, receiving problem
  2005-10-10 11:37 Tomasz Prochownik
@ 2005-10-10 13:13 ` Achim Machura
  0 siblings, 0 replies; 5+ messages in thread
From: Achim Machura @ 2005-10-10 13:13 UTC (permalink / raw)
  To: 'Tomasz Prochownik'; +Cc: Linuxppc-Embedded (E-Mail)

Hello Tomasz

> blocks (there is no response in the console).

perhaps we have the same problem a few times ago.
When we connect devices on ttySx which have wrong level on the lines the
uart stay in break mode.

I have made some fixes on the psc-driver. With these fixes the uart works,
but i don't know how efficient.
(clear breakmode and clear buffer)

If you want, i can send the code


best regards
achim

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-02-02 18:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-11  6:55 MPC5200,PSC in uart mode, receiving problem Derycke, Johan
2005-10-11  7:18 ` Wolfgang Denk
2005-10-11  8:10   ` AW: " Achim Machura
2006-02-02 18:22     ` Frank Bodammer
  -- strict thread matches above, loose matches on Subject: below --
2005-10-10 11:37 Tomasz Prochownik
2005-10-10 13:13 ` AW: " Achim Machura

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.