1
0
Fork 0

TTY/Serial driver updates for 5.8-rc1

Here is the tty and serial driver updates for 5.8-rc1
 
 Nothing huge at all, just a lot of little serial driver fixes, updates
 for new devices and features, and other small things.  Full details are
 in the shortlog.
 
 Note, you will get a conflict merging with your tree in the
 Documentation/devicetree/bindings/serial/rs485.yaml file, but it should
 be pretty obvious what to do.  If not, I'm sure Rob will clean it all up
 afterwards :)
 
 All of these have been in linux-next with no issues for a while.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXtzpCg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ylRxACgjGtOKPjahONL4lWd0F8ZYEcyw7sAn34woBCO
 BDUV3kolrRQ4OYNJWsHP
 =TvqG
 -----END PGP SIGNATURE-----

Merge tag 'tty-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver updates from Greg KH:
 "Here is the tty and serial driver updates for 5.8-rc1

  Nothing huge at all, just a lot of little serial driver fixes, updates
  for new devices and features, and other small things. Full details are
  in the shortlog.

  All of these have been in linux-next with no issues for a while"

* tag 'tty-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (67 commits)
  tty: serial: qcom_geni_serial: Add 51.2MHz frequency support
  tty: serial: imx: clear Ageing Timer Interrupt in handler
  serial: 8250_fintek: Add F81966 Support
  sc16is7xx: Add flag to activate IrDA mode
  dt-bindings: sc16is7xx: Add flag to activate IrDA mode
  serial: 8250: Support rs485 bus termination GPIO
  serial: 8520_port: Fix function param documentation
  dt-bindings: serial: Add binding for rs485 bus termination GPIO
  vt: keyboard: avoid signed integer overflow in k_ascii
  serial: 8250: Enable 16550A variants by default on non-x86
  tty: hvc_console, fix crashes on parallel open/close
  serial: imx: Initialize lock for non-registered console
  sc16is7xx: Read the LSR register for basic device presence check
  sc16is7xx: Allow sharing the IRQ line
  sc16is7xx: Use threaded IRQ
  sc16is7xx: Always use falling edge IRQ
  tty: n_gsm: Fix bogus i++ in gsm_data_kick
  tty: n_gsm: Remove unnecessary test in gsm_print_packet()
  serial: stm32: add no_console_suspend support
  tty: serial: fsl_lpuart: Use __maybe_unused instead of #if CONFIG_PM_SLEEP
  ...
alistair/sunxi64-5.8
Linus Torvalds 2020-06-07 09:52:36 -07:00
commit 081096d98b
47 changed files with 618 additions and 330 deletions

View File

@ -231,13 +231,13 @@ prints help, and C) an action_msg string, that will print right before your
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
After the ``sysrq_key_op`` is created, you can call the kernel function
``register_sysrq_key(int key, struct sysrq_key_op *op_p);`` this will
``register_sysrq_key(int key, const struct sysrq_key_op *op_p);`` this will
register the operation pointed to by ``op_p`` at table key 'key',
if that slot in the table is blank. At module unload time, you must call
the function ``unregister_sysrq_key(int key, struct sysrq_key_op *op_p)``, which
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
it is currently registered in that slot. This is in case the slot has been
overwritten since you registered it.
the function ``unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)``,
which will remove the key op pointed to by 'op_p' from the key 'key', if and
only if it is currently registered in that slot. This is in case the slot has
been overwritten since you registered it.
The Magic SysRQ system works by registering key operations against a key op
lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has

View File

