[U-Boot] [V2 03/15] S3C64XX: Use readl/writel to operate uart

Zhong Hongbo bocui107 at gmail.com
Fri Jul 13 18:11:41 CEST 2012


From: Zhong Hongbo <bocui107 at gmail.com>

Signed-off-by: Zhong Hongbo <bocui107 at gmail.com>
---
Change for V2:
	- Change the type of the return value from unsinged int
	   to unsinged long for s3c64xx_get_base_uart function.
	- Delete const for the local variable.
---
 arch/arm/include/asm/arch-s3c64xx/s3c6400.h |   65 +--------------------------
 arch/arm/include/asm/arch-s3c64xx/s3c64x0.h |   31 -------------
 arch/arm/include/asm/arch-s3c64xx/uart.h    |   54 ++++++++++++++++++++++
 board/samsung/smdk6400/lowlevel_init.S      |    8 ---
 drivers/serial/s3c64xx.c                    |   50 +++++++++++++--------
 5 files changed, 87 insertions(+), 121 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-s3c64xx/uart.h

diff --git a/arch/arm/include/asm/arch-s3c64xx/s3c6400.h b/arch/arm/include/asm/arch-s3c64xx/s3c6400.h
index d6c5dd9..77b9509 100644
--- a/arch/arm/include/asm/arch-s3c64xx/s3c6400.h
+++ b/arch/arm/include/asm/arch-s3c64xx/s3c6400.h
@@ -582,62 +582,6 @@
  */
 #define ELFIN_UART_BASE		0x7F005000
 
-#define ELFIN_UART0_OFFSET	0x0000
-#define ELFIN_UART1_OFFSET	0x0400
-#define ELFIN_UART2_OFFSET	0x0800
-
-#define ULCON_OFFSET		0x00
-#define UCON_OFFSET		0x04
-#define UFCON_OFFSET		0x08
-#define UMCON_OFFSET		0x0C
-#define UTRSTAT_OFFSET		0x10
-#define UERSTAT_OFFSET		0x14
-#define UFSTAT_OFFSET		0x18
-#define UMSTAT_OFFSET		0x1C
-#define UTXH_OFFSET		0x20
-#define URXH_OFFSET		0x24
-#define UBRDIV_OFFSET		0x28
-#define UDIVSLOT_OFFSET		0x2C
-#define UINTP_OFFSET		0x30
-#define UINTSP_OFFSET		0x34
-#define UINTM_OFFSET		0x38
-
-#define ULCON0_REG		__REG(0x7F005000)
-#define UCON0_REG		__REG(0x7F005004)
-#define UFCON0_REG		__REG(0x7F005008)
-#define UMCON0_REG		__REG(0x7F00500C)
-#define UTRSTAT0_REG		__REG(0x7F005010)
-#define UERSTAT0_REG		__REG(0x7F005014)
-#define UFSTAT0_REG		__REG(0x7F005018)
-#define UMSTAT0_REG		__REG(0x7F00501c)
-#define UTXH0_REG		__REG(0x7F005020)
-#define URXH0_REG		__REG(0x7F005024)
-#define UBRDIV0_REG		__REG(0x7F005028)
-#define UDIVSLOT0_REG		__REG(0x7F00502c)
-#define UINTP0_REG		__REG(0x7F005030)
-#define UINTSP0_REG		__REG(0x7F005034)
-#define UINTM0_REG		__REG(0x7F005038)
-
-#define ULCON1_REG		__REG(0x7F005400)
-#define UCON1_REG		__REG(0x7F005404)
-#define UFCON1_REG		__REG(0x7F005408)
-#define UMCON1_REG		__REG(0x7F00540C)
-#define UTRSTAT1_REG		__REG(0x7F005410)
-#define UERSTAT1_REG		__REG(0x7F005414)
-#define UFSTAT1_REG		__REG(0x7F005418)
-#define UMSTAT1_REG		__REG(0x7F00541c)
-#define UTXH1_REG		__REG(0x7F005420)
-#define URXH1_REG		__REG(0x7F005424)
-#define UBRDIV1_REG		__REG(0x7F005428)
-#define UDIVSLOT1_REG		__REG(0x7F00542c)
-#define UINTP1_REG		__REG(0x7F005430)
-#define UINTSP1_REG		__REG(0x7F005434)
-#define UINTM1_REG		__REG(0x7F005438)
-
-#define UTRSTAT_TX_EMPTY	(1 << 2)
-#define UTRSTAT_RX_READY	(1 << 0)
-#define UART_ERR_MASK		0xF
-
 /*
  * PWM timer
  */
