Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdad3113 authored by Alistair Delva's avatar Alistair Delva
Browse files

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: default avatarAlistair Delva <adelva@google.com>
parent aefee87e
Loading
Loading
Loading
Loading
+59 −7
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/serdev.h>
#include <linux/slab.h>

@@ -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);