@ -21,6 +21,8 @@ Optional properties:
the second cell is used to specify the GPIO polarity:
0 = active high,
1 = active low.
- irda-mode-ports: An array that lists the indices of the port that
should operate in IrDA mode.
Example:
sc16is750: sc16is750@51 {
@ -55,6 +57,8 @@ Optional properties:
the second cell is used to specify the GPIO polarity:
0 = active high,
1 = active low.
- irda-mode-ports: An array that lists the indices of the port that
should operate in IrDA mode.
Example:
sc16is750: sc16is750@0 {

View File

@ -41,4 +41,8 @@ properties:
rs485-rx-during-tx:
description: enables the receiving of data even while sending data.
$ref: /schemas/types.yaml#/definitions/flag
rs485-term-gpios:
description: GPIO pin to enable RS485 bus termination.
maxItems: 1
...

View File

@ -29,6 +29,14 @@ properties:
reg:
maxItems: 1
reg-io-width:
description: |
The size (in bytes) of the IO accesses that should be performed
on the device.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 1, 4 ]
clocks:
minItems: 2
maxItems: 5

View File

@ -48,6 +48,12 @@ properties:
minItems: 1
maxItems: 2
cts-gpios:
maxItems: 1
rts-gpios:
maxItems: 1
wakeup-source: true
rs485-rts-delay: true
@ -55,6 +61,14 @@ properties:
linux,rs485-enabled-at-boot-time: true
rs485-rx-during-tx: true
if:
required:
- st,hw-flow-ctrl
then:
properties:
cts-gpios: false
rts-gpios: false
required:
- compatible
- reg

View File

@ -430,6 +430,15 @@ register_cpus(void)
arch_initcall(register_cpus);
#ifdef CONFIG_MAGIC_SYSRQ
static const struct sysrq_key_op srm_sysrq_reboot_op = {
.handler = machine_halt,
.help_msg = "reboot(b)",
.action_msg = "Resetting",
.enable_mask = SYSRQ_ENABLE_BOOT,
};
#endif
void __init
setup_arch(char **cmdline_p)
{
@ -550,8 +559,8 @@ setup_arch(char **cmdline_p)
/* If we're using SRM, make sysrq-b halt back to the prom,
not auto-reboot. */
if (alpha_using_srm) {
struct sysrq_key_op *op = __sysrq_get_key_op('b');
op->handler = (void *) machine_halt;
unregister_sysrq_key('b', __sysrq_reboot_op);
register_sysrq_key('b', &srm_sysrq_reboot_op);
}
#endif

View File

@ -52,7 +52,7 @@ static void sysrq_handle_tlbdump(int key)
#endif
}
static struct sysrq_key_op sysrq_tlbdump_op = {
static const struct sysrq_key_op sysrq_tlbdump_op = {
.handler = sysrq_handle_tlbdump,
.help_msg = "show-tlbs(x)",
.action_msg = "Show TLB entries",

View File

@ -3919,7 +3919,7 @@ static void sysrq_handle_xmon(int key)
xmon_init(0);
}
static struct sysrq_key_op sysrq_xmon_op = {
static const struct sysrq_key_op sysrq_xmon_op = {
.handler = sysrq_handle_xmon,
.help_msg = "xmon(x)",
.action_msg = "Entering xmon",

View File

@ -313,7 +313,7 @@ static void sysrq_handle_globreg(int key)
trigger_all_cpu_backtrace();
}
static struct sysrq_key_op sparc_globalreg_op = {
static const struct sysrq_key_op sparc_globalreg_op = {
.handler = sysrq_handle_globreg,
.help_msg = "global-regs(y)",
.action_msg = "Show Global CPU Regs",
@ -388,7 +388,7 @@ static void sysrq_handle_globpmu(int key)
pmu_snapshot_all_cpus();
}
static struct sysrq_key_op sparc_globalpmu_op = {
static const struct sysrq_key_op sparc_globalpmu_op = {
.handler = sysrq_handle_globpmu,
.help_msg = "global-pmu(x)",
.action_msg = "Show Global PMU Regs",

View File

@ -307,13 +307,13 @@ static void drm_fb_helper_sysrq(int dummy1)
schedule_work(&drm_fb_helper_restore_work);
}
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
.handler = drm_fb_helper_sysrq,
.help_msg = "force-fb(V)",
.action_msg = "Restore framebuffer console",
};
#else
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
#endif
static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)

View File

@ -371,15 +371,14 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
* tty fields and return the kref reference.
*/
if (rc) {
tty_port_tty_set(&hp->port, NULL);
tty->driver_data = NULL;
tty_port_put(&hp->port);
printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
} else
} else {
/* We are ready... raise DTR/RTS */
if (C_BAUD(tty))
if (hp->ops->dtr_rts)
hp->ops->dtr_rts(hp, 1);
tty_port_set_initialized(&hp->port, true);
}
/* Force wakeup of the polling thread */
hvc_kick();
@ -389,22 +388,12 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
static void hvc_close(struct tty_struct *tty, struct file * filp)
{
struct hvc_struct *hp;
struct hvc_struct *hp = tty->driver_data;
unsigned long flags;
if (tty_hung_up_p(filp))
return;
/*
* No driver_data means that this close was issued after a failed
* hvc_open by the tty layer's release_dev() function and we can just
* exit cleanly because the kref reference wasn't made.
*/
if (!tty->driver_data)
return;
hp = tty->driver_data;
spin_lock_irqsave(&hp->port.lock, flags);
if (--hp->port.count == 0) {
@ -412,6 +401,9 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
/* We are done with the tty pointer now. */
tty_port_tty_set(&hp->port, NULL);
if (!tty_port_initialized(&hp->port))
return;
if (C_HUPCL(tty))
if (hp->ops->dtr_rts)
hp->ops->dtr_rts(hp, 0);
@ -428,6 +420,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
* waking periodically to check chars_in_buffer().
*/
tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
tty_port_set_initialized(&hp->port, false);
} else {
if (hp->port.count < 0)
printk(KERN_ERR "hvc_close %X: oops, count is %d\n",

View File

@ -196,8 +196,6 @@ module_param(hvcs_parm_num_devs, int, 0);
static const char hvcs_driver_name[] = "hvcs";
static const char hvcs_device_node[] = "hvcs";
static const char hvcs_driver_string[]
= "IBM hvcs (Hypervisor Virtual Console Server) Driver";
/* Status of partner info rescan triggered via sysfs. */
static int hvcs_rescan_status;

View File

@ -638,16 +638,15 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd)
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
static int mxser_change_speed(struct tty_struct *tty)
static void mxser_change_speed(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
unsigned cflag, cval, fcr;
int ret = 0;
unsigned char status;
cflag = tty->termios.c_cflag;
if (!info->ioaddr)
return ret;
return;
if (mxser_set_baud_method[tty->index] == 0)
mxser_set_baud(tty, tty_get_baud_rate(tty));
@ -803,8 +802,6 @@ static int mxser_change_speed(struct tty_struct *tty)
outb(fcr, info->ioaddr + UART_FCR); /* set fcr */
outb(cval, info->ioaddr + UART_LCR);
return ret;
}
static void mxser_check_modem_status(struct tty_struct *tty,

View File

@ -504,18 +504,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr,
else
pr_cont("(F)");
if (dlen) {
int ct = 0;
while (dlen--) {
if (ct % 8 == 0) {
pr_cont("\n");
pr_debug(" ");
}
pr_cont("%02X ", *data++);
ct++;
}
}
pr_cont("\n");
print_hex_dump_bytes("", DUMP_PREFIX_NONE, data, dlen);
}
@ -673,11 +662,10 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
* FIXME: lock against link layer control transmissions
*/
static void gsm_data_kick(struct gsm_mux *gsm)
static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci)
{
struct gsm_msg *msg, *nmsg;
int len;
int skip_sof = 0;
list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) {
if (gsm->constipated && msg->addr)
@ -699,18 +687,23 @@ static void gsm_data_kick(struct gsm_mux *gsm)
print_hex_dump_bytes("gsm_data_kick: ",
DUMP_PREFIX_OFFSET,
gsm->txframe, len);
if (gsm->output(gsm, gsm->txframe + skip_sof,
len - skip_sof) < 0)
if (gsm->output(gsm, gsm->txframe, len) < 0)
break;
/* FIXME: Can eliminate one SOF in many more cases */
gsm->tx_bytes -= msg->len;
/* For a burst of frames skip the extra SOF within the
burst */
skip_sof = 1;
list_del(&msg->list);
kfree(msg);
if (dlci) {
tty_port_tty_wakeup(&dlci->port);
} else {
int i = 0;
for (i = 0; i < NUM_DLCI; i++)
if (gsm->dlci[i])
tty_port_tty_wakeup(&gsm->dlci[i]->port);
}
}
}
@ -762,7 +755,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
/* Add to the actual output queue */
list_add_tail(&msg->list, &gsm->tx_list);
gsm->tx_bytes += msg->len;
gsm_data_kick(gsm);
gsm_data_kick(gsm, dlci);
}
/**
@ -1223,7 +1216,7 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
gsm_control_reply(gsm, CMD_FCON, NULL, 0);
/* Kick the link in case it is idling */
spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_data_kick(gsm);
gsm_data_kick(gsm, NULL);
spin_unlock_irqrestore(&gsm->tx_lock, flags);
break;
case CMD_FCOFF:
@ -2545,7 +2538,7 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
/* Queue poll */
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_data_kick(gsm);
gsm_data_kick(gsm, NULL);
if (gsm->tx_bytes < TX_THRESH_LO) {
gsm_dlci_data_sweep(gsm);
}

View File

@ -1885,7 +1885,7 @@ static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
*/
static __init int register_PCI(int i, struct pci_dev *dev)
{
int num_aiops, aiop, max_num_aiops, num_chan, chan;
int num_aiops, aiop, max_num_aiops, chan;
unsigned int aiopio[MAX_AIOPS_PER_BOARD];
CONTROLLER_t *ctlp;
@ -2157,8 +2157,7 @@ static __init int register_PCI(int i, struct pci_dev *dev)
/* Reset the AIOPIC, init the serial ports */
for (aiop = 0; aiop < num_aiops; aiop++) {
sResetAiopByNum(ctlp, aiop);
num_chan = ports_per_aiop;
for (chan = 0; chan < num_chan; chan++)
for (chan = 0; chan < ports_per_aiop; chan++)
init_r_port(i, aiop, chan, dev);
}
@ -2166,11 +2165,10 @@ static __init int register_PCI(int i, struct pci_dev *dev)
if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
(rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
(rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
num_chan = ports_per_aiop;
for (chan = 0; chan < num_chan; chan++)
for (chan = 0; chan < ports_per_aiop; chan++)
sPCIModemReset(ctlp, chan, 1);
msleep(500);
for (chan = 0; chan < num_chan; chan++)
for (chan = 0; chan < ports_per_aiop; chan++)
sPCIModemReset(ctlp, chan, 0);
msleep(500);
rmSpeakerReset(ctlp, rocketModel[i].model);

View File

@ -1026,7 +1026,9 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (up->port.dev) {
uart->port.dev = up->port.dev;
uart_get_rs485_mode(uart->port.dev, &uart->port.rs485);
ret = uart_get_rs485_mode(&uart->port);
if (ret)
goto err;
}
if (up->port.flags & UPF_FIXED_TYPE)
@ -1040,7 +1042,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
gpios = mctrl_gpio_init(&uart->port, 0);
if (IS_ERR(gpios)) {
ret = PTR_ERR(gpios);
goto out_unlock;
goto err;
} else {
uart->gpios = gpios;
}
@ -1089,8 +1091,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
serial8250_apply_quirks(uart);
ret = uart_add_one_port(&serial8250_reg,
&uart->port);
if (ret == 0)
ret = uart->port.line;
if (ret)
goto err;
ret = uart->port.line;
} else {
dev_info(uart->port.dev,
"skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
@ -1112,10 +1116,14 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
}
}
out_unlock:
mutex_unlock(&serial_mutex);
return ret;
err:
uart->port.dev = NULL;
mutex_unlock(&serial_mutex);
return ret;
}
EXPORT_SYMBOL(serial8250_register_8250_port);

View File

@ -25,13 +25,13 @@
#include "8250.h"
#define PCI_DEVICE_ID_ACCES_COM_2S 0x1052
#define PCI_DEVICE_ID_ACCES_COM_4S 0x105d
#define PCI_DEVICE_ID_ACCES_COM_8S 0x106c
#define PCI_DEVICE_ID_ACCES_COM232_8 0x10a8
#define PCI_DEVICE_ID_ACCES_COM_2SM 0x10d2
#define PCI_DEVICE_ID_ACCES_COM_4SM 0x10db
#define PCI_DEVICE_ID_ACCES_COM_8SM 0x10ea
#define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052
#define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d
#define PCI_DEVICE_ID_ACCESSIO_COM_8S 0x106c
#define PCI_DEVICE_ID_ACCESSIO_COM232_8 0x10a8
#define PCI_DEVICE_ID_ACCESSIO_COM_2SM 0x10d2
#define PCI_DEVICE_ID_ACCESSIO_COM_4SM 0x10db
#define PCI_DEVICE_ID_ACCESSIO_COM_8SM 0x10ea
#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
@ -755,9 +755,7 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
(kernel_ulong_t)&bd \
}
#define EXAR_DEVICE(vend, devid, bd) { \
PCI_VDEVICE(vend, PCI_DEVICE_ID_##devid), (kernel_ulong_t)&bd \
}
#define EXAR_DEVICE(vend, devid, bd) { PCI_DEVICE_DATA(vend, devid, &bd) }
#define IBM_DEVICE(devid, sdevid, bd) { \
PCI_DEVICE_SUB( \
@ -769,14 +767,13 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
}
static const struct pci_device_id exar_pci_tbl[] = {
EXAR_DEVICE(ACCESSIO, ACCES_COM_2S, acces_com_2x),
EXAR_DEVICE(ACCESSIO, ACCES_COM_4S, acces_com_4x),
EXAR_DEVICE(ACCESSIO, ACCES_COM_8S, acces_com_8x),
EXAR_DEVICE(ACCESSIO, ACCES_COM232_8, acces_com_8x),
EXAR_DEVICE(ACCESSIO, ACCES_COM_2SM, acces_com_2x),
EXAR_DEVICE(ACCESSIO, ACCES_COM_4SM, acces_com_4x),
EXAR_DEVICE(ACCESSIO, ACCES_COM_8SM, acces_com_8x),
EXAR_DEVICE(ACCESSIO, COM_2S, acces_com_2x),
EXAR_DEVICE(ACCESSIO, COM_4S, acces_com_4x),
EXAR_DEVICE(ACCESSIO, COM_8S, acces_com_8x),
EXAR_DEVICE(ACCESSIO, COM232_8, acces_com_8x),
EXAR_DEVICE(ACCESSIO, COM_2SM, acces_com_2x),
EXAR_DEVICE(ACCESSIO, COM_4SM, acces_com_4x),
EXAR_DEVICE(ACCESSIO, COM_8SM, acces_com_8x),
CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),
@ -794,24 +791,24 @@ static const struct pci_device_id exar_pci_tbl[] = {
IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn),
/* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */
EXAR_DEVICE(EXAR, EXAR_XR17C152, pbn_exar_XR17C15x),
EXAR_DEVICE(EXAR, EXAR_XR17C154, pbn_exar_XR17C15x),
EXAR_DEVICE(EXAR, EXAR_XR17C158, pbn_exar_XR17C15x),
EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x),
EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x),
EXAR_DEVICE(EXAR, XR17C158, pbn_exar_XR17C15x),
/* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */
EXAR_DEVICE(EXAR, EXAR_XR17V352, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, EXAR_XR17V354, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, EXAR_XR17V358, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, EXAR_XR17V4358, pbn_exar_XR17V4358),
EXAR_DEVICE(EXAR, EXAR_XR17V8358, pbn_exar_XR17V8358),
EXAR_DEVICE(COMMTECH, COMMTECH_4222PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, COMMTECH_4224PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, COMMTECH_4228PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, XR17V352, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, XR17V354, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, XR17V358, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, XR17V4358, pbn_exar_XR17V4358),
EXAR_DEVICE(EXAR, XR17V8358, pbn_exar_XR17V8358),
EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, COMMTECH_4222PCI335, pbn_fastcom335_2),
EXAR_DEVICE(COMMTECH, COMMTECH_4224PCI335, pbn_fastcom335_4),
EXAR_DEVICE(COMMTECH, COMMTECH_2324PCI335, pbn_fastcom335_4),
EXAR_DEVICE(COMMTECH, COMMTECH_2328PCI335, pbn_fastcom335_8),
EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2),
EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4),
EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8),
{ 0, }
};
MODULE_DEVICE_TABLE(pci, exar_pci_tbl);

