summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-05-12 06:47:38 +0200
committerCástor Muñoz <cmvidal@gmail.com>2016-05-13 23:21:42 +0200
commit8fb67f48ab57770c3233352de17846a8a773192a (patch)
treefcf00f022dcd297c10ab92df8b85021f55e96f6f /firmware/target
parent2a1e9eb8a8f50f636f86988de1f0cd1b3acf55bb (diff)
iPod Classic: updates for uc8702 driver
- Small rework on the UC8702 UART controller to make it compatible with other s5l870x SOCs. Files moved and renamed, many conditional code added to deal with capabilities and 'features' of the different CPUs. - A couple of optimizacions that should not affect the functionality. Change-Id: I705169f7e8b18d5d1da642f81ffc31c4089780a6
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c23
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/serial-ipod6g.c71
-rw-r--r--firmware/target/arm/s5l8702/system-s5l8702.c2
-rw-r--r--firmware/target/arm/s5l8702/uart-s5l8702.c155
-rw-r--r--firmware/target/arm/s5l8702/uart-target.h (renamed from firmware/target/arm/s5l8702/uart-s5l8702.h)24
-rw-r--r--firmware/target/arm/s5l8702/uc8702.h321
-rw-r--r--firmware/target/arm/uc870x.c (renamed from firmware/target/arm/s5l8702/uc8702.c)226
7 files changed, 300 insertions, 522 deletions
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index 291c809bce..614019bac1 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -31,7 +31,8 @@
#include "pmu-target.h"
#include "pcm-target.h"
#ifdef HAVE_SERIAL
-#include "uc8702.h"
+#include "uart-target.h"
+#include "uc870x.h"
#endif
#include "clocking-s5l8702.h"
@@ -50,7 +51,7 @@ bool dbg_hw_info(void)
int line;
int i;
unsigned int state = 0;
-#ifdef UC8702_DEBUG
+#ifdef UC870X_DEBUG
const unsigned int max_states=3;
#else
const unsigned int max_states=2;
@@ -120,20 +121,18 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("backlight: %s", pmu_read(0x29) ? "on" : "off");
_DEBUG_PRINTF("brightness value: %d", pmu_read(0x28));
}
-#ifdef UC8702_DEBUG
+#ifdef UC870X_DEBUG
else if(state==2)
{
extern struct uartc_port ser_port;
int tx_stat, rx_stat, tx_speed, rx_speed;
char line_cfg[4];
int abr_stat;
- unsigned int abr_cnt;
-
+ uint32_t abr_cnt;
char *abrstatus[] = {"Idle", "Launched", "Counting", "Abnormal"};
- uartc_port_get_line_info(&ser_port, &tx_stat, &rx_stat,
- &tx_speed, &rx_speed, line_cfg);
-
+ uartc_port_get_line_info(&ser_port,
+ &tx_stat, &rx_stat, &tx_speed, &rx_speed, line_cfg);
abr_stat = uartc_port_get_abr_info(&ser_port, &abr_cnt);
_DEBUG_PRINTF("UART %d:", ser_port.id);
@@ -141,7 +140,7 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("line: %s", line_cfg);
_DEBUG_PRINTF("Tx: %s, speed: %d", tx_stat ? "On":"Off", tx_speed);
_DEBUG_PRINTF("Rx: %s, speed: %d", rx_stat ? "On":"Off", rx_speed);
- _DEBUG_PRINTF("ABR: %s, cnt: %d", abrstatus[abr_stat], abr_cnt);
+ _DEBUG_PRINTF("ABR: %s, cnt: %u", abrstatus[abr_stat], abr_cnt);
line++;
_DEBUG_PRINTF("n_tx_bytes: %u", ser_port.n_tx_bytes);
_DEBUG_PRINTF("n_rx_bytes: %u", ser_port.n_rx_bytes);
@@ -149,10 +148,8 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("n_parity_err: %u", ser_port.n_parity_err);
_DEBUG_PRINTF("n_frame_err: %u", ser_port.n_frame_err);
_DEBUG_PRINTF("n_break_detect: %u", ser_port.n_break_detect);
- _DEBUG_PRINTF("n_abnormal0: %u", ser_port.n_abnormal0);
- _DEBUG_PRINTF("n_abnormal1: %u", ser_port.n_abnormal1);
-
- sleep(HZ/20);
+ _DEBUG_PRINTF("ABR n_abnormal: %u %u",
+ ser_port.n_abnormal0, ser_port.n_abnormal1);
}
#endif
else
diff --git a/firmware/target/arm/s5l8702/ipod6g/serial-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/serial-ipod6g.c
index b022fef675..c77b5d0c95 100644
--- a/firmware/target/arm/s5l8702/ipod6g/serial-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/serial-ipod6g.c
@@ -18,19 +18,16 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
#include "config.h"
#include "cpu.h"
#include "system.h"
-#include "kernel.h"
-
#include "serial.h"
+
#include "s5l8702.h"
-#include "uc8702.h"
-#include "uart-s5l8702.h"
+#include "uc870x.h"
/* Define LOGF_ENABLE to enable logf output in this file */
#define LOGF_ENABLE
@@ -38,16 +35,26 @@
/* shall include serial HW configuracion for specific target */
-#define IPOD6G_UART_CLK_HZ 12000000 /* external OSC0 ??? */
+#define IPOD6G_UART_CLK_HZ 12000000 /* external OSC0 ??? */
+
+/* This values below are valid with a UCLK of 12MHz */
+#define BRDATA_9600 (77) /* 9615 */
+#define BRDATA_19200 (38) /* 19231 */
+#define BRDATA_28800 (25) /* 28846 */
+#define BRDATA_38400 (19 | (0xc330c << 8)) /* 38305 */
+#define BRDATA_57600 (12) /* 57692 */
+#define BRDATA_115200 (6 | (0xffffff << 8)) /* 114286 */
-extern struct uartc s5l8702_uart;
+
+extern const struct uartc s5l8702_uartc;
#ifdef IPOD_ACCESSORY_PROTOCOL
void iap_rx_isr(int, char*, char*, uint32_t);
#endif
-struct uartc_port ser_port IDATA_ATTR = {
+struct uartc_port ser_port IDATA_ATTR =
+{
/* location */
- .uartc = &s5l8702_uart,
+ .uartc = &s5l8702_uartc,
.id = 0,
/* configuration */
@@ -70,17 +77,18 @@ struct uartc_port ser_port IDATA_ATTR = {
*/
void serial_setup(void)
{
- uart_port_init(&ser_port);
+ uartc_port_open(&ser_port);
/* set a default configuration, Tx and Rx modes are
disabled when the port is initialized */
- uartc_port_config(&ser_port, 115200, ULCON_DATA_BITS_8,
+ uartc_port_config(&ser_port, ULCON_DATA_BITS_8,
ULCON_PARITY_NONE, ULCON_STOP_BITS_1);
+ uartc_port_set_bitrate_raw(&ser_port, BRDATA_115200);
/* enable Tx interrupt request or POLLING mode */
uartc_port_set_tx_mode(&ser_port, UCON_MODE_INTREQ);
- logf("[%lu] serial_setup(): port %d ready!", USEC_TIMER, ser_port.id);
+ logf("[%lu] "MODEL_NAME" port %d ready!", USEC_TIMER, ser_port.id);
}
int tx_rdy(void)
@@ -93,16 +101,15 @@ void tx_writec(unsigned char c)
uartc_port_tx_byte(&ser_port, c);
}
+
#ifdef IPOD_ACCESSORY_PROTOCOL
#include "iap.h"
-enum {
+static enum {
ABR_STATUS_LAUNCHED, /* ST_SYNC */
ABR_STATUS_SYNCING, /* ST_SOF */
ABR_STATUS_DONE
-};
-
-int abr_status;
+} abr_status;
void serial_bitrate(int rate)
{
@@ -131,8 +138,13 @@ void serial_bitrate(int rate)
abr_status = ABR_STATUS_LAUNCHED;
}
else {
+ uint32_t brdata;
+ if (rate == 57600) brdata = BRDATA_57600;
+ else if (rate == 38400) brdata = BRDATA_38400;
+ else if (rate == 19200) brdata = BRDATA_19200;
+ else brdata = BRDATA_9600;
uartc_port_abr_stop(&ser_port); /* abort ABR if already launched */
- uartc_port_set_bitrate(&ser_port, rate);
+ uartc_port_set_bitrate_raw(&ser_port, brdata);
uartc_port_set_rx_mode(&ser_port, UCON_MODE_INTREQ);
abr_status = ABR_STATUS_DONE;
}
@@ -149,22 +161,21 @@ void iap_rx_isr(int len, char *data, char *err, uint32_t abr_cnt)
/* autobauding */
if (abr_cnt) {
#define BR2CNT(s) (IPOD6G_UART_CLK_HZ / (unsigned)(s))
- unsigned speed;
-
if (abr_cnt < BR2CNT(57600*1.1) || abr_cnt > BR2CNT(9600*0.9)) {
/* detected speed out of range, relaunch ABR */
uartc_port_abr_start(&ser_port);
return;
}
/* valid speed detected, select it */
- else if (abr_cnt < BR2CNT(48000)) speed = 57600;
- else if (abr_cnt < BR2CNT(33600)) speed = 38400;
- else if (abr_cnt < BR2CNT(24000)) speed = 28800;
- else if (abr_cnt < BR2CNT(14400)) speed = 19200;
- else speed = 9600;
+ uint32_t brdata;
+ if (abr_cnt < BR2CNT(48000)) brdata = BRDATA_57600;
+ else if (abr_cnt < BR2CNT(33600)) brdata = BRDATA_38400;
+ else if (abr_cnt < BR2CNT(24000)) brdata = BRDATA_28800;
+ else if (abr_cnt < BR2CNT(14400)) brdata = BRDATA_19200;
+ else brdata = BRDATA_9600;
/* set detected speed */
- uartc_port_set_bitrate(&ser_port, speed);
+ uartc_port_set_bitrate_raw(&ser_port, brdata);
uartc_port_set_rx_mode(&ser_port, UCON_MODE_INTREQ);
/* enter SOF state */
@@ -176,10 +187,12 @@ void iap_rx_isr(int len, char *data, char *err, uint32_t abr_cnt)
}
/* process received data */
- while (len--) {
+ while (len--)
+ {
bool sync_done = !iap_getc(*data++);
- if (abr_status == ABR_STATUS_SYNCING) {
+ if (abr_status == ABR_STATUS_SYNCING)
+ {
if (sync_done) {
abr_status = ABR_STATUS_DONE;
}
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c
index 6b20f44acb..fd3a464e2f 100644
--- a/firmware/target/arm/s5l8702/system-s5l8702.c
+++ b/firmware/target/arm/s5l8702/system-s5l8702.c
@@ -24,9 +24,9 @@
#include "panic.h"
#include "system-target.h"
#include "pmu-target.h"
+#include "uart-target.h"
#include "gpio-s5l8702.h"
#include "dma-s5l8702.h"
-#include "uart-s5l8702.h"
#include "clocking-s5l8702.h"
#define default_interrupt(name) \
diff --git a/firmware/target/arm/s5l8702/uart-s5l8702.c b/firmware/target/arm/s5l8702/uart-s5l8702.c
index 45d61ba627..9d8faaa173 100644
--- a/firmware/target/arm/s5l8702/uart-s5l8702.c
+++ b/firmware/target/arm/s5l8702/uart-s5l8702.c
@@ -18,110 +18,133 @@
* KIND, either express or implied.
*
****************************************************************************/
-
-/* Include Standard files */
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
#include "config.h"
#include "cpu.h"
#include "system.h"
-#include "kernel.h"
#include "s5l8702.h"
-#include "uc8702.h"
-#include "uart-s5l8702.h"
+#include "uc870x.h"
-/* s5l8702 UART configuration */
-struct uartc s5l8702_uart = {
- .baddr = S5L8702_UART_BASE
+/*
+ * s5l8702 UC870X HW: 1 UARTC, 4 ports
+ */
+static struct uartc_port *uartc_port_l[UARTC_N_PORTS];
+const struct uartc s5l8702_uartc =
+{
+ .id = 0,
+ .baddr = UARTC_BASE_ADDR,
+ .port_off = UARTC_PORT_OFFSET,
+ .n_ports = UARTC_N_PORTS,
+ .port_l = uartc_port_l,
};
/*
* Device level functions specific to S5L8702
*/
-void uart_gpio_control(int port_id, bool onoff)
+void uart_target_enable_gpio(int uart_id, int port_id)
{
- if (onoff) {
- switch (port_id) {
- case 0:
- /* configure UART0 Tx/Rx GPIO ports */
- PCON0 = (PCON0 & 0xff00ffff) | 0x00220000;
- break;
- case 1:
- /* configure UART1 GPIO ports, including RTS/CTS signals */
- PCOND = (PCOND & 0xff0000ff) | 0x00222200;
- break;
- case 2:
- case 3:
- /* unknown, probably UART3/4 not routed on s5l8702 */
- default:
- break;
- }
+ (void) uart_id;
+ switch (port_id) {
+ case 0:
+ /* configure UART0 Tx/Rx GPIO ports */
+ PCON0 = (PCON0 & 0xff00ffff) | 0x00220000;
+ break;
+ case 1:
+ /* configure UART1 GPIO ports, including RTS/CTS signals */
+ PCOND = (PCOND & 0xff0000ff) | 0x00222200;
+ break;
+ case 2:
+ case 3:
+ /* unknown */
+ default:
+ break;
}
- else {
+}
+
+void uart_target_disable_gpio(int uart_id, int port_id)
+{
+ (void) uart_id;
+ switch (port_id) {
/* configure minimal power consumption */
- switch (port_id) {
- case 0:
- PCON0 = (PCON0 & 0xff00ffff) | 0x00ee0000;
- break;
- case 1:
- PCOND = (PCOND & 0xff0000ff) | 0x00eeee00;
- break;
- case 2:
- case 3:
- default:
- break;
- }
+ case 0:
+ PCON0 = (PCON0 & 0xff00ffff) | 0x00ee0000;
+ break;
+ case 1:
+ PCOND = (PCOND & 0xff0000ff) | 0x00eeee00;
+ break;
+ case 2:
+ case 3:
+ default:
+ break;
}
}
-/* reset s5l8702 uart related hardware */
-static void s5l8702_uart_hw_init(void)
+void uart_target_enable_irq(int uart_id, int port_id)
{
- for (int id = 0; id < S5L8702_UART_PORT_MAX; id++) {
- VIC0INTENCLEAR = 1 << IRQ_UART(id); /* mask INT */
- uart_gpio_control(id, 0);
- }
+ (void) uart_id;
+ VIC0INTENABLE = 1 << IRQ_UART(port_id);
}
-void uart_init(void)
+void uart_target_disable_irq(int uart_id, int port_id)
{
- s5l8702_uart_hw_init();
- PWRCON(1) &= ~(1 << (CLOCKGATE_UART - 32)); /* on */
- uartc_open(&s5l8702_uart);
+ (void) uart_id;
+ VIC0INTENCLEAR = 1 << IRQ_UART(port_id);
}
-void uart_close(void)
+void uart_target_clear_irq(int uart_id, int port_id)
{
- uartc_close(&s5l8702_uart);
- PWRCON(1) |= (1 << (CLOCKGATE_UART - 32)); /* off */
- s5l8702_uart_hw_init();
+ (void) uart_id;
+ (void) port_id;
}
-void uart_port_init(struct uartc_port *port)
+void uart_target_enable_clocks(int uart_id)
{
- uart_gpio_control(port->id, 1);
- uartc_port_open(port);
- VIC0INTENABLE = 1 << IRQ_UART(port->id); /* unmask INT */
+ (void) uart_id;
+ PWRCON(1) &= ~(1 << (CLOCKGATE_UARTC - 32));
}
-void uart_port_close(struct uartc_port *port)
+void uart_target_disable_clocks(int uart_id)
{
- VIC0INTENCLEAR = 1 << IRQ_UART(port->id); /* mask INT */
- uartc_port_close(port);
- uart_gpio_control(port->id, 0);
+ (void) uart_id;
+ PWRCON(1) |= (1 << (CLOCKGATE_UARTC - 32));
}
-/* ISRs */
+/*
+ * ISRs
+ */
+
+/* On Classic, PORT0 interrupts are not used when iAP is disabled */
+#if !defined(IPOD_6G) || defined(IPOD_ACCESSORY_PROTOCOL)
void ICODE_ATTR INT_UART0(void)
{
- uartc_callback(&s5l8702_uart, 0);
+ uartc_callback(&s5l8702_uartc, 0);
}
+#endif
+/* PORT1,2,3 not used on Classic */
+#ifndef IPOD_6G
void ICODE_ATTR INT_UART1(void)
{
- uartc_callback(&s5l8702_uart, 1);
+ uartc_callback(&s5l8702_uartc, 1);
+}
+
+void ICODE_ATTR INT_UART2(void)
+{
+ uartc_callback(&s5l8702_uartc, 2);
+}
+
+void ICODE_ATTR INT_UART3(void)
+{
+ uartc_callback(&s5l8702_uartc, 3);
+}
+#endif
+
+/* Main init */
+void uart_init(void)
+{
+ uartc_open(&s5l8702_uartc);
}
diff --git a/firmware/target/arm/s5l8702/uart-s5l8702.h b/firmware/target/arm/s5l8702/uart-target.h
index c7ec684284..d6d45b9073 100644
--- a/firmware/target/arm/s5l8702/uart-s5l8702.h
+++ b/firmware/target/arm/s5l8702/uart-target.h
@@ -18,15 +18,21 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __UART_S5L8702_H__
-#define __UART_S5L8702_H__
+#ifndef __UART_TARGET_H__
+#define __UART_TARGET_H__
-#include "uc8702.h"
+/* Define this to show debug data on "View HW Info" */
+/* #define UC870X_DEBUG */
-/* s5l8702 low level routines */
-void uart_init (void);
-void uart_close(void);
-void uart_port_init (struct uartc_port *port);
-void uart_port_close (struct uartc_port *port);
+void uart_init(void);
-#endif /* __UART_S5L8702_H__ */
+/* s5l870x low level routines */
+void uart_target_enable_clocks(int uart_id);
+void uart_target_disable_clocks(int uart_id);
+void uart_target_enable_irq(int uart_id, int port_id);
+void uart_target_disable_irq(int uart_id, int port_id);
+void uart_target_clear_irq(int uart_id, int port_id);
+void uart_target_enable_gpio(int uart_id, int port_id);
+void uart_target_disable_gpio(int uart_id, int port_id);
+
+#endif /* __UART_TARGET_H__ */
diff --git a/firmware/target/arm/s5l8702/uc8702.h b/firmware/target/arm/s5l8702/uc8702.h
deleted file mode 100644
index 36e4f8faa4..0000000000
--- a/firmware/target/arm/s5l8702/uc8702.h
+++ /dev/null
@@ -1,321 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2014 by Cástor Muñoz
- *
- * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#ifndef __UC8702_H__
-#define __UC8702_H__
-
-#include <stdint.h>
-#include <stdbool.h>
-
-
-/* s5l8702 UART controller (UC8702):
- *
- * This UART is similar to the UART included in s5l8700 (see also
- * s3c2416 and s3c6400 datasheets), UC8702 adds fine tunning for
- * Tx/Rx bitrate and autobauding.
- */
-
-/*#define UC8702_DEBUG*/
-
-/*
- * uc8702 HW definitions
- */
-#define UART_PORT_MAX 4
-#define UART_FIFO_SIZE 16
-
-#define UART_PORT_BASE(b,i) ((b) + 0x4000 * (i))
-
-/*
- * controller registers
- */
-#define REG32_PTR_T volatile uint32_t *
-
-#define ULCON(ba) (*((REG32_PTR_T)((ba) + 0x00))) /* line control */
-#define UCON(ba) (*((REG32_PTR_T)((ba) + 0x04))) /* control */
-#define UFCON(ba) (*((REG32_PTR_T)((ba) + 0x08))) /* FIFO control */
-#define UMCON(ba) (*((REG32_PTR_T)((ba) + 0x0C))) /* modem control */
-#define UTRSTAT(ba) (*((REG32_PTR_T)((ba) + 0x10))) /* Tx/Rx status */
-#define UERSTAT(ba) (*((REG32_PTR_T)((ba) + 0x14))) /* Rx error status */
-#define UFSTAT(ba) (*((REG32_PTR_T)((ba) + 0x18))) /* FIFO status */
-#define UMSTAT(ba) (*((REG32_PTR_T)((ba) + 0x1C))) /* modem status */
-#define UTXH(ba) (*((REG32_PTR_T)((ba) + 0x20))) /* transmission hold */
-#define URXH(ba) (*((REG32_PTR_T)((ba) + 0x24))) /* receive buffer */
-#define UBRDIV(ba) (*((REG32_PTR_T)((ba) + 0x28))) /* baud rate divisor */
-#define UABRCNT(ba) (*((REG32_PTR_T)((ba) + 0x2c))) /* autobaud counter */
-#define UABRSTAT(ba) (*((REG32_PTR_T)((ba) + 0x30))) /* autobaud status */
-#define UBRCONTX(ba) (*((REG32_PTR_T)((ba) + 0x34))) /* Tx frame config */
-#define UBRCONRX(ba) (*((REG32_PTR_T)((ba) + 0x38))) /* Rx frame config */
-
-/* ULCON register */
-#define ULCON_DATA_BITS_MASK 0x3
-#define ULCON_DATA_BITS_POS 0
-#define ULCON_DATA_BITS_5 0
-#define ULCON_DATA_BITS_6 1
-#define ULCON_DATA_BITS_7 2
-#define ULCON_DATA_BITS_8 3
-
-#define ULCON_STOP_BITS_MASK 0x1
-#define ULCON_STOP_BITS_POS 2
-#define ULCON_STOP_BITS_1 0
-#define ULCON_STOP_BITS_2 1
-
-#define ULCON_PARITY_MASK 0x7
-#define ULCON_PARITY_POS 3
-#define ULCON_PARITY_NONE 0
-#define ULCON_PARITY_ODD 4
-#define ULCON_PARITY_EVEN 5
-#define ULCON_PARITY_FORCE_1 6
-#define ULCON_PARITY_FORCE_0 7
-
-#define ULCON_INFRARED_EN_BIT (1 << 6)
-
-/* UCON register */
-#define UCON_RX_MODE_MASK 0x3
-#define UCON_RX_MODE_POS 0
-
-#define UCON_TX_MODE_MASK 0x3
-#define UCON_TX_MODE_POS 2
-
-#define UCON_MODE_DISABLED 0
-#define UCON_MODE_INTREQ 1 /* INT request or polling mode */
-#define UCON_MODE_UNDEFINED 2 /* Not defined, DMAREQ signal 1 ??? */
-#define UCON_MODE_DMAREQ 3 /* DMA request (signal 0) */
-
-#define UCON_SEND_BREAK_BIT (1 << 4)
-#define UCON_LOOPBACK_BIT (1 << 5)
-#define UCON_RX_TOUT_EN_BIT (1 << 7) /* Rx timeout enable */
-
-#define UCON_CLKSEL_MASK 0x1
-#define UCON_CLKSEL_POS 10
-#define UCON_CLKSEL_PCLK 0 /* internal */
-#define UCON_CLKSEL_ECLK 1 /* external */
-
-#define UCON_RX_TOUT_INT_BIT (1 << 11) /* Rx timeout INT enable */
-#define UCON_RX_INT_BIT (1 << 12) /* Rx INT enable */
-#define UCON_TX_INT_BIT (1 << 13) /* Tx INT enable */
-#define UCON_ERR_INT_BIT (1 << 14) /* Rx error INT enable */
-#define UCON_MODEM_INT_BIT (1 << 15) /* modem INT enable (TBC) */
-#define UCON_AUTOBR_INT_BIT (1 << 16) /* autobauding INT enable */
-#define UCON_AUTOBR_START_BIT (1 << 17) /* autobauding start/stop */
-
-/* UFCON register */
-#define UFCON_FIFO_ENABLE_BIT (1 << 0)
-#define UFCON_RX_FIFO_RST_BIT (1 << 1)
-#define UFCON_TX_FIFO_RST_BIT (1 << 2)
-
-#define UFCON_RX_FIFO_TRG_MASK 0x3
-#define UFCON_RX_FIFO_TRG_POS 4
-#define UFCON_RX_FIFO_TRG_4 0
-#define UFCON_RX_FIFO_TRG_8 1
-#define UFCON_RX_FIFO_TRG_12 2
-#define UFCON_RX_FIFO_TRG_16 3
-
-#define UFCON_TX_FIFO_TRG_MASK 0x3
-#define UFCON_TX_FIFO_TRG_POS 6
-#define UFCON_TX_FIFO_TRG_EMPTY 0
-#define UFCON_TX_FIFO_TRG_4 1
-#define UFCON_TX_FIFO_TRG_8 2
-#define UFCON_TX_FIFO_TRG_12 3
-
-/* UMCON register */
-#define UMCON_RTS_BIT (1 << 0)
-#define UMCON_AUTO_FLOW_CTRL_BIT (1 << 4)
-
-/* UTRSTAT register */
-#define UTRSTAT_RXBUF_RDY_BIT (1 << 0)
-#define UTRSTAT_TXBUF_EMPTY_BIT (1 << 1)
-#define UTRSTAT_TX_EMPTY_BIT (1 << 2)
-#define UTRSTAT_RX_TOUT_INT_BIT (1 << 3) /* Rx timeout INT status */
-#define UTRSTAT_RX_INT_BIT (1 << 4)
-#define UTRSTAT_TX_INT_BIT (1 << 5)
-#define UTRSTAT_ERR_INT_BIT (1 << 6)
-#define UTRSTAT_MODEM_INT_BIT (1 << 7) /* modem INT status (TBC) */
-#define UTRSTAT_AUTOBR_INT_BIT (1 << 8) /* autobauding INT status */
-
-/* UERSTAT register */
-#define UERSTAT_OVERRUN_BIT (1 << 0)
-#define UERSTAT_PARITY_ERR_BIT (1 << 1)
-#define UERSTAT_FRAME_ERR_BIT (1 << 2)
-#define UERSTAT_BREAK_DETECT_BIT (1 << 3)
-
-/* UFSTAT register */
-#define UFSTAT_RX_FIFO_CNT_MASK 0xf
-#define UFSTAT_RX_FIFO_CNT_POS 0
-
-#define UFSTAT_TX_FIFO_CNT_MASK 0xf
-#define UFSTAT_TX_FIFO_CNT_POS 4
-
-#define UFSTAT_RX_FIFO_FULL_BIT (1 << 8)
-#define UFSTAT_TX_FIFO_FULL_BIT (1 << 9)
-#define UFSTAT_RX_FIFO_ERR_BIT (1 << 10) /* clears when reading UERSTAT
- for the last pending error */
-/* UMSTAT register */
-#define UMSTAT_CTS_ACTIVE_BIT (1 << 0)
-#define UMSTAT_CTS_DELTA_BIT (1 << 4)
-
-/* Bitrate:
- *
- * Master UCLK clock is divided by 16 to serialize data, UBRDIV is
- * used to configure nominal bit width, NBW = (UBRDIV+1)*16 in UCLK
- * clock ticks.
- *
- * Fine tuning works shrining/expanding each individual bit of each
- * frame. Each bit width can be incremented/decremented by 1/16 of
- * nominal bit width, it seems UCLK is divided by 17 for expanded
- * bits and divided by 15 for compressed bits. A whole frame of N
- * bits can be shrined or expanded up to (NBW * N / 16) UCLK clock
- * ticks (in 1/16 steps).
- */
-/* UBRCONx register */
-#define UC_FRAME_MAX_LEN 12 /* 1 start + 8 data + 1 par + 2 stop */
-#define UBRCON_JITTER_MASK 0x3
-#define UBRCON_JITTER_POS(bit) ((bit) << 1) /* 0..UC_FRAME_MAX_LEN-1 */
-
-#define UBRCON_JITTER_NONE 0 /* no jitter for this bit */
-#define UBRCON_JITTER_INC 1 /* increment 1/16 bit width */
-#define UBRCON_JITTER_UNUSED 2 /* does nothing */
-#define UBRCON_JITTER_DEC 3 /* decremet 1/16 bit width */
-
-/* Autobauding:
- *
- * Initial UABRSTAT is NOT_INIT, it goes to READY when either of
- * UCON_AUTOBR bits are enabled for the first time.
- *
- * Interrupts are enabled/disabled using UCON_AUTOBR_INT_BIT and
- * checked using UTRSTAT_AUTOBR_INT_BIT, writing this bit cleans the
- * interrupt.
- *
- * When UCON_AUTOBR_START_BIT is enabled, autobauding starts and the
- * hardware waits for a low pulse on RX line.
- *
- * Once autobauding is started, when a falling edge is detected on
- * the RX line, UABRSTAT changes to COUNTING status, an internal
- * counter starts incrementing at UCLK clock frequency. During
- * COUNTING state, UABRCNT reads as the value of the previous ABR
- * count, not the value of the current internal count.
- *
- * Count finish when a rising edge is detected on the line, at this
- * moment internal counter stops and it can be read using UABRCNT
- * register, UABRSTAT goes to READY, AUTOBR_START_BIT is disabled,
- * and an interrupt is raised if UCON_AUTOBR_INT_BIT is enabled.
- */
-/* UABRSTAT register */
-#define UABRSTAT_STATUS_MASK 0x3
-#define UABRSTAT_STATUS_POS 0
-
-#define UABRSTAT_STATUS_NOT_INIT 0 /* initial status */
-#define UABRSTAT_STATUS_READY 1 /* machine is ready */
-#define UABRSTAT_STATUS_COUNTING 2 /* count in progress */
-
-
-/*
- * structs
- */
-struct uartc
-{
- /* static configuration */
- const uint32_t baddr;
- /* private */
- struct uartc_port *port_l[UART_PORT_MAX];
-};
-
-struct uartc_port
-{
- /* static configuration */
- struct uartc * const uartc;
- const uint8_t id; /* port number */
- const uint8_t rx_trg; /* UFCON_RX_FIFO_TRG_xxx */
- const uint8_t tx_trg; /* UFCON_TX_FIFO_TRG_xxx */
- const uint8_t clksel; /* UFCON_CLKSEL_xxx */
- const uint32_t clkhz; /* UCLK (PCLK or ECLK) frequency */
- void (* const tx_cb) (int len); /* ISRs */
- void (* const rx_cb) (int len, char *data, char *err, uint32_t abr_cnt);
-
- /* private */
- uint32_t baddr;
- uint32_t utrstat_int_mask;
- bool abr_aborted;
- uint8_t rx_data[UART_FIFO_SIZE]; /* data buffer for rx_cb */
- uint8_t rx_err[UART_FIFO_SIZE]; /* error buffer for rx_cb */
-
-#ifdef UC8702_DEBUG
- uint32_t n_tx_bytes;
- uint32_t n_rx_bytes;
- uint32_t n_ovr_err;
- uint32_t n_parity_err;
- uint32_t n_frame_err;
- uint32_t n_break_detect;
- uint32_t n_abnormal0;
- uint32_t n_abnormal1;
-#endif
-};
-
-
-/*
- * uc8702 low level API
- */
-
-/* Initialization */
-void uartc_open(struct uartc* uartc);
-void uartc_close(struct uartc* uartc);
-void uartc_port_open(struct uartc_port *port);
-void uartc_port_close(struct uartc_port *port);
-void uartc_port_rx_onoff(struct uartc_port *port, bool onoff);
-void uartc_port_tx_onoff(struct uartc_port *port, bool onoff);
-
-/* Configuration */
-void uartc_port_config(struct uartc_port *port, unsigned int speed,
- uint8_t data_bits, uint8_t parity, uint8_t stop_bits);
-void uartc_port_set_bitrate(struct uartc_port *port, unsigned int speed);
-void uartc_port_set_rx_mode(struct uartc_port *port, uint32_t mode);
-void uartc_port_set_tx_mode(struct uartc_port *port, uint32_t mode);
-
-/* Transmit */
-bool uartc_port_tx_ready(struct uartc_port *port);
-void uartc_port_tx_byte(struct uartc_port *port, uint8_t ch);
-void uartc_port_send_byte(struct uartc_port *port, uint8_t ch);
-
-/* Receive */
-bool uartc_port_rx_ready(struct uartc_port *port);
-uint8_t uartc_port_rx_byte(struct uartc_port *port);
-uint8_t uartc_port_read_byte(struct uartc_port *port);
-
-/* Autobauding */
-void uartc_port_abr_start(struct uartc_port *port);
-void uartc_port_abr_stop(struct uartc_port *port);
-
-/* ISR */
-void uartc_callback(struct uartc *uartc, int dev);
-
-#ifdef UC8702_DEBUG
-enum {
- ABR_INFO_ST_IDLE,
- ABR_INFO_ST_LAUNCHED,
- ABR_INFO_ST_COUNTING,
- ABR_INFO_ST_ABNORMAL
-};
-
-void uartc_port_get_line_info(struct uartc_port *port,
- int *tx_status, int *rx_status,
- int *tx_speed, int *rx_speed, char *line_cfg);
-
-int uartc_port_get_abr_info(struct uartc_port *port, unsigned int *abr_cnt);
-#endif
-#endif /* __UC8702_H__ */
diff --git a/firmware/target/arm/s5l8702/uc8702.c b/firmware/target/arm/uc870x.c
index 91c4a3c9e6..9537c15e1a 100644
--- a/firmware/target/arm/s5l8702/uc8702.c
+++ b/firmware/target/arm/uc870x.c
@@ -19,79 +19,100 @@
*
****************************************************************************/
#include <stdint.h>
-#include "kernel.h"
-#include "uc8702.h"
+#include <stdbool.h>
+
+#include "config.h"
+#include "system.h"
+
+#include "uart-target.h"
+#include "uc870x.h"
/*
- * s5l8702 UART controller (UC8702)
+ * UC870x: UART controller for s5l870x
*/
/* Rx related masks */
+#if CONFIG_CPU == S5L8700
+#define UTRSTAT_RX_RELATED_INTS (UTRSTAT_RX_INT_BIT | UTRSTAT_ERR_INT_BIT)
+#define UCON_RX_RELATED_INTS (UCON_RX_INT_BIT | UCON_ERR_INT_BIT)
+
+#elif CONFIG_CPU == S5L8701
#define UTRSTAT_RX_RELATED_INTS \
- (UTRSTAT_RX_INT_BIT | UTRSTAT_RX_TOUT_INT_BIT | \
- UTRSTAT_ERR_INT_BIT | UTRSTAT_AUTOBR_INT_BIT)
+ (UTRSTAT_RX_INT_BIT | UTRSTAT_ERR_INT_BIT | UTRSTAT_AUTOBR_INT_BIT)
#define UCON_RX_RELATED_INTS \
- (UCON_RX_INT_BIT | UCON_RX_TOUT_INT_BIT | \
- UCON_ERR_INT_BIT | UCON_AUTOBR_INT_BIT)
+ (UCON_RX_INT_BIT | UCON_ERR_INT_BIT | UCON_AUTOBR_INT_BIT)
+
+#else /* CONFIG_CPU == S5L8702 */
+#define UTRSTAT_RX_RELATED_INTS \
+ (UTRSTAT_RX_INT_BIT | UTRSTAT_ERR_INT_BIT | \
+ UTRSTAT_AUTOBR_INT_BIT | UTRSTAT_RX_TOUT_INT_BIT)
+#define UCON_RX_RELATED_INTS \
+ (UCON_RX_INT_BIT | UCON_ERR_INT_BIT | \
+ UCON_AUTOBR_INT_BIT | UCON_RX_TOUT_INT_BIT)
+#endif
+
+#define UART_PORT_BASE(u,i) (((u)->baddr) + (u)->port_off * (i))
/* Initialization */
-static void uartc_port_id_reset(struct uartc* uartc, int id)
+static void uartc_reset_port_id(const struct uartc* uartc, int port_id)
{
- uint32_t baddr = UART_PORT_BASE(uartc->baddr, id);
+ uart_target_disable_irq(uartc->id, port_id);
+ uart_target_disable_gpio(uartc->id, port_id);
/* set port registers to default reset values */
+ uint32_t baddr = UART_PORT_BASE(uartc, port_id);
UCON(baddr) = 0;
ULCON(baddr) = 0;
UMCON(baddr) = 0;
UFCON(baddr) = UFCON_RX_FIFO_RST_BIT | UFCON_TX_FIFO_RST_BIT;
- /* clear all interrupts */
- UTRSTAT(baddr) = UTRSTAT_RX_RELATED_INTS
- | UTRSTAT_TX_INT_BIT
- | UTRSTAT_MODEM_INT_BIT;
+ UTRSTAT(baddr) = ~0; /* clear all interrupts */
UBRDIV(baddr) = 0;
+#if CONFIG_CPU == S5L8702
UBRCONTX(baddr) = 0;
UBRCONRX(baddr) = 0;
+#endif
- uartc->port_l[id] = (void*)0;
+ uartc->port_l[port_id] = (void*)0;
}
-static void uartc_reset(struct uartc* uartc)
+static void uartc_reset(const struct uartc* uartc)
{
- for (int id = 0; id < UART_PORT_MAX; id++)
- uartc_port_id_reset(uartc, id);
+ for (int port_id = 0; port_id < uartc->n_ports; port_id++)
+ uartc_reset_port_id(uartc, port_id);
}
-void uartc_open(struct uartc* uartc)
- __attribute__((alias("uartc_reset")));
+void uartc_open(const struct uartc *uartc)
+{
+ uart_target_enable_clocks(uartc->id);
+ uartc_reset(uartc);
+}
-void uartc_close(struct uartc* uartc)
- __attribute__((alias("uartc_reset")));
+void uartc_close(const struct uartc *uartc)
+{
+ uartc_reset(uartc);
+ uart_target_disable_clocks(uartc->id);
+}
void uartc_port_open(struct uartc_port *port)
{
- struct uartc *uartc = port->uartc;
- uint32_t baddr = UART_PORT_BASE(uartc->baddr, port->id);
+ const struct uartc *uartc = port->uartc;
+ uint32_t baddr = UART_PORT_BASE(uartc, port->id);
- port->baddr = baddr;
- port->utrstat_int_mask = (port->rx_cb ? UTRSTAT_RX_RELATED_INTS : 0)
- | (port->tx_cb ? UTRSTAT_TX_INT_BIT : 0);
- port->abr_aborted = 0;
+ uart_target_enable_gpio(uartc->id, port->id);
/* disable Tx/Rx and mask all interrupts */
UCON(baddr) = 0;
/* clear all interrupts */
- UTRSTAT(baddr) = UTRSTAT_RX_RELATED_INTS
- | UTRSTAT_TX_INT_BIT
- | UTRSTAT_MODEM_INT_BIT;
+ UTRSTAT(baddr) = ~0;
/* configure registers */
UFCON(baddr) = UFCON_FIFO_ENABLE_BIT
- | UFCON_RX_FIFO_RST_BIT
- | UFCON_TX_FIFO_RST_BIT
- | ((port->rx_trg & UFCON_RX_FIFO_TRG_MASK) << UFCON_RX_FIFO_TRG_POS)
- | ((port->tx_trg & UFCON_TX_FIFO_TRG_MASK) << UFCON_TX_FIFO_TRG_POS);
+ | UFCON_RX_FIFO_RST_BIT
+ | UFCON_TX_FIFO_RST_BIT
+ | ((port->rx_trg & UFCON_RX_FIFO_TRG_MASK) << UFCON_RX_FIFO_TRG_POS)
+ | ((port->tx_trg & UFCON_TX_FIFO_TRG_MASK) << UFCON_TX_FIFO_TRG_POS);
UMCON(baddr) = UMCON_RTS_BIT; /* activate nRTS (low level) */
@@ -101,38 +122,59 @@ void uartc_port_open(struct uartc_port *port)
| (port->rx_cb ? UCON_RX_RELATED_INTS|UCON_RX_TOUT_EN_BIT : 0)
| (port->tx_cb ? UCON_TX_INT_BIT : 0);
- /* register port on parent controller */
+ /* init and register port struct */
+ port->baddr = baddr;
+ port->utrstat_int_mask = (port->rx_cb ? UTRSTAT_RX_RELATED_INTS : 0)
+ | (port->tx_cb ? UTRSTAT_TX_INT_BIT : 0);
+#if CONFIG_CPU != S5L8700
+ port->abr_aborted = 0;
+#endif
uartc->port_l[port->id] = port;
+
+ /* enable interrupts */
+ uart_target_clear_irq(uartc->id, port->id);
+ /*if (port->utrstat_int_mask)*/
+ uart_target_enable_irq(uartc->id, port->id);
}
void uartc_port_close(struct uartc_port *port)
{
- uartc_port_id_reset(port->uartc, port->id);
+ uartc_reset_port_id(port->uartc, port->id);
}
/* Configuration */
-void uartc_port_config(struct uartc_port *port, unsigned int speed,
- uint8_t data_bits, uint8_t parity, uint8_t stop_bits)
+void uartc_port_config(struct uartc_port *port,
+ uint8_t data_bits, uint8_t parity, uint8_t stop_bits)
{
- uint32_t baddr = port->baddr;
-
- ULCON(baddr) = ((parity & ULCON_PARITY_MASK) << ULCON_PARITY_POS)
- | ((stop_bits & ULCON_STOP_BITS_MASK) << ULCON_STOP_BITS_POS)
- | ((data_bits & ULCON_DATA_BITS_MASK) << ULCON_DATA_BITS_POS);
+ ULCON(port->baddr) = ((parity & ULCON_PARITY_MASK) << ULCON_PARITY_POS)
+ | ((stop_bits & ULCON_STOP_BITS_MASK) << ULCON_STOP_BITS_POS)
+ | ((data_bits & ULCON_DATA_BITS_MASK) << ULCON_DATA_BITS_POS);
+}
- uartc_port_set_bitrate(port, speed);
+/* set bitrate using precalculated values */
+void uartc_port_set_bitrate_raw(struct uartc_port *port, uint32_t brdata)
+{
+ uint32_t baddr = port->baddr;
+ UBRDIV(baddr) = brdata & 0xff;
+#if CONFIG_CPU == S5L8702
+ UBRCONRX(baddr) = brdata >> 8;
+ UBRCONTX(baddr) = brdata >> 8;
+#endif
}
+#if 0
+/* calculate values to set real bitrate as close as possible to the
+ requested speed */
void uartc_port_set_bitrate(struct uartc_port *port, unsigned int speed)
{
- uint32_t baddr = port->baddr;
int uclk = port->clkhz;
/* Real baud width in UCLK/16 ticks: trunc(UCLK/(16*speed) + 0.5) */
int brdiv = (uclk + (speed << 3)) / (speed << 4);
- UBRDIV(baddr) = brdiv - 1;
+ uint32_t brdata = brdiv - 1;
+#if CONFIG_CPU == S5L8702
/* Fine adjust:
*
* Along the whole frame, insert/remove "jittered" bauds when needed
@@ -158,7 +200,6 @@ void uartc_port_set_bitrate(struct uartc_port *port, unsigned int speed)
int err_width = 0;
uint32_t brcon = 0;
- /* TODO: for (bit < configured frame length) */
for (int bit = 0; bit < UC_FRAME_MAX_LEN; bit++) {
err_width += baud_err_width;
/* adjust to the nearest width */
@@ -168,24 +209,25 @@ void uartc_port_set_bitrate(struct uartc_port *port, unsigned int speed)
}
}
- UBRCONRX(baddr) = brcon;
- UBRCONTX(baddr) = brcon;
-}
+ brdata |= (brcon << 8);
+#endif /* CONFIG_CPU == S5L8702 */
-/* TODO: uarc_port_set_bitrate_raw() using precalculated values */
+ uartc_port_set_rawbr(port, brdata);
+}
+#endif
/* Select Tx/Rx modes: disabling Tx/Rx resets HW, including
FIFOs and shift registers */
void uartc_port_set_rx_mode(struct uartc_port *port, uint32_t mode)
{
UCON(port->baddr) = (mode << UCON_RX_MODE_POS) |
- (UCON(port->baddr) & ~(UCON_RX_MODE_MASK << UCON_RX_MODE_POS));
+ (_UCON_RD(port->baddr) & ~(UCON_RX_MODE_MASK << UCON_RX_MODE_POS));
}
void uartc_port_set_tx_mode(struct uartc_port *port, uint32_t mode)
{
UCON(port->baddr) = (mode << UCON_TX_MODE_POS) |
- (UCON(port->baddr) & ~(UCON_TX_MODE_MASK << UCON_TX_MODE_POS));
+ (_UCON_RD(port->baddr) & ~(UCON_TX_MODE_MASK << UCON_TX_MODE_POS));
}
/* Transmit */
@@ -197,7 +239,7 @@ bool uartc_port_tx_ready(struct uartc_port *port)
void uartc_port_tx_byte(struct uartc_port *port, uint8_t ch)
{
UTXH(port->baddr) = ch;
-#ifdef UC8702_DEBUG
+#ifdef UC870X_DEBUG
port->n_tx_bytes++;
#endif
}
@@ -227,6 +269,7 @@ uint8_t uartc_port_read_byte(struct uartc_port *port)
return uartc_port_rx_byte(port);
}
+#if CONFIG_CPU != S5L8700
/* Autobauding */
static inline int uartc_port_abr_status(struct uartc_port *port)
{
@@ -236,7 +279,7 @@ static inline int uartc_port_abr_status(struct uartc_port *port)
void uartc_port_abr_start(struct uartc_port *port)
{
port->abr_aborted = 0;
- UCON(port->baddr) |= UCON_AUTOBR_START_BIT;
+ UCON(port->baddr) = _UCON_RD(port->baddr) | UCON_AUTOBR_START_BIT;
}
void uartc_port_abr_stop(struct uartc_port *port)
@@ -255,13 +298,14 @@ void uartc_port_abr_stop(struct uartc_port *port)
*/
port->abr_aborted = 1;
else
- UCON(port->baddr) &= ~UCON_AUTOBR_START_BIT;
+ UCON(port->baddr) = _UCON_RD(port->baddr) & ~UCON_AUTOBR_START_BIT;
}
+#endif /* CONFIG_CPU != S5L8700 */
/* ISR */
-void ICODE_ATTR uartc_callback(struct uartc *uartc, int id)
+void ICODE_ATTR uartc_callback(const struct uartc* uartc, int port_id)
{
- struct uartc_port *port = uartc->port_l[id];
+ struct uartc_port *port = uartc->port_l[port_id];
uint32_t baddr = port->baddr;
/* filter registered interrupts */
@@ -274,23 +318,25 @@ void ICODE_ATTR uartc_callback(struct uartc *uartc, int id)
if (ints & UTRSTAT_RX_RELATED_INTS)
{
int len = 0;
+#if CONFIG_CPU != S5L8700
uint32_t abr_cnt = 0;
if (ints & UTRSTAT_AUTOBR_INT_BIT)
{
if (uartc_port_abr_status(port) == UABRSTAT_STATUS_COUNTING) {
- #ifdef UC8702_DEBUG
- if (UCON(baddr) & UCON_AUTOBR_START_BIT) port->n_abnormal0++;
+ #ifdef UC870X_DEBUG
+ if (_UCON_RD(baddr) & UCON_AUTOBR_START_BIT) port->n_abnormal0++;
else port->n_abnormal1++;
#endif
/* try to fix abnormal situations */
- UCON(baddr) |= UCON_AUTOBR_START_BIT;
+ UCON(baddr) = _UCON_RD(baddr) | UCON_AUTOBR_START_BIT;
}
else if (!port->abr_aborted)
abr_cnt = UABRCNT(baddr);
}
if (ints & (UTRSTAT_RX_RELATED_INTS ^ UTRSTAT_AUTOBR_INT_BIT))
+#endif /* CONFIG_CPU != S5L8700 */
{
/* get FIFO count */
uint32_t ufstat = UFSTAT(baddr);
@@ -304,15 +350,19 @@ void ICODE_ATTR uartc_callback(struct uartc *uartc, int id)
}
}
- /* 'abr_cnt' is zero when no ABR interrupt exists, 'len'
- * might be zero due to RX_TOUT interrupts are raised by
- * the hardware even when RX FIFO is empty.
- * When overrun, it is marked on the first readed error:
+ /* 'len' might be zero due to RX_TOUT interrupts are
+ * raised by the hardware even when RX FIFO is empty.
+ * When overrun, it is marked on the first error:
* overrun = len ? (rx_err[0] & UERSTAT_OVERRUN_BIT) : 0
*/
+#if CONFIG_CPU == S5L8700
+ port->rx_cb(len, port->rx_data, port->rx_err);
+#else
+ /* 'abr_cnt' is zero when no ABR interrupt exists */
port->rx_cb(len, port->rx_data, port->rx_err, abr_cnt);
+#endif
- #ifdef UC8702_DEBUG
+#ifdef UC870X_DEBUG
if (len) {
port->n_rx_bytes += len;
if (port->rx_err[0] & UERSTAT_OVERRUN_BIT)
@@ -326,24 +376,25 @@ void ICODE_ATTR uartc_callback(struct uartc *uartc, int id)
port->n_break_detect++;
}
}
- #endif
+#endif
}
- #if 0
+#if 0
/* not used and not tested */
if (ints & UTRSTAT_TX_INT_BIT)
{
port->tx_cb(UART_FIFO_SIZE - ((UFSTAT(baddr) & \
UFSTAT_TX_FIFO_CNT_MASK) >> UFSTAT_TX_FIFO_CNT_POS));
}
- #endif
+#endif
}
-#ifdef UC8702_DEBUG
+#ifdef UC870X_DEBUG
/*#define LOGF_ENABLE*/
#include "logf.h"
+#if CONFIG_CPU == S5L8702
static int get_bitrate(int uclk, int brdiv, int brcon, int frame_len)
{
logf("get_bitrate(%d, %d, 0x%08x, %d)", uclk, brdiv, brcon, frame_len);
@@ -375,6 +426,7 @@ static int get_bitrate(int uclk, int brdiv, int brcon, int frame_len)
return avg_speed;
}
+#endif /* CONFIG_CPU == S5L8702 */
void uartc_port_get_line_info(struct uartc_port *port,
int *tx_status, int *rx_status,
@@ -382,25 +434,32 @@ void uartc_port_get_line_info(struct uartc_port *port,
{
uint32_t baddr = port->baddr;
- uint32_t ucon = UCON(baddr);
- if (*tx_status)
+ uint32_t ucon = _UCON_RD(baddr);
+ if (tx_status)
*tx_status = ((ucon >> UCON_TX_MODE_POS) & UCON_TX_MODE_MASK) ? 1 : 0;
- if (*rx_status)
+ if (rx_status)
*rx_status = ((ucon >> UCON_RX_MODE_POS) & UCON_RX_MODE_MASK) ? 1 : 0;
uint32_t ulcon = ULCON(baddr);
int n_data = ((ulcon >> ULCON_DATA_BITS_POS) & ULCON_DATA_BITS_MASK) + 5;
int n_stop = ((ulcon >> ULCON_STOP_BITS_POS) & ULCON_STOP_BITS_MASK) + 1;
int parity = (ulcon >> ULCON_PARITY_POS) & ULCON_PARITY_MASK;
- int frame_len = 1 + n_data + (parity ? 1 : 0) + n_stop;
uint32_t brdiv = UBRDIV(baddr) + 1;
- if (*tx_speed)
+#if CONFIG_CPU == S5L8702
+ int frame_len = 1 + n_data + (parity ? 1 : 0) + n_stop;
+ if (tx_speed)
*tx_speed = get_bitrate(port->clkhz, brdiv, UBRCONTX(baddr), frame_len);
- if (*rx_speed)
+ if (rx_speed)
*rx_speed = get_bitrate(port->clkhz, brdiv, UBRCONRX(baddr), frame_len);
+#else
+ /* speed = truncate(UCLK/(16*brdiv) + 0.5) */
+ int speed = (port->clkhz + (brdiv << 3)) / (brdiv << 4);
+ if (tx_speed) *tx_speed = speed;
+ if (rx_speed) *rx_speed = speed;
+#endif
- if (*line_cfg) {
+ if (line_cfg) {
line_cfg[0] = '0' + n_data;
line_cfg[1] = ((parity == ULCON_PARITY_NONE) ? 'N' :
((parity == ULCON_PARITY_EVEN) ? 'E' :
@@ -412,18 +471,18 @@ void uartc_port_get_line_info(struct uartc_port *port,
}
}
+#if CONFIG_CPU != S5L8700
/* Autobauding */
-int uartc_port_get_abr_info(struct uartc_port *port, unsigned int *abr_cnt)
+int uartc_port_get_abr_info(struct uartc_port *port, uint32_t *abr_cnt)
{
int status;
uint32_t abr_status;
- uint32_t baddr = port->baddr;
int flags = disable_irq_save();
abr_status = uartc_port_abr_status(port);
- if (UCON(port->baddr) & UCON_AUTOBR_START_BIT) {
+ if (_UCON_RD(port->baddr) & UCON_AUTOBR_START_BIT) {
if (abr_status == UABRSTAT_STATUS_COUNTING)
status = ABR_INFO_ST_COUNTING; /* waiting for rising edge */
else
@@ -436,11 +495,12 @@ int uartc_port_get_abr_info(struct uartc_port *port, unsigned int *abr_cnt)
status = ABR_INFO_ST_IDLE;
}
- if (*abr_cnt)
- *abr_cnt = UABRCNT(baddr);
+ if (abr_cnt)
+ *abr_cnt = UABRCNT(port->baddr);
restore_irq(flags);
return status;
}
-#endif /* UC8702_DEBUG */
+#endif /* CONFIG_CPU != S5L8700 */
+#endif /* UC870X_DEBUG */