ARM: omap: edma: add suspend resume hook
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and omap_hsmmc.
All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from __init context, annotations had to be dropped.
---
Changes from v8:
* Drop the edma_suspend hook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* Use SET_LATE_SYSTEM_SLEEP_PM_OPS in the dev_pm_ops declaration.
Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)
arch/arm/common/edma.c +58 -2
@@ -244,6 +244,8 @@ struct edma {/* list of channels with no even trigger; terminated by "-1" */ const s8 *noevent; +struct edma_soc_info *info; +/* The edma_inuse bit for each PaRAM slot is clear unless the * channel is in use ... by ARM or DSP, for QDMA, or whatever. */
@@ -295,7 +297,7 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no, ~(0x7 << bit), queue_no << bit); } -static void __init assign_priority_to_queue (unsigned ctlr,int queue_no, +static void assign_priority_to_queue (unsigned ctlr,int queue_no,int priority) {int bit = queue_no *4 ;
@@ -314,7 +316,7 @@ static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,* included in that particular EDMA variant (Eg : dm646x) * */ -static void __init map_dmach_param (unsigned ctlr) +static void map_dmach_param (unsigned ctlr) {int i;for (i =0 ; i <EDMA_MAX_DMACH ; i++)
@@ -1762,15 +1764,69 @@ static int edma_probe(struct platform_device *pdev)edma_write_array2 (j,EDMA_DRAE , i,1 ,0x0 );edma_write_array (j,EDMA_QRAE , i,0x0 ); } + edma_cc[j]->info = info[j]; arch_num_cc++; }return 0 ; } +static int edma_pm_resume (struct device *dev) +{ +int i, j, r; + + r =pm_runtime_get_sync (dev); +if (r <0 ) { +dev_err (dev,"%s: get_sync returned %d\n" , __func__, r); +return r; + } + +for (j =0 ; j < arch_num_cc; j++) { +struct edma *cc = edma_cc[j]; + +s8 (*queue_priority_mapping)[2 ]; + + queue_priority_mapping = cc->info->queue_priority_mapping; + +/* Event queue priority mapping */ +for (i =0 ; queue_priority_mapping[i][0 ] !=-1 ; i++) +assign_priority_to_queue (j, + queue_priority_mapping[i][0 ], + queue_priority_mapping[i][1 ]); + +/* +* Map the channel to param entry if channel mapping logic +* exist +*/ +if (edma_read (j,EDMA_CCCFG ) &CHMAP_EXIST ) +map_dmach_param (j); + +for (i =0 ; i < cc->num_channels; i++) { +if (test_bit (i, cc->edma_inuse)) { +/* ensure access through shadow region 0 */ +edma_or_array2 (j,EDMA_DRAE ,0 , i >>5 , +BIT (i &0x1f )); + +setup_dma_interrupt (i, + cc->intr_data[i].callback, + cc->intr_data[i].data); + } + } + } + +pm_runtime_put_sync (dev); + +return 0 ; +} + +static const struct dev_pm_ops edma_pm_ops = { +SET_LATE_SYSTEM_SLEEP_PM_OPS (NULL , edma_pm_resume) +}; +static struct platform_driver edma_driver = { .driver = { .name ="edma" , + .pm = &edma_pm_ops, .of_match_table = edma_of_ids, }, .probe = edma_probe,
Signature · 1 line
2.1.0
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Quoted 24 lines · Daniel Mack
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and
omap_hsmmc.All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from
__initcontext, annotations had to be dropped.[nm at ti.com: added error handling for runtime + suspend_late/early_resume]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Daniel Mack <[email protected]>Tested-by Joel Fernandes <[email protected]>Acked-by Joel Fernandes <[email protected]>---
Changes from v8:* Drop the
edma_suspendhook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* UseSET_LATE_SYSTEM_SLEEP_PM_OPSin thedev_pm_opsdeclaration.
Quoted 4 lines
Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)
Doesn't seem to be any comments here, any chance this can be picked up? This patch always seems to get missed but will be needed for suspend/resume on both AM335x and AM437x.
Regards,
Dave
Quoted 103 lines
arch/arm/common/edma.c +58
-2@@ -244,6 +244,8 @@ struct edma {/* list of channels with no even trigger; terminated by "-1" */ const s8 *noevent; +struct edma_soc_info *info; +/* The edma_inuse bit for each PaRAM slot is clear unless the * channel is in use ... by ARM or DSP, for QDMA, or whatever. */ @@ -295,7 +297,7 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no, ~(0x7 << bit), queue_no << bit); } -static void __init assign_priority_to_queue (unsigned ctlr,int queue_no, +static void assign_priority_to_queue (unsigned ctlr,int queue_no,int priority) {int bit = queue_no *4 ;@@ -314,7 +316,7 @@ static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,* included in that particular EDMA variant (Eg : dm646x) * */ -static void __init map_dmach_param (unsigned ctlr) +static void map_dmach_param (unsigned ctlr) {int i;for (i =0 ; i <EDMA_MAX_DMACH ; i++)@@ -1762,15 +1764,69 @@ static int edma_probe(struct platform_device *pdev)edma_write_array2 (j,EDMA_DRAE , i,1 ,0x0 );edma_write_array (j,EDMA_QRAE , i,0x0 ); } + edma_cc[j]->info = info[j]; arch_num_cc++; }return 0 ; } +static int edma_pm_resume (struct device *dev) +{ +int i, j, r; + + r =pm_runtime_get_sync (dev); +if (r <0 ) { +dev_err (dev,"%s: get_sync returned %d\n" , __func__, r); +return r; + } + +for (j =0 ; j < arch_num_cc; j++) { +struct edma *cc = edma_cc[j]; + +s8 (*queue_priority_mapping)[2 ]; + + queue_priority_mapping = cc->info->queue_priority_mapping; + +/* Event queue priority mapping */ +for (i =0 ; queue_priority_mapping[i][0 ] !=-1 ; i++) +assign_priority_to_queue (j, + queue_priority_mapping[i][0 ], + queue_priority_mapping[i][1 ]); + +/* +* Map the channel to param entry if channel mapping logic +* exist +*/ +if (edma_read (j,EDMA_CCCFG ) &CHMAP_EXIST ) +map_dmach_param (j); + +for (i =0 ; i < cc->num_channels; i++) { +if (test_bit (i, cc->edma_inuse)) { +/* ensure access through shadow region 0 */ +edma_or_array2 (j,EDMA_DRAE ,0 , i >>5 , +BIT (i &0x1f )); + +setup_dma_interrupt (i, + cc->intr_data[i].callback, + cc->intr_data[i].data); + } + } + } + +pm_runtime_put_sync (dev); + +return 0 ; +} + +static const struct dev_pm_ops edma_pm_ops = { +SET_LATE_SYSTEM_SLEEP_PM_OPS (NULL , edma_pm_resume) +}; +static struct platform_driver edma_driver = { .driver = { .name ="edma" , + .pm = &edma_pm_ops, .of_match_table = edma_of_ids, }, .probe = edma_probe,
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Quoted 25 lines · Dave Gerlach
Quoted 24 lines · Daniel Mack
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and
omap_hsmmc.All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from
__initcontext, annotations had to be dropped.[nm at ti.com: added error handling for runtime + suspend_late/early_resume]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Daniel Mack <[email protected]>Tested-by Joel Fernandes <[email protected]>Acked-by Joel Fernandes <[email protected]>---
Changes from v8:* Drop the
edma_suspendhook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* UseSET_LATE_SYSTEM_SLEEP_PM_OPSin thedev_pm_opsdeclaration.
Quoted 8 lines
Quoted 4 lines
Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)Doesn't seem to be any comments here, any chance this can be picked up? This patch always seems to get missed but will be needed for suspend/resume on both AM335x and AM437x.
Dave, do you have a branch against mainline with suspend working on any of these SoCs using which I can test this patch?
Thanks,
Sekhar
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Sekhar,
Quoted 31 lines · Sekhar Nori
Quoted 30 lines · Dave Gerlach
Quoted 28 lines · Daniel Mack
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and
omap_hsmmc.All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from
__initcontext, annotations had to be dropped.[nm at ti.com: added error handling for runtime + suspend_late/early_resume]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Daniel Mack <[email protected]>Tested-by Joel Fernandes <[email protected]>Acked-by Joel Fernandes <[email protected]>---
Changes from v8:* Drop the
edma_suspendhook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* UseSET_LATE_SYSTEM_SLEEP_PM_OPSin thedev_pm_opsdeclaration.Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)
Quoted 6 lines
Quoted 3 lines
Doesn't seem to be any comments here, any chance this can be picked up? This patch always seems to get missed but will be needed for suspend/resume on both AM335x and AM437x.
Dave, do you have a branch against mainline with suspend working on any of these SoCs using which I can test this patch?
Yes, here is WIP of next version with all required patches + this one.
https://github.com/dgerlach/linux-pm/tree/pm-ds0-v3.18-rc3-WIP
For suspend to work you need to select:
CONFIG_WKUP_M3_IPC=yCONFIG_WKUP_M3_RPROC=y
And you need to enable USB for multiple suspends to work.
You can get am335x-pm-firmware.elf FW here from HEAD:
https://git.ti.com/ti-cm3-pm-firmware/amx3-cm3/commits/next
You can place in /lib/firmware and select CONFIG_FW_LOADER_USER_HELPER_FALLBACK or build into kernel.
Also for what it's worth you can have my tested by:
I have tested on am335x-boneblack, am335x-evm, and am335x-evmsk, multiple suspend cycles work with no issue.
Regards,
Dave
Quoted 4 lines
Thanks,
Sekhar
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Quoted 40 lines · Dave Gerlach
Sekhar,
Quoted 31 lines · Sekhar Nori
Quoted 30 lines · Dave Gerlach
Quoted 28 lines · Daniel Mack
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and
omap_hsmmc.All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from
__initcontext, annotations had to be dropped.[nm at ti.com: added error handling for runtime + suspend_late/early_resume]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Daniel Mack <[email protected]>Tested-by Joel Fernandes <[email protected]>Acked-by Joel Fernandes <[email protected]>---
Changes from v8:* Drop the
edma_suspendhook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* UseSET_LATE_SYSTEM_SLEEP_PM_OPSin thedev_pm_opsdeclaration.Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)Quoted 6 lines
Quoted 3 lines
Doesn't seem to be any comments here, any chance this can be picked up? This patch always seems to get missed but will be needed for suspend/resume on both AM335x and AM437x.
Dave, do you have a branch against mainline with suspend working on any of these SoCs using which I can test this patch?
Quoted 7 lines
Yes, here is WIP of next version with all required patches + this one.
https://github.com/dgerlach/linux-pm/tree/pm-ds0-v3.18-rc3-WIPFor suspend to work you need to select:
CONFIG_WKUP_M3_IPC=yCONFIG_WKUP_M3_RPROC=y
I get this:
arch/arm/mach-omap2/pm33xx.c:28:31: fatal error: linux/wkup_m3_ipc.h: No such file or directory
#include <linux/wkup_m3_ipc.h>
^compilation terminated.
make[1]: *** [arch/arm/mach-omap2/pm33xx.o] Error 1
Forgot to commit wkup_m3_ipc.h?
Thanks,
Sekhar
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Sekhar,
Quoted 51 lines · Sekhar Nori
Quoted 40 lines · Dave Gerlach
Sekhar,
Quoted 31 lines · Sekhar Nori
Quoted 30 lines · Dave Gerlach
Quoted 28 lines · Daniel Mack
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and
omap_hsmmc.All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from
__initcontext, annotations had to be dropped.[nm at ti.com: added error handling for runtime + suspend_late/early_resume]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Daniel Mack <[email protected]>Tested-by Joel Fernandes <[email protected]>Acked-by Joel Fernandes <[email protected]>---
Changes from v8:* Drop the
edma_suspendhook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* UseSET_LATE_SYSTEM_SLEEP_PM_OPSin thedev_pm_opsdeclaration.Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)Quoted 6 lines
Quoted 3 lines
Doesn't seem to be any comments here, any chance this can be picked up? This patch always seems to get missed but will be needed for suspend/resume on both AM335x and AM437x.
Dave, do you have a branch against mainline with suspend working on any of these SoCs using which I can test this patch?
Quoted 7 lines
Yes, here is WIP of next version with all required patches + this one.
https://github.com/dgerlach/linux-pm/tree/pm-ds0-v3.18-rc3-WIPFor suspend to work you need to select:
CONFIG_WKUP_M3_IPC=yCONFIG_WKUP_M3_RPROC=yI get this:
Quoted 8 lines
arch/arm/mach-omap2/pm33xx.c:28:31: fatal error:linux/wkup_m3_ipc.h: No such file or directory#include <linux/wkup_m3_ipc.h> ^compilation terminated.
make[1]: *** [arch/arm/mach-omap2/pm33xx.o] Error 1Forgot to commit
wkup_m3_ipc.h?
Ahhh sorry about that, looks like I dropped it during a rebase. Added it in a patch and pushed that on top of the tree from yesterday. Sorry again!.
Regards,
Dave
Quoted 4 lines
Thanks,
Sekhar
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
In reply to Daniel MackQuoted 66 lines · Daniel Mack
This patch makes the edma driver resume correctly after suspend. Tested on an AM33xx platform with cyclic audio streams and
omap_hsmmc.All information can be reconstructed by already known runtime information.
As we now use some functions that were previously only used from
__initcontext, annotations had to be dropped.[nm at ti.com: added error handling for runtime + suspend_late/early_resume]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Daniel Mack <[email protected]>Tested-by Joel Fernandes <[email protected]>Acked-by Joel Fernandes <[email protected]>---
Changes from v8:* Drop the
edma_suspendhook altogether. Even though back then when I wrote the code I was sure disabling the interrupts during suspend is necessary, tests now show it in fact isn't. My test setup still works if that code is omitted.
* UseSET_LATE_SYSTEM_SLEEP_PM_OPSin thedev_pm_opsdeclaration.Thanks to Sekhar for pointing out the above.
arch/arm/common/edma.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-)arch/arm/common/edma.c +5
-2@@ -244,6 +244,8 @@ struct edma {/* list of channels with no even trigger; terminated by "-1" */ const s8 *noevent; +struct edma_soc_info *info; +/* The edma_inuse bit for each PaRAM slot is clear unless the * channel is in use ... by ARM or DSP, for QDMA, or whatever. */ @@ -295,7 +297,7 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no, ~(0x7 << bit), queue_no << bit); } -static void __init assign_priority_to_queue (unsigned ctlr,int queue_no, +static void assign_priority_to_queue (unsigned ctlr,int queue_no,int priority) {int bit = queue_no *4 ;@@ -314,7 +316,7 @@ static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,* included in that particular EDMA variant (Eg : dm646x) * */ -static void __init map_dmach_param (unsigned ctlr) +static void map_dmach_param (unsigned ctlr) {int i;for (i =0 ; i <EDMA_MAX_DMACH ; i++)@@ -1762,15 +1764,69 @@ static int edma_probe(struct platform_device *pdev)edma_write_array2 (j,EDMA_DRAE , i,1 ,0x0 );edma_write_array (j,EDMA_QRAE , i,0x0 ); } + edma_cc[j]->info = info[j]; arch_num_cc++;
arch/arm/common/edma.c static int edma_probe(struct platform_device *pdev) · line 1778
Quoted 10 lines
arch/arm/common/edma.c +5
-0}return 0 ; } +static int edma_pm_resume (struct device *dev) +{ +int i, j, r; + + r =pm_runtime_get_sync (dev);
I think I have asked this before, and I am still not sure why this call to pm_runtime_get_sync() is needed here. From my testing today, this does seem to be a a no-op and this call returns from rpm_resume() because of this check:
else if (dev->power.disable_depth == 1 && dev->power.is_suspended && dev->power.runtime_status == RPM_ACTIVE) retval = 1;
So, AFAICS, the net effect is an increment of dev->power.usage_count (which is already greater than 0) and its subsequent decrement at the end of the function.
After removing this call I did not see any EDMA malfunction as well (can access MMC/SD just fine after suspend/resume cycle).
So, any objections to merging this patch with the attached hunk applied?
Thanks,
Sekhar
---8<---
arch/arm/common/edma.c +1 -9
@@ -1803,13 +1803,7 @@ static int edma_probe(struct platform_device *pdev)static int edma_pm_resume (struct device *dev) { -int i, j, r; - - r =pm_runtime_get_sync (dev); -if (r <0 ) { -dev_err (dev,"%s: get_sync returned %d\n" , __func__, r); -return r; - } +int i, j;for (j =0 ; j < arch_num_cc; j++) {struct edma *cc = edma_cc[j];
@@ -1844,8 +1838,6 @@ static int edma_pm_resume(struct device *dev) } } -pm_runtime_put_sync (dev); -return 0 ; }
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Hi Sekhar,
Quoted 8 lines · Sekhar Nori
I think I have asked this before, and I am still not sure why this call to
pm_runtime_get_sync()is needed here. From my testing today, this does seem to be a a no-op and this call returns fromrpm_resume()because of this check:else if (dev->power.disable_depth == 1 && dev->power.is_suspended && dev->power.runtime_status == RPM_ACTIVE) retval = 1;
Yes. IIRC, it was in fact not needed.
Quoted 9 lines
So, AFAICS, the net effect is an increment of
dev->power.usage_count(which is already greater than 0) and its subsequent decrement at the end of the function.After removing this call I did not see any EDMA malfunction as well (can access MMC/SD just fine after suspend/resume cycle).
So, any objections to merging this patch with the attached hunk applied?
Looks good to me, we can still add it back later if it turns out to be needed.
Thanks,
Daniel
Quoted 33 lines
Thanks,
Sekhar---8<---
arch/arm/common/edma.c +1
-9@@ -1803,13 +1803,7 @@ static int edma_probe(struct platform_device *pdev)static int edma_pm_resume (struct device *dev) { -int i, j, r; - - r =pm_runtime_get_sync (dev); -if (r <0 ) { -dev_err (dev,"%s: get_sync returned %d\n" , __func__, r); -return r; - } +int i, j;for (j =0 ; j < arch_num_cc; j++) {struct edma *cc = edma_cc[j];@@ -1844,8 +1838,6 @@ static int edma_pm_resume(struct device *dev) } } -pm_runtime_put_sync (dev); -return 0 ; }
PATCH v9 1/1 ARM: omap: edma: add suspend resume hook
Quoted 18 lines · Daniel Mack
Hi Sekhar,
Quoted 8 lines · Sekhar Nori
I think I have asked this before, and I am still not sure why this call to
pm_runtime_get_sync()is needed here. From my testing today, this does seem to be a a no-op and this call returns fromrpm_resume()because of this check:else if (dev->power.disable_depth == 1 && dev->power.is_suspended && dev->power.runtime_status == RPM_ACTIVE) retval = 1;Yes. IIRC, it was in fact not needed.
Quoted 4 lines
So, AFAICS, the net effect is an increment of
dev->power.usage_count(which is already greater than 0) and its subsequent decrement at the end of the function.
Quoted 8 lines
Quoted 5 lines
After removing this call I did not see any EDMA malfunction as well (can access MMC/SD just fine after suspend/resume cycle).
So, any objections to merging this patch with the attached hunk applied?
Looks good to me, we can still add it back later if it turns out to be needed.
Okay, thanks for the confirmation.
Regards,
Sekhar