From cdad3113fcaa17a85e6632edc4eb2215780f593c Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Fri, 13 Dec 2019 13:56:42 -0800 Subject: [PATCH] ANDROID: serdev: add platform device support Enables devices on a platform bus, such as serial8250 on the ISA bus, to be enumerated by the serdev subsystem. This enables further layering by e.g. the gnss subsystem. With this in change, these devices can now register with the serdev core and show up as serdev tty ports (serialX) and child devices (serialX-Y). serial8250: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a U6_16550A serial serial0: tty port ttyS0 registered serial8250: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a U6_16550A serial serial1: tty port ttyS1 registered serial8250: ttyS2 at I/O 0x3e8 (irq = 4, base_baud = 115200) is a U6_16550A serial serial2: tty port ttyS2 registered serial8250: ttyS3 at I/O 0x2e8 (irq = 3, base_baud = 115200) is a U6_16550A serial serial3: tty port ttyS3 registered The modalias shows up like this: # cat /sys/bus/serial/devices/serial0-0/modalias platform:serial8250 Bug: 146517987 Change-Id: I3711c9d9ecd66fad638a45a8745e97569ae01791 Signed-off-by: Alistair Delva --- drivers/tty/serdev/core.c | 66 ++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 8ad3724bfe32..4fa59314640a 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -49,14 +50,32 @@ static const struct device_type serdev_ctrl_type = { static int serdev_device_match(struct device *dev, struct device_driver *drv) { - /* TODO: ACPI and platform matching */ - return of_driver_match_device(dev, drv); + /* TODO: ACPI matching */ + + if (of_driver_match_device(dev, drv)) + return 1; + + if (dev->parent->parent->bus == &platform_bus_type && + dev->parent->parent->bus->match(dev, drv)) + return 1; + + return 0; } static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env) { - /* TODO: ACPI and platform modalias */ - return of_device_uevent_modalias(dev, env); + int rc; + + /* TODO: ACPI modalias */ + + rc = of_device_uevent_modalias(dev, env); + if (rc != -ENODEV) + return rc; + + if (dev->parent->parent->bus == &platform_bus_type) + rc = dev->parent->parent->bus->uevent(dev, env); + + return rc; } /** @@ -406,6 +425,33 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl) return 0; } +static int platform_serdev_register_devices(struct serdev_controller *ctrl) +{ + struct serdev_device *serdev; + int err; + + if (ctrl->dev.parent->bus != &platform_bus_type) + return -ENODEV; + + serdev = serdev_device_alloc(ctrl); + if (!serdev) { + dev_err(&ctrl->dev, "failed to allocate serdev device for %s\n", + dev_name(ctrl->dev.parent)); + return -ENOMEM; + } + + pm_runtime_no_callbacks(&serdev->dev); + + err = serdev_device_add(serdev); + if (err) { + dev_err(&serdev->dev, + "failure adding device. status %d\n", err); + serdev_device_put(serdev); + } + + return err; +} + /** * serdev_controller_add() - Add an serdev controller * @ctrl: controller to be registered. @@ -415,7 +461,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl) */ int serdev_controller_add(struct serdev_controller *ctrl) { - int ret; + int ret_of, ret_platform, ret; /* Can't register until after driver model init */ if (WARN_ON(!is_registered)) @@ -425,9 +471,15 @@ int serdev_controller_add(struct serdev_controller *ctrl) if (ret) return ret; - ret = of_serdev_register_devices(ctrl); - if (ret) + ret_platform = platform_serdev_register_devices(ctrl); + ret_of = of_serdev_register_devices(ctrl); + if (ret_of && ret_platform) { + dev_dbg(&ctrl->dev, "no devices registered: of:%d " + "platform:%d\n", + ret_of, ret_platform); + ret = -ENODEV; goto out_dev_del; + } dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n", ctrl->nr, &ctrl->dev);