From: NeilBrown <neil@brown.name>
To: Mark Rutland <mark.rutland@arm.com>,
One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>,
Peter Hurley <peter@hurleysoftware.com>,
Arnd Bergmann <arnd@arndb.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sebastian Reichel <sre@kernel.org>, Pavel Machek <pavel@ucw.cz>,
Grant Likely <grant.likely@linaro.org>,
Jiri Slaby <jslaby@suse.cz>
Cc: GTA04 owners <gta04-owner@goldelico.com>,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 2/3] TTY: add support for tty_slave devices.
Date: Wed, 18 Mar 2015 16:58:31 +1100 [thread overview]
Message-ID: <20150318055831.21025.85317.stgit@notabene.brown> (raw)
In-Reply-To: <20150318055437.21025.13990.stgit@notabene.brown>
A "tty slave" is a device connected via UART.
Such a device may need its own driver, e.g. for powering
it up on tty open and powering it down on tty release.
tty-slave is a new bus-type which drivers can be written and devices
created.
A "tty slave" device is declared as a child of the uart in
device-tree:
&uart1 {
bluetooth {
compatible = "wi2wi,w2cbw003";
vdd-supply = <&vaux4>;
};
};
This device will be inserted in the driver-model tree between the uart
and the tty.
The tty-slave driver can replace any of the tty_operations functions
so a call by the tty can be intercepted before being handled by the uart.
Signed-off-by: NeilBrown <neil@brown.name>
---
drivers/tty/Kconfig | 1
drivers/tty/Makefile | 1
drivers/tty/slave/Kconfig | 7 ++
drivers/tty/slave/Makefile | 2 +
drivers/tty/slave/tty_slave_core.c | 136 ++++++++++++++++++++++++++++++++++++
drivers/tty/tty_io.c | 54 +++++++++++---
include/linux/tty.h | 1
include/linux/tty_slave.h | 26 +++++++
8 files changed, 215 insertions(+), 13 deletions(-)
create mode 100644 drivers/tty/slave/Kconfig
create mode 100644 drivers/tty/slave/Makefile
create mode 100644 drivers/tty/slave/tty_slave_core.c
create mode 100644 include/linux/tty_slave.h
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index b24aa010f68c..f9155a45ee7c 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -419,4 +419,5 @@ config DA_CONSOLE
help
This enables a console on a Dash channel.
+source drivers/tty/slave/Kconfig
endif # TTY
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 58ad1c05b7f8..ec57846eac29 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o
obj-$(CONFIG_DA_TTY) += metag_da.o
obj-y += ipwireless/
+obj-y += slave/
diff --git a/drivers/tty/slave/Kconfig b/drivers/tty/slave/Kconfig
new file mode 100644
index 000000000000..3976760c2e28
--- /dev/null
+++ b/drivers/tty/slave/Kconfig
@@ -0,0 +1,7 @@
+menuconfig TTY_SLAVE
+ tristate "TTY slave devices"
+ depends on OF
+ help
+ Devices which attach via a uart, but need extra
+ driver support for power management etc.
+
diff --git a/drivers/tty/slave/Makefile b/drivers/tty/slave/Makefile
new file mode 100644
index 000000000000..65669acb392e
--- /dev/null
+++ b/drivers/tty/slave/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_TTY_SLAVE) += tty_slave_core.o
diff --git a/drivers/tty/slave/tty_slave_core.c b/drivers/tty/slave/tty_slave_core.c
new file mode 100644
index 000000000000..6218ea5bb69e
--- /dev/null
+++ b/drivers/tty/slave/tty_slave_core.c
@@ -0,0 +1,136 @@
+/*
+ * tty-slave-core - device bus for tty slaves
+ *
+ * Copyright (C) 2015 NeilBrown <neil@brown.name>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * A "tty-slave" is a device permanently attached to a particularly
+ * tty, typically wired to a UART.
+ * A tty-slave has two particular roles.
+ * Firstly it can intercept any tty_operations to provide extra control
+ * of the device. For example it might intercept "open" and "close"
+ * in order to power the device up and down. It might intercept
+ * "hangup" to toggle a reset line on the device.
+ *
+ * Secondly it appears as a parent of the tty in the device model, so
+ * that any attributes it presents are visible to udev when the tty
+ * is added. This allows udev to start appropriate handlers such as
+ * hciattach or inputattach.
+ *
+ * tty-slave devices must be described in devicetree as a child node
+ * of the node which described the parent of the tty, typically a
+ * UART.
+ * If such a child is present, the tty device will not be registered
+ * until the slave device is fully probed and initialized.
+ */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_slave.h>
+
+
+static int tty_slave_match(struct device *dev, struct device_driver *drv)
+{
+ return of_driver_match_device(dev, drv);
+}
+
+static void tty_slave_release(struct device *dev)
+{
+ kfree(dev);
+}
+
+struct bus_type tty_slave_bus_type = {
+ .name = "tty-slave",
+ .match = tty_slave_match,
+};
+
+int tty_slave_register(struct device *parent, struct device_node *node,
+ struct device *tty, struct tty_driver *drv)
+{
+ struct tty_slave *slave;
+ int retval;
+
+ if (!of_get_property(node, "compatible", NULL))
+ return -ENODEV;
+
+ slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+ if (!slave)
+ return -ENOMEM;
+
+ slave->dev.bus = &tty_slave_bus_type;
+ slave->dev.parent = parent;
+ slave->dev.release = tty_slave_release;
+ slave->dev.of_node = of_node_get(node);
+ dev_set_name(&slave->dev, "%s", node->name);
+ slave->tty_dev = tty;
+ slave->tty_drv = drv;
+ slave->ops = *drv->ops;
+ retval = device_register(&slave->dev);
+ if (retval) {
+ of_node_put(node);
+ kfree(slave);
+ }
+ return retval;
+}
+EXPORT_SYMBOL(tty_slave_register);
+
+void tty_slave_activate(struct tty_struct *tty)
+{
+ struct device *parent = NULL;
+ if (tty->dev)
+ parent = tty->dev->parent;
+ if (parent &&
+ parent->bus == &tty_slave_bus_type)
+ {
+ struct tty_slave *dev =
+ container_of(parent, struct tty_slave, dev);
+ tty->ops = &dev->ops;
+ }
+}
+EXPORT_SYMBOL(tty_slave_activate);
+
+int tty_slave_finalize(struct tty_slave *slave)
+{
+ slave->tty_dev->parent = &slave->dev;
+ return tty_register_finalize(slave->tty_drv,
+ slave->tty_dev);
+}
+EXPORT_SYMBOL(tty_slave_finalize);
+
+int tty_slave_driver_register(struct device_driver *drv)
+{
+ drv->bus = &tty_slave_bus_type;
+ return driver_register(drv);
+}
+EXPORT_SYMBOL(tty_slave_driver_register);
+
+static int __init tty_slave_init(void)
+{
+ return bus_register(&tty_slave_bus_type);
+}
+
+static void __exit tty_slave_exit(void)
+{
+ bus_unregister(&tty_slave_bus_type);
+}
+
+postcore_initcall(tty_slave_init);
+module_exit(tty_slave_exit);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 27632ad17d6f..2b2d3b549a58 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -95,6 +95,8 @@
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/ratelimit.h>
+#include <linux/of.h>
+#include <linux/tty_slave.h>
#include <linux/uaccess.h>
@@ -3124,6 +3126,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
tty->index = idx;
tty_line_name(driver, idx, tty->name);
tty->dev = tty_get_device(tty);
+ tty_slave_activate(tty);
return tty;
}
@@ -3205,6 +3208,29 @@ static void tty_device_create_release(struct device *dev)
kfree(dev);
}
+int tty_register_finalize(struct tty_driver *driver, struct device *dev)
+{
+ int retval;
+ bool cdev = false;
+ int index = dev->devt - MKDEV(driver->major,
+ driver->minor_start);
+ printk("REGISTER %d %d 0x%x %d\n", driver->major, driver->minor_start, dev->devt, index);
+ if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+ retval = tty_cdev_add(driver,
+ dev->devt,
+ index, 1);
+ if (retval)
+ return retval;
+ cdev = true;
+ }
+ retval = device_register(dev);
+ if (retval == 0)
+ return 0;
+ if (cdev)
+ cdev_del(&driver->cdevs[index]);
+ return retval;
+}
+EXPORT_SYMBOL(tty_register_finalize);
/**
* tty_register_device_attr - register a tty device
* @driver: the tty driver that describes the tty device
@@ -3234,7 +3260,8 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
struct device *dev = NULL;
int retval = -ENODEV;
- bool cdev = false;
+ struct device_node *node;
+ bool slave_registered = false;
if (index >= driver->num) {
printk(KERN_ERR "Attempt to register invalid tty line number "
@@ -3247,13 +3274,6 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
else
tty_line_name(driver, index, name);
- if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
- retval = tty_cdev_add(driver, devt, index, 1);
- if (retval)
- goto error;
- cdev = true;
- }
-
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
retval = -ENOMEM;
@@ -3268,16 +3288,24 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
dev->groups = attr_grp;
dev_set_drvdata(dev, drvdata);
- retval = device_register(dev);
- if (retval)
- goto error;
+ if (device && device->of_node)
+ for_each_available_child_of_node(device->of_node, node) {
+ if (tty_slave_register(device, node, dev, driver) == 0)
+ slave_registered = true;
+ if (slave_registered)
+ break;
+ }
+
+ if (!slave_registered) {
+ retval = tty_register_finalize(driver, dev);
+ if (retval)
+ goto error;
+ }
return dev;
error:
put_device(dev);
- if (cdev)
- cdev_del(&driver->cdevs[index]);
return ERR_PTR(retval);
}
EXPORT_SYMBOL_GPL(tty_register_device_attr);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 04d5f1213700..efb4e053b856 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -373,6 +373,7 @@ extern void proc_clear_tty(struct task_struct *p);
extern struct tty_struct *get_current_tty(void);
/* tty_io.c */
extern int __init tty_init(void);
+extern int tty_register_finalize(struct tty_driver *driver, struct device *dev);
#else
static inline void console_init(void)
{ }
diff --git a/include/linux/tty_slave.h b/include/linux/tty_slave.h
new file mode 100644
index 000000000000..21bfd7c01a2e
--- /dev/null
+++ b/include/linux/tty_slave.h
@@ -0,0 +1,26 @@
+
+struct tty_slave {
+ struct device *tty_dev;
+ struct tty_driver *tty_drv;
+ struct tty_operations ops;
+ struct device dev;
+};
+
+int tty_slave_finalize(struct tty_slave *slave);
+int tty_slave_driver_register(struct device_driver *drv);
+#if config_enabled(CONFIG_TTY_SLAVE)
+void tty_slave_activate(struct tty_struct *tty);
+int tty_slave_register(struct device *parent, struct device_node *node,
+ struct device *tty, struct tty_driver *drv);
+#else
+static inline void tty_slave_activate(struct tty_struct *tty)
+{
+}
+static inline int tty_slave_register(struct device *parent,
+ struct device_node *node,
+ struct device *tty,
+ struct tty_driver *drv)
+{
+ return -ENODEV;
+}
+#endif
next prev parent reply other threads:[~2015-03-18 5:58 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-18 5:58 [PATCH 0/3] tty slave device support - version 3 NeilBrown
2015-03-18 5:58 ` NeilBrown [this message]
2015-03-18 9:11 ` [PATCH 2/3] TTY: add support for tty_slave devices Paul Bolle
2015-03-22 3:32 ` NeilBrown
2015-03-20 19:41 ` Pavel Machek
2015-03-22 3:42 ` [Gta04-owner] " NeilBrown
[not found] ` <20150322144209.14abc603-wvvUuzkyo1EYVZTmpyfIwg@public.gmane.org>
2015-03-22 7:58 ` Pavel Machek
2015-03-24 10:31 ` Jiri Slaby
2015-03-30 23:45 ` NeilBrown
2015-03-25 16:30 ` Peter Hurley
2015-03-25 21:17 ` [Gta04-owner] " NeilBrown
2015-03-27 11:09 ` Peter Hurley
2015-03-31 0:33 ` NeilBrown
2015-03-18 5:58 ` [PATCH 1/3] TTY: use class_find_device to find port in uart_suspend/resume NeilBrown
[not found] ` <20150318055831.21025.27864.stgit-wvvUuzkyo1EYVZTmpyfIwg@public.gmane.org>
2015-03-25 16:20 ` Peter Hurley
2015-03-29 21:49 ` [Gta04-owner] " NeilBrown
2015-03-18 5:58 ` [PATCH 3/3] tty/slaves: add a driver to power on/off UART attached devices NeilBrown
[not found] ` <20150318055831.21025.33670.stgit-wvvUuzkyo1EYVZTmpyfIwg@public.gmane.org>
2015-03-20 7:54 ` [Gta04-owner] " Dr. H. Nikolaus Schaller
[not found] ` <C53A3E5D-5AEA-4F0F-88A9-F9BC8CB0D0D6-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-03-20 8:54 ` NeilBrown
2015-03-20 9:34 ` Dr. H. Nikolaus Schaller
[not found] ` <14FB51CF-9568-4BF4-B917-2C019D992FDB-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-03-20 19:50 ` Pavel Machek
2015-03-20 23:31 ` NeilBrown
2015-03-24 17:58 ` Dr. H. Nikolaus Schaller
2015-03-25 1:45 ` Sebastian Reichel
2015-03-25 7:59 ` Dr. H. Nikolaus Schaller
2015-03-25 15:21 ` Sebastian Reichel
2015-03-25 16:44 ` Dr. H. Nikolaus Schaller
2015-03-26 18:08 ` Sebastian Reichel
2015-03-27 9:22 ` Dr. H. Nikolaus Schaller
2015-03-27 16:31 ` Sebastian Reichel
2015-03-27 17:11 ` Dr. H. Nikolaus Schaller
2015-04-27 20:35 ` Pavel Machek
2015-04-29 6:56 ` Dr. H. Nikolaus Schaller
2015-03-25 20:53 ` Pavel Machek
2015-03-25 21:25 ` Dr. H. Nikolaus Schaller
[not found] ` <1F3B5E32-1330-457C-AE25-791319293C38-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-03-26 5:56 ` Pavel Machek
2015-03-26 6:44 ` Dr. H. Nikolaus Schaller
[not found] ` <365B2C25-1782-4ADE-B620-190A4CC5E8E3-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-04-04 7:52 ` Pavel Machek
2015-03-25 20:42 ` Pavel Machek
2015-03-25 21:22 ` Dr. H. Nikolaus Schaller
2015-03-20 7:54 ` [Gta04-owner] [PATCH 0/3] tty slave device support - version 3 Dr. H. Nikolaus Schaller
[not found] ` <80D7E742-4633-4CCD-B754-221387D82922-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-03-20 8:43 ` NeilBrown
2015-03-20 8:54 ` Dr. H. Nikolaus Schaller
2015-03-20 13:08 ` Sebastian Reichel
2015-03-20 13:57 ` Dr. H. Nikolaus Schaller
[not found] ` <72268D51-F993-497A-B4F9-707C8DB7155C-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-03-20 17:14 ` Sebastian Reichel
2015-03-20 19:31 ` Pavel Machek
[not found] ` <20150318055437.21025.13990.stgit-wvvUuzkyo1EYVZTmpyfIwg@public.gmane.org>
2015-05-05 19:54 ` Peter Hurley
2015-05-05 20:46 ` NeilBrown
[not found] ` <55492001.30806-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
2015-05-06 5:19 ` [Gta04-owner] " Dr. H. Nikolaus Schaller
[not found] ` <DE60E7AA-1BF4-4A68-9638-E09F85FD5C72-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-05-06 9:27 ` Pavel Machek
2015-05-06 11:50 ` Dr. H. Nikolaus Schaller
2015-05-06 12:05 ` Peter Hurley
2015-05-06 12:27 ` Dr. H. Nikolaus Schaller
2015-05-06 12:36 ` Mark Rutland
2015-05-06 13:28 ` Dr. H. Nikolaus Schaller
2015-05-06 14:15 ` Mark Rutland
2015-05-06 16:09 ` Dr. H. Nikolaus Schaller
2015-05-06 17:18 ` Mark Rutland
2015-05-07 12:46 ` Dr. H. Nikolaus Schaller
2015-05-07 14:30 ` Peter Hurley
2015-05-07 15:11 ` Dr. H. Nikolaus Schaller
2015-05-07 16:18 ` Peter Hurley
2015-05-07 16:57 ` Dr. H. Nikolaus Schaller
[not found] ` <B4D487C5-C260-497B-A441-6C381D53616C-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-05-07 14:56 ` Peter Hurley
[not found] ` <554B7D33.602-WaGBZJeGNqdsbIuE7sb01tBPR1lH4CV8@public.gmane.org>
2015-05-07 15:34 ` Dr. H. Nikolaus Schaller
2015-05-07 15:51 ` Peter Hurley
2015-05-07 16:46 ` Dr. H. Nikolaus Schaller
2015-05-13 8:09 ` Dr. H. Nikolaus Schaller
2015-06-03 11:49 ` [PATCH RFC 0/3] UART slave device support Dr. H. Nikolaus Schaller
[not found] ` <56C579D3-E8F8-4B5A-B6E8-993B113F3461-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-06-06 13:09 ` Pavel Machek
[not found] ` <463356C5-E3C6-432C-A1C5-71F0287F1FEE@goldelico.com>
2015-06-03 12:09 ` [Gta04-owner] [PATCH RFC 3/3] misc: Add w2g0004 gps receiver driver Christ van Willegen
2015-05-07 15:37 ` [Gta04-owner] [PATCH 0/3] tty slave device support - version 3 Peter Hurley
[not found] ` <A2594559-CA92-40C2-A06A-AC2483E85CB1-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-05-06 14:28 ` Pavel Machek
2015-05-06 16:12 ` Dr. H. Nikolaus Schaller
[not found] ` <C68A105A-7147-4143-9B91-1A239726A780-xXXSsgcRVICgSpxsJD1C4w@public.gmane.org>
2015-06-06 13:09 ` Pavel Machek
2015-06-06 18:53 ` Belisko Marek
2015-06-06 18:55 ` Belisko Marek
2015-05-07 15:48 ` Rob Herring
2015-05-06 11:10 ` Peter Hurley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150318055831.21025.85317.stgit@notabene.brown \
--to=neil@brown.name \
--cc=arnd@arndb.de \
--cc=devicetree@vger.kernel.org \
--cc=gnomes@lxorguk.ukuu.org.uk \
--cc=grant.likely@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=gta04-owner@goldelico.com \
--cc=jslaby@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=pavel@ucw.cz \
--cc=peter@hurleysoftware.com \
--cc=sre@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).