From 732dbf3a6104a3abfcfcd066dcaf89e5054ce009 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 22 Dec 2016 08:31:34 +0100 Subject: serial: do not accept sysrq characters via serial port many embedded boards have a disconnected TTL level serial which can generate some garbage that can lead to spurious false sysrq detects. Signed-off-by: John Crispin Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 5def8e830fb0..58484fb35cc8 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -450,7 +450,7 @@ extern void uart_handle_cts_change(struct uart_port *uport, extern void uart_insert_char(struct uart_port *port, unsigned int status, unsigned int overrun, unsigned int ch, unsigned int flag); -#ifdef SUPPORT_SYSRQ +#if defined(SUPPORT_SYSRQ) && defined(CONFIG_MAGIC_SYSRQ_SERIAL) static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) { -- cgit v1.2.3 From 219fb0c1436e4893a290ba270bc0e644d02465a3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:37 +0200 Subject: serial: sh-sci: Remove the platform data dma slave rx/tx channel IDs Only SH platforms still use platform data for the sh-sci, and none of them declare DMA channels connected to the SCI. Remove the corresponding platform data fields and simplify the driver accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_sci.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 9f2bfd055742..1a894c47bfc0 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -71,9 +71,6 @@ struct plat_sci_port { unsigned char regtype; struct plat_sci_port_ops *ops; - - unsigned int dma_slave_tx; - unsigned int dma_slave_rx; }; #endif /* __LINUX_SERIAL_SCI_H */ -- cgit v1.2.3 From d5cb1319a91d4f1328b1c70b82c5899acd96af85 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:38 +0200 Subject: serial: sh-sci: Remove manual break debouncing The sh-sci driver implements manual break debouncing for a few SH platforms by reading the value of the RX pin port register. This feature is optional and the driver considers all negative or zero values of the platform data port_reg field as invalid. As the four platforms that set the field to a register address all use an address higher than 0x7fffffff, the driver will always consider the value as invalid and never perform debouncing. The feature is unused, remove it. Debouncing could be implemented properly in the future using the pinctrl and GPIO APIs if desired. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_sci.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 1a894c47bfc0..b4419931bf4c 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -9,8 +9,6 @@ * Generic header for SuperH (H)SCI(F) (used by sh/sh64 and related parts) */ -#define SCIx_NOT_SUPPORTED (-1) - /* Serial Control Register (@ = not supported by all parts) */ #define SCSCR_TIE BIT(7) /* Transmit Interrupt Enable */ #define SCSCR_RIE BIT(6) /* Receive Interrupt Enable */ @@ -41,8 +39,6 @@ enum { SCIx_NR_REGTYPES, }; -struct device; - struct plat_sci_port_ops { void (*init_pins)(struct uart_port *, unsigned int cflag); }; @@ -66,7 +62,6 @@ struct plat_sci_port { /* * Platform overrides if necessary, defaults otherwise. */ - int port_reg; unsigned char regshift; unsigned char regtype; -- cgit v1.2.3 From 97ed9790c514066bfae67f22e084b505ed5af436 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:39 +0200 Subject: serial: sh-sci: Remove unused platform data capabilities field The field isn't set by any platform but is only used internally in the driver to hold data parsed from DT. Move it to the sci_port structure. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_sci.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index b4419931bf4c..f9a4526f4ec5 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -43,18 +43,12 @@ struct plat_sci_port_ops { void (*init_pins)(struct uart_port *, unsigned int cflag); }; -/* - * Port-specific capabilities - */ -#define SCIx_HAVE_RTSCTS BIT(0) - /* * Platform device specific platform_data struct */ struct plat_sci_port { unsigned int type; /* SCI / SCIF / IRDA / HSCIF */ upf_t flags; /* UPF_* flags */ - unsigned long capabilities; /* Port features/capabilities */ unsigned int sampling_rate; unsigned int scscr; /* SCSCR initialization */ -- cgit v1.2.3 From dfc80387aefb78161f83732804c6d01c89c24595 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 11 Jan 2017 16:43:40 +0200 Subject: serial: sh-sci: Compute the regshift value for SCI ports SCI instances found in SH SoCs have different spacing between registers depending on the SoC. The platform data contains a regshift field that tells the driver by how many bits to shift the register offset to compute its address. We can compute the regshift value automatically based on the memory resource size, there's no need to pass the value through platform data. Fix the sh7750 SCI and sh7760 SIM port memory resources length to ensure proper computation of the regshift value. Signed-off-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_sci.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index f9a4526f4ec5..e598eaef3962 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -56,7 +56,6 @@ struct plat_sci_port { /* * Platform overrides if necessary, defaults otherwise. */ - unsigned char regshift; unsigned char regtype; struct plat_sci_port_ops *ops; -- cgit v1.2.3 From 9ed90d20449b01beb71a4e125d291a36c80c4ad4 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 16 Jan 2017 16:54:28 -0600 Subject: tty: move the non-file related parts of tty_release to new tty_release_struct For in-kernel tty users, we need to be able to create and destroy 'struct tty' that are not associated with a file. The creation side is fine, but tty_release() needs to be split into the file handle portion and the struct tty portion. Introduce a new function, tty_release_struct, to handle just the destroying of a struct tty. Signed-off-by: Rob Herring Reviewed-by: Andy Shevchenko Reviewed-By: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/tty.h b/include/linux/tty.h index 40144f382516..86c7853282b7 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -528,6 +528,7 @@ extern int tty_alloc_file(struct file *file); extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void tty_free_file(struct file *file); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); +extern void tty_release_struct(struct tty_struct *tty, int idx); extern int tty_release(struct inode *inode, struct file *filp); extern void tty_init_termios(struct tty_struct *tty); extern int tty_standard_install(struct tty_driver *driver, -- cgit v1.2.3 From c92d781f1a5ea19708b1e1e2b85a3fbd4a738b30 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 16 Jan 2017 16:54:31 -0600 Subject: tty: constify tty_ldisc_receive_buf buffer pointer This is needed to work with the client operations which uses const ptrs. Really, the flags pointer could be const, too, but this would be a tree wide fix. Signed-off-by: Rob Herring Reviewed-by: Andy Shevchenko Reviewed-By: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/tty.h b/include/linux/tty.h index 86c7853282b7..21c0fabfed60 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -657,7 +657,7 @@ extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); -extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, +extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, char *f, int count); /* n_tty.c */ -- cgit v1.2.3 From bcd375f7f71f7106c97516bf5395149954ef8810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6lling?= Date: Fri, 13 Jan 2017 21:07:56 +0100 Subject: console: Add callback to flush scrollback buffer to consw struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new callback is in preparation for persistent scrollback buffer support for VGA consoles. With a single scrollback buffer for all consoles, we could flush the buffer just by invocating consw->con_switch(). But when each VGA console has its own scrollback buffer, we need a new callback to tell the video console driver which buffer to flush. Signed-off-by: Manuel Schölling Reviewed-by: Andrey Utkin Tested-by: Andrey Utkin Tested-by: Adam Borowski Signed-off-by: Greg Kroah-Hartman --- include/linux/console.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/console.h b/include/linux/console.h index 9c26c6685587..5949d1855589 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -72,6 +72,10 @@ struct consw { void (*con_invert_region)(struct vc_data *, u16 *, int); u16 *(*con_screen_pos)(struct vc_data *, int); unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *); + /* + * Flush the video console driver's scrollback buffer + */ + void (*con_flush_scrollback)(struct vc_data *); /* * Prepare the console for the debugger. This includes, but is not * limited to, unblanking the console, loading an appropriate -- cgit v1.2.3 From c3485ee0d560b182e1e0f67d67246718739f0782 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 2 Feb 2017 13:48:05 -0600 Subject: tty_port: Add port client functions Introduce a client (upward direction) operations struct for tty_port clients. Initially supported operations are for receiving data and write wake-up. This will allow for having clients other than an ldisc. Convert the calls to the ldisc to use the client ops as the default operations. Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel Tested-By: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/tty.h b/include/linux/tty.h index 21c0fabfed60..1017e904c0a3 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -217,12 +217,18 @@ struct tty_port_operations { /* Called on the final put of a port */ void (*destruct)(struct tty_port *port); }; - + +struct tty_port_client_operations { + int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t); + void (*write_wakeup)(struct tty_port *port); +}; + struct tty_port { struct tty_bufhead buf; /* Locked internally */ struct tty_struct *tty; /* Back pointer */ struct tty_struct *itty; /* internal back ptr */ const struct tty_port_operations *ops; /* Port operations */ + const struct tty_port_client_operations *client_ops; /* Port client operations */ spinlock_t lock; /* Lock protecting tty field */ int blocked_open; /* Waiting to open */ int count; /* Usage count */ @@ -241,6 +247,7 @@ struct tty_port { based drain is needed else set to size of fifo */ struct kref kref; /* Ref counter */ + void *client_data; }; /* tty_port::iflags bits -- use atomic bit ops */ -- cgit v1.2.3 From cd6484e1830be260abfba80a9c7d8f65531126d6 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 2 Feb 2017 13:48:07 -0600 Subject: serdev: Introduce new bus for serial attached devices The serdev bus is designed for devices such as Bluetooth, WiFi, GPS and NFC connected to UARTs on host processors. Tradionally these have been handled with tty line disciplines, rfkill, and userspace glue such as hciattach. This approach has many drawbacks since it doesn't fit into the Linux driver model. Handling of sideband signals, power control and firmware loading are the main issues. This creates a serdev bus with controllers (i.e. host serial ports) and attached devices. Typically, these are point to point connections, but some devices have muxing protocols or a h/w mux is conceivable. Any muxing is not yet supported with the serdev bus. Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel Tested-By: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- include/linux/serdev.h | 241 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 include/linux/serdev.h (limited to 'include/linux') diff --git a/include/linux/serdev.h b/include/linux/serdev.h new file mode 100644 index 000000000000..3ac26c1a8aab --- /dev/null +++ b/include/linux/serdev.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _LINUX_SERDEV_H +#define _LINUX_SERDEV_H + +#include +#include + +struct serdev_controller; +struct serdev_device; + +/* + * serdev device structures + */ + +/** + * struct serdev_device_ops - Callback operations for a serdev device + * @receive_buf: Function called with data received from device. + * @write_wakeup: Function called when ready to transmit more data. + */ +struct serdev_device_ops { + int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t); + void (*write_wakeup)(struct serdev_device *); +}; + +/** + * struct serdev_device - Basic representation of an serdev device + * @dev: Driver model representation of the device. + * @nr: Device number on serdev bus. + * @ctrl: serdev controller managing this device. + * @ops: Device operations. + */ +struct serdev_device { + struct device dev; + int nr; + struct serdev_controller *ctrl; + const struct serdev_device_ops *ops; +}; + +static inline struct serdev_device *to_serdev_device(struct device *d) +{ + return container_of(d, struct serdev_device, dev); +} + +/** + * struct serdev_device_driver - serdev slave device driver + * @driver: serdev device drivers should initialize name field of this + * structure. + * @probe: binds this driver to a serdev device. + * @remove: unbinds this driver from the serdev device. + */ +struct serdev_device_driver { + struct device_driver driver; + int (*probe)(struct serdev_device *); + void (*remove)(struct serdev_device *); +}; + +static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d) +{ + return container_of(d, struct serdev_device_driver, driver); +} + +/* + * serdev controller structures + */ +struct serdev_controller_ops { + int (*write_buf)(struct serdev_controller *, const unsigned char *, size_t); + void (*write_flush)(struct serdev_controller *); + int (*write_room)(struct serdev_controller *); + int (*open)(struct serdev_controller *); + void (*close)(struct serdev_controller *); + void (*set_flow_control)(struct serdev_controller *, bool); + unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int); +}; + +/** + * struct serdev_controller - interface to the serdev controller + * @dev: Driver model representation of the device. + * @nr: number identifier for this controller/bus. + * @serdev: Pointer to slave device for this controller. + * @ops: Controller operations. + */ +struct serdev_controller { + struct device dev; + unsigned int nr; + struct serdev_device *serdev; + const struct serdev_controller_ops *ops; +}; + +static inline struct serdev_controller *to_serdev_controller(struct device *d) +{ + return container_of(d, struct serdev_controller, dev); +} + +static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev) +{ + return dev_get_drvdata(&serdev->dev); +} + +static inline void serdev_device_set_drvdata(struct serdev_device *serdev, void *data) +{ + dev_set_drvdata(&serdev->dev, data); +} + +/** + * serdev_device_put() - decrement serdev device refcount + * @serdev serdev device. + */ +static inline void serdev_device_put(struct serdev_device *serdev) +{ + if (serdev) + put_device(&serdev->dev); +} + +static inline void serdev_device_set_client_ops(struct serdev_device *serdev, + const struct serdev_device_ops *ops) +{ + serdev->ops = ops; +} + +static inline +void *serdev_controller_get_drvdata(const struct serdev_controller *ctrl) +{ + return ctrl ? dev_get_drvdata(&ctrl->dev) : NULL; +} + +static inline void serdev_controller_set_drvdata(struct serdev_controller *ctrl, + void *data) +{ + dev_set_drvdata(&ctrl->dev, data); +} + +/** + * serdev_controller_put() - decrement controller refcount + * @ctrl serdev controller. + */ +static inline void serdev_controller_put(struct serdev_controller *ctrl) +{ + if (ctrl) + put_device(&ctrl->dev); +} + +struct serdev_device *serdev_device_alloc(struct serdev_controller *); +int serdev_device_add(struct serdev_device *); +void serdev_device_remove(struct serdev_device *); + +struct serdev_controller *serdev_controller_alloc(struct device *, size_t); +int serdev_controller_add(struct serdev_controller *); +void serdev_controller_remove(struct serdev_controller *); + +static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl) +{ + struct serdev_device *serdev = ctrl->serdev; + + if (!serdev || !serdev->ops->write_wakeup) + return; + + serdev->ops->write_wakeup(ctrl->serdev); +} + +static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, + const unsigned char *data, + size_t count) +{ + struct serdev_device *serdev = ctrl->serdev; + + if (!serdev || !serdev->ops->receive_buf) + return -EINVAL; + + return serdev->ops->receive_buf(ctrl->serdev, data, count); +} + +#if IS_ENABLED(CONFIG_SERIAL_DEV_BUS) + +int serdev_device_open(struct serdev_device *); +void serdev_device_close(struct serdev_device *); +unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); +void serdev_device_set_flow_control(struct serdev_device *, bool); +int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); +void serdev_device_write_flush(struct serdev_device *); +int serdev_device_write_room(struct serdev_device *); + +/* + * serdev device driver functions + */ +int __serdev_device_driver_register(struct serdev_device_driver *, struct module *); +#define serdev_device_driver_register(sdrv) \ + __serdev_device_driver_register(sdrv, THIS_MODULE) + +/** + * serdev_device_driver_unregister() - unregister an serdev client driver + * @sdrv: the driver to unregister + */ +static inline void serdev_device_driver_unregister(struct serdev_device_driver *sdrv) +{ + if (sdrv) + driver_unregister(&sdrv->driver); +} + +#define module_serdev_device_driver(__serdev_device_driver) \ + module_driver(__serdev_device_driver, serdev_device_driver_register, \ + serdev_device_driver_unregister) + +#else + +static inline int serdev_device_open(struct serdev_device *sdev) +{ + return -ENODEV; +} +static inline void serdev_device_close(struct serdev_device *sdev) {} +static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev, unsigned int baudrate) +{ + return 0; +} +static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} +static inline int serdev_device_write_buf(struct serdev_device *sdev, const unsigned char *buf, size_t count) +{ + return -ENODEV; +} +static inline void serdev_device_write_flush(struct serdev_device *sdev) {} +static inline int serdev_device_write_room(struct serdev_device *sdev) +{ + return 0; +} + +#define serdev_device_driver_register(x) +#define serdev_device_driver_unregister(x) + +#endif /* CONFIG_SERIAL_DEV_BUS */ + +#endif /*_LINUX_SERDEV_H */ -- cgit v1.2.3 From bed35c6dfa6a36233c3e1238a40dc1ae67955898 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 2 Feb 2017 13:48:08 -0600 Subject: serdev: add a tty port controller driver Add a serdev controller driver for tty ports. The controller is registered with serdev when tty ports are registered with the TTY core. As the TTY core is built-in only, this has the side effect of making serdev built-in as well. Signed-off-by: Rob Herring Reviewed-By: Sebastian Reichel Tested-By: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- include/linux/serdev.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'include/linux') diff --git a/include/linux/serdev.h b/include/linux/serdev.h index 3ac26c1a8aab..9519da6253a8 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -238,4 +238,25 @@ static inline int serdev_device_write_room(struct serdev_device *sdev) #endif /* CONFIG_SERIAL_DEV_BUS */ +/* + * serdev hooks into TTY core + */ +struct tty_port; +struct tty_driver; + +#ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT +struct device *serdev_tty_port_register(struct tty_port *port, + struct device *parent, + struct tty_driver *drv, int idx); +void serdev_tty_port_unregister(struct tty_port *port); +#else +static inline struct device *serdev_tty_port_register(struct tty_port *port, + struct device *parent, + struct tty_driver *drv, int idx) +{ + return ERR_PTR(-ENODEV); +} +static inline void serdev_tty_port_unregister(struct tty_port *port) {} +#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ + #endif /*_LINUX_SERDEV_H */ -- cgit v1.2.3