diff options
author | Suman Anna | 2019-03-04 10:21:56 -0600 |
---|---|---|
committer | Suman Anna | 2019-03-04 10:22:56 -0600 |
commit | 8a953aee290af1ad27ce85e258c09f4a109916bd (patch) | |
tree | 2ce20273f258ea14ef01b2dbb93fc22773e22efe | |
parent | e80509505068ed7649a88c021128b7895a90b340 (diff) | |
parent | cb6320f7002078445ba5cebb5cdefca75136e052 (diff) | |
download | afd-analog-8a953aee290af1ad27ce85e258c09f4a109916bd.tar.gz afd-analog-8a953aee290af1ad27ce85e258c09f4a109916bd.tar.xz afd-analog-8a953aee290af1ad27ce85e258c09f4a109916bd.zip |
Merge branch 'rproc-linux-4.19.y' of git://git.ti.com/rpmsg/remoteproc into rpmsg-ti-linux-4.19.y
Pull in the updated remoteproc feature branch that adds the support
for system suspend/resume and runtime auto-suspend/resume support on
the IPU and DSP remote processors on OMAP4, OMAP5 and DRA7 SoCs. The
feature branch merge also pulls in automatically the dependent OMAP
iommu feature branch with suspend/resume support. OMAP mailbox driver
already has the suspend/resume support in upstream 4.19 kernel.
* 'rproc-linux-4.19.y' of git://git.ti.com/rpmsg/remoteproc:
remoteproc: Fix sysfs interface to stop a suspended processor
remoteproc/omap: add support for runtime auto-suspend/resume
remoteproc/omap: add support for system suspend/resume
ARM: dts: dra7: Add standby info for IPU & DSPs
ARM: dts: omap5: Add standby info for IPU and DSP
ARM: dts: omap4: Add standby info for IPU and DSP
dt-bindings: remoteproc: Update omap remoteproc binding for suspend
iommu/omap: introduce new API for runtime suspend/resume control
iommu/omap: Add system suspend/resume support
iommu/omap: add logic to save/restore locked TLBs
iommu/omap: streamline enable/disable through runtime pm callbacks
ARM: OMAP2+: add pdata-quirks for OMAP3 ISP IOMMU
ARM: OMAP2+: Add iommu pdata-quirks for DRA7 DSP EDMA MMUs
ARM: OMAP2+: plug in device_enable/idle ops for IOMMUs
iommu/omap: add pdata ops for omap_device_enable/idle
Signed-off-by: Suman Anna <s-anna@ti.com>
-rw-r--r-- | Documentation/devicetree/bindings/remoteproc/ti,omap-remoteproc.txt | 8 | ||||
-rw-r--r-- | arch/arm/boot/dts/dra7.dtsi | 3 | ||||
-rw-r--r-- | arch/arm/boot/dts/dra74x.dtsi | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/omap4.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/omap5.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pdata-quirks.c | 22 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.c | 280 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.h | 3 | ||||
-rw-r--r-- | drivers/remoteproc/omap_remoteproc.c | 432 | ||||
-rw-r--r-- | drivers/remoteproc/omap_remoteproc.h | 18 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_sysfs.c | 3 | ||||
-rw-r--r-- | include/linux/omap-iommu.h | 15 | ||||
-rw-r--r-- | include/linux/platform_data/iommu-omap.h | 2 |
13 files changed, 745 insertions, 46 deletions
diff --git a/Documentation/devicetree/bindings/remoteproc/ti,omap-remoteproc.txt b/Documentation/devicetree/bindings/remoteproc/ti,omap-remoteproc.txt index d5aeb1aa2784..873481b552a2 100644 --- a/Documentation/devicetree/bindings/remoteproc/ti,omap-remoteproc.txt +++ b/Documentation/devicetree/bindings/remoteproc/ti,omap-remoteproc.txt | |||
@@ -117,6 +117,11 @@ The following are the optional properties: | |||
117 | The timers to be used should match with the watchdog | 117 | The timers to be used should match with the watchdog |
118 | timers used in the firmware image. | 118 | timers used in the firmware image. |
119 | 119 | ||
120 | - ti,rproc-standby-info: Standby data for the remote processor. This is | ||
121 | mandatory to support Power Management for the OMAP | ||
122 | remoteprocs, and should contain the address containing | ||
123 | the module standby status. | ||
124 | |||
120 | Example: | 125 | Example: |
121 | -------- | 126 | -------- |
122 | 127 | ||
@@ -141,6 +146,7 @@ Example: | |||
141 | ti,hwmods = "dsp"; | 146 | ti,hwmods = "dsp"; |
142 | syscon-bootreg = <&scm_conf 0x304>; | 147 | syscon-bootreg = <&scm_conf 0x304>; |
143 | iommus = <&mmu_dsp>; | 148 | iommus = <&mmu_dsp>; |
149 | ti,rproc-standby-info = <0x4a004420>; | ||
144 | mboxes = <&mailbox &mbox_dsp>; | 150 | mboxes = <&mailbox &mbox_dsp>; |
145 | memory-region = <&dsp_memory_region>; | 151 | memory-region = <&dsp_memory_region>; |
146 | timers = <&timer5>; | 152 | timers = <&timer5>; |
@@ -170,6 +176,7 @@ Example: | |||
170 | reg-names = "l2ram"; | 176 | reg-names = "l2ram"; |
171 | ti,hwmods = "ipu"; | 177 | ti,hwmods = "ipu"; |
172 | iommus = <&mmu_ipu>; | 178 | iommus = <&mmu_ipu>; |
179 | ti,rproc-standby-info = <0x4a008920>; | ||
173 | mboxes = <&mailbox &mbox_ipu>; | 180 | mboxes = <&mailbox &mbox_ipu>; |
174 | memory-region = <&ipu_memory_region>; | 181 | memory-region = <&ipu_memory_region>; |
175 | timers = <&timer3>, <&timer4>; | 182 | timers = <&timer3>, <&timer4>; |
@@ -202,6 +209,7 @@ Example: | |||
202 | ti,hwmods = "dsp1"; | 209 | ti,hwmods = "dsp1"; |
203 | syscon-bootreg = <&scm_conf 0x55c>; | 210 | syscon-bootreg = <&scm_conf 0x55c>; |
204 | iommus = <&mmu0_dsp1>, <&mmu1_dsp1>; | 211 | iommus = <&mmu0_dsp1>, <&mmu1_dsp1>; |
212 | ti,rproc-standby-info = <0x4a005420>; | ||
205 | mboxes = <&mailbox5 &mbox_dsp1_ipc3x>; | 213 | mboxes = <&mailbox5 &mbox_dsp1_ipc3x>; |
206 | memory-region = <&dsp1_memory_region>; | 214 | memory-region = <&dsp1_memory_region>; |
207 | timers = <&timer5>; | 215 | timers = <&timer5>; |
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 1b37091d5fde..af178ac5e55b 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi | |||
@@ -1064,6 +1064,7 @@ | |||
1064 | reg-names = "l2ram"; | 1064 | reg-names = "l2ram"; |
1065 | ti,hwmods = "ipu1"; | 1065 | ti,hwmods = "ipu1"; |
1066 | iommus = <&mmu_ipu1>; | 1066 | iommus = <&mmu_ipu1>; |
1067 | ti,rproc-standby-info = <0x4a005520>; | ||
1067 | status = "disabled"; | 1068 | status = "disabled"; |
1068 | }; | 1069 | }; |
1069 | 1070 | ||
@@ -1073,6 +1074,7 @@ | |||
1073 | reg-names = "l2ram"; | 1074 | reg-names = "l2ram"; |
1074 | ti,hwmods = "ipu2"; | 1075 | ti,hwmods = "ipu2"; |
1075 | iommus = <&mmu_ipu2>; | 1076 | iommus = <&mmu_ipu2>; |
1077 | ti,rproc-standby-info = <0x4a008920>; | ||
1076 | status = "disabled"; | 1078 | status = "disabled"; |
1077 | }; | 1079 | }; |
1078 | 1080 | ||
@@ -1085,6 +1087,7 @@ | |||
1085 | ti,hwmods = "dsp1"; | 1087 | ti,hwmods = "dsp1"; |
1086 | syscon-bootreg = <&scm_conf 0x55c>; | 1088 | syscon-bootreg = <&scm_conf 0x55c>; |
1087 | iommus = <&mmu0_dsp1>, <&mmu1_dsp1>; | 1089 | iommus = <&mmu0_dsp1>, <&mmu1_dsp1>; |
1090 | ti,rproc-standby-info = <0x4a005420>; | ||
1088 | status = "disabled"; | 1091 | status = "disabled"; |
1089 | }; | 1092 | }; |
1090 | 1093 | ||
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi index 492ee7d355ef..5f7c8922a07c 100644 --- a/arch/arm/boot/dts/dra74x.dtsi +++ b/arch/arm/boot/dts/dra74x.dtsi | |||
@@ -102,6 +102,7 @@ | |||
102 | ti,hwmods = "dsp2"; | 102 | ti,hwmods = "dsp2"; |
103 | syscon-bootreg = <&scm_conf 0x560>; | 103 | syscon-bootreg = <&scm_conf 0x560>; |
104 | iommus = <&mmu0_dsp2>, <&mmu1_dsp2>; | 104 | iommus = <&mmu0_dsp2>, <&mmu1_dsp2>; |
105 | ti,rproc-standby-info = <0x4a005620>; | ||
105 | status = "disabled"; | 106 | status = "disabled"; |
106 | }; | 107 | }; |
107 | }; | 108 | }; |
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index f51870087ba5..ecc67a244d55 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi | |||
@@ -464,6 +464,7 @@ | |||
464 | ti,hwmods = "dsp"; | 464 | ti,hwmods = "dsp"; |
465 | syscon-bootreg = <&scm_conf 0x304>; | 465 | syscon-bootreg = <&scm_conf 0x304>; |
466 | iommus = <&mmu_dsp>; | 466 | iommus = <&mmu_dsp>; |
467 | ti,rproc-standby-info = <0x4a004420>; | ||
467 | mboxes = <&mailbox &mbox_dsp>; | 468 | mboxes = <&mailbox &mbox_dsp>; |
468 | status = "disabled"; | 469 | status = "disabled"; |
469 | }; | 470 | }; |
@@ -474,6 +475,7 @@ | |||
474 | reg-names = "l2ram"; | 475 | reg-names = "l2ram"; |
475 | ti,hwmods = "ipu"; | 476 | ti,hwmods = "ipu"; |
476 | iommus = <&mmu_ipu>; | 477 | iommus = <&mmu_ipu>; |
478 | ti,rproc-standby-info = <0x4a008920>; | ||
477 | mboxes = <&mailbox &mbox_ipu>; | 479 | mboxes = <&mailbox &mbox_ipu>; |
478 | status = "disabled"; | 480 | status = "disabled"; |
479 | }; | 481 | }; |
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index d09180fb6fe3..51a8755689e5 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi | |||
@@ -901,6 +901,7 @@ | |||
901 | ti,hwmods = "dsp"; | 901 | ti,hwmods = "dsp"; |
902 | syscon-bootreg = <&scm_conf 0x304>; | 902 | syscon-bootreg = <&scm_conf 0x304>; |
903 | iommus = <&mmu_dsp>; | 903 | iommus = <&mmu_dsp>; |
904 | ti,rproc-standby-info = <0x4a004420>; | ||
904 | mboxes = <&mailbox &mbox_dsp>; | 905 | mboxes = <&mailbox &mbox_dsp>; |
905 | status = "disabled"; | 906 | status = "disabled"; |
906 | }; | 907 | }; |
@@ -911,6 +912,7 @@ | |||
911 | reg-names = "l2ram"; | 912 | reg-names = "l2ram"; |
912 | ti,hwmods = "ipu"; | 913 | ti,hwmods = "ipu"; |
913 | iommus = <&mmu_ipu>; | 914 | iommus = <&mmu_ipu>; |
915 | ti,rproc-standby-info = <0x4a008920>; | ||
914 | mboxes = <&mailbox &mbox_ipu>; | 916 | mboxes = <&mailbox &mbox_ipu>; |
915 | status = "disabled"; | 917 | status = "disabled"; |
916 | }; | 918 | }; |
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 2271add0a661..9b6aec1fef88 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c | |||
@@ -104,6 +104,13 @@ static struct iommu_platform_data omap3_iommu_pdata = { | |||
104 | .reset_name = "mmu", | 104 | .reset_name = "mmu", |
105 | .assert_reset = omap_device_assert_hardreset, | 105 | .assert_reset = omap_device_assert_hardreset, |
106 | .deassert_reset = omap_device_deassert_hardreset, | 106 | .deassert_reset = omap_device_deassert_hardreset, |
107 | .device_enable = omap_device_enable, | ||
108 | .device_idle = omap_device_idle, | ||
109 | }; | ||
110 | |||
111 | static struct iommu_platform_data omap3_iommu_isp_pdata = { | ||
112 | .device_enable = omap_device_enable, | ||
113 | .device_idle = omap_device_idle, | ||
107 | }; | 114 | }; |
108 | 115 | ||
109 | static int omap3_sbc_t3730_twl_callback(struct device *dev, | 116 | static int omap3_sbc_t3730_twl_callback(struct device *dev, |
@@ -438,6 +445,8 @@ static struct iommu_platform_data omap4_iommu_pdata = { | |||
438 | .reset_name = "mmu_cache", | 445 | .reset_name = "mmu_cache", |
439 | .assert_reset = omap_device_assert_hardreset, | 446 | .assert_reset = omap_device_assert_hardreset, |
440 | .deassert_reset = omap_device_deassert_hardreset, | 447 | .deassert_reset = omap_device_deassert_hardreset, |
448 | .device_enable = omap_device_enable, | ||
449 | .device_idle = omap_device_idle, | ||
441 | }; | 450 | }; |
442 | #endif | 451 | #endif |
443 | 452 | ||
@@ -466,9 +475,16 @@ static struct iommu_platform_data dra7_ipu1_dsp_iommu_pdata = { | |||
466 | .reset_name = "mmu_cache", | 475 | .reset_name = "mmu_cache", |
467 | .assert_reset = omap_device_assert_hardreset, | 476 | .assert_reset = omap_device_assert_hardreset, |
468 | .deassert_reset = omap_device_deassert_hardreset, | 477 | .deassert_reset = omap_device_deassert_hardreset, |
478 | .device_enable = omap_device_enable, | ||
479 | .device_idle = omap_device_idle, | ||
469 | .set_pwrdm_constraint = omap_iommu_set_pwrdm_constraint, | 480 | .set_pwrdm_constraint = omap_iommu_set_pwrdm_constraint, |
470 | }; | 481 | }; |
471 | 482 | ||
483 | static struct iommu_platform_data dra7_dsp_mmu_edma_pdata = { | ||
484 | .device_enable = omap_device_enable, | ||
485 | .device_idle = omap_device_idle, | ||
486 | }; | ||
487 | |||
472 | static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc1; | 488 | static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc1; |
473 | static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc2; | 489 | static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc2; |
474 | static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc3; | 490 | static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc3; |
@@ -585,6 +601,8 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = { | |||
585 | #ifdef CONFIG_ARCH_OMAP3 | 601 | #ifdef CONFIG_ARCH_OMAP3 |
586 | OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu", | 602 | OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu", |
587 | &omap3_iommu_pdata), | 603 | &omap3_iommu_pdata), |
604 | OF_DEV_AUXDATA("ti,omap2-iommu", 0x480bd400, "480bd400.mmu", | ||
605 | &omap3_iommu_isp_pdata), | ||
588 | OF_DEV_AUXDATA("ti,omap3-smartreflex-core", 0x480cb000, | 606 | OF_DEV_AUXDATA("ti,omap3-smartreflex-core", 0x480cb000, |
589 | "480cb000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]), | 607 | "480cb000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]), |
590 | OF_DEV_AUXDATA("ti,omap3-smartreflex-mpu-iva", 0x480c9000, | 608 | OF_DEV_AUXDATA("ti,omap3-smartreflex-mpu-iva", 0x480c9000, |
@@ -644,6 +662,10 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = { | |||
644 | &dra7_ipu1_dsp_iommu_pdata), | 662 | &dra7_ipu1_dsp_iommu_pdata), |
645 | OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x41501000, "41501000.mmu", | 663 | OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x41501000, "41501000.mmu", |
646 | &dra7_ipu1_dsp_iommu_pdata), | 664 | &dra7_ipu1_dsp_iommu_pdata), |
665 | OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x40d02000, "40d02000.mmu", | ||
666 | &dra7_dsp_mmu_edma_pdata), | ||
667 | OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x41502000, "41502000.mmu", | ||
668 | &dra7_dsp_mmu_edma_pdata), | ||
647 | OF_DEV_AUXDATA("ti,dra7-iommu", 0x55082000, "55082000.mmu", | 669 | OF_DEV_AUXDATA("ti,dra7-iommu", 0x55082000, "55082000.mmu", |
648 | &omap4_iommu_pdata), | 670 | &omap4_iommu_pdata), |
649 | OF_DEV_AUXDATA("ti,dra7-iommu", 0x58882000, "58882000.mmu", | 671 | OF_DEV_AUXDATA("ti,dra7-iommu", 0x58882000, "58882000.mmu", |
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index f623f76378a0..c69d86900520 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -69,6 +69,9 @@ static struct omap_iommu_domain *to_omap_domain(struct iommu_domain *dom) | |||
69 | /** | 69 | /** |
70 | * omap_iommu_save_ctx - Save registers for pm off-mode support | 70 | * omap_iommu_save_ctx - Save registers for pm off-mode support |
71 | * @dev: client device | 71 | * @dev: client device |
72 | * | ||
73 | * This should be treated as an deprecated API. It is preserved only | ||
74 | * to maintain existing functionality for OMAP3 ISP driver. | ||
72 | **/ | 75 | **/ |
73 | void omap_iommu_save_ctx(struct device *dev) | 76 | void omap_iommu_save_ctx(struct device *dev) |
74 | { | 77 | { |
@@ -96,6 +99,9 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); | |||
96 | /** | 99 | /** |
97 | * omap_iommu_restore_ctx - Restore registers for pm off-mode support | 100 | * omap_iommu_restore_ctx - Restore registers for pm off-mode support |
98 | * @dev: client device | 101 | * @dev: client device |
102 | * | ||
103 | * This should be treated as an deprecated API. It is preserved only | ||
104 | * to maintain existing functionality for OMAP3 ISP driver. | ||
99 | **/ | 105 | **/ |
100 | void omap_iommu_restore_ctx(struct device *dev) | 106 | void omap_iommu_restore_ctx(struct device *dev) |
101 | { | 107 | { |
@@ -190,53 +196,18 @@ static void omap2_iommu_disable(struct omap_iommu *obj) | |||
190 | 196 | ||
191 | static int iommu_enable(struct omap_iommu *obj) | 197 | static int iommu_enable(struct omap_iommu *obj) |
192 | { | 198 | { |
193 | int err; | 199 | 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 | 200 | ||
215 | err = omap2_iommu_enable(obj); | 201 | ret = pm_runtime_get_sync(obj->dev); |
202 | if (ret < 0) | ||
203 | pm_runtime_put_noidle(obj->dev); | ||
216 | 204 | ||
217 | return err; | 205 | return ret < 0 ? ret : 0; |
218 | } | 206 | } |
219 | 207 | ||
220 | static void iommu_disable(struct omap_iommu *obj) | 208 | static void iommu_disable(struct omap_iommu *obj) |
221 | { | 209 | { |
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); | 210 | 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 | } | 211 | } |
241 | 212 | ||
242 | /* | 213 | /* |
@@ -922,15 +893,219 @@ static void omap_iommu_detach(struct omap_iommu *obj) | |||
922 | 893 | ||
923 | dma_unmap_single(obj->dev, obj->pd_dma, IOPGD_TABLE_SIZE, | 894 | dma_unmap_single(obj->dev, obj->pd_dma, IOPGD_TABLE_SIZE, |
924 | DMA_TO_DEVICE); | 895 | DMA_TO_DEVICE); |
925 | iommu_disable(obj); | ||
926 | obj->pd_dma = 0; | 896 | obj->pd_dma = 0; |
927 | obj->iopgd = NULL; | 897 | obj->iopgd = NULL; |
898 | iommu_disable(obj); | ||
928 | 899 | ||
929 | spin_unlock(&obj->iommu_lock); | 900 | spin_unlock(&obj->iommu_lock); |
930 | 901 | ||
931 | dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); | 902 | dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); |
932 | } | 903 | } |
933 | 904 | ||
905 | static void omap_iommu_save_tlb_entries(struct omap_iommu *obj) | ||
906 | { | ||
907 | struct iotlb_lock lock; | ||
908 | struct cr_regs cr; | ||
909 | struct cr_regs *tmp; | ||
910 | int i; | ||
911 | |||
912 | /* check if there are any locked tlbs to save */ | ||
913 | iotlb_lock_get(obj, &lock); | ||
914 | obj->num_cr_ctx = lock.base; | ||
915 | if (!obj->num_cr_ctx) | ||
916 | return; | ||
917 | |||
918 | tmp = obj->cr_ctx; | ||
919 | for_each_iotlb_cr(obj, obj->num_cr_ctx, i, cr) | ||
920 | *tmp++ = cr; | ||
921 | } | ||
922 | |||
923 | static void omap_iommu_restore_tlb_entries(struct omap_iommu *obj) | ||
924 | { | ||
925 | struct iotlb_lock l; | ||
926 | struct cr_regs *tmp; | ||
927 | int i; | ||
928 | |||
929 | /* no locked tlbs to restore */ | ||
930 | if (!obj->num_cr_ctx) | ||
931 | return; | ||
932 | |||
933 | l.base = 0; | ||
934 | tmp = obj->cr_ctx; | ||
935 | for (i = 0; i < obj->num_cr_ctx; i++, tmp++) { | ||
936 | l.vict = i; | ||
937 | iotlb_lock_set(obj, &l); | ||
938 | iotlb_load_cr(obj, tmp); | ||
939 | } | ||
940 | l.base = obj->num_cr_ctx; | ||
941 | l.vict = i; | ||
942 | iotlb_lock_set(obj, &l); | ||
943 | } | ||
944 | |||
945 | /** | ||
946 | * omap_iommu_domain_deactivate - deactivate attached iommu devices | ||
947 | * @domain: iommu domain attached to the target iommu device | ||
948 | * | ||
949 | * This API allows the client devices of IOMMU devices to suspend | ||
950 | * the IOMMUs they control at runtime, after they are idled and | ||
951 | * suspended all activity. System Suspend will leverage the PM | ||
952 | * driver late callbacks. | ||
953 | **/ | ||
954 | int omap_iommu_domain_deactivate(struct iommu_domain *domain) | ||
955 | { | ||
956 | struct omap_iommu_domain *omap_domain = to_omap_domain(domain); | ||
957 | struct omap_iommu_device *iommu; | ||
958 | struct omap_iommu *oiommu; | ||
959 | int i; | ||
960 | |||
961 | if (!omap_domain->dev) | ||
962 | return 0; | ||
963 | |||
964 | iommu = omap_domain->iommus; | ||
965 | iommu += (omap_domain->num_iommus - 1); | ||
966 | for (i = 0; i < omap_domain->num_iommus; i++, iommu--) { | ||
967 | oiommu = iommu->iommu_dev; | ||
968 | pm_runtime_put_sync(oiommu->dev); | ||
969 | } | ||
970 | |||
971 | return 0; | ||
972 | } | ||
973 | EXPORT_SYMBOL_GPL(omap_iommu_domain_deactivate); | ||
974 | |||
975 | /** | ||
976 | * omap_iommu_domain_activate - activate attached iommu devices | ||
977 | * @domain: iommu domain attached to the target iommu device | ||
978 | * | ||
979 | * This API allows the client devices of IOMMU devices to resume the | ||
980 | * IOMMUs they control at runtime, before they can resume operations. | ||
981 | * System Resume will leverage the PM driver late callbacks. | ||
982 | **/ | ||
983 | int omap_iommu_domain_activate(struct iommu_domain *domain) | ||
984 | { | ||
985 | struct omap_iommu_domain *omap_domain = to_omap_domain(domain); | ||
986 | struct omap_iommu_device *iommu; | ||
987 | struct omap_iommu *oiommu; | ||
988 | int i; | ||
989 | |||
990 | if (!omap_domain->dev) | ||
991 | return 0; | ||
992 | |||
993 | iommu = omap_domain->iommus; | ||
994 | for (i = 0; i < omap_domain->num_iommus; i++, iommu++) { | ||
995 | oiommu = iommu->iommu_dev; | ||
996 | pm_runtime_get_sync(oiommu->dev); | ||
997 | } | ||
998 | |||
999 | return 0; | ||
1000 | } | ||
1001 | EXPORT_SYMBOL_GPL(omap_iommu_domain_activate); | ||
1002 | |||
1003 | /** | ||
1004 | * omap_iommu_runtime_suspend - disable an iommu device | ||
1005 | * @dev: iommu device | ||
1006 | * | ||
1007 | * This function performs all that is necessary to disable an | ||
1008 | * IOMMU device, either during final detachment from a client | ||
1009 | * device, or during system/runtime suspend of the device. This | ||
1010 | * includes programming all the appropriate IOMMU registers, and | ||
1011 | * managing the associated omap_hwmod's state and the device's | ||
1012 | * reset line. This function also saves the context of any | ||
1013 | * locked TLBs if suspending. | ||
1014 | **/ | ||
1015 | static int omap_iommu_runtime_suspend(struct device *dev) | ||
1016 | { | ||
1017 | struct platform_device *pdev = to_platform_device(dev); | ||
1018 | struct iommu_platform_data *pdata = dev_get_platdata(dev); | ||
1019 | struct omap_iommu *obj = to_iommu(dev); | ||
1020 | int ret; | ||
1021 | |||
1022 | /* save the TLBs only during suspend, and not for power down */ | ||
1023 | if (obj->domain && obj->iopgd) | ||
1024 | omap_iommu_save_tlb_entries(obj); | ||
1025 | |||
1026 | omap2_iommu_disable(obj); | ||
1027 | |||
1028 | if (pdata && pdata->device_idle) | ||
1029 | pdata->device_idle(pdev); | ||
1030 | |||
1031 | if (pdata && pdata->assert_reset) | ||
1032 | pdata->assert_reset(pdev, pdata->reset_name); | ||
1033 | |||
1034 | if (pdata && pdata->set_pwrdm_constraint) { | ||
1035 | ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst); | ||
1036 | if (ret) { | ||
1037 | dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n", | ||
1038 | ret); | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | /** | ||
1046 | * omap_iommu_runtime_resume - enable an iommu device | ||
1047 | * @dev: iommu device | ||
1048 | * | ||
1049 | * This function performs all that is necessary to enable an | ||
1050 | * IOMMU device, either during initial attachment to a client | ||
1051 | * device, or during system/runtime resume of the device. This | ||
1052 | * includes programming all the appropriate IOMMU registers, and | ||
1053 | * managing the associated omap_hwmod's state and the device's | ||
1054 | * reset line. The function also restores any locked TLBs if | ||
1055 | * resuming after a suspend. | ||
1056 | **/ | ||
1057 | static int omap_iommu_runtime_resume(struct device *dev) | ||
1058 | { | ||
1059 | struct platform_device *pdev = to_platform_device(dev); | ||
1060 | struct iommu_platform_data *pdata = dev_get_platdata(dev); | ||
1061 | struct omap_iommu *obj = to_iommu(dev); | ||
1062 | int ret = 0; | ||
1063 | |||
1064 | if (pdata && pdata->set_pwrdm_constraint) { | ||
1065 | ret = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst); | ||
1066 | if (ret) { | ||
1067 | dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n", | ||
1068 | ret); | ||
1069 | } | ||
1070 | } | ||
1071 | |||
1072 | if (pdata && pdata->deassert_reset) { | ||
1073 | ret = pdata->deassert_reset(pdev, pdata->reset_name); | ||
1074 | if (ret) { | ||
1075 | dev_err(dev, "deassert_reset failed: %d\n", ret); | ||
1076 | return ret; | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | if (pdata && pdata->device_enable) | ||
1081 | pdata->device_enable(pdev); | ||
1082 | |||
1083 | /* restore the TLBs only during resume, and not for power up */ | ||
1084 | if (obj->domain) | ||
1085 | omap_iommu_restore_tlb_entries(obj); | ||
1086 | |||
1087 | ret = omap2_iommu_enable(obj); | ||
1088 | |||
1089 | return ret; | ||
1090 | } | ||
1091 | |||
1092 | /** | ||
1093 | * omap_iommu_suspend_prepare - prepare() dev_pm_ops implementation | ||
1094 | * @dev: iommu device | ||
1095 | * | ||
1096 | * This function performs the necessary checks to determine if the IOMMU | ||
1097 | * device needs suspending or not. The function checks if the runtime_pm | ||
1098 | * status of the device is suspended, and returns 1 in that case. This | ||
1099 | * results in the PM core to skip invoking any of the Sleep PM callbacks | ||
1100 | * (suspend, suspend_late, resume, resume_early etc). | ||
1101 | */ | ||
1102 | static int omap_iommu_prepare(struct device *dev) | ||
1103 | { | ||
1104 | if (pm_runtime_status_suspended(dev)) | ||
1105 | return 1; | ||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
934 | static bool omap_iommu_can_register(struct platform_device *pdev) | 1109 | static bool omap_iommu_can_register(struct platform_device *pdev) |
935 | { | 1110 | { |
936 | struct device_node *np = pdev->dev.of_node; | 1111 | struct device_node *np = pdev->dev.of_node; |
@@ -1005,6 +1180,15 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
1005 | if (!obj) | 1180 | if (!obj) |
1006 | return -ENOMEM; | 1181 | return -ENOMEM; |
1007 | 1182 | ||
1183 | /* | ||
1184 | * self-manage the ordering dependencies between omap_device_enable/idle | ||
1185 | * and omap_device_assert/deassert_hardreset API | ||
1186 | */ | ||
1187 | if (pdev->dev.pm_domain) { | ||
1188 | dev_dbg(&pdev->dev, "device pm_domain is being reset\n"); | ||
1189 | pdev->dev.pm_domain = NULL; | ||
1190 | } | ||
1191 | |||
1008 | obj->name = dev_name(&pdev->dev); | 1192 | obj->name = dev_name(&pdev->dev); |
1009 | obj->nr_tlb_entries = 32; | 1193 | obj->nr_tlb_entries = 32; |
1010 | err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries); | 1194 | err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries); |
@@ -1017,6 +1201,11 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
1017 | 1201 | ||
1018 | obj->dev = &pdev->dev; | 1202 | obj->dev = &pdev->dev; |
1019 | obj->ctx = (void *)obj + sizeof(*obj); | 1203 | obj->ctx = (void *)obj + sizeof(*obj); |
1204 | obj->cr_ctx = devm_kzalloc(&pdev->dev, | ||
1205 | sizeof(*obj->cr_ctx) * obj->nr_tlb_entries, | ||
1206 | GFP_KERNEL); | ||
1207 | if (!obj->cr_ctx) | ||
1208 | return -ENOMEM; | ||
1020 | 1209 | ||
1021 | spin_lock_init(&obj->iommu_lock); | 1210 | spin_lock_init(&obj->iommu_lock); |
1022 | spin_lock_init(&obj->page_table_lock); | 1211 | spin_lock_init(&obj->page_table_lock); |
@@ -1093,6 +1282,14 @@ static int omap_iommu_remove(struct platform_device *pdev) | |||
1093 | return 0; | 1282 | return 0; |
1094 | } | 1283 | } |
1095 | 1284 | ||
1285 | static const struct dev_pm_ops omap_iommu_pm_ops = { | ||
1286 | .prepare = omap_iommu_prepare, | ||
1287 | SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
1288 | pm_runtime_force_resume) | ||
1289 | SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend, | ||
1290 | omap_iommu_runtime_resume, NULL) | ||
1291 | }; | ||
1292 | |||
1096 | static const struct of_device_id omap_iommu_of_match[] = { | 1293 | static const struct of_device_id omap_iommu_of_match[] = { |
1097 | { .compatible = "ti,omap2-iommu" }, | 1294 | { .compatible = "ti,omap2-iommu" }, |
1098 | { .compatible = "ti,omap4-iommu" }, | 1295 | { .compatible = "ti,omap4-iommu" }, |
@@ -1106,6 +1303,7 @@ static struct platform_driver omap_iommu_driver = { | |||
1106 | .remove = omap_iommu_remove, | 1303 | .remove = omap_iommu_remove, |
1107 | .driver = { | 1304 | .driver = { |
1108 | .name = "omap-iommu", | 1305 | .name = "omap-iommu", |
1306 | .pm = &omap_iommu_pm_ops, | ||
1109 | .of_match_table = of_match_ptr(omap_iommu_of_match), | 1307 | .of_match_table = of_match_ptr(omap_iommu_of_match), |
1110 | }, | 1308 | }, |
1111 | }; | 1309 | }; |
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index 7766d5a4f3f1..ca07fbf287d0 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h | |||
@@ -76,6 +76,9 @@ struct omap_iommu { | |||
76 | 76 | ||
77 | void *ctx; /* iommu context: registres saved area */ | 77 | void *ctx; /* iommu context: registres saved area */ |
78 | 78 | ||
79 | struct cr_regs *cr_ctx; | ||
80 | u32 num_cr_ctx; | ||
81 | |||
79 | int has_bus_err_back; | 82 | int has_bus_err_back; |
80 | u32 id; | 83 | u32 id; |
81 | 84 | ||
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 3e34778c2ceb..2016de9e650d 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c | |||
@@ -16,14 +16,17 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/io.h> | ||
19 | #include <linux/of_device.h> | 20 | #include <linux/of_device.h> |
20 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
21 | #include <linux/of_reserved_mem.h> | 22 | #include <linux/of_reserved_mem.h> |
22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/pm_runtime.h> | ||
23 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
24 | #include <linux/remoteproc.h> | 26 | #include <linux/remoteproc.h> |
25 | #include <linux/mailbox_client.h> | 27 | #include <linux/mailbox_client.h> |
26 | #include <linux/omap-mailbox.h> | 28 | #include <linux/omap-mailbox.h> |
29 | #include <linux/omap-iommu.h> | ||
27 | #include <linux/regmap.h> | 30 | #include <linux/regmap.h> |
28 | #include <linux/mfd/syscon.h> | 31 | #include <linux/mfd/syscon.h> |
29 | #include <clocksource/timer-ti-dm.h> | 32 | #include <clocksource/timer-ti-dm.h> |
@@ -37,6 +40,9 @@ | |||
37 | #define OMAP_RPROC_DSP_LOCAL_MEM_OFFSET (0x00800000) | 40 | #define OMAP_RPROC_DSP_LOCAL_MEM_OFFSET (0x00800000) |
38 | #define OMAP_RPROC_IPU_L2RAM_DEV_ADDR (0x20000000) | 41 | #define OMAP_RPROC_IPU_L2RAM_DEV_ADDR (0x20000000) |
39 | 42 | ||
43 | /* default auto-suspend delay (ms) */ | ||
44 | #define DEFAULT_AUTOSUSPEND_DELAY 10000 | ||
45 | |||
40 | /** | 46 | /** |
41 | * struct omap_rproc_boot_data - boot data structure for the DSP omap rprocs | 47 | * struct omap_rproc_boot_data - boot data structure for the DSP omap rprocs |
42 | * @syscon: regmap handle for the system control configuration module | 48 | * @syscon: regmap handle for the system control configuration module |
@@ -83,7 +89,12 @@ struct omap_rproc_timer { | |||
83 | * @num_mems: number of internal memory regions | 89 | * @num_mems: number of internal memory regions |
84 | * @num_timers: number of rproc timer(s) | 90 | * @num_timers: number of rproc timer(s) |
85 | * @timers: timer(s) info used by rproc | 91 | * @timers: timer(s) info used by rproc |
92 | * @autosuspend_delay: auto-suspend delay value to be used for runtime pm | ||
93 | * @need_resume: if true a resume is needed in the system resume callback | ||
86 | * @rproc: rproc handle | 94 | * @rproc: rproc handle |
95 | * @pm_comp: completion primitive to sync for suspend response | ||
96 | * @standby_addr: kernel address of the register having module standby status | ||
97 | * @suspend_acked: state machine flag to store the suspend request ack | ||
87 | */ | 98 | */ |
88 | struct omap_rproc { | 99 | struct omap_rproc { |
89 | struct mbox_chan *mbox; | 100 | struct mbox_chan *mbox; |
@@ -93,17 +104,24 @@ struct omap_rproc { | |||
93 | int num_mems; | 104 | int num_mems; |
94 | int num_timers; | 105 | int num_timers; |
95 | struct omap_rproc_timer *timers; | 106 | struct omap_rproc_timer *timers; |
107 | int autosuspend_delay; | ||
108 | bool need_resume; | ||
96 | struct rproc *rproc; | 109 | struct rproc *rproc; |
110 | struct completion pm_comp; | ||
111 | void __iomem *standby_addr; | ||
112 | bool suspend_acked; | ||
97 | }; | 113 | }; |
98 | 114 | ||
99 | /** | 115 | /** |
100 | * struct omap_rproc_dev_data - device data for the omap remote processor | 116 | * struct omap_rproc_dev_data - device data for the omap remote processor |
101 | * @device_name: device name of the remote processor | 117 | * @device_name: device name of the remote processor |
102 | * @fw_name: firmware name to use | 118 | * @fw_name: firmware name to use |
119 | * @autosuspend_delay: custom auto-suspend delay value in milliseconds | ||
103 | */ | 120 | */ |
104 | struct omap_rproc_dev_data { | 121 | struct omap_rproc_dev_data { |
105 | const char *device_name; | 122 | const char *device_name; |
106 | const char *fw_name; | 123 | const char *fw_name; |
124 | int autosuspend_delay; | ||
107 | }; | 125 | }; |
108 | 126 | ||
109 | /** | 127 | /** |
@@ -344,6 +362,11 @@ static void omap_rproc_mbox_callback(struct mbox_client *client, void *data) | |||
344 | case RP_MBOX_ECHO_REPLY: | 362 | case RP_MBOX_ECHO_REPLY: |
345 | dev_info(dev, "received echo reply from %s\n", name); | 363 | dev_info(dev, "received echo reply from %s\n", name); |
346 | break; | 364 | break; |
365 | case RP_MBOX_SUSPEND_ACK: | ||
366 | case RP_MBOX_SUSPEND_CANCEL: | ||
367 | oproc->suspend_acked = msg == RP_MBOX_SUSPEND_ACK; | ||
368 | complete(&oproc->pm_comp); | ||
369 | break; | ||
347 | default: | 370 | default: |
348 | if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG) | 371 | if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG) |
349 | return; | 372 | return; |
@@ -364,11 +387,23 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) | |||
364 | struct device *dev = rproc->dev.parent; | 387 | struct device *dev = rproc->dev.parent; |
365 | int ret; | 388 | int ret; |
366 | 389 | ||
390 | /* wake up the rproc before kicking it */ | ||
391 | ret = pm_runtime_get_sync(dev); | ||
392 | if (WARN_ON(ret < 0)) { | ||
393 | dev_err(dev, "pm_runtime_get_sync() failed during kick, ret = %d\n", | ||
394 | ret); | ||
395 | pm_runtime_put_noidle(dev); | ||
396 | return; | ||
397 | } | ||
398 | |||
367 | /* send the index of the triggered virtqueue in the mailbox payload */ | 399 | /* send the index of the triggered virtqueue in the mailbox payload */ |
368 | ret = mbox_send_message(oproc->mbox, (void *)vqid); | 400 | ret = mbox_send_message(oproc->mbox, (void *)vqid); |
369 | if (ret < 0) | 401 | if (ret < 0) |
370 | dev_err(dev, "failed to send mailbox message, status = %d\n", | 402 | dev_err(dev, "failed to send mailbox message, status = %d\n", |
371 | ret); | 403 | ret); |
404 | |||
405 | pm_runtime_mark_last_busy(dev); | ||
406 | pm_runtime_put_autosuspend(dev); | ||
372 | } | 407 | } |
373 | 408 | ||
374 | /** | 409 | /** |
@@ -461,6 +496,19 @@ static int omap_rproc_start(struct rproc *rproc) | |||
461 | goto reset_timers; | 496 | goto reset_timers; |
462 | } | 497 | } |
463 | 498 | ||
499 | /* | ||
500 | * remote processor is up, so update the runtime pm status and | ||
501 | * enable the auto-suspend. The device usage count is incremented | ||
502 | * manually for balancing it for auto-suspend | ||
503 | */ | ||
504 | pm_runtime_set_active(dev); | ||
505 | pm_runtime_set_autosuspend_delay(dev, oproc->autosuspend_delay); | ||
506 | pm_runtime_use_autosuspend(dev); | ||
507 | pm_runtime_get_noresume(dev); | ||
508 | pm_runtime_enable(dev); | ||
509 | pm_runtime_mark_last_busy(dev); | ||
510 | pm_runtime_put_autosuspend(dev); | ||
511 | |||
464 | return 0; | 512 | return 0; |
465 | 513 | ||
466 | reset_timers: | 514 | reset_timers: |
@@ -479,17 +527,49 @@ static int omap_rproc_stop(struct rproc *rproc) | |||
479 | struct omap_rproc *oproc = rproc->priv; | 527 | struct omap_rproc *oproc = rproc->priv; |
480 | int ret; | 528 | int ret; |
481 | 529 | ||
530 | /* | ||
531 | * cancel any possible scheduled runtime suspend by incrementing | ||
532 | * the device usage count, and resuming the device. The remoteproc | ||
533 | * also needs to be woken up if suspended, to avoid the remoteproc | ||
534 | * OS to continue to remember any context that it has saved, and | ||
535 | * avoid potential issues in misindentifying a subsequent device | ||
536 | * reboot as a power restore boot | ||
537 | */ | ||
538 | ret = pm_runtime_get_sync(dev); | ||
539 | if (ret < 0) { | ||
540 | pm_runtime_put_noidle(dev); | ||
541 | return ret; | ||
542 | } | ||
543 | |||
482 | ret = pdata->device_shutdown(pdev); | 544 | ret = pdata->device_shutdown(pdev); |
483 | if (ret) | 545 | if (ret) |
484 | return ret; | 546 | goto out; |
485 | 547 | ||
486 | ret = omap_rproc_disable_timers(rproc, true); | 548 | ret = omap_rproc_disable_timers(rproc, true); |
487 | if (ret) | 549 | if (ret) |
488 | return ret; | 550 | goto enable_device; |
489 | 551 | ||
490 | mbox_free_channel(oproc->mbox); | 552 | mbox_free_channel(oproc->mbox); |
491 | 553 | ||
554 | /* | ||
555 | * update the runtime pm states and status now that the remoteproc | ||
556 | * has stopped | ||
557 | */ | ||
558 | pm_runtime_disable(dev); | ||
559 | pm_runtime_dont_use_autosuspend(dev); | ||
560 | pm_runtime_put_noidle(dev); | ||
561 | pm_runtime_set_suspended(dev); | ||
562 | |||
492 | return 0; | 563 | return 0; |
564 | |||
565 | enable_device: | ||
566 | pdata->device_enable(pdev); | ||
567 | out: | ||
568 | /* schedule the next auto-suspend */ | ||
569 | pm_runtime_mark_last_busy(dev); | ||
570 | pm_runtime_put_autosuspend(dev); | ||
571 | return ret; | ||
572 | |||
493 | } | 573 | } |
494 | 574 | ||
495 | /* | 575 | /* |
@@ -534,6 +614,289 @@ static const struct rproc_ops omap_rproc_ops = { | |||
534 | .da_to_va = omap_rproc_da_to_va, | 614 | .da_to_va = omap_rproc_da_to_va, |
535 | }; | 615 | }; |
536 | 616 | ||
617 | #ifdef CONFIG_PM | ||
618 | static bool _is_rproc_in_standby(struct omap_rproc *oproc) | ||
619 | { | ||
620 | static int standby_mask = (1 << 18); | ||
621 | |||
622 | return readl(oproc->standby_addr) & standby_mask; | ||
623 | } | ||
624 | |||
625 | /* 1 sec is long enough time to let the remoteproc side suspend the device */ | ||
626 | #define DEF_SUSPEND_TIMEOUT 1000 | ||
627 | static int _omap_rproc_suspend(struct rproc *rproc, bool auto_suspend) | ||
628 | { | ||
629 | struct device *dev = rproc->dev.parent; | ||
630 | struct platform_device *pdev = to_platform_device(dev); | ||
631 | struct omap_rproc_pdata *pdata = dev_get_platdata(dev); | ||
632 | struct omap_rproc *oproc = rproc->priv; | ||
633 | unsigned long to = msecs_to_jiffies(DEF_SUSPEND_TIMEOUT); | ||
634 | unsigned long ta = jiffies + to; | ||
635 | u32 suspend_msg = auto_suspend ? | ||
636 | RP_MBOX_SUSPEND_AUTO : RP_MBOX_SUSPEND_SYSTEM; | ||
637 | int ret; | ||
638 | |||
639 | reinit_completion(&oproc->pm_comp); | ||
640 | oproc->suspend_acked = false; | ||
641 | ret = mbox_send_message(oproc->mbox, (void *)suspend_msg); | ||
642 | if (ret < 0) { | ||
643 | dev_err(dev, "PM mbox_send_message failed: %d\n", ret); | ||
644 | return ret; | ||
645 | } | ||
646 | |||
647 | ret = wait_for_completion_timeout(&oproc->pm_comp, to); | ||
648 | if (!oproc->suspend_acked) | ||
649 | return -EBUSY; | ||
650 | |||
651 | /* | ||
652 | * The remoteproc side is returning the ACK message before saving the | ||
653 | * context, because the context saving is performed within a SYS/BIOS | ||
654 | * function, and it cannot have any inter-dependencies against the IPC | ||
655 | * layer. Also, as the SYS/BIOS needs to preserve properly the processor | ||
656 | * register set, sending this ACK or signalling the completion of the | ||
657 | * context save through a shared memory variable can never be the | ||
658 | * absolute last thing to be executed on the remoteproc side, and the | ||
659 | * MPU cannot use the ACK message as a sync point to put the remoteproc | ||
660 | * into reset. The only way to ensure that the remote processor has | ||
661 | * completed saving the context is to check that the module has reached | ||
662 | * STANDBY state (after saving the context, the SYS/BIOS executes the | ||
663 | * appropriate target-specific WFI instruction causing the module to | ||
664 | * enter STANDBY). | ||
665 | */ | ||
666 | while (!_is_rproc_in_standby(oproc)) { | ||
667 | if (time_after(jiffies, ta)) | ||
668 | return -ETIME; | ||
669 | schedule(); | ||
670 | } | ||
671 | |||
672 | ret = pdata->device_shutdown(pdev); | ||
673 | if (ret) | ||
674 | return ret; | ||
675 | |||
676 | ret = omap_rproc_disable_timers(rproc, false); | ||
677 | if (ret) { | ||
678 | dev_err(dev, "disabling timers during suspend failed %d\n", | ||
679 | ret); | ||
680 | goto enable_device; | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * IOMMUs would have to be disabled specifically for runtime suspend. | ||
685 | * They are handled automatically through System PM callbacks for | ||
686 | * regular system suspend | ||
687 | */ | ||
688 | if (auto_suspend) { | ||
689 | ret = omap_iommu_domain_deactivate(rproc->domain); | ||
690 | if (ret) { | ||
691 | dev_err(dev, "iommu domain deactivate failed %d\n", | ||
692 | ret); | ||
693 | goto enable_timers; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | return 0; | ||
698 | |||
699 | enable_timers: | ||
700 | /* ignore errors on re-enabling code */ | ||
701 | omap_rproc_enable_timers(rproc, false); | ||
702 | enable_device: | ||
703 | pdata->device_enable(pdev); | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static int _omap_rproc_resume(struct rproc *rproc, bool auto_suspend) | ||
708 | { | ||
709 | struct device *dev = rproc->dev.parent; | ||
710 | struct platform_device *pdev = to_platform_device(dev); | ||
711 | struct omap_rproc_pdata *pdata = dev_get_platdata(dev); | ||
712 | struct omap_rproc *oproc = rproc->priv; | ||
713 | int ret; | ||
714 | |||
715 | /* | ||
716 | * IOMMUs would have to be enabled specifically for runtime resume. | ||
717 | * They would have been already enabled automatically through System | ||
718 | * PM callbacks for regular system resume | ||
719 | */ | ||
720 | if (auto_suspend) { | ||
721 | ret = omap_iommu_domain_activate(rproc->domain); | ||
722 | if (ret) { | ||
723 | dev_err(dev, "omap_iommu activate failed %d\n", ret); | ||
724 | goto out; | ||
725 | } | ||
726 | } | ||
727 | |||
728 | /* boot address could be lost after suspend, so restore it */ | ||
729 | if (oproc->boot_data) { | ||
730 | ret = omap_rproc_write_dsp_boot_addr(rproc); | ||
731 | if (ret) { | ||
732 | dev_err(dev, "boot address restore failed %d\n", ret); | ||
733 | goto suspend_iommu; | ||
734 | } | ||
735 | } | ||
736 | |||
737 | ret = omap_rproc_enable_timers(rproc, false); | ||
738 | if (ret) { | ||
739 | dev_err(dev, "enabling timers during resume failed %d\n", | ||
740 | ret); | ||
741 | goto suspend_iommu; | ||
742 | } | ||
743 | |||
744 | ret = pdata->device_enable(pdev); | ||
745 | if (ret) | ||
746 | goto disable_timers; | ||
747 | |||
748 | return 0; | ||
749 | |||
750 | disable_timers: | ||
751 | omap_rproc_disable_timers(rproc, false); | ||
752 | suspend_iommu: | ||
753 | if (auto_suspend) | ||
754 | omap_iommu_domain_deactivate(rproc->domain); | ||
755 | out: | ||
756 | return ret; | ||
757 | } | ||
758 | |||
759 | static int __maybe_unused omap_rproc_suspend(struct device *dev) | ||
760 | { | ||
761 | struct platform_device *pdev = to_platform_device(dev); | ||
762 | struct rproc *rproc = platform_get_drvdata(pdev); | ||
763 | struct omap_rproc *oproc = rproc->priv; | ||
764 | int ret = 0; | ||
765 | |||
766 | mutex_lock(&rproc->lock); | ||
767 | if (rproc->state == RPROC_OFFLINE) | ||
768 | goto out; | ||
769 | |||
770 | if (rproc->state == RPROC_SUSPENDED) | ||
771 | goto out; | ||
772 | |||
773 | if (rproc->state != RPROC_RUNNING) { | ||
774 | ret = -EBUSY; | ||
775 | goto out; | ||
776 | } | ||
777 | |||
778 | ret = _omap_rproc_suspend(rproc, false); | ||
779 | if (ret) { | ||
780 | dev_err(dev, "suspend failed %d\n", ret); | ||
781 | goto out; | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * remoteproc is running at the time of system suspend, so remember | ||
786 | * it so as to wake it up during system resume | ||
787 | */ | ||
788 | oproc->need_resume = 1; | ||
789 | rproc->state = RPROC_SUSPENDED; | ||
790 | |||
791 | /* | ||
792 | * update the runtime pm status to be suspended, without decrementing | ||
793 | * the device usage count | ||
794 | */ | ||
795 | pm_runtime_disable(dev); | ||
796 | pm_runtime_set_suspended(dev); | ||
797 | out: | ||
798 | mutex_unlock(&rproc->lock); | ||
799 | return ret; | ||
800 | } | ||
801 | |||
802 | static int __maybe_unused omap_rproc_resume(struct device *dev) | ||
803 | { | ||
804 | struct platform_device *pdev = to_platform_device(dev); | ||
805 | struct rproc *rproc = platform_get_drvdata(pdev); | ||
806 | struct omap_rproc *oproc = rproc->priv; | ||
807 | int ret = 0; | ||
808 | |||
809 | mutex_lock(&rproc->lock); | ||
810 | if (rproc->state == RPROC_OFFLINE) | ||
811 | goto out; | ||
812 | |||
813 | if (rproc->state != RPROC_SUSPENDED) { | ||
814 | ret = -EBUSY; | ||
815 | goto out; | ||
816 | } | ||
817 | |||
818 | /* | ||
819 | * remoteproc was auto-suspended at the time of system suspend, | ||
820 | * so no need to wake-up the processor (leave it in suspended | ||
821 | * state, will be woken up during a subsequent runtime_resume) | ||
822 | */ | ||
823 | if (!oproc->need_resume) | ||
824 | goto out; | ||
825 | |||
826 | ret = _omap_rproc_resume(rproc, false); | ||
827 | if (ret) { | ||
828 | dev_err(dev, "resume failed %d\n", ret); | ||
829 | goto out; | ||
830 | } | ||
831 | oproc->need_resume = false; | ||
832 | |||
833 | rproc->state = RPROC_RUNNING; | ||
834 | |||
835 | /* | ||
836 | * update the runtime pm status to be active, without incrementing | ||
837 | * the device usage count | ||
838 | */ | ||
839 | pm_runtime_set_active(dev); | ||
840 | pm_runtime_enable(dev); | ||
841 | pm_runtime_mark_last_busy(dev); | ||
842 | out: | ||
843 | mutex_unlock(&rproc->lock); | ||
844 | return ret; | ||
845 | } | ||
846 | |||
847 | static int omap_rproc_runtime_suspend(struct device *dev) | ||
848 | { | ||
849 | struct rproc *rproc = dev_get_drvdata(dev); | ||
850 | struct omap_rproc *oproc = rproc->priv; | ||
851 | int ret; | ||
852 | |||
853 | if (WARN_ON(rproc->state != RPROC_RUNNING)) { | ||
854 | dev_err(dev, "rproc cannot be runtime suspended when not running!\n"); | ||
855 | return -EBUSY; | ||
856 | } | ||
857 | |||
858 | /* | ||
859 | * do not even attempt suspend if the remote processor is not | ||
860 | * idled for runtime auto-suspend | ||
861 | */ | ||
862 | if (!_is_rproc_in_standby(oproc)) { | ||
863 | ret = -EBUSY; | ||
864 | goto abort; | ||
865 | } | ||
866 | |||
867 | ret = _omap_rproc_suspend(rproc, true); | ||
868 | if (ret) | ||
869 | goto abort; | ||
870 | |||
871 | rproc->state = RPROC_SUSPENDED; | ||
872 | return 0; | ||
873 | |||
874 | abort: | ||
875 | pm_runtime_mark_last_busy(dev); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | static int omap_rproc_runtime_resume(struct device *dev) | ||
880 | { | ||
881 | struct rproc *rproc = dev_get_drvdata(dev); | ||
882 | int ret; | ||
883 | |||
884 | if (WARN_ON(rproc->state != RPROC_SUSPENDED)) { | ||
885 | dev_err(dev, "rproc cannot be runtime resumed if not suspended!\n"); | ||
886 | return -EBUSY; | ||
887 | } | ||
888 | |||
889 | ret = _omap_rproc_resume(rproc, true); | ||
890 | if (ret) { | ||
891 | dev_err(dev, "runtime resume failed %d\n", ret); | ||
892 | return ret; | ||
893 | } | ||
894 | |||
895 | rproc->state = RPROC_RUNNING; | ||
896 | return 0; | ||
897 | } | ||
898 | #endif /* CONFIG_PM */ | ||
899 | |||
537 | static const struct omap_rproc_dev_data omap4_dsp_dev_data = { | 900 | static const struct omap_rproc_dev_data omap4_dsp_dev_data = { |
538 | .device_name = "dsp", | 901 | .device_name = "dsp", |
539 | .fw_name = "omap4-dsp-fw.xe64T", | 902 | .fw_name = "omap4-dsp-fw.xe64T", |
@@ -607,6 +970,33 @@ static const struct of_device_id omap_rproc_of_match[] = { | |||
607 | }; | 970 | }; |
608 | MODULE_DEVICE_TABLE(of, omap_rproc_of_match); | 971 | MODULE_DEVICE_TABLE(of, omap_rproc_of_match); |
609 | 972 | ||
973 | static int omap_rproc_get_autosuspend_delay(struct platform_device *pdev) | ||
974 | { | ||
975 | struct device_node *np = pdev->dev.of_node; | ||
976 | const struct omap_rproc_dev_data *data; | ||
977 | int delay = -EINVAL; | ||
978 | |||
979 | data = of_device_get_match_data(&pdev->dev); | ||
980 | if (!data) | ||
981 | return -ENODEV; | ||
982 | |||
983 | if (!of_device_is_compatible(np, "ti,dra7-dsp") && | ||
984 | !of_device_is_compatible(np, "ti,dra7-ipu")) { | ||
985 | delay = data->autosuspend_delay; | ||
986 | goto out; | ||
987 | } | ||
988 | |||
989 | for (; data && data->device_name; data++) { | ||
990 | if (!strcmp(dev_name(&pdev->dev), data->device_name)) { | ||
991 | delay = data->autosuspend_delay; | ||
992 | break; | ||
993 | } | ||
994 | } | ||
995 | |||
996 | out: | ||
997 | return (delay > 0) ? delay : DEFAULT_AUTOSUSPEND_DELAY; | ||
998 | } | ||
999 | |||
610 | static const char *omap_rproc_get_firmware(struct platform_device *pdev) | 1000 | static const char *omap_rproc_get_firmware(struct platform_device *pdev) |
611 | { | 1001 | { |
612 | struct device_node *np = pdev->dev.of_node; | 1002 | struct device_node *np = pdev->dev.of_node; |
@@ -754,6 +1144,7 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
754 | struct omap_rproc *oproc; | 1144 | struct omap_rproc *oproc; |
755 | struct rproc *rproc; | 1145 | struct rproc *rproc; |
756 | const char *firmware; | 1146 | const char *firmware; |
1147 | u32 standby_addr = 0; | ||
757 | int ret; | 1148 | int ret; |
758 | 1149 | ||
759 | if (!np) { | 1150 | if (!np) { |
@@ -761,6 +1152,16 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
761 | return -ENODEV; | 1152 | return -ENODEV; |
762 | } | 1153 | } |
763 | 1154 | ||
1155 | /* | ||
1156 | * self-manage the ordering dependencies between omap_device_enable/idle | ||
1157 | * and omap_device_assert/deassert_hardreset API during runtime suspend | ||
1158 | * and resume, rather than relying on the order in omap_device layer. | ||
1159 | */ | ||
1160 | if (pdev->dev.pm_domain) { | ||
1161 | dev_dbg(&pdev->dev, "device pm_domain is being reset for this remoteproc device\n"); | ||
1162 | pdev->dev.pm_domain = NULL; | ||
1163 | } | ||
1164 | |||
764 | if (!pdata || !pdata->device_enable || !pdata->device_shutdown) { | 1165 | if (!pdata || !pdata->device_enable || !pdata->device_shutdown) { |
765 | dev_err(&pdev->dev, "platform data is either missing or incomplete\n"); | 1166 | dev_err(&pdev->dev, "platform data is either missing or incomplete\n"); |
766 | return -ENODEV; | 1167 | return -ENODEV; |
@@ -818,6 +1219,26 @@ static int omap_rproc_probe(struct platform_device *pdev) | |||
818 | oproc->num_timers); | 1219 | oproc->num_timers); |
819 | } | 1220 | } |
820 | 1221 | ||
1222 | init_completion(&oproc->pm_comp); | ||
1223 | oproc->autosuspend_delay = omap_rproc_get_autosuspend_delay(pdev); | ||
1224 | if (oproc->autosuspend_delay < 0) { | ||
1225 | ret = oproc->autosuspend_delay; | ||
1226 | goto free_rproc; | ||
1227 | } | ||
1228 | |||
1229 | ret = of_property_read_u32(np, "ti,rproc-standby-info", &standby_addr); | ||
1230 | if (ret || !standby_addr) { | ||
1231 | ret = !standby_addr ? -EINVAL : ret; | ||
1232 | goto free_rproc; | ||
1233 | } | ||
1234 | |||
1235 | oproc->standby_addr = devm_ioremap(&pdev->dev, standby_addr, | ||
1236 | sizeof(u32)); | ||
1237 | if (!oproc->standby_addr) { | ||
1238 | ret = -ENOMEM; | ||
1239 | goto free_rproc; | ||
1240 | } | ||
1241 | |||
821 | ret = of_reserved_mem_device_init(&pdev->dev); | 1242 | ret = of_reserved_mem_device_init(&pdev->dev); |
822 | if (ret) { | 1243 | if (ret) { |
823 | dev_err(&pdev->dev, "device does not have specific CMA pool\n"); | 1244 | dev_err(&pdev->dev, "device does not have specific CMA pool\n"); |
@@ -853,11 +1274,18 @@ static int omap_rproc_remove(struct platform_device *pdev) | |||
853 | return 0; | 1274 | return 0; |
854 | } | 1275 | } |
855 | 1276 | ||
1277 | static const struct dev_pm_ops omap_rproc_pm_ops = { | ||
1278 | SET_SYSTEM_SLEEP_PM_OPS(omap_rproc_suspend, omap_rproc_resume) | ||
1279 | SET_RUNTIME_PM_OPS(omap_rproc_runtime_suspend, | ||
1280 | omap_rproc_runtime_resume, NULL) | ||
1281 | }; | ||
1282 | |||
856 | static struct platform_driver omap_rproc_driver = { | 1283 | static struct platform_driver omap_rproc_driver = { |
857 | .probe = omap_rproc_probe, | 1284 | .probe = omap_rproc_probe, |
858 | .remove = omap_rproc_remove, | 1285 | .remove = omap_rproc_remove, |
859 | .driver = { | 1286 | .driver = { |
860 | .name = "omap-rproc", | 1287 | .name = "omap-rproc", |
1288 | .pm = &omap_rproc_pm_ops, | ||
861 | .of_match_table = omap_rproc_of_match, | 1289 | .of_match_table = omap_rproc_of_match, |
862 | }, | 1290 | }, |
863 | }; | 1291 | }; |
diff --git a/drivers/remoteproc/omap_remoteproc.h b/drivers/remoteproc/omap_remoteproc.h index 18f522617683..b74d140cbbb6 100644 --- a/drivers/remoteproc/omap_remoteproc.h +++ b/drivers/remoteproc/omap_remoteproc.h | |||
@@ -2,7 +2,7 @@ | |||
2 | /* | 2 | /* |
3 | * Remote processor messaging | 3 | * Remote processor messaging |
4 | * | 4 | * |
5 | * Copyright (C) 2011 Texas Instruments, Inc. | 5 | * Copyright (C) 2011-2019 Texas Instruments, Inc. |
6 | * Copyright (C) 2011 Google, Inc. | 6 | * Copyright (C) 2011 Google, Inc. |
7 | * All rights reserved. | 7 | * All rights reserved. |
8 | */ | 8 | */ |
@@ -32,6 +32,16 @@ | |||
32 | * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the | 32 | * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the |
33 | * recovery mechanism (to some extent). | 33 | * recovery mechanism (to some extent). |
34 | * | 34 | * |
35 | * @RP_MBOX_SUSPEND_AUTO: auto suspend request for the remote processor | ||
36 | * | ||
37 | * @RP_MBOX_SUSPEND_SYSTEM: system suspend request for the remote processor | ||
38 | * | ||
39 | * @RP_MBOX_SUSPEND_ACK: successful response from remote processor for a | ||
40 | * suspend request | ||
41 | * | ||
42 | * @RP_MBOX_SUSPEND_CANCEL: a cancel suspend response from a remote processor | ||
43 | * on a suspend request | ||
44 | * | ||
35 | * Introduce new message definitions if any here. | 45 | * Introduce new message definitions if any here. |
36 | * | 46 | * |
37 | * @RP_MBOX_END_MSG: Indicates end of known/defined messages from remote core | 47 | * @RP_MBOX_END_MSG: Indicates end of known/defined messages from remote core |
@@ -45,7 +55,11 @@ enum omap_rp_mbox_messages { | |||
45 | RP_MBOX_ECHO_REQUEST = 0xFFFFFF03, | 55 | RP_MBOX_ECHO_REQUEST = 0xFFFFFF03, |
46 | RP_MBOX_ECHO_REPLY = 0xFFFFFF04, | 56 | RP_MBOX_ECHO_REPLY = 0xFFFFFF04, |
47 | RP_MBOX_ABORT_REQUEST = 0xFFFFFF05, | 57 | RP_MBOX_ABORT_REQUEST = 0xFFFFFF05, |
48 | RP_MBOX_END_MSG = 0xFFFFFF06, | 58 | RP_MBOX_SUSPEND_AUTO = 0xFFFFFF10, |
59 | RP_MBOX_SUSPEND_SYSTEM = 0xFFFFFF11, | ||
60 | RP_MBOX_SUSPEND_ACK = 0xFFFFFF12, | ||
61 | RP_MBOX_SUSPEND_CANCEL = 0xFFFFFF13, | ||
62 | RP_MBOX_END_MSG = 0xFFFFFF14, | ||
49 | }; | 63 | }; |
50 | 64 | ||
51 | #endif /* _OMAP_RPMSG_H */ | 65 | #endif /* _OMAP_RPMSG_H */ |
diff --git a/drivers/remoteproc/remoteproc_sysfs.c b/drivers/remoteproc/remoteproc_sysfs.c index 6b7e8b2b43be..0c47bc0bb36a 100644 --- a/drivers/remoteproc/remoteproc_sysfs.c +++ b/drivers/remoteproc/remoteproc_sysfs.c | |||
@@ -100,7 +100,8 @@ static ssize_t state_store(struct device *dev, | |||
100 | module_put(dev->parent->driver->owner); | 100 | module_put(dev->parent->driver->owner); |
101 | } | 101 | } |
102 | } else if (sysfs_streq(buf, "stop")) { | 102 | } else if (sysfs_streq(buf, "stop")) { |
103 | if (rproc->state != RPROC_RUNNING) | 103 | if (rproc->state != RPROC_RUNNING && |
104 | rproc->state != RPROC_SUSPENDED) | ||
104 | return -EINVAL; | 105 | return -EINVAL; |
105 | 106 | ||
106 | rproc_shutdown(rproc); | 107 | rproc_shutdown(rproc); |
diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h index ce1b7c6283ee..5b66325bc63c 100644 --- a/include/linux/omap-iommu.h +++ b/include/linux/omap-iommu.h | |||
@@ -13,12 +13,27 @@ | |||
13 | #ifndef _OMAP_IOMMU_H_ | 13 | #ifndef _OMAP_IOMMU_H_ |
14 | #define _OMAP_IOMMU_H_ | 14 | #define _OMAP_IOMMU_H_ |
15 | 15 | ||
16 | struct iommu_domain; | ||
17 | |||
16 | #ifdef CONFIG_OMAP_IOMMU | 18 | #ifdef CONFIG_OMAP_IOMMU |
17 | extern void omap_iommu_save_ctx(struct device *dev); | 19 | extern void omap_iommu_save_ctx(struct device *dev); |
18 | extern void omap_iommu_restore_ctx(struct device *dev); | 20 | extern void omap_iommu_restore_ctx(struct device *dev); |
21 | |||
22 | int omap_iommu_domain_deactivate(struct iommu_domain *domain); | ||
23 | int omap_iommu_domain_activate(struct iommu_domain *domain); | ||
19 | #else | 24 | #else |
20 | static inline void omap_iommu_save_ctx(struct device *dev) {} | 25 | static inline void omap_iommu_save_ctx(struct device *dev) {} |
21 | static inline void omap_iommu_restore_ctx(struct device *dev) {} | 26 | static inline void omap_iommu_restore_ctx(struct device *dev) {} |
27 | |||
28 | static inline int omap_iommu_domain_deactivate(struct iommu_domain *domain) | ||
29 | { | ||
30 | return -ENOTSUP; | ||
31 | } | ||
32 | |||
33 | static inline int omap_iommu_domain_activate(struct iommu_domain *domain) | ||
34 | { | ||
35 | return -ENOTSUP; | ||
36 | } | ||
22 | #endif | 37 | #endif |
23 | 38 | ||
24 | #endif | 39 | #endif |
diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h index 1a0aa46a5ad6..6669dc9394da 100644 --- a/include/linux/platform_data/iommu-omap.h +++ b/include/linux/platform_data/iommu-omap.h | |||
@@ -16,6 +16,8 @@ struct iommu_platform_data { | |||
16 | const char *reset_name; | 16 | const char *reset_name; |
17 | int (*assert_reset)(struct platform_device *pdev, const char *name); | 17 | int (*assert_reset)(struct platform_device *pdev, const char *name); |
18 | int (*deassert_reset)(struct platform_device *pdev, const char *name); | 18 | int (*deassert_reset)(struct platform_device *pdev, const char *name); |
19 | int (*device_enable)(struct platform_device *pdev); | ||
20 | int (*device_idle)(struct platform_device *pdev); | ||
19 | int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request, | 21 | int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request, |
20 | u8 *pwrst); | 22 | u8 *pwrst); |
21 | }; | 23 | }; |