#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/printk.h>
#include <linux/sprintf.h>
#include <linux/string.h>
static inline struct device *
get_serdev_controller_from_parent(struct device *ctrl_dev,
int serial_ctrl_port,
const char *serdev_ctrl_name)
{
struct device *child;
char name[32];
int i;
for (i = 0; i < 3; i++) {
switch (i) {
case 0:
snprintf(name, sizeof(name), "%s:0", dev_name(ctrl_dev));
break;
case 1:
snprintf(name, sizeof(name), "%s.%d",
dev_name(ctrl_dev), serial_ctrl_port);
break;
case 2:
strscpy(name, serdev_ctrl_name, sizeof(name));
break;
}
child = device_find_child_by_name(ctrl_dev, name);
put_device(ctrl_dev);
if (!child) {
pr_err("error could not find '%s' device\n", name);
return ERR_PTR(-ENODEV);
}
ctrl_dev = child;
}
return ctrl_dev;
}
static inline struct device *
get_serdev_controller(const char *serial_ctrl_hid,
const char *serial_ctrl_uid,
int serial_ctrl_port,
const char *serdev_ctrl_name)
{
struct acpi_device *adev;
struct device *parent;
adev = acpi_dev_get_first_match_dev(serial_ctrl_hid, serial_ctrl_uid, -1);
if (!adev) {
pr_err("error could not get %s/%s serial-ctrl adev\n",
serial_ctrl_hid, serial_ctrl_uid ?: "*");
return ERR_PTR(-ENODEV);
}
parent = get_device(acpi_get_first_physical_node(adev));
acpi_dev_put(adev);
if (!parent) {
pr_err("error could not get %s/%s serial-ctrl physical node\n",
serial_ctrl_hid, serial_ctrl_uid ?: "*");
return ERR_PTR(-ENODEV);
}
return get_serdev_controller_from_parent(parent, serial_ctrl_port, serdev_ctrl_name);
}