[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