View File

@ -19,6 +19,7 @@
#define CHIP_ID2 0x21
#define CHIP_ID_F81865 0x0407
#define CHIP_ID_F81866 0x1010
#define CHIP_ID_F81966 0x0215
#define CHIP_ID_F81216AD 0x1602
#define CHIP_ID_F81216H 0x0501
#define CHIP_ID_F81216 0x0802
@ -62,9 +63,9 @@
#define F81216_LDN_HIGH 0x4
/*
* F81866 registers
* F81866/966 registers
*
* The IRQ setting mode of F81866 is not the same with F81216 series.
* The IRQ setting mode of F81866/966 is not the same with F81216 series.
* Level/Low: IRQ_MODE0:0, IRQ_MODE1:0
* Edge/High: IRQ_MODE0:1, IRQ_MODE1:0
*
@ -155,6 +156,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata)
switch (chip) {
case CHIP_ID_F81865:
case CHIP_ID_F81866:
case CHIP_ID_F81966:
case CHIP_ID_F81216AD:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
@ -171,6 +173,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min,
int *max)
{
switch (pdata->pid) {
case CHIP_ID_F81966:
case CHIP_ID_F81865:
case CHIP_ID_F81866:
*min = F81866_LDN_LOW;
@ -248,6 +251,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
sio_write_reg(pdata, LDN, pdata->index);
switch (pdata->pid) {
case CHIP_ID_F81966:
case CHIP_ID_F81866:
sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1,
0);
@ -274,6 +278,7 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
{
switch (pdata->pid) {
case CHIP_ID_F81216H: /* 128Bytes FIFO */
case CHIP_ID_F81966:
case CHIP_ID_F81866:
sio_write_mask_reg(pdata, FIFO_CTRL,
FIFO_MODE_MASK | RXFTHR_MODE_MASK,
@ -291,6 +296,7 @@ static void fintek_8250_goto_highspeed(struct uart_8250_port *uart,
sio_write_reg(pdata, LDN, pdata->index);
switch (pdata->pid) {
case CHIP_ID_F81966:
case CHIP_ID_F81866: /* set uart clock for high speed serial mode */
sio_write_mask_reg(pdata, F81866_UART_CLK,
F81866_UART_CLK_MASK,
@ -327,6 +333,7 @@ static void fintek_8250_set_termios(struct uart_port *port,
case CHIP_ID_F81216H:
reg = RS485;
break;
case CHIP_ID_F81966:
case CHIP_ID_F81866:
reg = F81866_UART_CLK;
break;
@ -373,6 +380,7 @@ static void fintek_8250_set_termios_handler(struct uart_8250_port *uart)
switch (pdata->pid) {
case CHIP_ID_F81216H:
case CHIP_ID_F81966:
case CHIP_ID_F81866:
uart->port.set_termios = fintek_8250_set_termios;
break;
@ -443,6 +451,7 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart)
switch (pdata->pid) {
case CHIP_ID_F81216AD:
case CHIP_ID_F81216H:
case CHIP_ID_F81966:
case CHIP_ID_F81866:
case CHIP_ID_F81865:
uart->port.rs485_config = fintek_8250_rs485_config;

View File

@ -681,6 +681,9 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485)
memset(rs485->padding, 0, sizeof(rs485->padding));
port->rs485 = *rs485;
gpiod_set_value(port->rs485_term_gpio,
rs485->flags & SER_RS485_TERMINATE_BUS);
/*
* Both serial8250_em485_init() and serial8250_em485_destroy()
* are idempotent.
@ -1432,7 +1435,7 @@ static void serial8250_stop_rx(struct uart_port *port)
/**
* serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback
* @up: uart 8250 port
* @p: uart 8250 port
*
* Generic callback usable by 8250 uart drivers to stop rs485 transmission.
*/
@ -2615,6 +2618,8 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
{
unsigned int tolerance = port->uartclk / 100;
/*
* Ask the core to calculate the divisor for us.
* Allow 1% tolerance at the upper limit so uart clks marginally
@ -2623,7 +2628,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
*/
return uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / UART_DIV_MAX,
port->uartclk);
(port->uartclk + tolerance) / 16);
}
void

View File

@ -63,6 +63,7 @@ config SERIAL_8250_PNP
config SERIAL_8250_16550A_VARIANTS
bool "Support for variants of the 16550A serial port"
depends on SERIAL_8250
default !X86
help
The 8250 driver can probe for many variants of the venerable 16550A
serial port. Doing so takes additional time at boot.

View File

@ -440,7 +440,7 @@ static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
static int simple_config(struct pcmcia_device *link)
{
struct serial_info *info = link->priv;
int i = -ENODEV, try;
int ret, try;
/*
* First pass: look for a config entry that looks normal.
@ -472,8 +472,8 @@ found_port:
if (info->quirk && info->quirk->config)
info->quirk->config(link);
i = pcmcia_enable_device(link);
if (i != 0)
ret = pcmcia_enable_device(link);
if (ret != 0)
return -1;
return setup_serial(link, info, link->resource[0]->start, link->irq);
}

View File

@ -1034,13 +1034,22 @@ config SERIAL_SIFIVE_CONSOLE
boot time.)
config SERIAL_LANTIQ
bool "Lantiq serial driver"
depends on LANTIQ
tristate "Lantiq serial driver"
depends on (LANTIQ || X86) || COMPILE_TEST
select SERIAL_CORE
help
Support for UART on Lantiq and Intel SoCs.
To compile this driver as a module, select M here. The
module will be called lantiq.
config SERIAL_LANTIQ_CONSOLE
bool "Console on Lantiq UART"
depends on SERIAL_LANTIQ=y
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
Support for console and UART on Lantiq SoCs.
Select this option if you would like to use a Lantiq UART as the
system console.
config SERIAL_QE
tristate "Freescale QUICC Engine serial port support"
@ -1462,6 +1471,7 @@ config SERIAL_STM32
tristate "STMicroelectronics STM32 serial port support"
select SERIAL_CORE
depends on ARCH_STM32 || COMPILE_TEST
select SERIAL_MCTRL_GPIO if GPIOLIB
help
This driver is for the on-chip Serial Controller on
STMicroelectronics STM32 MCUs.

View File

@ -2607,6 +2607,7 @@ 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;

View File

@ -766,8 +766,6 @@ static int ar933x_uart_probe(struct platform_device *pdev)
goto err_disable_clk;
}
uart_get_rs485_mode(&pdev->dev, &port->rs485);
port->mapbase = mem_res->start;
port->line = id;
port->irq = irq_res->start;
@ -786,6 +784,10 @@ static int ar933x_uart_probe(struct platform_device *pdev)
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
ret = uart_get_rs485_mode(port);
if (ret)
goto err_disable_clk;
up->gpios = mctrl_gpio_init(port, 0);
if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS)
return PTR_ERR(up->gpios);

View File

@ -2491,8 +2491,6 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
atmel_init_property(atmel_port, pdev);
atmel_set_ops(port);
uart_get_rs485_mode(&mpdev->dev, &port->rs485);
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
port->ops = &atmel_pops;
@ -2506,6 +2504,10 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
ret = uart_get_rs485_mode(port);
if (ret)
return ret;
/* for console, the clock could already be configured */
if (!atmel_port->clk) {
atmel_port->clk = clk_get(&mpdev->dev, "usart");

View File

@ -1231,9 +1231,7 @@ static void lpuart_dma_rx_free(struct uart_port *port)
struct lpuart_port, port);
struct dma_chan *chan = sport->dma_rx_chan;
if (chan)
dmaengine_terminate_all(chan);
dmaengine_terminate_all(chan);
dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
kfree(sport->rx_ring.buf);
sport->rx_ring.tail = 0;
@ -1514,17 +1512,17 @@ static void lpuart_request_dma(struct lpuart_port *sport)
{
sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx");
if (IS_ERR(sport->dma_tx_chan)) {
dev_info_once(sport->port.dev,
"DMA tx channel request failed, operating without tx DMA (%ld)\n",
PTR_ERR(sport->dma_tx_chan));
dev_dbg_once(sport->port.dev,
"DMA tx channel request failed, operating without tx DMA (%ld)\n",
PTR_ERR(sport->dma_tx_chan));
sport->dma_tx_chan = NULL;
}
sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx");
if (IS_ERR(sport->dma_rx_chan)) {
dev_info_once(sport->port.dev,
"DMA rx channel request failed, operating without rx DMA (%ld)\n",
PTR_ERR(sport->dma_rx_chan));
dev_dbg_once(sport->port.dev,
"DMA rx channel request failed, operating without rx DMA (%ld)\n",
PTR_ERR(sport->dma_rx_chan));
sport->dma_rx_chan = NULL;
}
}
@ -2621,7 +2619,9 @@ static int lpuart_probe(struct platform_device *pdev)
if (ret)
goto failed_attach_port;
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
ret = uart_get_rs485_mode(&sport->port);
if (ret)
goto failed_get_rs485;
if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX)
dev_err(&pdev->dev, "driver doesn't support RX during TX\n");
@ -2634,6 +2634,7 @@ static int lpuart_probe(struct platform_device *pdev)
return 0;
failed_get_rs485:
failed_attach_port:
failed_irq_request:
lpuart_disable_clks(sport);
@ -2664,8 +2665,7 @@ static int lpuart_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int lpuart_suspend(struct device *dev)
static int __maybe_unused lpuart_suspend(struct device *dev)
{
struct lpuart_port *sport = dev_get_drvdata(dev);
unsigned long temp;
@ -2723,7 +2723,7 @@ static int lpuart_suspend(struct device *dev)
return 0;
}
static int lpuart_resume(struct device *dev)
static int __maybe_unused lpuart_resume(struct device *dev)
{
struct lpuart_port *sport = dev_get_drvdata(dev);
bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
@ -2754,7 +2754,6 @@ static int lpuart_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume);

View File

@ -909,6 +909,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
usr2 &= ~USR2_ORE;
if (usr1 & (USR1_RRDY | USR1_AGTIM)) {
imx_uart_writel(sport, USR1_AGTIM, USR1);
__imx_uart_rxint(irq, dev_id);
ret = IRQ_HANDLED;
}
@ -2252,6 +2254,8 @@ static int imx_uart_probe(struct platform_device *pdev)
return PTR_ERR(base);
rxirq = platform_get_irq(pdev, 0);
if (rxirq < 0)
return rxirq;
txirq = platform_get_irq_optional(pdev, 1);
rtsirq = platform_get_irq_optional(pdev, 2);
@ -2302,7 +2306,11 @@ static int imx_uart_probe(struct platform_device *pdev)
sport->ucr4 = readl(sport->port.membase + UCR4);
sport->ufcr = readl(sport->port.membase + UFCR);
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
ret = uart_get_rs485_mode(&sport->port);
if (ret) {
clk_disable_unprepare(sport->clk_ipg);
return ret;
}
if (sport->port.rs485.flags & SER_RS485_ENABLED &&
(!sport->have_rtscts && !sport->have_rtsgpio))
@ -2398,6 +2406,9 @@ 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);

View File

@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/lantiq.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@ -597,6 +598,7 @@ static const struct uart_ops lqasc_pops = {
.verify_port = lqasc_verify_port,
};
#ifdef CONFIG_SERIAL_LANTIQ_CONSOLE
static void
lqasc_console_putchar(struct uart_port *port, int ch)
{
@ -705,6 +707,14 @@ lqasc_serial_early_console_setup(struct earlycon_device *device,
OF_EARLYCON_DECLARE(lantiq, "lantiq,asc", lqasc_serial_early_console_setup);
OF_EARLYCON_DECLARE(lantiq, "intel,lgm-asc", lqasc_serial_early_console_setup);
#define LANTIQ_SERIAL_CONSOLE (&lqasc_console)
#else
#define LANTIQ_SERIAL_CONSOLE NULL
#endif /* CONFIG_SERIAL_LANTIQ_CONSOLE */
static struct uart_driver lqasc_reg = {
.owner = THIS_MODULE,
.driver_name = DRVNAME,
@ -712,7 +722,7 @@ static struct uart_driver lqasc_reg = {
.major = 0,
.minor = 0,
.nr = MAXPORTS,
.cons = &lqasc_console,
.cons = LANTIQ_SERIAL_CONSOLE,
};
static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port)
@ -814,8 +824,7 @@ static void free_irq_intel(struct uart_port *port)
free_irq(ltq_port->common_irq, port);
}
static int __init
lqasc_probe(struct platform_device *pdev)
static int lqasc_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct ltq_uart_port *ltq_port;
@ -899,6 +908,13 @@ lqasc_probe(struct platform_device *pdev)
return ret;
}
static int lqasc_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
return uart_remove_one_port(&lqasc_reg, port);
}
static const struct ltq_soc_data soc_data_lantiq = {
.fetch_irq = fetch_irq_lantiq,
.request_irq = request_irq_lantiq,
@ -916,8 +932,11 @@ static const struct of_device_id ltq_asc_match[] = {
{ .compatible = "intel,lgm-asc", .data = &soc_data_intel },
{},
};
MODULE_DEVICE_TABLE(of, ltq_asc_match);
static struct platform_driver lqasc_driver = {
.probe = lqasc_probe,
.remove = lqasc_remove,
.driver = {
.name = DRVNAME,
.of_match_table = ltq_asc_match,
@ -933,10 +952,21 @@ init_lqasc(void)
if (ret != 0)
return ret;
ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
ret = platform_driver_register(&lqasc_driver);
if (ret != 0)
uart_unregister_driver(&lqasc_reg);
return ret;
}
device_initcall(init_lqasc);
static void __exit exit_lqasc(void)
{
platform_driver_unregister(&lqasc_driver);
uart_unregister_driver(&lqasc_reg);
}
module_init(init_lqasc);
module_exit(exit_lqasc);
MODULE_DESCRIPTION("Serial driver for Lantiq & Intel gateway SoCs");
MODULE_LICENSE("GPL v2");

View File

@ -23,7 +23,6 @@
#include <linux/nmi.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/sizes.h>
#include <linux/soc/nxp/lpc32xx-misc.h>

View File

@ -33,8 +33,7 @@
#include <linux/pm_wakeirq.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_data/serial-omap.h>
#define OMAP_MAX_HSUART_PORTS 10
@ -153,7 +152,7 @@ struct uart_omap_port {
u32 errata;
u32 features;
int rts_gpio;
struct gpio_desc *rts_gpiod;
struct pm_qos_request pm_qos_request;
u32 latency;
@ -303,11 +302,11 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_OMAP_SCR, up->scr);
res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ?
1 : 0;
if (gpio_get_value(up->rts_gpio) != res) {
if (gpiod_get_value(up->rts_gpiod) != res) {
if (port->rs485.delay_rts_after_send > 0)
mdelay(
port->rs485.delay_rts_after_send);
gpio_set_value(up->rts_gpio, res);
gpiod_set_value(up->rts_gpiod, res);
}
} else {
/* We're asked to stop, but there's still stuff in the
@ -412,8 +411,8 @@ static void serial_omap_start_tx(struct uart_port *port)
/* if rts not already enabled */
res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
if (gpio_get_value(up->rts_gpio) != res) {
gpio_set_value(up->rts_gpio, res);
if (gpiod_get_value(up->rts_gpiod) != res) {
gpiod_set_value(up->rts_gpiod, res);
if (port->rs485.delay_rts_before_send > 0)
mdelay(port->rs485.delay_rts_before_send);
}
@ -1414,12 +1413,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
* Just as a precaution, only allow rs485
* to be enabled if the gpio pin is valid
*/
if (gpio_is_valid(up->rts_gpio)) {
if (up->rts_gpiod) {
/* enable / disable rts */
val = (port->rs485.flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
val = (port->rs485.flags & val) ? 1 : 0;
gpio_set_value(up->rts_gpio, val);
gpiod_set_value(up->rts_gpiod, val);
} else
port->rs485.flags &= ~SER_RS485_ENABLED;
@ -1596,18 +1595,22 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
}
static int serial_omap_probe_rs485(struct uart_omap_port *up,
struct device_node *np)
struct device *dev)
{
struct serial_rs485 *rs485conf = &up->port.rs485;
struct device_node *np = dev->of_node;
enum gpiod_flags gflags;
int ret;
rs485conf->flags = 0;
up->rts_gpio = -EINVAL;
up->rts_gpiod = NULL;
if (!np)
return 0;
uart_get_rs485_mode(up->dev, rs485conf);
ret = uart_get_rs485_mode(&up->port);
if (ret)
return ret;
if (of_property_read_bool(np, "rs485-rts-active-high")) {
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
@ -1618,19 +1621,20 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
}
/* check for tx enable gpio */
up->rts_gpio = of_get_named_gpio(np, "rts-gpio", 0);
if (gpio_is_valid(up->rts_gpio)) {
ret = devm_gpio_request(up->dev, up->rts_gpio, "omap-serial");
if (ret < 0)
gflags = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ?
GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
up->rts_gpiod = devm_gpiod_get_optional(dev, "rts", gflags);
if (IS_ERR(up->rts_gpiod)) {
ret = PTR_ERR(up->rts_gpiod);
if (ret == -EPROBE_DEFER)
return ret;
ret = rs485conf->flags & SER_RS485_RTS_AFTER_SEND ? 1 : 0;
ret = gpio_direction_output(up->rts_gpio, ret);
if (ret < 0)
return ret;
} else if (up->rts_gpio == -EPROBE_DEFER) {
return -EPROBE_DEFER;
/*
* FIXME: the code historically ignored any other error than
* -EPROBE_DEFER and just went on without GPIO.
*/
up->rts_gpiod = NULL;
} else {
up->rts_gpio = -EINVAL;
gpiod_set_consumer_name(up->rts_gpiod, "omap-serial");
}
return 0;
@ -1703,7 +1707,7 @@ static int serial_omap_probe(struct platform_device *pdev)
dev_info(up->port.dev, "no wakeirq for uart%d\n",
up->port.line);
ret = serial_omap_probe_rs485(up, pdev->dev.of_node);
ret = serial_omap_probe_rs485(up, &pdev->dev);
if (ret < 0)
goto err_rs485;

View File

@ -141,9 +141,10 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport);
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
32000000, 48000000, 64000000, 80000000,
96000000, 100000000, 102400000,
112000000, 120000000, 128000000};
32000000, 48000000, 51200000, 64000000,
80000000, 96000000, 100000000,
102400000, 112000000, 120000000,
128000000};
#define to_dev_port(ptr, member) \
container_of(ptr, struct qcom_geni_serial_port, member)

View File

@ -154,10 +154,33 @@ struct s3c24xx_uart_port {
#define portaddrl(port, reg) \
((unsigned long *)(unsigned long)((port)->membase + (reg)))
#define rd_regb(port, reg) (readb_relaxed(portaddr(port, reg)))
static u32 rd_reg(struct uart_port *port, u32 reg)
{
switch (port->iotype) {
case UPIO_MEM:
return readb_relaxed(portaddr(port, reg));
case UPIO_MEM32:
return readl_relaxed(portaddr(port, reg));
default:
return 0;
}
return 0;
}
#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
#define wr_regb(port, reg, val) writeb_relaxed(val, portaddr(port, reg))
static void wr_reg(struct uart_port *port, u32 reg, u32 val)
{
switch (port->iotype) {
case UPIO_MEM:
writeb_relaxed(val, portaddr(port, reg));
break;
case UPIO_MEM32:
writel_relaxed(val, portaddr(port, reg));
break;
}
}
#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
/* Byte-order aware bit setting/clearing functions. */
@ -714,7 +737,7 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
fifocnt--;
uerstat = rd_regl(port, S3C2410_UERSTAT);
ch = rd_regb(port, S3C2410_URXH);
ch = rd_reg(port, S3C2410_URXH);
if (port->flags & UPF_CONS_FLOW) {
int txe = s3c24xx_serial_txempty_nofifo(port);
@ -826,7 +849,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
}
if (port->x_char) {
wr_regb(port, S3C2410_UTXH, port->x_char);
wr_reg(port, S3C2410_UTXH, port->x_char);
port->icount.tx++;
port->x_char = 0;
goto out;
@ -852,7 +875,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break;
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
wr_reg(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
count--;
@ -916,7 +939,7 @@ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
/* no modem control lines */
static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
{
unsigned int umstat = rd_regb(port, S3C2410_UMSTAT);
unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
if (umstat & S3C2410_UMSTAT_CTS)
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
@ -1281,14 +1304,14 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
struct s3c24xx_uart_info *info = ourport->info;
struct clk *clk;
unsigned long rate;
unsigned int cnt, baud, quot, clk_sel, best_quot = 0;
unsigned int cnt, baud, quot, best_quot = 0;
char clkname[MAX_CLK_NAME_LENGTH];
int calc_deviation, deviation = (1 << 30) - 1;
clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
ourport->info->def_clk_sel;
for (cnt = 0; cnt < info->num_clks; cnt++) {
if (!(clk_sel & (1 << cnt)))
/* Keep selected clock if provided */
if (ourport->cfg->clk_sel &&
!(ourport->cfg->clk_sel & (1 << cnt)))
continue;
sprintf(clkname, "clk_uart_baud%d", cnt);
@ -1974,7 +1997,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct s3c24xx_uart_port *ourport;
int index = probe_index;
int ret;
int ret, prop = 0;
if (np) {
ret = of_alias_get_id(np, "serial");
@ -2000,10 +2023,27 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
if (np)
if (np) {
of_property_read_u32(np,
"samsung,uart-fifosize", &ourport->port.fifosize);
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
switch (prop) {
case 1:
ourport->port.iotype = UPIO_MEM;
break;
case 4:
ourport->port.iotype = UPIO_MEM32;
break;
default:
dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
prop);
ret = -EINVAL;
break;
}
}
}
if (ourport->drv_data->fifosize[index])
ourport->port.fifosize = ourport->drv_data->fifosize[index];
else if (ourport->info->fifosize)
@ -2185,7 +2225,7 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
return NO_POLL_CHAR;
return rd_regb(port, S3C2410_URXH);
return rd_reg(port, S3C2410_URXH);
}
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
@ -2200,7 +2240,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
while (!s3c24xx_serial_console_txrdy(port, ufcon))
cpu_relax();
wr_regb(port, S3C2410_UTXH, c);
wr_reg(port, S3C2410_UTXH, c);
}
#endif /* CONFIG_CONSOLE_POLL */
@ -2212,7 +2252,7 @@ s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
while (!s3c24xx_serial_console_txrdy(port, ufcon))
cpu_relax();
wr_regb(port, S3C2410_UTXH, ch);
wr_reg(port, S3C2410_UTXH, ch);
}
static void
@ -2587,6 +2627,18 @@ module_platform_driver(samsung_serial_driver);
* Early console.
*/
static void wr_reg_barrier(struct uart_port *port, u32 reg, u32 val)
{
switch (port->iotype) {
case UPIO_MEM:
writeb(val, portaddr(port, reg));
break;
case UPIO_MEM32:
writel(val, portaddr(port, reg));
break;
}
}
struct samsung_early_console_data {
u32 txfull_mask;
};
@ -2612,7 +2664,7 @@ static void samsung_early_putc(struct uart_port *port, int c)
else
samsung_early_busyuart(port);
writeb(c, port->membase + S3C2410_UTXH);
wr_reg_barrier(port, S3C2410_UTXH, c);
}
static void samsung_early_write(struct console *con, const char *s,

View File

@ -315,6 +315,7 @@ struct sc16is7xx_one {
struct kthread_work tx_work;
struct kthread_work reg_work;
struct sc16is7xx_one_config config;
bool irda_mode;
};
struct sc16is7xx_port {
@ -327,7 +328,6 @@ struct sc16is7xx_port {
unsigned char buf[SC16IS7XX_FIFO_SIZE];
struct kthread_worker kworker;
struct task_struct *kworker_task;
struct kthread_work irq_work;
struct mutex efr_lock;
struct sc16is7xx_one p[];
};
@ -710,9 +710,9 @@ static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
return true;
}
static void sc16is7xx_ist(struct kthread_work *ws)
static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
{
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
mutex_lock(&s->efr_lock);
@ -727,13 +727,6 @@ static void sc16is7xx_ist(struct kthread_work *ws)
}
mutex_unlock(&s->efr_lock);
}
static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
{
struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
kthread_queue_work(&s->kworker, &s->irq_work);
return IRQ_HANDLED;
}
@ -994,6 +987,7 @@ static int sc16is7xx_config_rs485(struct uart_port *port,
static int sc16is7xx_startup(struct uart_port *port)
{
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned int val;
@ -1032,6 +1026,13 @@ static int sc16is7xx_startup(struct uart_port *port)
/* Now, initialize the UART */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);
/* Enable IrDA mode if requested in DT */
/* This bit must be written with LCR[7] = 0 */
sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
SC16IS7XX_MCR_IRDA_BIT,
one->irda_mode ?
SC16IS7XX_MCR_IRDA_BIT : 0);
/* Enable the Rx and Tx FIFO */
sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
SC16IS7XX_EFCR_RXDISABLE_BIT |
@ -1176,10 +1177,11 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
static int sc16is7xx_probe(struct device *dev,
const struct sc16is7xx_devtype *devtype,
struct regmap *regmap, int irq, unsigned long flags)
struct regmap *regmap, int irq)
{
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
unsigned long freq = 0, *pfreq = dev_get_platdata(dev);
unsigned int val;
u32 uartclk = 0;
int i, ret;
struct sc16is7xx_port *s;
@ -1187,6 +1189,16 @@ static int sc16is7xx_probe(struct device *dev,
if (IS_ERR(regmap))
return PTR_ERR(regmap);
/*
* This device does not have an identification register that would
* tell us if we are really connected to the correct device.
* The best we can do is to check if communication is at all possible.
*/
ret = regmap_read(regmap,
SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
if (ret < 0)
return ret;
/* Alloc port structure */
s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL);
if (!s) {
@ -1221,7 +1233,6 @@ static int sc16is7xx_probe(struct device *dev,
mutex_init(&s->efr_lock);
kthread_init_worker(&s->kworker);
kthread_init_work(&s->irq_work, sc16is7xx_ist);
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
"sc16is7xx");
if (IS_ERR(s->kworker_task)) {
@ -1302,9 +1313,33 @@ static int sc16is7xx_probe(struct device *dev,
sc16is7xx_power(&s->p[i].port, 0);
}
/* Setup interrupt */
ret = devm_request_irq(dev, irq, sc16is7xx_irq,
flags, dev_name(dev), s);
if (dev->of_node) {
struct property *prop;
const __be32 *p;
u32 u;
of_property_for_each_u32(dev->of_node, "irda-mode-ports",
prop, p, u)
if (u < devtype->nr_uart)
s->p[u].irda_mode = true;
}
/*
* Setup interrupt. We first try to acquire the IRQ line as level IRQ.
* If that succeeds, we can allow sharing the interrupt as well.
* In case the interrupt controller doesn't support that, we fall
* back to a non-shared falling-edge trigger.
*/
ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq,
IRQF_TRIGGER_LOW | IRQF_SHARED |
IRQF_ONESHOT,
dev_name(dev), s);
if (!ret)
return 0;
ret = devm_request_threaded_irq(dev, irq, NULL, sc16is7xx_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(dev), s);
if (!ret)
return 0;
@ -1378,7 +1413,6 @@ static struct regmap_config regcfg = {
static int sc16is7xx_spi_probe(struct spi_device *spi)
{
const struct sc16is7xx_devtype *devtype;
unsigned long flags = 0;
struct regmap *regmap;
int ret;
@ -1399,14 +1433,13 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
const struct spi_device_id *id_entry = spi_get_device_id(spi);
devtype = (struct sc16is7xx_devtype *)id_entry->driver_data;
flags = IRQF_TRIGGER_FALLING;
}
regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
(devtype->nr_uart - 1);
regmap = devm_regmap_init_spi(spi, &regcfg);
return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq, flags);
return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq);
}
static int sc16is7xx_spi_remove(struct spi_device *spi)
@ -1445,7 +1478,6 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
const struct sc16is7xx_devtype *devtype;
unsigned long flags = 0;
struct regmap *regmap;
if (i2c->dev.of_node) {
@ -1454,14 +1486,13 @@ static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
return -ENODEV;
} else {
devtype = (struct sc16is7xx_devtype *)id->driver_data;
flags = IRQF_TRIGGER_FALLING;
}
regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
(devtype->nr_uart - 1);
regmap = devm_regmap_init_i2c(i2c, &regcfg);
return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq, flags);
return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq);
}
static int sc16is7xx_i2c_remove(struct i2c_client *client)

View File

@ -3295,8 +3295,10 @@ EXPORT_SYMBOL(uart_remove_one_port);
* This function implements the device tree binding described in
* Documentation/devicetree/bindings/serial/rs485.txt.
*/
void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
int uart_get_rs485_mode(struct uart_port *port)
{
struct serial_rs485 *rs485conf = &port->rs485;
struct device *dev = port->dev;
u32 rs485_delay[2];
int ret;
@ -3315,6 +3317,7 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
* to get to a defined state with the following properties:
*/
rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED |
SER_RS485_TERMINATE_BUS |
SER_RS485_RTS_AFTER_SEND);
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
@ -3328,6 +3331,23 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf)
rs485conf->flags &= ~SER_RS485_RTS_ON_SEND;
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
}
/*
* Disabling termination by default is the safe choice: Else if many
* bus participants enable it, no communication is possible at all.
* Works fine for short cables and users may enable for longer cables.
*/
port->rs485_term_gpio = devm_gpiod_get_optional(dev, "rs485-term",
GPIOD_OUT_LOW);
if (IS_ERR(port->rs485_term_gpio)) {
ret = PTR_ERR(port->rs485_term_gpio);
port->rs485_term_gpio = NULL;
if (ret != -EPROBE_DEFER)
dev_err(dev, "Cannot get rs485-term-gpios\n");
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(uart_get_rs485_mode);

View File

@ -2,7 +2,6 @@
#include <linux/bitops.h>
#include <linux/serial_core.h>
#include <linux/io.h>
#include <linux/gpio.h>
#define SCI_MAJOR 204
#define SCI_MINOR_START 8

View File

@ -31,6 +31,7 @@
#include <linux/tty_flip.h>
#include <linux/tty.h>
#include "serial_mctrl_gpio.h"
#include "stm32-usart.h"
static void stm32_stop_tx(struct uart_port *port);
@ -158,9 +159,7 @@ static int stm32_init_rs485(struct uart_port *port,
if (!pdev->dev.of_node)
return -ENODEV;
uart_get_rs485_mode(&pdev->dev, rs485conf);
return 0;
return uart_get_rs485_mode(port);
}
static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res,
@ -510,12 +509,29 @@ static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl)
stm32_set_bits(port, ofs->cr3, USART_CR3_RTSE);
else
stm32_clr_bits(port, ofs->cr3, USART_CR3_RTSE);
mctrl_gpio_set(stm32_port->gpios, mctrl);
}
static unsigned int stm32_get_mctrl(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
unsigned int ret;
/* This routine is used to get signals of: DCD, DSR, RI, and CTS */
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
return mctrl_gpio_get(stm32_port->gpios, &ret);
}
static void stm32_enable_ms(struct uart_port *port)
{
mctrl_gpio_enable_ms(to_stm32_port(port)->gpios);
}
static void stm32_disable_ms(struct uart_port *port)
{
mctrl_gpio_disable_ms(to_stm32_port(port)->gpios);
}
/* Transmit stop */
@ -626,6 +642,9 @@ static void stm32_shutdown(struct uart_port *port)
u32 val, isr;
int ret;
/* Disable modem control interrupts */
stm32_disable_ms(port);
val = USART_CR1_TXEIE | USART_CR1_TE;
val |= stm32_port->cr1_irq | USART_CR1_RE;
val |= BIT(cfg->uart_enable_bit);
@ -764,6 +783,12 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
}
/* Handle modem control interrupts */
if (UART_ENABLE_MS(port, termios->c_cflag))
stm32_enable_ms(port);
else
stm32_disable_ms(port);
usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
/*
@ -898,6 +923,7 @@ static const struct uart_ops stm32_uart_ops = {
.throttle = stm32_throttle,
.unthrottle = stm32_unthrottle,
.stop_rx = stm32_stop_rx,
.enable_ms = stm32_enable_ms,
.break_ctl = stm32_break_ctl,
.startup = stm32_startup,
.shutdown = stm32_shutdown,
@ -931,7 +957,9 @@ static int stm32_init_port(struct stm32_port *stm32port,
port->rs485_config = stm32_config_rs485;
stm32_init_rs485(port, pdev);
ret = stm32_init_rs485(port, pdev);
if (ret)
return ret;
if (stm32port->info->cfg.has_wakeup) {
stm32port->wakeirq = platform_get_irq(pdev, 1);
@ -960,10 +988,31 @@ static int stm32_init_port(struct stm32_port *stm32port,
stm32port->port.uartclk = clk_get_rate(stm32port->clk);
if (!stm32port->port.uartclk) {
clk_disable_unprepare(stm32port->clk);
ret = -EINVAL;
goto err_clk;
}
stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0);
if (IS_ERR(stm32port->gpios)) {
ret = PTR_ERR(stm32port->gpios);
goto err_clk;
}
/* Both CTS/RTS gpios and "st,hw-flow-ctrl" should not be specified */
if (stm32port->hw_flow_control) {
if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) ||
mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) {
dev_err(&pdev->dev, "Conflicting RTS/CTS config\n");
ret = -EINVAL;
goto err_clk;
}
}
return ret;
err_clk:
clk_disable_unprepare(stm32port->clk);
return ret;
}
@ -1375,7 +1424,18 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev)
else
stm32_serial_enable_wakeup(port, false);
pinctrl_pm_select_sleep_state(dev);
/*
* When "no_console_suspend" is enabled, keep the pinctrl default state
* and rely on bootloader stage to restore this state upon resume.
* Otherwise, apply the idle or sleep states depending on wakeup
* capabilities.
*/
if (console_suspend_enabled || !uart_console(port)) {
if (device_may_wakeup(dev))
pinctrl_pm_select_idle_state(dev);
else
pinctrl_pm_select_sleep_state(dev);
}
return 0;
}