@@ -804,17 +748,12 @@
 #define DMC_DDR_USER_CONFIG	1
 
 #ifndef __ASSEMBLY__
-enum s3c64xx_uarts_nr {
-	S3C64XX_UART0,
-	S3C64XX_UART1,
-	S3C64XX_UART2,
-};
 
 #include "s3c64x0.h"
 
-static inline s3c64xx_uart *s3c64xx_get_base_uart(enum s3c64xx_uarts_nr nr)
+static inline unsigned long s3c64xx_get_base_uart(void)
 {
-	return (s3c64xx_uart *)(ELFIN_UART_BASE + (nr * 0x400));
+	return ELFIN_UART_BASE;
 }
 
 static inline unsigned long s3c64xx_get_base_nand(void)
diff --git a/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h b/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h
index 0bbf1d0..7add68c 100644
--- a/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h
+++ b/arch/arm/include/asm/arch-s3c64xx/s3c64x0.h
@@ -40,37 +40,6 @@
 
 #include <asm/types.h>
 
-/* UART (see manual chapter 11) */
-typedef struct {
-	volatile u32	ULCON;
-	volatile u32	UCON;
-	volatile u32	UFCON;
-	volatile u32	UMCON;
-	volatile u32	UTRSTAT;
-	volatile u32	UERSTAT;
-	volatile u32	UFSTAT;
-	volatile u32	UMSTAT;
-#ifdef __BIG_ENDIAN
-	volatile u8	res1[3];
-	volatile u8	UTXH;
-	volatile u8	res2[3];
-	volatile u8	URXH;
-#else /* Little Endian */
-	volatile u8	UTXH;
-	volatile u8	res1[3];
-	volatile u8	URXH;
-	volatile u8	res2[3];
-#endif
-	volatile u32	UBRDIV;
-#ifdef __BIG_ENDIAN
-	volatile u8	res3[2];
-	volatile u16	UDIVSLOT;
-#else
-	volatile u16	UDIVSLOT;
-	volatile u8	res3[2];
-#endif
-} s3c64xx_uart;
-
 /* PWM TIMER (see manual chapter 10) */
 typedef struct {
 	volatile u32	TCNTB;
diff --git a/arch/arm/include/asm/arch-s3c64xx/uart.h b/arch/arm/include/asm/arch-s3c64xx/uart.h
new file mode 100644
index 0000000..f3f37aa
--- /dev/null
+++ b/arch/arm/include/asm/arch-s3c64xx/uart.h
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2012
+ * Zhong Hongbo <bocui107 at gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_UART__
+#define __ASM_ARCH_UART__
+
+#ifndef __ASSEMBLY__
+
+enum s3c64xx_uarts_nr {
+	S3C64XX_UART0,
+	S3C64XX_UART1,
+	S3C64XX_UART2,
+};
+
+/* UART (see manual chapter 11) */
+struct s3c64xx_uart {
+	unsigned int	ulcon;
+	unsigned int	ucon;
+	unsigned int	ufcon;
+	unsigned int	umcon;
+	unsigned int	utrstat;
+	unsigned int	uerstat;
+	unsigned int	ufstat;
+	unsigned int	umstat;
+	unsigned int	utxh;
+	unsigned int	urxh;
+	unsigned int	ubrdiv;
+	unsigned int	udivslot;
+	unsigned int	uintp;
+	unsigned int	uintsp;
+	unsigned int	uintm;
+} s3c64xx_uart;
+#endif
+#endif
diff --git a/board/samsung/smdk6400/lowlevel_init.S b/board/samsung/smdk6400/lowlevel_init.S
index 4a82e4d..1142be1 100644
--- a/board/samsung/smdk6400/lowlevel_init.S
+++ b/board/samsung/smdk6400/lowlevel_init.S
@@ -36,14 +36,6 @@
 
 #include <asm/arch/s3c6400.h>
 
-#ifdef CONFIG_SERIAL1
-#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
-#elif defined(CONFIG_SERIAL2)
-#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET)
-#else
-#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET)
-#endif
-
 _TEXT_BASE:
 	.word	CONFIG_SYS_TEXT_BASE
 
diff --git a/drivers/serial/s3c64xx.c b/drivers/serial/s3c64xx.c
index a88e930..e411085 100644
--- a/drivers/serial/s3c64xx.c
+++ b/drivers/serial/s3c64xx.c
@@ -22,8 +22,9 @@
  */
 
 #include <common.h>
-
+#include <asm/io.h>
 #include <asm/arch/s3c6400.h>
+#include <asm/arch/uart.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -42,6 +43,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define barrier() asm volatile("" ::: "memory")
 
+static inline struct s3c64xx_uart *s3c_get_base_uart(void)
+{
+	u32 offset = UART_NR * 0x4000;
+	return (struct s3c64xx_uart *)(s3c64xx_get_base_uart() + offset);
+}
 /*
  * The coefficient, used to calculate the baudrate on S3C6400 UARTs is
  * calculated as
@@ -70,15 +76,16 @@ static const int udivslot[] = {
 
 void serial_setbrg(void)
 {
-	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
+	struct s3c64xx_uart *uart = s3c_get_base_uart();
 	u32 pclk = get_PCLK();
 	u32 baudrate = gd->baudrate;
+	unsigned int val;
 	int i;
 
-	i = (pclk / baudrate) % 16;
+	val = pclk / baudrate;
 
-	uart->UBRDIV = pclk / baudrate / 16 - 1;
-	uart->UDIVSLOT = udivslot[i];
+	writel(val / 16 - 1, &uart->ubrdiv);
+	writew(udivslot[val % 16], &uart->udivslot);
 
 	for (i = 0; i < 100; i++)
 		barrier();
@@ -90,16 +97,19 @@ void serial_setbrg(void)
  */
 int serial_init(void)
 {
-	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
+	struct s3c64xx_uart *uart = s3c_get_base_uart();
 
 	/* reset and enable FIFOs, set triggers to the maximum */
-	uart->UFCON = 0xff;
-	uart->UMCON = 0;
+	writel(0, &uart->ufcon);
+	writel(0, &uart->umcon);
 	/* 8N1 */
-	uart->ULCON = 3;
+	writel(0x3, &uart->ulcon);
 	/* No interrupts, no DMA, pure polling */
-	uart->UCON = 5;
-
+#if defined(CONFIG_S3C6400)
+	writel(0x5, &uart->ucon);
+#else
+	writel(0xe45, &uart->ucon);
+#endif
 	serial_setbrg();
 
 	return 0;
@@ -112,12 +122,13 @@ int serial_init(void)
  */
 int serial_getc(void)
 {
-	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
+	struct s3c64xx_uart *uart = s3c_get_base_uart();
 
 	/* wait for character to arrive */
-	while (!(uart->UTRSTAT & 0x1));
+	while (!(readl(&uart->utrstat) & 0x1))
+		;
 
-	return uart->URXH & 0xff;
+	return (int)(readb(&uart->urxh) & 0xff);
 }
 
 #ifdef CONFIG_MODEM_SUPPORT
@@ -139,7 +150,7 @@ void enable_putc(void)
  */
 void serial_putc(const char c)
 {
-	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
+	struct s3c64xx_uart *uart = s3c_get_base_uart();
 
 #ifdef CONFIG_MODEM_SUPPORT
 	if (be_quiet)
@@ -147,9 +158,10 @@ void serial_putc(const char c)
 #endif
 
 	/* wait for room in the tx FIFO */
-	while (!(uart->UTRSTAT & 0x2));
+	while (!(readl(&uart->utrstat) & 0x2))
+		;
 
-	uart->UTXH = c;
+	writeb(c, &uart->utxh);
 
 	/* If \n, also do \r */
 	if (c == '\n')
@@ -161,9 +173,9 @@ void serial_putc(const char c)
  */
 int serial_tstc(void)
 {
-	s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
+	struct s3c64xx_uart *uart = s3c_get_base_uart();
 
-	return uart->UTRSTAT & 0x1;
+	return readl(&uart->utrstat) & 0x1;
 }
 
 void serial_puts(const char *s)
-- 
1.7.5.4



More information about the U-Boot mailing list