// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Maxime Coquelin 2015
* Copyright (C) STMicroelectronics SA 2017
* Authors: Maxime Coquelin <mcoquelin.stm32@gmail.com>
* Gerald Baeza <gerald.baeza@st.com>
*
* Inspired by st-asc.c from STMicroelectronics (c)
*/
#if defined(CONFIG_SERIAL_STM32_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/dma-direction.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/spinlock.h>
#include <linux/sysrq.h>
#include <linux/tty_flip.h>
#include <linux/tty.h>
#include "stm32-usart.h"
static void stm32_stop_tx(struct uart_port *port);
static void stm32_transmit_chars(struct uart_port *port);
static inline struct stm32_port *to_stm32_port(struct uart_port *port)
{
return container_of(port, struct stm32_port, port);
}
static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits)
{
u32 val;
val = readl_relaxed(port->membase + reg);
val |= bits;
writel_relaxed(val, port->membase + reg);
}
static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits)
{
u32 val;
val = readl_relaxed(port->membase + reg);
val &= ~bits;
writel_relaxed(val, port->membase + reg);
}
static void stm32_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE,
u32 delay_DDE, u32 baud)
{
u32 rs485_deat_dedt;
u32 rs485_deat_dedt_max = (USART_CR1_DEAT_MASK >> USART_CR1_DEAT_SHIFT);
bool over8;
*cr3 |= USART_CR3_DEM;
over8 = *cr1 & USART_CR1_OVER8;
if (over8)
rs485_deat_dedt = delay_ADE * baud * 8;
else
rs485_deat_dedt = delay_ADE * baud * 16;
rs485_deat_dedt = DIV_ROUND_CLOSEST(rs485_deat_dedt, 1000);
rs485_deat_dedt = rs485_deat_dedt > rs485_deat_dedt_max ?
rs485_deat_dedt_max : rs485_deat_dedt;
rs485_deat_dedt = (rs485_deat_dedt << USART_CR1_DEAT_SHIFT) &
USART_CR1_DEAT_MASK;
*cr1 |= rs485_deat_dedt;
if (over8)
rs485_deat_dedt = delay_DDE *