TTY/Serial patches for 5.9-rc1
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXyv30A8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ynW+gCgv+OqxT0jeNRAMSQcpMvP3wTBMKIAn1StfjJ4 y8uwZuQQimD49uj8XtDq =bKSv -----END PGP SIGNATURE----- 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:
Коммит
d6efb3ac3e
|
@ -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
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
/*
|
||||
* Altera JTAG UART register definitions according to the Altera JTAG UART
|
||||
* datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
|
||||
* datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
|
||||
*/
|
||||
|
||||
#define ALTERA_JTAGUART_SIZE 8
|
||||
|
|
|
@ -2607,7 +2607,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
|
|||
uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE);
|
||||
uap->port.flags = UPF_BOOT_AUTOCONF;
|
||||
uap->port.line = index;
|
||||
spin_lock_init(&uap->port.lock);
|
||||
|
||||
amba_ports[index] = uap;
|
||||
|
||||
|
|
|
@ -1925,6 +1925,9 @@ static void __lpuart32_serial_setbrg(struct uart_port *port,
|
|||
tmp_sbr++;
|
||||
}
|
||||
|
||||
if (tmp_sbr > UARTBAUD_SBR_MASK)
|
||||
continue;
|
||||
|
||||
if (tmp_diff <= baud_diff) {
|
||||
baud_diff = tmp_diff;
|
||||
osr = tmp_osr;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/serial.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/rational.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -188,6 +189,13 @@ struct imx_uart_data {
|
|||
enum imx_uart_type devtype;
|
||||
};
|
||||
|
||||
enum imx_tx_state {
|
||||
OFF,
|
||||
WAIT_AFTER_RTS,
|
||||
SEND,
|
||||
WAIT_AFTER_SEND,
|
||||
};
|
||||
|
||||
struct imx_port {
|
||||
struct uart_port port;
|
||||
struct timer_list timer;
|
||||
|
@ -224,6 +232,10 @@ struct imx_port {
|
|||
unsigned int dma_tx_nents;
|
||||
unsigned int saved_reg[10];
|
||||
bool context_saved;
|
||||
|
||||
enum imx_tx_state tx_state;
|
||||
struct hrtimer trigger_start_tx;
|
||||
struct hrtimer trigger_stop_tx;
|
||||
};
|
||||
|
||||
struct imx_port_ucrs {
|
||||
|
@ -361,7 +373,7 @@ static inline int imx_uart_is_imx6q(struct imx_port *sport)
|
|||
/*
|
||||
* Save and restore functions for UCR1, UCR2 and UCR3 registers
|
||||
*/
|
||||
#if defined(CONFIG_SERIAL_IMX_CONSOLE)
|
||||
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
|
||||
static void imx_uart_ucrs_save(struct imx_port *sport,
|
||||
struct imx_port_ucrs *ucr)
|
||||
{
|
||||
|
@ -400,6 +412,15 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
|
|||
mctrl_gpio_set(sport->gpios, sport->port.mctrl);
|
||||
}
|
||||
|
||||
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
|
||||
{
|
||||
long sec = msec / MSEC_PER_SEC;
|
||||
long nsec = (msec % MSEC_PER_SEC) * 1000000;
|
||||
ktime_t t = ktime_set(sec, nsec);
|
||||
|
||||
hrtimer_start(hrt, t, HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_start_rx(struct uart_port *port)
|
||||
{
|
||||
|
@ -427,7 +448,10 @@ static void imx_uart_start_rx(struct uart_port *port)
|
|||
static void imx_uart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
u32 ucr1;
|
||||
u32 ucr1, ucr4, usr2;
|
||||
|
||||
if (sport->tx_state == OFF)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We are maybe in the SMP context, so if the DMA TX thread is running
|
||||
|
@ -439,21 +463,44 @@ static void imx_uart_stop_tx(struct uart_port *port)
|
|||
ucr1 = imx_uart_readl(sport, UCR1);
|
||||
imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1);
|
||||
|
||||
/* in rs485 mode disable transmitter if shifter is empty */
|
||||
if (port->rs485.flags & SER_RS485_ENABLED &&
|
||||
imx_uart_readl(sport, USR2) & USR2_TXDC) {
|
||||
u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4;
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
imx_uart_rts_active(sport, &ucr2);
|
||||
else
|
||||
imx_uart_rts_inactive(sport, &ucr2);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
usr2 = imx_uart_readl(sport, USR2);
|
||||
if (!(usr2 & USR2_TXDC)) {
|
||||
/* The shifter is still busy, so retry once TC triggers */
|
||||
return;
|
||||
}
|
||||
|
||||
imx_uart_start_rx(port);
|
||||
ucr4 = imx_uart_readl(sport, UCR4);
|
||||
ucr4 &= ~UCR4_TCEN;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
|
||||
ucr4 = imx_uart_readl(sport, UCR4);
|
||||
ucr4 &= ~UCR4_TCEN;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
/* in rs485 mode disable transmitter */
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
if (sport->tx_state == SEND) {
|
||||
sport->tx_state = WAIT_AFTER_SEND;
|
||||
start_hrtimer_ms(&sport->trigger_stop_tx,
|
||||
port->rs485.delay_rts_after_send);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sport->tx_state == WAIT_AFTER_RTS ||
|
||||
sport->tx_state == WAIT_AFTER_SEND) {
|
||||
u32 ucr2;
|
||||
|
||||
hrtimer_try_to_cancel(&sport->trigger_start_tx);
|
||||
|
||||
ucr2 = imx_uart_readl(sport, UCR2);
|
||||
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
imx_uart_rts_active(sport, &ucr2);
|
||||
else
|
||||
imx_uart_rts_inactive(sport, &ucr2);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
|
||||
imx_uart_start_rx(port);
|
||||
|
||||
sport->tx_state = OFF;
|
||||
}
|
||||
} else {
|
||||
sport->tx_state = OFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,28 +698,50 @@ static void imx_uart_start_tx(struct uart_port *port)
|
|||
if (!sport->port.x_char && uart_circ_empty(&port->state->xmit))
|
||||
return;
|
||||
|
||||
/*
|
||||
* We cannot simply do nothing here if sport->tx_state == SEND already
|
||||
* because UCR1_TXMPTYEN might already have been cleared in
|
||||
* imx_uart_stop_tx(), but tx_state is still SEND.
|
||||
*/
|
||||
|
||||
if (port->rs485.flags & SER_RS485_ENABLED) {
|
||||
u32 ucr2;
|
||||
if (sport->tx_state == OFF) {
|
||||
u32 ucr2 = imx_uart_readl(sport, UCR2);
|
||||
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
|
||||
imx_uart_rts_active(sport, &ucr2);
|
||||
else
|
||||
imx_uart_rts_inactive(sport, &ucr2);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
|
||||
ucr2 = imx_uart_readl(sport, UCR2);
|
||||
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
|
||||
imx_uart_rts_active(sport, &ucr2);
|
||||
else
|
||||
imx_uart_rts_inactive(sport, &ucr2);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
|
||||
imx_uart_stop_rx(port);
|
||||
|
||||
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
|
||||
imx_uart_stop_rx(port);
|
||||
|
||||
/*
|
||||
* Enable transmitter and shifter empty irq only if DMA is off.
|
||||
* In the DMA case this is done in the tx-callback.
|
||||
*/
|
||||
if (!sport->dma_is_enabled) {
|
||||
u32 ucr4 = imx_uart_readl(sport, UCR4);
|
||||
ucr4 |= UCR4_TCEN;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
sport->tx_state = WAIT_AFTER_RTS;
|
||||
start_hrtimer_ms(&sport->trigger_start_tx,
|
||||
port->rs485.delay_rts_before_send);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sport->tx_state == WAIT_AFTER_SEND
|
||||
|| sport->tx_state == WAIT_AFTER_RTS) {
|
||||
|
||||
hrtimer_try_to_cancel(&sport->trigger_stop_tx);
|
||||
|
||||
/*
|
||||
* Enable transmitter and shifter empty irq only if DMA
|
||||
* is off. In the DMA case this is done in the
|
||||
* tx-callback.
|
||||
*/
|
||||
if (!sport->dma_is_enabled) {
|
||||
u32 ucr4 = imx_uart_readl(sport, UCR4);
|
||||
ucr4 |= UCR4_TCEN;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
}
|
||||
|
||||
sport->tx_state = SEND;
|
||||
}
|
||||
} else {
|
||||
sport->tx_state = SEND;
|
||||
}
|
||||
|
||||
if (!sport->dma_is_enabled) {
|
||||
|
@ -1630,7 +1699,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
ucr2 &= ~UCR2_IRTS;
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
ucr2 |= UCR2_STPB;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
|
@ -1857,10 +1925,6 @@ static int imx_uart_rs485_config(struct uart_port *port,
|
|||
struct imx_port *sport = (struct imx_port *)port;
|
||||
u32 ucr2;
|
||||
|
||||
/* unimplemented */
|
||||
rs485conf->delay_rts_before_send = 0;
|
||||
rs485conf->delay_rts_after_send = 0;
|
||||
|
||||
/* RTS is required to control the transmitter */
|
||||
if (!sport->have_rtscts && !sport->have_rtsgpio)
|
||||
rs485conf->flags &= ~SER_RS485_ENABLED;
|
||||
|
@ -1915,7 +1979,7 @@ static const struct uart_ops imx_uart_pops = {
|
|||
|
||||
static struct imx_port *imx_uart_ports[UART_NR];
|
||||
|
||||
#ifdef CONFIG_SERIAL_IMX_CONSOLE
|
||||
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
|
||||
static void imx_uart_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
@ -2112,39 +2176,6 @@ static struct console imx_uart_console = {
|
|||
|
||||
#define IMX_CONSOLE &imx_uart_console
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL)
|
||||
cpu_relax();
|
||||
|
||||
imx_uart_writel(sport, ch, URTX0);
|
||||
}
|
||||
|
||||
static void imx_uart_console_early_write(struct console *con, const char *s,
|
||||
unsigned count)
|
||||
{
|
||||
struct earlycon_device *dev = con->data;
|
||||
|
||||
uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
|
||||
}
|
||||
|
||||
static int __init
|
||||
imx_console_early_setup(struct earlycon_device *dev, const char *opt)
|
||||
{
|
||||
if (!dev->port.membase)
|
||||
return -ENODEV;
|
||||
|
||||
dev->con->write = imx_uart_console_early_write;
|
||||
|
||||
return 0;
|
||||
}
|
||||
OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
|
||||
OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define IMX_CONSOLE NULL
|
||||
#endif
|
||||
|
@ -2223,6 +2254,32 @@ static void imx_uart_probe_pdata(struct imx_port *sport,
|
|||
sport->have_rtscts = 1;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t)
|
||||
{
|
||||
struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
if (sport->tx_state == WAIT_AFTER_RTS)
|
||||
imx_uart_start_tx(&sport->port);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
|
||||
{
|
||||
struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
if (sport->tx_state == WAIT_AFTER_SEND)
|
||||
imx_uart_stop_tx(&sport->port);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static int imx_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_port *sport;
|
||||
|
@ -2369,6 +2426,11 @@ static int imx_uart_probe(struct platform_device *pdev)
|
|||
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
|
||||
hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
sport->trigger_start_tx.function = imx_trigger_start_tx;
|
||||
sport->trigger_stop_tx.function = imx_trigger_stop_tx;
|
||||
|
||||
/*
|
||||
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
|
||||
* chips only have one interrupt.
|
||||
|
@ -2406,9 +2468,6 @@ static int imx_uart_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* We need to initialize lock even for non-registered console */
|
||||
spin_lock_init(&sport->port.lock);
|
||||
|
||||
imx_uart_ports[sport->port.line] = sport;
|
||||
|
||||
platform_set_drvdata(pdev, sport);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2020 NXP
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define URTX0 0x40 /* Transmitter Register */
|
||||
#define UTS_TXFULL (1<<4) /* TxFIFO full */
|
||||
#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
|
||||
|
||||
static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
|
||||
cpu_relax();
|
||||
|
||||
writel_relaxed(ch, port->membase + URTX0);
|
||||
}
|
||||
|
||||
static void imx_uart_console_early_write(struct console *con, const char *s,
|
||||
unsigned count)
|
||||
{
|
||||
struct earlycon_device *dev = con->data;
|
||||
|
||||
uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
|
||||
}
|
||||
|
||||
static int __init
|
||||
imx_console_early_setup(struct earlycon_device *dev, const char *opt)
|
||||
{
|
||||
if (!dev->port.membase)
|
||||
return -ENODEV;
|
||||
|
||||
dev->con->write = imx_uart_console_early_write;
|
||||
|
||||
return 0;
|
||||
}
|
||||
OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
|
||||
OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
|
||||
|
||||
MODULE_AUTHOR("NXP");
|
||||
MODULE_DESCRIPTION("IMX earlycon driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "jsm.h"
|
||||
|
||||
MODULE_AUTHOR("Digi International, http://www.digi.com");
|
||||
MODULE_AUTHOR("Digi International, https://www.digi.com");
|
||||
MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("jsm");
|
||||
|
|
|
@ -538,7 +538,8 @@ static int __init kgdboc_earlycon_init(char *opt)
|
|||
|
||||
if (!con) {
|
||||
/*
|
||||
* Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets
|
||||
* Both earlycon and kgdboc_earlycon are initialized during
|
||||
* early parameter parsing. We cannot guarantee earlycon gets
|
||||
* in first and, in any case, on ACPI systems earlycon may
|
||||
* defer its own initialization (usually to somewhere within
|
||||
* setup_arch() ). To cope with either of these situations
|
||||
|
|
|
@ -696,6 +696,7 @@ static void msm_enable_ms(struct uart_port *port)
|
|||
}
|
||||
|
||||
static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
|
||||
__must_hold(&port->lock)
|
||||
{
|
||||
struct tty_port *tport = &port->state->port;
|
||||
unsigned int sr;
|
||||
|
@ -771,6 +772,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
|
|||
}
|
||||
|
||||
static void msm_handle_rx(struct uart_port *port)
|
||||
__must_hold(&port->lock)
|
||||
{
|
||||
struct tty_port *tport = &port->state->port;
|
||||
unsigned int sr;
|
||||
|
|
|
@ -1857,41 +1857,24 @@ static void pch_uart_pci_remove(struct pci_dev *pdev)
|
|||
kfree(priv);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_PM
|
||||
static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
||||
static int __maybe_unused pch_uart_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct eg20t_port *priv = pci_get_drvdata(pdev);
|
||||
struct eg20t_port *priv = dev_get_drvdata(dev);
|
||||
|
||||
uart_suspend_port(&pch_uart_driver, &priv->port);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pch_uart_pci_resume(struct pci_dev *pdev)
|
||||
static int __maybe_unused pch_uart_pci_resume(struct device *dev)
|
||||
{
|
||||
struct eg20t_port *priv = pci_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s-pci_enable_device failed(ret=%d) ", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
struct eg20t_port *priv = dev_get_drvdata(dev);
|
||||
|
||||
uart_resume_port(&pch_uart_driver, &priv->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pch_uart_pci_suspend NULL
|
||||
#define pch_uart_pci_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct pci_device_id pch_uart_pci_id[] = {
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
|
||||
|
@ -1945,13 +1928,16 @@ probe_error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(pch_uart_pci_pm_ops,
|
||||
pch_uart_pci_suspend,
|
||||
pch_uart_pci_resume);
|
||||
|
||||
static struct pci_driver pch_uart_pci_driver = {
|
||||
.name = "pch_uart",
|
||||
.id_table = pch_uart_pci_id,
|
||||
.probe = pch_uart_pci_probe,
|
||||
.remove = pch_uart_pci_remove,
|
||||
.suspend = pch_uart_pci_suspend,
|
||||
.resume = pch_uart_pci_resume,
|
||||
.driver.pm = &pch_uart_pci_pm_ops,
|
||||
};
|
||||
|
||||
static int __init pch_uart_module_init(void)
|
||||
|
|
|
@ -213,6 +213,7 @@ static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable)
|
|||
}
|
||||
|
||||
static bool pmz_receive_chars(struct uart_pmac_port *uap)
|
||||
__must_hold(&uap->port.lock)
|
||||
{
|
||||
struct tty_port *port;
|
||||
unsigned char ch, r1, drop, flag;
|
||||
|
|
|
@ -768,7 +768,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
|
|||
u8 buf[sizeof(u32)];
|
||||
int c;
|
||||
|
||||
memset(buf, 0, ARRAY_SIZE(buf));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD);
|
||||
|
||||
for (c = 0; c < tx_bytes ; c++) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* http://armlinux.simtec.co.uk/
|
||||
*/
|
||||
|
||||
/* Hote on 2410 error handling
|
||||
/* Note on 2410 error handling
|
||||
*
|
||||
* The s3c2410 manual has a love/hate affair with the contents of the
|
||||
* UERSTAT register in the UART blocks, and keeps marking some of the
|
||||
|
@ -327,7 +327,6 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
|
|||
unsigned long flags;
|
||||
int count;
|
||||
|
||||
|
||||
dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
|
||||
count = dma->tx_bytes_requested - state.residue;
|
||||
async_tx_ack(dma->tx_desc);
|
||||
|
@ -409,7 +408,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
|
|||
struct circ_buf *xmit = &port->state->xmit;
|
||||
struct s3c24xx_uart_dma *dma = ourport->dma;
|
||||
|
||||
|
||||
if (ourport->tx_mode != S3C24XX_TX_DMA)
|
||||
enable_tx_dma(ourport);
|
||||
|
||||
|
@ -816,7 +814,6 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
|
||||
{
|
||||
struct s3c24xx_uart_port *ourport = dev_id;
|
||||
|
@ -842,8 +839,8 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
|
|||
count >= ourport->min_dma_size) {
|
||||
int align = dma_get_cache_alignment() -
|
||||
(xmit->tail & (dma_get_cache_alignment() - 1));
|
||||
if (count-align >= ourport->min_dma_size) {
|
||||
dma_count = count-align;
|
||||
if (count - align >= ourport->min_dma_size) {
|
||||
dma_count = count - align;
|
||||
count = align;
|
||||
}
|
||||
}
|
||||
|
@ -1589,7 +1586,6 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
|
||||
|
||||
static struct console s3c24xx_serial_console;
|
||||
|
@ -1672,7 +1668,6 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
|
|||
}
|
||||
},
|
||||
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
|
||||
|
||||
[2] = {
|
||||
.port = {
|
||||
.lock = __PORT_LOCK_UNLOCKED(2),
|
||||
|
@ -1728,7 +1723,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
|
|||
udelay(1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ARM_S3C24XX_CPUFREQ
|
||||
|
||||
static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
|
||||
|
@ -1903,9 +1897,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|||
|
||||
port->mapbase = res->start;
|
||||
ret = platform_get_irq(platdev, 0);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
port->irq = 0;
|
||||
else {
|
||||
} else {
|
||||
port->irq = ret;
|
||||
ourport->rx_irq = ret;
|
||||
ourport->tx_irq = ret + 1;
|
||||
|
@ -1977,8 +1971,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[];
|
|||
|
||||
static int probe_index;
|
||||
|
||||
static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
|
||||
struct platform_device *pdev)
|
||||
static inline struct s3c24xx_serial_drv_data *
|
||||
s3c24xx_get_driver_data(struct platform_device *pdev)
|
||||
{
|
||||
#ifdef CONFIG_OF
|
||||
if (pdev->dev.of_node) {
|
||||
|
@ -2329,7 +2323,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
|
|||
*baud = rate / (16 * (ubrdiv + 1));
|
||||
dev_dbg(port->dev, "calculated baud %d\n", *baud);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int __init
|
||||
|
@ -2696,6 +2689,7 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device,
|
|||
device->port.private_data = &s3c2410_early_console_data;
|
||||
return samsung_early_console_setup(device, opt);
|
||||
}
|
||||
|
||||
OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
|
||||
s3c2410_early_console_setup);
|
||||
|
||||
|
@ -2710,6 +2704,7 @@ static int __init s3c2440_early_console_setup(struct earlycon_device *device,
|
|||
device->port.private_data = &s3c2440_early_console_data;
|
||||
return samsung_early_console_setup(device, opt);
|
||||
}
|
||||
|
||||
OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",
|
||||
s3c2440_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
|
||||
|
@ -2728,6 +2723,7 @@ static int __init s5pv210_early_console_setup(struct earlycon_device *device,
|
|||
device->port.private_data = &s5pv210_early_console_data;
|
||||
return samsung_early_console_setup(device, opt);
|
||||
}
|
||||
|
||||
OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
|
||||
s5pv210_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
|
||||
|
|
|
@ -439,16 +439,16 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup,
|
|||
/* Overrrun error */
|
||||
flag = TTY_OVERRUN;
|
||||
tup->uport.icount.overrun++;
|
||||
dev_err(tup->uport.dev, "Got overrun errors\n");
|
||||
dev_dbg(tup->uport.dev, "Got overrun errors\n");
|
||||
} else if (lsr & UART_LSR_PE) {
|
||||
/* Parity error */
|
||||
flag = TTY_PARITY;
|
||||
tup->uport.icount.parity++;
|
||||
dev_err(tup->uport.dev, "Got Parity errors\n");
|
||||
dev_dbg(tup->uport.dev, "Got Parity errors\n");
|
||||
} else if (lsr & UART_LSR_FE) {
|
||||
flag = TTY_FRAME;
|
||||
tup->uport.icount.frame++;
|
||||
dev_err(tup->uport.dev, "Got frame errors\n");
|
||||
dev_dbg(tup->uport.dev, "Got frame errors\n");
|
||||
} else if (lsr & UART_LSR_BI) {
|
||||
/*
|
||||
* Break error
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/sched/signal.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
@ -1120,7 +1121,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
|
||||
static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
|
||||
{
|
||||
struct tty_port *port = &state->port;
|
||||
struct uart_port *uport;
|
||||
|
@ -1523,6 +1524,7 @@ static void uart_set_termios(struct tty_struct *tty,
|
|||
/* Handle transition away from B0 status */
|
||||
else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
|
||||
unsigned int mask = TIOCM_DTR;
|
||||
|
||||
if (!(cflag & CRTSCTS) || !tty_throttled(tty))
|
||||
mask |= TIOCM_RTS;
|
||||
uart_set_mctrl(uport, mask);
|
||||
|
@ -2279,6 +2281,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
|
|||
if (console_suspend_enabled || !uart_console(uport)) {
|
||||
/* Protected by port mutex for now */
|
||||
struct tty_struct *tty = port->tty;
|
||||
|
||||
ret = ops->startup(uport);
|
||||
if (ret == 0) {
|
||||
if (tty)
|
||||
|
|
|
@ -3301,9 +3301,6 @@ static int sci_probe_single(struct platform_device *dev,
|
|||
sciport->port.flags |= UPF_HARD_FLOW;
|
||||
}
|
||||
|
||||
if (sci_uart_driver.cons->index == sciport->port.line)
|
||||
spin_lock_init(&sciport->port.lock);
|
||||
|
||||
ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
|
||||
if (ret) {
|
||||
sci_cleanup_single(sciport);
|
||||
|
|
|
@ -883,7 +883,6 @@ console_initcall(sifive_console_init);
|
|||
|
||||
static void __ssp_add_console_port(struct sifive_serial_port *ssp)
|
||||
{
|
||||
spin_lock_init(&ssp->port.lock);
|
||||
sifive_serial_console_ports[ssp->port.line] = ssp;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,9 +129,13 @@ static int stm32_config_rs485(struct uart_port *port,
|
|||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
cr3 &= ~USART_CR3_DEP;
|
||||
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl & ~TIOCM_RTS);
|
||||
} else {
|
||||
cr3 |= USART_CR3_DEP;
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl | TIOCM_RTS);
|
||||
}
|
||||
|
||||
writel_relaxed(cr3, port->membase + ofs->cr3);
|
||||
|
@ -847,9 +851,13 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
|
||||
cr3 &= ~USART_CR3_DEP;
|
||||
rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl & ~TIOCM_RTS);
|
||||
} else {
|
||||
cr3 |= USART_CR3_DEP;
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
mctrl_gpio_set(stm32_port->gpios,
|
||||
stm32_port->port.mctrl | TIOCM_RTS);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -1033,8 +1041,9 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
|
|||
if (WARN_ON(id >= STM32_MAX_PORTS))
|
||||
return NULL;
|
||||
|
||||
stm32_ports[id].hw_flow_control = of_property_read_bool(np,
|
||||
"st,hw-flow-ctrl");
|
||||
stm32_ports[id].hw_flow_control =
|
||||
of_property_read_bool (np, "st,hw-flow-ctrl") /*deprecated*/ ||
|
||||
of_property_read_bool (np, "uart-has-rtscts");
|
||||
stm32_ports[id].port.line = id;
|
||||
stm32_ports[id].cr1_irq = USART_CR1_RXNEIE;
|
||||
stm32_ports[id].cr3_irq = 0;
|
||||
|
|
|
@ -567,9 +567,6 @@ static int hv_probe(struct platform_device *op)
|
|||
sunserial_console_match(&sunhv_console, op->dev.of_node,
|
||||
&sunhv_reg, port->line, false);
|
||||
|
||||
/* We need to initialize lock even for non-registered console */
|
||||
spin_lock_init(&port->lock);
|
||||
|
||||
err = uart_add_one_port(&sunhv_reg, port);
|
||||
if (err)
|
||||
goto out_unregister_driver;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* Register definitions
|
||||
*
|
||||
* For register details see datasheet:
|
||||
* http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf
|
||||
* https://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf
|
||||
*/
|
||||
|
||||
#define ULITE_RX 0x00
|
||||
|
|
|
@ -252,7 +252,6 @@ struct mgsl_struct {
|
|||
|
||||
char device_name[25]; /* device instance name */
|
||||
|
||||
unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */
|
||||
unsigned char bus; /* expansion bus number (zero based) */
|
||||
unsigned char function; /* PCI device number */
|
||||
|
||||
|
@ -3432,15 +3431,9 @@ static inline void line_info(struct seq_file *m, struct mgsl_struct *info)
|
|||
char stat_buf[30];
|
||||
unsigned long flags;
|
||||
|
||||
if (info->bus_type == MGSL_BUS_TYPE_PCI) {
|
||||
seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
|
||||
info->device_name, info->io_base, info->irq_level,
|
||||
info->phys_memory_base, info->phys_lcr_base);
|
||||
} else {
|
||||
seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d",
|
||||
info->device_name, info->io_base,
|
||||
info->irq_level, info->dma_level);
|
||||
}
|
||||
seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
|
||||
info->device_name, info->io_base, info->irq_level,
|
||||
info->phys_memory_base, info->phys_lcr_base);
|
||||
|
||||
/* output current serial signal states */
|
||||
spin_lock_irqsave(&info->irq_spinlock,flags);
|
||||
|
@ -3556,54 +3549,27 @@ static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
|
|||
if ( info->max_frame_size % DMABUFFERSIZE )
|
||||
BuffersPerFrame++;
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
/*
|
||||
* The PCI adapter has 256KBytes of shared memory to use.
|
||||
* This is 64 PAGE_SIZE buffers.
|
||||
*
|
||||
* The first page is used for padding at this time so the
|
||||
* buffer list does not begin at offset 0 of the PCI
|
||||
* adapter's shared memory.
|
||||
*
|
||||
* The 2nd page is used for the buffer list. A 4K buffer
|
||||
* list can hold 128 DMA_BUFFER structures at 32 bytes
|
||||
* each.
|
||||
*
|
||||
* This leaves 62 4K pages.
|
||||
*
|
||||
* The next N pages are used for transmit frame(s). We
|
||||
* reserve enough 4K page blocks to hold the required
|
||||
* number of transmit dma buffers (num_tx_dma_buffers),
|
||||
* each of MaxFrameSize size.
|
||||
*
|
||||
* Of the remaining pages (62-N), determine how many can
|
||||
* be used to receive full MaxFrameSize inbound frames
|
||||
*/
|
||||
info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
|
||||
info->rx_buffer_count = 62 - info->tx_buffer_count;
|
||||
} else {
|
||||
/* Calculate the number of PAGE_SIZE buffers needed for */
|
||||
/* receive and transmit DMA buffers. */
|
||||
|
||||
|
||||
/* Calculate the number of DMA buffers necessary to */
|
||||
/* hold 7 max size receive frames and one max size transmit frame. */
|
||||
/* The receive buffer count is bumped by one so we avoid an */
|
||||
/* End of List condition if all receive buffers are used when */
|
||||
/* using linked list DMA buffers. */
|
||||
|
||||
info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
|
||||
info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
|
||||
|
||||
/*
|
||||
* limit total TxBuffers & RxBuffers to 62 4K total
|
||||
* (ala PCI Allocation)
|
||||
*/
|
||||
|
||||
if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 )
|
||||
info->rx_buffer_count = 62 - info->tx_buffer_count;
|
||||
|
||||
}
|
||||
/*
|
||||
* The PCI adapter has 256KBytes of shared memory to use. This is 64
|
||||
* PAGE_SIZE buffers.
|
||||
*
|
||||
* The first page is used for padding at this time so the buffer list
|
||||
* does not begin at offset 0 of the PCI adapter's shared memory.
|
||||
*
|
||||
* The 2nd page is used for the buffer list. A 4K buffer list can hold
|
||||
* 128 DMA_BUFFER structures at 32 bytes each.
|
||||
*
|
||||
* This leaves 62 4K pages.
|
||||
*
|
||||
* The next N pages are used for transmit frame(s). We reserve enough
|
||||
* 4K page blocks to hold the required number of transmit dma buffers
|
||||
* (num_tx_dma_buffers), each of MaxFrameSize size.
|
||||
*
|
||||
* Of the remaining pages (62-N), determine how many can be used to
|
||||
* receive full MaxFrameSize inbound frames
|
||||
*/
|
||||
info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
|
||||
info->rx_buffer_count = 62 - info->tx_buffer_count;
|
||||
|
||||
if ( debug_level >= DEBUG_LEVEL_INFO )
|
||||
printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",
|
||||
|
@ -3652,23 +3618,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
/* PCI adapter uses shared memory. */
|
||||
info->buffer_list = info->memory_base + info->last_mem_alloc;
|
||||
info->buffer_list_phys = info->last_mem_alloc;
|
||||
info->last_mem_alloc += BUFFERLISTSIZE;
|
||||
} else {
|
||||
/* ISA adapter uses system memory. */
|
||||
/* The buffer lists are allocated as a common buffer that both */
|
||||
/* the processor and adapter can access. This allows the driver to */
|
||||
/* inspect portions of the buffer while other portions are being */
|
||||
/* updated by the adapter using Bus Master DMA. */
|
||||
|
||||
info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL);
|
||||
if (info->buffer_list == NULL)
|
||||
return -ENOMEM;
|
||||
info->buffer_list_phys = (u32)(info->buffer_list_dma_addr);
|
||||
}
|
||||
/* PCI adapter uses shared memory. */
|
||||
info->buffer_list = info->memory_base + info->last_mem_alloc;
|
||||
info->buffer_list_phys = info->last_mem_alloc;
|
||||
info->last_mem_alloc += BUFFERLISTSIZE;
|
||||
|
||||
/* We got the memory for the buffer entry lists. */
|
||||
/* Initialize the memory block to all zeros. */
|
||||
|
@ -3734,9 +3687,6 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
|
|||
*/
|
||||
static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
|
||||
{
|
||||
if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI)
|
||||
dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr);
|
||||
|
||||
info->buffer_list = NULL;
|
||||
info->rx_buffer_list = NULL;
|
||||
info->tx_buffer_list = NULL;
|
||||
|
@ -3762,24 +3712,13 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
|
|||
static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
|
||||
{
|
||||
int i;
|
||||
u32 phys_addr;
|
||||
|
||||
/* Allocate page sized buffers for the receive buffer list */
|
||||
|
||||
for ( i = 0; i < Buffercount; i++ ) {
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
/* PCI adapter uses shared memory buffers. */
|
||||
BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
|
||||
phys_addr = info->last_mem_alloc;
|
||||
info->last_mem_alloc += DMABUFFERSIZE;
|
||||
} else {
|
||||
/* ISA adapter uses system memory. */
|
||||
BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL);
|
||||
if (BufferList[i].virt_addr == NULL)
|
||||
return -ENOMEM;
|
||||
phys_addr = (u32)(BufferList[i].dma_addr);
|
||||
}
|
||||
BufferList[i].phys_addr = phys_addr;
|
||||
BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
|
||||
BufferList[i].phys_addr = info->last_mem_alloc;
|
||||
info->last_mem_alloc += DMABUFFERSIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3807,8 +3746,6 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf
|
|||
if ( BufferList ) {
|
||||
for ( i = 0 ; i < Buffercount ; i++ ) {
|
||||
if ( BufferList[i].virt_addr ) {
|
||||
if ( info->bus_type != MGSL_BUS_TYPE_PCI )
|
||||
dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr);
|
||||
BufferList[i].virt_addr = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -4040,58 +3977,40 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
|
|||
}
|
||||
info->irq_requested = true;
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
|
||||
printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_memory_base);
|
||||
goto errout;
|
||||
}
|
||||
info->shared_mem_requested = true;
|
||||
if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
|
||||
printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
|
||||
goto errout;
|
||||
}
|
||||
info->lcr_mem_requested = true;
|
||||
|
||||
info->memory_base = ioremap(info->phys_memory_base,
|
||||
0x40000);
|
||||
if (!info->memory_base) {
|
||||
printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_memory_base );
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if ( !mgsl_memory_test(info) ) {
|
||||
printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_memory_base );
|
||||
goto errout;
|
||||
}
|
||||
|
||||
info->lcr_base = ioremap(info->phys_lcr_base,
|
||||
PAGE_SIZE);
|
||||
if (!info->lcr_base) {
|
||||
printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
|
||||
goto errout;
|
||||
}
|
||||
info->lcr_base += info->lcr_offset;
|
||||
|
||||
} else {
|
||||
/* claim DMA channel */
|
||||
|
||||
if (request_dma(info->dma_level,info->device_name) < 0){
|
||||
printk( "%s(%d):Can't request DMA channel on device %s DMA=%d\n",
|
||||
__FILE__,__LINE__,info->device_name, info->dma_level );
|
||||
goto errout;
|
||||
}
|
||||
info->dma_requested = true;
|
||||
|
||||
/* ISA adapter uses bus master DMA */
|
||||
set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
|
||||
enable_dma(info->dma_level);
|
||||
if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
|
||||
printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_memory_base);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
info->shared_mem_requested = true;
|
||||
if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
|
||||
printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
|
||||
goto errout;
|
||||
}
|
||||
info->lcr_mem_requested = true;
|
||||
|
||||
info->memory_base = ioremap(info->phys_memory_base, 0x40000);
|
||||
if (!info->memory_base) {
|
||||
printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_memory_base );
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if ( !mgsl_memory_test(info) ) {
|
||||
printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_memory_base );
|
||||
goto errout;
|
||||
}
|
||||
|
||||
info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE);
|
||||
if (!info->lcr_base) {
|
||||
printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n",
|
||||
__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
|
||||
goto errout;
|
||||
}
|
||||
info->lcr_base += info->lcr_offset;
|
||||
|
||||
if ( mgsl_allocate_dma_buffers(info) < 0 ) {
|
||||
printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n",
|
||||
__FILE__,__LINE__,info->device_name, info->dma_level );
|
||||
|
@ -4200,16 +4119,10 @@ static void mgsl_add_device( struct mgsl_struct *info )
|
|||
else if ( info->max_frame_size > 65535 )
|
||||
info->max_frame_size = 65535;
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
|
||||
info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
|
||||
info->phys_memory_base, info->phys_lcr_base,
|
||||
info->max_frame_size );
|
||||
} else {
|
||||
printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
|
||||
info->device_name, info->io_base, info->irq_level, info->dma_level,
|
||||
info->max_frame_size );
|
||||
}
|
||||
printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
|
||||
info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
|
||||
info->phys_memory_base, info->phys_lcr_base,
|
||||
info->max_frame_size );
|
||||
|
||||
#if SYNCLINK_GENERIC_HDLC
|
||||
hdlcdev_init(info);
|
||||
|
@ -4420,8 +4333,7 @@ static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
|
|||
outw( Cmd + info->loopback_bits, info->io_base + CCAR );
|
||||
|
||||
/* Read to flush write to CCAR */
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
inw( info->io_base + CCAR );
|
||||
inw( info->io_base + CCAR );
|
||||
|
||||
} /* end of usc_RTCmd() */
|
||||
|
||||
|
@ -4445,8 +4357,7 @@ static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
|
|||
outw( Cmd + info->mbre_bit, info->io_base );
|
||||
|
||||
/* Read to flush write to DCAR */
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
inw( info->io_base );
|
||||
inw( info->io_base );
|
||||
|
||||
} /* end of usc_DmaCmd() */
|
||||
|
||||
|
@ -4475,8 +4386,7 @@ static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
|
|||
outw( RegValue, info->io_base );
|
||||
|
||||
/* Read to flush write to DCAR */
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
inw( info->io_base );
|
||||
inw( info->io_base );
|
||||
|
||||
} /* end of usc_OutDmaReg() */
|
||||
|
||||
|
@ -4528,8 +4438,7 @@ static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
|
|||
outw( RegValue, info->io_base + CCAR );
|
||||
|
||||
/* Read to flush write to CCAR */
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
inw( info->io_base + CCAR );
|
||||
inw( info->io_base + CCAR );
|
||||
|
||||
} /* end of usc_OutReg() */
|
||||
|
||||
|
@ -4728,10 +4637,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
|
|||
|
||||
RegValue = usc_InReg( info, RICR ) & 0xc0;
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
|
||||
else
|
||||
usc_OutReg( info, RICR, (u16)(0x140a | RegValue) );
|
||||
usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
|
||||
|
||||
/* Unlatch all Rx status bits and clear Rx status IRQ Pending */
|
||||
|
||||
|
@ -4792,10 +4698,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
|
|||
* 0000 0000 0011 0110 = 0x0036
|
||||
*/
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
usc_OutReg( info, TICR, 0x0736 );
|
||||
else
|
||||
usc_OutReg( info, TICR, 0x1436 );
|
||||
usc_OutReg( info, TICR, 0x0736 );
|
||||
|
||||
usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
|
||||
usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
|
||||
|
@ -4885,10 +4788,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
|
|||
/* DPLL is enabled. Use BRG1 to provide continuous reference clock */
|
||||
/* for DPLL. DPLL mode in HCR is dependent on the encoding used. */
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
XtalSpeed = 11059200;
|
||||
else
|
||||
XtalSpeed = 14745600;
|
||||
XtalSpeed = 11059200;
|
||||
|
||||
if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
|
||||
DpllDivisor = 16;
|
||||
|
@ -5011,13 +4911,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
|
|||
* 0110 0000 0000 1011 = 0x600b
|
||||
*/
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
/* PCI adapter does not need DMA wait state */
|
||||
usc_OutDmaReg( info, DCR, 0xa00b );
|
||||
}
|
||||
else
|
||||
usc_OutDmaReg( info, DCR, 0x800b );
|
||||
|
||||
/* PCI adapter does not need DMA wait state */
|
||||
usc_OutDmaReg( info, DCR, 0xa00b );
|
||||
|
||||
/* Receive DMA mode Register (RDMR)
|
||||
*
|
||||
|
@ -5109,12 +5004,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
|
|||
* <7..0> 0x00 Maximum number of clock cycles per bus grant
|
||||
*/
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
/* don't limit bus occupancy on PCI adapter */
|
||||
usc_OutDmaReg( info, BDCR, 0x0000 );
|
||||
}
|
||||
else
|
||||
usc_OutDmaReg( info, BDCR, 0x2000 );
|
||||
/* don't limit bus occupancy on PCI adapter */
|
||||
usc_OutDmaReg( info, BDCR, 0x0000 );
|
||||
|
||||
usc_stop_transmitter(info);
|
||||
usc_stop_receiver(info);
|
||||
|
@ -5155,10 +5046,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable)
|
|||
/* Write 16-bit Time Constant for BRG0 */
|
||||
/* use clock speed if available, otherwise use 8 for diagnostics */
|
||||
if (info->params.clock_speed) {
|
||||
if (info->bus_type == MGSL_BUS_TYPE_PCI)
|
||||
usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
|
||||
else
|
||||
usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1));
|
||||
usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
|
||||
} else
|
||||
usc_OutReg(info, TC0R, (u16)8);
|
||||
|
||||
|
@ -5201,10 +5089,7 @@ static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
|
|||
u16 Tc;
|
||||
|
||||
if ( data_rate ) {
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
XtalSpeed = 11059200;
|
||||
else
|
||||
XtalSpeed = 14745600;
|
||||
XtalSpeed = 11059200;
|
||||
|
||||
|
||||
/* Tc = (Xtal/Speed) - 1 */
|
||||
|
@ -5682,44 +5567,38 @@ static void usc_load_txfifo( struct mgsl_struct *info )
|
|||
*/
|
||||
static void usc_reset( struct mgsl_struct *info )
|
||||
{
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
|
||||
int i;
|
||||
u32 readval;
|
||||
int i;
|
||||
u32 readval;
|
||||
|
||||
/* Set BIT30 of Misc Control Register */
|
||||
/* (Local Control Register 0x50) to force reset of USC. */
|
||||
/* Set BIT30 of Misc Control Register */
|
||||
/* (Local Control Register 0x50) to force reset of USC. */
|
||||
|
||||
volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
|
||||
u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);
|
||||
volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
|
||||
u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);
|
||||
|
||||
info->misc_ctrl_value |= BIT30;
|
||||
*MiscCtrl = info->misc_ctrl_value;
|
||||
info->misc_ctrl_value |= BIT30;
|
||||
*MiscCtrl = info->misc_ctrl_value;
|
||||
|
||||
/*
|
||||
* Force at least 170ns delay before clearing
|
||||
* reset bit. Each read from LCR takes at least
|
||||
* 30ns so 10 times for 300ns to be safe.
|
||||
*/
|
||||
for(i=0;i<10;i++)
|
||||
readval = *MiscCtrl;
|
||||
/*
|
||||
* Force at least 170ns delay before clearing reset bit. Each read from
|
||||
* LCR takes at least 30ns so 10 times for 300ns to be safe.
|
||||
*/
|
||||
for(i=0;i<10;i++)
|
||||
readval = *MiscCtrl;
|
||||
|
||||
info->misc_ctrl_value &= ~BIT30;
|
||||
*MiscCtrl = info->misc_ctrl_value;
|
||||
info->misc_ctrl_value &= ~BIT30;
|
||||
*MiscCtrl = info->misc_ctrl_value;
|
||||
|
||||
*LCR0BRDR = BUS_DESCRIPTOR(
|
||||
1, // Write Strobe Hold (0-3)
|
||||
2, // Write Strobe Delay (0-3)
|
||||
2, // Read Strobe Delay (0-3)
|
||||
0, // NWDD (Write data-data) (0-3)
|
||||
4, // NWAD (Write Addr-data) (0-31)
|
||||
0, // NXDA (Read/Write Data-Addr) (0-3)
|
||||
0, // NRDD (Read Data-Data) (0-3)
|
||||
5 // NRAD (Read Addr-Data) (0-31)
|
||||
);
|
||||
} else {
|
||||
/* do HW reset */
|
||||
outb( 0,info->io_base + 8 );
|
||||
}
|
||||
*LCR0BRDR = BUS_DESCRIPTOR(
|
||||
1, // Write Strobe Hold (0-3)
|
||||
2, // Write Strobe Delay (0-3)
|
||||
2, // Read Strobe Delay (0-3)
|
||||
0, // NWDD (Write data-data) (0-3)
|
||||
4, // NWAD (Write Addr-data) (0-31)
|
||||
0, // NXDA (Read/Write Data-Addr) (0-3)
|
||||
0, // NRDD (Read Data-Data) (0-3)
|
||||
5 // NRAD (Read Addr-Data) (0-31)
|
||||
);
|
||||
|
||||
info->mbre_bit = 0;
|
||||
info->loopback_bits = 0;
|
||||
|
@ -6228,11 +6107,7 @@ static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
|
|||
* ClkSpeed = 921600 (ISA), 691200 (PCI)
|
||||
*/
|
||||
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
|
||||
else
|
||||
usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) );
|
||||
|
||||
usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
|
||||
|
||||
/*
|
||||
* Hardware Configuration Register (HCR)
|
||||
|
@ -6837,10 +6712,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
|
|||
|
||||
/* Actually copy data from source buffer to DMA buffer. */
|
||||
/* Also set the data count for this individual DMA buffer. */
|
||||
if ( info->bus_type == MGSL_BUS_TYPE_PCI )
|
||||
mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
|
||||
else
|
||||
memcpy(pBufEntry->virt_addr, Buffer, Copycount);
|
||||
mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
|
||||
|
||||
pBufEntry->count = Copycount;
|
||||
|
||||
|
@ -7315,9 +7187,6 @@ static bool mgsl_memory_test( struct mgsl_struct *info )
|
|||
unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
|
||||
unsigned long * TestAddr;
|
||||
|
||||
if ( info->bus_type != MGSL_BUS_TYPE_PCI )
|
||||
return true;
|
||||
|
||||
TestAddr = (unsigned long *)info->memory_base;
|
||||
|
||||
/* Test data lines with test pattern at one location. */
|
||||
|
@ -8003,7 +7872,6 @@ static int synclink_init_one (struct pci_dev *dev,
|
|||
info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1);
|
||||
info->phys_lcr_base &= ~(PAGE_SIZE-1);
|
||||
|
||||
info->bus_type = MGSL_BUS_TYPE_PCI;
|
||||
info->io_addr_size = 8;
|
||||
info->irq_flags = IRQF_SHARED;
|
||||
|
||||
|
|
|
@ -1405,7 +1405,7 @@ void tty_save_termios(struct tty_struct *tty)
|
|||
/* Stash the termios data */
|
||||
tp = tty->driver->termios[idx];
|
||||
if (tp == NULL) {
|
||||
tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
|
||||
tp = kmalloc(sizeof(*tp), GFP_KERNEL);
|
||||
if (tp == NULL)
|
||||
return;
|
||||
tty->driver->termios[idx] = tp;
|
||||
|
@ -2489,7 +2489,7 @@ static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *
|
|||
struct serial_struct v;
|
||||
int flags;
|
||||
|
||||
if (copy_from_user(&v, ss, sizeof(struct serial_struct)))
|
||||
if (copy_from_user(&v, ss, sizeof(*ss)))
|
||||
return -EFAULT;
|
||||
|
||||
flags = v.flags & ASYNC_DEPRECATED;
|
||||
|
@ -2507,11 +2507,11 @@ static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user *
|
|||
struct serial_struct v;
|
||||
int err;
|
||||
|
||||
memset(&v, 0, sizeof(struct serial_struct));
|
||||
memset(&v, 0, sizeof(v));
|
||||
if (!tty->ops->get_serial)
|
||||
return -ENOTTY;
|
||||
err = tty->ops->get_serial(tty, &v);
|
||||
if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct)))
|
||||
if (!err && copy_to_user(ss, &v, sizeof(v)))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
}
|
||||
|
@ -2673,25 +2673,25 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
#ifdef CONFIG_COMPAT
|
||||
|
||||
struct serial_struct32 {
|
||||
compat_int_t type;
|
||||
compat_int_t line;
|
||||
compat_uint_t port;
|
||||
compat_int_t irq;
|
||||
compat_int_t flags;
|
||||
compat_int_t xmit_fifo_size;
|
||||
compat_int_t custom_divisor;
|
||||
compat_int_t baud_base;
|
||||
unsigned short close_delay;
|
||||
char io_type;
|
||||
char reserved_char[1];
|
||||
compat_int_t hub6;
|
||||
unsigned short closing_wait; /* time to wait before closing */
|
||||
unsigned short closing_wait2; /* no longer used... */
|
||||
compat_uint_t iomem_base;
|
||||
unsigned short iomem_reg_shift;
|
||||
unsigned int port_high;
|
||||
/* compat_ulong_t iomap_base FIXME */
|
||||
compat_int_t reserved[1];
|
||||
compat_int_t type;
|
||||
compat_int_t line;
|
||||
compat_uint_t port;
|
||||
compat_int_t irq;
|
||||
compat_int_t flags;
|
||||
compat_int_t xmit_fifo_size;
|
||||
compat_int_t custom_divisor;
|
||||
compat_int_t baud_base;
|
||||
unsigned short close_delay;
|
||||
char io_type;
|
||||
char reserved_char;
|
||||
compat_int_t hub6;
|
||||
unsigned short closing_wait; /* time to wait before closing */
|
||||
unsigned short closing_wait2; /* no longer used... */
|
||||
compat_uint_t iomem_base;
|
||||
unsigned short iomem_reg_shift;
|
||||
unsigned int port_high;
|
||||
/* compat_ulong_t iomap_base FIXME */
|
||||
compat_int_t reserved;
|
||||
};
|
||||
|
||||
static int compat_tty_tiocsserial(struct tty_struct *tty,
|
||||
|
@ -2705,7 +2705,7 @@ static int compat_tty_tiocsserial(struct tty_struct *tty,
|
|||
struct serial_struct v;
|
||||
int flags;
|
||||
|
||||
if (copy_from_user(&v32, ss, sizeof(struct serial_struct32)))
|
||||
if (copy_from_user(&v32, ss, sizeof(*ss)))
|
||||
return -EFAULT;
|
||||
|
||||
memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base));
|
||||
|
@ -2743,7 +2743,7 @@ static int compat_tty_tiocgserial(struct tty_struct *tty,
|
|||
0xfffffff : ptr_to_compat(v.iomem_base);
|
||||
v32.iomem_reg_shift = v.iomem_reg_shift;
|
||||
v32.port_high = v.port_high;
|
||||
if (copy_to_user(ss, &v32, sizeof(struct serial_struct32)))
|
||||
if (copy_to_user(ss, &v32, sizeof(v32)))
|
||||
err = -EFAULT;
|
||||
}
|
||||
return err;
|
||||
|
@ -3215,7 +3215,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
|
|||
if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
|
||||
driver = kzalloc(sizeof(*driver), GFP_KERNEL);
|
||||
if (!driver)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
|
@ -542,7 +542,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
|||
if (!ct)
|
||||
return 0;
|
||||
|
||||
unilist = vmemdup_user(list, ct * sizeof(struct unipair));
|
||||
unilist = vmemdup_user(list, array_size(sizeof(struct unipair), ct));
|
||||
if (IS_ERR(unilist))
|
||||
return PTR_ERR(unilist);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -2019,7 +2020,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|||
goto reterr;
|
||||
}
|
||||
kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
|
||||
i = kbs->kb_func;
|
||||
i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
|
||||
|
||||
switch (cmd) {
|
||||
case KDGKBSENT:
|
||||
|
|
|
@ -193,7 +193,7 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
|
|||
/* Allocate a new buffer before freeing the old one ... */
|
||||
/* chars can take up to 4 bytes with unicode */
|
||||
bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
|
||||
GFP_KERNEL);
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!bp) {
|
||||
printk(KERN_WARNING "selection: kmalloc() failed\n");
|
||||
clear_selection();
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -302,14 +302,15 @@ sisusbcon_deinit(struct vc_data *c)
|
|||
|
||||
/* interface routine */
|
||||
static u8
|
||||
sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
||||
u8 blink, u8 underline, u8 reverse, u8 unused)
|
||||
sisusbcon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity,
|
||||
bool blink, bool underline, bool reverse,
|
||||
bool unused)
|
||||
{
|
||||
u8 attr = color;
|
||||
|
||||
if (underline)
|
||||
attr = (attr & 0xf0) | c->vc_ulcolor;
|
||||
else if (intensity == 0)
|
||||
else if (intensity == VCI_HALF_BRIGHT)
|
||||
attr = (attr & 0xf0) | c->vc_halfcolor;
|
||||
|
||||
if (reverse)
|
||||
|
@ -320,7 +321,7 @@ sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
|||
if (blink)
|
||||
attr ^= 0x80;
|
||||
|
||||
if (intensity == 2)
|
||||
if (intensity == VCI_BOLD)
|
||||
attr ^= 0x08;
|
||||
|
||||
return attr;
|
||||
|
@ -726,7 +727,7 @@ sisusbcon_cursor(struct vc_data *c, int mode)
|
|||
|
||||
baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
|
||||
|
||||
switch (c->vc_cursor_type & 0x0f) {
|
||||
switch (CUR_SIZE(c->vc_cursor_type)) {
|
||||
case CUR_BLOCK: from = 1;
|
||||
to = c->vc_font.height;
|
||||
break;
|
||||
|
|
|
@ -394,8 +394,10 @@ static inline u16 mda_convert_attr(u16 ch)
|
|||
(ch & 0x00ff) | attr;
|
||||
}
|
||||
|
||||
static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
||||
u8 blink, u8 underline, u8 reverse, u8 italic)
|
||||
static u8 mdacon_build_attr(struct vc_data *c, u8 color,
|
||||
enum vc_intensity intensity,
|
||||
bool blink, bool underline, bool reverse,
|
||||
bool italic)
|
||||
{
|
||||
/* The attribute is just a bit vector:
|
||||
*
|
||||
|
@ -405,11 +407,11 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
|||
* Bit 7 : blink
|
||||
*/
|
||||
|
||||
return (intensity & 3) |
|
||||
((underline & 1) << 2) |
|
||||
((reverse & 1) << 3) |
|
||||
(!!italic << 4) |
|
||||
((blink & 1) << 7);
|
||||
return (intensity & VCI_MASK) |
|
||||
(underline << 2) |
|
||||
(reverse << 3) |
|
||||
(italic << 4) |
|
||||
(blink << 7);
|
||||
}
|
||||
|
||||
static void mdacon_invert_region(struct vc_data *c, u16 *p, int count)
|
||||
|
@ -488,9 +490,9 @@ static void mdacon_cursor(struct vc_data *c, int mode)
|
|||
return;
|
||||
}
|
||||
|
||||
mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2);
|
||||
mda_set_cursor(c->state.y * mda_num_columns * 2 + c->state.x * 2);
|
||||
|
||||
switch (c->vc_cursor_type & 0x0f) {
|
||||
switch (CUR_SIZE(c->vc_cursor_type)) {
|
||||
|
||||
case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break;
|
||||
case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break;
|
||||
|
|
|
@ -362,12 +362,12 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
|
|||
|
||||
if (ystart < yend) {
|
||||
newport_clear_screen(sx << 3, ystart, xend, yend,
|
||||
(vc->vc_color & 0xf0) >> 4);
|
||||
(vc->state.color & 0xf0) >> 4);
|
||||
} else {
|
||||
newport_clear_screen(sx << 3, ystart, xend, 1023,
|
||||
(vc->vc_color & 0xf0) >> 4);
|
||||
(vc->state.color & 0xf0) >> 4);
|
||||
newport_clear_screen(sx << 3, 0, xend, yend,
|
||||
(vc->vc_color & 0xf0) >> 4);
|
||||
(vc->state.color & 0xf0) >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,11 +591,11 @@ static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
|||
topscan = (topscan + (lines << 4)) & 0x3ff;
|
||||
newport_clear_lines(vc->vc_rows - lines,
|
||||
vc->vc_rows - 1,
|
||||
(vc->vc_color & 0xf0) >> 4);
|
||||
(vc->state.color & 0xf0) >> 4);
|
||||
} else {
|
||||
topscan = (topscan + (-lines << 4)) & 0x3ff;
|
||||
newport_clear_lines(0, lines - 1,
|
||||
(vc->vc_color & 0xf0) >> 4);
|
||||
(vc->state.color & 0xf0) >> 4);
|
||||
}
|
||||
npregs->cset.topscan = (topscan - 1) & 0x3ff;
|
||||
return false;
|
||||
|
|
|
@ -132,21 +132,21 @@ static void sticon_cursor(struct vc_data *conp, int mode)
|
|||
{
|
||||
unsigned short car1;
|
||||
|
||||
car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols];
|
||||
car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
|
||||
switch (mode) {
|
||||
case CM_ERASE:
|
||||
sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x);
|
||||
sti_putc(sticon_sti, car1, conp->state.y, conp->state.x);
|
||||
break;
|
||||
case CM_MOVE:
|
||||
case CM_DRAW:
|
||||
switch (conp->vc_cursor_type & 0x0f) {
|
||||
switch (CUR_SIZE(conp->vc_cursor_type)) {
|
||||
case CUR_UNDERLINE:
|
||||
case CUR_LOWER_THIRD:
|
||||
case CUR_LOWER_HALF:
|
||||
case CUR_TWO_THIRDS:
|
||||
case CUR_BLOCK:
|
||||
sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
|
||||
conp->vc_y, conp->vc_x);
|
||||
conp->state.y, conp->state.x);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -288,8 +288,10 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens,
|
||||
u8 blink, u8 underline, u8 reverse, u8 italic)
|
||||
static u8 sticon_build_attr(struct vc_data *conp, u8 color,
|
||||
enum vc_intensity intens,
|
||||
bool blink, bool underline, bool reverse,
|
||||
bool italic)
|
||||
{
|
||||
u8 attr = ((color & 0x70) >> 1) | ((color & 7));
|
||||
|
||||
|
|
|
@ -251,6 +251,10 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
|
|||
p = (void *) (c->vc_origin + t * c->vc_size_row);
|
||||
|
||||
while (count--) {
|
||||
if ((vgacon_scrollback_cur->tail + c->vc_size_row) >
|
||||
vgacon_scrollback_cur->size)
|
||||
vgacon_scrollback_cur->tail = 0;
|
||||
|
||||
scr_memcpyw(vgacon_scrollback_cur->data +
|
||||
vgacon_scrollback_cur->tail,
|
||||
p, c->vc_size_row);
|
||||
|
@ -629,8 +633,10 @@ static void vgacon_deinit(struct vc_data *c)
|
|||
con_set_default_unimap(c);
|
||||
}
|
||||
|
||||
static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
||||
u8 blink, u8 underline, u8 reverse, u8 italic)
|
||||
static u8 vgacon_build_attr(struct vc_data *c, u8 color,
|
||||
enum vc_intensity intensity,
|
||||
bool blink, bool underline, bool reverse,
|
||||
bool italic)
|
||||
{
|
||||
u8 attr = color;
|
||||
|
||||
|
@ -639,7 +645,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
|||
attr = (attr & 0xF0) | c->vc_itcolor;
|
||||
else if (underline)
|
||||
attr = (attr & 0xf0) | c->vc_ulcolor;
|
||||
else if (intensity == 0)
|
||||
else if (intensity == VCI_HALF_BRIGHT)
|
||||
attr = (attr & 0xf0) | c->vc_halfcolor;
|
||||
}
|
||||
if (reverse)
|
||||
|
@ -648,14 +654,14 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
|
|||
0x77);
|
||||
if (blink)
|
||||
attr ^= 0x80;
|
||||
if (intensity == 2)
|
||||
if (intensity == VCI_BOLD)
|
||||
attr ^= 0x08;
|
||||
if (!vga_can_do_color) {
|
||||
if (italic)
|
||||
attr = (attr & 0xF8) | 0x02;
|
||||
else if (underline)
|
||||
attr = (attr & 0xf8) | 0x01;
|
||||
else if (intensity == 0)
|
||||
else if (intensity == VCI_HALF_BRIGHT)
|
||||
attr = (attr & 0xf0) | 0x08;
|
||||
}
|
||||
return attr;
|
||||
|
@ -718,17 +724,17 @@ static void vgacon_cursor(struct vc_data *c, int mode)
|
|||
case CM_ERASE:
|
||||
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
|
||||
if (vga_video_type >= VIDEO_TYPE_VGAC)
|
||||
vgacon_set_cursor_size(c->vc_x, 31, 30);
|
||||
vgacon_set_cursor_size(c->state.x, 31, 30);
|
||||
else
|
||||
vgacon_set_cursor_size(c->vc_x, 31, 31);
|
||||
vgacon_set_cursor_size(c->state.x, 31, 31);
|
||||
break;
|
||||
|
||||
case CM_MOVE:
|
||||
case CM_DRAW:
|
||||
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
|
||||
switch (c->vc_cursor_type & 0x0f) {
|
||||
switch (CUR_SIZE(c->vc_cursor_type)) {
|
||||
case CUR_UNDERLINE:
|
||||
vgacon_set_cursor_size(c->vc_x,
|
||||
vgacon_set_cursor_size(c->state.x,
|
||||
c->vc_font.height -
|
||||
(c->vc_font.height <
|
||||
10 ? 2 : 3),
|
||||
|
@ -737,21 +743,21 @@ static void vgacon_cursor(struct vc_data *c, int mode)
|
|||
10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_TWO_THIRDS:
|
||||
vgacon_set_cursor_size(c->vc_x,
|
||||
vgacon_set_cursor_size(c->state.x,
|
||||
c->vc_font.height / 3,
|
||||
c->vc_font.height -
|
||||
(c->vc_font.height <
|
||||
10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_LOWER_THIRD:
|
||||
vgacon_set_cursor_size(c->vc_x,
|
||||
vgacon_set_cursor_size(c->state.x,
|
||||
(c->vc_font.height * 2) / 3,
|
||||
c->vc_font.height -
|
||||
(c->vc_font.height <
|
||||
10 ? 1 : 2));
|
||||
break;
|
||||
case CUR_LOWER_HALF:
|
||||
vgacon_set_cursor_size(c->vc_x,
|
||||
vgacon_set_cursor_size(c->state.x,
|
||||
c->vc_font.height / 2,
|
||||
c->vc_font.height -
|
||||
(c->vc_font.height <
|
||||
|
@ -759,12 +765,12 @@ static void vgacon_cursor(struct vc_data *c, int mode)
|
|||
break;
|
||||
case CUR_NONE:
|
||||
if (vga_video_type >= VIDEO_TYPE_VGAC)
|
||||
vgacon_set_cursor_size(c->vc_x, 31, 30);
|
||||
vgacon_set_cursor_size(c->state.x, 31, 30);
|
||||
else
|
||||
vgacon_set_cursor_size(c->vc_x, 31, 31);
|
||||
vgacon_set_cursor_size(c->state.x, 31, 31);
|
||||
break;
|
||||
default:
|
||||
vgacon_set_cursor_size(c->vc_x, 1,
|
||||
vgacon_set_cursor_size(c->state.x, 1,
|
||||
c->vc_font.height);
|
||||
break;
|
||||
}
|
||||
|
@ -1352,8 +1358,8 @@ static void vgacon_save_screen(struct vc_data *c)
|
|||
* console initialization routines.
|
||||
*/
|
||||
vga_bootup_console = 1;
|
||||
c->vc_x = screen_info.orig_x;
|
||||
c->vc_y = screen_info.orig_y;
|
||||
c->state.x = screen_info.orig_x;
|
||||
c->state.y = screen_info.orig_y;
|
||||
}
|
||||
|
||||
/* We can't copy in more than the size of the video buffer,
|
||||
|
|
|
@ -240,8 +240,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
|
||||
int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
|
||||
int y = real_y(ops->p, vc->vc_y);
|
||||
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
|
||||
int y = real_y(ops->p, vc->state.y);
|
||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
||||
int err = 1;
|
||||
char *src;
|
||||
|
||||
|
@ -286,10 +286,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
cursor.set |= FB_CUR_SETCMAP;
|
||||
}
|
||||
|
||||
if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) ||
|
||||
if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
|
||||
(ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||
|
||||
ops->cursor_reset) {
|
||||
ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x;
|
||||
ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
|
||||
ops->cursor_state.image.dy = vc->vc_font.height * y;
|
||||
cursor.set |= FB_CUR_SETPOS;
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
ops->p->cursor_shape = vc->vc_cursor_type;
|
||||
cursor.set |= FB_CUR_SETSHAPE;
|
||||
|
||||
switch (ops->p->cursor_shape & CUR_HWMASK) {
|
||||
switch (CUR_SIZE(ops->p->cursor_shape)) {
|
||||
case CUR_NONE:
|
||||
cur_height = 0;
|
||||
break;
|
||||
|
|
|
@ -655,11 +655,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
|
|||
}
|
||||
if (!save) {
|
||||
int lines;
|
||||
if (vc->vc_y + logo_lines >= rows)
|
||||
lines = rows - vc->vc_y - 1;
|
||||
if (vc->state.y + logo_lines >= rows)
|
||||
lines = rows - vc->state.y - 1;
|
||||
else
|
||||
lines = logo_lines;
|
||||
vc->vc_y += lines;
|
||||
vc->state.y += lines;
|
||||
vc->vc_pos += lines * vc->vc_size_row;
|
||||
}
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
|
|||
vc->vc_size_row *
|
||||
rows);
|
||||
scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2));
|
||||
vc->vc_y += logo_lines;
|
||||
vc->state.y += logo_lines;
|
||||
vc->vc_pos += logo_lines * vc->vc_size_row;
|
||||
kfree(save);
|
||||
}
|
||||
|
@ -1393,7 +1393,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
|||
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
|
||||
return;
|
||||
|
||||
if (vc->vc_cursor_type & 0x10)
|
||||
if (vc->vc_cursor_type & CUR_SW)
|
||||
fbcon_del_cursor_timer(info);
|
||||
else
|
||||
fbcon_add_cursor_timer(info);
|
||||
|
|
|
@ -225,8 +225,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
|
||||
int w = (vc->vc_font.height + 7) >> 3, c;
|
||||
int y = real_y(ops->p, vc->vc_y);
|
||||
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
|
||||
int y = real_y(ops->p, vc->state.y);
|
||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
||||
int err = 1, dx, dy;
|
||||
char *src;
|
||||
u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
||||
|
@ -284,7 +284,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
}
|
||||
|
||||
dx = y * vc->vc_font.height;
|
||||
dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width);
|
||||
dy = vyres - ((vc->state.x + 1) * vc->vc_font.width);
|
||||
|
||||
if (ops->cursor_state.image.dx != dx ||
|
||||
ops->cursor_state.image.dy != dy ||
|
||||
|
@ -325,7 +325,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
ops->p->cursor_shape = vc->vc_cursor_type;
|
||||
cursor.set |= FB_CUR_SETSHAPE;
|
||||
|
||||
switch (ops->p->cursor_shape & CUR_HWMASK) {
|
||||
switch (CUR_SIZE(ops->p->cursor_shape)) {
|
||||
case CUR_NONE:
|
||||
cur_height = 0;
|
||||
break;
|
||||
|
|
|
@ -208,8 +208,8 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
|
||||
int w = (vc->vc_font.height + 7) >> 3, c;
|
||||
int y = real_y(ops->p, vc->vc_y);
|
||||
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
|
||||
int y = real_y(ops->p, vc->state.y);
|
||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
||||
int err = 1, dx, dy;
|
||||
char *src;
|
||||
u32 vxres = GETVXRES(ops->p->scrollmode, info);
|
||||
|
@ -267,7 +267,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
}
|
||||
|
||||
dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height);
|
||||
dy = vc->vc_x * vc->vc_font.width;
|
||||
dy = vc->state.x * vc->vc_font.width;
|
||||
|
||||
if (ops->cursor_state.image.dx != dx ||
|
||||
ops->cursor_state.image.dy != dy ||
|
||||
|
@ -308,7 +308,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
ops->p->cursor_shape = vc->vc_cursor_type;
|
||||
cursor.set |= FB_CUR_SETSHAPE;
|
||||
|
||||
switch (ops->p->cursor_shape & CUR_HWMASK) {
|
||||
switch (CUR_SIZE(ops->p->cursor_shape)) {
|
||||
case CUR_NONE:
|
||||
cur_height = 0;
|
||||
break;
|
||||
|
|
|
@ -255,8 +255,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
|
||||
int w = (vc->vc_font.width + 7) >> 3, c;
|
||||
int y = real_y(ops->p, vc->vc_y);
|
||||
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
|
||||
int y = real_y(ops->p, vc->state.y);
|
||||
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
|
||||
int err = 1, dx, dy;
|
||||
char *src;
|
||||
u32 vyres = GETVYRES(ops->p->scrollmode, info);
|
||||
|
@ -315,7 +315,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
}
|
||||
|
||||
dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height);
|
||||
dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width);
|
||||
dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width);
|
||||
|
||||
if (ops->cursor_state.image.dx != dx ||
|
||||
ops->cursor_state.image.dy != dy ||
|
||||
|
@ -348,7 +348,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
ops->p->cursor_shape = vc->vc_cursor_type;
|
||||
cursor.set |= FB_CUR_SETSHAPE;
|
||||
|
||||
switch (ops->p->cursor_shape & CUR_HWMASK) {
|
||||
switch (CUR_SIZE(ops->p->cursor_shape)) {
|
||||
case CUR_NONE:
|
||||
cur_height = 0;
|
||||
break;
|
||||
|
|
|
@ -83,10 +83,10 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
|||
int softback_lines, int fg, int bg)
|
||||
{
|
||||
struct fb_tilecursor cursor;
|
||||
int use_sw = (vc->vc_cursor_type & 0x10);
|
||||
int use_sw = vc->vc_cursor_type & CUR_SW;
|
||||
|
||||
cursor.sx = vc->vc_x;
|
||||
cursor.sy = vc->vc_y;
|
||||
cursor.sx = vc->state.x;
|
||||
cursor.sy = vc->state.y;
|
||||
cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
|
||||
cursor.fg = fg;
|
||||
cursor.bg = bg;
|
||||
|
|
|
@ -24,17 +24,13 @@ struct module;
|
|||
struct tty_struct;
|
||||
struct notifier_block;
|
||||
|
||||
/*
|
||||
* this is what the terminal answers to a ESC-Z or csi0c query.
|
||||
*/
|
||||
#define VT100ID "\033[?1;2c"
|
||||
#define VT102ID "\033[?6c"
|
||||
|
||||
enum con_scroll {
|
||||
SM_UP,
|
||||
SM_DOWN,
|
||||
};
|
||||
|
||||
enum vc_intensity;
|
||||
|
||||
/**
|
||||
* struct consw - callbacks for consoles
|
||||
*
|
||||
|
@ -74,8 +70,9 @@ struct consw {
|
|||
void (*con_scrolldelta)(struct vc_data *vc, int lines);
|
||||
int (*con_set_origin)(struct vc_data *vc);
|
||||
void (*con_save_screen)(struct vc_data *vc);
|
||||
u8 (*con_build_attr)(struct vc_data *vc, u8 color, u8 intensity,
|
||||
u8 blink, u8 underline, u8 reverse, u8 italic);
|
||||
u8 (*con_build_attr)(struct vc_data *vc, u8 color,
|
||||
enum vc_intensity intensity,
|
||||
bool blink, bool underline, bool reverse, bool italic);
|
||||
void (*con_invert_region)(struct vc_data *vc, u16 *p, int count);
|
||||
u16 *(*con_screen_pos)(struct vc_data *vc, int offset);
|
||||
unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position,
|
||||
|
|
|
@ -21,6 +21,43 @@ struct uni_pagedir;
|
|||
struct uni_screen;
|
||||
|
||||
#define NPAR 16
|
||||
#define VC_TABSTOPS_COUNT 256U
|
||||
|
||||
enum vc_intensity {
|
||||
VCI_HALF_BRIGHT,
|
||||
VCI_NORMAL,
|
||||
VCI_BOLD,
|
||||
VCI_MASK = 0x3,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct vc_state -- state of a VC
|
||||
* @x: cursor's x-position
|
||||
* @y: cursor's y-position
|
||||
* @color: foreground & background colors
|
||||
* @Gx_charset: what's G0/G1 slot set to (like GRAF_MAP, LAT1_MAP)
|
||||
* @charset: what character set to use (0=G0 or 1=G1)
|
||||
* @intensity: see enum vc_intensity for values
|
||||
* @reverse: reversed foreground/background colors
|
||||
*
|
||||
* These members are defined separately from struct vc_data as we save &
|
||||
* restore them at times.
|
||||
*/
|
||||
struct vc_state {
|
||||
unsigned int x, y;
|
||||
|
||||
unsigned char color;
|
||||
|
||||
unsigned char Gx_charset[2];
|
||||
unsigned int charset : 1;
|
||||
|
||||
/* attribute flags */
|
||||
enum vc_intensity intensity;
|
||||
bool italic;
|
||||
bool underline;
|
||||
bool blink;
|
||||
bool reverse;
|
||||
};
|
||||
|
||||
/*
|
||||
* Example: vc_data of a console that was scrolled 3 lines down.
|
||||
|
@ -57,6 +94,8 @@ struct uni_screen;
|
|||
struct vc_data {
|
||||
struct tty_port port; /* Upper level data */
|
||||
|
||||
struct vc_state state, saved_state;
|
||||
|
||||
unsigned short vc_num; /* Console number */
|
||||
unsigned int vc_cols; /* [#] Console size */
|
||||
unsigned int vc_rows;
|
||||
|
@ -73,8 +112,6 @@ struct vc_data {
|
|||
/* attributes for all characters on screen */
|
||||
unsigned char vc_attr; /* Current attributes */
|
||||
unsigned char vc_def_color; /* Default colors */
|
||||
unsigned char vc_color; /* Foreground & background */
|
||||
unsigned char vc_s_color; /* Saved foreground & background */
|
||||
unsigned char vc_ulcolor; /* Color for underline mode */
|
||||
unsigned char vc_itcolor;
|
||||
unsigned char vc_halfcolor; /* Color for half intensity mode */
|
||||
|
@ -82,8 +119,6 @@ struct vc_data {
|
|||
unsigned int vc_cursor_type;
|
||||
unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */
|
||||
unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
|
||||
unsigned int vc_x, vc_y; /* Cursor position */
|
||||
unsigned int vc_saved_x, vc_saved_y;
|
||||
unsigned long vc_pos; /* Cursor address */
|
||||
/* fonts */
|
||||
unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
|
||||
|
@ -98,8 +133,6 @@ struct vc_data {
|
|||
int vt_newvt;
|
||||
wait_queue_head_t paste_wait;
|
||||
/* mode flags */
|
||||
unsigned int vc_charset : 1; /* Character set G0 / G1 */
|
||||
unsigned int vc_s_charset : 1; /* Saved character set */
|
||||
unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */
|
||||
unsigned int vc_toggle_meta : 1; /* Toggle high bit? */
|
||||
unsigned int vc_decscnm : 1; /* Screen Mode */
|
||||
|
@ -107,17 +140,6 @@ struct vc_data {
|
|||
unsigned int vc_decawm : 1; /* Autowrap Mode */
|
||||
unsigned int vc_deccm : 1; /* Cursor Visible */
|
||||
unsigned int vc_decim : 1; /* Insert Mode */
|
||||
/* attribute flags */
|
||||
unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
|
||||
unsigned int vc_italic:1;
|
||||
unsigned int vc_underline : 1;
|
||||
unsigned int vc_blink : 1;
|
||||
unsigned int vc_reverse : 1;
|
||||
unsigned int vc_s_intensity : 2; /* saved rendition */
|
||||
unsigned int vc_s_italic:1;
|
||||
unsigned int vc_s_underline : 1;
|
||||
unsigned int vc_s_blink : 1;
|
||||
unsigned int vc_s_reverse : 1;
|
||||
/* misc */
|
||||
unsigned int vc_priv : 3;
|
||||
unsigned int vc_need_wrap : 1;
|
||||
|
@ -126,13 +148,9 @@ struct vc_data {
|
|||
unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
|
||||
unsigned char vc_utf_count;
|
||||
int vc_utf_char;
|
||||
unsigned int vc_tab_stop[8]; /* Tab stops. 256 columns. */
|
||||
DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */
|
||||
unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */
|
||||
unsigned short * vc_translate;
|
||||
unsigned char vc_G0_charset;
|
||||
unsigned char vc_G1_charset;
|
||||
unsigned char vc_saved_G0;
|
||||
unsigned char vc_saved_G1;
|
||||
unsigned int vc_resize_user; /* resize request from user */
|
||||
unsigned int vc_bell_pitch; /* Console bell pitch */
|
||||
unsigned int vc_bell_duration; /* Console bell duration */
|
||||
|
@ -149,24 +167,29 @@ struct vc {
|
|||
struct work_struct SAK_work;
|
||||
|
||||
/* might add scrmem, kbd at some time,
|
||||
to have everything in one place - the disadvantage
|
||||
would be that vc_cons etc can no longer be static */
|
||||
to have everything in one place */
|
||||
};
|
||||
|
||||
extern struct vc vc_cons [MAX_NR_CONSOLES];
|
||||
extern void vc_SAK(struct work_struct *work);
|
||||
|
||||
#define CUR_DEF 0
|
||||
#define CUR_NONE 1
|
||||
#define CUR_UNDERLINE 2
|
||||
#define CUR_LOWER_THIRD 3
|
||||
#define CUR_LOWER_HALF 4
|
||||
#define CUR_TWO_THIRDS 5
|
||||
#define CUR_BLOCK 6
|
||||
#define CUR_HWMASK 0x0f
|
||||
#define CUR_SWMASK 0xfff0
|
||||
|
||||
#define CUR_DEFAULT CUR_UNDERLINE
|
||||
#define CUR_MAKE(size, change, set) ((size) | ((change) << 8) | \
|
||||
((set) << 16))
|
||||
#define CUR_SIZE(c) ((c) & 0x00000f)
|
||||
# define CUR_DEF 0
|
||||
# define CUR_NONE 1
|
||||
# define CUR_UNDERLINE 2
|
||||
# define CUR_LOWER_THIRD 3
|
||||
# define CUR_LOWER_HALF 4
|
||||
# define CUR_TWO_THIRDS 5
|
||||
# define CUR_BLOCK 6
|
||||
#define CUR_SW 0x000010
|
||||
#define CUR_ALWAYS_BG 0x000020
|
||||
#define CUR_INVERT_FG_BG 0x000040
|
||||
#define CUR_FG 0x000700
|
||||
#define CUR_BG 0x007000
|
||||
#define CUR_CHANGE(c) ((c) & 0x00ff00)
|
||||
#define CUR_SET(c) (((c) & 0xff0000) >> 8)
|
||||
|
||||
bool con_is_visible(const struct vc_data *vc);
|
||||
|
||||
|
|
|
@ -155,6 +155,8 @@ extern int early_serial_setup(struct uart_port *port);
|
|||
|
||||
extern int early_serial8250_setup(struct earlycon_device *device,
|
||||
const char *options);
|
||||
extern void serial8250_update_uartclk(struct uart_port *port,
|
||||
unsigned int uartclk);
|
||||
extern void serial8250_do_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios, struct ktermios *old);
|
||||
extern void serial8250_do_set_ldisc(struct uart_port *port,
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -30,6 +29,7 @@
|
|||
struct uart_port;
|
||||
struct serial_struct;
|
||||
struct device;
|
||||
struct gpio_desc;
|
||||
|
||||
/*
|
||||
* This structure describes all the operations that can be done on the
|
||||
|
|
|
@ -74,8 +74,6 @@ int con_set_default_unimap(struct vc_data *vc);
|
|||
void con_free_unimap(struct vc_data *vc);
|
||||
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
|
||||
|
||||
#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \
|
||||
((vc)->vc_toggle_meta ? 0x80 : 0)])
|
||||
#else
|
||||
static inline int con_set_trans_old(unsigned char __user *table)
|
||||
{
|
||||
|
@ -124,7 +122,6 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define vc_translate(vc, c) (c)
|
||||
#endif
|
||||
|
||||
/* vt.c */
|
||||
|
|
|
@ -26,20 +26,6 @@
|
|||
/*
|
||||
* The type definitions. These are from Ted Ts'o's serial.h
|
||||
*/
|
||||
#define PORT_UNKNOWN 0
|
||||
#define PORT_8250 1
|
||||
#define PORT_16450 2
|
||||
#define PORT_16550 3
|
||||
#define PORT_16550A 4
|
||||
#define PORT_CIRRUS 5
|
||||
#define PORT_16650 6
|
||||
#define PORT_16650V2 7
|
||||
#define PORT_16750 8
|
||||
#define PORT_STARTECH 9
|
||||
#define PORT_16C950 10
|
||||
#define PORT_16654 11
|
||||
#define PORT_16850 12
|
||||
#define PORT_RSA 13
|
||||
#define PORT_NS16550A 14
|
||||
#define PORT_XSCALE 15
|
||||
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
|
||||
|
|
Загрузка…
Ссылка в новой задаче