From: Jacky Huang <ychuang570808@gmail.com>
To: Jiri Slaby <jirislaby@kernel.org>,
robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org,
lee@kernel.org, mturquette@baylibre.com, sboyd@kernel.org,
p.zabel@pengutronix.de, gregkh@linuxfoundation.org
Cc: devicetree@vger.kernel.org, linux-clk@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
schung@nuvoton.com, Jacky Huang <ychuang3@nuvoton.com>
Subject: Re: [PATCH 14/15] tty: serial: Add Nuvoton ma35d1 serial driver support
Date: Thu, 16 Mar 2023 21:28:02 +0800 [thread overview]
Message-ID: <d7291026-eab4-89e6-98d5-d7cfbaab18de@gmail.com> (raw)
In-Reply-To: <18250d8b-77b6-4887-44b4-a60bf1211a31@kernel.org>
Dear Jiri,
Thanks for your review.
I will create #define constant to replace every occurrence of magics or
hard coding number.
For every occurrence of "struct uart_ma35d1_port *up = (struct
uart_ma35d1_port *)port; ",
it will be replaced with to_ma35d1_uart_port() .
On 2023/3/15 下午 06:13, Jiri Slaby wrote:
> On 15. 03. 23, 8:29, Jacky Huang wrote:
>> --- /dev/null
>> +++ b/drivers/tty/serial/ma35d1_serial.c
>> @@ -0,0 +1,842 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * MA35D1 serial driver
>> + * Copyright (C) 2023 Nuvoton Technology Corp.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/moduleparam.h>
>
> What parameters does this module have?
+#include <linux/ioport.h>
>> +#include <linux/init.h>
>> +#include <linux/console.h>
>> +#include <linux/sysrq.h>
>> +#include <linux/delay.h>
>
> What do you use from delay.h?
>
>> +#include <linux/platform_device.h>
>> +#include <linux/tty.h>
>> +#include <linux/tty_flip.h>
>> +#include <linux/clk.h>
>> +#include <linux/serial_reg.h>
>> +#include <linux/serial_core.h>
>> +#include <linux/serial.h>
>> +#include <linux/nmi.h>
>
> nmi.h?
>
> Please clean up all of the includes.
>
moduleparam.h, delay.h, and nmi.h are not used.
I will test and remove all unused #include.
>> +#include <linux/mutex.h>
>> +#include <linux/slab.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/of.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/io.h>
>> +#include <asm/irq.h>
>> +#include <asm/serial.h>
>> +#include "ma35d1_serial.h"
>> +
>> +#define UART_NR 17
>> +
>> +static struct uart_driver ma35d1serial_reg;
>> +struct clk *clk;
>> +
>> +struct uart_ma35d1_port {
>> + struct uart_port port;
>> + u16 capabilities; /* port capabilities */
>> + u8 ier;
>> + u8 lcr;
>> + u8 mcr;
>> + u8 mcr_mask; /* mask of user bits */
>> + u8 mcr_force; /* mask of forced bits */
>
> Where are all those used?
>
I will remove the unused structure members in the next version.
>> + struct serial_rs485 rs485; /* rs485 settings */
>> + u32 baud_rate;
>
> And this one.
>
It's not used. I will remove it.
>> + int rx_count;
>> + u32 console_baud_rate;
>> + u32 console_line;
>> + u32 console_int;
>> +};
>> +
>> +static struct device_node *ma35d1serial_uart_nodes[UART_NR];
>> +static struct uart_ma35d1_port ma35d1serial_ports[UART_NR] = { 0 };
>
>> +static void __stop_tx(struct uart_ma35d1_port *p);
>
> What for?
This function is used to disable TX FIFO empty interrupt.
naming issue?
>
>> +static void transmit_chars(struct uart_ma35d1_port *up);
>> +
>> +static struct uart_ma35d1_port *to_ma35d1_uart_port(struct uart_port
>> *uart)
>> +{
>> + return container_of(uart, struct uart_ma35d1_port, port);
>> +}
>> +
>> +static u32 serial_in(struct uart_ma35d1_port *p, int offset)
>
> Q: int? A: No.
will modify "int offset" to "u32 offset"
>
>> +{
>> + return __raw_readl(p->port.membase + offset);
>> +}
>> +
>> +static void serial_out(struct uart_ma35d1_port *p, int offset, int
>> value)
>
> No ints here, please.
will modify offset and value data type to u32
>
>> +{
>> + __raw_writel(value, p->port.membase + offset);
>> +}
>> +
>> +static void __stop_tx(struct uart_ma35d1_port *p)
>> +{
>> + u32 ier;
>> +
>> + ier = serial_in(p, UART_REG_IER);
>> + if (ier & THRE_IEN)
>> + serial_out(p, UART_REG_IER, ier & ~THRE_IEN);
>> +}
>> +
>> +static void ma35d1serial_stop_tx(struct uart_port *port)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>
> Despite you have to_ma35d1_uart_port(), you do this?
>
You're right. I will use to_ma35d1_uart_port() to replace it.
>> +
>> + __stop_tx(up);
>> +}
>> +
>> +static void ma35d1serial_start_tx(struct uart_port *port)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>> + u32 ier;
>> + struct circ_buf *xmit = &up->port.state->xmit;
>> +
>> + ier = serial_in(up, UART_REG_IER);
>> + serial_out(up, UART_REG_IER, ier & ~THRE_IEN);
>> + if (uart_circ_chars_pending(xmit) <
>> + (16 - ((serial_in(up, UART_REG_FSR) >> 16) & 0x3F)))
>
> You look like you need a helper for this computation (hint:
> GENMASK()). What do those magic constants mean?
>
I will add #define macro for the bit mask..
>> + transmit_chars(up);
>> + serial_out(up, UART_REG_IER, ier | THRE_IEN);
>> +}
>> +
>> +static void ma35d1serial_stop_rx(struct uart_port *port)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>
> Bah. Nah.
>> +
>> + serial_out(up, UART_REG_IER, serial_in(up, UART_REG_IER) &
>> ~RDA_IEN);
>> +}
>> +
>> +static void
>> +receive_chars(struct uart_ma35d1_port *up)
>> +{
>> + u8 ch;
>> + u32 fsr;
>> + u32 isr;
>> + u32 dcnt;
>> + char flag;
>
> flag is u8 too. And a reverse xmas tree, please. Actually, you can put
> all those u32 to a single line.
>
OK, I will fix it.
>> +
>> + isr = serial_in(up, UART_REG_ISR);
>> + fsr = serial_in(up, UART_REG_FSR);
>> +
>> + while (!(fsr & RX_EMPTY)) {
>> + flag = TTY_NORMAL;
>> + up->port.icount.rx++;
>> +
>> + if (unlikely(fsr & (BIF | FEF | PEF | RX_OVER_IF))) {
>> + if (fsr & BIF) {
>> + serial_out(up, UART_REG_FSR, BIF);
>> + up->port.icount.brk++;
>> + if (uart_handle_break(&up->port))
>> + continue;
>> + }
>> + if (fsr & FEF) {
>> + serial_out(up, UART_REG_FSR, FEF);
>> + up->port.icount.frame++;
>> + }
>> + if (fsr & PEF) {
>> + serial_out(up, UART_REG_FSR, PEF);
>> + up->port.icount.parity++;
>> + }
>> + if (fsr & RX_OVER_IF) {
>> + serial_out(up, UART_REG_FSR, RX_OVER_IF);
>> + up->port.icount.overrun++;
>> + }
>> + if (fsr & BIF)
>> + flag = TTY_BREAK;
>> + if (fsr & PEF)
>> + flag = TTY_PARITY;
>> + if (fsr & FEF)
>> + flag = TTY_FRAME;
>> + }
>> + ch = (u8)serial_in(up, UART_REG_RBR);
>> + if (uart_handle_sysrq_char(&up->port, ch))
>> + continue;
>> +
>> + uart_insert_char(&up->port, fsr, RX_OVER_IF, ch, flag);
>
> No lock needed?
>
I will wrap it with spin_lock and spin_unlock.
>> + up->rx_count++;
>> + dcnt = (serial_in(up, UART_REG_FSR) >> 8) & 0x3f;
>
> More magic constants. No.
>
>> + if (up->rx_count > 1023) {
>> + spin_lock(&up->port.lock);
>> + tty_flip_buffer_push(&up->port.state->port);
>> + spin_unlock(&up->port.lock);
>> + up->rx_count = 0;
>> + if ((isr & RXTO_IF) && (dcnt == 0))
>> + goto tout_end;
>> + }
>> + if (isr & RDA_IF) {
>> + if (dcnt == 1)
>> + return;
>> + }
>> + fsr = serial_in(up, UART_REG_FSR);
>> + }
>> + spin_lock(&up->port.lock);
>> + tty_flip_buffer_push(&up->port.state->port);
>> + spin_unlock(&up->port.lock);
>> +tout_end:
>> + up->rx_count = 0;
>> +}
>> +
>> +static void transmit_chars(struct uart_ma35d1_port *up)
>
> Why this cannot use uart_port_tx()?
OK, I will rename it as uart_port_tx().
>
>> +{
>> + struct circ_buf *xmit = &up->port.state->xmit;
>> + int count = 16 - ((serial_in(up, UART_REG_FSR) >> 16) & 0xF);
>> +
>> + if (serial_in(up, UART_REG_FSR) & TX_FULL)
>> + count = 0;
>> + if (up->port.x_char) {
>> + serial_out(up, UART_REG_THR, up->port.x_char);
>> + up->port.icount.tx++;
>> + up->port.x_char = 0;
>> + return;
>> + }
>> + if (uart_tx_stopped(&up->port)) {
>> + ma35d1serial_stop_tx(&up->port);
>> + return;
>> + }
>> + if (uart_circ_empty(xmit)) {
>> + __stop_tx(up);
>> + return;
>> + }
>> + while (count > 0) {
>> + serial_out(up, UART_REG_THR, xmit->buf[xmit->tail]);
>> + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
>> + up->port.icount.tx++;
>> + count--;
>> + if (uart_circ_empty(xmit))
>> + break;
>> + }
>> + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
>> + uart_write_wakeup(&up->port);
>> + if (uart_circ_empty(xmit))
>> + __stop_tx(up);
>> +}
>> +
>> +static irqreturn_t ma35d1serial_interrupt(int irq, void *dev_id)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)dev_id;
>> + u32 isr, fsr;
>> +
>> + isr = serial_in(up, UART_REG_ISR);
>> + fsr = serial_in(up, UART_REG_FSR);
>> + if (isr & (RDA_IF | RXTO_IF))
>> + receive_chars(up);
>> + if (isr & THRE_INT)
>> + transmit_chars(up);
>> + if (fsr & (BIF | FEF | PEF | RX_OVER_IF | TX_OVER_IF))
>> + serial_out(up, UART_REG_FSR,
>> + (BIF | FEF | PEF | RX_OVER_IF | TX_OVER_IF));
>> +
>> + return IRQ_HANDLED;
>
> You give no way for OS to disable the irq when the HW goes crazy. I.e.
> you should return IRQ_HANDLED only when you really handled the irq.
>
>> +}
> ...
>> +static u32 ma35d1serial_get_mctrl(struct uart_port *port)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>> + u32 status;
>> + u32 ret = 0;
>> +
>> + status = serial_in(up, UART_REG_MSR);
>> + if (!(status & 0x10))
>
> 0x10 is magic.
>
>> + ret |= TIOCM_CTS;
>> + return ret;
>> +}
>> +
>> +static void ma35d1serial_set_mctrl(struct uart_port *port, u32 mctrl)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>> + u32 mcr = 0;
>> + u32 ier = 0;
>> +
>> + if (mctrl & TIOCM_RTS) {
>> + /* set RTS high level trigger */
>> + mcr = serial_in(up, UART_REG_MCR);
>> + mcr |= 0x200;
>> + mcr &= ~(0x2);
>> + }
>> + if (up->mcr & UART_MCR_AFE) {
>> + /* set RTS high level trigger */
>> + mcr = serial_in(up, UART_REG_MCR);
>> + mcr |= 0x200;
>> + mcr &= ~(0x2);
>
> This is repeated. Parentheses are superfluous. And again, 0x200, 0x2
> are magic.
>
>> +
>> + /* enable CTS/RTS auto-flow control */
>> + serial_out(up, UART_REG_IER,
>> + (serial_in(up, UART_REG_IER) | (0x3000)));
>> +
>> + /* Set hardware flow control */
>> + up->port.flags |= UPF_HARD_FLOW;
>> + } else {
>> + /* disable CTS/RTS auto-flow control */
>> + ier = serial_in(up, UART_REG_IER);
>> + ier &= ~(0x3000);
>
> Detto.
>
>> + serial_out(up, UART_REG_IER, ier);
>> +
>> + /* un-set hardware flow control */
>> + up->port.flags &= ~UPF_HARD_FLOW;
>> + }
>> +
>> + /* set CTS high level trigger */
>> + serial_out(up, UART_REG_MSR, (serial_in(up, UART_REG_MSR) |
>> (0x100)));
>> + serial_out(up, UART_REG_MCR, mcr);
>> +}
> ...
>> +static int ma35d1serial_startup(struct uart_port *port)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>> + struct tty_struct *tty = port->state->port.tty;
>> + int retval;
>> +
>> + /* Reset FIFO */
>> + serial_out(up, UART_REG_FCR, TFR | RFR /* | RX_DIS */);
>
> So why not RX_DIS?
>
>> +
>> + /* Clear pending interrupts */
>> + serial_out(up, UART_REG_ISR, 0xFFFFFFFF);
>> +
>> + retval = request_irq(port->irq, ma35d1serial_interrupt, 0,
>> + tty ? tty->name : "ma35d1_serial", port);
>> + if (retval) {
>> + dev_err(up->port.dev, "request irq failed.\n");
>> + return retval;
>> + }
>> +
>> + /* Now, initialize the UART */
>> + /* FIFO trigger level 4 byte */
>> + /* RTS trigger level 8 bytes */
>> + serial_out(up, UART_REG_FCR,
>> + serial_in(up, UART_REG_FCR) | 0x10 | 0x20000);
>> + serial_out(up, UART_REG_LCR, 0x7); /* 8 bit */
>> + serial_out(up, UART_REG_TOR, 0x40);
>
> You know what.
>
>> + serial_out(up, UART_REG_IER,
>> + RTO_IEN | RDA_IEN | TIME_OUT_EN | BUFERR_IEN);
>> + return 0;
>> +}
>> +
>> +static void ma35d1serial_shutdown(struct uart_port *port)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>> +
>> + free_irq(port->irq, port);
>> +
>> + /* Disable interrupts from this port */
>> + serial_out(up, UART_REG_IER, 0);
>
> The two lines are switched, IMO. First disable HW, then let the ISR
> finish and free it.
You're right. I will fix it.
>
>> +}
>> +
>> +static u32 ma35d1serial_get_divisor(struct uart_port *port, u32 baud)
>> +{
>> + u32 quot;
>> +
>> + quot = (port->uartclk / baud) - 2;
>> + return quot;
>
> quot variable is completely superfluous.
remove quot
and
return (port->uartclk / baud) - 2;
>
>> +}
>> +
>> +static void ma35d1serial_set_termios(struct uart_port *port,
>> + struct ktermios *termios,
>> + const struct ktermios *old)
>> +{
>> + struct uart_ma35d1_port *up = (struct uart_ma35d1_port *)port;
>> + u32 lcr = 0;
>> + unsigned long flags;
>> + u32 baud, quot;
>> +
>> + switch (termios->c_cflag & CSIZE) {
>> + case CS5:
>> + lcr = 0;
>> + break;
>> + case CS6:
>> + lcr |= 1;
>> + break;
>> + case CS7:
>> + lcr |= 2;
>> + break;
>> + case CS8:
>> + default:
>> + lcr |= 3;
>> + break;
>> + }
>
> IOW:
> lcr = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag));
>
All registers in this uart controller are 32-bits.
lcr will finally be written to the register UART_REG_LCR.of
which bit[1:0] represents for UART word length.
00 - 5 bits
01 - 6 bits
10 - 7 bits
11 - 8bits
Instead, I will add
#define WLS_5 0x0
#define WLS_6 0x1
#define WLS_7 0x2
#define WLS_8 0x3
and replace lcr |= 1 with
lcr |= WLS_6;
>> +
>> + if (termios->c_cflag & CSTOPB)
>> + lcr |= NSB;
>> + if (termios->c_cflag & PARENB)
>> + lcr |= PBE;
>> + if (!(termios->c_cflag & PARODD))
>> + lcr |= EPE;
>> + if (termios->c_cflag & CMSPAR)
>> + lcr |= SPE;
>> +
>> + baud = uart_get_baud_rate(port, termios, old, port->uartclk /
>> 0xffff,
>> + port->uartclk / 11);
>> +
>> + quot = ma35d1serial_get_divisor(port, baud);
>> +
>> + /*
>> + * Ok, we're now changing the port state. Do it with
>> + * interrupts disabled.
>> + */
>> + spin_lock_irqsave(&up->port.lock, flags);
>> +
>> + up->port.read_status_mask = RX_OVER_IF;
>> + if (termios->c_iflag & INPCK)
>> + up->port.read_status_mask |= FEF | PEF;
>> + if (termios->c_iflag & (BRKINT | PARMRK))
>> + up->port.read_status_mask |= BIF;
>> +
>> + /*
>> + * Characteres to ignore
>> + */
>> + up->port.ignore_status_mask = 0;
>> + if (termios->c_iflag & IGNPAR)
>> + up->port.ignore_status_mask |= FEF | PEF;
>> + if (termios->c_iflag & IGNBRK) {
>> + up->port.ignore_status_mask |= BIF;
>> + /*
>> + * If we're ignoring parity and break indicators,
>> + * ignore overruns too (for real raw support).
>> + */
>> + if (termios->c_iflag & IGNPAR)
>> + up->port.ignore_status_mask |= RX_OVER_IF;
>> + }
>> + if (termios->c_cflag & CRTSCTS)
>> + up->mcr |= UART_MCR_AFE;
>> + else
>> + up->mcr &= ~UART_MCR_AFE;
>> +
>> + ma35d1serial_set_mctrl(&up->port, up->port.mctrl);
>> + serial_out(up, UART_REG_BAUD, quot | 0x30000000);
>> + serial_out(up, UART_REG_LCR, lcr);
>> + spin_unlock_irqrestore(&up->port.lock, flags);
>> +}
> ...
>> +static void ma35d1serial_config_port(struct uart_port *port, int flags)
>> +{
>> + int ret;
>> +
>> + /*
>> + * Find the region that we can probe for. This in turn
>> + * tells us whether we can probe for the type of port.
>> + */
>> + ret = ma35d1serial_request_port(port);
>> + if (ret < 0)
>> + return;
>
> ma35d1serial_request_port() does nothing. You can remove it altogether.
>
OK, I will remove it.
>> + port->type = PORT_MA35D1;
>> +}
>
>
>> +static int ma35d1serial_ioctl(struct uart_port *port, u32 cmd,
>> unsigned long arg)
>> +{
>> + switch (cmd) {
>> + default:
>> + return -ENOIOCTLCMD;
>> + }
>> + return 0;
>> +}
>
> Drop that completely.
>
OK.
>> +static void
>> +ma35d1serial_console_init_port(void)
>> +{
>> + int i = 0;
>> + struct device_node *np;
>> +
>> + for_each_matching_node(np, ma35d1_serial_of_match) {
>> + if (ma35d1serial_uart_nodes[i] == NULL) {
>> + ma35d1serial_uart_nodes[i] = np;
>> + i++;
>
> Unless the dt is broken, this is OK. But I would add a sanity check to i.
>
I will add
if (i == UART_NR)
break;
>> + }
>> + }
>> +}
> ...
>> +/*
>> + * Register a set of serial devices attached to a platform device.
>> + * The list is terminated with a zero flags entry, which means we
>> expect
>> + * all entries to have at least UPF_BOOT_AUTOCONF set.
>> + */
>> +static int ma35d1serial_probe(struct platform_device *pdev)
>> +{
>> + struct resource *res_mem;
>> + struct uart_ma35d1_port *up;
>> + int ret;
>> + struct clk *clk;
>> + int err;
>> +
>> + if (pdev->dev.of_node) {
>> + ret = of_alias_get_id(pdev->dev.of_node, "serial");
>> + if (ret < 0) {
>> + dev_err(&pdev->dev,
>> + "failed to get alias/pdev id, errno %d\n",
>> + ret);
>> + return ret;
>> + }
>> + }
>> + up = &ma35d1serial_ports[ret];
>> + up->port.line = ret;
>> + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (!res_mem)
>> + return -ENODEV;
>> +
>> + up->port.iobase = res_mem->start;
>> + up->port.membase = ioremap(up->port.iobase, 0x10000);
>> + up->port.ops = &ma35d1serial_ops;
>> +
>> + spin_lock_init(&up->port.lock);
>> +
>> + clk = of_clk_get(pdev->dev.of_node, 0);
>> + if (IS_ERR(clk)) {
>> + err = PTR_ERR(clk);
>> + dev_err(&pdev->dev, "failed to get core clk: %d\n", err);
>> + return -ENOENT;
>> + }
>> + err = clk_prepare_enable(clk);
>> + if (err)
>> + return -ENOENT;
>> +
>> + if (up->port.line != 0)
>> + up->port.uartclk = clk_get_rate(clk);
>> + up->port.irq = platform_get_irq(pdev, 0);
>> + up->port.dev = &pdev->dev;
>> + up->port.flags = UPF_BOOT_AUTOCONF;
>> + up->port.rs485_config = ma35d1serial_config_rs485;
>> + ret = uart_add_one_port(&ma35d1serial_reg, &up->port);
>
> What if this fails?
>
I will add return value check.
>> + platform_set_drvdata(pdev, up);
>> + return 0;
>> +}
>> +
>> +/*
>> + * Remove serial ports registered against a platform device.
>> + */
>> +static int ma35d1serial_remove(struct platform_device *dev)
>> +{
>> + int i;
>> + struct uart_port *port = platform_get_drvdata(dev);
>> +
>> + free_irq(port->irq, port);
>
> Hmm, this doesn't look right. You did that already, or?
>
>> + for (i = 0; i < UART_NR; i++) {
>> + struct uart_ma35d1_port *up = &ma35d1serial_ports[i];
>> +
>> + if (up->port.dev == &dev->dev)
>
> You did platform_set_drvdata(), so why all this?
>
static int ma35d1serial_remove(struct platform_device *dev)
{
struct uart_port *port = platform_get_drvdata(dev);
uart_remove_one_port(&ma35d1serial_reg, &up->port);
free_irq(port->irq, port);
return 0;
}
>> + uart_remove_one_port(&ma35d1serial_reg, &up->port);
>> + }
>> + return 0;
>> +}
>
Best Regards,
Jacky Huang
next prev parent reply other threads:[~2023-03-16 13:28 UTC|newest]
Thread overview: 89+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-15 7:28 [PATCH 00/15] Introduce Nuvoton ma35d1 SoC Jacky Huang
2023-03-15 7:28 ` [PATCH 01/15] arm64: Kconfig.platforms: Add config for Nuvoton MA35 platform Jacky Huang
2023-03-15 7:28 ` [PATCH 02/15] arm64: defconfig: Add Nuvoton MA35 family support Jacky Huang
2023-03-16 14:23 ` Arnd Bergmann
2023-03-17 9:05 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 03/15] mfd: Add the header file of Nuvoton ma35d1 system manager Jacky Huang
2023-03-16 13:30 ` Ilpo Järvinen
2023-03-17 6:51 ` Jacky Huang
2023-03-16 14:44 ` Arnd Bergmann
2023-03-17 9:28 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 04/15] dt-bindings: clock: nuvoton: add binding for ma35d1 clock controller Jacky Huang
2023-03-16 7:31 ` Krzysztof Kozlowski
2023-03-16 13:35 ` Jacky Huang
2023-03-16 14:09 ` Krzysztof Kozlowski
2023-03-15 7:28 ` [PATCH 05/15] dt-bindings: reset: nuvoton: add binding for ma35d1 IP reset control Jacky Huang
2023-03-16 7:31 ` Krzysztof Kozlowski
2023-03-15 7:28 ` [PATCH 06/15] dt-bindings: mfd: syscon: Add nuvoton,ma35d1-sys compatible Jacky Huang
2023-03-16 7:31 ` Krzysztof Kozlowski
2023-03-17 1:03 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 07/15] dt-bindings: arm: Add initial bindings for Nuvoton platform Jacky Huang
2023-03-16 7:33 ` Krzysztof Kozlowski
2023-03-16 14:32 ` Arnd Bergmann
2023-03-18 1:26 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 08/15] dt-bindings: clock: Document ma35d1 clock controller bindings Jacky Huang
2023-03-15 21:59 ` Stephen Boyd
2023-03-16 3:24 ` Jacky Huang
2023-03-16 7:35 ` Krzysztof Kozlowski
2023-03-17 3:47 ` Jacky Huang
2023-03-17 9:13 ` Krzysztof Kozlowski
2023-03-17 9:52 ` Jacky Huang
2023-03-17 16:03 ` Krzysztof Kozlowski
2023-03-18 2:11 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 09/15] dt-bindings: reset: Document ma35d1 reset " Jacky Huang
2023-03-16 7:37 ` Krzysztof Kozlowski
2023-03-16 7:39 ` Krzysztof Kozlowski
2023-03-18 4:30 ` Jacky Huang
2023-03-19 11:05 ` Krzysztof Kozlowski
2023-03-20 6:26 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 10/15] dt-bindings: serial: Document ma35d1 uart " Jacky Huang
2023-03-16 7:40 ` Krzysztof Kozlowski
2023-03-17 4:18 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 11/15] arm64: dts: nuvoton: Add initial ma35d1 device tree Jacky Huang
2023-03-16 7:45 ` Krzysztof Kozlowski
2023-03-18 6:07 ` Jacky Huang
2023-03-19 11:06 ` Krzysztof Kozlowski
2023-03-19 14:16 ` Jacky Huang
2023-03-16 14:17 ` Arnd Bergmann
2023-03-16 16:44 ` Lee Jones
2023-03-18 13:32 ` Jacky Huang
2023-03-18 13:17 ` Jacky Huang
2023-03-18 14:04 ` Arnd Bergmann
2023-03-20 15:38 ` Jacky Huang
2023-03-15 7:28 ` [PATCH 12/15] clk: nuvoton: Add clock driver for ma35d1 clock controller Jacky Huang
2023-03-15 22:07 ` kernel test robot
2023-03-15 22:30 ` Stephen Boyd
2023-03-17 3:07 ` Jacky Huang
2023-03-16 7:51 ` Krzysztof Kozlowski
2023-03-19 2:55 ` Jacky Huang
2023-03-16 15:56 ` Ilpo Järvinen
2023-03-19 5:16 ` Jacky Huang
2023-03-20 10:31 ` Ilpo Järvinen
2023-03-21 15:03 ` Jacky Huang
2023-03-15 7:29 ` [PATCH 13/15] reset: Add Nuvoton ma35d1 reset driver support Jacky Huang
2023-03-16 7:51 ` Krzysztof Kozlowski
2023-03-17 7:13 ` Jacky Huang
2023-03-16 15:05 ` Ilpo Järvinen
2023-03-19 13:10 ` Jacky Huang
2023-03-15 7:29 ` [PATCH 14/15] tty: serial: Add Nuvoton ma35d1 serial " Jacky Huang
2023-03-15 7:37 ` Greg KH
2023-03-15 9:40 ` Jacky Huang
2023-03-15 9:48 ` kernel test robot
2023-03-15 10:13 ` Jiri Slaby
2023-03-16 13:28 ` Jacky Huang [this message]
2023-03-16 14:54 ` Ilpo Järvinen
2023-03-20 8:23 ` Jacky Huang
2023-03-20 10:04 ` Ilpo Järvinen
2023-03-21 14:23 ` Jacky Huang
2023-03-15 7:29 ` [PATCH 15/15] MAINTAINERS: Add entry for NUVOTON MA35 Jacky Huang
2023-03-16 14:38 ` Arnd Bergmann
2023-03-19 12:01 ` Jacky Huang
2023-03-19 12:36 ` Tomer Maimon
2023-03-16 7:41 ` [PATCH 00/15] Introduce Nuvoton ma35d1 SoC Krzysztof Kozlowski
2023-03-16 14:05 ` Arnd Bergmann
2023-03-17 6:30 ` Jacky Huang
2023-03-17 13:21 ` Arnd Bergmann
2023-03-17 16:06 ` Krzysztof Kozlowski
2023-03-18 3:07 ` Jacky Huang
2023-03-18 9:07 ` Arnd Bergmann
2023-03-18 3:00 ` Jacky Huang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d7291026-eab4-89e6-98d5-d7cfbaab18de@gmail.com \
--to=ychuang570808@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=jirislaby@kernel.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=lee@kernel.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=mturquette@baylibre.com \
--cc=p.zabel@pengutronix.de \
--cc=robh+dt@kernel.org \
--cc=sboyd@kernel.org \
--cc=schung@nuvoton.com \
--cc=ychuang3@nuvoton.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.