summaryrefslogtreecommitdiff
path: root/drivers/slimbus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/slimbus')
-rw-r--r--drivers/slimbus/core.c37
-rw-r--r--drivers/slimbus/qcom-ngd-ctrl.c34
2 files changed, 54 insertions, 17 deletions
diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c
index 95b00d28ad6e..55eda5863a6b 100644
--- a/drivers/slimbus/core.c
+++ b/drivers/slimbus/core.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/idr.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/slimbus.h>
#include "slimbus.h"
@@ -32,6 +33,10 @@ static int slim_device_match(struct device *dev, struct device_driver *drv)
struct slim_device *sbdev = to_slim_device(dev);
struct slim_driver *sbdrv = to_slim_driver(drv);
+ /* Attempt an OF style match first */
+ if (of_driver_match_device(dev, drv))
+ return 1;
+
return !!slim_match(sbdrv->id_table, sbdev);
}
@@ -39,8 +44,23 @@ static int slim_device_probe(struct device *dev)
{
struct slim_device *sbdev = to_slim_device(dev);
struct slim_driver *sbdrv = to_slim_driver(dev->driver);
+ int ret;
- return sbdrv->probe(sbdev);
+ ret = sbdrv->probe(sbdev);
+ if (ret)
+ return ret;
+
+ /* try getting the logical address after probe */
+ ret = slim_get_logical_addr(sbdev);
+ if (!ret) {
+ if (sbdrv->device_status)
+ sbdrv->device_status(sbdev, sbdev->status);
+ } else {
+ dev_err(&sbdev->dev, "Failed to get logical address\n");
+ ret = -EPROBE_DEFER;
+ }
+
+ return ret;
}
static int slim_device_remove(struct device *dev)
@@ -57,11 +77,24 @@ static int slim_device_remove(struct device *dev)
return 0;
}
+static int slim_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct slim_device *sbdev = to_slim_device(dev);
+ int ret;
+
+ ret = of_device_uevent_modalias(dev, env);
+ if (ret != -ENODEV)
+ return ret;
+
+ return add_uevent_var(env, "MODALIAS=slim:%s", dev_name(&sbdev->dev));
+}
+
struct bus_type slimbus_bus = {
.name = "slimbus",
.match = slim_device_match,
.probe = slim_device_probe,
.remove = slim_device_remove,
+ .uevent = slim_device_uevent,
};
EXPORT_SYMBOL_GPL(slimbus_bus);
@@ -77,7 +110,7 @@ EXPORT_SYMBOL_GPL(slimbus_bus);
int __slim_driver_register(struct slim_driver *drv, struct module *owner)
{
/* ID table and probe are mandatory */
- if (!drv->id_table || !drv->probe)
+ if (!(drv->driver.of_match_table || drv->id_table) || !drv->probe)
return -EINVAL;
drv->driver.bus = &slimbus_bus;
diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index 8be4d6786c61..7218fb963d0a 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -1004,6 +1004,7 @@ static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
struct slim_eaddr *ea, u8 *laddr)
{
struct slim_val_inf msg = {0};
+ u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
struct slim_msg_txn txn;
u8 wbuf[10] = {0};
u8 rbuf[10] = {0};
@@ -1034,6 +1035,9 @@ static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
return ret;
}
+ if (!memcmp(rbuf, failed_ea, 6))
+ return -ENXIO;
+
*laddr = rbuf[6];
return ret;
@@ -1234,8 +1238,17 @@ static int qcom_slim_ngd_enable(struct qcom_slim_ngd_ctrl *ctrl, bool enable)
pm_runtime_resume(ctrl->dev);
pm_runtime_mark_last_busy(ctrl->dev);
pm_runtime_put(ctrl->dev);
+
+ ret = slim_register_controller(&ctrl->ctrl);
+ if (ret) {
+ dev_err(ctrl->dev, "error adding slim controller\n");
+ return ret;
+ }
+
+ dev_info(ctrl->dev, "SLIM controller Registered\n");
} else {
qcom_slim_qmi_exit(ctrl);
+ slim_unregister_controller(&ctrl->ctrl);
}
return 0;
@@ -1342,7 +1355,6 @@ static int of_qcom_slim_ngd_register(struct device *parent,
ngd->base = ctrl->base + ngd->id * data->offset +
(ngd->id - 1) * data->size;
ctrl->ngd = ngd;
- platform_driver_register(&qcom_slim_ngd_driver);
return 0;
}
@@ -1357,11 +1369,6 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
int ret;
ctrl->ctrl.dev = dev;
- ret = slim_register_controller(&ctrl->ctrl);
- if (ret) {
- dev_err(dev, "error adding slim controller\n");
- return ret;
- }
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, QCOM_SLIM_NGD_AUTOSUSPEND);
@@ -1371,7 +1378,7 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
ret = qcom_slim_ngd_qmi_svc_event_init(ctrl);
if (ret) {
dev_err(&pdev->dev, "QMI service registration failed:%d", ret);
- goto err;
+ return ret;
}
INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
@@ -1383,14 +1390,12 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
}
return 0;
-err:
- slim_unregister_controller(&ctrl->ctrl);
wq_err:
qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
if (ctrl->mwq)
destroy_workqueue(ctrl->mwq);
- return 0;
+ return ret;
}
static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
@@ -1441,6 +1446,7 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
init_completion(&ctrl->reconf);
init_completion(&ctrl->qmi.qmi_comp);
+ platform_driver_register(&qcom_slim_ngd_driver);
return of_qcom_slim_ngd_register(dev, ctrl);
}
@@ -1456,7 +1462,7 @@ static int qcom_slim_ngd_remove(struct platform_device *pdev)
struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
- slim_unregister_controller(&ctrl->ctrl);
+ qcom_slim_ngd_enable(ctrl, false);
qcom_slim_ngd_exit_dma(ctrl);
qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
if (ctrl->mwq)
@@ -1467,7 +1473,7 @@ static int qcom_slim_ngd_remove(struct platform_device *pdev)
return 0;
}
-static int qcom_slim_ngd_runtime_idle(struct device *dev)
+static int __maybe_unused qcom_slim_ngd_runtime_idle(struct device *dev)
{
struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
@@ -1477,8 +1483,7 @@ static int qcom_slim_ngd_runtime_idle(struct device *dev)
return -EAGAIN;
}
-#ifdef CONFIG_PM
-static int qcom_slim_ngd_runtime_suspend(struct device *dev)
+static int __maybe_unused qcom_slim_ngd_runtime_suspend(struct device *dev)
{
struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
int ret = 0;
@@ -1491,7 +1496,6 @@ static int qcom_slim_ngd_runtime_suspend(struct device *dev)
return ret;
}
-#endif
static const struct dev_pm_ops qcom_slim_ngd_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,