LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: John Linn <john.linn@xilinx.com>
To: linuxppc-dev@ozlabs.org, jwboyer@linux.vnet.ibm.com
Cc: John Linn <john.linn@xilinx.com>
Subject: [PATCH] [POWERPC] Xilinx: Boot: Fix 16550 UART initialization
Date: Mon, 17 Mar 2008 09:41:54 -0700	[thread overview]
Message-ID: <20080317164202.7E8A41A3806F@mail213-sin.bigfish.com> (raw)

The UART 16550 initialization was not setting up the registers
correctly. Code was added to pull the frequency and speed from
the device tree and initialize the registers using those values.

The boot code was not and is still not using the cmd line
to setup up the uart. The frequency of the clock driving the
UART must be specified in the device tree so that the baud
rate generator can be setup.

---

Please pull this patch for 2.6.26.
---
 arch/powerpc/boot/ns16550.c |   69 +++++++++++++++++++++++++++++++++---------
 1 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
index f8f1b2f..d8edd48 100644
--- a/arch/powerpc/boot/ns16550.c
+++ b/arch/powerpc/boot/ns16550.c
@@ -15,23 +15,47 @@
 #include "io.h"
 #include "ops.h"
 
-#define UART_DLL	0	/* Out: Divisor Latch Low */
-#define UART_DLM	1	/* Out: Divisor Latch High */
-#define UART_FCR	2	/* Out: FIFO Control Register */
-#define UART_LCR	3	/* Out: Line Control Register */
-#define UART_MCR	4	/* Out: Modem Control Register */
-#define UART_LSR	5	/* In:  Line Status Register */
-#define UART_LSR_THRE	0x20	/* Transmit-hold-register empty */
-#define UART_LSR_DR	0x01	/* Receiver data ready */
-#define UART_MSR	6	/* In:  Modem Status Register */
-#define UART_SCR	7	/* I/O: Scratch Register */
-
-static unsigned char *reg_base;
-static u32 reg_shift;
+#define UART_DLL		0	/* Out: Divisor Latch Low */
+#define UART_DLM		1	/* Out: Divisor Latch High */
+#define UART_FCR		2	/* Out: FIFO Control Register */
+#define UART_FCR_CLEAR_RCVR 	0x02 	/* Clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT	0x04 	/* Clear the XMIT FIFO */
+#define UART_LCR		3	/* Out: Line Control Register */
+#define UART_MCR		4	/* Out: Modem Control Register */
+#define UART_MCR_RTS		0x02 	/* RTS complement */
+#define UART_MCR_DTR		0x01 	/* DTR complement */
+#define UART_LSR		5	/* In:  Line Status Register */
+#define UART_LSR_THRE		0x20	/* Transmit-hold-register empty */
+#define UART_LSR_DR		0x01	/* Receiver data ready */
+#define UART_LCR_DLAB		0x80 	/* Divisor latch access bit */
+#define UART_LCR_WLEN8		0x03 	/* Wordlength: 8 bits */
+#define UART_MSR		6	/* In:  Modem Status Register */
+#define UART_SCR		7	/* I/O: Scratch Register */
+
+volatile static unsigned char *reg_base;
+volatile static u32 reg_shift;
+volatile static u16 divisor;
 
 static int ns16550_open(void)
 {
-	out_8(reg_base + (UART_FCR << reg_shift), 0x06);
+
+	/* Access baud rate */
+	out_8(reg_base + (UART_LCR << reg_shift), UART_LCR_DLAB);
+
+	/* Baud rate based on input clock */
+	out_8(reg_base + (UART_DLL << reg_shift), divisor & 0xFF);
+	out_8(reg_base + (UART_DLM << reg_shift), divisor >> 8);
+
+	/* 8 data, 1 stop, no parity */
+	out_8(reg_base + (UART_LCR << reg_shift), UART_LCR_WLEN8);
+
+	/* RTS/DTR */
+	out_8(reg_base + (UART_MCR << reg_shift), UART_MCR_RTS | UART_MCR_DTR);
+
+	/* Clear transmitter and receiver */
+	out_8(reg_base + (UART_FCR << reg_shift), 
+				UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR);
+
 	return 0;
 }
 
@@ -56,6 +80,7 @@ int ns16550_console_init(void *devp, struct serial_console_data *scdp)
 {
 	int n;
 	unsigned long reg_phys;
+	u32 clk, spd;
 
 	n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
 	if (n != sizeof(reg_base)) {
@@ -65,9 +90,23 @@ int ns16550_console_init(void *devp, struct serial_console_data *scdp)
 		reg_base = (void *)reg_phys;
 	}
 
-	n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
+	n = getprop(devp, "reg-shift", (void *)&reg_shift, sizeof(reg_shift));
 	if (n != sizeof(reg_shift))
 		reg_shift = 0;
+	
+	/* the base address has to change for devices with odd reg spacing */
+	reg_base = reg_base + ((1 << reg_shift) - 1); 
+
+	n = getprop(devp, "current-speed", (void *)&spd, sizeof(spd));
+	if (n != sizeof(spd))
+		spd = 9600;
+
+	/* should there be a default clock rate?*/
+	n = getprop(devp, "clock-frequency", (void *)&clk, sizeof(clk));
+	if (n != sizeof(clk))
+		return -1;
+
+	divisor = clk / (16 * spd);
 
 	scdp->open = ns16550_open;
 	scdp->putc = ns16550_putc;
-- 
1.5.2.1

             reply	other threads:[~2008-03-17 16:42 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-17 16:41 John Linn [this message]
2008-03-17 19:47 ` [PATCH] [POWERPC] Xilinx: Boot: Fix 16550 UART initialization Grant Likely
2008-03-17 19:57   ` John Linn
2008-03-17 20:08     ` Grant Likely
2008-03-17 20:10       ` John Linn
2008-03-17 20:13         ` Grant Likely
2008-03-17 20:17       ` Stephen Neuendorffer
2008-03-17 20:24         ` Grant Likely
2008-03-17 20:25           ` Stephen Neuendorffer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080317164202.7E8A41A3806F@mail213-sin.bigfish.com \
    --to=john.linn@xilinx.com \
    --cc=jwboyer@linux.vnet.ibm.com \
    --cc=linuxppc-dev@ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox