mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'tty-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH: "Here is the large set of TTY and Serial driver patches for 5.9-rc1. Lots of bugfixes in here, thanks to syzbot fuzzing for serial and vt and console code. Other highlights include: - much needed vt/vc code cleanup from Jiri Slaby - 8250 driver fixes and additions - various serial driver updates and feature enhancements - locking cleanup for serial/console initializations - other minor cleanups All of these have been in linux-next with no reported issues" * tag 'tty-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits) MAINTAINERS: enlist Greg formally for console stuff vgacon: Fix for missing check in scrollback handling Revert "serial: 8250: Let serial core initialise spin lock" serial: 8250: Let serial core initialise spin lock tty: keyboard, do not speculate on func_table index serial: stm32: Add RS485 RTS GPIO control serial: 8250_dw: Fix common clocks usage race condition serial: 8250_dw: Pass the same rate to the clk round and set rate methods serial: 8250_dw: Simplify the ref clock rate setting procedure serial: 8250: Add 8250 port clock update method tty: serial: imx: add imx earlycon driver tty: serial: imx: enable imx serial console port as module tty/synclink: remove leftover bits of non-PCI card support tty: Use the preferred form for passing the size of a structure type tty: Fix identation issues in struct serial_struct32 tty: Avoid the use of one-element arrays serial: msm_serial: add sparse context annotation serial: pmac_zilog: add sparse context annotation newport_con: vc_color is now in state serial: imx: use hrtimers for rs485 delays ...
This commit is contained in:
@@ -35,9 +35,11 @@ properties:
|
||||
description: label associated with this uart
|
||||
|
||||
st,hw-flow-ctrl:
|
||||
description: enable hardware flow control
|
||||
description: enable hardware flow control (deprecated)
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
uart-has-rtscts: true
|
||||
|
||||
dmas:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
@@ -5,7 +5,7 @@ GSM 0710 tty multiplexor HOWTO
|
||||
This line discipline implements the GSM 07.10 multiplexing protocol
|
||||
detailed in the following 3GPP document:
|
||||
|
||||
http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
|
||||
https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
|
||||
|
||||
This document give some hints on how to use this driver with GPRS and 3G
|
||||
modems connected to a physical serial port.
|
||||
|
||||
@@ -4386,6 +4386,12 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/connector/
|
||||
|
||||
CONSOLE SUBSYSTEM
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
S: Supported
|
||||
F: drivers/video/console/
|
||||
F: include/linux/console*
|
||||
|
||||
CONTROL GROUP (CGROUP)
|
||||
M: Tejun Heo <tj@kernel.org>
|
||||
M: Li Zefan <lizefan@huawei.com>
|
||||
|
||||
@@ -184,11 +184,6 @@ void line_flush_chars(struct tty_struct *tty)
|
||||
line_flush_buffer(tty);
|
||||
}
|
||||
|
||||
int line_put_char(struct tty_struct *tty, unsigned char ch)
|
||||
{
|
||||
return line_write(tty, &ch, sizeof(ch));
|
||||
}
|
||||
|
||||
int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
|
||||
{
|
||||
struct line *line = tty->driver_data;
|
||||
|
||||
@@ -66,7 +66,6 @@ extern int line_setup(char **conf, unsigned nlines, char **def,
|
||||
char *init, char *name);
|
||||
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
|
||||
int len);
|
||||
extern int line_put_char(struct tty_struct *tty, unsigned char ch);
|
||||
extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
|
||||
extern int line_chars_in_buffer(struct tty_struct *tty);
|
||||
extern void line_flush_buffer(struct tty_struct *tty);
|
||||
|
||||
@@ -95,7 +95,6 @@ static const struct tty_operations ssl_ops = {
|
||||
.open = line_open,
|
||||
.close = line_close,
|
||||
.write = line_write,
|
||||
.put_char = line_put_char,
|
||||
.write_room = line_write_room,
|
||||
.chars_in_buffer = line_chars_in_buffer,
|
||||
.flush_buffer = line_flush_buffer,
|
||||
|
||||
@@ -102,7 +102,6 @@ static const struct tty_operations console_ops = {
|
||||
.install = con_install,
|
||||
.close = line_close,
|
||||
.write = line_write,
|
||||
.put_char = line_put_char,
|
||||
.write_room = line_write_room,
|
||||
.chars_in_buffer = line_chars_in_buffer,
|
||||
.flush_buffer = line_flush_buffer,
|
||||
|
||||
@@ -109,16 +109,16 @@ static void braille_write(u16 *buf)
|
||||
/* Follow the VC cursor*/
|
||||
static void vc_follow_cursor(struct vc_data *vc)
|
||||
{
|
||||
vc_x = vc->vc_x - (vc->vc_x % WIDTH);
|
||||
vc_y = vc->vc_y;
|
||||
lastvc_x = vc->vc_x;
|
||||
lastvc_y = vc->vc_y;
|
||||
vc_x = vc->state.x - (vc->state.x % WIDTH);
|
||||
vc_y = vc->state.y;
|
||||
lastvc_x = vc->state.x;
|
||||
lastvc_y = vc->state.y;
|
||||
}
|
||||
|
||||
/* Maybe the VC cursor moved, if so follow it */
|
||||
static void vc_maybe_cursor_moved(struct vc_data *vc)
|
||||
{
|
||||
if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y)
|
||||
if (vc->state.x != lastvc_x || vc->state.y != lastvc_y)
|
||||
vc_follow_cursor(vc);
|
||||
}
|
||||
|
||||
|
||||
@@ -263,8 +263,8 @@ static unsigned char get_attributes(struct vc_data *vc, u16 *pos)
|
||||
|
||||
static void speakup_date(struct vc_data *vc)
|
||||
{
|
||||
spk_x = spk_cx = vc->vc_x;
|
||||
spk_y = spk_cy = vc->vc_y;
|
||||
spk_x = spk_cx = vc->state.x;
|
||||
spk_y = spk_cy = vc->state.y;
|
||||
spk_pos = spk_cp = vc->vc_pos;
|
||||
spk_old_attr = spk_attr;
|
||||
spk_attr = get_attributes(vc, (u_short *)spk_pos);
|
||||
@@ -1551,9 +1551,9 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
|
||||
*/
|
||||
is_cursor = value + 1;
|
||||
old_cursor_pos = vc->vc_pos;
|
||||
old_cursor_x = vc->vc_x;
|
||||
old_cursor_y = vc->vc_y;
|
||||
speakup_console[vc->vc_num]->ht.cy = vc->vc_y;
|
||||
old_cursor_x = vc->state.x;
|
||||
old_cursor_y = vc->state.y;
|
||||
speakup_console[vc->vc_num]->ht.cy = vc->state.y;
|
||||
cursor_con = vc->vc_num;
|
||||
if (cursor_track == CT_Highlight)
|
||||
reset_highlight_buffers(vc);
|
||||
@@ -1574,8 +1574,8 @@ static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
|
||||
i = 0;
|
||||
if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
|
||||
speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
|
||||
speakup_console[vc_num]->ht.rx[bi] = vc->vc_x;
|
||||
speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
|
||||
speakup_console[vc_num]->ht.rx[bi] = vc->state.x;
|
||||
speakup_console[vc_num]->ht.ry[bi] = vc->state.y;
|
||||
}
|
||||
while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
|
||||
if (ic[i] > 32) {
|
||||
@@ -1664,9 +1664,9 @@ static int speak_highlight(struct vc_data *vc)
|
||||
return 0;
|
||||
hc = get_highlight_color(vc);
|
||||
if (hc != -1) {
|
||||
d = vc->vc_y - speakup_console[vc_num]->ht.cy;
|
||||
d = vc->state.y - speakup_console[vc_num]->ht.cy;
|
||||
if ((d == 1) || (d == -1))
|
||||
if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y)
|
||||
if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y)
|
||||
return 0;
|
||||
spk_parked |= 0x01;
|
||||
spk_do_flush();
|
||||
@@ -1693,8 +1693,8 @@ static void cursor_done(struct timer_list *unused)
|
||||
}
|
||||
speakup_date(vc);
|
||||
if (win_enabled) {
|
||||
if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
|
||||
vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
|
||||
if (vc->state.x >= win_left && vc->state.x <= win_right &&
|
||||
vc->state.y >= win_top && vc->state.y <= win_bottom) {
|
||||
spk_keydown = 0;
|
||||
is_cursor = 0;
|
||||
goto out;
|
||||
@@ -1757,7 +1757,7 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
|
||||
if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
|
||||
/* Speakup output, discard */
|
||||
return;
|
||||
if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1))
|
||||
if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1))
|
||||
bleep(3);
|
||||
if ((is_cursor) || (cursor_track == read_all_mode)) {
|
||||
if (cursor_track == CT_Highlight)
|
||||
@@ -1766,8 +1766,8 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
|
||||
return;
|
||||
}
|
||||
if (win_enabled) {
|
||||
if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
|
||||
vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
|
||||
if (vc->state.x >= win_left && vc->state.x <= win_right &&
|
||||
vc->state.y >= win_top && vc->state.y <= win_bottom) {
|
||||
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
#define IntrQuit 0x40 /* received QUIT code */
|
||||
#define IntrEOF 0x80 /* received EOF code */
|
||||
|
||||
#define IntrRxTrigger 0x100 /* rx data count reach tigger value */
|
||||
#define IntrRxTrigger 0x100 /* rx data count reach trigger value */
|
||||
#define IntrTxTrigger 0x200 /* tx data count below trigger value */
|
||||
|
||||
#define Magic_no (Config_base + 0)
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
@@ -43,6 +45,8 @@ struct dw8250_data {
|
||||
int msr_mask_off;
|
||||
struct clk *clk;
|
||||
struct clk *pclk;
|
||||
struct notifier_block clk_notifier;
|
||||
struct work_struct clk_work;
|
||||
struct reset_control *rst;
|
||||
|
||||
unsigned int skip_autocfg:1;
|
||||
@@ -54,6 +58,16 @@ static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
|
||||
return container_of(data, struct dw8250_data, data);
|
||||
}
|
||||
|
||||
static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
|
||||
{
|
||||
return container_of(nb, struct dw8250_data, clk_notifier);
|
||||
}
|
||||
|
||||
static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work)
|
||||
{
|
||||
return container_of(work, struct dw8250_data, clk_work);
|
||||
}
|
||||
|
||||
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
||||
@@ -260,6 +274,46 @@ static int dw8250_handle_irq(struct uart_port *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dw8250_clk_work_cb(struct work_struct *work)
|
||||
{
|
||||
struct dw8250_data *d = work_to_dw8250_data(work);
|
||||
struct uart_8250_port *up;
|
||||
unsigned long rate;
|
||||
|
||||
rate = clk_get_rate(d->clk);
|
||||
if (rate <= 0)
|
||||
return;
|
||||
|
||||
up = serial8250_get_port(d->data.line);
|
||||
|
||||
serial8250_update_uartclk(&up->port, rate);
|
||||
}
|
||||
|
||||
static int dw8250_clk_notifier_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct dw8250_data *d = clk_to_dw8250_data(nb);
|
||||
|
||||
/*
|
||||
* We have no choice but to defer the uartclk update due to two
|
||||
* deadlocks. First one is caused by a recursive mutex lock which
|
||||
* happens when clk_set_rate() is called from dw8250_set_termios().
|
||||
* Second deadlock is more tricky and is caused by an inverted order of
|
||||
* the clk and tty-port mutexes lock. It happens if clock rate change
|
||||
* is requested asynchronously while set_termios() is executed between
|
||||
* tty-port mutex lock and clk_set_rate() function invocation and
|
||||
* vise-versa. Anyway if we didn't have the reference clock alteration
|
||||
* in the dw8250_set_termios() method we wouldn't have needed this
|
||||
* deferred event handling complication.
|
||||
*/
|
||||
if (event == POST_RATE_CHANGE) {
|
||||
queue_work(system_unbound_wq, &d->clk_work);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static void
|
||||
dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
|
||||
{
|
||||
@@ -275,27 +329,27 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
|
||||
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned int baud = tty_termios_baud_rate(termios);
|
||||
unsigned long newrate = tty_termios_baud_rate(termios) * 16;
|
||||
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
||||
long rate;
|
||||
int ret;
|
||||
|
||||
clk_disable_unprepare(d->clk);
|
||||
rate = clk_round_rate(d->clk, baud * 16);
|
||||
if (rate < 0)
|
||||
ret = rate;
|
||||
else if (rate == 0)
|
||||
ret = -ENOENT;
|
||||
else
|
||||
ret = clk_set_rate(d->clk, rate);
|
||||
rate = clk_round_rate(d->clk, newrate);
|
||||
if (rate > 0) {
|
||||
/*
|
||||
* Premilinary set the uartclk to the new clock rate so the
|
||||
* clock update event handler caused by the clk_set_rate()
|
||||
* calling wouldn't actually update the UART divisor since
|
||||
* we about to do this anyway.
|
||||
*/
|
||||
swap(p->uartclk, rate);
|
||||
ret = clk_set_rate(d->clk, newrate);
|
||||
if (ret)
|
||||
swap(p->uartclk, rate);
|
||||
}
|
||||
clk_prepare_enable(d->clk);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
p->uartclk = rate;
|
||||
|
||||
out:
|
||||
p->status &= ~UPSTAT_AUTOCTS;
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
p->status |= UPSTAT_AUTOCTS;
|
||||
@@ -319,6 +373,39 @@ static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios)
|
||||
serial8250_do_set_ldisc(p, termios);
|
||||
}
|
||||
|
||||
static int dw8250_startup(struct uart_port *p)
|
||||
{
|
||||
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Some platforms may provide a reference clock shared between several
|
||||
* devices. In this case before using the serial port first we have to
|
||||
* make sure that any clock state change is known to the UART port at
|
||||
* least post factum.
|
||||
*/
|
||||
if (d->clk) {
|
||||
ret = clk_notifier_register(d->clk, &d->clk_notifier);
|
||||
if (ret)
|
||||
dev_warn(p->dev, "Failed to set the clock notifier\n");
|
||||
}
|
||||
|
||||
return serial8250_do_startup(p);
|
||||
}
|
||||
|
||||
static void dw8250_shutdown(struct uart_port *p)
|
||||
{
|
||||
struct dw8250_data *d = to_dw8250_data(p->private_data);
|
||||
|
||||
serial8250_do_shutdown(p);
|
||||
|
||||
if (d->clk) {
|
||||
clk_notifier_unregister(d->clk, &d->clk_notifier);
|
||||
|
||||
flush_work(&d->clk_work);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dw8250_fallback_dma_filter will prevent the UART from getting just any free
|
||||
* channel on platforms that have DMA engines, but don't have any channels
|
||||
@@ -414,6 +501,8 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
p->serial_out = dw8250_serial_out;
|
||||
p->set_ldisc = dw8250_set_ldisc;
|
||||
p->set_termios = dw8250_set_termios;
|
||||
p->startup = dw8250_startup;
|
||||
p->shutdown = dw8250_shutdown;
|
||||
|
||||
p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
|
||||
if (!p->membase)
|
||||
@@ -475,6 +564,9 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(data->clk))
|
||||
return PTR_ERR(data->clk);
|
||||
|
||||
INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
|
||||
data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
|
||||
|
||||
err = clk_prepare_enable(data->clk);
|
||||
if (err)
|
||||
dev_warn(dev, "could not enable optional baudclk: %d\n", err);
|
||||
|
||||
@@ -78,14 +78,18 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
|
||||
|
||||
static int serial8250_em_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
struct serial8250_em_priv *priv;
|
||||
struct uart_8250_port up;
|
||||
int ret;
|
||||
struct resource *regs;
|
||||
int irq, ret;
|
||||
|
||||
if (!regs || !irq) {
|
||||
dev_err(&pdev->dev, "missing registers or irq\n");
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "missing registers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -101,7 +105,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
|
||||
|
||||
memset(&up, 0, sizeof(up));
|
||||
up.port.mapbase = regs->start;
|
||||
up.port.irq = irq->start;
|
||||
up.port.irq = irq;
|
||||
up.port.type = PORT_UNKNOWN;
|
||||
up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
|
||||
up.port.dev = &pdev->dev;
|
||||
|
||||
@@ -207,12 +207,11 @@ static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset)
|
||||
static int ingenic_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_8250_port uart = {};
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
struct ingenic_uart_data *data;
|
||||
const struct ingenic_uart_config *cdata;
|
||||
const struct of_device_id *match;
|
||||
int err, line;
|
||||
struct resource *regs;
|
||||
int irq, err, line;
|
||||
|
||||
match = of_match_device(of_match, &pdev->dev);
|
||||
if (!match) {
|
||||
@@ -221,8 +220,13 @@ static int ingenic_uart_probe(struct platform_device *pdev)
|
||||
}
|
||||
cdata = match->data;
|
||||
|
||||
if (!regs || !irq) {
|
||||
dev_err(&pdev->dev, "no registers/irq defined\n");
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "no registers defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -238,7 +242,7 @@ static int ingenic_uart_probe(struct platform_device *pdev)
|
||||
uart.port.regshift = 2;
|
||||
uart.port.serial_out = ingenic_uart_serial_out;
|
||||
uart.port.serial_in = ingenic_uart_serial_in;
|
||||
uart.port.irq = irq->start;
|
||||
uart.port.irq = irq;
|
||||
uart.port.dev = &pdev->dev;
|
||||
uart.port.fifosize = cdata->fifosize;
|
||||
uart.tx_loadsz = cdata->tx_loadsz;
|
||||
|
||||
@@ -51,7 +51,7 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev)
|
||||
return clkval;
|
||||
}
|
||||
|
||||
static unsigned int get_num_ports(struct mcb_device *mdev,
|
||||
static int get_num_ports(struct mcb_device *mdev,
|
||||
void __iomem *membase)
|
||||
{
|
||||
switch (mdev->id) {
|
||||
@@ -140,7 +140,7 @@ static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
|
||||
return;
|
||||
|
||||
num_ports = get_num_ports(mdev, data[0].uart.port.membase);
|
||||
if (num_ports < 0 || num_ports > 4) {
|
||||
if (num_ports <= 0 || num_ports > 4) {
|
||||
dev_err(&mdev->dev, "error retrieving number of ports!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,13 +512,17 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
|
||||
static int mtk8250_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_8250_port uart = {};
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
struct mtk8250_data *data;
|
||||
int err;
|
||||
struct resource *regs;
|
||||
int irq, err;
|
||||
|
||||
if (!regs || !irq) {
|
||||
dev_err(&pdev->dev, "no registers/irq defined\n");
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "no registers defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -542,7 +546,7 @@ static int mtk8250_probe(struct platform_device *pdev)
|
||||
|
||||
spin_lock_init(&uart.port.lock);
|
||||
uart.port.mapbase = regs->start;
|
||||
uart.port.irq = irq->start;
|
||||
uart.port.irq = irq;
|
||||
uart.port.pm = mtk8250_do_pm;
|
||||
uart.port.type = PORT_16550;
|
||||
uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
|
||||
|
||||
@@ -1209,17 +1209,21 @@ MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
|
||||
|
||||
static int omap8250_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct omap8250_priv *priv;
|
||||
const struct omap8250_platdata *pdata;
|
||||
struct uart_8250_port up;
|
||||
int ret;
|
||||
struct resource *regs;
|
||||
void __iomem *membase;
|
||||
int irq, ret;
|
||||
|
||||
if (!regs || !irq) {
|
||||
dev_err(&pdev->dev, "missing registers or irq\n");
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "missing registers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1236,7 +1240,7 @@ static int omap8250_probe(struct platform_device *pdev)
|
||||
up.port.dev = &pdev->dev;
|
||||
up.port.mapbase = regs->start;
|
||||
up.port.membase = membase;
|
||||
up.port.irq = irq->start;
|
||||
up.port.irq = irq;
|
||||
/*
|
||||
* It claims to be 16C750 compatible however it is a little different.
|
||||
* It has EFR and has no FCR7_64byte bit. The AFE (which it claims to
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -2631,6 +2632,46 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
|
||||
(port->uartclk + tolerance) / 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note in order to avoid the tty port mutex deadlock don't use the next method
|
||||
* within the uart port callbacks. Primarily it's supposed to be utilized to
|
||||
* handle a sudden reference clock rate change.
|
||||
*/
|
||||
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned int baud, quot, frac = 0;
|
||||
struct ktermios *termios;
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&port->state->port.mutex);
|
||||
|
||||
if (port->uartclk == uartclk)
|
||||
goto out_lock;
|
||||
|
||||
port->uartclk = uartclk;
|
||||
termios = &port->state->port.tty->termios;
|
||||
|
||||
baud = serial8250_get_baud_rate(port, termios, NULL);
|
||||
quot = serial8250_get_divisor(port, baud, &frac);
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
serial8250_set_divisor(port, baud, quot, frac);
|
||||
serial_port_out(port, UART_LCR, up->lcr);
|
||||
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
serial8250_rpm_put(up);
|
||||
|
||||
out_lock:
|
||||
mutex_unlock(&port->state->port.mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_update_uartclk);
|
||||
|
||||
void
|
||||
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -93,12 +92,15 @@ static int serial_pxa_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_8250_port uart = {};
|
||||
struct pxa8250_data *data;
|
||||
struct resource *mmres, *irqres;
|
||||
int ret;
|
||||
struct resource *mmres;
|
||||
int irq, ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!mmres || !irqres)
|
||||
if (!mmres)
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
@@ -121,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev)
|
||||
uart.port.iotype = UPIO_MEM32;
|
||||
uart.port.mapbase = mmres->start;
|
||||
uart.port.regshift = 2;
|
||||
uart.port.irq = irqres->start;
|
||||
uart.port.irq = irq;
|
||||
uart.port.fifosize = 64;
|
||||
uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;
|
||||
uart.port.dev = &pdev->dev;
|
||||
|
||||
@@ -222,7 +222,7 @@ config SERIAL_8250_MANY_PORTS
|
||||
Say Y here if you have dumb serial boards other than the four
|
||||
standard COM 1/2/3/4 ports. This may happen if you have an AST
|
||||
FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
|
||||
from <http://www.tldp.org/docs.html#howto>), or other custom
|
||||
from <https://www.tldp.org/docs.html#howto>), or other custom
|
||||
serial port hardware which acts similar to standard serial port
|
||||
hardware. If you only use the standard COM 1/2/3/4 ports, you can
|
||||
say N here to save some memory. You can also say Y if you have an
|
||||
@@ -266,7 +266,7 @@ config SERIAL_8250_BOCA
|
||||
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
|
||||
help
|
||||
Say Y here if you have a Boca serial board. Please read the Boca
|
||||
mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
|
||||
mini-HOWTO, available from <https://www.tldp.org/docs.html#howto>
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called 8250_boca.
|
||||
|
||||
@@ -502,20 +502,27 @@ config SERIAL_IMX
|
||||
can enable its onboard serial port by enabling this option.
|
||||
|
||||
config SERIAL_IMX_CONSOLE
|
||||
bool "Console on IMX serial port"
|
||||
depends on SERIAL_IMX=y
|
||||
tristate "Console on IMX serial port"
|
||||
depends on SERIAL_IMX
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON if OF
|
||||
help
|
||||
If you have enabled the serial port on the Freescale IMX
|
||||
CPU you can make it the console by answering Y to this option.
|
||||
CPU you can make it the console by answering Y/M to this option.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
Even if you say Y/M here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttymxc0". (Try "man bootparam" or see the documentation of
|
||||
your bootloader about how to pass options to the kernel at boot time.)
|
||||
|
||||
config SERIAL_IMX_EARLYCON
|
||||
bool "Earlycon on IMX serial port"
|
||||
depends on OF
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
If you have enabled the earlycon on the Freescale IMX
|
||||
CPU you can make it the earlycon by answering Y to this option.
|
||||
|
||||
config SERIAL_UARTLITE
|
||||
tristate "Xilinx uartlite serial port support"
|
||||
depends on HAS_IOMEM
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user