summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/export/s5l8702.h9
-rw-r--r--firmware/export/uc870x.h (renamed from firmware/target/arm/s5l8702/uc8702.h)123
-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/uc870x.c (renamed from firmware/target/arm/s5l8702/uc8702.c)226
9 files changed, 393 insertions, 242 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index cd1bf492d8..098eca427f 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1610,7 +1610,7 @@ target/arm/s5l8702/ipod6g/pmu-ipod6g.c
target/arm/s5l8702/ipod6g/rtc-ipod6g.c
target/arm/s5l8700/usb-nano2g-6g.c
#ifdef HAVE_SERIAL
-target/arm/s5l8702/uc8702.c
+target/arm/uc870x.c
target/arm/s5l8702/uart-s5l8702.c
target/arm/s5l8702/ipod6g/serial-ipod6g.c
#endif
diff --git a/firmware/export/s5l8702.h b/firmware/export/s5l8702.h
index 00d92a58b1..59170b04ea 100644
--- a/firmware/export/s5l8702.h
+++ b/firmware/export/s5l8702.h
@@ -711,9 +711,10 @@
/////UART/////
-/* UC8702 uart controller */
-#define S5L8702_UART_BASE 0x3cc00000
-#define S5L8702_UART_PORT_MAX 4
+/* s5l8702 UC870X HW: 1 UARTC, 4 ports */
+#define UARTC_BASE_ADDR 0x3CC00000
+#define UARTC_N_PORTS 4
+#define UARTC_PORT_OFFSET 0x4000
/////CLOCK GATES/////
@@ -737,7 +738,7 @@
#define CLOCKGATE_TIMER 37
#define CLOCKGATE_I2C1 38
#define CLOCKGATE_I2S0 39
-#define CLOCKGATE_UART 41
+#define CLOCKGATE_UARTC 41
#define CLOCKGATE_I2S1 42
#define CLOCKGATE_SPI1 43
#define CLOCKGATE_GPIO 44
diff --git a/firmware/target/arm/s5l8702/uc8702.h b/firmware/export/uc870x.h
index 36e4f8faa4..ad7168fe64 100644
--- a/firmware/target/arm/s5l8702/uc8702.h
+++ b/firmware/export/uc870x.h
@@ -18,32 +18,27 @@
* KIND, either express or implied.
*
****************************************************************************/
-#ifndef __UC8702_H__
-#define __UC8702_H__
+#ifndef __UC870X_H__
+#define __UC870X_H__
#include <stdint.h>
#include <stdbool.h>
+#include "config.h"
+#include "system.h"
+#include "uart-target.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
+ * UC870x: UART controller for s5l870x
+ *
+ * This UART is similar to the UART described in s5l8700 datasheet,
+ * (see also s3c2416 and s3c6400 datasheets). On s5l8701/2 the UC870x
+ * includes autobauding, and fine tunning for Tx/Rx on s5l8702.
*/
-#define UART_PORT_MAX 4
-#define UART_FIFO_SIZE 16
-
-#define UART_PORT_BASE(b,i) ((b) + 0x4000 * (i))
/*
- * controller registers
+ * Controller registers
*/
#define REG32_PTR_T volatile uint32_t *
@@ -58,10 +53,14 @@
#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 */
+#if CONFIG_CPU != S5L8700
#define UABRCNT(ba) (*((REG32_PTR_T)((ba) + 0x2c))) /* autobaud counter */
#define UABRSTAT(ba) (*((REG32_PTR_T)((ba) + 0x30))) /* autobaud status */
+#endif
+#if CONFIG_CPU == S5L8702
#define UBRCONTX(ba) (*((REG32_PTR_T)((ba) + 0x34))) /* Tx frame config */
#define UBRCONRX(ba) (*((REG32_PTR_T)((ba) + 0x38))) /* Rx frame config */
+#endif
/* ULCON register */
#define ULCON_DATA_BITS_MASK 0x3
@@ -107,13 +106,31 @@
#define UCON_CLKSEL_PCLK 0 /* internal */
#define UCON_CLKSEL_ECLK 1 /* external */
+#if CONFIG_CPU == S5L8702
#define UCON_RX_TOUT_INT_BIT (1 << 11) /* Rx timeout INT enable */
+#endif
#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) */
+#if CONFIG_CPU != S5L8700
#define UCON_AUTOBR_INT_BIT (1 << 16) /* autobauding INT enable */
#define UCON_AUTOBR_START_BIT (1 << 17) /* autobauding start/stop */
+#endif
+
+#if CONFIG_CPU == S5L8701
+/* WTF! ABR bits are swapped on reads, so don't forget to
+ always use this workaround to read the UCON register. */
+static inline uint32_t _UCON_RD(uint32_t ba)
+{
+ uint32_t ucon = UCON(ba);
+ return ((ucon & 0xffff) |
+ ((ucon & UCON_AUTOBR_INT_BIT) << 1) |
+ ((ucon & UCON_AUTOBR_START_BIT) >> 1));
+}
+#else
+#define _UCON_RD(ba) UCON(ba)
+#endif
/* UFCON register */
#define UFCON_FIFO_ENABLE_BIT (1 << 0)
@@ -142,12 +159,16 @@
#define UTRSTAT_RXBUF_RDY_BIT (1 << 0)
#define UTRSTAT_TXBUF_EMPTY_BIT (1 << 1)
#define UTRSTAT_TX_EMPTY_BIT (1 << 2)
+#if CONFIG_CPU == S5L8702
#define UTRSTAT_RX_TOUT_INT_BIT (1 << 3) /* Rx timeout INT status */
+#endif
#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_MODEM_INT_BIT (1 << 7) /* modem INT status */
+#if CONFIG_CPU != S5L8700
#define UTRSTAT_AUTOBR_INT_BIT (1 << 8) /* autobauding INT status */
+#endif
/* UERSTAT register */
#define UERSTAT_OVERRUN_BIT (1 << 0)
@@ -170,6 +191,8 @@
#define UMSTAT_CTS_ACTIVE_BIT (1 << 0)
#define UMSTAT_CTS_DELTA_BIT (1 << 4)
+
+#if CONFIG_CPU == S5L8702
/* Bitrate:
*
* Master UCLK clock is divided by 16 to serialize data, UBRDIV is
@@ -192,7 +215,10 @@
#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 */
+#endif /* CONFIG_CPU == S5L8702 */
+
+#if CONFIG_CPU != S5L8700
/* Autobauding:
*
* Initial UABRSTAT is NOT_INIT, it goes to READY when either of
@@ -223,6 +249,13 @@
#define UABRSTAT_STATUS_NOT_INIT 0 /* initial status */
#define UABRSTAT_STATUS_READY 1 /* machine is ready */
#define UABRSTAT_STATUS_COUNTING 2 /* count in progress */
+#endif /* CONFIG_CPU != S5L8700 */
+
+
+/*
+ * other HW definitions
+ */
+#define UART_FIFO_SIZE 16
/*
@@ -231,58 +264,70 @@
struct uartc
{
/* static configuration */
- const uint32_t baddr;
- /* private */
- struct uartc_port *port_l[UART_PORT_MAX];
+ uint8_t id;
+ uint8_t n_ports;
+ uint16_t port_off;
+ uint32_t baddr;
+ struct uartc_port **port_l;
};
struct uartc_port
{
/* static configuration */
- struct uartc * const uartc;
+ const 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 */
+#if CONFIG_CPU != S5L8700
void (* const rx_cb) (int len, char *data, char *err, uint32_t abr_cnt);
+#else
+ void (* const rx_cb) (int len, char *data, char *err);
+#endif
/* 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 */
+#if CONFIG_CPU != S5L8700
+ bool abr_aborted;
+#endif
-#ifdef UC8702_DEBUG
+#ifdef UC870X_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;
+#if CONFIG_CPU != S5L8700
+ /* autobauding */
uint32_t n_abnormal0;
uint32_t n_abnormal1;
#endif
+#endif
};
/*
- * uc8702 low level API
+ * uc870x low level API
*/
/* Initialization */
-void uartc_open(struct uartc* uartc);
-void uartc_close(struct uartc* uartc);
+void uartc_open(const struct uartc* uartc);
+void uartc_close(const 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_config(struct uartc_port *port,
+ uint8_t data_bits, uint8_t parity, uint8_t stop_bits);
+void uartc_port_set_bitrate_raw(struct uartc_port *port, uint32_t brdata);
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);
@@ -297,14 +342,22 @@ 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);
+#if CONFIG_CPU != S5L8700
/* Autobauding */
void uartc_port_abr_start(struct uartc_port *port);
void uartc_port_abr_stop(struct uartc_port *port);
+#endif
/* ISR */
-void uartc_callback(struct uartc *uartc, int dev);
+void uartc_callback(const struct uartc *uartc, int port_id);
-#ifdef UC8702_DEBUG
+/* Debug */
+#ifdef UC870X_DEBUG
+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);
+
+#if CONFIG_CPU != S5L8700
enum {
ABR_INFO_ST_IDLE,
ABR_INFO_ST_LAUNCHED,
@@ -312,10 +365,8 @@ enum {
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);
+int uartc_port_get_abr_info(struct uartc_port *port, uint32_t *abr_cnt);
#endif
-#endif /* __UC8702_H__ */
+#endif /* UC870X_DEBUG */
+
+#endif /* __UC870X_H__ */
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.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 */