Update source to Armbian-dev-202610.A311Y3

This commit is contained in:
2026-11-11 08:50:43 +08:00
parent 3428a94f6b
commit f459ef6a9e
12514 changed files with 2264376 additions and 468481 deletions
@@ -87,6 +87,9 @@ static void meson_uart_enable_tx_engine(struct uart_port *port)
{
u32 val;
if (!port->membase)
return;
val = readl_relaxed(port->membase + AML_UART_CONTROL);
val |= AML_UART_TX_EN;
writel_relaxed(val, port->membase + AML_UART_CONTROL);
@@ -110,10 +113,13 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
bool locked = true;
u32 val, tmp;
if (!port->membase)
return;
if (oops_in_progress)
locked = spin_trylock_irqsave(&port->lock, flags);
locked = uart_port_trylock_irqsave(port, &flags);
else
spin_lock_irqsave(&port->lock, flags);
uart_port_lock_irqsave(port, &flags);
val = readl_relaxed(port->membase + AML_UART_CONTROL);
tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
@@ -123,7 +129,7 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
writel_relaxed(val, port->membase + AML_UART_CONTROL);
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
uart_port_unlock_irqrestore(port, flags);
}
static void meson_serial_early_console_write(struct console *co,
@@ -90,10 +90,8 @@ static unsigned int xtal_tick_en;
struct meson_uart_port {
struct uart_port port;
spinlock_t wr_lock; /* protect write */
unsigned long baud;
struct pinctrl *p;
unsigned long for_bt;
};
static struct meson_uart_port *meson_ports[AML_UART_PORT_MAX];
@@ -113,6 +111,9 @@ static unsigned int meson_uart_tx_empty(struct uart_port *port)
{
u32 val;
if (!port->membase)
return 0;
val = readl_relaxed(port->membase + AML_UART_STATUS);
return (val & AML_UART_TX_EMPTY) ? TIOCSER_TEMT : 0;
}
@@ -124,6 +125,9 @@ static void meson_uart_stop_tx(struct uart_port *port)
if (port->line == 0)
return;
if (!port->membase)
return;
val = readl_relaxed(port->membase + AML_UART_CONTROL);
val &= ~AML_UART_TX_EN;
writel_relaxed(val, port->membase + AML_UART_CONTROL);
@@ -133,6 +137,9 @@ static void meson_uart_stop_rx(struct uart_port *port)
{
u32 val;
if (!port->membase)
return;
val = readl_relaxed(port->membase + AML_UART_CONTROL);
val &= ~AML_UART_RX_EN;
writel_relaxed(val, port->membase + AML_UART_CONTROL);
@@ -146,6 +153,10 @@ static void meson_uart_shutdown(struct uart_port *port)
if (port->line == 0)
return;
/* uart_port_lock_irqsave() dereferences port->state, guard against NULL */
if (!port->state || !port->membase)
return;
uart_port_lock_irqsave(port, &flags);
val = readl_relaxed(port->membase + AML_UART_CONTROL);
@@ -159,12 +170,13 @@ static void meson_uart_shutdown(struct uart_port *port)
static void meson_uart_start_tx(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
struct meson_uart_port *mup = to_meson_port(port);
struct tty_port *tport;
unsigned char ch;
unsigned long flags;
spin_lock_irqsave(&mup->wr_lock, flags);
if (!port->state || !port->membase)
return;
tport = &port->state->port;
while (!kfifo_is_empty(&tport->xmit_fifo)) {
if (readl_relaxed(port->membase + AML_UART_STATUS)
@@ -176,17 +188,19 @@ static void meson_uart_start_tx(struct uart_port *port)
writel_relaxed(ch, port->membase + AML_UART_WFIFO);
}
spin_unlock_irqrestore(&mup->wr_lock, flags);
}
static void meson_transmit_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
struct meson_uart_port *mup = to_meson_port(port);
struct tty_port *tport;
unsigned char ch;
int count = 256;
if (!port->state || !port->membase)
return;
tport = &port->state->port;
if (port->x_char) {
writel_relaxed(port->x_char, port->membase + AML_UART_WFIFO);
port->icount.tx++;
@@ -197,8 +211,6 @@ static void meson_transmit_chars(struct uart_port *port)
if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))
return;
spin_lock(&mup->wr_lock);
while (!kfifo_is_empty(&tport->xmit_fifo) && count-- > 0) {
if (readl_relaxed(port->membase + AML_UART_STATUS)
& AML_UART_TX_FULL)
@@ -210,8 +222,6 @@ static void meson_transmit_chars(struct uart_port *port)
writel_relaxed(ch, port->membase + AML_UART_WFIFO);
}
spin_unlock(&mup->wr_lock);
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port);
@@ -220,10 +230,15 @@ static void meson_transmit_chars(struct uart_port *port)
static void meson_receive_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
struct tty_port *tport;
char flag;
u32 status, ch, mode;
if (!port->state || !port->membase)
return;
tport = &port->state->port;
do {
flag = TTY_NORMAL;
port->icount.rx++;
@@ -283,6 +298,9 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
{
struct uart_port *port = (struct uart_port *)dev_id;
if (!port || !port->membase)
return IRQ_HANDLED;
uart_port_lock(port);
if (!(readl_relaxed(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY))
@@ -307,6 +325,9 @@ static int meson_uart_startup(struct uart_port *port)
int ret = 0;
unsigned long flags;
if (!port->membase)
return -EINVAL;
uart_port_lock_irqsave(port, &flags);
val = readl_relaxed(port->membase + AML_UART_CONTROL);
@@ -334,6 +355,9 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
struct meson_uart_port *mup = to_meson_port(port);
struct platform_device *pdev = to_platform_device(port->dev);
if (!port->membase)
return;
while (!(readl_relaxed(port->membase + AML_UART_STATUS) & AML_UART_TX_EMPTY))
cpu_relax();
@@ -386,6 +410,9 @@ static void meson_uart_set_termios(struct uart_port *port,
unsigned long flags;
u32 val;
if (!port->state || !port->membase || !port->dev)
return;
uart_port_lock_irqsave(port, &flags);
cflags = termios->c_cflag;
@@ -474,58 +501,46 @@ static int meson_uart_verify_port(struct uart_port *port,
static void meson_uart_release_port(struct uart_port *port)
{
if (port->flags & UPF_IOREMAP) {
devm_iounmap(port->dev, port->membase);
port->membase = NULL;
devm_release_mem_region(port->dev, port->mapbase, port->mapsize);
}
#ifdef CONFIG_SMP
static cpumask_t meson_irq_hint_mask;
static inline void meson_uart_set_irq_affinity(struct uart_port *port)
{
int cpu;
if (port->line == 1) {
cpumask_clear(&meson_irq_hint_mask);
for (cpu = 1; cpu < nr_cpu_ids; cpu++) {
if (cpu_online(cpu)) {
cpumask_set_cpu(cpu, &meson_irq_hint_mask);
irq_set_affinity_hint(port->irq, &meson_irq_hint_mask);
}
}
if (cpumask_empty(&meson_irq_hint_mask))
irq_set_affinity_hint(port->irq, NULL);
}
}
#else
static inline void meson_uart_set_irq_affinity(struct uart_port *port)
{
}
#endif
static int meson_uart_request_port(struct uart_port *port)
{
struct platform_device *pdev = to_platform_device(port->dev);
struct meson_uart_port *mup = to_meson_port(port);
struct resource *res;
int size, ret;
u32 val;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "cannot obtain I/O memory region");
return -ENODEV;
}
size = resource_size(res);
if (!devm_request_mem_region(port->dev, port->mapbase, size, dev_name(port->dev))) {
dev_err(port->dev, "Memory region busy\n");
return -EBUSY;
}
if (port->flags & UPF_IOREMAP) {
port->membase = devm_ioremap(port->dev, port->mapbase, size);
if (!port->membase)
return -ENOMEM;
}
dev_dbg(&pdev->dev, "==uart%d reg addr = 0x%llx\n", port->line, (unsigned long long)port->mapbase);
val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
writel_relaxed(val, port->membase + AML_UART_MISC);
writel_relaxed(readl_relaxed(port->membase + AML_UART_CONTROL) | AML_UART_INV_RTS,
port->membase + AML_UART_CONTROL);
if (mup->for_bt)
ret = devm_request_threaded_irq(port->dev, port->irq, NULL,
meson_uart_interrupt,
IRQF_ONESHOT | IRQF_SHARED,
meson_uart_type(port), port);
else
ret = devm_request_irq(port->dev, port->irq, meson_uart_interrupt,
IRQF_SHARED, port->name, port);
return ret;
return 0;
}
static void meson_uart_config_port(struct uart_port *port, int flags)
@@ -547,6 +562,9 @@ static int meson_uart_poll_get_char(struct uart_port *port)
u32 c;
unsigned long flags;
if (!port->membase)
return NO_POLL_CHAR;
uart_port_lock_irqsave(port, &flags);
if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)
@@ -565,6 +583,9 @@ static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c)
u32 reg;
int ret;
if (!port->membase)
return;
uart_port_lock_irqsave(port, &flags);
/* Wait until FIFO is empty or timeout */
@@ -680,6 +701,9 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
else
uart_port_lock_irqsave(port, &flags);
if (!port->membase)
goto out;
val = readl_relaxed(port->membase + AML_UART_CONTROL);
tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
writel_relaxed(tmp, port->membase + AML_UART_CONTROL);
@@ -687,6 +711,7 @@ static void meson_serial_port_write(struct uart_port *port, const char *s,
uart_console_write(port, s, count, meson_console_putchar);
writel_relaxed(val, port->membase + AML_UART_CONTROL);
out:
if (locked)
uart_port_unlock_irqrestore(port, flags);
}
@@ -774,6 +799,9 @@ static int meson_uart_freeze(struct device *dev)
pdev = to_platform_device(dev);
port = platform_get_drvdata(pdev);
if (!port || !port->membase)
return -EINVAL;
pinctrl_pm_select_sleep_state(dev);
val = readl_relaxed(port->membase + AML_UART_CONTROL);
@@ -814,6 +842,9 @@ static int meson_uart_restore(struct device *dev)
pdev = to_platform_device(dev);
port = platform_get_drvdata(pdev);
if (!port || !port->membase)
return -EINVAL;
pinctrl_pm_select_default_state(dev);
if (port->line == 0) {
@@ -893,13 +924,8 @@ static int meson_uart_probe(struct platform_device *pdev)
if (!mup)
return -ENOMEM;
spin_lock_init(&mup->wr_lock);
port = &mup->port;
prop = of_get_property(pdev->dev.of_node, "uart_for_bt", NULL);
if (prop)
mup->for_bt = of_read_ulong(prop, 1);
clk = devm_clk_get(&pdev->dev, "clk_gate");
if (IS_ERR(clk)) {
dev_dbg(&pdev->dev, "%s: clock gate not found\n", dev_name(&pdev->dev));
@@ -953,6 +979,15 @@ static int meson_uart_probe(struct platform_device *pdev)
/* return -1; */
}
if (!port->membase) {
port->membase = devm_ioremap_resource(&pdev->dev, res_mem);
if (IS_ERR(port->membase)) {
meson_ports[pdev->id] = NULL;
return PTR_ERR(port->membase);
}
port->flags &= ~UPF_IOREMAP;
}
prop = of_get_property(pdev->dev.of_node, "support-sysrq", NULL);
if (prop) {
support_sysrq = of_read_ulong(prop, 1);
@@ -960,9 +995,29 @@ static int meson_uart_probe(struct platform_device *pdev)
port->has_sysrq = 1;
}
ret = uart_add_one_port(&meson_uart_driver, port);
if (ret)
#ifndef CONFIG_PREEMPT_RT
ret = devm_request_irq(&pdev->dev, port->irq, meson_uart_interrupt,
IRQF_SHARED, dev_name(&pdev->dev), port);
meson_uart_set_irq_affinity(port);
#else
ret = devm_request_threaded_irq(&pdev->dev, port->irq, NULL,
meson_uart_interrupt,
IRQF_ONESHOT | IRQF_SHARED,
dev_name(&pdev->dev), port);
#endif
if (ret) {
dev_err(&pdev->dev, "request irq %d failed: %d\n", port->irq, ret);
meson_ports[pdev->id] = NULL;
return ret;
}
ret = uart_add_one_port(&meson_uart_driver, port);
if (ret) {
dev_err(&pdev->dev, "uart_add_one_port failed: %d\n", ret);
meson_ports[pdev->id] = NULL;
devm_free_irq(&pdev->dev, port->irq, port);
}
return ret;
}
@@ -972,6 +1027,9 @@ static void meson_uart_remove(struct platform_device *pdev)
struct uart_port *port;
port = platform_get_drvdata(pdev);
if (!port)
return;
uart_remove_one_port(&meson_uart_driver, port);
meson_ports[pdev->id] = NULL;
}
@@ -997,6 +1055,8 @@ static int meson_uart_resume(struct platform_device *pdev)
writel_relaxed(val, port->membase + AML_UART_CONTROL);
}
meson_uart_set_irq_affinity(port);
return 0;
}