* Re: [PATCH v9 3/3] printk: fix double printing with earlycon
From: Petr Mladek @ 2017-06-06 14:31 UTC (permalink / raw)
To: Aleksey Makarov
Cc: Sergey Senozhatsky, Sabrina Dubroca, linux-serial, linux-kernel,
Sudeep Holla, Greg Kroah-Hartman, Peter Hurley, Jiri Slaby,
Robin Murphy, Steven Rostedt, Nair, Jayachandran,
Sergey Senozhatsky
In-Reply-To: <20170601120325.GA25497@pathway.suse.cz>
On Thu 2017-06-01 14:03:25, Petr Mladek wrote:
> On Fri 2017-05-26 12:37:12, Aleksey Makarov wrote:
> > The console_cmdline array is the place where we add descriptions
> > of consoles that should receive log output. ACPI SPCR specifies exactly
> > that information, and I believe it should go to that array.
>
> Are consoles defined by earlycon= command line parameter
> added to console_cmdline? I do not see this anywhere in
> the following functions:
>
> + param_setup_earlycon()
> + setup_earlycon()
> + register_earlycon()
> + early_init_dt_scan_chosen_stdout()
> + of_setup_earlycon()
>
> IMHO, the main question is whether the console defined by
> ACPI SPCR is early or normal one.
The answer is that it depends. The console defined by ACPI
SPCR is early when just 'earlycon' is defined on the command
line. See param_setup_earlycon() and the use of
earlycon_init_is_deferred. Otherwise, it is supposed to
be a normal console.
We need to call add_preferred_console() in parse_spcr()
to allow using the console as a normal one.
We must also work correctly when the user explicitly defines
the console on the command line, using another alias.
As a result, we could not easily prevent having two matching consoles
in console_cmdline list. And as long as the last mentioned console
has the special status (preferred_console, CON_CONSDEV), it would
make sense to try matching the preferred console first.
Sadly, it causes the change of the behavior of ttyS0 and ttyS1.
Now, systemd seems to handle the console= parameters as well.
According to http://0pointer.de/blog/projects/serial-console.html,
systemd instantiates one serial-getty@.service on the preferred
(last mentioned) console.
This might be a reason to define both console=ttyS0 console=ttyS1
on the command line. People might actually want to get the logs
and the login prompt on different console.
Well, it is a bug that kernel shows the messages only on one
console.
There is one more thing that I found. Early consoles are forcefully
removed in a late_initcall(printk_late_init). It happens when they
use a code that is discarded after all initcalls finishes.
This has two effects.
First, boot consoles are removed even when the preferred one
is not registered. This explains why we need to call both
setup_earlycon() and add_preferred_console() in parse_spcr().
Second, the boot console might be removed before the normal/preferred
one is registered. For example, the normal one might be registered later
by a deferred probe call. As a result, the normal console might miss
that there was an early one, replays the entire log, and you
might see the beginning of the log twice.
All in all, I think that I have finally understood what
Aleksey wanted to say in his great summary, see
https://lkml.kernel.org/r/4e679bec-4804-9791-fc2b-0e96ad67d511@linaro.org
My proposed solution in parse_spcr() do not fly.
And I am still undecided about the Alexey's patch:
+ the patch makes some sense
+ but people might see the changed order as regressions;
there might be more users, especially because of systemd
+ IMHO, the patch fixed the duplicit output only partly;
it would not help when the normal console is registered
later
Best Regards,
Petr
^ permalink raw reply
* Re: [PATCH v4 16/28] tty: serial: owl: Implement console driver
From: Alan Cox @ 2017-06-06 13:34 UTC (permalink / raw)
To: Andreas Färber
Cc: support, 张天益, Greg Kroah-Hartman, 96boards,
linux-kernel, Thomas Liau, mp-cs, linux-serial, 刘炜,
Jiri Slaby, linux-arm-kernel, 张东风
In-Reply-To: <20170606005426.26446-17-afaerber@suse.de>
> +
> +static void owl_uart_set_termios(struct uart_port *port,
> + struct ktermios *termios,
> + struct ktermios *old)
> +{
> + struct owl_uart_port *owl_port = to_owl_uart_port(port);
> + unsigned int baud;
> + u32 ctl;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&port->lock, flags);
> +
> + /* We don't support modem control lines. */
> + termios->c_cflag &= ~(HUPCL | CMSPAR);
> + termios->c_cflag |= CLOCAL;
CLOCAL and HUPCL are software not hardware properties so are probably
best not forced (it'll confuse some apps if you do)
> +
> + /* We don't support BREAK character recognition. */
> + termios->c_iflag &= ~(IGNBRK | BRKINT);
Ditto these
You do clear CMSPAR which is right if not supported but then later on we
have:
> + if (termios->c_cflag & PARENB) {
> + if (termios->c_cflag & CMSPAR) {
> + if (termios->c_cflag & PARODD)
> + ctl |= OWL_UART_CTL_PRS_MARK;
> + else
> + ctl |= OWL_UART_CTL_PRS_SPACE;
> + } else if (termios->c_cflag & PARODD)
> + ctl |= OWL_UART_CTL_PRS_ODD;
> + else
> + ctl |= OWL_UART_CTL_PRS_EVEN;
> + } else
> + ctl |= OWL_UART_CTL_PRS_NONE;
Which seems to indicate you do support CMSPAR so shouldn't be clearing it.
> +
> + if (termios->c_cflag & CRTSCTS)
> + ctl |= OWL_UART_CTL_AFE;
> + else
> + ctl &= ~OWL_UART_CTL_AFE;
> +
> + owl_uart_write(port, ctl, OWL_UART_CTL);
> +
> + baud = uart_get_baud_rate(port, termios, old, 9600, 3200000);
> + owl_uart_change_baudrate(owl_port, baud);
You should re-encode the resulting baud rate into the termios
/* Don't rewrite B0 */
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
^ permalink raw reply
* Re: [PATCH 0/9] tty: drop broken alt-speed handling
From: Alan Cox @ 2017-06-06 11:29 UTC (permalink / raw)
To: Johan Hovold
Cc: Greg Kroah-Hartman, Jiri Slaby, Tony Luck, Fenghua Yu,
Samuel Ortiz, David S. Miller, linux-kernel, linux-usb,
linux-serial
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
On Tue, 6 Jun 2017 12:54:32 +0200
Johan Hovold <johan@kernel.org> wrote:
> Setting an alt-speed using TIOCSSERIAL and SPD flags has been deprecated
> since v2.1.69 and has been broken for all tty drivers but serial-core
> since v3.10 and commit 6865ff222cca ("TTY: do not warn about setting
> speed via SPD_*") without anyone noticing (for four years).
We have the ability to set the speed directly via termios so I doubt
anyone is using the remaining hacks either but I guess someone may. All
looks good to me.
Reviewed-by: Alan Cox <alan@linux.intel.com>
Alan
^ permalink raw reply
* Re: [PATCH 8/9] tty: ircomm: remove dead and broken ioctl code
From: Alan Cox @ 2017-06-06 11:27 UTC (permalink / raw)
To: Johan Hovold
Cc: Greg Kroah-Hartman, Jiri Slaby, Tony Luck, Fenghua Yu,
Samuel Ortiz, David S. Miller, linux-kernel, linux-usb,
linux-serial
In-Reply-To: <20170606105441.689-9-johan@kernel.org>
On Tue, 6 Jun 2017 12:54:40 +0200
Johan Hovold <johan@kernel.org> wrote:
> Remove three ifdefed and broken implementations of TIOCSSERIAL and
> TIOCGICOUNT, and parity handling in set_termios which had suffered
> severe bit rot.
I would be amazed if the IRDA code still works. It's not been tested
properly for years and it never followed the tty rules properly in the
first place - so this looks good, although moving IRDA into staging
and /dev/null would IMHO be far better.
IRDA is dead, and IR remotes are handled via completely different code.
Alan
^ permalink raw reply
* [PATCH 9/9] tty: drop unused alt_speed from tty_struct
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Drop the now unused alt_speed field from struct tty_struct.
Setting an alt_speed using the ASYNC_SPD flags has been deprecated since
v2.1.69, and has been broken for all tty drivers but serial-core since
v3.10 and commit 6865ff222cca ("TTY: do not warn about setting speed via
SPD_*") without anyone noticing.
Note that serial-core still supports changing speed using TIOCSSERIAL
and SPD flags (including "alt-speeds"), but also warns about it being
deprecated since pre-git.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
include/linux/tty.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/include/linux/tty.h b/include/linux/tty.h
index eccb4ec30a8a..585cf2b5ca94 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -316,7 +316,6 @@ struct tty_struct {
struct tty_struct *link;
struct fasync_struct *fasync;
- int alt_speed; /* For magic substitution of 38400 bps */
wait_queue_head_t write_wait;
wait_queue_head_t read_wait;
struct work_struct hangup_work;
--
2.13.0
^ permalink raw reply related
* [PATCH 8/9] tty: ircomm: remove dead and broken ioctl code
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Remove three ifdefed and broken implementations of TIOCSSERIAL and
TIOCGICOUNT, and parity handling in set_termios which had suffered
severe bit rot.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
net/irda/ircomm/ircomm_tty_ioctl.c | 107 +------------------------------------
1 file changed, 1 insertion(+), 106 deletions(-)
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index f18070118d05..171c3dee760e 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -97,33 +97,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self,
self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
}
tty_port_set_check_carrier(&self->port, ~cflag & CLOCAL);
-#if 0
- /*
- * Set up parity check flag
- */
-
- if (I_INPCK(self->tty))
- driver->read_status_mask |= LSR_FE | LSR_PE;
- if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
- driver->read_status_mask |= LSR_BI;
-
- /*
- * Characters to ignore
- */
- driver->ignore_status_mask = 0;
- if (I_IGNPAR(driver->tty))
- driver->ignore_status_mask |= LSR_PE | LSR_FE;
-
- if (I_IGNBRK(self->tty)) {
- self->ignore_status_mask |= LSR_BI;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (I_IGNPAR(self->tty))
- self->ignore_status_mask |= LSR_OE;
- }
-#endif
+
self->settings.data_format = cval;
ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
@@ -271,67 +245,6 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
struct serial_struct __user *new_info)
{
-#if 0
- struct serial_struct new_serial;
- struct ircomm_tty_cb old_state, *state;
-
- if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
- return -EFAULT;
-
-
- state = self
- old_state = *self;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((new_serial.baud_base != state->settings.data_rate) ||
- (new_serial.close_delay != state->close_delay) ||
- ((new_serial.flags & ~ASYNC_USR_MASK) !=
- (self->flags & ~ASYNC_USR_MASK)))
- return -EPERM;
- state->flags = ((state->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- self->flags = ((self->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- /* self->custom_divisor = new_serial.custom_divisor; */
- goto check_and_exit;
- }
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
-
- if (self->settings.data_rate != new_serial.baud_base) {
- self->settings.data_rate = new_serial.baud_base;
- ircomm_param_request(self, IRCOMM_DATA_RATE, TRUE);
- }
-
- self->close_delay = new_serial.close_delay * HZ/100;
- self->closing_wait = new_serial.closing_wait * HZ/100;
- /* self->custom_divisor = new_serial.custom_divisor; */
-
- self->flags = ((self->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
- self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- check_and_exit:
-
- if (tty_port_initialized(self)) {
- if (((old_state.flags & ASYNC_SPD_MASK) !=
- (self->flags & ASYNC_SPD_MASK)) ||
- (old_driver.custom_divisor != driver->custom_divisor)) {
- if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- driver->tty->alt_speed = 57600;
- if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- driver->tty->alt_speed = 115200;
- if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- driver->tty->alt_speed = 230400;
- if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- driver->tty->alt_speed = 460800;
- ircomm_tty_change_speed(driver);
- }
- }
-#endif
return 0;
}
@@ -367,24 +280,6 @@ int ircomm_tty_ioctl(struct tty_struct *tty,
case TIOCGICOUNT:
pr_debug("%s(), TIOCGICOUNT not impl!\n", __func__);
-#if 0
- save_flags(flags); cli();
- cnow = driver->icount;
- restore_flags(flags);
- p_cuser = (struct serial_icounter_struct __user *) arg;
- if (put_user(cnow.cts, &p_cuser->cts) ||
- put_user(cnow.dsr, &p_cuser->dsr) ||
- put_user(cnow.rng, &p_cuser->rng) ||
- put_user(cnow.dcd, &p_cuser->dcd) ||
- put_user(cnow.rx, &p_cuser->rx) ||
- put_user(cnow.tx, &p_cuser->tx) ||
- put_user(cnow.frame, &p_cuser->frame) ||
- put_user(cnow.overrun, &p_cuser->overrun) ||
- put_user(cnow.parity, &p_cuser->parity) ||
- put_user(cnow.brk, &p_cuser->brk) ||
- put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
- return -EFAULT;
-#endif
return 0;
default:
ret = -ENOIOCTLCMD; /* ioctls which we must ignore */
--
2.13.0
^ permalink raw reply related
* [PATCH 7/9] tty: rocket: drop broken alt-speed support
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Setting an alt_speed using the ROCKET_SPD flags has been deprecated
since v2.1.69, and has been broken since commit 6865ff222cca ("TTY: do
not warn about setting speed via SPD_*") without anyone noticing.
To make things worse commit 6df3526b6649 ("rocket: first pass at termios
reporting") in v2.6.25 started reporting back the actual baud rate used,
something which also required 38400 to again be set whenever changing a
SPD flag.
Drop the broken alt-speed handling altogether, and add a ratelimited
warning about using TIOCCSERIAL to change speed as being deprecated.
Note that the rocket driver has never supported using a custom divisor
(ASYNC_SPD_CUST equivalent).
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/tty/rocket.c | 27 ++++++---------------------
1 file changed, 6 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index b51a877da986..20d79a6007d5 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -947,18 +947,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
tty_port_set_initialized(&info->port, 1);
- /*
- * Set up the tty->alt_speed kludge
- */
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- tty->alt_speed = 57600;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- tty->alt_speed = 115200;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- tty->alt_speed = 230400;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- tty->alt_speed = 460800;
-
configure_r_port(tty, info, NULL);
if (C_BAUD(tty)) {
sSetDTR(cp);
@@ -1219,23 +1207,20 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
return -EPERM;
}
info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
- configure_r_port(tty, info, NULL);
mutex_unlock(&info->port.mutex);
return 0;
}
+ if ((new_serial.flags ^ info->flags) & ROCKET_SPD_MASK) {
+ /* warn about deprecation, unless clearing */
+ if (new_serial.flags & ROCKET_SPD_MASK)
+ dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
+ }
+
info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
info->port.close_delay = new_serial.close_delay;
info->port.closing_wait = new_serial.closing_wait;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- tty->alt_speed = 57600;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- tty->alt_speed = 115200;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- tty->alt_speed = 230400;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- tty->alt_speed = 460800;
mutex_unlock(&info->port.mutex);
configure_r_port(tty, info, NULL);
--
2.13.0
^ permalink raw reply related
* [PATCH 6/9] tty: cyclades: drop broken alt-speed support
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Setting an alt_speed using the ASYNC_SPD flags has been deprecated since
v2.1.69, and has been broken since v3.10 and commit 6865ff222cca ("TTY:
do not warn about setting speed via SPD_*") without anyone noticing.
Drop the broken alt-speed handling altogether, and add a ratelimited
warning about using TIOCCSERIAL to to change speed as being deprecated.
Note that using ASYNC_SPD_CUST is still supported.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/tty/cyclades.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 104f09c58163..d272bc4e7fb5 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -1975,18 +1975,6 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
cflag = tty->termios.c_cflag;
iflag = tty->termios.c_iflag;
- /*
- * Set up the tty->alt_speed kludge
- */
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
-
card = info->card;
channel = info->line - card->first_line;
@@ -2295,12 +2283,16 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
struct serial_struct __user *new_info)
{
struct serial_struct new_serial;
+ int old_flags;
int ret;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
mutex_lock(&info->port.mutex);
+
+ old_flags = info->port.flags;
+
if (!capable(CAP_SYS_ADMIN)) {
if (new_serial.close_delay != info->port.close_delay ||
new_serial.baud_base != info->baud ||
@@ -2332,6 +2324,11 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
check_and_exit:
if (tty_port_initialized(&info->port)) {
+ if ((new_serial.flags ^ old_flags) & ASYNC_SPD_MASK) {
+ /* warn about deprecation unless clearing */
+ if (new_serial.flags & ASYNC_SPD_MASK)
+ dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
+ }
cy_set_line_char(info, tty);
ret = 0;
} else {
--
2.13.0
^ permalink raw reply related
* [PATCH 5/9] tty: amiserial: drop broken alt-speed support
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Setting an alt_speed using the ASYNC_SPD flags has been deprecated since
v2.1.69, and has been broken since v3.10 and commit 6865ff222cca ("TTY:
do not warn about setting speed via SPD_*") without anyone noticing.
Drop the broken alt-speed handling altogether, and add a ratelimited
warning about using TIOCCSERIAL to change speed as being deprecated.
Note that using ASYNC_SPD_CUST is still supported.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/tty/amiserial.c | 23 +++--------------------
1 file changed, 3 insertions(+), 20 deletions(-)
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index dea16bb8c46a..9820e20993db 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -570,18 +570,6 @@ static int startup(struct tty_struct *tty, struct serial_state *info)
info->xmit.head = info->xmit.tail = 0;
/*
- * Set up the tty->alt_speed kludge
- */
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
-
- /*
* and set the speed of the serial port
*/
change_speed(tty, info, NULL);
@@ -1084,14 +1072,9 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
check_and_exit:
if (tty_port_initialized(port)) {
if (change_spd) {
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
+ /* warn about deprecation unless clearing */
+ if (new_serial.flags & ASYNC_SPD_MASK)
+ dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
change_speed(tty, state, NULL);
}
} else
--
2.13.0
^ permalink raw reply related
* [PATCH 4/9] tty: simserial: drop unused alt_speed handling
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
This driver was setting the deprecated and broken alt_speed based on port
flags, but never provided a means to change the flags or to actually
change the speed.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
arch/ia64/hp/sim/simserial.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index de8cba121013..70d52e9bb575 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -387,19 +387,6 @@ static int activate(struct tty_port *port, struct tty_struct *tty)
}
state->xmit.head = state->xmit.tail = 0;
-
- /*
- * Set up the tty->alt_speed kludge
- */
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
-
errout:
local_irq_restore(flags);
return retval;
--
2.13.0
^ permalink raw reply related
* [PATCH 3/9] USB: serial: ftdi_sio: remove broken alt-speed handling
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Remove the broken alt_speed code, and warn when trying to set the line
speed using TIOCSSERIAL and SPD flags.
The use of SPD flags to set the line speed has been deprecated since
v2.1.69 and support for alt_speed (e.g. "warp") has even been removed
from TTY core in v3.10 by commit 6865ff222cca ("TTY: do not warn about
setting speed via SPD_*"), effectively breaking all driver
implementations of this except for serial core.
Also remove the verbose and outdated comment on how to set baud rates.
Note that setting a custom divisor will continue to work with the
caveat that 38400 must again be selected every time the divisor is
changed since v2.6.24 and commit 669a6db1037e ("USB: ftd_sio: cleanups
and updates for new termios work") which started reporting back the
actual baud rate used.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/ftdi_sio.c | 56 +++++++------------------------------------
1 file changed, 9 insertions(+), 47 deletions(-)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index df5c45a4b1d7..1cec03799cdf 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1244,42 +1244,13 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
int div_okay = 1;
int baud;
- /*
- * The logic involved in setting the baudrate can be cleanly split into
- * 3 steps.
- * 1. Standard baud rates are set in tty->termios->c_cflag
- * 2. If these are not enough, you can set any speed using alt_speed as
- * follows:
- * - set tty->termios->c_cflag speed to B38400
- * - set your real speed in tty->alt_speed; it gets ignored when
- * alt_speed==0, (or)
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
- * follows:
- * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP],
- * this just sets alt_speed to (HI: 57600, VHI: 115200,
- * SHI: 230400, WARP: 460800)
- * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
- * 3. You can also set baud rate by setting custom divisor as follows
- * - set tty->termios->c_cflag speed to B38400
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
- * follows:
- * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
- * o custom_divisor set to baud_base / your_new_baudrate
- * ** Step 3 is done courtesy of code borrowed from serial.c
- * I should really spend some time and separate + move this common
- * code to serial.c, it is replicated in nearly every serial driver
- * you see.
- */
-
- /* 1. Get the baud rate from the tty settings, this observes
- alt_speed hack */
-
baud = tty_get_baud_rate(tty);
dev_dbg(dev, "%s - tty_get_baud_rate reports speed %d\n", __func__, baud);
- /* 2. Observe async-compatible custom_divisor hack, update baudrate
- if needed */
-
+ /*
+ * Observe deprecated async-compatible custom_divisor hack, update
+ * baudrate if needed.
+ */
if (baud == 38400 &&
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(priv->custom_divisor)) {
@@ -1288,8 +1259,6 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
__func__, priv->custom_divisor, baud);
}
- /* 3. Convert baudrate to device-specific divisor */
-
if (!baud)
baud = 9600;
switch (priv->chip_type) {
@@ -1529,21 +1498,14 @@ static int set_serial_info(struct tty_struct *tty,
check_and_exit:
write_latency_timer(port);
- if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK) {
- if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- tty->alt_speed = 57600;
- else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- tty->alt_speed = 115200;
- else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- tty->alt_speed = 230400;
- else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- tty->alt_speed = 460800;
- else
- tty->alt_speed = 0;
- }
if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK ||
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
priv->custom_divisor != old_priv.custom_divisor)) {
+
+ /* warn about deprecation unless clearing */
+ if (priv->flags & ASYNC_SPD_MASK)
+ dev_warn_ratelimited(&port->dev, "use of SPD flags is deprecated\n");
+
change_speed(tty, port);
mutex_unlock(&priv->cfg_lock);
}
--
2.13.0
^ permalink raw reply related
* [PATCH 2/9] USB: serial: ftdi_sio: simplify TIOCSSERIAL flag logic
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Simplify TIOCSSERIAL flag logic somewhat.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/ftdi_sio.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index aba74f817dc6..df5c45a4b1d7 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1505,8 +1505,7 @@ static int set_serial_info(struct tty_struct *tty,
/* Do error checking and permission checking */
if (!capable(CAP_SYS_ADMIN)) {
- if (((new_serial.flags & ~ASYNC_USR_MASK) !=
- (priv->flags & ~ASYNC_USR_MASK))) {
+ if ((new_serial.flags ^ priv->flags) & ~ASYNC_USR_MASK) {
mutex_unlock(&priv->cfg_lock);
return -EPERM;
}
@@ -1530,8 +1529,7 @@ static int set_serial_info(struct tty_struct *tty,
check_and_exit:
write_latency_timer(port);
- if ((old_priv.flags & ASYNC_SPD_MASK) !=
- (priv->flags & ASYNC_SPD_MASK)) {
+ if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK) {
if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
tty->alt_speed = 57600;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
@@ -1543,10 +1541,9 @@ static int set_serial_info(struct tty_struct *tty,
else
tty->alt_speed = 0;
}
- if (((old_priv.flags & ASYNC_SPD_MASK) !=
- (priv->flags & ASYNC_SPD_MASK)) ||
- (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
- (old_priv.custom_divisor != priv->custom_divisor))) {
+ if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK ||
+ ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
+ priv->custom_divisor != old_priv.custom_divisor)) {
change_speed(tty, port);
mutex_unlock(&priv->cfg_lock);
}
--
2.13.0
^ permalink raw reply related
* [PATCH 1/9] serial: rate limit custom-speed deprecation notice
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
In-Reply-To: <20170606105441.689-1-johan@kernel.org>
Contrary to what a comment claimed, the ASYNC_SPD flags and custom
divisor can be set by a non-privileged user so rate limit the
deprecation notice as was intended.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/tty/serial/serial_core.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 13bfd5dcffce..f534a40aebde 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -954,11 +954,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
old_custom_divisor != uport->custom_divisor) {
/*
* If they're setting up a custom divisor or speed,
- * instead of clearing it, then bitch about it. No
- * need to rate-limit; it's CAP_SYS_ADMIN only.
+ * instead of clearing it, then bitch about it.
*/
if (uport->flags & UPF_SPD_MASK) {
- dev_notice(uport->dev,
+ dev_notice_ratelimited(uport->dev,
"%s sets custom speed on %s. This is deprecated.\n",
current->comm,
tty_name(port->tty));
--
2.13.0
^ permalink raw reply related
* [PATCH 0/9] tty: drop broken alt-speed handling
From: Johan Hovold @ 2017-06-06 10:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Jiri Slaby, Tony Luck, Fenghua Yu, Samuel Ortiz, David S. Miller,
linux-kernel, linux-usb, linux-serial, Johan Hovold
Setting an alt-speed using TIOCSSERIAL and SPD flags has been deprecated
since v2.1.69 and has been broken for all tty drivers but serial-core
since v3.10 and commit 6865ff222cca ("TTY: do not warn about setting
speed via SPD_*") without anyone noticing (for four years).
Instead of reverting the offending commit, lets get rid of this legacy
code while adding back a warning about the SPD flags being deprecated to
the drivers that once implemented it. Note that drivers implementing
SPD_CUST will continue to support using a custom divisor.
Also note that serial-core did not rely on the TTY layer for SPD
handling and continues to support it while warning about deprecation
(since 2003 at least).
Greg, I suggest you take it all trough the TTY tree even if merging
through multiple trees and applying the final patch once everything is
upstream would be an option. Also the irda clean up does not depend on
the rest of series as the code implementing SPD handling was ifdefed
out.
Johan
Johan Hovold (9):
serial: rate limit custom-speed deprecation notice
USB: serial: ftdi_sio: simplify TIOCSSERIAL flag logic
USB: serial: ftdi_sio: remove broken alt-speed handling
tty: simserial: drop unused alt_speed handling
tty: amiserial: drop broken alt-speed support
tty: cyclades: drop broken alt-speed support
tty: rocket: drop broken alt-speed support
tty: ircomm: remove dead and broken ioctl code
tty: drop unused alt_speed from tty_struct
arch/ia64/hp/sim/simserial.c | 13 -----
drivers/tty/amiserial.c | 23 ++------
drivers/tty/cyclades.c | 21 ++++----
drivers/tty/rocket.c | 27 +++-------
drivers/tty/serial/serial_core.c | 5 +-
drivers/usb/serial/ftdi_sio.c | 67 +++++------------------
include/linux/tty.h | 1 -
net/irda/ircomm/ircomm_tty_ioctl.c | 107 +------------------------------------
8 files changed, 34 insertions(+), 230 deletions(-)
--
2.13.0
^ permalink raw reply
* [PATCH v4 16/28] tty: serial: owl: Implement console driver
From: Andreas Färber @ 2017-06-06 0:54 UTC (permalink / raw)
To: linux-arm-kernel
Cc: mp-cs, Thomas Liau, 张东风, 刘炜,
张天益, 96boards, support, linux-kernel,
Andreas Färber, Greg Kroah-Hartman, Jiri Slaby, linux-serial
In-Reply-To: <20170606005426.26446-1-afaerber@suse.de>
Implement serial console driver to complement earlycon.
Based on LeMaker linux-actions tree.
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
v3 -> v4: Unchanged
v2 -> v3:
* Adopted BIT() macro
* Implemented baudrate setting
v2: new
drivers/tty/serial/Kconfig | 4 +-
drivers/tty/serial/owl-uart.c | 591 ++++++++++++++++++++++++++++++++++++++-
include/uapi/linux/serial_core.h | 3 +
3 files changed, 595 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 38f90ea45cf7..b0cddfbd8d74 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1689,7 +1689,7 @@ config SERIAL_MVEBU_CONSOLE
Otherwise, say 'N'.
config SERIAL_OWL
- bool "Actions Semi Owl serial port support"
+ tristate "Actions Semi Owl serial port support"
depends on ARCH_ACTIONS || COMPILE_TEST
select SERIAL_CORE
help
@@ -1705,7 +1705,7 @@ config SERIAL_OWL_CONSOLE
default y
help
Say 'Y' here if you wish to use Actions Semiconductor S500/S900 UART
- as the system console. Only earlycon is implemented currently.
+ as the system console.
endmenu
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index 1b8008797a1b..14e0324144cf 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -20,6 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/io.h>
@@ -28,22 +29,59 @@
#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#define OWL_UART_PORT_NUM 7
+#define OWL_UART_DEV_NAME "ttyOWL"
#define OWL_UART_CTL 0x000
+#define OWL_UART_RXDAT 0x004
#define OWL_UART_TXDAT 0x008
#define OWL_UART_STAT 0x00c
+#define OWL_UART_CTL_DWLS_MASK (0x3 << 0)
+#define OWL_UART_CTL_DWLS_5BITS (0x0 << 0)
+#define OWL_UART_CTL_DWLS_6BITS (0x1 << 0)
+#define OWL_UART_CTL_DWLS_7BITS (0x2 << 0)
+#define OWL_UART_CTL_DWLS_8BITS (0x3 << 0)
+#define OWL_UART_CTL_STPS_2BITS BIT(2)
+#define OWL_UART_CTL_PRS_MASK (0x7 << 4)
+#define OWL_UART_CTL_PRS_NONE (0x0 << 4)
+#define OWL_UART_CTL_PRS_ODD (0x4 << 4)
+#define OWL_UART_CTL_PRS_MARK (0x5 << 4)
+#define OWL_UART_CTL_PRS_EVEN (0x6 << 4)
+#define OWL_UART_CTL_PRS_SPACE (0x7 << 4)
+#define OWL_UART_CTL_AFE BIT(12)
#define OWL_UART_CTL_TRFS_TX BIT(14)
#define OWL_UART_CTL_EN BIT(15)
+#define OWL_UART_CTL_RXDE BIT(16)
+#define OWL_UART_CTL_TXDE BIT(17)
#define OWL_UART_CTL_RXIE BIT(18)
#define OWL_UART_CTL_TXIE BIT(19)
#define OWL_UART_STAT_RIP BIT(0)
#define OWL_UART_STAT_TIP BIT(1)
+#define OWL_UART_STAT_RXER BIT(2)
+#define OWL_UART_STAT_TFER BIT(3)
+#define OWL_UART_STAT_RXST BIT(4)
+#define OWL_UART_STAT_RFEM BIT(5)
#define OWL_UART_STAT_TFFU BIT(6)
+#define OWL_UART_STAT_TFES BIT(10)
#define OWL_UART_STAT_TRFL_MASK (0x1f << 11)
#define OWL_UART_STAT_UTBB BIT(17)
+static struct uart_driver owl_uart_driver;
+
+struct owl_uart_port {
+ struct uart_port port;
+ struct clk *clk;
+};
+
+#define to_owl_uart_port(prt) container_of(prt, struct owl_uart_port, prt)
+
+static struct owl_uart_port *owl_uart_ports[OWL_UART_PORT_NUM];
+
static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned int off)
{
writel(val, port->membase + off);
@@ -54,6 +92,380 @@ static inline u32 owl_uart_read(struct uart_port *port, unsigned int off)
return readl(port->membase + off);
}
+static void owl_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static unsigned int owl_uart_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+static unsigned int owl_uart_tx_empty(struct uart_port *port)
+{
+ unsigned long flags;
+ u32 val;
+ unsigned int ret;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ ret = (val & OWL_UART_STAT_TFES) ? TIOCSER_TEMT : 0;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return ret;
+}
+
+static void owl_uart_stop_rx(struct uart_port *port)
+{
+ u32 val;
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_RXDE);
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_RIP;
+ owl_uart_write(port, val, OWL_UART_STAT);
+}
+
+static void owl_uart_stop_tx(struct uart_port *port)
+{
+ u32 val;
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_TXDE);
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_TIP;
+ owl_uart_write(port, val, OWL_UART_STAT);
+}
+
+static void owl_uart_start_tx(struct uart_port *port)
+{
+ u32 val;
+
+ if (uart_tx_stopped(port)) {
+ owl_uart_stop_tx(port);
+ return;
+ }
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_TIP;
+ owl_uart_write(port, val, OWL_UART_STAT);
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val |= OWL_UART_CTL_TXIE;
+ owl_uart_write(port, val, OWL_UART_CTL);
+}
+
+static void owl_uart_send_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned int ch;
+
+ if (uart_tx_stopped(port))
+ return;
+
+ if (port->x_char) {
+ while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU))
+ cpu_relax();
+ owl_uart_write(port, port->x_char, OWL_UART_TXDAT);
+ port->icount.tx++;
+ port->x_char = 0;
+ }
+
+ while (!(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)) {
+ if (uart_circ_empty(xmit))
+ break;
+
+ ch = xmit->buf[xmit->tail];
+ owl_uart_write(port, ch, OWL_UART_TXDAT);
+ xmit->tail = (xmit->tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ owl_uart_stop_tx(port);
+}
+
+static void owl_uart_receive_chars(struct uart_port *port)
+{
+ u32 stat, val;
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val &= ~OWL_UART_CTL_TRFS_TX;
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ stat = owl_uart_read(port, OWL_UART_STAT);
+ while (!(stat & OWL_UART_STAT_RFEM)) {
+ char flag = TTY_NORMAL;
+
+ if (stat & OWL_UART_STAT_RXER)
+ port->icount.overrun++;
+
+ if (stat & OWL_UART_STAT_RXST) {
+ /* We are not able to distinguish the error type. */
+ port->icount.brk++;
+ port->icount.frame++;
+
+ stat &= port->read_status_mask;
+ if (stat & OWL_UART_STAT_RXST)
+ flag = TTY_PARITY;
+ } else
+ port->icount.rx++;
+
+ val = owl_uart_read(port, OWL_UART_RXDAT);
+ val &= 0xff;
+
+ if ((stat & port->ignore_status_mask) == 0)
+ tty_insert_flip_char(&port->state->port, val, flag);
+
+ stat = owl_uart_read(port, OWL_UART_STAT);
+ }
+
+ spin_unlock(&port->lock);
+ tty_flip_buffer_push(&port->state->port);
+ spin_lock(&port->lock);
+}
+
+static irqreturn_t owl_uart_irq(int irq, void *dev_id)
+{
+ struct uart_port *port = (struct uart_port *)dev_id;
+ u32 stat;
+
+ spin_lock(&port->lock);
+
+ stat = owl_uart_read(port, OWL_UART_STAT);
+
+ if (stat & OWL_UART_STAT_RIP)
+ owl_uart_receive_chars(port);
+
+ if (stat & OWL_UART_STAT_TIP)
+ owl_uart_send_chars(port);
+
+ stat = owl_uart_read(port, OWL_UART_STAT);
+ stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP;
+ owl_uart_write(port, stat, OWL_UART_STAT);
+
+ spin_unlock(&port->lock);
+
+ return IRQ_HANDLED;
+}
+
+static void owl_uart_shutdown(struct uart_port *port)
+{
+ u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_RXIE
+ | OWL_UART_CTL_TXDE | OWL_UART_CTL_RXDE | OWL_UART_CTL_EN);
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ free_irq(port->irq, port);
+}
+
+static int owl_uart_startup(struct uart_port *port)
+{
+ u32 val;
+ unsigned long flags;
+ int ret;
+
+ ret = request_irq(port->irq, owl_uart_irq, IRQF_TRIGGER_HIGH,
+ "owl-uart", port);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP
+ | OWL_UART_STAT_RXER | OWL_UART_STAT_TFER | OWL_UART_STAT_RXST;
+ owl_uart_write(port, val, OWL_UART_STAT);
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val |= OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE;
+ val |= OWL_UART_CTL_EN;
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+static void owl_uart_change_baudrate(struct owl_uart_port *owl_port,
+ unsigned long baud)
+{
+ clk_set_rate(owl_port->clk, baud * 8);
+}
+
+static void owl_uart_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct owl_uart_port *owl_port = to_owl_uart_port(port);
+ unsigned int baud;
+ u32 ctl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* We don't support modem control lines. */
+ termios->c_cflag &= ~(HUPCL | CMSPAR);
+ termios->c_cflag |= CLOCAL;
+
+ /* We don't support BREAK character recognition. */
+ termios->c_iflag &= ~(IGNBRK | BRKINT);
+
+ ctl = owl_uart_read(port, OWL_UART_CTL);
+
+ ctl &= ~OWL_UART_CTL_DWLS_MASK;
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ ctl |= OWL_UART_CTL_DWLS_5BITS;
+ break;
+ case CS6:
+ ctl |= OWL_UART_CTL_DWLS_6BITS;
+ break;
+ case CS7:
+ ctl |= OWL_UART_CTL_DWLS_7BITS;
+ break;
+ case CS8:
+ default:
+ ctl |= OWL_UART_CTL_DWLS_8BITS;
+ break;
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ ctl |= OWL_UART_CTL_STPS_2BITS;
+ else
+ ctl &= ~OWL_UART_CTL_STPS_2BITS;
+
+ ctl &= ~OWL_UART_CTL_PRS_MASK;
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & CMSPAR) {
+ if (termios->c_cflag & PARODD)
+ ctl |= OWL_UART_CTL_PRS_MARK;
+ else
+ ctl |= OWL_UART_CTL_PRS_SPACE;
+ } else if (termios->c_cflag & PARODD)
+ ctl |= OWL_UART_CTL_PRS_ODD;
+ else
+ ctl |= OWL_UART_CTL_PRS_EVEN;
+ } else
+ ctl |= OWL_UART_CTL_PRS_NONE;
+
+ if (termios->c_cflag & CRTSCTS)
+ ctl |= OWL_UART_CTL_AFE;
+ else
+ ctl &= ~OWL_UART_CTL_AFE;
+
+ owl_uart_write(port, ctl, OWL_UART_CTL);
+
+ baud = uart_get_baud_rate(port, termios, old, 9600, 3200000);
+ owl_uart_change_baudrate(owl_port, baud);
+
+ port->read_status_mask |= OWL_UART_STAT_RXER;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= OWL_UART_STAT_RXST;
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void owl_uart_release_port(struct uart_port *port)
+{
+ struct platform_device *pdev = to_platform_device(port->dev);
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return;
+
+ if (port->flags & UPF_IOREMAP) {
+ devm_release_mem_region(port->dev, port->mapbase,
+ resource_size(res));
+ devm_iounmap(port->dev, port->membase);
+ port->membase = NULL;
+ }
+}
+
+static int owl_uart_request_port(struct uart_port *port)
+{
+ struct platform_device *pdev = to_platform_device(port->dev);
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!devm_request_mem_region(port->dev, port->mapbase,
+ resource_size(res), dev_name(port->dev)))
+ return -EBUSY;
+
+ if (port->flags & UPF_IOREMAP) {
+ port->membase = devm_ioremap_nocache(port->dev, port->mapbase,
+ resource_size(res));
+ if (!port->membase)
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static const char *owl_uart_type(struct uart_port *port)
+{
+ return (port->type == PORT_OWL) ? "owl-uart" : NULL;
+}
+
+static int owl_uart_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ if (port->type != PORT_OWL)
+ return -EINVAL;
+
+ if (port->irq != ser->irq)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void owl_uart_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_OWL;
+ owl_uart_request_port(port);
+ }
+}
+
+static struct uart_ops owl_uart_ops = {
+ .set_mctrl = owl_uart_set_mctrl,
+ .get_mctrl = owl_uart_get_mctrl,
+ .tx_empty = owl_uart_tx_empty,
+ .start_tx = owl_uart_start_tx,
+ .stop_rx = owl_uart_stop_rx,
+ .stop_tx = owl_uart_stop_tx,
+ .startup = owl_uart_startup,
+ .shutdown = owl_uart_shutdown,
+ .set_termios = owl_uart_set_termios,
+ .type = owl_uart_type,
+ .config_port = owl_uart_config_port,
+ .request_port = owl_uart_request_port,
+ .release_port = owl_uart_release_port,
+ .verify_port = owl_uart_verify_port,
+};
+
#ifdef CONFIG_SERIAL_OWL_CONSOLE
static void owl_console_putchar(struct uart_port *port, int ch)
@@ -110,6 +522,57 @@ static void owl_uart_port_write(struct uart_port *port, const char *s,
local_irq_restore(flags);
}
+static void owl_uart_console_write(struct console *co, const char *s,
+ u_int count)
+{
+ struct owl_uart_port *owl_port;
+
+ owl_port = owl_uart_ports[co->index];
+ if (!owl_port)
+ return;
+
+ owl_uart_port_write(&owl_port->port, s, count);
+}
+
+static int owl_uart_console_setup(struct console *co, char *options)
+{
+ struct owl_uart_port *owl_port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index < 0 || co->index >= OWL_UART_PORT_NUM)
+ return -EINVAL;
+
+ owl_port = owl_uart_ports[co->index];
+ if (!owl_port || !owl_port->port.membase)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&owl_port->port, co, baud, parity, bits, flow);
+}
+
+static struct console owl_uart_console = {
+ .name = OWL_UART_DEV_NAME,
+ .write = owl_uart_console_write,
+ .device = uart_console_device,
+ .setup = owl_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &owl_uart_driver,
+};
+
+static int __init owl_uart_console_init(void)
+{
+ register_console(&owl_uart_console);
+
+ return 0;
+}
+console_initcall(owl_uart_console_init);
+
static void owl_uart_early_console_write(struct console *co,
const char *s,
u_int count)
@@ -132,4 +595,130 @@ owl_uart_early_console_setup(struct earlycon_device *device, const char *opt)
OF_EARLYCON_DECLARE(owl, "actions,owl-uart",
owl_uart_early_console_setup);
-#endif /* CONFIG_SERIAL_OWL_CONSOLE */
+#define OWL_UART_CONSOLE (&owl_uart_console)
+#else
+#define OWL_UART_CONSOLE NULL
+#endif
+
+static struct uart_driver owl_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "owl-uart",
+ .dev_name = OWL_UART_DEV_NAME,
+ .nr = OWL_UART_PORT_NUM,
+ .cons = OWL_UART_CONSOLE,
+};
+
+static int owl_uart_probe(struct platform_device *pdev)
+{
+ struct resource *res_mem, *res_irq;
+ struct owl_uart_port *owl_port;
+ int ret;
+
+ if (pdev->dev.of_node)
+ pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
+
+ if (pdev->id < 0 || pdev->id >= OWL_UART_PORT_NUM) {
+ dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
+ return -EINVAL;
+ }
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res_mem) {
+ dev_err(&pdev->dev, "could not get mem\n");
+ return -ENODEV;
+ }
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq) {
+ dev_err(&pdev->dev, "could not get irq\n");
+ return -ENODEV;
+ }
+
+ if (owl_uart_ports[pdev->id]) {
+ dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
+ return -EBUSY;
+ }
+
+ owl_port = devm_kzalloc(&pdev->dev, sizeof(*owl_port), GFP_KERNEL);
+ if (!owl_port)
+ return -ENOMEM;
+
+ owl_port->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(owl_port->clk)) {
+ dev_err(&pdev->dev, "could not get clk\n");
+ return PTR_ERR(owl_port->clk);
+ }
+
+ owl_port->port.dev = &pdev->dev;
+ owl_port->port.line = pdev->id;
+ owl_port->port.type = PORT_OWL;
+ owl_port->port.iotype = UPIO_MEM;
+ owl_port->port.mapbase = res_mem->start;
+ owl_port->port.irq = res_irq->start;
+ owl_port->port.uartclk = clk_get_rate(owl_port->clk);
+ owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY;
+ owl_port->port.x_char = 0;
+ owl_port->port.fifosize = 16;
+ owl_port->port.ops = &owl_uart_ops;
+
+ owl_uart_ports[pdev->id] = owl_port;
+ platform_set_drvdata(pdev, owl_port);
+
+ ret = uart_add_one_port(&owl_uart_driver, &owl_port->port);
+ if (ret)
+ owl_uart_ports[pdev->id] = NULL;
+
+ return ret;
+}
+
+static int owl_uart_remove(struct platform_device *pdev)
+{
+ struct owl_uart_port *owl_port;
+
+ owl_port = platform_get_drvdata(pdev);
+ uart_remove_one_port(&owl_uart_driver, &owl_port->port);
+ owl_uart_ports[pdev->id] = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id owl_uart_dt_matches[] = {
+ { .compatible = "actions,owl-uart" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, owl_uart_dt_matches);
+
+static struct platform_driver owl_uart_platform_driver = {
+ .probe = owl_uart_probe,
+ .remove = owl_uart_remove,
+ .driver = {
+ .name = "owl-uart",
+ .of_match_table = owl_uart_dt_matches,
+ },
+};
+
+static int __init owl_uart_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&owl_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&owl_uart_platform_driver);
+ if (ret)
+ uart_unregister_driver(&owl_uart_driver);
+
+ return ret;
+}
+
+static void __init owl_uart_exit(void)
+{
+ platform_driver_unregister(&owl_uart_platform_driver);
+ uart_unregister_driver(&owl_uart_driver);
+}
+
+module_init(owl_uart_init);
+module_exit(owl_uart_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 9ec741b133fe..5e850e68930d 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -271,4 +271,7 @@
/* MPS2 UART */
#define PORT_MPS2UART 116
+/* Actions Semi Owl UART */
+#define PORT_OWL 117
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
2.12.3
^ permalink raw reply related
* [PATCH v4 09/28] tty: serial: Add Actions Semi Owl UART earlycon
From: Andreas Färber @ 2017-06-06 0:54 UTC (permalink / raw)
To: linux-arm-kernel
Cc: support, 张天益, Greg Kroah-Hartman, 96boards,
linux-kernel, Thomas Liau, mp-cs, linux-serial, 刘炜,
Jiri Slaby, Andreas Färber, 张东风
In-Reply-To: <20170606005426.26446-1-afaerber@suse.de>
This implements an earlycon for Actions Semi S500/S900 SoCs.
Based on LeMaker linux-actions tree.
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
v3 -> v4: Unchanged
v2 -> v3:
* Adopted BIT() macro
v1 -> v2:
* Extended Kconfig help to mention earlycon (Arnd)
* Spelled out Actions Semiconductor in Kconfig help
* Adopted "actions" vendor prefix
drivers/tty/serial/Kconfig | 19 ++++++
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/owl-uart.c | 135 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 155 insertions(+)
create mode 100644 drivers/tty/serial/owl-uart.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 5c8850f7a2a0..38f90ea45cf7 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1688,6 +1688,25 @@ config SERIAL_MVEBU_CONSOLE
and warnings and which allows logins in single user mode)
Otherwise, say 'N'.
+config SERIAL_OWL
+ bool "Actions Semi Owl serial port support"
+ depends on ARCH_ACTIONS || COMPILE_TEST
+ select SERIAL_CORE
+ help
+ This driver is for Actions Semiconductor S500/S900 SoC's UART.
+ Say 'Y' here if you wish to use the on-board serial port.
+ Otherwise, say 'N'.
+
+config SERIAL_OWL_CONSOLE
+ bool "Console on Actions Semi Owl serial port"
+ depends on SERIAL_OWL=y
+ select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
+ default y
+ help
+ Say 'Y' here if you wish to use Actions Semiconductor S500/S900 UART
+ as the system console. Only earlycon is implemented currently.
+
endmenu
config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 53c03e005132..fe88a75d9a59 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_SERIAL_STM32) += stm32-usart.o
obj-$(CONFIG_SERIAL_MVEBU_UART) += mvebu-uart.o
obj-$(CONFIG_SERIAL_PIC32) += pic32_uart.o
obj-$(CONFIG_SERIAL_MPS2_UART) += mps2-uart.o
+obj-$(CONFIG_SERIAL_OWL) += owl-uart.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
new file mode 100644
index 000000000000..1b8008797a1b
--- /dev/null
+++ b/drivers/tty/serial/owl-uart.c
@@ -0,0 +1,135 @@
+/*
+ * Actions Semi Owl family serial console
+ *
+ * Copyright 2013 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2016-2017 Andreas Färber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#define OWL_UART_CTL 0x000
+#define OWL_UART_TXDAT 0x008
+#define OWL_UART_STAT 0x00c
+
+#define OWL_UART_CTL_TRFS_TX BIT(14)
+#define OWL_UART_CTL_EN BIT(15)
+#define OWL_UART_CTL_RXIE BIT(18)
+#define OWL_UART_CTL_TXIE BIT(19)
+
+#define OWL_UART_STAT_RIP BIT(0)
+#define OWL_UART_STAT_TIP BIT(1)
+#define OWL_UART_STAT_TFFU BIT(6)
+#define OWL_UART_STAT_TRFL_MASK (0x1f << 11)
+#define OWL_UART_STAT_UTBB BIT(17)
+
+static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned int off)
+{
+ writel(val, port->membase + off);
+}
+
+static inline u32 owl_uart_read(struct uart_port *port, unsigned int off)
+{
+ return readl(port->membase + off);
+}
+
+#ifdef CONFIG_SERIAL_OWL_CONSOLE
+
+static void owl_console_putchar(struct uart_port *port, int ch)
+{
+ if (!port->membase)
+ return;
+
+ while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)
+ cpu_relax();
+
+ owl_uart_write(port, ch, OWL_UART_TXDAT);
+}
+
+static void owl_uart_port_write(struct uart_port *port, const char *s,
+ u_int count)
+{
+ u32 old_ctl, val;
+ unsigned long flags;
+ int locked;
+
+ local_irq_save(flags);
+
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else {
+ spin_lock(&port->lock);
+ locked = 1;
+ }
+
+ old_ctl = owl_uart_read(port, OWL_UART_CTL);
+ val = old_ctl | OWL_UART_CTL_TRFS_TX;
+ /* disable IRQ */
+ val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE);
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+ uart_console_write(port, s, count, owl_console_putchar);
+
+ /* wait until all contents have been sent out */
+ while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TRFL_MASK)
+ cpu_relax();
+
+ /* clear IRQ pending */
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_TIP | OWL_UART_STAT_RIP;
+ owl_uart_write(port, val, OWL_UART_STAT);
+
+ owl_uart_write(port, old_ctl, OWL_UART_CTL);
+
+ if (locked)
+ spin_unlock(&port->lock);
+
+ local_irq_restore(flags);
+}
+
+static void owl_uart_early_console_write(struct console *co,
+ const char *s,
+ u_int count)
+{
+ struct earlycon_device *dev = co->data;
+
+ owl_uart_port_write(&dev->port, s, count);
+}
+
+static int __init
+owl_uart_early_console_setup(struct earlycon_device *device, const char *opt)
+{
+ if (!device->port.membase)
+ return -ENODEV;
+
+ device->con->write = owl_uart_early_console_write;
+
+ return 0;
+}
+OF_EARLYCON_DECLARE(owl, "actions,owl-uart",
+ owl_uart_early_console_setup);
+
+#endif /* CONFIG_SERIAL_OWL_CONSOLE */
--
2.12.3
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 08/28] dt-bindings: serial: Document Actions Semi Owl UARTs
From: Andreas Färber @ 2017-06-06 0:54 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, support, 张天益, devicetree,
Greg Kroah-Hartman, 96boards, linux-kernel, Thomas Liau,
Rob Herring, mp-cs, linux-serial, 刘炜,
Andreas Färber, 张东风
In-Reply-To: <20170606005426.26446-1-afaerber@suse.de>
This UART is found on S500 and S900 SoCs.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
v3 -> v4: Unchanged
v2 -> v3: unchanged
v1 -> v2:
* Adopted "actions" vendor prefix
.../devicetree/bindings/serial/actions,owl-uart.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 Documentation/devicetree/bindings/serial/actions,owl-uart.txt
diff --git a/Documentation/devicetree/bindings/serial/actions,owl-uart.txt b/Documentation/devicetree/bindings/serial/actions,owl-uart.txt
new file mode 100644
index 000000000000..aa873eada02d
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/actions,owl-uart.txt
@@ -0,0 +1,16 @@
+Actions Semi Owl UART
+
+Required properties:
+- compatible : "actions,s500-uart", "actions,owl-uart" for S500
+ "actions,s900-uart", "actions,owl-uart" for S900
+- reg : Offset and length of the register set for the device.
+- interrupts : Should contain UART interrupt.
+
+
+Example:
+
+ uart3: serial@b0126000 {
+ compatible = "actions,s500-uart", "actions,owl-uart";
+ reg = <0xb0126000 0x1000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ };
--
2.12.3
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 00/28] ARM: Initial Actions Semi S500 and S900 enablement
From: Andreas Färber @ 2017-06-06 0:53 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, Ulf Hansson, linux-doc, 刘炜,
devicetree, mp-cs, 96boards, Rob Herring, Kevin Hilman,
Daniel Lezcano, linux-serial, support, Arnd Bergmann, linux-pm,
Thomas Gleixner, 张天益, Greg Kroah-Hartman,
Jonathan Corbet, Rafael J . Wysocki, linux-kernel, Thomas Liau,
张东风, Olof Johansson
Hello,
This patch series adds initial support for Actions Semiconductor S500 (ARMv7)
and S900 (ARMv8) SoCs.
v4 refactors the clocksource driver again and fixes power-gating for CPU2/CPU3.
With this v4 I would like to start applying initial patches to my tree for 4.13.
@Actions: Last call for comments on vendor prefix and SoC bindings!
@uCRobotics: Last call for comments on vendor prefix and board bindings!
@LeMaker: Last call for comments on module and board bindings!
Work branch for testing:
https://github.com/afaerber/linux/commits/bg96-next
Booting from U-Boot to initrd is straightforward on both boards:
https://en.opensuse.org/HCL:Guitar
https://en.opensuse.org/HCL:Bubblegum-96
Have a lot of fun!
Cheers,
Andreas
v3 -> v4:
* Revert to hardcoded TIMER0/1 in clocksource (Daniel)
* Make power domains CPU2 and CPU3 always-on
* Clean up SMP vs. PM domains code duplication
* Extend earlycon documentation (Jonathan)
* Update MAINTAINERS with SPS files
v2 -> v3:
* Clocksource fix
* Clocksource cleanups (Daniel)
* Serial cleanups
* Add S500 CPU enable-method
* Add power domain driver
* Rework clocksource for S900 compatibility
v1 -> v2:
* S900 DT fixes (Mark)
* Kconfig name changes (Arnd)
* Bubblegum-96 .dts rename
* Vendor prefix rename
* Minor cleanups
* Add serial driver
* Add MAINTAINERS section
* Use SPDX-License-Identifier in DT (Rob)
* Add clocksource driver
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Olof Johansson <olof@lixom.net>
Cc: Rob Herring <robh@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: mp-cs@actions-semi.com
Cc: Thomas Liau <thomas.liau@actions-semi.com>
Cc: 96boards@ucrobotics.com
Cc: support@lemaker.org
Cc: linux-serial@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-pm@vger.kernel.org
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Kevin Hilman <khilman@kernel.org>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Cc: linux-doc@vger.kernel.org
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: devicetree@vger.kernel.org
Andreas Färber (28):
dt-bindings: Add vendor prefix for Actions Semi
dt-bindings: arm: Document Actions Semi S500
dt-bindings: timer: Document Owl timer
clocksource: Add Owl timer
clocksource: owl: Add S900 support
ARM: Prepare Actions Semi S500
ARM64: Prepare Actions Semi S900
dt-bindings: serial: Document Actions Semi Owl UARTs
tty: serial: Add Actions Semi Owl UART earlycon
Documentation: kernel-parameters: Document owl earlycon
ARM: dts: Add Actions Semi S500 and LeMaker Guitar
dt-bindings: Add vendor prefix for uCRobotics
dt-bindings: arm: Document Actions Semi S900
ARM64: dts: Add Actions Semi S900 and Bubblegum-96
MAINTAINERS: Add Actions Semi Owl section
tty: serial: owl: Implement console driver
ARM64: dts: actions: s900-bubblegum-96: Add fake uart5 clock
ARM: dts: s500-guitar-bb-rev-b: Add fake uart3 clock
dt-bindings: arm: cpus: Add S500 enable-method
ARM: owl: Implement CPU enable-method for S500
ARM: dts: s500: Set CPU enable-method
dt-bindings: power: Add Owl SPS power domains
soc: actions: Add Owl SPS
MAINTAINERS: Update Actions Semi section with SPS
ARM: dts: s500: Add SPS node
ARM: dts: s500: Set power domains for CPU2 and CPU3
soc: actions: owl-sps: Factor out owl_sps_set_pg() for power-gating
ARM: owl: smp: Implement SPS power-gating for CPU2 and CPU3
Documentation/admin-guide/kernel-parameters.txt | 6 +
Documentation/devicetree/bindings/arm/actions.txt | 39 ++
Documentation/devicetree/bindings/arm/cpus.txt | 1 +
.../devicetree/bindings/power/actions,owl-sps.txt | 17 +
.../bindings/serial/actions,owl-uart.txt | 16 +
.../bindings/timer/actions,owl-timer.txt | 20 +
.../devicetree/bindings/vendor-prefixes.txt | 2 +
MAINTAINERS | 13 +
arch/arm/Kconfig | 2 +
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 2 +
arch/arm/boot/dts/s500-guitar-bb-rev-b.dts | 33 +
arch/arm/boot/dts/s500-guitar.dtsi | 22 +
arch/arm/boot/dts/s500.dtsi | 189 ++++++
arch/arm/mach-actions/Kconfig | 16 +
arch/arm/mach-actions/Makefile | 4 +
arch/arm/mach-actions/headsmp.S | 68 ++
arch/arm/mach-actions/owl.c | 28 +
arch/arm/mach-actions/platsmp.c | 198 ++++++
arch/arm64/Kconfig.platforms | 6 +
arch/arm64/boot/dts/Makefile | 1 +
arch/arm64/boot/dts/actions/Makefile | 5 +
arch/arm64/boot/dts/actions/s900-bubblegum-96.dts | 42 ++
arch/arm64/boot/dts/actions/s900.dtsi | 164 +++++
drivers/clocksource/Kconfig | 7 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/owl-timer.c | 172 +++++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/actions/Kconfig | 16 +
drivers/soc/actions/Makefile | 2 +
drivers/soc/actions/owl-sps-helper.c | 51 ++
drivers/soc/actions/owl-sps.c | 224 +++++++
drivers/tty/serial/Kconfig | 19 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/owl-uart.c | 724 +++++++++++++++++++++
include/dt-bindings/power/s500-powergate.h | 19 +
include/linux/soc/actions/owl-sps.h | 11 +
include/uapi/linux/serial_core.h | 3 +
39 files changed, 2147 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/actions.txt
create mode 100644 Documentation/devicetree/bindings/power/actions,owl-sps.txt
create mode 100644 Documentation/devicetree/bindings/serial/actions,owl-uart.txt
create mode 100644 Documentation/devicetree/bindings/timer/actions,owl-timer.txt
create mode 100644 arch/arm/boot/dts/s500-guitar-bb-rev-b.dts
create mode 100644 arch/arm/boot/dts/s500-guitar.dtsi
create mode 100644 arch/arm/boot/dts/s500.dtsi
create mode 100644 arch/arm/mach-actions/Kconfig
create mode 100644 arch/arm/mach-actions/Makefile
create mode 100644 arch/arm/mach-actions/headsmp.S
create mode 100644 arch/arm/mach-actions/owl.c
create mode 100644 arch/arm/mach-actions/platsmp.c
create mode 100644 arch/arm64/boot/dts/actions/Makefile
create mode 100644 arch/arm64/boot/dts/actions/s900-bubblegum-96.dts
create mode 100644 arch/arm64/boot/dts/actions/s900.dtsi
create mode 100644 drivers/clocksource/owl-timer.c
create mode 100644 drivers/soc/actions/Kconfig
create mode 100644 drivers/soc/actions/Makefile
create mode 100644 drivers/soc/actions/owl-sps-helper.c
create mode 100644 drivers/soc/actions/owl-sps.c
create mode 100644 drivers/tty/serial/owl-uart.c
create mode 100644 include/dt-bindings/power/s500-powergate.h
create mode 100644 include/linux/soc/actions/owl-sps.h
--
2.12.3
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [GIT PULL] TTY fix for 4.12-rc4
From: Greg KH @ 2017-06-04 15:41 UTC (permalink / raw)
To: Linus Torvalds, Jiri Slaby
Cc: Stephen Rothwell, Andrew Morton, linux-kernel, linux-serial
The following changes since commit 5ed02dbb497422bf225783f46e6eadd237d23d6b:
Linux 4.12-rc3 (2017-05-28 17:20:53 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/ tags/tty-4.12-rc4
for you to fetch changes up to fc098af16b9ff6d470d779d8ddcfb2d91869045a:
Revert "tty: fix port buffer locking" (2017-06-04 10:23:25 +0200)
----------------------------------------------------------------
TTY fix for 4.12-rc4
Here is a single tty core fix for 4.12-rc4. It reverts a patch that a
lot of people reported as causing lockdep and other warnings. Right
after I reverted this in my tree, it seems like another "correct" fix
might have shown up, but it's too late in the release cycle to be
messing with tty core locking, so let's just revert this for now to go
back how things always have been and try it again for 4.13.
This has not been in linux-next as I only reverted it a few hours ago.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----------------------------------------------------------------
Greg Kroah-Hartman (1):
Revert "tty: fix port buffer locking"
drivers/tty/tty_port.c | 2 --
1 file changed, 2 deletions(-)
^ permalink raw reply
* Re: [RFC, PATCH] imx: serial: Take tty->files_lock opportunistically
From: Greg Kroah-Hartman @ 2017-06-03 9:30 UTC (permalink / raw)
To: Peter Senna Tschudin
Cc: Alan Cox, Rob Herring, Andrey Smirnov,
linux-serial@vger.kernel.org, Chris Healy, Jiri Slaby,
linux-kernel@vger.kernel.org
In-Reply-To: <20170530134427.GD6786@collabora.com>
On Tue, May 30, 2017 at 03:44:27PM +0200, Peter Senna Tschudin wrote:
> On Tue, May 30, 2017 at 02:42:13PM +0100, Alan Cox wrote:
>
> I sent a second patch recently:
>
> https://patchwork.kernel.org/patch/9725625/
And it's already in linux-next so all should be good here.
^ permalink raw reply
* Re: [PATCH 6/6] tty: serial: lpuart: add a more accurate baud rate calculation method
From: Andy Shevchenko @ 2017-06-02 17:11 UTC (permalink / raw)
To: A.S. Dong
Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm Mailing List, Greg Kroah-Hartman, Jiri Slaby, Andy Duan,
Stefan Agner, Mingkai Hu, Y.B. Lu
In-Reply-To: <AM3PR04MB3062F7BCE82860C377C214E80F10@AM3PR04MB306.eurprd04.prod.outlook.com>
On Wed, May 31, 2017 at 5:18 PM, A.S. Dong <aisheng.dong@nxp.com> wrote:
>> On Tue, May 9, 2017 at 10:50 AM, Dong Aisheng <aisheng.dong@nxp.com> wrote:
By some reason my previous message went privately.
It didn't have anything major anyway and here I'm suggesting
optimization of finding factors of the formula in use. See below.
>> > + u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
>> > + u32 clk = sport->port.uartclk;
>> > +
>> > + /*
>> > + * The idea is to use the best OSR (over-sampling rate) possible.
>> > + * Note, OSR is typically hard-set to 16 in other LPUART
>> instantiations.
>> > + * Loop to find the best OSR value possible, one that generates
>> minimum
>> > + * baud_diff iterate through the rest of the supported values of
>> OSR.
>> > + *
>> > + * Calculation Formula:
>> > + * Baud Rate = baud clock / ((OSR+1) × SBR)
>> > + */
>> > + baud_diff = baudrate;
>> > + osr = 0;
>> > + sbr = 0;
>> > +
>>
>> > + for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
I missed one thing, what happened by default to OSR? What is the value in use?
>> I _think_ you may simplify this and avoid for-loop if you reconsider
>> approach.
> But there is indeed a optimization way, see below.
> To optimize the looping, we probably could do:
> If (!baud_diff)
> Break;
It's a small one, we may have more interesting approach.
So, the algo is the following:
Assume the ranges like this:
OSR = [4 ... 32]
SBR = [2 ... 8192]
Then:
1. Get ratio factor as
ratio = CLK / desired baud rate
2. If ratio < 8192 * 9 / 2, just use (ratio / 4, 4) as (OSR, SBR)
setting. (Needs clarification on OSR < 4)
3. if ratio >= 8192 * 31, just use those two numbers (8192, 31). You
can't do anything better there.
4. Otherwise, get a minimum required factor of OSR
osr_min = ratio / 8192
5. Start your loop from osr_min + 1 to 31.
6 (optional). Of course you may not consider baud_diff > osr_min, it's
I suppose obvious
P.S. Note, all divisions by 2^n are just simple right shifts. Diffs
are calculated as multiplication of OSR and SBR in comparison to
ratio. One division so far.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v5 10/11] gpio-exar/8250-exar: Make set of exported GPIOs configurable
From: Andy Shevchenko @ 2017-06-02 10:32 UTC (permalink / raw)
To: Jan Kiszka
Cc: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot,
Linux Kernel Mailing List, linux-serial@vger.kernel.org,
linux-gpio@vger.kernel.org, Sudip Mukherjee, Sascha Weisenberger
In-Reply-To: <f8b03cad4ea23bf64f9e1fe29f38a1998b458293.1496388533.git.jan.kiszka@siemens.com>
On Fri, Jun 2, 2017 at 10:28 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> On the SIMATIC, IOT2040 only a single pin is exportable as GPIO, the
> rest is required to operate the UART. To allow modeling this case,
> expand the platform device data structure to specify a (consecutive) pin
> subset for exporting by the gpio-exar driver.
> + if (device_property_read_u32(&pdev->dev, "gpio-exar,first-pin",
> + &first_pin) < 0 ||
> + device_property_read_u32(&pdev->dev, "ngpios", &ngpios) < 0)
> + return -EINVAL;
You shadow an error.
Please use
ret = device_property_...;
if (ret)
return ret;
ret = ...
...
Moreover, I missed how you named first property, I would go rather
with "linux," prefix to show that is _internal_ / Linux only property.
Perhaps something like "linux,first-pin" ?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v5 11/11] serial: exar: Add support for IOT2040 device
From: Jan Kiszka @ 2017-06-02 7:28 UTC (permalink / raw)
To: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot
Cc: Linux Kernel Mailing List, linux-serial, linux-gpio,
Sudip Mukherjee, Andy Shevchenko, Sascha Weisenberger
In-Reply-To: <cover.1496388533.git.jan.kiszka@siemens.com>
This implements the setup of RS232 and the switch-over to RS485 or RS422
for the Siemens IOT2040. That uses an EXAR XR17V352 with external logic
to switch between the different modes. The external logic is controlled
via MPIO pins of the EXAR controller.
Only pin 10 can be exported as GPIO on the IOT2040. It is connected to
an LED.
As the XR17V352 used on the IOT2040 is not equipped with an external
EEPROM, it cannot present itself as IOT2040-variant via subvendor/
subdevice IDs. Thus, we have to check via DMI for the target platform.
Co-developed with Sascha Weisenberger.
Signed-off-by: Sascha Weisenberger <sascha.weisenberger@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
drivers/tty/serial/8250/8250_exar.c | 129 +++++++++++++++++++++++++++++++++++-
1 file changed, 128 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index bd0e40e869b8..4154601b1d03 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -10,6 +10,7 @@
* the Free Software Foundation; either version 2 of the License.
*/
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -62,6 +63,43 @@
#define UART_EXAR_MPIOSEL_15_8 0x99 /* MPIOSEL[15:8] */
#define UART_EXAR_MPIOOD_15_8 0x9a /* MPIOOD[15:8] */
+#define UART_EXAR_RS485_DLY(x) ((x) << 4)
+
+/*
+ * IOT2040 MPIO wiring semantics:
+ *
+ * MPIO Port Function
+ * ---- ---- --------
+ * 0 2 Mode bit 0
+ * 1 2 Mode bit 1
+ * 2 2 Terminate bus
+ * 3 - <reserved>
+ * 4 3 Mode bit 0
+ * 5 3 Mode bit 1
+ * 6 3 Terminate bus
+ * 7 - <reserved>
+ * 8 2 Enable
+ * 9 3 Enable
+ * 10 - Red LED
+ * 11..15 - <unused>
+ */
+
+/* IOT2040 MPIOs 0..7 */
+#define IOT2040_UART_MODE_RS232 0x01
+#define IOT2040_UART_MODE_RS485 0x02
+#define IOT2040_UART_MODE_RS422 0x03
+#define IOT2040_UART_TERMINATE_BUS 0x04
+
+#define IOT2040_UART1_MASK 0x0f
+#define IOT2040_UART2_SHIFT 4
+
+#define IOT2040_UARTS_DEFAULT_MODE 0x11 /* both RS232 */
+#define IOT2040_UARTS_GPIO_LO_MODE 0x88 /* reserved pins as input */
+
+/* IOT2040 MPIOs 8..15 */
+#define IOT2040_UARTS_ENABLE 0x03
+#define IOT2040_UARTS_GPIO_HI_MODE 0xF8 /* enable & LED as outputs */
+
struct exar8250;
struct exar8250_platform {
@@ -243,18 +281,107 @@ static const struct exar8250_platform exar8250_default_platform = {
.register_gpio = xr17v35x_register_gpio,
};
+static int iot2040_rs485_config(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED);
+ u8 __iomem *p = port->membase;
+ u8 mask = IOT2040_UART1_MASK;
+ u8 mode, value;
+
+ if (is_rs485) {
+ if (rs485->flags & SER_RS485_RX_DURING_TX)
+ mode = IOT2040_UART_MODE_RS422;
+ else
+ mode = IOT2040_UART_MODE_RS485;
+
+ if (rs485->flags & SER_RS485_TERMINATE_BUS)
+ mode |= IOT2040_UART_TERMINATE_BUS;
+ } else {
+ mode = IOT2040_UART_MODE_RS232;
+ }
+
+ if (port->line == 3) {
+ mask <<= IOT2040_UART2_SHIFT;
+ mode <<= IOT2040_UART2_SHIFT;
+ }
+
+ value = readb(p + UART_EXAR_MPIOLVL_7_0);
+ value &= ~mask;
+ value |= mode;
+ writeb(value, p + UART_EXAR_MPIOLVL_7_0);
+
+ value = readb(p + UART_EXAR_FCTR);
+ if (is_rs485)
+ value |= UART_FCTR_EXAR_485;
+ else
+ value &= ~UART_FCTR_EXAR_485;
+ writeb(value, p + UART_EXAR_FCTR);
+
+ if (is_rs485)
+ writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR);
+
+ port->rs485 = *rs485;
+
+ return 0;
+}
+
+static const struct property_entry iot2040_gpio_properties[] = {
+ PROPERTY_ENTRY_U32("gpio-exar,first-pin", 10),
+ PROPERTY_ENTRY_U32("ngpios", 1),
+ { }
+};
+
+static int iot2040_register_gpio(struct pci_dev *pcidev,
+ struct uart_8250_port *port)
+{
+ u8 __iomem *p = port->port.membase;
+
+ writeb(IOT2040_UARTS_DEFAULT_MODE, p + UART_EXAR_MPIOLVL_7_0);
+ writeb(IOT2040_UARTS_GPIO_LO_MODE, p + UART_EXAR_MPIOSEL_7_0);
+ writeb(IOT2040_UARTS_ENABLE, p + UART_EXAR_MPIOLVL_15_8);
+ writeb(IOT2040_UARTS_GPIO_HI_MODE, p + UART_EXAR_MPIOSEL_15_8);
+
+ port->port.private_data =
+ __xr17v35x_register_gpio(pcidev, iot2040_gpio_properties);
+
+ return 0;
+}
+
+static const struct exar8250_platform iot2040_platform = {
+ .rs485_config = iot2040_rs485_config,
+ .register_gpio = iot2040_register_gpio,
+};
+
+static const struct dmi_system_id exar_platforms[] = {
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+ DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+ "6ES7647-0AA00-1YA2"),
+ },
+ .driver_data = (void *)&iot2040_platform,
+ },
+ {}
+};
+
static int
pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
struct uart_8250_port *port, int idx)
{
const struct exar8250_board *board = priv->board;
const struct exar8250_platform *platform;
+ const struct dmi_system_id *dmi_match;
unsigned int offset = idx * 0x400;
unsigned int baud = 7812500;
u8 __iomem *p;
int ret;
- platform = &exar8250_default_platform;
+ dmi_match = dmi_first_match(exar_platforms);
+ if (dmi_match)
+ platform = dmi_match->driver_data;
+ else
+ platform = &exar8250_default_platform;
port->port.uartclk = baud * 16;
port->port.rs485_config = platform->rs485_config;
--
2.12.3
^ permalink raw reply related
* [PATCH v5 10/11] gpio-exar/8250-exar: Make set of exported GPIOs configurable
From: Jan Kiszka @ 2017-06-02 7:28 UTC (permalink / raw)
To: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot
Cc: Linux Kernel Mailing List, linux-serial, linux-gpio,
Sudip Mukherjee, Andy Shevchenko, Sascha Weisenberger
In-Reply-To: <cover.1496388533.git.jan.kiszka@siemens.com>
On the SIMATIC, IOT2040 only a single pin is exportable as GPIO, the
rest is required to operate the UART. To allow modeling this case,
expand the platform device data structure to specify a (consecutive) pin
subset for exporting by the gpio-exar driver.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
drivers/gpio/gpio-exar.c | 52 +++++++++++++++++++++----------------
drivers/tty/serial/8250/8250_exar.c | 15 ++++++++---
2 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 1a629831d45b..220e93ed9111 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -31,6 +31,7 @@ struct exar_gpio_chip {
int index;
void __iomem *regs;
char name[20];
+ unsigned int first_pin;
};
static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
@@ -51,11 +52,12 @@ static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
static int exar_set_direction(struct gpio_chip *chip, int direction,
unsigned int offset)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
+ EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
+ unsigned int bit = (offset + exar_gpio->first_pin) % 8;
- addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
- exar_update(chip, addr, direction, offset % 8);
+ exar_update(chip, addr, direction, bit);
return 0;
}
@@ -73,36 +75,33 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg)
static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
- int val;
-
- addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
- val = exar_get(chip, addr) & BIT(offset % 8);
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
+ EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
+ unsigned int bit = (offset + exar_gpio->first_pin) % 8;
- return !!val;
+ return !!(exar_get(chip, addr) & BIT(bit));
}
static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
- int val;
-
- addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
- val = exar_get(chip, addr) & BIT(offset % 8);
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
+ EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
+ unsigned int bit = (offset + exar_gpio->first_pin) % 8;
- return !!val;
+ return !!(exar_get(chip, addr) & BIT(bit));
}
static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
int value)
{
- unsigned int bank = offset / 8;
- unsigned int addr;
+ struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+ unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
+ EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
+ unsigned int bit = (offset + exar_gpio->first_pin) % 8;
- addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
- exar_update(chip, addr, value, offset % 8);
+ exar_update(chip, addr, value, bit);
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
@@ -121,6 +120,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
{
struct pci_dev *pcidev = to_pci_dev(pdev->dev.parent);
struct exar_gpio_chip *exar_gpio;
+ u32 first_pin, ngpios;
void __iomem *p;
int index, ret;
@@ -132,6 +132,11 @@ static int gpio_exar_probe(struct platform_device *pdev)
if (!p)
return -ENOMEM;
+ if (device_property_read_u32(&pdev->dev, "gpio-exar,first-pin",
+ &first_pin) < 0 ||
+ device_property_read_u32(&pdev->dev, "ngpios", &ngpios) < 0)
+ return -EINVAL;
+
exar_gpio = devm_kzalloc(&pdev->dev, sizeof(*exar_gpio), GFP_KERNEL);
if (!exar_gpio)
return -ENOMEM;
@@ -149,9 +154,10 @@ static int gpio_exar_probe(struct platform_device *pdev)
exar_gpio->gpio_chip.get = exar_get_value;
exar_gpio->gpio_chip.set = exar_set_value;
exar_gpio->gpio_chip.base = -1;
- exar_gpio->gpio_chip.ngpio = 16;
+ exar_gpio->gpio_chip.ngpio = ngpios;
exar_gpio->regs = p;
exar_gpio->index = index;
+ exar_gpio->first_pin = first_pin;
ret = devm_gpiochip_add_data(&pdev->dev,
&exar_gpio->gpio_chip, exar_gpio);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 1106f1f58c77..bd0e40e869b8 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/property.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/slab.h>
@@ -201,7 +202,8 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
}
static void *
-__xr17v35x_register_gpio(struct pci_dev *pcidev)
+__xr17v35x_register_gpio(struct pci_dev *pcidev,
+ const struct property_entry *properties)
{
struct platform_device *pdev;
@@ -212,7 +214,8 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev)
pdev->dev.parent = &pcidev->dev;
ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
- if (platform_device_add(pdev) < 0) {
+ if (platform_device_add_properties(pdev, properties) < 0 ||
+ platform_device_add(pdev) < 0) {
platform_device_put(pdev);
return NULL;
}
@@ -220,12 +223,18 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev)
return pdev;
}
+static const struct property_entry exar_gpio_properties[] = {
+ PROPERTY_ENTRY_U32("gpio-exar,first-pin", 0),
+ PROPERTY_ENTRY_U32("ngpios", 16),
+ { }
+};
+
static int xr17v35x_register_gpio(struct pci_dev *pcidev,
struct uart_8250_port *port)
{
if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
port->port.private_data =
- __xr17v35x_register_gpio(pcidev);
+ __xr17v35x_register_gpio(pcidev, exar_gpio_properties);
return 0;
}
--
2.12.3
^ permalink raw reply related
* [PATCH v5 09/11] platform: Accept const properties
From: Jan Kiszka @ 2017-06-02 7:28 UTC (permalink / raw)
To: Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot
Cc: Linux Kernel Mailing List, linux-serial, linux-gpio,
Sudip Mukherjee, Andy Shevchenko, Sascha Weisenberger
In-Reply-To: <cover.1496388533.git.jan.kiszka@siemens.com>
Aligns us with device_add_properties, the function we call.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
drivers/base/platform.c | 2 +-
include/linux/platform_device.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index a102152301c8..71ea6f4d33c2 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data);
* platform device is released.
*/
int platform_device_add_properties(struct platform_device *pdev,
- struct property_entry *properties)
+ const struct property_entry *properties)
{
return device_add_properties(&pdev->dev, properties);
}
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 98c2a7c7108e..49f634d96118 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -172,7 +172,7 @@ extern int platform_device_add_resources(struct platform_device *pdev,
extern int platform_device_add_data(struct platform_device *pdev,
const void *data, size_t size);
extern int platform_device_add_properties(struct platform_device *pdev,
- struct property_entry *properties);
+ const struct property_entry *properties);
extern int platform_device_add(struct platform_device *pdev);
extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
--
2.12.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox