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 <adelva@google.com>
This commit is contained in:
@@ -31,7 +31,18 @@ static ssize_t modalias_show(struct device *dev,
|
||||
if (len != -ENODEV)
|
||||
return len;
|
||||
|
||||
return of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
len = of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
if (len != -ENODEV)
|
||||
return len;
|
||||
|
||||
if (dev->parent->parent->bus == &platform_bus_type) {
|
||||
struct platform_device *pdev =
|
||||
to_platform_device(dev->parent->parent);
|
||||
|
||||
len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
@@ -45,13 +56,18 @@ static int serdev_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* TODO: platform modalias */
|
||||
|
||||
rc = acpi_device_uevent_modalias(dev, env);
|
||||
if (rc != -ENODEV)
|
||||
return rc;
|
||||
|
||||
return of_device_uevent_modalias(dev, env);
|
||||
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;
|
||||
}
|
||||
|
||||
static void serdev_device_release(struct device *dev)
|
||||
@@ -87,11 +103,17 @@ static int serdev_device_match(struct device *dev, struct device_driver *drv)
|
||||
if (!is_serdev_device(dev))
|
||||
return 0;
|
||||
|
||||
/* TODO: platform matching */
|
||||
if (acpi_driver_match_device(dev, drv))
|
||||
return 1;
|
||||
|
||||
return of_driver_match_device(dev, drv);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -707,6 +729,33 @@ static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
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.
|
||||
@@ -716,7 +765,7 @@ static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl)
|
||||
*/
|
||||
int serdev_controller_add(struct serdev_controller *ctrl)
|
||||
{
|
||||
int ret_of, ret_acpi, ret;
|
||||
int ret_of, ret_acpi, ret_platform, ret;
|
||||
|
||||
/* Can't register until after driver model init */
|
||||
if (WARN_ON(!is_registered))
|
||||
@@ -730,9 +779,11 @@ int serdev_controller_add(struct serdev_controller *ctrl)
|
||||
|
||||
ret_of = of_serdev_register_devices(ctrl);
|
||||
ret_acpi = acpi_serdev_register_devices(ctrl);
|
||||
if (ret_of && ret_acpi) {
|
||||
dev_dbg(&ctrl->dev, "no devices registered: of:%d acpi:%d\n",
|
||||
ret_of, ret_acpi);
|
||||
ret_platform = platform_serdev_register_devices(ctrl);
|
||||
if (ret_of && ret_acpi && ret_platform) {
|
||||
dev_dbg(&ctrl->dev, "no devices registered: of:%d acpi:%d "
|
||||
"platform:%d\n",
|
||||
ret_of, ret_acpi, ret_platform);
|
||||
ret = -ENODEV;
|
||||
goto err_rpm_disable;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user