View File

@ -274,6 +274,7 @@ struct stm32_port {
bool fifoen;
int wakeirq;
int rdr_mask; /* receive data register mask */
struct mctrl_gpios *gpios; /* modem control gpios */
};
static struct stm32_port stm32_ports[STM32_MAX_PORTS];

View File

@ -1235,9 +1235,7 @@ static void cdns_uart_console_write(struct console *co, const char *s,
writel(ctrl, port->membase + CDNS_UART_CR);
uart_console_write(port, s, count, cdns_uart_console_putchar);
while ((readl(port->membase + CDNS_UART_SR) &
(CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE)) !=
CDNS_UART_SR_TXEMPTY)
while (cdns_uart_tx_empty(port) != TIOCSER_TEMT)
cpu_relax();
/* restore interrupt state */
@ -1262,6 +1260,7 @@ static int cdns_uart_console_setup(struct console *co, char *options)
int bits = 8;
int parity = 'n';
int flow = 'n';
unsigned long time_out;
if (!port->membase) {
pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
@ -1272,6 +1271,13 @@ static int cdns_uart_console_setup(struct console *co, char *options)
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
/* Wait for tx_empty before setting up the console */
time_out = jiffies + usecs_to_jiffies(TX_TIMEOUT);
while (time_before(jiffies, time_out) &&
cdns_uart_tx_empty(port) != TIOCSER_TEMT)
cpu_relax();
return uart_set_options(port, co, baud, parity, bits, flow);
}

View File

@ -106,7 +106,7 @@ static void sysrq_handle_loglevel(int key)
pr_info("Loglevel set to %d\n", i);
console_loglevel = i;
}
static struct sysrq_key_op sysrq_loglevel_op = {
static const struct sysrq_key_op sysrq_loglevel_op = {
.handler = sysrq_handle_loglevel,
.help_msg = "loglevel(0-9)",
.action_msg = "Changing Loglevel",
@ -119,14 +119,14 @@ static void sysrq_handle_SAK(int key)
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
schedule_work(SAK_work);
}
static struct sysrq_key_op sysrq_SAK_op = {
static const struct sysrq_key_op sysrq_SAK_op = {
.handler = sysrq_handle_SAK,
.help_msg = "sak(k)",
.action_msg = "SAK",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
#else
#define sysrq_SAK_op (*(struct sysrq_key_op *)NULL)
#define sysrq_SAK_op (*(const struct sysrq_key_op *)NULL)
#endif
#ifdef CONFIG_VT
@ -135,14 +135,14 @@ static void sysrq_handle_unraw(int key)
vt_reset_unicode(fg_console);
}
static struct sysrq_key_op sysrq_unraw_op = {
static const struct sysrq_key_op sysrq_unraw_op = {
.handler = sysrq_handle_unraw,
.help_msg = "unraw(r)",
.action_msg = "Keyboard mode set to system default",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
#else
#define sysrq_unraw_op (*(struct sysrq_key_op *)NULL)
#define sysrq_unraw_op (*(const struct sysrq_key_op *)NULL)
#endif /* CONFIG_VT */
static void sysrq_handle_crash(int key)
@ -152,7 +152,7 @@ static void sysrq_handle_crash(int key)
panic("sysrq triggered crash\n");
}
static struct sysrq_key_op sysrq_crash_op = {
static const struct sysrq_key_op sysrq_crash_op = {
.handler = sysrq_handle_crash,
.help_msg = "crash(c)",
.action_msg = "Trigger a crash",
@ -165,18 +165,20 @@ static void sysrq_handle_reboot(int key)
local_irq_enable();
emergency_restart();
}
static struct sysrq_key_op sysrq_reboot_op = {
static const struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reboot(b)",
.action_msg = "Resetting",
.enable_mask = SYSRQ_ENABLE_BOOT,
};
const struct sysrq_key_op *__sysrq_reboot_op = &sysrq_reboot_op;
static void sysrq_handle_sync(int key)
{
emergency_sync();
}
static struct sysrq_key_op sysrq_sync_op = {
static const struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "sync(s)",
.action_msg = "Emergency Sync",
@ -188,7 +190,7 @@ static void sysrq_handle_show_timers(int key)
sysrq_timer_list_show();
}
static struct sysrq_key_op sysrq_show_timers_op = {
static const struct sysrq_key_op sysrq_show_timers_op = {
.handler = sysrq_handle_show_timers,
.help_msg = "show-all-timers(q)",
.action_msg = "Show clockevent devices & pending hrtimers (no others)",
@ -198,7 +200,7 @@ static void sysrq_handle_mountro(int key)
{
emergency_remount();
}
static struct sysrq_key_op sysrq_mountro_op = {
static const struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "unmount(u)",
.action_msg = "Emergency Remount R/O",
@ -211,13 +213,13 @@ static void sysrq_handle_showlocks(int key)
debug_show_all_locks();
}
static struct sysrq_key_op sysrq_showlocks_op = {
static const struct sysrq_key_op sysrq_showlocks_op = {
.handler = sysrq_handle_showlocks,
.help_msg = "show-all-locks(d)",
.action_msg = "Show Locks Held",
};
#else
#define sysrq_showlocks_op (*(struct sysrq_key_op *)NULL)
#define sysrq_showlocks_op (*(const struct sysrq_key_op *)NULL)
#endif
#ifdef CONFIG_SMP
@ -264,7 +266,7 @@ static void sysrq_handle_showallcpus(int key)
}
}
static struct sysrq_key_op sysrq_showallcpus_op = {
static const struct sysrq_key_op sysrq_showallcpus_op = {
.handler = sysrq_handle_showallcpus,
.help_msg = "show-backtrace-all-active-cpus(l)",
.action_msg = "Show backtrace of all active CPUs",
@ -282,7 +284,7 @@ static void sysrq_handle_showregs(int key)
show_regs(regs);
perf_event_print_debug();
}
static struct sysrq_key_op sysrq_showregs_op = {
static const struct sysrq_key_op sysrq_showregs_op = {
.handler = sysrq_handle_showregs,
.help_msg = "show-registers(p)",
.action_msg = "Show Regs",
@ -294,7 +296,7 @@ static void sysrq_handle_showstate(int key)
show_state();
show_workqueue_state();
}
static struct sysrq_key_op sysrq_showstate_op = {
static const struct sysrq_key_op sysrq_showstate_op = {
.handler = sysrq_handle_showstate,
.help_msg = "show-task-states(t)",
.action_msg = "Show State",
@ -305,7 +307,7 @@ static void sysrq_handle_showstate_blocked(int key)
{
show_state_filter(TASK_UNINTERRUPTIBLE);
}
static struct sysrq_key_op sysrq_showstate_blocked_op = {
static const struct sysrq_key_op sysrq_showstate_blocked_op = {
.handler = sysrq_handle_showstate_blocked,
.help_msg = "show-blocked-tasks(w)",
.action_msg = "Show Blocked State",
@ -319,21 +321,21 @@ static void sysrq_ftrace_dump(int key)
{
ftrace_dump(DUMP_ALL);
}
static struct sysrq_key_op sysrq_ftrace_dump_op = {
static const struct sysrq_key_op sysrq_ftrace_dump_op = {
.handler = sysrq_ftrace_dump,
.help_msg = "dump-ftrace-buffer(z)",
.action_msg = "Dump ftrace buffer",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
#else
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL)
#define sysrq_ftrace_dump_op (*(const struct sysrq_key_op *)NULL)
#endif
static void sysrq_handle_showmem(int key)
{
show_mem(0, NULL);
}
static struct sysrq_key_op sysrq_showmem_op = {
static const struct sysrq_key_op sysrq_showmem_op = {
.handler = sysrq_handle_showmem,
.help_msg = "show-memory-usage(m)",
.action_msg = "Show Memory",
@ -364,7 +366,7 @@ static void sysrq_handle_term(int key)
send_sig_all(SIGTERM);
console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
}
static struct sysrq_key_op sysrq_term_op = {
static const struct sysrq_key_op sysrq_term_op = {
.handler = sysrq_handle_term,
.help_msg = "terminate-all-tasks(e)",
.action_msg = "Terminate All Tasks",
@ -394,7 +396,7 @@ static void sysrq_handle_moom(int key)
{
schedule_work(&moom_work);
}
static struct sysrq_key_op sysrq_moom_op = {
static const struct sysrq_key_op sysrq_moom_op = {
.handler = sysrq_handle_moom,
.help_msg = "memory-full-oom-kill(f)",
.action_msg = "Manual OOM execution",
@ -406,7 +408,7 @@ static void sysrq_handle_thaw(int key)
{
emergency_thaw_all();
}
static struct sysrq_key_op sysrq_thaw_op = {
static const struct sysrq_key_op sysrq_thaw_op = {
.handler = sysrq_handle_thaw,
.help_msg = "thaw-filesystems(j)",
.action_msg = "Emergency Thaw of all frozen filesystems",
@ -419,7 +421,7 @@ static void sysrq_handle_kill(int key)
send_sig_all(SIGKILL);
console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
}
static struct sysrq_key_op sysrq_kill_op = {
static const struct sysrq_key_op sysrq_kill_op = {
.handler = sysrq_handle_kill,
.help_msg = "kill-all-tasks(i)",
.action_msg = "Kill All Tasks",
@ -430,7 +432,7 @@ static void sysrq_handle_unrt(int key)
{
normalize_rt_tasks();
}
static struct sysrq_key_op sysrq_unrt_op = {
static const struct sysrq_key_op sysrq_unrt_op = {
.handler = sysrq_handle_unrt,
.help_msg = "nice-all-RT-tasks(n)",
.action_msg = "Nice All RT Tasks",
@ -440,7 +442,7 @@ static struct sysrq_key_op sysrq_unrt_op = {
/* Key Operations table and lock */
static DEFINE_SPINLOCK(sysrq_key_table_lock);
static struct sysrq_key_op *sysrq_key_table[36] = {
static const struct sysrq_key_op *sysrq_key_table[36] = {
&sysrq_loglevel_op, /* 0 */
&sysrq_loglevel_op, /* 1 */
&sysrq_loglevel_op, /* 2 */
@ -516,9 +518,9 @@ static int sysrq_key_table_key2index(int key)
/*
* get and put functions for the table, exposed to modules.
*/
struct sysrq_key_op *__sysrq_get_key_op(int key)
static const struct sysrq_key_op *__sysrq_get_key_op(int key)
{
struct sysrq_key_op *op_p = NULL;
const struct sysrq_key_op *op_p = NULL;
int i;
i = sysrq_key_table_key2index(key);
@ -528,7 +530,7 @@ struct sysrq_key_op *__sysrq_get_key_op(int key)
return op_p;
}
static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
static void __sysrq_put_key_op(int key, const struct sysrq_key_op *op_p)
{
int i = sysrq_key_table_key2index(key);
@ -538,7 +540,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
void __handle_sysrq(int key, bool check_mask)
{
struct sysrq_key_op *op_p;
const struct sysrq_key_op *op_p;
int orig_log_level;
int orig_suppress_printk;
int i;
@ -1061,8 +1063,8 @@ int sysrq_toggle_support(int enable_mask)
}
EXPORT_SYMBOL_GPL(sysrq_toggle_support);
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
struct sysrq_key_op *remove_op_p)
static int __sysrq_swap_key_ops(int key, const struct sysrq_key_op *insert_op_p,
const struct sysrq_key_op *remove_op_p)
{
int retval;
@ -1085,13 +1087,13 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
return retval;
}
int register_sysrq_key(int key, struct sysrq_key_op *op_p)
int register_sysrq_key(int key, const struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, op_p, NULL);
}
EXPORT_SYMBOL(register_sysrq_key);
int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
int unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, NULL, op_p);
}

View File

@ -605,6 +605,7 @@ static int vcc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
port->index = vcc_table_add(port);
if (port->index == -1) {
pr_err("VCC: no more TTY indices left for allocation\n");
rv = -ENOMEM;
goto free_ldc;
}

View File

@ -127,7 +127,11 @@ static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf' and friends */
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static bool dead_key_next;
static int npadch = -1; /* -1 or number assembled on pad */
/* Handles a number being assembled on the number pad */
static bool npadch_active;
static unsigned int npadch_value;
static unsigned int diacr;
static char rep; /* flag telling character repeat */
@ -845,12 +849,12 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
shift_state &= ~(1 << value);
/* kludge */
if (up_flag && shift_state != old_state && npadch != -1) {
if (up_flag && shift_state != old_state && npadch_active) {
if (kbd->kbdmode == VC_UNICODE)
to_utf8(vc, npadch);
to_utf8(vc, npadch_value);
else
put_queue(vc, npadch & 0xff);
npadch = -1;
put_queue(vc, npadch_value & 0xff);
npadch_active = false;
}
}
@ -868,7 +872,7 @@ static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
{
int base;
unsigned int base;
if (up_flag)
return;
@ -882,10 +886,12 @@ static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
base = 16;
}
if (npadch == -1)
npadch = value;
else
npadch = npadch * base + value;
if (!npadch_active) {
npadch_value = 0;
npadch_active = true;
}
npadch_value = npadch_value * base + value;
}
static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)

View File

@ -185,47 +185,54 @@ int set_selection_user(const struct tiocl_selection __user *sel,
return set_selection_kernel(&v, tty);
}
static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
{
struct vc_data *vc = vc_cons[fg_console].d;
int new_sel_start, new_sel_end, spc;
char *bp, *obp;
int i, ps, pe;
u32 c;
int ret = 0;
bool unicode;
unsigned int i;
poke_blanked_console();
v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
ps = v->ys * vc->vc_size_row + (v->xs << 1);
pe = v->ye * vc->vc_size_row + (v->xe << 1);
if (v->sel_mode == TIOCL_SELCLEAR) {
/* useful for screendump without selection highlights */
/* 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);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
return 0;
return -ENOMEM;
}
kfree(vc_sel.buffer);
vc_sel.buffer = bp;
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
v->ys);
return 0;
obp = bp;
for (i = vc_sel.start; i <= vc_sel.end; i += 2) {
u32 c = sel_pos(i, unicode);
if (unicode)
bp += store_utf8(c, bp);
else
*bp++ = c;
if (!isspace(c))
obp = bp;
if (!((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
unless non-space at end of line. */
if (obp != bp) {
bp = obp;
*bp++ = '\r';
}
obp = bp;
}
}
vc_sel.buf_len = bp - vc_sel.buffer;
if (ps > pe) /* make vc_sel.start <= vc_sel.end */
swap(ps, pe);
return 0;
}
if (vc_sel.cons != vc_cons[fg_console].d) {
clear_selection();
vc_sel.cons = vc_cons[fg_console].d;
}
unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE;
static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps,
int pe)
{
int new_sel_start, new_sel_end, spc;
bool unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE;
switch (v->sel_mode) {
switch (mode) {
case TIOCL_SELCHAR: /* character-by-character selection */
new_sel_start = ps;
new_sel_end = pe;
@ -303,40 +310,44 @@ static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *
vc_sel.start = new_sel_start;
vc_sel.end = new_sel_end;
/* 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);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
return vc_selection_store_chars(vc, unicode);
}
static int vc_selection(struct vc_data *vc, struct tiocl_selection *v,
struct tty_struct *tty)
{
int ps, pe;
poke_blanked_console();
if (v->sel_mode == TIOCL_SELCLEAR) {
/* useful for screendump without selection highlights */
clear_selection();
return -ENOMEM;
return 0;
}
kfree(vc_sel.buffer);
vc_sel.buffer = bp;
obp = bp;
for (i = vc_sel.start; i <= vc_sel.end; i += 2) {
c = sel_pos(i, unicode);
if (unicode)
bp += store_utf8(c, bp);
else
*bp++ = c;
if (!isspace(c))
obp = bp;
if (! ((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
unless non-space at end of line. */
if (obp != bp) {
bp = obp;
*bp++ = '\r';
}
obp = bp;
}
v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
v->ys);
return 0;
}
vc_sel.buf_len = bp - vc_sel.buffer;
return ret;
ps = v->ys * vc->vc_size_row + (v->xs << 1);
pe = v->ye * vc->vc_size_row + (v->xe << 1);
if (ps > pe) /* make vc_sel.start <= vc_sel.end */
swap(ps, pe);
if (vc_sel.cons != vc) {
clear_selection();
vc_sel.cons = vc;
}
return vc_do_selection(vc, v->sel_mode, ps, pe);
}
int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
@ -345,7 +356,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
mutex_lock(&vc_sel.lock);
console_lock();
ret = __set_selection_kernel(v, tty);
ret = vc_selection(vc_cons[fg_console].d, v, tty);
console_unlock();
mutex_unlock(&vc_sel.lock);

View File

@ -10,6 +10,7 @@
#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>
@ -251,6 +252,7 @@ struct uart_port {
struct attribute_group *attr_group; /* port specific attributes */
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
struct serial_rs485 rs485;
struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */
struct serial_iso7816 iso7816;
void *private_data; /* generic platform data pointer */
};
@ -472,5 +474,5 @@ extern int uart_handle_break(struct uart_port *port);
(cflag) & CRTSCTS || \
!((cflag) & CLOCAL))
void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf);
int uart_get_rs485_mode(struct uart_port *port);
#endif /* LINUX_SERIAL_CORE_H */

View File

@ -30,10 +30,10 @@
#define SYSRQ_ENABLE_RTNICE 0x0100
struct sysrq_key_op {
void (*handler)(int);
char *help_msg;
char *action_msg;
int enable_mask;
void (* const handler)(int);
const char * const help_msg;
const char * const action_msg;
const int enable_mask;
};
#ifdef CONFIG_MAGIC_SYSRQ
@ -45,9 +45,9 @@ struct sysrq_key_op {
void handle_sysrq(int key);
void __handle_sysrq(int key, bool check_mask);
int register_sysrq_key(int key, struct sysrq_key_op *op);
int unregister_sysrq_key(int key, struct sysrq_key_op *op);
struct sysrq_key_op *__sysrq_get_key_op(int key);
int register_sysrq_key(int key, const struct sysrq_key_op *op);
int unregister_sysrq_key(int key, const struct sysrq_key_op *op);
extern const struct sysrq_key_op *__sysrq_reboot_op;
int sysrq_toggle_support(int enable_mask);
int sysrq_mask(void);
@ -62,12 +62,12 @@ static inline void __handle_sysrq(int key, bool check_mask)
{
}
static inline int register_sysrq_key(int key, struct sysrq_key_op *op)
static inline int register_sysrq_key(int key, const struct sysrq_key_op *op)
{
return -EINVAL;
}
static inline int unregister_sysrq_key(int key, struct sysrq_key_op *op)
static inline int unregister_sysrq_key(int key, const struct sysrq_key_op *op)
{
return -EINVAL;
}

View File

@ -935,7 +935,7 @@ static void sysrq_handle_dbg(int key)
kgdb_breakpoint();
}
static struct sysrq_key_op sysrq_dbg_op = {
static const struct sysrq_key_op sysrq_dbg_op = {
.handler = sysrq_handle_dbg,
.help_msg = "debug(g)",
.action_msg = "DEBUG",

View File

@ -29,7 +29,7 @@ static void handle_poweroff(int key)
schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work);
}
static struct sysrq_key_op sysrq_poweroff_op = {
static const struct sysrq_key_op sysrq_poweroff_op = {
.handler = handle_poweroff,
.help_msg = "poweroff(o)",
.action_msg = "Power Off",

View File

@ -807,7 +807,7 @@ static void sysrq_show_rcu(int key)
show_rcu_gp_kthreads();
}
static struct sysrq_key_op sysrq_rcudump_op = {
static const struct sysrq_key_op sysrq_rcudump_op = {
.handler = sysrq_show_rcu,
.help_msg = "show-rcu(y)",
.action_msg = "Show RCU tree",