* [RFC PATCH 1/5] serdev: Add serdev_device_id
2020-10-26 17:57 [RFC PATCH 0/5] Add serdev_device_id for platform instantiation Vaishnav M A
@ 2020-10-26 17:57 ` Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 2/5] file2alias: Support for serdev devices Vaishnav M A
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Vaishnav M A @ 2020-10-26 17:57 UTC (permalink / raw)
To: johan
Cc: ribalda, robh, gregkh, jirislaby, masahiroy, andriy.shevchenko,
linux-kernel, linux-serial, linux-kbuild, jkridner, drew,
robertcnelson, vaishnav
Currently,a serdev device driver can only be used with devices that are
nodes of a device tree, or are part of the ACPI table.id_table will be
used for devices that are not part of the device tree nor the ACPI table
(example: device on greybus gbphy created uart).
corresponding modalias field is introduced to name the driver to be
used with the device, required for device(s) that are neither described
by device tree nor ACPI table.serdev_device_uevent is also extended
for modalias devices.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Signed-off-by: Vaishnav M A <vaishnav@beagleboard.org>
---
drivers/tty/serdev/core.c | 41 ++++++++++++++++++++++++++++-----
include/linux/mod_devicetable.h | 10 ++++++++
include/linux/serdev.h | 3 +++
3 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index c5f0d936b003..01b248fdc264 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -27,12 +27,17 @@ static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int len;
+ struct serdev_device *serdev = to_serdev_device(dev);
len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
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;
+
+ return sprintf(buf, "%s%s\n", SERDEV_MODULE_PREFIX, serdev->modalias);
}
static DEVICE_ATTR_RO(modalias);
@@ -45,14 +50,18 @@ ATTRIBUTE_GROUPS(serdev_device);
static int serdev_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
int rc;
-
- /* TODO: platform modalias */
+ struct serdev_device *serdev = to_serdev_device(dev);
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;
+
+ return add_uevent_var(env, "MODALIAS=%s%s", SERDEV_MODULE_PREFIX,
+ serdev->modalias);
}
static void serdev_device_release(struct device *dev)
@@ -83,16 +92,36 @@ static const struct device_type serdev_ctrl_type = {
.release = serdev_ctrl_release,
};
+static int serdev_match_id(const struct serdev_device_id *id,
+ const struct serdev_device *sdev)
+{
+ while (id->name[0]) {
+ if (!strcmp(sdev->modalias, id->name))
+ return 1;
+ id++;
+ }
+
+ return 0;
+}
+
static int serdev_device_match(struct device *dev, struct device_driver *drv)
{
+ const struct serdev_device *sdev = to_serdev_device(dev);
+ const struct serdev_device_driver *sdrv = to_serdev_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 (sdrv->id_table)
+ return serdev_match_id(sdrv->id_table, sdev);
+
+ return strcmp(sdev->modalias, drv->name) == 0;
}
/**
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 5b08a473cdba..656353952da2 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -486,6 +486,16 @@ struct i3c_device_id {
const void *data;
};
+/* serdev */
+
+#define SERDEV_NAME_SIZE 32
+#define SERDEV_MODULE_PREFIX "serdev:"
+
+struct serdev_device_id {
+ char name[SERDEV_NAME_SIZE];
+ kernel_ulong_t driver_data;
+};
+
/* spi */
#define SPI_NAME_SIZE 32
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 9f14f9c12ec4..0d9c90a250b0 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <linux/mod_devicetable.h>
#include <linux/termios.h>
#include <linux/delay.h>
@@ -45,6 +46,7 @@ struct serdev_device {
const struct serdev_device_ops *ops;
struct completion write_comp;
struct mutex write_lock;
+ char modalias[SERDEV_NAME_SIZE];
};
static inline struct serdev_device *to_serdev_device(struct device *d)
@@ -63,6 +65,7 @@ struct serdev_device_driver {
struct device_driver driver;
int (*probe)(struct serdev_device *);
void (*remove)(struct serdev_device *);
+ const struct serdev_device_id *id_table;
};
static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d)
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 2/5] file2alias: Support for serdev devices
2020-10-26 17:57 [RFC PATCH 0/5] Add serdev_device_id for platform instantiation Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 1/5] serdev: Add serdev_device_id Vaishnav M A
@ 2020-10-26 17:57 ` Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 3/5] serdev: add of_ helper to get serdev controller Vaishnav M A
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Vaishnav M A @ 2020-10-26 17:57 UTC (permalink / raw)
To: johan
Cc: ribalda, robh, gregkh, jirislaby, masahiroy, andriy.shevchenko,
linux-kernel, linux-serial, linux-kbuild, jkridner, drew,
robertcnelson, vaishnav
This patch allows file2alias to generate the proper module headers to
support serdev modalias drivers.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Signed-off-by: Vaishnav M A <vaishnav@beagleboard.org>
---
scripts/mod/devicetable-offsets.c | 3 +++
scripts/mod/file2alias.c | 10 ++++++++++
2 files changed, 13 insertions(+)
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 27007c18e754..732cd03e911d 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -152,6 +152,9 @@ int main(void)
DEVID_FIELD(i3c_device_id, part_id);
DEVID_FIELD(i3c_device_id, extra_info);
+ DEVID(serdev_device_id);
+ DEVID_FIELD(serdev_device_id, name);
+
DEVID(spi_device_id);
DEVID_FIELD(spi_device_id, name);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 2417dd1dee33..540fee036d9d 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -947,6 +947,15 @@ static int do_spi_entry(const char *filename, void *symval,
return 1;
}
+static int do_serdev_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD_ADDR(symval, serdev_device_id, name);
+ sprintf(alias, SERDEV_MODULE_PREFIX "%s", *name);
+
+ return 1;
+}
+
static const struct dmifield {
const char *prefix;
int field;
@@ -1420,6 +1429,7 @@ static const struct devtable devtable[] = {
{"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
{"i2c", SIZE_i2c_device_id, do_i2c_entry},
{"i3c", SIZE_i3c_device_id, do_i3c_entry},
+ {"serdev", SIZE_serdev_device_id, do_serdev_entry},
{"spi", SIZE_spi_device_id, do_spi_entry},
{"dmi", SIZE_dmi_system_id, do_dmi_entry},
{"platform", SIZE_platform_device_id, do_platform_entry},
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 3/5] serdev: add of_ helper to get serdev controller
2020-10-26 17:57 [RFC PATCH 0/5] Add serdev_device_id for platform instantiation Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 1/5] serdev: Add serdev_device_id Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 2/5] file2alias: Support for serdev devices Vaishnav M A
@ 2020-10-26 17:57 ` Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 4/5] gnss: ubx add MODULE_DEVICE_TABLE(serdev) Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 5/5] gnss: change of_property_read to device_property_read Vaishnav M A
4 siblings, 0 replies; 6+ messages in thread
From: Vaishnav M A @ 2020-10-26 17:57 UTC (permalink / raw)
To: johan
Cc: ribalda, robh, gregkh, jirislaby, masahiroy, andriy.shevchenko,
linux-kernel, linux-serial, linux-kbuild, jkridner, drew,
robertcnelson, vaishnav
add of_find_serdev_controller_by_node() to obtain a
serdev_controller from the device_node, which can
help if the serdev_device is not described over
device tree and instantiation of the device happens later
from a different driver, for the same purpose an option
to not delete an empty serdev controller is added.
Signed-off-by: Vaishnav M A <vaishnav@beagleboard.org>
---
drivers/tty/serdev/core.c | 17 +++++++++++++++++
include/linux/serdev.h | 2 ++
2 files changed, 19 insertions(+)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 01b248fdc264..85977b36ed7f 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -582,6 +582,17 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
return 0;
}
+struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node)
+{
+ struct device *dev = bus_find_device_by_of_node(&serdev_bus_type, node);
+
+ if (!dev)
+ return NULL;
+
+ return (dev->type == &serdev_ctrl_type) ? to_serdev_controller(dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(of_find_serdev_controller_by_node);
+
#ifdef CONFIG_ACPI
#define SERDEV_ACPI_MAX_SCAN_DEPTH 32
@@ -779,6 +790,12 @@ int serdev_controller_add(struct serdev_controller *ctrl)
pm_runtime_enable(&ctrl->dev);
+ /* provide option to not delete a serdev controller without devices
+ * if property is present
+ */
+ if (device_property_present(&ctrl->dev, "force-empty-serdev-controller"))
+ return 0;
+
ret_of = of_serdev_register_devices(ctrl);
ret_acpi = acpi_serdev_register_devices(ctrl);
if (ret_of && ret_acpi) {
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 0d9c90a250b0..2e1eb4d17e1b 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -115,6 +115,8 @@ static inline struct serdev_controller *to_serdev_controller(struct device *d)
return container_of(d, struct serdev_controller, dev);
}
+struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node);
+
static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev)
{
return dev_get_drvdata(&serdev->dev);
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 4/5] gnss: ubx add MODULE_DEVICE_TABLE(serdev)
2020-10-26 17:57 [RFC PATCH 0/5] Add serdev_device_id for platform instantiation Vaishnav M A
` (2 preceding siblings ...)
2020-10-26 17:57 ` [RFC PATCH 3/5] serdev: add of_ helper to get serdev controller Vaishnav M A
@ 2020-10-26 17:57 ` Vaishnav M A
2020-10-26 17:57 ` [RFC PATCH 5/5] gnss: change of_property_read to device_property_read Vaishnav M A
4 siblings, 0 replies; 6+ messages in thread
From: Vaishnav M A @ 2020-10-26 17:57 UTC (permalink / raw)
To: johan
Cc: ribalda, robh, gregkh, jirislaby, masahiroy, andriy.shevchenko,
linux-kernel, linux-serial, linux-kbuild, jkridner, drew,
robertcnelson, vaishnav
export serdev id table to the module header.
Signed-off-by: Vaishnav M A <vaishnav@beagleboard.org>
---
drivers/gnss/ubx.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/gnss/ubx.c b/drivers/gnss/ubx.c
index 7b05bc40532e..e50056cc4223 100644
--- a/drivers/gnss/ubx.c
+++ b/drivers/gnss/ubx.c
@@ -138,6 +138,14 @@ static const struct of_device_id ubx_of_match[] = {
MODULE_DEVICE_TABLE(of, ubx_of_match);
#endif
+static const struct serdev_device_id ubx_serdev_id[] = {
+ { "neo-6m", },
+ { "neo-8", },
+ { "neo-m8", },
+ {}
+};
+MODULE_DEVICE_TABLE(serdev, ubx_serdev_id);
+
static struct serdev_device_driver ubx_driver = {
.driver = {
.name = "gnss-ubx",
@@ -146,6 +154,7 @@ static struct serdev_device_driver ubx_driver = {
},
.probe = ubx_probe,
.remove = ubx_remove,
+ .id_table = ubx_serdev_id,
};
module_serdev_device_driver(ubx_driver);
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 5/5] gnss: change of_property_read to device_property_read
2020-10-26 17:57 [RFC PATCH 0/5] Add serdev_device_id for platform instantiation Vaishnav M A
` (3 preceding siblings ...)
2020-10-26 17:57 ` [RFC PATCH 4/5] gnss: ubx add MODULE_DEVICE_TABLE(serdev) Vaishnav M A
@ 2020-10-26 17:57 ` Vaishnav M A
4 siblings, 0 replies; 6+ messages in thread
From: Vaishnav M A @ 2020-10-26 17:57 UTC (permalink / raw)
To: johan
Cc: ribalda, robh, gregkh, jirislaby, masahiroy, andriy.shevchenko,
linux-kernel, linux-serial, linux-kbuild, jkridner, drew,
robertcnelson, vaishnav
change of_property_read_u32() for the current-speed property
to use the device_property_read_u32() this helps passing the
properties over a suitably populated struct property_entry.
Signed-off-by: Vaishnav M A <vaishnav@beagleboard.org>
---
drivers/gnss/serial.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gnss/serial.c b/drivers/gnss/serial.c
index def64b36d994..473faeea6aae 100644
--- a/drivers/gnss/serial.c
+++ b/drivers/gnss/serial.c
@@ -110,10 +110,9 @@ static int gnss_serial_set_power(struct gnss_serial *gserial,
static int gnss_serial_parse_dt(struct serdev_device *serdev)
{
struct gnss_serial *gserial = serdev_device_get_drvdata(serdev);
- struct device_node *node = serdev->dev.of_node;
u32 speed = 4800;
- of_property_read_u32(node, "current-speed", &speed);
+ device_property_read_u32(&serdev->dev, "current-speed", &speed);
gserial->speed = speed;
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread