diff options
author | Vencislav Atanasov <user890104@freemyipod.org> | 2024-11-20 23:55:47 +0200 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2024-11-21 20:05:18 -0500 |
commit | 39f8101d603a76448a4f3d1786f7cf2d6d683606 (patch) | |
tree | 62ce2c49a536eb2683eca619d8af54299c72a9fd | |
parent | 1c7fddad5b7525b1d5edbd6d775ef529ef2a2c7c (diff) | |
download | rockbox-39f8101d60.tar.gz rockbox-39f8101d60.zip |
Enable UC870x "auto baud" and "fine tune" features based on the SoC capabilities
This makes it easier to add support for the remaining SoCs of the S5L87xx series.
Change-Id: I563aa55eed385b5f8e1c52edb866b08176ea116e
-rw-r--r-- | firmware/export/uc870x.h | 61 | ||||
-rw-r--r-- | firmware/target/arm/uc870x.c | 81 |
2 files changed, 79 insertions, 63 deletions
diff --git a/firmware/export/uc870x.h b/firmware/export/uc870x.h index ad7168fe64..7f0ac8169a 100644 --- a/firmware/export/uc870x.h +++ b/firmware/export/uc870x.h @@ -33,9 +33,16 @@ * 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. + * (see also s3c2416 and s3c6400 datasheets). On s5l8701+ the UC870x + * includes autobauding, and fine tuning for Tx/Rx speed on s5l8702+. */ +#if (CONFIG_CPU == S5L8701) +#define UART_CAP_AUTOBAUD +#elif (CONFIG_CPU == S5L8702) || (CONFIG_CPU == S5L8720) +#define UART_CAP_AUTOBAUD +#define UART_CAP_FINETUNE +#endif + /* * Controller registers @@ -53,11 +60,13 @@ #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 + +#ifdef UART_CAP_AUTOBAUD #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 + +#ifdef UART_CAP_FINETUNE #define UBRCONTX(ba) (*((REG32_PTR_T)((ba) + 0x34))) /* Tx frame config */ #define UBRCONRX(ba) (*((REG32_PTR_T)((ba) + 0x38))) /* Rx frame config */ #endif @@ -106,19 +115,20 @@ #define UCON_CLKSEL_PCLK 0 /* internal */ #define UCON_CLKSEL_ECLK 1 /* external */ -#if CONFIG_CPU == S5L8702 +#ifdef UART_CAP_FINETUNE #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 + +#ifdef UART_CAP_AUTOBAUD #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 +#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) @@ -130,7 +140,8 @@ static inline uint32_t _UCON_RD(uint32_t ba) } #else #define _UCON_RD(ba) UCON(ba) -#endif +#endif /* (CONFIG_CPU == S5L8701) */ +#endif /* UART_CAP_AUTOBAUD */ /* UFCON register */ #define UFCON_FIFO_ENABLE_BIT (1 << 0) @@ -159,14 +170,17 @@ static inline uint32_t _UCON_RD(uint32_t ba) #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 + +#ifdef UART_CAP_FINETUNE #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 */ -#if CONFIG_CPU != S5L8700 + +#ifdef UART_CAP_AUTOBAUD #define UTRSTAT_AUTOBR_INT_BIT (1 << 8) /* autobauding INT status */ #endif @@ -192,7 +206,7 @@ static inline uint32_t _UCON_RD(uint32_t ba) #define UMSTAT_CTS_DELTA_BIT (1 << 4) -#if CONFIG_CPU == S5L8702 +#ifdef UART_CAP_FINETUNE /* Bitrate: * * Master UCLK clock is divided by 16 to serialize data, UBRDIV is @@ -215,10 +229,10 @@ static inline uint32_t _UCON_RD(uint32_t ba) #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 */ +#endif /* UART_CAP_FINETUNE */ -#if CONFIG_CPU != S5L8700 +#ifdef UART_CAP_AUTOBAUD /* Autobauding: * * Initial UABRSTAT is NOT_INIT, it goes to READY when either of @@ -249,7 +263,7 @@ static inline uint32_t _UCON_RD(uint32_t ba) #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 */ +#endif /* UART_CAP_AUTOBAUD */ /* @@ -281,7 +295,7 @@ struct uartc_port 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 +#ifdef UART_CAP_AUTOBAUD 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); @@ -292,7 +306,7 @@ struct uartc_port uint32_t utrstat_int_mask; 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 +#ifdef UART_CAP_AUTOBAUD bool abr_aborted; #endif @@ -303,12 +317,11 @@ struct uartc_port uint32_t n_parity_err; uint32_t n_frame_err; uint32_t n_break_detect; -#if CONFIG_CPU != S5L8700 - /* autobauding */ +#ifdef UART_CAP_AUTOBAUD uint32_t n_abnormal0; uint32_t n_abnormal1; -#endif -#endif +#endif /* UART_CAP_AUTOBAUD */ +#endif /* UC870X_DEBUG */ }; @@ -342,7 +355,7 @@ 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 +#ifdef UART_CAP_AUTOBAUD /* Autobauding */ void uartc_port_abr_start(struct uartc_port *port); void uartc_port_abr_stop(struct uartc_port *port); @@ -357,7 +370,7 @@ 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 +#ifdef UART_CAP_AUTOBAUD enum { ABR_INFO_ST_IDLE, ABR_INFO_ST_LAUNCHED, @@ -366,7 +379,7 @@ enum { }; int uartc_port_get_abr_info(struct uartc_port *port, uint32_t *abr_cnt); -#endif +#endif /* UART_CAP_AUTOBAUD */ #endif /* UC870X_DEBUG */ #endif /* __UC870X_H__ */ diff --git a/firmware/target/arm/uc870x.c b/firmware/target/arm/uc870x.c index 9537c15e1a..61a1cc41e0 100644 --- a/firmware/target/arm/uc870x.c +++ b/firmware/target/arm/uc870x.c @@ -32,26 +32,29 @@ * 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_ERR_INT_BIT | UTRSTAT_AUTOBR_INT_BIT) -#define UCON_RX_RELATED_INTS \ - (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) +/* Rx related INTs */ +#ifdef UART_CAP_AUTOBAUD +#define AUTOBAUD_UTRSTAT_INT UTRSTAT_AUTOBR_INT_BIT +#define AUTOBAUD_UCON_INT UCON_AUTOBR_INT_BIT +#else +#define AUTOBAUD_UTRSTAT_INT 0 +#define AUTOBAUD_UCON_INT 0 #endif +#ifdef UART_CAP_FINETUNE +#define FINETUNE_UTRSTAT_INT UTRSTAT_RX_TOUT_INT_BIT +#define FINETUNE_UCON_INT UCON_RX_TOUT_INT_BIT +#else +#define FINETUNE_UTRSTAT_INT 0 +#define FINETUNE_UCON_INT 0 +#endif + +#define UTRSTAT_RX_INTS (UTRSTAT_RX_INT_BIT | UTRSTAT_ERR_INT_BIT | \ + AUTOBAUD_UTRSTAT_INT | FINETUNE_UTRSTAT_INT) + +#define UCON_RX_INTS (UCON_RX_INT_BIT | UCON_ERR_INT_BIT | \ + AUTOBAUD_UCON_INT | FINETUNE_UCON_INT) + #define UART_PORT_BASE(u,i) (((u)->baddr) + (u)->port_off * (i)) /* Initialization */ @@ -68,7 +71,7 @@ static void uartc_reset_port_id(const struct uartc* uartc, int port_id) UFCON(baddr) = UFCON_RX_FIFO_RST_BIT | UFCON_TX_FIFO_RST_BIT; UTRSTAT(baddr) = ~0; /* clear all interrupts */ UBRDIV(baddr) = 0; -#if CONFIG_CPU == S5L8702 +#ifdef UART_CAP_FINETUNE UBRCONTX(baddr) = 0; UBRCONRX(baddr) = 0; #endif @@ -119,14 +122,14 @@ void uartc_port_open(struct uartc_port *port) UCON(baddr) = (UCON_MODE_DISABLED << UCON_RX_MODE_POS) | (UCON_MODE_DISABLED << UCON_TX_MODE_POS) | ((port->clksel & UCON_CLKSEL_MASK) << UCON_CLKSEL_POS) - | (port->rx_cb ? UCON_RX_RELATED_INTS|UCON_RX_TOUT_EN_BIT : 0) + | (port->rx_cb ? UCON_RX_INTS|UCON_RX_TOUT_EN_BIT : 0) | (port->tx_cb ? UCON_TX_INT_BIT : 0); /* init and register port struct */ port->baddr = baddr; - port->utrstat_int_mask = (port->rx_cb ? UTRSTAT_RX_RELATED_INTS : 0) + port->utrstat_int_mask = (port->rx_cb ? UTRSTAT_RX_INTS : 0) | (port->tx_cb ? UTRSTAT_TX_INT_BIT : 0); -#if CONFIG_CPU != S5L8700 +#ifdef UART_CAP_AUTOBAUD port->abr_aborted = 0; #endif uartc->port_l[port->id] = port; @@ -156,7 +159,7 @@ 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 +#ifdef UART_CAP_FINETUNE UBRCONRX(baddr) = brdata >> 8; UBRCONTX(baddr) = brdata >> 8; #endif @@ -174,7 +177,7 @@ void uartc_port_set_bitrate(struct uartc_port *port, unsigned int speed) uint32_t brdata = brdiv - 1; -#if CONFIG_CPU == S5L8702 +#ifdef UART_CAP_FINETUNE /* Fine adjust: * * Along the whole frame, insert/remove "jittered" bauds when needed @@ -210,7 +213,7 @@ void uartc_port_set_bitrate(struct uartc_port *port, unsigned int speed) } brdata |= (brcon << 8); -#endif /* CONFIG_CPU == S5L8702 */ +#endif /* UART_CAP_FINETUNE */ uartc_port_set_rawbr(port, brdata); } @@ -269,7 +272,7 @@ uint8_t uartc_port_read_byte(struct uartc_port *port) return uartc_port_rx_byte(port); } -#if CONFIG_CPU != S5L8700 +#ifdef UART_CAP_AUTOBAUD /* Autobauding */ static inline int uartc_port_abr_status(struct uartc_port *port) { @@ -300,7 +303,7 @@ void uartc_port_abr_stop(struct uartc_port *port) else UCON(port->baddr) = _UCON_RD(port->baddr) & ~UCON_AUTOBR_START_BIT; } -#endif /* CONFIG_CPU != S5L8700 */ +#endif /* UART_CAP_AUTOBAUD */ /* ISR */ void ICODE_ATTR uartc_callback(const struct uartc* uartc, int port_id) @@ -315,10 +318,10 @@ void ICODE_ATTR uartc_callback(const struct uartc* uartc, int port_id) this ISR will be processed in the next call */ UTRSTAT(baddr) = ints; - if (ints & UTRSTAT_RX_RELATED_INTS) + if (ints & UTRSTAT_RX_INTS) { int len = 0; -#if CONFIG_CPU != S5L8700 +#ifdef UART_CAP_AUTOBAUD uint32_t abr_cnt = 0; if (ints & UTRSTAT_AUTOBR_INT_BIT) @@ -335,8 +338,8 @@ void ICODE_ATTR uartc_callback(const struct uartc* uartc, int port_id) abr_cnt = UABRCNT(baddr); } - if (ints & (UTRSTAT_RX_RELATED_INTS ^ UTRSTAT_AUTOBR_INT_BIT)) -#endif /* CONFIG_CPU != S5L8700 */ + if (ints & (UTRSTAT_RX_INTS ^ UTRSTAT_AUTOBR_INT_BIT)) +#endif /* UART_CAP_AUTOBAUD */ { /* get FIFO count */ uint32_t ufstat = UFSTAT(baddr); @@ -355,11 +358,11 @@ void ICODE_ATTR uartc_callback(const struct uartc* uartc, int port_id) * 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 +#ifdef UART_CAP_AUTOBAUD /* 'abr_cnt' is zero when no ABR interrupt exists */ port->rx_cb(len, port->rx_data, port->rx_err, abr_cnt); +#else + port->rx_cb(len, port->rx_data, port->rx_err); #endif #ifdef UC870X_DEBUG @@ -394,7 +397,7 @@ void ICODE_ATTR uartc_callback(const struct uartc* uartc, int port_id) /*#define LOGF_ENABLE*/ #include "logf.h" -#if CONFIG_CPU == S5L8702 +#ifdef UART_CAP_FINETUNE 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); @@ -426,7 +429,7 @@ static int get_bitrate(int uclk, int brdiv, int brcon, int frame_len) return avg_speed; } -#endif /* CONFIG_CPU == S5L8702 */ +#endif /* UART_CAP_FINETUNE */ void uartc_port_get_line_info(struct uartc_port *port, int *tx_status, int *rx_status, @@ -446,7 +449,7 @@ void uartc_port_get_line_info(struct uartc_port *port, int parity = (ulcon >> ULCON_PARITY_POS) & ULCON_PARITY_MASK; uint32_t brdiv = UBRDIV(baddr) + 1; -#if CONFIG_CPU == S5L8702 +#ifdef UART_CAP_FINETUNE 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); @@ -471,7 +474,7 @@ void uartc_port_get_line_info(struct uartc_port *port, } } -#if CONFIG_CPU != S5L8700 +#ifdef UART_CAP_AUTOBAUD /* Autobauding */ int uartc_port_get_abr_info(struct uartc_port *port, uint32_t *abr_cnt) { @@ -502,5 +505,5 @@ int uartc_port_get_abr_info(struct uartc_port *port, uint32_t *abr_cnt) return status; } -#endif /* CONFIG_CPU != S5L8700 */ +#endif /* UART_CAP_AUTOBAUD */ #endif /* UC870X_DEBUG */ |