i3c: i3c-master-qcom-geni: Manage probe time resources

This change enhances the probe routine and cleanup the resources
properly if the failure is observed on previous operations.

Also add proper logging to exactly highlight the failure.

Change-Id: Idedc9e424a739758c3b8aa08675fb3e06bf67bb2
Signed-off-by: Mukesh Kumar Savaliya <msavaliy@codeaurora.org>
This commit is contained in:
Mukesh Kumar Savaliya
2020-06-19 23:53:08 +05:30
parent 6d79a96abb
commit d4f9da6511

View File

@@ -20,6 +20,7 @@
#include <linux/ipc_logging.h>
#include <linux/pinctrl/qcom-pinctrl.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/pm_wakeup.h>
#include <linux/workqueue.h>
@@ -1298,8 +1299,11 @@ static int geni_i3c_master_bus_init(struct i3c_master_controller *m)
/* Get an address for the master. */
ret = i3c_master_get_free_addr(m, 0);
if (ret < 0)
if (ret < 0) {
GENI_SE_ERR(gi3c->ipcl, true, gi3c->se.dev,
"%s: error No free addr:%d\n", __func__, ret);
goto err_cleanup;
}
info.dyn_addr = ret;
info.dcr = I3C_DCR_GENERIC_DEVICE;
@@ -1742,7 +1746,7 @@ static int i3c_geni_rsrcs_init(struct geni_i3c_dev *gi3c,
(DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH));
if (ret) {
GENI_SE_DBG(gi3c->ipcl, false, gi3c->se.dev,
"geni_se_resources_init\n");
"geni_se_resources_init Failed:%d\n", ret);
return ret;
}
@@ -1754,8 +1758,7 @@ static int i3c_geni_rsrcs_init(struct geni_i3c_dev *gi3c,
gi3c->clk_src_freq = 100000000;
}
ret = device_property_read_u32(&pdev->dev, "dfs-index",
&gi3c->dfs_idx);
ret = device_property_read_u32(&pdev->dev, "dfs-index", &gi3c->dfs_idx);
if (ret)
gi3c->dfs_idx = 0xf;
@@ -1848,8 +1851,7 @@ static int i3c_ibi_rsrcs_init(struct geni_i3c_dev *gi3c,
IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), gi3c);
if (ret) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Request_irq failed:%d: err:%d\n",
gi3c->ibi.mngr_irq, ret);
"Request_irq:%d: err:%d\n", gi3c->ibi.mngr_irq, ret);
return ret;
}
@@ -1875,8 +1877,7 @@ static int i3c_ibi_rsrcs_init(struct geni_i3c_dev *gi3c,
dev_name(&pdev->dev), gi3c);
if (ret) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Request_irq failed:%d: err:%d\n",
gi3c->ibi.gpii_irq[0], ret);
"Request_irq failed:%d: err:%d\n", gi3c->ibi.gpii_irq[0], ret);
return ret;
}
@@ -1907,58 +1908,68 @@ static int geni_i3c_probe(struct platform_device *pdev)
gi3c->se.dev = &pdev->dev;
gi3c->ipcl = ipc_log_context_create(4, dev_name(gi3c->se.dev), 0);
if (!gi3c->ipcl)
dev_info(&pdev->dev, "Error creating IPC Log\n");
ret = i3c_geni_rsrcs_init(gi3c, pdev);
if (ret)
return ret;
if (ret) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Error:%d i3c_geni_rsrcs_init\n", ret);
goto cleanup_init;
}
ret = i3c_geni_rsrcs_clk_init(gi3c);
if (ret)
return ret;
if (ret) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Error:%d i3c_geni_rsrcs_clk_init\n", ret);
goto cleanup_init;
}
gi3c->irq = platform_get_irq(pdev, 0);
if (gi3c->irq < 0) {
ret = gi3c->irq;
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"IRQ error for i3c-master-geni\n");
return gi3c->irq;
"IRQ error=%d for i3c-master-geni\n", ret);
goto cleanup_init;
}
init_completion(&gi3c->done);
mutex_init(&gi3c->lock);
spin_lock_init(&gi3c->spinlock);
platform_set_drvdata(pdev, gi3c);
/* Keep interrupt disabled so the system can enter low-power mode */
irq_set_status_flags(gi3c->irq, IRQ_NOAUTOEN);
ret = devm_request_irq(&pdev->dev, gi3c->irq, geni_i3c_irq,
IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), gi3c);
if (ret) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Request_irq failed:%d: err:%d\n",
gi3c->irq, ret);
return ret;
"i3c irq failed:%d: err:%d\n", gi3c->irq, ret);
goto cleanup_init;
}
/* Disable the interrupt so that the system can enter low-power mode */
disable_irq(gi3c->irq);
ret = se_geni_resources_on(&gi3c->se.i3c_rsc);
if (ret) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Error turning on resources %d\n", ret);
return ret;
goto cleanup_init;
}
proto = get_se_proto(gi3c->se.base);
if (proto != I3C) {
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Invalid proto %d\n", proto);
se_geni_resources_off(&gi3c->se.i3c_rsc);
return -ENXIO;
ret = -ENXIO;
goto geni_resources_off;
}
se_mode = geni_read_reg(gi3c->se.base, GENI_IF_FIFO_DISABLE_RO);
if (se_mode) {
/* GSI mode not supported */
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Non supported mode %d\n", se_mode);
se_geni_resources_off(&gi3c->se.i3c_rsc);
return -ENXIO;
ret = -ENXIO;
goto geni_resources_off;
}
tx_depth = get_tx_fifo_depth(gi3c->se.base);
@@ -1979,8 +1990,9 @@ static int geni_i3c_probe(struct platform_device *pdev)
ret = i3c_ibi_rsrcs_init(gi3c, pdev);
if (ret) {
se_geni_resources_off(&gi3c->se.i3c_rsc);
return ret;
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"Error: %d, i3c_ibi_rsrcs_init\n", ret);
goto geni_resources_off;
}
se_geni_resources_off(&gi3c->se.i3c_rsc);
@@ -1995,16 +2007,26 @@ static int geni_i3c_probe(struct platform_device *pdev)
ret = i3c_master_register(&gi3c->ctrlr, &pdev->dev,
&geni_i3c_master_ops, false);
if (ret)
GENI_SE_ERR(gi3c->ipcl, false, gi3c->se.dev,
"i3c_master_register failed:%d\n", ret);
if (ret) {
GENI_SE_ERR(gi3c->ipcl, true, gi3c->se.dev,
"I3C master registration failed=%d, continue\n", ret);
/* NOTE : This may fail on 7E NACK, but should return 0 */
ret = 0;
}
//enable hot-join IRQ also
geni_write_reg(~0u, gi3c->se.ibi_base, IBI_GEN_IRQ_EN);
GENI_SE_DBG(gi3c->ipcl, false, gi3c->se.dev, "I3C probed\n");
GENI_SE_ERR(gi3c->ipcl, true, gi3c->se.dev, "I3C probed:%d\n", ret);
return ret;
return 0;
geni_resources_off:
se_geni_resources_off(&gi3c->se.i3c_rsc);
cleanup_init:
GENI_SE_ERR(gi3c->ipcl, true, gi3c->se.dev, "I3C probe failed\n");
return ret;
}
static int geni_i3c_remove(struct platform_device *pdev)