aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuman Anna2015-12-17 18:24:24 -0600
committerSuman Anna2019-03-03 17:39:54 -0600
commitf7b2c293b8dce275d2c8ea247dd2a6b55cc8b6e1 (patch)
tree299c56cf423d4c8b3de7cec1ba2dadf76ea1c464
parent82b6677359074f75edb5d1e1e6902b6dc2bd145a (diff)
downloadremoteproc-f7b2c293b8dce275d2c8ea247dd2a6b55cc8b6e1.tar.gz
remoteproc-f7b2c293b8dce275d2c8ea247dd2a6b55cc8b6e1.tar.xz
remoteproc-f7b2c293b8dce275d2c8ea247dd2a6b55cc8b6e1.zip
iommu/omap: streamline enable/disable through runtime pm callbacks
The OMAP IOMMU devices are typically present within the respective client processor subsystem and have their own dedicated hard-reset line. Enabling an IOMMU requires the reset line to be deasserted and the clocks to be enabled before programming the necessary IOMMU registers. The IOMMU disable sequence follow the reverse order of enabling. The OMAP IOMMU driver programs the reset lines through pdata ops to invoke the omap_device_assert/deassert_hardreset API. The clocks are managed through the pm_runtime framework, and the callbacks associated with the device's pm_domain, implemented in the omap_device layer. Streamline the enable and disable sequences in the OMAP IOMMU driver by implementing all the above operations within the runtime pm callbacks. All the OMAP devices have device pm_domain callbacks plugged in the omap_device layer for automatic runtime management of the clocks. Invoking the reset management functions within the runtime pm callbacks in OMAP IOMMU driver therefore requires that the default device's pm domain callbacks in the omap_device layer be reset, as the ordering sequence for managing the reset lines and clocks from the pm_domain callbacks don't gel well with the implementation in the IOMMU driver callbacks. The omap_device_enable/omap_device_idle functions are invoked through the newly added pdata ops. Consolidating all the device management sequences within the runtime pm callbacks allows the driver to easily support both system suspend/resume and runtime suspend/resume using common code. Signed-off-by: Suman Anna <s-anna@ti.com>
-rw-r--r--drivers/iommu/omap-iommu.c139
1 files changed, 99 insertions, 40 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index f623f76378a0..4deb92105ad1 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -190,53 +190,18 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
190 190
191static int iommu_enable(struct omap_iommu *obj) 191static int iommu_enable(struct omap_iommu *obj)
192{ 192{
193 int err; 193 int ret;
194 struct platform_device *pdev = to_platform_device(obj->dev);
195 struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
196
197 if (pdata && pdata->set_pwrdm_constraint) {
198 err = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst);
199 if (err) {
200 dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n",
201 err);
202 }
203 }
204
205 if (pdata && pdata->deassert_reset) {
206 err = pdata->deassert_reset(pdev, pdata->reset_name);
207 if (err) {
208 dev_err(obj->dev, "deassert_reset failed: %d\n", err);
209 return err;
210 }
211 }
212
213 pm_runtime_get_sync(obj->dev);
214 194
215 err = omap2_iommu_enable(obj); 195 ret = pm_runtime_get_sync(obj->dev);
196 if (ret < 0)
197 pm_runtime_put_noidle(obj->dev);
216 198
217 return err; 199 return ret < 0 ? ret : 0;
218} 200}
219 201
220static void iommu_disable(struct omap_iommu *obj) 202static void iommu_disable(struct omap_iommu *obj)
221{ 203{
222 struct platform_device *pdev = to_platform_device(obj->dev);
223 struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
224 int ret;
225
226 omap2_iommu_disable(obj);
227
228 pm_runtime_put_sync(obj->dev); 204 pm_runtime_put_sync(obj->dev);
229
230 if (pdata && pdata->assert_reset)
231 pdata->assert_reset(pdev, pdata->reset_name);
232
233 if (pdata && pdata->set_pwrdm_constraint) {
234 ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst);
235 if (ret) {
236 dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n",
237 ret);
238 }
239 }
240} 205}
241 206
242/* 207/*
@@ -931,6 +896,85 @@ static void omap_iommu_detach(struct omap_iommu *obj)
931 dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); 896 dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
932} 897}
933 898
899/**
900 * omap_iommu_runtime_suspend - disable an iommu device
901 * @dev: iommu device
902 *
903 * This function performs all that is necessary to disable an
904 * IOMMU device, either during final detachment from a client
905 * device, or during system/runtime suspend of the device. This
906 * includes programming all the appropriate IOMMU registers, and
907 * managing the associated omap_hwmod's state and the device's
908 * reset line.
909 **/
910static int omap_iommu_runtime_suspend(struct device *dev)
911{
912 struct platform_device *pdev = to_platform_device(dev);
913 struct iommu_platform_data *pdata = dev_get_platdata(dev);
914 struct omap_iommu *obj = to_iommu(dev);
915 int ret;
916
917 omap2_iommu_disable(obj);
918
919 if (pdata && pdata->device_idle)
920 pdata->device_idle(pdev);
921
922 if (pdata && pdata->assert_reset)
923 pdata->assert_reset(pdev, pdata->reset_name);
924
925 if (pdata && pdata->set_pwrdm_constraint) {
926 ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst);
927 if (ret) {
928 dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n",
929 ret);
930 }
931 }
932
933 return 0;
934}
935
936/**
937 * omap_iommu_runtime_resume - enable an iommu device
938 * @dev: iommu device
939 *
940 * This function performs all that is necessary to enable an
941 * IOMMU device, either during initial attachment to a client
942 * device, or during system/runtime resume of the device. This
943 * includes programming all the appropriate IOMMU registers, and
944 * managing the associated omap_hwmod's state and the device's
945 * reset line.
946 **/
947static int omap_iommu_runtime_resume(struct device *dev)
948{
949 struct platform_device *pdev = to_platform_device(dev);
950 struct iommu_platform_data *pdata = dev_get_platdata(dev);
951 struct omap_iommu *obj = to_iommu(dev);
952 int ret = 0;
953
954 if (pdata && pdata->set_pwrdm_constraint) {
955 ret = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst);
956 if (ret) {
957 dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n",
958 ret);
959 }
960 }
961
962 if (pdata && pdata->deassert_reset) {
963 ret = pdata->deassert_reset(pdev, pdata->reset_name);
964 if (ret) {
965 dev_err(dev, "deassert_reset failed: %d\n", ret);
966 return ret;
967 }
968 }
969
970 if (pdata && pdata->device_enable)
971 pdata->device_enable(pdev);
972
973 ret = omap2_iommu_enable(obj);
974
975 return ret;
976}
977
934static bool omap_iommu_can_register(struct platform_device *pdev) 978static bool omap_iommu_can_register(struct platform_device *pdev)
935{ 979{
936 struct device_node *np = pdev->dev.of_node; 980 struct device_node *np = pdev->dev.of_node;
@@ -1005,6 +1049,15 @@ static int omap_iommu_probe(struct platform_device *pdev)
1005 if (!obj) 1049 if (!obj)
1006 return -ENOMEM; 1050 return -ENOMEM;
1007 1051
1052 /*
1053 * self-manage the ordering dependencies between omap_device_enable/idle
1054 * and omap_device_assert/deassert_hardreset API
1055 */
1056 if (pdev->dev.pm_domain) {
1057 dev_dbg(&pdev->dev, "device pm_domain is being reset\n");
1058 pdev->dev.pm_domain = NULL;
1059 }
1060
1008 obj->name = dev_name(&pdev->dev); 1061 obj->name = dev_name(&pdev->dev);
1009 obj->nr_tlb_entries = 32; 1062 obj->nr_tlb_entries = 32;
1010 err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries); 1063 err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries);
@@ -1093,6 +1146,11 @@ static int omap_iommu_remove(struct platform_device *pdev)
1093 return 0; 1146 return 0;
1094} 1147}
1095 1148
1149static const struct dev_pm_ops omap_iommu_pm_ops = {
1150 SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
1151 omap_iommu_runtime_resume, NULL)
1152};
1153
1096static const struct of_device_id omap_iommu_of_match[] = { 1154static const struct of_device_id omap_iommu_of_match[] = {
1097 { .compatible = "ti,omap2-iommu" }, 1155 { .compatible = "ti,omap2-iommu" },
1098 { .compatible = "ti,omap4-iommu" }, 1156 { .compatible = "ti,omap4-iommu" },
@@ -1106,6 +1164,7 @@ static struct platform_driver omap_iommu_driver = {
1106 .remove = omap_iommu_remove, 1164 .remove = omap_iommu_remove,
1107 .driver = { 1165 .driver = {
1108 .name = "omap-iommu", 1166 .name = "omap-iommu",
1167 .pm = &omap_iommu_pm_ops,
1109 .of_match_table = of_match_ptr(omap_iommu_of_match), 1168 .of_match_table = of_match_ptr(omap_iommu_of_match),
1110 }, 1169 },
1111}; 1170};