forked from Minki/linux
serial: stm32: add FIFO threshold configuration
Add the support for two optional DT properties, to configure RX and TX FIFO thresholds: - rx-threshold - tx-threshold This replaces hard-coded 8 bytes threshold. Keep 8 as the default value if not specified, for backward compatibility. Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com> Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com> Changes in v2: Change added properties naming as proposed by Rob Herring. Link: https://lore.kernel.org/r/20210413174015.23011-5-erwan.leray@foss.st.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
31db3ce05b
commit
2aa1bbb21f
@ -306,7 +306,7 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
|
||||
* Enables TX FIFO threashold irq when FIFO is enabled,
|
||||
* or TX empty irq when FIFO is disabled
|
||||
*/
|
||||
if (stm32_port->fifoen)
|
||||
if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
|
||||
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_TXFTIE);
|
||||
else
|
||||
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
|
||||
@ -317,7 +317,7 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
|
||||
if (stm32_port->fifoen)
|
||||
if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
|
||||
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE);
|
||||
else
|
||||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
|
||||
@ -796,9 +796,10 @@ static void stm32_usart_set_termios(struct uart_port *port,
|
||||
cr3 = readl_relaxed(port->membase + ofs->cr3);
|
||||
cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTIE;
|
||||
if (stm32_port->fifoen) {
|
||||
cr3 &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK);
|
||||
cr3 |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT;
|
||||
cr3 |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT;
|
||||
if (stm32_port->txftcfg >= 0)
|
||||
cr3 |= stm32_port->txftcfg << USART_CR3_TXFTCFG_SHIFT;
|
||||
if (stm32_port->rxftcfg >= 0)
|
||||
cr3 |= stm32_port->rxftcfg << USART_CR3_RXFTCFG_SHIFT;
|
||||
}
|
||||
|
||||
if (cflag & CSTOPB)
|
||||
@ -828,7 +829,8 @@ static void stm32_usart_set_termios(struct uart_port *port,
|
||||
, bits);
|
||||
|
||||
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
|
||||
stm32_port->fifoen)) {
|
||||
(stm32_port->fifoen &&
|
||||
stm32_port->rxftcfg >= 0))) {
|
||||
if (cflag & CSTOPB)
|
||||
bits = bits + 3; /* 1 start bit + 2 stop bits */
|
||||
else
|
||||
@ -1016,6 +1018,39 @@ static const struct uart_ops stm32_uart_ops = {
|
||||
.verify_port = stm32_usart_verify_port,
|
||||
};
|
||||
|
||||
/*
|
||||
* STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG)
|
||||
* Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case,
|
||||
* RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE.
|
||||
* So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1.
|
||||
*/
|
||||
static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 };
|
||||
|
||||
static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p,
|
||||
int *ftcfg)
|
||||
{
|
||||
u32 bytes, i;
|
||||
|
||||
/* DT option to get RX & TX FIFO threshold (default to 8 bytes) */
|
||||
if (of_property_read_u32(pdev->dev.of_node, p, &bytes))
|
||||
bytes = 8;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++)
|
||||
if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes)
|
||||
break;
|
||||
if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg))
|
||||
i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s set to %d bytes\n", p,
|
||||
stm32h7_usart_fifo_thresh_cfg[i]);
|
||||
|
||||
/* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */
|
||||
if (i)
|
||||
*ftcfg = i - 1;
|
||||
else
|
||||
*ftcfg = -EINVAL;
|
||||
}
|
||||
|
||||
static void stm32_usart_deinit_port(struct stm32_port *stm32port)
|
||||
{
|
||||
clk_disable_unprepare(stm32port->clk);
|
||||
@ -1052,6 +1087,12 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
|
||||
of_property_read_bool(pdev->dev.of_node, "rx-tx-swap");
|
||||
|
||||
stm32port->fifoen = stm32port->info->cfg.has_fifo;
|
||||
if (stm32port->fifoen) {
|
||||
stm32_usart_get_ftcfg(pdev, "rx-threshold",
|
||||
&stm32port->rxftcfg);
|
||||
stm32_usart_get_ftcfg(pdev, "tx-threshold",
|
||||
&stm32port->txftcfg);
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
port->membase = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -216,12 +216,6 @@ struct stm32_usart_info stm32h7_info = {
|
||||
#define USART_CR3_TXFTCFG_MASK GENMASK(31, 29) /* H7 */
|
||||
#define USART_CR3_TXFTCFG_SHIFT 29 /* H7 */
|
||||
|
||||
/* TX FIFO threashold set to half of its depth */
|
||||
#define USART_CR3_TXFTCFG_HALF 0x2
|
||||
|
||||
/* RX FIFO threashold set to half of its depth */
|
||||
#define USART_CR3_RXFTCFG_HALF 0x2
|
||||
|
||||
/* USART_GTPR */
|
||||
#define USART_GTPR_PSC_MASK GENMASK(7, 0)
|
||||
#define USART_GTPR_GT_MASK GENMASK(15, 8)
|
||||
@ -273,6 +267,8 @@ struct stm32_port {
|
||||
bool hw_flow_control;
|
||||
bool swap; /* swap RX & TX pins */
|
||||
bool fifoen;
|
||||
int rxftcfg; /* RX FIFO threshold CFG */
|
||||
int txftcfg; /* TX FIFO threshold CFG */
|
||||
bool wakeup_src;
|
||||
int rdr_mask; /* receive data register mask */
|
||||
struct mctrl_gpios *gpios; /* modem control gpios */
|
||||
|
Loading…
Reference in New Issue
Block a user