#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 {
        struct mtk_iommu_data   *data;
        struct device           *dev = &pdev->dev;
+       struct device_node      *larbnode, *smicomm_node;
+       struct platform_device  *plarbdev;
+       struct device_link      *link;
        struct resource         *res;
        resource_size_t         ioaddr;
        struct component_match  *match = NULL;
                return larb_nr;
 
        for (i = 0; i < larb_nr; i++) {
-               struct device_node *larbnode;
-               struct platform_device *plarbdev;
                u32 id;
 
                larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
                                            compare_of, larbnode);
        }
 
+       /* Get smi-common dev from the last larb. */
+       smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
+       if (!smicomm_node)
+               return -EINVAL;
+
+       plarbdev = of_find_device_by_node(smicomm_node);
+       of_node_put(smicomm_node);
+       data->smicomm_dev = &plarbdev->dev;
+
+       link = device_link_add(data->smicomm_dev, dev,
+                       DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+       if (!link) {
+               dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
+               return -EINVAL;
+       }
+
        platform_set_drvdata(pdev, data);
 
        ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
                                     "mtk-iommu.%pa", &ioaddr);
        if (ret)
-               return ret;
+               goto out_link_remove;
 
        iommu_device_set_ops(&data->iommu, &mtk_iommu_ops);
        iommu_device_set_fwnode(&data->iommu, &pdev->dev.of_node->fwnode);
        iommu_device_unregister(&data->iommu);
 out_sysfs_remove:
        iommu_device_sysfs_remove(&data->iommu);
+out_link_remove:
+       device_link_remove(data->smicomm_dev, dev);
        return ret;
 }
 
                bus_set_iommu(&platform_bus_type, NULL);
 
        clk_disable_unprepare(data->bclk);
+       device_link_remove(data->smicomm_dev, &pdev->dev);
        devm_free_irq(&pdev->dev, data->irq, data);
        component_master_del(&pdev->dev, &mtk_iommu_com_ops);
        return 0;