summaryrefslogtreecommitdiff
path: root/plat
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2016-03-01 22:19:39 +0000
committerAndre Przywara <andre.przywara@arm.com>2016-06-02 01:27:48 +0100
commitdca067ee938b3f1c1fda30e56095e0dc62a3a723 (patch)
tree64778d7838e235bced90dc98f2ee9a20f654d930 /plat
parent040150acf71cba5c9d0c7f4a969d63861a189cae (diff)
sun50i: clean up serial (debug) driver
The serial debug driver is hard to read. Also it uses a C struct to describe a fixed hardware device' register layout. Clean up the code to be more readable and switch to the usual (BASE_ADDR + REG_OFFSET) scheme for accessing registers. Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Diffstat (limited to 'plat')
-rw-r--r--plat/sun50iw1p1/drivers/uart/uart.c105
-rw-r--r--plat/sun50iw1p1/include/uart.h28
2 files changed, 60 insertions, 73 deletions
diff --git a/plat/sun50iw1p1/drivers/uart/uart.c b/plat/sun50iw1p1/drivers/uart/uart.c
index 710957c..bd1e7ff 100644
--- a/plat/sun50iw1p1/drivers/uart/uart.c
+++ b/plat/sun50iw1p1/drivers/uart/uart.c
@@ -33,100 +33,90 @@
#include <uart.h>
#include <gpio.h>
#include <ccmu.h>
+
#if DEBUG
-#define thr rbr
-#define dll rbr
-#define dlh ier
-#define iir fcr
-
-static serial_hw_t *serial_ctrl_base = NULL;
-static uint32_t uart_lock = 1;
-#if 0
-normal_gpio_set_t uart_ctrl[2] =
-{
- { 2, 8, 4, 1, 1, 0, {0}},//PB8: 4--RX
- { 2, 9, 4, 1, 1, 0, {0}},//PB9: 4--TX
-};
-#endif
-void sunxi_serial_init(int uart_port, void *gpio_cfg, int gpio_max)
+uintptr_t serial_ctrl_base;
+int uart_locked = 1;
+
+void sunxi_serial_init(int uart_port)
{
- uint32_t reg, i;
+ uint32_t reg;
uint32_t uart_clk;
- if( (uart_port < 0) ||(uart_port > 0) )
- {
- return ;
- }
- //reset
+ /* assert the UART port's reset line */
reg = mmio_read_32(CCMU_BUS_SOFT_RST_REG4);
- reg &= ~(1<<(CCM_UART_PORT_OFFSET + uart_port));
- mmio_write_32(CCMU_BUS_SOFT_RST_REG4,reg);
- for( i = 0; i < 100; i++ );
- reg |= (1<<(CCM_UART_PORT_OFFSET + uart_port));
- mmio_write_32(CCMU_BUS_SOFT_RST_REG4,reg);
- //gate
+ reg &= ~(1 << (CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_SOFT_RST_REG4, reg);
+
+ /* release the clock gate */
reg = mmio_read_32(CCMU_BUS_CLK_GATING_REG3);
- reg &= ~(1<<(CCM_UART_PORT_OFFSET + uart_port));
- mmio_write_32(CCMU_BUS_CLK_GATING_REG3,reg);
- for( i = 0; i < 100; i++ );
- reg |= (1<<(CCM_UART_PORT_OFFSET + uart_port));
- mmio_write_32(CCMU_BUS_CLK_GATING_REG3,reg);
-
- //gpio
- //boot_set_gpio(gpio_cfg, gpio_max, 1); //boot set,so not need to set again
- //uart init
- serial_ctrl_base = (serial_hw_t *)(SUNXI_UART0_BASE + uart_port * CCM_UART_ADDR_OFFSET);
- serial_ctrl_base->mcr = 0x3;
- uart_clk = (24000000 + 8 * UART_BAUD)/(16 * UART_BAUD);
- serial_ctrl_base->lcr |= 0x80;
- serial_ctrl_base->dlh = uart_clk>>8;
- serial_ctrl_base->dll = uart_clk&0xff;
- serial_ctrl_base->lcr &= ~0x80;
- serial_ctrl_base->lcr = ((PARITY&0x03)<<3) | ((STOP&0x01)<<2) | (DLEN&0x03);
- serial_ctrl_base->fcr = 0x7;
+ reg |= (1 << (CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_CLK_GATING_REG3, reg);
+
+ /* de-assert the UART port's reset line */
+ reg = mmio_read_32(CCMU_BUS_SOFT_RST_REG4);
+ reg |= (1 << (CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_SOFT_RST_REG4, reg);
+
+
+ /* The GPIO pins are already configured */
+ serial_ctrl_base = SUNXI_UART0_BASE + uart_port * CCM_UART_ADDR_OFFSET;
+
+ mmio_write_32(serial_ctrl_base + DW_UART_MCR, 0x3);
+ uart_clk = (24000000 + 8 * UART_BAUD) / (16 * UART_BAUD);
+ mmio_write_32(serial_ctrl_base + DW_UART_LCR,
+ mmio_read_32(serial_ctrl_base + DW_UART_LCR) | 0x80);
+
+ mmio_write_32(serial_ctrl_base + DW_UART_DLH, uart_clk >> 8);
+ mmio_write_32(serial_ctrl_base + DW_UART_DLL, uart_clk & 0xff);
+ mmio_write_32(serial_ctrl_base + DW_UART_LCR,
+ mmio_read_32(serial_ctrl_base + DW_UART_LCR) & ~0x80);
+ mmio_write_32(serial_ctrl_base + DW_UART_LCR,
+ (PARITY << 3) | (STOP << 2) | DLEN);
+ mmio_write_32(serial_ctrl_base + DW_UART_FCR, 0x7);
- uart_lock = 0;
+ uart_locked = 0;
return;
}
-
void sunxi_serial_exit(void)
{
- uart_lock = 1;
+ uart_locked = 1;
}
void sunxi_serial_putc (char c)
{
- if (uart_lock)
+ if (uart_locked)
return;
- while((serial_ctrl_base->lsr & ( 1 << 6 )) == 0);
- serial_ctrl_base->thr = c;
+ while (!(mmio_read_32(serial_ctrl_base + DW_UART_LSR) & 0x40))
+ ;
+ mmio_write_32(serial_ctrl_base + DW_UART_THR, c);
}
char sunxi_serial_getc (void)
{
- if (uart_lock)
+ if (uart_locked)
return 0;
- while((serial_ctrl_base->lsr & 1) == 0);
- return serial_ctrl_base->rbr;
-
+ while (!(mmio_read_32(serial_ctrl_base + DW_UART_LSR) & 0x01))
+ ;
+ return mmio_read_32(serial_ctrl_base + DW_UART_RBR);
}
int sunxi_serial_tstc (void)
{
- return serial_ctrl_base->lsr & 1;
+ return mmio_read_32(serial_ctrl_base + DW_UART_LSR) & 0x01;
}
#endif /* DEBUG */
int console_init(unsigned long base_addr,
unsigned int uart_clk, unsigned int baud_rate)
{
- sunxi_serial_init(0,NULL,0);
+ sunxi_serial_init(0);
return 0;
}
@@ -146,4 +136,3 @@ int console_getc(void)
{
return sunxi_serial_getc();
}
-
diff --git a/plat/sun50iw1p1/include/uart.h b/plat/sun50iw1p1/include/uart.h
index af26c0b..e057bab 100644
--- a/plat/sun50iw1p1/include/uart.h
+++ b/plat/sun50iw1p1/include/uart.h
@@ -1,22 +1,20 @@
#ifndef _UART_H_
#define _UART_H_
-#define NULL ((void*)0)
#define CCM_UART_PORT_OFFSET 16
#define CCM_UART_ADDR_OFFSET 0x400
-typedef struct serial_hw
-{
- volatile unsigned int rbr; /* 0 */
- volatile unsigned int ier; /* 1 */
- volatile unsigned int fcr; /* 2 */
- volatile unsigned int lcr; /* 3 */
- volatile unsigned int mcr; /* 4 */
- volatile unsigned int lsr; /* 5 */
- volatile unsigned int msr; /* 6 */
- volatile unsigned int sch; /* 7 */
-}serial_hw_t;
-
+#define DW_UART_RBR 0x00
+#define DW_UART_THR 0x00
+#define DW_UART_DLL 0x00
+#define DW_UART_IER 0x04
+#define DW_UART_DLH 0x04
+#define DW_UART_FCR 0x08
+#define DW_UART_LCR 0x0c
+#define DW_UART_MCR 0x10
+#define DW_UART_LSR 0x14
+#define DW_UART_MSR 0x18
+#define DW_UART_SCH 0x1c
#define UART_BAUD 115200 // Baud rate for UART
// Compute the divisor factor
@@ -26,13 +24,13 @@ typedef struct serial_hw
#define DLEN 3 // Data Length: 0 - 5bits; 1 - 6bits; 2 - 7bits; 3 - 8bits
#if DEBUG
-void sunxi_serial_init(int uart_port, void *gpio_cfg, int gpio_max);
+void sunxi_serial_init(int uart_port);
void sunxi_serial_exit(void);
void sunxi_serial_putc (char c);
char sunxi_serial_getc (void);
int sunxi_serial_tstc (void);
#else
-static inline void sunxi_serial_init(int uart_port, void *gpio_cfg, int gpio_max) {}
+static inline void sunxi_serial_init(int uart_port) {}
static inline void sunxi_serial_exit(void) {}
static inline void sunxi_serial_putc(char c) {}
static inline char sunxi_serial_getc(void) { return 0;}