ARM: OMAP2+: AM33XX: Add suspend-resume support
Subsystems (11)
v2 cover ARM: OMAP2+: AM33XX: Add suspend-resume support
Hi,
This is the second version of the patch series for adding suspend-resume support for AM33XX. Based on the feedback received on the previous patch series [1] almost all the patches have undergone a bit a rework.
The 1st two patches depend on the changes for mailbox code migration from arch/arm/*-omap*/ to drivers/mailbox/ [2].
The patch series also depends on recent changes to the OMAP PM framework by Paul Walmsley.
I found it easiest to apply the AM33XX suspend-resume patches on top of Paul's TEST_pwrdm_post_fpwrst_devel_a_3.9 branch + the patches @ [2].
With these dependencies met, the PM code uses the firmware interface and expects the userspace to load the WKUP_M3 binary before the suspend-resume functionality is made available. The binary file (and the source-code for WKUP_M3) can be obtained from the 'next' branch at [3]. The WKUP_M3 binary can either be loaded post bootup via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be included in the kernel image as part of the build process.
DDR3 specific changes have been skipped for now since mainline U-Boot exhibited stability issues on all the DDR3 based AM335x boards that i could lay my hands on.
I have done basic testing along with power measurments on the different power rails on the AM335x EVM. PER domain transition on the BeagleBone fails if the CPSW driver is included in the kernel and is yet to be root caused. Along with this issue more extensive testing on other OMAP platforms is also pending right now.
For more details on the AM335x suspend-resume support please refer to the changelog in the different patches.
Regards,
Vaibhav
[1] http://marc.info/?l=linux-arm-kernel&m=135185970731607&w=4
[2] http://marc.info/?l=linux-omap&m=135583648827089&w=4
[3] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next
Vaibhav Bedia (18):
mailbox: OMAP2+: Add support for AM33XX
mailbox: Add an API for flushing the FIFO
memory: emif: Move EMIF related header file to include/linux/
ARM: OMAP2+: AM33XX: CM: Get rid of unncessary header inclusions
ARM: OMAP2+: AM33XX: CM/PRM: Use __ASSEMBLER__ macros in header files
ARM: OMAP2+: AM33XX: hwmod: Register OCMC RAM hwmod
ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
ARM: OMAP2+: AM33XX: hwmod: Fixup cpgmac0 hwmod entry
ARM: OMAP2+: AM33XX: Update the hardreset API
ARM: OMAP2+: AM33XX: hwmod: Update the WKUP-M3 hwmod with reset
status bit
ARM: DTS: AM33XX: Add nodes for OCMC RAM and WKUP-M3
ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent
device
ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
ARM: OMAP2+: AM33XX: control: Add some control module registers and
APIs
ARM: OMAP2+: AM33XX: Add assembly code for PM operations
ARM: OMAP2+: AM33XX: Basic suspend resume support
ARM: OMAP2+: AM33XX: Select Mailbox when PM is enabled
ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
.../devicetree/bindings/arm/omap/timer.txt | 2 + arch/arm/boot/dts/am33xx.dtsi | 12 + arch/arm/mach-omap2/Kconfig | 4 +- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/board-generic.c | 1 + arch/arm/mach-omap2/cm33xx.h | 10 +- arch/arm/mach-omap2/common.h | 10 + arch/arm/mach-omap2/control.c | 20 + arch/arm/mach-omap2/control.h | 41 ++ arch/arm/mach-omap2/io.c | 7 + arch/arm/mach-omap2/omap_hwmod.c | 5 +- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 50 +- arch/arm/mach-omap2/pm.h | 7 + arch/arm/mach-omap2/pm33xx.c | 469 ++++++++++++++++ arch/arm/mach-omap2/pm33xx.h | 56 ++ arch/arm/mach-omap2/prm33xx.c | 11 +- arch/arm/mach-omap2/prm33xx.h | 5 +- arch/arm/mach-omap2/sleep33xx.S | 584 +++++++++++++++++++ arch/arm/mach-omap2/sram.c | 10 +- arch/arm/mach-omap2/sram.h | 2 + arch/arm/mach-omap2/timer.c | 39 ++- drivers/mailbox/mailbox-omap2.c | 54 ++- drivers/mailbox/mailbox.c | 36 ++ drivers/mailbox/mailbox.h | 3 + drivers/memory/emif.c | 2 +- drivers/memory/emif.h | 589 -------------------- include/linux/mailbox.h | 1 + include/linux/ti_emif.h | 589 ++++++++++++++++++++ 28 files changed, 1989 insertions(+), 632 deletions(-) create mode 100644 arch/arm/mach-omap2/pm33xx.c create mode 100644 arch/arm/mach-omap2/pm33xx.h create mode 100644 arch/arm/mach-omap2/sleep33xx.S delete mode 100644 drivers/memory/emif.h create mode 100644 include/linux/ti_emif.h
RFC v2 1/18 mailbox: OMAP2+: Add support for AM33XX
Mailbox IP on AM33XX is the same as that present in OMAP4. The single instance of Mailbox IP on AM33XX contains 8 sub-modules and facilitates communication between MPU, PRUs and WKUP_M3.
The first mailbox sub-module is assigned for communication between MPU and WKUP-M3.
---v1->v2:
Address the comment on operator usage from Russ Dill
drivers/mailbox/mailbox-omap2.c | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)
drivers/mailbox/mailbox-omap2.c +34 -1
@@ -151,7 +151,7 @@ static void omap2_mbox_disable_irq(struct mailbox *mbox,struct omap_mbox2_priv *p = mbox->priv;u32 bit = (irq ==IRQ_TX ) ? p->notfull_bit : p->newmsg_bit; -if (!cpu_is_omap44xx ()) +if (!cpu_is_omap44xx () && !soc_is_am33xx ()) bit =mbox_read_reg (p->irqdisable) & ~bit;mbox_write_reg (bit, p->irqdisable);
@@ -352,6 +352,32 @@ struct mailbox mbox_2_info = {struct mailbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info,NULL };#endif +#if defined(CONFIG_SOC_AM33XX ) +static struct omap_mbox2_priv omap2_mbox_wkup_m3_priv = { + .tx_fifo = { + .msg =MAILBOX_MESSAGE (0 ), + .fifo_stat =MAILBOX_FIFOSTATUS (0 ), + .msg_stat =MAILBOX_MSGSTATUS (0 ), + }, + .rx_fifo = { + .msg =MAILBOX_MESSAGE (1 ), + .msg_stat =MAILBOX_MSGSTATUS (1 ), + }, + .irqenable =OMAP4_MAILBOX_IRQENABLE (3 ), + .irqstatus =OMAP4_MAILBOX_IRQSTATUS (3 ), + .irqdisable =OMAP4_MAILBOX_IRQENABLE_CLR (3 ), + .notfull_bit =MAILBOX_IRQ_NOTFULL (0 ), + .newmsg_bit =MAILBOX_IRQ_NEWMSG (0 ), +}; + +struct mailbox mbox_wkup_m3_info = { + .name ="wkup_m3" , + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_wkup_m3_priv, +}; +struct mailbox *am33xx_mboxes[] = { &mbox_wkup_m3_info,NULL }; +#endif +static int __devinit omap2_mbox_probe (struct platform_device *pdev) {struct resource *mem;
@@ -386,6 +412,13 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev) list[0 ]->irq = list[1 ]->irq =platform_get_irq (pdev,0 ); }#endif +#if defined(CONFIG_SOC_AM33XX ) + else if (soc_is_am33xx()) { + list = am33xx_mboxes; + + list[0 ]->irq =platform_get_irq (pdev,0 ); + } +#endif else {pr_err ("%s: platform not supported\n" , __func__);return -ENODEV ;
Signature · 1 line
1.7.0.4
Tony Lindgren
maintainerRFC v2 1/18 mailbox: OMAP2+: Add support for AM33XX
Quoted 23 lines · Vaibhav Bedia
Mailbox IP on AM33XX is the same as that present in OMAP4. The single instance of Mailbox IP on AM33XX contains 8 sub-modules and facilitates communication between MPU, PRUs and
WKUP_M3.The first mailbox sub-module is assigned for communication between MPU and WKUP-M3.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Russ Dill <[email protected]>Cc Santosh Shilimkar <[email protected]>---
v1->v2:
Address the comment on operator usage from Russ Dilldrivers/mailbox/mailbox-omap2.c | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)drivers/mailbox/mailbox-omap2.c +0
-0
drivers/mailbox/mailbox-omap2.c static void omap2_mbox_disable_irq(struct mailbox *mbox, · line 157
Quoted 8 lines
drivers/mailbox/mailbox-omap2.c +1
-1@@ -151,7 +151,7 @@ static void omap2_mbox_disable_irq(struct mailbox *mbox,struct omap_mbox2_priv *p = mbox->priv;u32 bit = (irq ==IRQ_TX ) ? p->notfull_bit : p->newmsg_bit; -if (!cpu_is_omap44xx ()) +if (!cpu_is_omap44xx () && !soc_is_am33xx ()) bit =mbox_read_reg (p->irqdisable) & ~bit;mbox_write_reg (bit, p->irqdisable);
The cpu_is/soc_is macros are no longer available to drivers with 8d91a42e (Merge tag 'omap-late-cleanups'...). So you'll have to pass whatever flags the driver needs in platform_data or as device tree properties.
Quoted 4 lines
drivers/mailbox/mailbox-omap2.c +0
-0@@ -386,6 +412,13 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev) list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0); }#endif
drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 424
Quoted 10 lines
drivers/mailbox/mailbox-omap2.c +7
-0+#if defined(CONFIG_SOC_AM33XX ) + else if (soc_is_am33xx()) { + list = am33xx_mboxes; + + list[0 ]->irq =platform_get_irq (pdev,0 ); + } +#endif else {pr_err ("%s: platform not supported\n" , __func__);return -ENODEV ;
Here too.
Tony
RFC v2 1/18 mailbox: OMAP2+: Add support for AM33XX
Hi Tony,
On Tue, Jan 01, 2013 at 23:55:06, Tony Lindgren wrote:
[...]
Quoted 8 lines
Quoted 2 lines
mbox_write_reg(bit, p->irqdisable);The cpu_is/soc_is macros are no longer available to drivers with
8d91a42e(Merge tag 'omap-late-cleanups'...). So you'll have to pass whatever flags the driver needs inplatform_dataor as device tree properties.
Thanks for the heads-up. Will rework this patch once the mailbox driver migration is finalized.
Regards,
Vaibhav
RFC v2 1/18 mailbox: OMAP2+: Add support for AM33XX
In reply to Vaibhav BediaQuoted 5 lines · Vaibhav Bedia
Mailbox IP on AM33XX is the same as that present in OMAP4. The single instance of Mailbox IP on AM33XX contains 8 sub-modules and facilitates communication between MPU, PRUs and
WKUP_M3.
PRUS?
Quoted 60 lines
The first mailbox sub-module is assigned for communication between MPU and WKUP-M3.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Russ Dill <[email protected]>Cc Santosh Shilimkar <[email protected]>---
v1->v2:
Address the comment on operator usage from Russ Dilldrivers/mailbox/mailbox-omap2.c | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)drivers/mailbox/mailbox-omap2.c +27
-1@@ -151,7 +151,7 @@ static void omap2_mbox_disable_irq(struct mailbox *mbox,struct omap_mbox2_priv *p = mbox->priv;u32 bit = (irq ==IRQ_TX ) ? p->notfull_bit : p->newmsg_bit; -if (!cpu_is_omap44xx ()) +if (!cpu_is_omap44xx () && !soc_is_am33xx ()) bit =mbox_read_reg (p->irqdisable) & ~bit;mbox_write_reg (bit, p->irqdisable);@@ -352,6 +352,32 @@ struct mailbox mbox_2_info = {struct mailbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info,NULL };#endif +#if defined(CONFIG_SOC_AM33XX ) +static struct omap_mbox2_priv omap2_mbox_wkup_m3_priv = { + .tx_fifo = { + .msg =MAILBOX_MESSAGE (0 ), + .fifo_stat =MAILBOX_FIFOSTATUS (0 ), + .msg_stat =MAILBOX_MSGSTATUS (0 ), + }, + .rx_fifo = { + .msg =MAILBOX_MESSAGE (1 ), + .msg_stat =MAILBOX_MSGSTATUS (1 ), + }, + .irqenable =OMAP4_MAILBOX_IRQENABLE (3 ), + .irqstatus =OMAP4_MAILBOX_IRQSTATUS (3 ), + .irqdisable =OMAP4_MAILBOX_IRQENABLE_CLR (3 ), + .notfull_bit =MAILBOX_IRQ_NOTFULL (0 ), + .newmsg_bit =MAILBOX_IRQ_NEWMSG (0 ), +}; + +struct mailbox mbox_wkup_m3_info = { + .name ="wkup_m3" , + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_wkup_m3_priv, +}; +struct mailbox *am33xx_mboxes[] = { &mbox_wkup_m3_info,NULL }; +#endif +static int __devinit omap2_mbox_probe (struct platform_device *pdev) {struct resource *mem;
drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 415
Quoted 4 lines
drivers/mailbox/mailbox-omap2.c +1
-0@@ -386,6 +412,13 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev) list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0); }#endif +#if defined(CONFIG_SOC_AM33XX )
ifdef in middle of the code. I know you are just
following what is already there.
drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 418
Quoted 3 lines
drivers/mailbox/mailbox-omap2.c +3
-0+else if (soc_is_am33xx ()) { + list = am33xx_mboxes; +
UN-necessary extra line here.
drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 421
Quoted 3 lines
drivers/mailbox/mailbox-omap2.c +3
-0+ list[0]->irq = platform_get_irq(pdev, 0); + } +#endif
Hopefully mailbox clean-up will kill that #ifdeffery. Apart from those comments, patch looks fine to me.
Regards
Santosh
RFC v2 1/18 mailbox: OMAP2+: Add support for AM33XX
Quoted 7 lines · Santosh
Quoted 5 lines · Vaibhav Bedia
Mailbox IP on AM33XX is the same as that present in OMAP4. The single instance of Mailbox IP on AM33XX contains 8 sub-modules and facilitates communication between MPU, PRUs and
WKUP_M3.PRUS?
Programmable Real Time Units. Will clarify in next version
Quoted 67 lines
Quoted 61 lines
The first mailbox sub-module is assigned for communication between MPU and WKUP-M3.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Russ Dill <[email protected]>Cc Santosh Shilimkar <[email protected]>---
v1->v2:
Address the comment on operator usage from Russ Dilldrivers/mailbox/mailbox-omap2.c | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-)drivers/mailbox/mailbox-omap2.c +27
-1@@ -151,7 +151,7 @@ static void omap2_mbox_disable_irq(struct mailbox *mbox,struct omap_mbox2_priv *p = mbox->priv;u32 bit = (irq ==IRQ_TX ) ? p->notfull_bit : p->newmsg_bit; -if (!cpu_is_omap44xx ()) +if (!cpu_is_omap44xx () && !soc_is_am33xx ()) bit =mbox_read_reg (p->irqdisable) & ~bit;mbox_write_reg (bit, p->irqdisable);@@ -352,6 +352,32 @@ struct mailbox mbox_2_info = {struct mailbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info,NULL };#endif +#if defined(CONFIG_SOC_AM33XX ) +static struct omap_mbox2_priv omap2_mbox_wkup_m3_priv = { + .tx_fifo = { + .msg =MAILBOX_MESSAGE (0 ), + .fifo_stat =MAILBOX_FIFOSTATUS (0 ), + .msg_stat =MAILBOX_MSGSTATUS (0 ), + }, + .rx_fifo = { + .msg =MAILBOX_MESSAGE (1 ), + .msg_stat =MAILBOX_MSGSTATUS (1 ), + }, + .irqenable =OMAP4_MAILBOX_IRQENABLE (3 ), + .irqstatus =OMAP4_MAILBOX_IRQSTATUS (3 ), + .irqdisable =OMAP4_MAILBOX_IRQENABLE_CLR (3 ), + .notfull_bit =MAILBOX_IRQ_NOTFULL (0 ), + .newmsg_bit =MAILBOX_IRQ_NEWMSG (0 ), +}; + +struct mailbox mbox_wkup_m3_info = { + .name ="wkup_m3" , + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_wkup_m3_priv, +}; +struct mailbox *am33xx_mboxes[] = { &mbox_wkup_m3_info,NULL }; +#endif +static int __devinit omap2_mbox_probe (struct platform_device *pdev) {struct resource *mem;drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 415
Quoted 4 lines
drivers/mailbox/mailbox-omap2.c +1
-0@@ -386,6 +412,13 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev) list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0); }#endif +#if defined(CONFIG_SOC_AM33XX )ifdef in middle of the code. I know you are just
following what is already there.
Quoted 4 lines
drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 418
Quoted 3 lines
drivers/mailbox/mailbox-omap2.c +3
-0+else if (soc_is_am33xx ()) { + list = am33xx_mboxes; +UN-necessary extra line here.
Will remove
Quoted 7 lines
drivers/mailbox/mailbox-omap2.c static int __devinit omap2_mbox_probe(struct platform_device *pdev) · line 421
Quoted 3 lines
drivers/mailbox/mailbox-omap2.c +3
-0+ list[0]->irq = platform_get_irq(pdev, 0); + } +#endif Hopefully mailbox clean-up will kill that #ifdeffery. Apart from those comments, patch looks fine to me.
Thanks,
Vaibhav
RFC v2 2/18 mailbox: Add an API for flushing the FIFO
In reply to Vaibhav BediaOn AM33XX, the mailbox module between the MPU and the WKUP-M3 co-processor facilitates a one-way communication. MPU uses the assigned mailbox sub-module to issue the interrupt to the WKUP-M3 co-processor which then goes and reads the the IPC data from registers in the control module.
WKUP-M3 is in the L4_WKUP and does not have any access to the mailbox module. Due to this limitation, the MPU is completely responsible for FIFO maintenance and interrupt generation. MPU needs to ensure that the FIFO does not overflow by reading back the assigned mailbox sub-module.
This patch adds an API in the mailbox code which the MPU can use to empty the FIFO by issuing a readback command.
---
Note: This patch which will be slightly reworked once the mailbox driver changes are finalized.
drivers/mailbox/mailbox-omap2.c | 19 +++++++++++++++++++ drivers/mailbox/mailbox.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/mailbox/mailbox.h | 3 +++ include/linux/mailbox.h | 1 + 4 files changed, 59 insertions(+), 0 deletions(-)
drivers/mailbox/mailbox-omap2.c +19 -0
@@ -125,6 +125,23 @@ static int omap2_mbox_fifo_full(struct mailbox *mbox)return mbox_read_reg (fifo->fifo_stat); } +static int omap2_mbox_fifo_needs_flush (struct mailbox *mbox) +{ +struct omap_mbox2_priv *p = mbox->priv; +struct omap_mbox2_fifo *fifo = &p->tx_fifo; + +return mbox_read_reg (fifo->msg_stat); +} + +static void omap2_mbox_fifo_readback (struct mailbox *mbox, +struct mailbox_msg *msg) +{ +struct omap_mbox2_priv *p = mbox->priv; +struct omap_mbox2_fifo *fifo = &p->tx_fifo; + + msg->header =mbox_read_reg (fifo->msg); +} +static int ompa2_mbox_poll_for_space (struct mailbox *mbox) {if (omap2_mbox_fifo_full (mbox))
@@ -221,6 +238,8 @@ static struct mailbox_ops omap2_mbox_ops = { .read = omap2_mbox_fifo_read, .write = omap2_mbox_fifo_write, .empty = omap2_mbox_fifo_empty, + .fifo_needs_flush = omap2_mbox_fifo_needs_flush, + .fifo_readback = omap2_mbox_fifo_readback, .poll_for_space = ompa2_mbox_poll_for_space, .enable_irq = omap2_mbox_enable_irq, .disable_irq = omap2_mbox_disable_irq,
drivers/mailbox/mailbox.c +36 -0
@@ -57,6 +57,15 @@ static inline int mbox_empty(struct mailbox *mbox) {return mbox->ops->empty (mbox); } +static inline int mbox_fifo_needs_flush (struct mailbox *mbox) +{ +return mbox->ops->fifo_needs_flush (mbox); +} +static inline void mbox_fifo_readback (struct mailbox *mbox, +struct mailbox_msg *msg) +{ + mbox->ops->fifo_readback (mbox, msg); +}/* Mailbox IRQ handle functions */ static inline void ack_mbox_irq (struct mailbox *mbox,mailbox_irq_t irq)
@@ -110,6 +119,33 @@ out: }EXPORT_SYMBOL (mailbox_msg_send); +/* +* Flush the Rx FIFO by reading back the messages +* Since the normal expectation is that the Rx will do the +* reading, add a debug message to indicate if we really flush +* +* Returns the no. of messages read back +*/ +int mailbox_rx_flush (struct mailbox *mbox) +{ +int ret =0 ; +struct mailbox_msg readback_msg; + +while (mbox_fifo_needs_flush (mbox)) { +mbox_fifo_readback (mbox, &readback_msg); + ret++; + } + +if (ret) { +/* no more messages in the fifo. clear IRQ source. */ +ack_mbox_irq (mbox,IRQ_RX ); +pr_debug ("Flushed %s Rx FIFO by reading back\n" , mbox->name); + } + +return ret; +} +EXPORT_SYMBOL (mailbox_rx_flush); +#define TRANSFER_TIMEOUT 30000/* Becomes ~3s timeout */ static struct mailbox_msg no_irq_msg_res;
drivers/mailbox/mailbox.h +3 -0
@@ -24,6 +24,9 @@ struct mailbox_ops {int (*write)(struct mailbox *mbox,struct mailbox_msg *msg);int (*empty)(struct mailbox *mbox);int (*poll_for_space)(struct mailbox *mbox); +int (*fifo_needs_flush)(struct mailbox *mbox); +void (*fifo_readback)(struct mailbox *mbox, +struct mailbox_msg *msg);/* irq */ void (*enable_irq)(struct mailbox *mbox,mailbox_irq_t irq);
include/linux/mailbox.h +1 -0
@@ -22,6 +22,7 @@ struct mailbox_msg {#define MAILBOX_FILL_HEADER_MSG (_msg, _header) \ MAILBOX_FILL_MSG(_msg, _header, NULL, 0); +int mailbox_rx_flush (struct mailbox *);int mailbox_msg_send (struct mailbox *,struct mailbox_msg *msg);struct mailbox_msg *mailbox_msg_send_receive_no_irq (struct mailbox *,struct mailbox_msg *msg);
Signature · 1 line
1.7.0.4
RFC v2 2/18 mailbox: Add an API for flushing the FIFO
Quoted 13 lines · Vaibhav Bedia
On AM33XX, the mailbox module between the MPU and the WKUP-M3 co-processor facilitates a one-way communication. MPU uses the assigned mailbox sub-module to issue the interrupt to the WKUP-M3 co-processor which then goes and reads the the IPC data from registers in the control module.
WKUP-M3 is in the
L4_WKUPand does not have any access to the mailbox module. Due to this limitation, the MPU is completely responsible for FIFO maintenance and interrupt generation. MPU needs to ensure that the FIFO does not overflow by reading back the assigned mailbox sub-module.
Quoted 9 lines
This patch adds an API in the mailbox code which the MPU can use to empty the FIFO by issuing a readback command.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>---
Note: This patch which will be slightly reworked once the mailbox driver changes are finalized.
Can you expand a bit please ?
Quoted 64 lines
drivers/mailbox/mailbox-omap2.c | 19 +++++++++++++++++++ drivers/mailbox/mailbox.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/mailbox/mailbox.h | 3 +++ include/linux/mailbox.h | 1 + 4 files changed, 59 insertions(+), 0 deletions(-)drivers/mailbox/mailbox-omap2.c +19
-0@@ -125,6 +125,23 @@ static int omap2_mbox_fifo_full(struct mailbox *mbox)return mbox_read_reg (fifo->fifo_stat); } +static int omap2_mbox_fifo_needs_flush (struct mailbox *mbox) +{ +struct omap_mbox2_priv *p = mbox->priv; +struct omap_mbox2_fifo *fifo = &p->tx_fifo; + +return mbox_read_reg (fifo->msg_stat); +} + +static void omap2_mbox_fifo_readback (struct mailbox *mbox, +struct mailbox_msg *msg) +{ +struct omap_mbox2_priv *p = mbox->priv; +struct omap_mbox2_fifo *fifo = &p->tx_fifo; + + msg->header =mbox_read_reg (fifo->msg); +} +static int ompa2_mbox_poll_for_space (struct mailbox *mbox) {if (omap2_mbox_fifo_full (mbox))@@ -221,6 +238,8 @@ static struct mailbox_ops omap2_mbox_ops = { .read = omap2_mbox_fifo_read, .write = omap2_mbox_fifo_write, .empty = omap2_mbox_fifo_empty, + .fifo_needs_flush = omap2_mbox_fifo_needs_flush, + .fifo_readback = omap2_mbox_fifo_readback, .poll_for_space = ompa2_mbox_poll_for_space, .enable_irq = omap2_mbox_enable_irq, .disable_irq = omap2_mbox_disable_irq,drivers/mailbox/mailbox.c +9
-0@@ -57,6 +57,15 @@ static inline int mbox_empty(struct mailbox *mbox) {return mbox->ops->empty (mbox); } +static inline int mbox_fifo_needs_flush (struct mailbox *mbox) +{ +return mbox->ops->fifo_needs_flush (mbox); +} +static inline void mbox_fifo_readback (struct mailbox *mbox, +struct mailbox_msg *msg) +{ + mbox->ops->fifo_readback (mbox, msg); +}/* Mailbox IRQ handle functions */ static inline void ack_mbox_irq (struct mailbox *mbox,mailbox_irq_t irq)
drivers/mailbox/mailbox.c out: · line 122
Quoted 4 lines
drivers/mailbox/mailbox.c +1
-0@@ -110,6 +119,33 @@ out: }EXPORT_SYMBOL (mailbox_msg_send); +/*
s/*/**
drivers/mailbox/mailbox.c out: · line 128
Quoted 6 lines
drivers/mailbox/mailbox.c +6
-0+* Flush the Rx FIFO by reading back the messages +* Since the normal expectation is that the Rx will do the +* reading, add a debug message to indicate if we really flush +* +* Returns the no. of messages read back +*/
Just look at the kernel doc style for above
Rest looks fine.
Regards
Santosh
RFC v2 2/18 mailbox: Add an API for flushing the FIFO
Quoted 17 lines · Santosh
Quoted 16 lines · Vaibhav Bedia
On AM33XX, the mailbox module between the MPU and the WKUP-M3 co-processor facilitates a one-way communication. MPU uses the assigned mailbox sub-module to issue the interrupt to the WKUP-M3 co-processor which then goes and reads the the IPC data from registers in the control module.
WKUP-M3 is in the
L4_WKUPand does not have any access to the mailbox module. Due to this limitation, the MPU is completely responsible for FIFO maintenance and interrupt generation. MPU needs to ensure that the FIFO does not overflow by reading back the assigned mailbox sub-module.This patch adds an API in the mailbox code which the MPU can use to empty the FIFO by issuing a readback command.
Quoted 7 lines
Quoted 6 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>---
Note: This patch which will be slightly reworked once the mailbox driver changes are finalized.Can you expand a bit please ?
There could be some changes in the structure names.
Quoted 62 lines
Quoted 62 lines
drivers/mailbox/mailbox-omap2.c | 19 +++++++++++++++++++ drivers/mailbox/mailbox.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/mailbox/mailbox.h | 3 +++ include/linux/mailbox.h | 1 + 4 files changed, 59 insertions(+), 0 deletions(-)drivers/mailbox/mailbox-omap2.c +19
-0@@ -125,6 +125,23 @@ static int omap2_mbox_fifo_full(struct mailbox *mbox)return mbox_read_reg (fifo->fifo_stat); } +static int omap2_mbox_fifo_needs_flush (struct mailbox *mbox) +{ +struct omap_mbox2_priv *p = mbox->priv; +struct omap_mbox2_fifo *fifo = &p->tx_fifo; + +return mbox_read_reg (fifo->msg_stat); +} + +static void omap2_mbox_fifo_readback (struct mailbox *mbox, +struct mailbox_msg *msg) +{ +struct omap_mbox2_priv *p = mbox->priv; +struct omap_mbox2_fifo *fifo = &p->tx_fifo; + + msg->header =mbox_read_reg (fifo->msg); +} +static int ompa2_mbox_poll_for_space (struct mailbox *mbox) {if (omap2_mbox_fifo_full (mbox))@@ -221,6 +238,8 @@ static struct mailbox_ops omap2_mbox_ops = { .read = omap2_mbox_fifo_read, .write = omap2_mbox_fifo_write, .empty = omap2_mbox_fifo_empty, + .fifo_needs_flush = omap2_mbox_fifo_needs_flush, + .fifo_readback = omap2_mbox_fifo_readback, .poll_for_space = ompa2_mbox_poll_for_space, .enable_irq = omap2_mbox_enable_irq, .disable_irq = omap2_mbox_disable_irq,drivers/mailbox/mailbox.c +9
-0@@ -57,6 +57,15 @@ static inline int mbox_empty(struct mailbox *mbox) {return mbox->ops->empty (mbox); } +static inline int mbox_fifo_needs_flush (struct mailbox *mbox) +{ +return mbox->ops->fifo_needs_flush (mbox); +} +static inline void mbox_fifo_readback (struct mailbox *mbox, +struct mailbox_msg *msg) +{ + mbox->ops->fifo_readback (mbox, msg); +}
Quoted 8 lines
drivers/mailbox/mailbox.c out: · line 122
Quoted 7 lines
drivers/mailbox/mailbox.c +1
-0/* Mailbox IRQ handle functions */ static inline void ack_mbox_irq (struct mailbox *mbox,mailbox_irq_t irq)@@ -110,6 +119,33 @@ out: }EXPORT_SYMBOL (mailbox_msg_send); +/* s/*/**
Will do.
Quoted 10 lines
drivers/mailbox/mailbox.c out: · line 128
Quoted 6 lines
drivers/mailbox/mailbox.c +6
-0+* Flush the Rx FIFO by reading back the messages +* Since the normal expectation is that the Rx will do the +* reading, add a debug message to indicate if we really flush +* +* Returns the no. of messages read back +*/ Just look at the kernel doc style for above
Rest looks fine.
Ok.
Thanks,
Vaibhav
RFC v2 3/18 memory: emif: Move EMIF related header file to include/linux/
In reply to Vaibhav BediaOMAP4 and AM33XX share the same EMIF controller IP. Although there are significant differences in the IP integration due to which AM33XX can't reuse the EMIF driver DVFS similar to OMAP4, it can definitely benefit by reusing the EMIF related macros defined in drivers/memory/emif.h.
In the current OMAP PM framework the PM code resides under arch/arm/mach-omap2/. To enable reuse of the register defines move the emif header file to include/linux so that both the EMIF driver and the AM33XX PM code can benefit.
---v1->v2:
This is a new patch in the series to enable code reuse between the EMIF driver and AM33XX PM code
drivers/memory/emif.c | 2 +- drivers/memory/emif.h | 589 ----------------------------------------------- include/linux/ti_emif.h | 589 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 590 insertions(+), 590 deletions(-) delete mode 100644 drivers/memory/emif.h create mode 100644 include/linux/ti_emif.h
drivers/memory/emif.c +1 -1
@@ -24,8 +24,8 @@#include <linux/module.h> #include <linux/list.h> #include <linux/spinlock.h> +#include <linux/ti_emif.h> #include <memory/jedec_ddr.h> -#include "emif.h" #include "of_memory.h" /**
drivers/memory/emif.h deleted +0 -589
589 lines not on this page · raw message
include/linux/ti_emif.h new file +589 -0
589 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC v2 3/18 memory: emif: Move EMIF related header file to include/linux/
Quoted 15 lines · Vaibhav Bedia
OMAP4 and AM33XX share the same EMIF controller IP. Although there are significant differences in the IP integration due to which AM33XX can't reuse the EMIF driver DVFS similar to OMAP4, it can definitely benefit by reusing the EMIF related macros defined in
drivers/memory/emif.h.In the current OMAP PM framework the PM code resides under
arch/arm/mach-omap2/. To enable reuse of the register defines move the emif header file toinclude/linuxso that both the EMIF driver and the AM33XX PM code can benefit.Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Aneesh V <[email protected]>
Quoted 8 lines
---
v1->v2:
This is a new patch in the series to enable code reuse between the EMIF driver and AM33XX PM codedrivers/memory/emif.c | 2 +- drivers/memory/emif.h | 589 ----------------------------------------------- include/linux/ti_emif.h | 589 +++++++++++++++++++++++++++++++++++++++++++++++
You are just moving the file. So "git mv file1 flie2; and the git format-patch -C" on committed patch should just generate few lines of patch.
Quoted 9 lines
include/linux/ti_emif.h new file +9
-0+/* DDR_PHY_CTRL_1 - EMIF4D5 */ +#define DLL_HALF_DELAY_SHIFT_4D5 21 +#define DLL_HALF_DELAY_MASK_4D5 (1 << 21) +#define READ_LATENCY_SHIFT_4D5 0 +#define READ_LATENCY_MASK_4D5 (0x1f << 0) + +/* DDR_PHY_CTRL_1_SHDW */ +#define DDR_PHY_CTRL_1_SHDW_SHIFT 5 +#define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5)
include/linux/ti_emif.h line 564
Quoted 10 lines
include/linux/ti_emif.h new file +10
-0+#define READ_LATENCY_SHDW_SHIFT 0 +#define READ_LATENCY_SHDW_MASK (0x1f << 0) + +#ifndef __ASSEMBLY__ +/* +* Structure containing shadow of important registers in EMIF +* The calculation function fills in this structure to be later used for +* initialisation and DVFS +*/ +struct emif_regs {
Are you using above struct. If not we can leave it in same place and just move the register defines.
Regards
santosh
RFC v2 3/18 memory: emif: Move EMIF related header file to include/linux/
On Tue, Jan 08, 2013 at 19:34:41, Shilimkar, Santosh wrote:
[...]
Quoted 8 lines
Quoted 4 lines
drivers/memory/emif.c | 2 +- drivers/memory/emif.h | 589 ----------------------------------------------- include/linux/ti_emif.h | 589 +++++++++++++++++++++++++++++++++++++++++++++++You are just moving the file. So "git mv file1 flie2; and the git format-patch -C"
on committed patch should just generate few lines of patch.
Ok. Didn't know about this.
Quoted 13 lines
Quoted 13 lines
include/linux/ti_emif.h new file +13
-0+/* DDR_PHY_CTRL_1 - EMIF4D5 */ +#define DLL_HALF_DELAY_SHIFT_4D5 21 +#define DLL_HALF_DELAY_MASK_4D5 (1 << 21) +#define READ_LATENCY_SHIFT_4D5 0 +#define READ_LATENCY_MASK_4D5 (0x1f << 0) + +/* DDR_PHY_CTRL_1_SHDW */ +#define DDR_PHY_CTRL_1_SHDW_SHIFT 5 +#define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5) +#define READ_LATENCY_SHDW_SHIFT 0 +#define READ_LATENCY_SHDW_MASK (0x1f << 0) + +#ifndef __ASSEMBLY__
Quoted 9 lines
include/linux/ti_emif.h line 564
Quoted 6 lines
include/linux/ti_emif.h new file +6
-0+/* +* Structure containing shadow of important registers in EMIF +* The calculation function fills in this structure to be later used for +* initialisation and DVFS +*/ +struct emif_regs {Are you using above struct. If not we can leave it in same place and just move the register defines.
No, the struct is not used. I'll leave it here in the next version.
Regards,
Vaibhav
RFC v2 4/18 ARM: OMAP2+: AM33XX: CM: Get rid of unncessary header inclusions
In reply to Vaibhav BediaSome of the included header files are not needed so remove them.
---v1->v2:
This is a new patch in the series based on Santosh's feedback on splitting the changes
arch/arm/mach-omap2/cm33xx.h | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
arch/arm/mach-omap2/cm33xx.h +1 -6
@@ -17,16 +17,11 @@#ifndef __ARCH_ARM_MACH_OMAP2_CM_33XX_H#define __ARCH_ARM_MACH_OMAP2_CM_33XX_H -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/io.h> -#include "common.h" #include "cm.h" #include "cm-regbits-33xx.h" -#include "cm33xx.h" +#include "iomap.h" /* CM base address */ #define AM33XX_CM_BASE 0x44e00000
Signature · 1 line
1.7.0.4
RFC v2 4/18 ARM: OMAP2+: AM33XX: CM: Get rid of unncessary header inclusions
Quoted 10 lines · Vaibhav Bedia
Some of the included header files are not needed so remove them.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
RFC v2 5/18 ARM: OMAP2+: AM33XX: CM/PRM: Use __ASSEMBLER__ macros in header files
In reply to Vaibhav BediaThis is necessary to ensure that macros declared here can be reused from assembly files.
---v1->v2:
Split out the header file changes in a separate patch based on the feedback from Santosh
arch/arm/mach-omap2/cm33xx.h | 3 +++ arch/arm/mach-omap2/prm33xx.h | 3 +++ 2 files changed, 6 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/cm33xx.h +3 -0
@@ -376,6 +376,7 @@#define AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_CEFUSE_MOD, 0x0020) +#ifndef __ASSEMBLER__extern bool am33xx_cm_is_clkdm_in_hwsup (s16 inst,u16 cdoffs);extern void am33xx_cm_clkdm_enable_hwsup (s16 inst,u16 cdoffs);extern void am33xx_cm_clkdm_disable_hwsup (s16 inst,u16 cdoffs);
@@ -412,4 +413,6 @@ static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, }#endif +#endif /* ASSEMBLER */ +#endif
arch/arm/mach-omap2/prm33xx.h +3 -0
@@ -117,6 +117,7 @@#define AM33XX_PM_CEFUSE_PWRSTST_OFFSET 0x0004#define AM33XX_PM_CEFUSE_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004) +#ifndef __ASSEMBLER__extern u32 am33xx_prm_read_reg (s16 inst,u16 idx);extern void am33xx_prm_write_reg (u32 val,s16 inst,u16 idx);extern u32 am33xx_prm_rmw_reg_bits (u32 mask,u32 bits,s16 inst,s16 idx);
@@ -126,4 +127,6 @@ extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst,extern int am33xx_prm_assert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs);extern int am33xx_prm_deassert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs,u16 rstst_offs); +#endif /* ASSEMBLER */ +#endif
Signature · 1 line
1.7.0.4
RFC v2 5/18 ARM: OMAP2+: AM33XX: CM/PRM: Use __ASSEMBLER__ macros in header files
Quoted 31 lines · Vaibhav Bedia
This is necessary to ensure that macros declared here can be reused from assembly files.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Paul Walmsley <[email protected]>Cc Benoit Cousson <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
v1->v2:
Split out the header file changes in a separate patch based on the feedback from Santosharch/arm/mach-omap2/cm33xx.h | 3 +++ arch/arm/mach-omap2/prm33xx.h | 3 +++ 2 files changed, 6 insertions(+), 0 deletions(-)arch/arm/mach-omap2/cm33xx.h +1
-0@@ -376,6 +376,7 @@#define AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL AM33XX_CM_REGADDR(AM33XX_CM_CEFUSE_MOD, 0x0020) +#ifndef __ASSEMBLER__extern bool am33xx_cm_is_clkdm_in_hwsup (s16 inst,u16 cdoffs);extern void am33xx_cm_clkdm_enable_hwsup (s16 inst,u16 cdoffs);extern void am33xx_cm_clkdm_disable_hwsup (s16 inst,u16 cdoffs);
arch/arm/mach-omap2/cm33xx.h static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, · line 417
Quoted 5 lines
arch/arm/mach-omap2/cm33xx.h +2
-0@@ -412,4 +413,6 @@ static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, }#endif +#endif /* ASSEMBLER */ +
Drop that extra line.
Quoted 14 lines
arch/arm/mach-omap2/cm33xx.h +0
-0#endif arch/arm/mach-omap2/prm33xx.h +1
-0@@ -117,6 +117,7 @@#define AM33XX_PM_CEFUSE_PWRSTST_OFFSET 0x0004#define AM33XX_PM_CEFUSE_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004) +#ifndef __ASSEMBLER__extern u32 am33xx_prm_read_reg (s16 inst,u16 idx);extern void am33xx_prm_write_reg (u32 val,s16 inst,u16 idx);extern u32 am33xx_prm_rmw_reg_bits (u32 mask,u32 bits,s16 inst,s16 idx);
arch/arm/mach-omap2/prm33xx.h extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, · line 131
Quoted 5 lines
arch/arm/mach-omap2/prm33xx.h +2
-0@@ -126,4 +127,6 @@ extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst,extern int am33xx_prm_assert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs);extern int am33xx_prm_deassert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs,u16 rstst_offs); +#endif /* ASSEMBLER */ +
ditto
Otherwise looks fine.
RFC v2 5/18 ARM: OMAP2+: AM33XX: CM/PRM: Use __ASSEMBLER__ macros in header files
On Tue, Jan 08, 2013 at 20:31:44, Shilimkar, Santosh wrote:
[...]
Quoted 3 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+#endif /* ASSEMBLER */ +Drop that extra line.
Ok.
Quoted 9 lines
Quoted 9 lines
#endifarch/arm/mach-omap2/prm33xx.h +0
-0@@ -117,6 +117,7 @@#define AM33XX_PM_CEFUSE_PWRSTST_OFFSET 0x0004#define AM33XX_PM_CEFUSE_PWRSTST AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004)
Quoted 12 lines
arch/arm/mach-omap2/prm33xx.h extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, · line 131
Quoted 10 lines
arch/arm/mach-omap2/prm33xx.h +3
-0+#ifndef __ASSEMBLER__extern u32 am33xx_prm_read_reg (s16 inst,u16 idx);extern void am33xx_prm_write_reg (u32 val,s16 inst,u16 idx);extern u32 am33xx_prm_rmw_reg_bits (u32 mask,u32 bits,s16 inst,s16 idx);@@ -126,4 +127,6 @@ extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst,extern int am33xx_prm_assert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs);extern int am33xx_prm_deassert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs,u16 rstst_offs); +#endif /* ASSEMBLER */ +ditto
Ok.
Quoted 3 lines
Otherwise looks fine.
Thanks,
Vaibhav
RFC v2 6/18 ARM: OMAP2+: AM33XX: hwmod: Register OCMC RAM hwmod
In reply to Vaibhav BediaOCMC RAM lies in the PER power domain and this memory support retention.
---v1->v2:
Move out the OCMC hwmod code from #if 0 block based on Vaibhav Hiremath's comment
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 47 ++++++++++++++++------------ 1 files changed, 27 insertions(+), 20 deletions(-)
arch/arm/mach-omap2/omap_hwmod_33xx_data.c +27 -20
@@ -414,7 +414,6 @@ static struct omap_hwmod am33xx_adc_tsc_hwmod = {* - cEFUSE (doesn't fall under any ocp_if) * - clkdiv32k * - debugss -* - ocmc ram * - ocp watch point * - aes0 * - sha0
@@ -481,25 +480,6 @@ static struct omap_hwmod am33xx_debugss_hwmod = { }, }; -/* ocmcram */ -static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = { - .name ="ocmcram" , -}; - -static struct omap_hwmod am33xx_ocmcram_hwmod = { - .name ="ocmcram" , - .class = &am33xx_ocmcram_hwmod_class, - .clkdm_name ="l3_clkdm" , - .flags = (HWMOD_INIT_NO_IDLE |HWMOD_INIT_NO_RESET ), - .main_clk ="l3_gclk" , - .prcm = { - .omap4 = { - .clkctrl_offs =AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET , - .modulemode =MODULEMODE_SWCTRL , - }, - }, -}; -/* ocpwp */ static struct omap_hwmod_class am33xx_ocpwp_hwmod_class = { .name ="ocpwp" ,
@@ -570,6 +550,25 @@ static struct omap_hwmod am33xx_sha0_hwmod = {#endif +/* ocmcram */ +static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = { + .name ="ocmcram" , +}; + +static struct omap_hwmod am33xx_ocmcram_hwmod = { + .name ="ocmcram" , + .class = &am33xx_ocmcram_hwmod_class, + .clkdm_name ="l3_clkdm" , + .flags = (HWMOD_INIT_NO_IDLE |HWMOD_INIT_NO_RESET ), + .main_clk ="l3_gclk" , + .prcm = { + .omap4 = { + .clkctrl_offs =AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET , + .modulemode =MODULEMODE_SWCTRL , + }, + }, +}; +/* 'smartreflex' class */ static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = { .name ="smartreflex" ,
@@ -3328,6 +3327,13 @@ static struct omap_hwmod_ocp_if am33xx_l3_s__usbss = { .flags = OCPIF_SWSUP_IDLE, }; +/* l3 main -> ocmc */ +static struct omap_hwmod_ocp_if am33xx_l3_main__ocmc = { + .master = &am33xx_l3_main_hwmod, + .slave = &am33xx_ocmcram_hwmod, + .user =OCP_USER_MPU |OCP_USER_SDMA , +}; +static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[]__initdata = { &am33xx_l4_fw__emif_fw, &am33xx_l3_main__emif,
@@ -3398,6 +3404,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l3_main__tptc0, &am33xx_l3_main__tptc1, &am33xx_l3_main__tptc2, + &am33xx_l3_main__ocmc, &am33xx_l3_s__usbss, &am33xx_l4_hs__cpgmac0, &am33xx_cpgmac0__mdio,
Signature · 1 line
1.7.0.4
RFC v2 6/18 ARM: OMAP2+: AM33XX: hwmod: Register OCMC RAM hwmod
Quoted 10 lines · Vaibhav Bedia
OCMC RAM lies in the PER power domain and this memory support retention.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Looks fine to me.
RFC v2 7/18 ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
In reply to Vaibhav BediaTPTC0 needs to be idled and put to standby under SW control. Add the appropriate flags in the TPTC0 hwmod entry.
---v1->v2:
No change
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_33xx_data.c +1 -0
@@ -1823,6 +1823,7 @@ static struct omap_hwmod am33xx_tptc0_hwmod = { .class = &am33xx_tptc_hwmod_class, .clkdm_name = "l3_clkdm", .mpu_irqs = am33xx_tptc0_irqs, + .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), .main_clk = "l3_gclk", .prcm = { .omap4 = {
Signature · 1 line
1.7.0.4
RFC v2 7/18 ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
Quoted 3 lines · Vaibhav Bedia
TPTC0 needs to be idled and put to standby under SW control. Add the appropriate flags in the TPTC0 hwmod entry.
Can you please expand TPTC0 in chane log.
Quoted 7 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Patch is fine otherwise.
RFC v2 7/18 ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
Quoted 5 lines · Santosh
Quoted 3 lines · Vaibhav Bedia
TPTC0 needs to be idled and put to standby under SW control. Add the appropriate flags in the TPTC0 hwmod entry.
Can you please expand TPTC0 in chane log.
Third Party Transfer Controller. It's part of the DMA IP. Will add it in the changelog.
Quoted 11 lines
Quoted 7 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Patch is fine otherwise.
RFC v2 7/18 ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
In reply to Vaibhav BediaQuoted 1 line · Vaibhav Bedia
TPTC0 needs to be idled and put to standby under SW control.
Please elaborate about why (e.g. HW support not available, HW support broken/buggy, etc.) since these blocks are not well documented in the docs that I have (spruh73f.)
Thanks,
Kevin
Quoted 27 lines
Add the appropriate flags in the TPTC0 hwmod entry.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
v1->v2:
No changearch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)arch/arm/mach-omap2/omap_hwmod_33xx_data.c +1
-0@@ -1823,6 +1823,7 @@ static struct omap_hwmod am33xx_tptc0_hwmod = { .class = &am33xx_tptc_hwmod_class, .clkdm_name = "l3_clkdm", .mpu_irqs = am33xx_tptc0_irqs, + .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), .main_clk = "l3_gclk", .prcm = { .omap4 = {
RFC v2 7/18 ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
Hi Kevin,
Quoted 8 lines · Kevin Hilman
Quoted 1 line · Vaibhav Bedia
TPTC0 needs to be idled and put to standby under SW control.
Please elaborate about why (e.g. HW support not available, HW support broken/buggy, etc.) since these blocks are not well documented in the docs that I have (spruh73f.)
This change was picked up for v3.9. I'll submit a follow-up patch adding in a comment in the hwmod file for this.
Regards,
Vaibhav
RFC v2 8/18 ARM: OMAP2+: AM33XX: hwmod: Fixup cpgmac0 hwmod entry
In reply to Vaibhav BediaThe current HWMOD code expects the memory region with the IP's SYSCONFIG register to be marked with ADDR_TYPE_RT flag.
CPGMAC0 hwmod entry specifies two memory regions and marks both with the flag ADDR_TYPE_RT although only the 2nd region has the SYSCONFIG register. This leads to the HWMOD code accessing the wrong memory address for idle and standby operations. Fix this by removing the ADDR_TYPE_RT flag from the 1st memory region in CPGMAC0 hwmod entry.
---v1->v2:
Address review comments from Santosh and
Vaibhav Hiremath. Previous discussion on the change
is @ http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129512.html
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/omap_hwmod_33xx_data.c +0 -1
@@ -2496,7 +2496,6 @@ static struct omap_hwmod_addr_space am33xx_cpgmac0_addr_space[] = { { .pa_start = 0x4a100000, .pa_end = 0x4a100000 + SZ_2K - 1, - .flags = ADDR_TYPE_RT, },/* cpsw wr */ {
Signature · 1 line
1.7.0.4
RFC v2 8/18 ARM: OMAP2+: AM33XX: hwmod: Fixup cpgmac0 hwmod entry
Quoted 11 lines · Vaibhav Bedia
The current HWMOD code expects the memory region with the IP's SYSCONFIG register to be marked with
ADDR_TYPE_RTflag.CPGMAC0 hwmod entry specifies two memory regions and marks both with the flag
ADDR_TYPE_RTalthough only the 2nd region has the SYSCONFIG register. This leads to the HWMOD code accessing the wrong memory address for idle and standby operations. Fix this by removing theADDR_TYPE_RTflag from the 1st memory region in CPGMAC0 hwmod entry.
Quoted 7 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Seems correct to me though Benoit, Paul can
may have comment.
Regards
Santosh
RFC v2 9/18 ARM: OMAP2+: AM33XX: hwmod: Update the WKUP-M3 hwmod with reset status bit
In reply to Vaibhav BediaWKUP-M3 has a reset status bit (RM_WKUP_STST.WKUP_M3_LRST) Update the WKUP-M3 hwmod data to reflect the same.
---v1->v2:
Change the patch order to keep git bisect happy
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_33xx_data.c +1 -0
@@ -269,6 +269,7 @@ static struct omap_hwmod am33xx_wkup_m3_hwmod = { .omap4 = { .clkctrl_offs = AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET, .rstctrl_offs = AM33XX_RM_WKUP_RSTCTRL_OFFSET, + .rstst_offs = AM33XX_RM_WKUP_RSTST_OFFSET, .modulemode = MODULEMODE_SWCTRL, }, },
Signature · 1 line
1.7.0.4
RFC v2 9/18 ARM: OMAP2+: AM33XX: hwmod: Update the WKUP-M3 hwmod with reset status bit
Vaibhav,
Quoted 10 lines · Vaibhav Bedia
WKUP-M3 has a reset status bit (RM_WKUP_STST.WKUP_M3_LRST) Update the WKUP-M3 hwmod data to reflect the same.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
I think you should make a separate series for
the data file updates/fixes.
Regards
Santosh
RFC v2 10/18 ARM: OMAP2+: AM33XX: Update the hardreset API
In reply to Vaibhav BediaWKUP-M3 has a reset status bit (RM_WKUP_STST.WKUP_M3_LRST) Update the hardreset API to ensure that the reset line properly deasserted.
---v1->v2:
Address comments from Vaibhav Hiremath and change the patch order as pointed out by Santosh Shilimkar
arch/arm/mach-omap2/omap_hwmod.c | 5 +---- arch/arm/mach-omap2/prm33xx.c | 11 +++++++---- arch/arm/mach-omap2/prm33xx.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +1 -4
@@ -3041,11 +3041,8 @@ static int _am33xx_assert_hardreset(struct omap_hwmod *oh,static int _am33xx_deassert_hardreset (struct omap_hwmod *oh,struct omap_hwmod_rst_info *ohri) { -if (ohri->st_shift) -pr_err ("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n" , - oh->name, ohri->name); -return am33xx_prm_deassert_hardreset (ohri->rst_shift, + ohri->st_shift, oh->clkdm->pwrdm.ptr->prcm_offs, oh->prcm.omap4.rstctrl_offs, oh->prcm.omap4.rstst_offs);
arch/arm/mach-omap2/prm33xx.c +7 -4
@@ -110,11 +110,11 @@ int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs)* -EINVAL upon an argument error, -EEXIST if the submodule was already out * of reset, or -EBUSY if the submodule did not exit reset promptly. */ -int am33xx_prm_deassert_hardreset (u8 shift,s16 inst, +int am33xx_prm_deassert_hardreset (u8 shift,u8 st_shift,s16 inst,u16 rstctrl_offs,u16 rstst_offs) {int c; -u32 mask =1 << shift; +u32 mask =1 << st_shift;/* Check the current status to avoid de-asserting the line twice */ if (am33xx_prm_is_hardreset_asserted (shift, inst, rstctrl_offs) ==0 )
@@ -122,11 +122,14 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,/* Clear the reset status by writing 1 to the status bit */ am33xx_prm_rmw_reg_bits (0xffffffff , mask, inst, rstst_offs); +/* de-assert the reset control line */ + mask =1 << shift; +am33xx_prm_rmw_reg_bits (mask,0 , inst, rstctrl_offs); -/* wait the status to be set */ -omap_test_timeout (am33xx_prm_is_hardreset_asserted (shift, inst, +/* wait the status to be set */ +omap_test_timeout (am33xx_prm_is_hardreset_asserted (st_shift, inst, rstst_offs),MAX_MODULE_HARDRESET_WAIT , c);
arch/arm/mach-omap2/prm33xx.h +1 -1
@@ -125,7 +125,7 @@ extern void am33xx_prm_global_warm_sw_reset(void);extern int am33xx_prm_is_hardreset_asserted (u8 shift,s16 inst,u16 rstctrl_offs);extern int am33xx_prm_assert_hardreset (u8 shift,s16 inst,u16 rstctrl_offs); -extern int am33xx_prm_deassert_hardreset (u8 shift,s16 inst, +extern int am33xx_prm_deassert_hardreset (u8 shift,u8 st_shift,s16 inst,u16 rstctrl_offs,u16 rstst_offs);#endif /* ASSEMBLER */
Signature · 1 line
1.7.0.4
RFC v2 10/18 ARM: OMAP2+: AM33XX: Update the hardreset API
Quoted 11 lines · Vaibhav Bedia
WKUP-M3 has a reset status bit (RM_WKUP_STST.WKUP_M3_LRST) Update the hardreset API to ensure that the reset line properly deasserted.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Looks good.
RFC v2 11/18 ARM: DTS: AM33XX: Add nodes for OCMC RAM and WKUP-M3
In reply to Vaibhav BediaSince AM33XX supports only DT-boot, this is needed for the appropriate device nodes to be created.
Note: OCMC RAM is part of the PER power domain and supports retention. The assembly code for low power entry/exit will run from OCMC RAM. To ensure that the OMAP PM code does not attempt to disable the clock to OCMC RAM as part of the suspend process add the no_idle_on_suspend flag.
---v1->v2:
Add a proper changelog
arch/arm/boot/dts/am33xx.dtsi | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
arch/arm/boot/dts/am33xx.dtsi +11 -0
@@ -385,5 +385,16 @@ mac-address = [ 00 00 00 00 00 00 ]; }; }; + + ocmcram: ocmcram at 40300000 { + compatible = "ti,ocmcram"; + ti,hwmods = "ocmcram"; + ti,no_idle_on_suspend; + }; + + wkup_m3: wkup_m3 at 44d00000 { + compatible = "ti,wkup_m3"; + ti,hwmods = "wkup_m3"; + }; }; };
Signature · 1 line
1.7.0.4
RFC v2 11/18 ARM: DTS: AM33XX: Add nodes for OCMC RAM and WKUP-M3
Quoted 9 lines · Vaibhav Bedia
Since AM33XX supports only DT-boot, this is needed for the appropriate device nodes to be created.
Note: OCMC RAM is part of the PER power domain and supports retention. The assembly code for low power entry/exit will run from OCMC RAM. To ensure that the OMAP PM code does not attempt to disable the clock to OCMC RAM as part of the suspend process add the
no_idle_on_suspendflag.
Quoted 8 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lindgren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Looks fine to me.
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
In reply to Vaibhav BediaThe current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
---v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.
arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/timer.c +33 -0
@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +static struct clock_event_device clockevent_gpt = { .name ="gp_timer" , .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT ,
@@ -135,6 +165,8 @@ static struct clock_event_device clockevent_gpt = { .rating = 300, .set_next_event = omap2_gp_timer_set_next_event, .set_mode = omap2_gp_timer_set_mode, + .suspend = omap_clkevt_suspend, + .resume = omap_clkevt_resume, };static struct property device_disabled = {
@@ -323,6 +355,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,int res; clkev.errata =omap_dm_timer_get_errata (); + clkev.id = gptimer_id;/* * For clock-event timers we never read the timer counter and
Signature · 1 line
1.7.0.4
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 59 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +20
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id);
arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 160
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +
Am still bit uncomfortable with direct hwmod usage in the suspend/resmue hooks.
Jon, Any alternatives you can think of ?
Regards,
Santosh
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 73 lines · Santosh
Quoted 59 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +20
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id);arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 160
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +Am still bit uncomfortable with direct hwmod usage in the suspend/resmue hooks.
Quoted 2 lines
Jon, Any alternatives you can think of ?
Jon,
Any suggestions here?
Regards,
Vaibhav
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 74 lines · Vaibhav
Quoted 73 lines · Santosh
Quoted 59 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +20
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id);arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 160
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +Am still bit uncomfortable with direct hwmod usage in the suspend/resmue hooks.
Quoted 6 lines
Quoted 2 lines
Jon, Any alternatives you can think of ?
Jon,
Any suggestions here?
Sorry completed this missed this!
Unfortunately, I don't have any good suggestions here. However, I am wondering if the suspend/resume handlers can just be calls to omap_hwmod_idle/enable and we can remove these __omap_dm_timer_xxxx calls (I don't think they are needed). Furthermore, my understanding is this is only needed for AM335x (per the changelog), and so we should not add suspend/resume handlers for all OMAP2+ based devices.
Cheers
Jon
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 83 lines · Jon Hunter
Quoted 74 lines · Vaibhav
Quoted 73 lines · Santosh
Quoted 59 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +20
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id);arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 160
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +Am still bit uncomfortable with direct hwmod usage in the suspend/resmue hooks.
Quoted 6 lines
Quoted 2 lines
Jon, Any alternatives you can think of ?
Jon,
Any suggestions here?
Quoted 9 lines
Sorry completed this missed this!
Unfortunately, I don't have any good suggestions here. However, I am wondering if the suspend/resume handlers can just be calls to omap_hwmod_idle/enable and we can remove these
__omap_dm_timer_xxxxcalls (I don't think they are needed). Furthermore, my understanding is this is only needed for AM335x (per the changelog), and so we should not add suspend/resume handlers for all OMAP2+ based devices.
I agree with the direction.
Regards,
Santosh
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 86 lines · Santosh
Quoted 85 lines · Jon Hunter
Quoted 74 lines · Vaibhav
Quoted 73 lines · Santosh
Quoted 59 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +20
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id);arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 160
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +Am still bit uncomfortable with direct hwmod usage in the suspend/resmue hooks.
Quoted 6 lines
Quoted 2 lines
Jon, Any alternatives you can think of ?
Jon,
Any suggestions here?
Sorry completed this missed this!
Quoted 9 lines
Quoted 7 lines
Unfortunately, I don't have any good suggestions here. However, I am wondering if the suspend/resume handlers can just be calls to omap_hwmod_idle/enable and we can remove these
__omap_dm_timer_xxxxcalls (I don't think they are needed). Furthermore, my understanding is this is only needed for AM335x (per the changelog), and so we should not add suspend/resume handlers for all OMAP2+ based devices.I agree with the direction.
I need to retain the call to enable the interrupt but the others can be dropped. Will take care of this and the comment on invoking the suspend/resume handlers only for AM335x in the next version.
Regards,
Vaibhav
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 94 lines · Vaibhav
Quoted 93 lines · Santosh
Quoted 92 lines · Jon Hunter
Quoted 74 lines · Vaibhav
Quoted 73 lines · Santosh
Quoted 59 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +20
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate); +omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id);arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 160
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW ); +} +Am still bit uncomfortable with direct hwmod usage in the suspend/resmue hooks.
Quoted 6 lines
Quoted 2 lines
Jon, Any alternatives you can think of ?
Jon,
Any suggestions here?
Sorry completed this missed this!
Unfortunately, I don't have any good suggestions here. However, I am wondering if the suspend/resume handlers can just be calls to omap_hwmod_idle/enable and we can remove these
__omap_dm_timer_xxxxcalls (I don't think they are needed). Furthermore, my understanding is this is only needed for AM335x (per the changelog), and so we should not add suspend/resume handlers for all OMAP2+ based devices.
Quoted 6 lines
Quoted 2 lines
I agree with the direction.
I need to retain the call to enable the interrupt but the others can be dropped. Will take care of this and the comment on invoking the suspend/resume handlers only for AM335x in the next version.
Ok fair enough. By the way, I posted a patch today [1] that will use the hwmod name as the clockevent timer name. Care to try on top of that patch and then we can eliminate the sprintf.
Cheers
Jon
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Quoted 5 lines · Jon
Ok fair enough. By the way, I posted a patch today [1] that will use the hwmod name as the clockevent timer name. Care to try on top of that patch and then we can eliminate the sprintf.
Thanks. Will try it out later today.
Regards,
Vaibhav
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
In reply to Vaibhav BediaQuoted 40 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +1
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } } +static void omap_clkevt_suspend (struct clock_event_device *unused)
arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 141
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate);
I am not sure you need to call __omap_dm_timer_stop() here. This should have already been called as timekeeping_suspend() will call omap2_gp_timer_set_mode() to shutdown the timer.
Quoted 7 lines
arch/arm/mach-omap2/timer.c +7
-0+omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh;
arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 158
Quoted 10 lines
arch/arm/mach-omap2/timer.c +10
-0+ +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW );
Similarly here, I am not sure these __omap_dm_timer_xxxx calls are needed.
arch/arm/mach-omap2/timer.c static struct clock_event_device clockevent_gpt = { · line 169
Quoted 11 lines
arch/arm/mach-omap2/timer.c +4
-0+} +static struct clock_event_device clockevent_gpt = { .name ="gp_timer" , .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT ,@@ -135,6 +165,8 @@ static struct clock_event_device clockevent_gpt = { .rating = 300, .set_next_event = omap2_gp_timer_set_next_event, .set_mode = omap2_gp_timer_set_mode, + .suspend = omap_clkevt_suspend, + .resume = omap_clkevt_resume,
AFAIK, this is only applicable for AM335x devices and so should not be added for all.
arch/arm/mach-omap2/timer.c static void __init omap2_gp_clockevent_init(int gptimer_id, · line 358
Quoted 8 lines
arch/arm/mach-omap2/timer.c +1
-0};static struct property device_disabled = {@@ -323,6 +355,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,int res; clkev.errata =omap_dm_timer_get_errata (); + clkev.id = gptimer_id;
We should not use gptimer_id anymore. This will go away once the migration to dev-tree is completed. You may be better off storing the oh_name in the clock_event_device name field and passing to the suspend/resume handlers.
Cheers
Jon
RFC v2 12/18 ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device
Hi Jon,
Quoted 41 lines · Jon
Quoted 39 lines · Vaibhav Bedia
The current OMAP timer code registers two timers - one as clocksource and one as clockevent. AM33XX has only one usable timer in the WKUP domain so one of the timers needs suspend-resume support to restore the configuration to pre-suspend state.
commit adc78e6 (timekeeping: Add suspend and resume of clock event devices) introduced .suspend and .resume callbacks for clock event devices. Leverages these callbacks to have AM33XX clockevent timer which is in not in WKUP domain to behave properly across system suspend.
Signed-off-by Vaibhav Bedia <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Get rid of harcoded timer id.
Note: since a platform device is not created for these timer instances and because there's very minimal change needed for restarting the timer a full blown context save and restore has been skipped.arch/arm/mach-omap2/timer.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-)arch/arm/mach-omap2/timer.c +0
-0@@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, } }
Quoted 15 lines
arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 141
Quoted 11 lines
arch/arm/mach-omap2/timer.c +11
-0+static void omap_clkevt_suspend (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh) +return ; + +__omap_dm_timer_stop (&clkev,1 , clkev.rate);I am not sure you need to call
__omap_dm_timer_stop()here. This should have already been called astimekeeping_suspend()will callomap2_gp_timer_set_mode()to shutdown the timer.
You are right, i can drop the call to __omap_dm_timer_stop().
Quoted 12 lines
Quoted 12 lines
arch/arm/mach-omap2/timer.c +11
-0+omap_hwmod_idle (oh); +} + +static void omap_clkevt_resume (struct clock_event_device *unused) +{ +char name[10 ]; +struct omap_hwmod *oh; + +sprintf (name,"timer%d" , clkev.id); + oh =omap_hwmod_lookup (name); +if (!oh)
Quoted 8 lines
arch/arm/mach-omap2/timer.c static void omap2_gp_timer_set_mode(enum clock_event_mode mode, · line 158
Quoted 6 lines
arch/arm/mach-omap2/timer.c +6
-0+return ; + +omap_hwmod_enable (oh); +__omap_dm_timer_load_start (&clkev, +OMAP_TIMER_CTRL_ST |OMAP_TIMER_CTRL_AR ,0 ,1 ); +__omap_dm_timer_int_enable (&clkev,OMAP_TIMER_INT_OVERFLOW );Similarly here, I am not sure these
__omap_dm_timer_xxxxcalls are needed.
I went through the code again. __omap_dm_timer_load_start() is invoked from omap2_gp_timer_set_mode() with the auto-reload flag when setting the mode to CLOCK_EVT_MODE_PERIODIC and without the auto-reload flag in omap2_gp_timer_set_next_event(). So looks like this call can be dropped. But I do need the call to __omap_dm_timer_int_enable() to re-enable the interrupts from the timer.
Quoted 16 lines
arch/arm/mach-omap2/timer.c static struct clock_event_device clockevent_gpt = { · line 169
Quoted 12 lines
arch/arm/mach-omap2/timer.c +4
-0+} +static struct clock_event_device clockevent_gpt = { .name ="gp_timer" , .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT ,@@ -135,6 +165,8 @@ static struct clock_event_device clockevent_gpt = { .rating = 300, .set_next_event = omap2_gp_timer_set_next_event, .set_mode = omap2_gp_timer_set_mode, + .suspend = omap_clkevt_suspend, + .resume = omap_clkevt_resume,AFAIK, this is only applicable for AM335x devices and so should not be added for all.
Agreed. Will address this in the next version.
Quoted 6 lines
Quoted 6 lines
arch/arm/mach-omap2/timer.c +0
-0};static struct property device_disabled = {@@ -323,6 +355,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,int res;
Quoted 8 lines
arch/arm/mach-omap2/timer.c static void __init omap2_gp_clockevent_init(int gptimer_id, · line 358
Quoted 2 lines
arch/arm/mach-omap2/timer.c +1
-0clkev.errata =omap_dm_timer_get_errata (); + clkev.id = gptimer_id;We should not use
gptimer_idanymore. This will go away once the migration to dev-tree is completed. You may be better off storing theoh_namein theclock_event_devicename field and passing to the suspend/resume handlers.
Currently the name field in clock_event_device is set to "gp_timer". Should I set the name in omap2_gp_clockevent_init() based on the gptimer_id?
Regards,
Vaibhav
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
In reply to Vaibhav BediaAM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
For now a new DT property has been added to allow the timer code to select the timer with the right property.
It has been pointed out by Santosh Shilimkar and Kevin Hilman that such a change will result in soc-idle never being achieved on AM33XX. There are other reasons why soc-idle does not look feasible on AM33XX so for now we go ahead with the interchange of the the timers. If at a later point of time we do come up with an approach which makes soc-idle possible on AM33XX, this can be revisited.
---v1->v2:
Use DT properties for changing the timers
.../devicetree/bindings/arm/omap/timer.txt | 2 ++ arch/arm/boot/dts/am33xx.dtsi | 1 + arch/arm/mach-omap2/timer.c | 6 +++--- 3 files changed, 6 insertions(+), 3 deletions(-)
Documentation/devicetree/bindings/arm/omap/timer.txt +2 -0
@@ -18,6 +18,8 @@ Optional properties: - ti,timer-pwm: Indicates the timer can generate a PWM output. - ti,timer-secure: Indicates the timer is reserved on a secure OMAP device and therefore cannot be used by the kernel. +- ti,timer-non-wkup Indicates the timer is in non-wkup power domain and hence + will lose register context when the power domain transitions Example:
arch/arm/boot/dts/am33xx.dtsi +1 -0
@@ -251,6 +251,7 @@ reg = <0x48040000 0x400>; interrupts = <68>; ti,hwmods = "timer2"; + ti,timer-non-wkup; }; timer3: timer at 48042000 {
arch/arm/mach-omap2/timer.c +3 -3
@@ -264,7 +264,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,int r =0 ;if (of_have_populated_dt ()) { - np =omap_get_timer_dt (omap_timer_match,NULL ); + np =omap_get_timer_dt (omap_timer_match, property);if (!np)return -ENODEV ;
@@ -633,8 +633,8 @@ OMAP_SYS_TIMER(3_gp, gptimer);#endif /* CONFIG_ARCH_OMAP3 */ #ifdef CONFIG_SOC_AM33XX -OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", -2 ,OMAP4_MPU_SOURCE ); +OMAP_SYS_GP_TIMER_INIT(3_am33xx, 2, OMAP4_MPU_SOURCE, "ti,timer-non-wkup", +1 ,OMAP4_MPU_SOURCE ); OMAP_SYS_TIMER(3_am33xx, gptimer);#endif /* CONFIG_SOC_AM33XX */
Signature · 1 line
1.7.0.4
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
Quoted 17 lines · Vaibhav Bedia
AM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
For now a new DT property has been added to allow the timer code to select the timer with the right property.
Quoted 8 lines
It has been pointed out by Santosh Shilimkar and Kevin Hilman that such a change will result in soc-idle never being achieved on AM33XX. There are other reasons why soc-idle does not look feasible on AM33XX so for now we go ahead with the interchange of the the timers. If at a later point of time we do come up with an approach which makes soc-idle possible on AM33XX, this can be revisited.
Can you please explain other reasons as well for clarity ?
Regards
Santosh
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
Quoted 26 lines · Santosh
Quoted 17 lines · Vaibhav Bedia
AM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
For now a new DT property has been added to allow the timer code to select the timer with the right property.
Quoted 8 lines
It has been pointed out by Santosh Shilimkar and Kevin Hilman that such a change will result in soc-idle never being achieved on AM33XX. There are other reasons why soc-idle does not look feasible on AM33XX so for now we go ahead with the interchange of the the timers. If at a later point of time we do come up with an approach which makes soc-idle possible on AM33XX, this can be revisited.
Quoted 2 lines
Can you please explain other reasons as well for clarity ?
I guess from h/w perspective it boils down to lack of HW-AUTO and IO-Daisy chaining on AM33xx [1].
Since there's no 32ksynctimer, do we also need to register DMTIMER1 as the persistent clock on AM33xx? This can only be done from DMTIMER1 which is currently serving as the clockevent.
Regards,
Vaibhav
[1] http://marc.info/?l=linux-arm-kernel&m=135238055717206&w=4
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
In reply to Vaibhav BediaQuoted 48 lines · Vaibhav Bedia
AM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
For now a new DT property has been added to allow the timer code to select the timer with the right property.
It has been pointed out by Santosh Shilimkar and Kevin Hilman that such a change will result in soc-idle never being achieved on AM33XX. There are other reasons why soc-idle does not look feasible on AM33XX so for now we go ahead with the interchange of the the timers. If at a later point of time we do come up with an approach which makes soc-idle possible on AM33XX, this can be revisited.
Signed-off-by Vaibhav Bedia <[email protected]>Signed-off-by Vaibhav Hiremath <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Jon Hunter <[email protected]>---
v1->v2:
Use DT properties for changing the timers.../devicetree/bindings/arm/omap/timer.txt | 2 ++ arch/arm/boot/dts/am33xx.dtsi | 1 + arch/arm/mach-omap2/timer.c | 6 +++--- 3 files changed, 6 insertions(+), 3 deletions(-)Documentation/devicetree/bindings/arm/omap/timer.txt +0
-0
Documentation/devicetree/bindings/arm/omap/timer.txt Optional properties: · line 22
Quoted 5 lines
Documentation/devicetree/bindings/arm/omap/timer.txt +2
-0@@ -18,6 +18,8 @@ Optional properties: - ti,timer-pwm: Indicates the timer can generate a PWM output. - ti,timer-secure: Indicates the timer is reserved on a secure OMAP device and therefore cannot be used by the kernel. +- ti,timer-non-wkup Indicates the timer is in non-wkup power domain and hence + will lose register context when the power domain transitions
I was hoping that we could avoid adding another property, especially given that his equivalent to a timer that does not have the "ti,timer-alwon" property.
arch/arm/boot/dts/am33xx.dtsi line 254
Quoted 11 lines
Documentation/devicetree/bindings/arm/omap/timer.txt +0
-0Example:arch/arm/boot/dts/am33xx.dtsi +1
-0@@ -251,6 +251,7 @@ reg = <0x48040000 0x400>; interrupts = <68>; ti,hwmods = "timer2"; + ti,timer-non-wkup;
Is this is only one not in the wake-up domain?
Quoted 17 lines
arch/arm/boot/dts/am33xx.dtsi +0
-0}; timer3: timer at 48042000 {arch/arm/mach-omap2/timer.c +1
-1@@ -264,7 +264,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,int r =0 ;if (of_have_populated_dt ()) { - np =omap_get_timer_dt (omap_timer_match,NULL ); + np =omap_get_timer_dt (omap_timer_match, property);if (!np)return -ENODEV ;
arch/arm/mach-omap2/timer.c OMAP_SYS_TIMER(3_gp, gptimer); · line 637
Quoted 7 lines
arch/arm/mach-omap2/timer.c +2
-2@@ -633,8 +633,8 @@ OMAP_SYS_TIMER(3_gp, gptimer);#endif /* CONFIG_ARCH_OMAP3 */ #ifdef CONFIG_SOC_AM33XX -OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", -2 ,OMAP4_MPU_SOURCE ); +OMAP_SYS_GP_TIMER_INIT(3_am33xx, 2, OMAP4_MPU_SOURCE, "ti,timer-non-wkup", +1 ,OMAP4_MPU_SOURCE );
It seems to me here that we should specify the property "ti,timer-alwon" for the clocksource and then no property for the clockevent. Hence, may be the code needs to be adjusted so that if clockevent or clocksource can use any timer (ie. no property specified), we look for a timer that has no "ti-timer-xxxx" properties. This will ensure that if we need a particular timer for clocksource, which we look for after clockevent, it will be available.
Cheers
Jon
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
In reply to Vaibhav BediaHi Vaibhav,
Quoted 6 lines · Vaibhav Bedia
AM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Quoted 7 lines
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
I have been thinking about this some more. In the case where we are using gptimers for both clock-events and clock-source (on both AM33xx and OMAP) and I am wondering if it makes sense to switch the timers so that we use the always-on timer for clock-source and a different one from clock-events.
For OMAP, if we are not using the 32k-sync for clock-source, then we are never going to achieve low power states during idle as we will always have one gptimer running. And in this case, to your point below, it would be better to use the always-on for clock-source so that in suspend we can at least hit low power states and maintain time.
Quoted 10 lines
For now a new DT property has been added to allow the timer code to select the timer with the right property.
It has been pointed out by Santosh Shilimkar and Kevin Hilman that such a change will result in soc-idle never being achieved on AM33XX. There are other reasons why soc-idle does not look feasible on AM33XX so for now we go ahead with the interchange of the the timers. If at a later point of time we do come up with an approach which makes soc-idle possible on AM33XX, this can be revisited.
Right, but this would also be true for OMAP if we don't use the 32k-sync as we only have one gptimer in the wake-up domain.
Cheers
Jon
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
Quoted 23 lines · Jon Hunter
Hi Vaibhav,
Quoted 6 lines · Vaibhav Bedia
AM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Quoted 7 lines
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
I have been thinking about this some more. In the case where we are using gptimers for both clock-events and clock-source (on both AM33xx and OMAP) and I am wondering if it makes sense to switch the timers so that we use the always-on timer for clock-source and a different one from clock-events.
Quoted 5 lines
For OMAP, if we are not using the 32k-sync for clock-source, then we are never going to achieve low power states during idle as we will always have one gptimer running. And in this case, to your point below, it would be better to use the always-on for clock-source so that in suspend we can at least hit low power states and maintain time.
I have posted a patch today [1] that I hope will address this issue for you. Can you give that a try?
Cheers
Jon
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
Quoted 25 lines · Jon Hunter
Quoted 23 lines · Jon Hunter
Hi Vaibhav,
Quoted 6 lines · Vaibhav Bedia
AM33XX has two timers (DTIMER0/1) in the WKUP domain. On GP devices the source of DMTIMER0 is fixed to an inaccurate internal 32k RC oscillator and this makes the DMTIMER0 practically either as a clocksource or as clockevent.
Quoted 7 lines
Currently the timer instance in WKUP domain is used as the clockevent and the timer in non-WKUP domain as the clocksource. DMTIMER1 in WKUP domain can keep running in suspend from a 32K clock fed from external OSC and can serve as the persistent clock for the kernel. To enable this, interchange the timers used as clocksource and clockevent for AM33XX.
I have been thinking about this some more. In the case where we are using gptimers for both clock-events and clock-source (on both AM33xx and OMAP) and I am wondering if it makes sense to switch the timers so that we use the always-on timer for clock-source and a different one from clock-events.
Quoted 8 lines
Quoted 5 lines
For OMAP, if we are not using the 32k-sync for clock-source, then we are never going to achieve low power states during idle as we will always have one gptimer running. And in this case, to your point below, it would be better to use the always-on for clock-source so that in suspend we can at least hit low power states and maintain time.
I have posted a patch today [1] that I hope will address this issue for you. Can you give that a try?
By the way, this need to be applied on top of the fix I sent yesterday to pass the property.
Cheers
Jon
RFC v2 13/18 ARM: OMAP2+: AM33XX: timer: Interchance clkevt and clksrc timers
Quoted 4 lines · Jon
By the way, this need to be applied on top of the fix I sent yesterday to pass the property.
Ok. Thanks for pointing this out.
RFC v2 14/18 ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
In reply to Vaibhav BediaAdd minimal APIs for writing to the IPC and the M3_TXEV registers in the Control module. These will be used in a subsequent patch which adds suspend-resume support for AM33XX.
---v1->v2:
This a new patch in the series to isolate the control module accesses as pointed out by Kevin Hilman.
arch/arm/mach-omap2/control.c | 20 ++++++++++++++++++++ arch/arm/mach-omap2/control.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/control.c +20 -0
@@ -604,3 +604,23 @@ int omap3_ctrl_save_padconf(void) }#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ + +#if defined(CONFIG_SOC_AM33XX ) && defined(CONFIG_PM ) +void am33xx_txev_eoi (void ) +{ +omap_ctrl_writel (AM33XX_M3_TXEV_ACK ,AM33XX_CONTROL_M3_TXEV_EOI ); +} + +void am33xx_txev_enable (void ) +{ +omap_ctrl_writel (AM33XX_M3_TXEV_ENABLE ,AM33XX_CONTROL_M3_TXEV_EOI ); +} + +void am33xx_wkup_m3_ipc_cmd (struct am33xx_ipc_data *data) +{ +omap_ctrl_writel (data->resume_addr,AM33XX_CONTROL_IPC_MSG_REG0 ); +omap_ctrl_writel (data->sleep_mode,AM33XX_CONTROL_IPC_MSG_REG1 ); +omap_ctrl_writel (data->param1,AM33XX_CONTROL_IPC_MSG_REG2 ); +omap_ctrl_writel (data->param2,AM33XX_CONTROL_IPC_MSG_REG3 ); +} +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
arch/arm/mach-omap2/control.h +41 -0
53 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC v2 14/18 ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
Quoted 4 lines · Vaibhav Bedia
Add minimal APIs for writing to the IPC and the
M3_TXEVregisters in the Control module. These will be used in a subsequent patch which adds suspend-resume support for AM33XX.
Quoted 8 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
On Control module, we are trying to move driver/module specific code to respective drivers. Can you not add below code to ipc related driver component.
If not, then patch as such is fine with me.
Regards
Santosh
RFC v2 14/18 ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
Quoted 13 lines · Santosh
Quoted 4 lines · Vaibhav Bedia
Add minimal APIs for writing to the IPC and the
M3_TXEVregisters in the Control module. These will be used in a subsequent patch which adds suspend-resume support for AM33XX.Quoted 8 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
Quoted 6 lines
On Control module, we are trying to move driver/module specific code to respective drivers. Can you not add below code to ipc related driver component.
If not, then patch as such is fine with me.
I had it in the pm33xx.c in the previous version. Kevin had asked me to move it to control.c. Should I revert move it back there?
Regards,
Vaibhav
RFC v2 14/18 ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
Quoted 18 lines · Vaibhav
Quoted 17 lines · Santosh
Quoted 4 lines · Vaibhav Bedia
Add minimal APIs for writing to the IPC and the
M3_TXEVregisters in the Control module. These will be used in a subsequent patch which adds suspend-resume support for AM33XX.Quoted 8 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
On Control module, we are trying to move driver/module specific code to respective drivers. Can you not add below code to ipc related driver component.
Quoted 6 lines
Quoted 2 lines
If not, then patch as such is fine with me.
I had it in the
pm33xx.cin the previous version. Kevin had asked me to move it tocontrol.c. Should I revert move it back there?
pm33xx.c is not the right place. I was hoping to move to some driver. If that is not possible then leave it in control module.
Regards
Santosh
RFC v2 14/18 ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
Quoted 19 lines · Santosh
Quoted 18 lines · Vaibhav
Quoted 17 lines · Santosh
Quoted 4 lines · Vaibhav Bedia
Add minimal APIs for writing to the IPC and the
M3_TXEVregisters in the Control module. These will be used in a subsequent patch which adds suspend-resume support for AM33XX.Quoted 8 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
On Control module, we are trying to move driver/module specific code to respective drivers. Can you not add below code to ipc related driver component.
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
If not, then patch as such is fine with me.
I had it in the
pm33xx.cin the previous version. Kevin had asked me to move it tocontrol.c. Should I revert move it back there?
pm33xx.cis not the right place. I was hoping to move to some driver. If that is not possible then leave it in control module.
I think I'll leave it here for now. Could I have you ack in that case?
Thanks,
Vaibhav
RFC v2 14/18 ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
Quoted 23 lines · Vaibhav
Quoted 22 lines · Santosh
Quoted 21 lines · Vaibhav
Quoted 19 lines · Santosh
Quoted 4 lines · Vaibhav Bedia
Add minimal APIs for writing to the IPC and the
M3_TXEVregisters in the Control module. These will be used in a subsequent patch which adds suspend-resume support for AM33XX.Quoted 8 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Vaibhav Hiremath <[email protected]>---
On Control module, we are trying to move driver/module specific code to respective drivers. Can you not add below code to ipc related driver component.
If not, then patch as such is fine with me.
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
I had it in the
pm33xx.cin the previous version. Kevin had asked me to move it tocontrol.c. Should I revert move it back there?
pm33xx.cis not the right place. I was hoping to move to some driver. If that is not possible then leave it in control module.I think I'll leave it here for now. Could I have you ack in that case?
Yep.
RFC v2 15/18 ARM: OMAP2+: AM33XX: Add assembly code for PM operations
In reply to Vaibhav BediaIn preparation for suspend-resume support for AM33XX, add the assembly file with the code which is copied to internal memory (OCMC RAM) during bootup and runs from there.
As part of the low power entry (DeepSleep0 mode in AM33XX TRM), the code running from OCMC RAM does the following
1. Stores the EMIF configuration
2. Puts external memory in self-refresh
3. Disables EMIF clock
4. Puts the PLLs in bypass
5. Executes WFI after writing to MPU_CLKCTRL register.
If no interrupts have come, WFI execution on MPU gets registered as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes care of clockdomain and powerdomain transitions as part of the DeepSleep0 mode entry.
In case a late interrupt comes in, WFI ends up as a NOP and MPU continues execution from internal memory. The 'abort path' code undoes whatever was done as part of the low power entry and indicates a suspend failure by passing a non-zero value to the cpu_resume routine.
The 'resume path' code is similar to the 'abort path' with the key difference of MMU being enabled in the 'abort path' but being disabled in the 'resume path' due to MPU getting powered off.
In addition to the top level steps outlined above, there are some additional register writes related to external memory controller which help in lowering the overall power consumption in the suspended state. These include changing the state of the IOs to LVCMOS mode and enabling pull downs on the IOs to reduce leakage in low power state.
---v1->v2:
This is a new patch in the series to keep the assembly code additionl separate as mentioned by Kevin Hilman
arch/arm/mach-omap2/sleep33xx.S | 584 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 584 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-omap2/sleep33xx.S
arch/arm/mach-omap2/sleep33xx.S new file +584 -0
@@ -0,0 +1,584 @@ +/* + * Low level suspend code for AM33XX SoCs + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Bedia <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/linkage.h> +#include <linux/ti_emif.h> +#include <asm/memory.h> +#include <asm/assembler.h> + +#include "cm33xx.h" +#include "pm33xx.h" +#include "prm33xx.h" +#include "control.h" + + .text + .align 3 + + .macro pll_bypass, name, clk_mode_addr, idlest_addr, pll_mode +pll_bypass_\name: + ldr r0, \clk_mode_addr + ldr r1, [r0] + str r1, clk_mode_\pll_mode + bic r1, r1, #(7 << 0) + orr r1, r1, #0x5 + str r1, [r0] + ldr r0, \idlest_addr +wait_pll_bypass_\name: + ldr r1, [r0] + tst r1, #0x0 + bne wait_pll_bypass_\name + .endm + + .macro pll_lock, name, clk_mode_addr, idlest_addr, pll_mode +pll_lock_\name: + ldr r0, \clk_mode_addr + ldr r1, clk_mode_\pll_mode + str r1, [r0] + and r1, r1, #0x7 + cmp r1, #0x7 + bne pll_mode_restored_\name + ldr r0, \idlest_addr +wait_pll_lock_\name: + ldr r1, [r0] + ands r1, #0x1 + beq wait_pll_lock_\name +pll_mode_restored_\name: + nop + .endm + + .macro ddr_self_refresh, num +ddr_self_refresh_\num: + add r1, r0, #EMIF_POWER_MANAGEMENT_CONTROL + ldr r2, [r1] + orr r2, r2, #0xa0 @ a reasonable delay for entering SR + str r2, [r1, #0] + str r2, [r1, #4] @ write to shadow register also + + ldr r2, ddr_start @ do a dummy access to DDR + ldr r3, [r2, #0] + ldr r3, [r1, #0] @ now set the LP MODE to Self-Refresh + orr r3, r3, #0x200 + str r3, [r1, #0] + + mov r1, #0x1000 @ Give some time for system to enter SR +wait_sr_\num: + subs r1, r1, #1 + bne wait_sr_\num + .endm + + .macro wait_sdram_config, num +wait_sdram_config_\num: + mov r0, #0x100 +wait_sc_\num: + subs r0, r0 ,#1 + bne wait_sc_\num + .endm + +ENTRY(am33xx_do_wfi) + stmfd sp!, {r4 - r11, lr} @ save registers on stack + /* Get the EMIF virtual address */ + ldr r0, emif_addr_func + blx r0 + /* Save it for later use */ + str r0, emif_addr_virt + + /* This ensures isb */ + ldr r0, dcache_flush + blx r0 + + /* Same as v7_flush_icache_all - saving a branch */ + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + + ldr r0, emif_addr_virt + /* Save EMIF configuration */ + ldr r1, [r0, #EMIF_SDRAM_CONFIG] + str r1, emif_sdcfg_val + ldr r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] + str r1, emif_ref_ctrl_val + ldr r1, [r0, #EMIF_SDRAM_TIMING_1] + str r1, emif_timing1_val + ldr r1, [r0, #EMIF_SDRAM_TIMING_2] + str r1, emif_timing2_val + ldr r1, [r0, #EMIF_SDRAM_TIMING_3] + str r1, emif_timing3_val + ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] + str r1, emif_pmcr_val + ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] + str r1, emif_pmcr_shdw_val + ldr r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] + str r1, emif_zqcfg_val + ldr r1, [r0, #EMIF_DDR_PHY_CTRL_1] + str r1, emif_rd_lat_val + + /* Ensure that all the writes to DDR leave the A8 */ + dsb + dmb + isb + + ddr_self_refresh 1 + + /* Disable EMIF at this point */ + ldr r1, virt_emif_clkctrl + ldr r2, [r1] + bic r2, r2, #(3 << 0) + str r2, [r1] + + ldr r1, virt_emif_clkctrl +wait_emif_disable: + ldr r2, [r1] + ldr r3, module_disabled_val + cmp r2, r3 + bne wait_emif_disable + + /* + * For the MPU WFI to be registered as an interrupt + * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set + * to DISABLED + */ + ldr r1, virt_mpu_clkctrl + ldr r2, [r1] + bic r2, r2, #(3 << 0) + str r2, [r1] + + /* DDR3 reset override and mDDR mode selection */ + ldr r0, virt_ddr_io_ctrl + mov r1, #(0x9 << 28) + str r1, [r0] + + /* Weak pull down for DQ, DM */ + ldr r1, virt_ddr_data0_ioctrl + ldr r2, susp_io_pull_data + str r2, [r1] + + ldr r1, virt_ddr_data1_ioctrl + ldr r2, susp_io_pull_data + str r2, [r1] + + /* Disable VTP */ + ldr r1, virt_ddr_vtp_ctrl + ldr r2, susp_vtp_ctrl_val + str r2, [r1] + + /* Enable SRAM LDO ret mode */ + ldr r0, virt_sram_ldo_addr + ldr r1, [r0] + orr r1, #1 + str r1, [r0] + +put_pll_bypass: + /* Put the PLLs in bypass mode */ + pll_bypass core, virt_core_clk_mode, virt_core_idlest, core_val + pll_bypass ddr, virt_ddr_clk_mode, virt_ddr_idlest, ddr_val + pll_bypass disp, virt_disp_clk_mode, virt_disp_idlest, disp_val + pll_bypass per, virt_per_clk_mode, virt_per_idlest, per_val + pll_bypass mpu, virt_mpu_clk_mode, virt_mpu_idlest, mpu_val + + dsb + dmb + isb + + wfi + + /* NOPs to ensure the A8 pipeline is clean */ + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + /* We come here in case of an abort due to a late interrupt */ + + /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */ + ldr r1, virt_mpu_clkctrl + mov r2, #0x2 + str r2, [r1] + + /* Relock the PLLs */ + pll_lock mpu_abt, virt_mpu_clk_mode, virt_mpu_idlest, mpu_val + pll_lock per_abt, virt_per_clk_mode, virt_per_idlest, per_val + pll_lock disp_abt, virt_disp_clk_mode, virt_disp_idlest, disp_val + pll_lock ddr_abt, virt_ddr_clk_mode, virt_ddr_idlest, ddr_val + pll_lock core_abt, virt_core_clk_mode, virt_core_idlest, core_val + + /* Disable SRAM LDO ret mode */ + ldr r0, virt_sram_ldo_addr + ldr r1, [r0] + bic r1, #1 + str r1, [r0] + + /* Restore the pull for DQ, DM */ + ldr r1, virt_ddr_data0_ioctrl + ldr r2, resume_io_pull_data + str r2, [r1] + + ldr r1, virt_ddr_data1_ioctrl + ldr r2, resume_io_pull_data + str r2, [r1] + + /* Enable EMIF */ + ldr r1, virt_emif_clkctrl + mov r2, #0x2 + str r2, [r1] +wait_emif_enable: + ldr r3, [r1] + cmp r2, r3 + bne wait_emif_enable + + /* Enable VTP */ +config_vtp_abt: + ldr r0, virt_ddr_vtp_ctrl + ldr r1, [r0] + mov r2, #0x0 @ clear the register + str r2, [r0] + mov r2, #0x6 @ write the filter value + str r2, [r0] + + ldr r1, [r0] + ldr r2, vtp_enable @ set the enable bit + orr r2, r2, r1 + str r2, [r0] + + ldr r1, [r0] @ toggle the CLRZ bit + bic r1, #1 + str r1, [r0] + + ldr r1, [r0] + orr r1, #1 + str r1, [r0] + +poll_vtp_ready_abt: + ldr r1, [r0] @ poll for VTP ready + tst r1, #(AM33XX_VTP_CTRL_READY) + beq poll_vtp_ready_abt + + /* DDR3 reset override and mDDR mode clear */ + ldr r0, virt_ddr_io_ctrl + mov r1, #0 + str r1, [r0] + +emif_self_refresh_dis: + /* Disable EMIF self-refresh */ + ldr r0, emif_addr_virt + add r0, r0, #EMIF_POWER_MANAGEMENT_CONTROL + ldr r1, [r0] + bic r1, r1, #LP_MODE_MASK + str r1, [r0] + str r1, [r0, #4] + + /* + * A write to SDRAM CONFIG register triggers + * an init sequence and hence it must be done + * at the end + */ + ldr r0, emif_addr_virt + add r0, r0, #EMIF_SDRAM_CONFIG + ldr r4, emif_sdcfg_val + str r4, [r0] + + mov r0, #0x1000 +wait_abt: + subs r0, r0, #1 + bne wait_abt + + /* Let the suspend code know about the abort */ + mov r0, #1 + ldmfd sp!, {r4 - r11, pc} @ restore regs and return +ENDPROC(am33xx_do_wfi) + + .align +ENTRY(am33xx_resume_offset) + .word . - am33xx_do_wfi + +ENTRY(am33xx_resume_from_deep_sleep) + /* Take the PLLs out of LP_BYPASS */ + pll_lock mpu, phys_mpu_clk_mode, phys_mpu_idlest, mpu_val + pll_lock per, phys_per_clk_mode, phys_per_idlest, per_val + pll_lock disp, phys_disp_clk_mode, phys_disp_idlest, disp_val + pll_lock ddr, phys_ddr_clk_mode, phys_ddr_idlest, ddr_val + pll_lock core, phys_core_clk_mode, phys_core_idlest, core_val + + /* Disable SRAM LDO ret mode */ + ldr r0, phys_sram_ldo_addr + ldr r1, [r0] + bic r1, #1 + str r1, [r0] + + /* Restore the pull for DQ, DM */ + ldr r1, phys_ddr_data0_ioctrl + ldr r2, resume_io_pull_data + str r2, [r1] + + ldr r1, phys_ddr_data1_ioctrl + ldr r2, resume_io_pull_data + str r2, [r1] + +config_vtp: + ldr r0, phys_ddr_vtp_ctrl + ldr r1, [r0] + mov r2, #0x0 @ clear the register + str r2, [r0] + mov r2, #0x6 @ write the filter value + str r2, [r0] + + ldr r1, [r0] + ldr r2, vtp_enable @ set the enable bit + orr r2, r2, r1 + str r2, [r0] + + ldr r1, [r0] @ toggle the CLRZ bit + bic r1, #1 + str r1, [r0] + + ldr r1, [r0] + orr r1, #1 + str r1, [r0] + +poll_vtp_ready: + ldr r1, [r0] @ poll for VTP ready + tst r1, #AM33XX_VTP_CTRL_READY + beq poll_vtp_ready + + /* DDR3 reset override and mDDR mode clear */ + ldr r0, phys_ddr_io_ctrl + mov r1, #0 + str r1, [r0] + + /* Enable EMIF */ + ldr r1, phys_emif_clkctrl + mov r2, #0x2 + str r2, [r1] +wait_emif_enable1: + ldr r3, [r1] + cmp r2, r3 + bne wait_emif_enable1 + +config_emif_timings: + ldr r3, emif_phys_addr + ldr r4, emif_rd_lat_val + str r4, [r3, #EMIF_DDR_PHY_CTRL_1] + str r4, [r3, #EMIF_DDR_PHY_CTRL_1_SHDW] + ldr r4, emif_timing1_val + str r4, [r3, #EMIF_SDRAM_TIMING_1] + str r4, [r3, #EMIF_SDRAM_TIMING_1_SHDW] + ldr r4, emif_timing2_val + str r4, [r3, #EMIF_SDRAM_TIMING_2] + str r4, [r3, #EMIF_SDRAM_TIMING_2_SHDW] + ldr r4, emif_timing3_val + str r4, [r3, #EMIF_SDRAM_TIMING_3] + str r4, [r3, #EMIF_SDRAM_TIMING_3_SHDW] + ldr r4, emif_ref_ctrl_val + str r4, [r3, #EMIF_SDRAM_REFRESH_CONTROL] + str r4, [r3, #EMIF_SDRAM_REFRESH_CTRL_SHDW] + ldr r4, emif_pmcr_val + str r4, [r3, #EMIF_POWER_MANAGEMENT_CONTROL] + ldr r4, emif_pmcr_shdw_val + str r4, [r3, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] + + /* + * A write to SDRAM CONFIG register triggers + * an init sequence and hence it must be done + *@the end + */ + ldr r4, emif_sdcfg_val + str r4, [r3, #EMIF_SDRAM_CONFIG] + + /* Back from la-la-land. Kill some time for sanity to settle in */ + mov r0, #0x1000 +wait_resume: + subs r0, r0, #1 + bne wait_resume + + /* We are back. Branch to the common CPU resume routine */ + mov r0, #0 + ldr pc, resume_addr +ENDPROC(am33xx_resume_from_deep_sleep) + + +/* + * Local variables + */ + .align +resume_addr: + .word cpu_resume - PAGE_OFFSET + 0x80000000 +dcache_flush: + .word v7_flush_dcache_all +emif_addr_func: + .word am33xx_get_emif_base +ddr_start: + .word PAGE_OFFSET +emif_phys_addr: + .word AM33XX_EMIF_BASE +virt_mpu_idlest: + .word AM33XX_CM_IDLEST_DPLL_MPU +virt_mpu_clk_mode: + .word AM33XX_CM_CLKMODE_DPLL_MPU +phys_mpu_clk_mode: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_CLKMODE_DPLL_MPU_OFFSET) +phys_mpu_idlest: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_IDLEST_DPLL_MPU_OFFSET) +virt_core_idlest: + .word AM33XX_CM_IDLEST_DPLL_CORE +virt_core_clk_mode: + .word AM33XX_CM_CLKMODE_DPLL_CORE +phys_core_clk_mode: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_CLKMODE_DPLL_CORE_OFFSET) +phys_core_idlest: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_IDLEST_DPLL_CORE_OFFSET) +virt_per_idlest: + .word AM33XX_CM_IDLEST_DPLL_PER +virt_per_clk_mode: + .word AM33XX_CM_CLKMODE_DPLL_PER +phys_per_clk_mode: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_CLKMODE_DPLL_PER_OFFSET) +phys_per_idlest: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_IDLEST_DPLL_PER_OFFSET) +virt_disp_idlest: + .word AM33XX_CM_IDLEST_DPLL_DISP +virt_disp_clk_mode: + .word AM33XX_CM_CLKMODE_DPLL_DISP +phys_disp_clk_mode: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_CLKMODE_DPLL_DISP_OFFSET) +phys_disp_idlest: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_IDLEST_DPLL_DISP_OFFSET) +virt_ddr_idlest: + .word AM33XX_CM_IDLEST_DPLL_DDR +virt_ddr_clk_mode: + .word AM33XX_CM_CLKMODE_DPLL_DDR +phys_ddr_clk_mode: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_CLKMODE_DPLL_DDR_OFFSET) +phys_ddr_idlest: + .word (AM33XX_CM_BASE + AM33XX_CM_WKUP_MOD + \ + AM33XX_CM_IDLEST_DPLL_DDR_OFFSET) +virt_sram_ldo_addr: + .word AM33XX_PRM_LDO_SRAM_MPU_CTRL +phys_sram_ldo_addr: + .word (AM33XX_PRM_BASE + AM33XX_PRM_DEVICE_MOD + \ + AM33XX_PRM_LDO_SRAM_MPU_CTRL_OFFSET) +virt_mpu_clkctrl: + .word AM33XX_CM_MPU_MPU_CLKCTRL +virt_emif_clkctrl: + .word AM33XX_CM_PER_EMIF_CLKCTRL +phys_emif_clkctrl: + .word (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \ + AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET) +module_disabled_val: + .word 0x30000 + +/* DDR related defines */ +virt_ddr_io_ctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_DDR_IO_CTRL) +phys_ddr_io_ctrl: + .word AM33XX_CTRL_BASE + AM33XX_DDR_IO_CTRL +virt_ddr_vtp_ctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_VTP0_CTRL_REG) +phys_ddr_vtp_ctrl: + .word AM33XX_CTRL_BASE + AM33XX_VTP0_CTRL_REG +virt_ddr_cmd0_ioctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_DDR_CMD0_IOCTRL) +phys_ddr_cmd0_ioctrl: + .word AM33XX_CTRL_BASE + AM33XX_DDR_CMD0_IOCTRL +virt_ddr_cmd1_ioctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_DDR_CMD1_IOCTRL) +phys_ddr_cmd1_ioctrl: + .word AM33XX_CTRL_BASE + AM33XX_DDR_CMD1_IOCTRL +virt_ddr_cmd2_ioctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_DDR_CMD2_IOCTRL) +phys_ddr_cmd2_ioctrl: + .word AM33XX_CTRL_BASE + AM33XX_DDR_CMD2_IOCTRL +virt_ddr_data0_ioctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_DDR_DATA0_IOCTRL) +phys_ddr_data0_ioctrl: + .word AM33XX_CTRL_BASE + AM33XX_DDR_DATA0_IOCTRL +virt_ddr_data1_ioctrl: + .word AM33XX_CTRL_REGADDR(AM33XX_DDR_DATA1_IOCTRL) +phys_ddr_data1_ioctrl: + .word AM33XX_CTRL_BASE + AM33XX_DDR_DATA1_IOCTRL +vtp_enable: + .word AM33XX_VTP_CTRL_ENABLE + +/* + * Values recommended by the HW team. These change the pulls + * on certain IOs of DATA and CMD macros + */ +susp_io_pull_data: + .word 0x3FF00003 +susp_io_pull_cmd1: + .word 0xFFE0018B +susp_io_pull_cmd2: + .word 0xFFA0098B +resume_io_pull_data: + .word 0x18B +resume_io_pull_cmd: + .word 0x18B +susp_vtp_ctrl_val: + .word 0x10117 + +/* Placeholder for storing EMIF configuration */ +emif_addr_virt: + .word 0xDEADBEEF +emif_rd_lat_val: + .word 0xDEADBEEF +emif_timing1_val: + .word 0xDEADBEEF +emif_timing2_val: + .word 0xDEADBEEF +emif_timing3_val: + .word 0xDEADBEEF +emif_sdcfg_val: + .word 0xDEADBEEF +emif_ref_ctrl_val: + .word 0xDEADBEEF +emif_zqcfg_val: + .word 0xDEADBEEF +emif_pmcr_val: + .word 0xDEADBEEF +emif_pmcr_shdw_val: + .word 0xDEADBEEF + +/* Placeholder for storing PLL mode */ +clk_mode_mpu_val: + .word 0xDEADBEEF +clk_mode_per_val: + .word 0xDEADBEEF +clk_mode_disp_val: + .word 0xDEADBEEF +clk_mode_ddr_val: + .word 0xDEADBEEF +clk_mode_core_val: + .word 0xDEADBEEF + + .align 3 +ENTRY(am33xx_do_wfi_sz) + .word . - am33xx_do_wfi +
Signature · 1 line
1.7.0.4
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
In reply to Vaibhav BediaAM335x supports various low power modes as documented in section 8.1.4.3 of the AM335x TRM which is available @ http://www.ti.com/litv/pdf/spruh73f
DeepSleep0 mode offers the lowest power mode with limited wakeup sources without a system reboot and is mapped as the suspend state in the kernel. In this state, MPU and PER domains are turned off with the internal RAM held in retention to facilitate resume process. As part of the boot process, the assembly code is copied over to OCMCRAM using the OMAP SRAM code.
AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU in DeepSleep0 entry and exit. WKUP_M3 takes care of the clockdomain and powerdomain transitions based on the intended low power state. MPU needs to load the appropriate WKUP_M3 binary onto the WKUP_M3 memory space before it can leverage any of the PM features like DeepSleep.
The IPC mechanism between MPU and WKUP_M3 uses a mailbox sub-module and 8 IPC registers in the Control module. MPU uses the assigned Mailbox for issuing an interrupt to WKUP_M3 which then goes and checks the IPC registers for the payload. WKUP_M3 has the ability to trigger on interrupt to MPU by executing the "sev" instruction.
In the current implementation when the suspend process is initiated MPU interrupts the WKUP_M3 to let it know about the intent of entering DeepSleep0 and waits for an ACK. When the ACK is received MPU continues with its suspend process to suspend all the drivers and then jumps to assembly in OCMC RAM. The assembly code puts the PLLs in bypass, puts the external RAM in self-refresh mode and then finally execute the WFI instruction. Execution of the WFI instruction triggers another interrupt to the WKUP_M3 which then continues wiht the power down sequence wherein the clockdomain and powerdomain transition takes place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt lines for the wakeup sources. WFI execution on WKUP_M3 causes the hardware to disable the main oscillator of the SoC.
When a wakeup event occurs, WKUP_M3 starts the power-up sequence by switching on the power domains and finally enabling the clock to MPU. Since the MPU gets powered down as part of the sleep sequence in the resume path ROM code starts executing. The ROM code detects a wakeup from sleep and then jumps to the resume location in OCMC which was populated in one of the IPC registers as part of the suspend sequence.
The low level code in OCMC relocks the PLLs, enables access to external RAM and then jumps to the cpu_resume code of the kernel to finish the resume process.
---v1->v2:
Move assembly code addition, control module access and hookup in OMAP PM framework in separate patches. Address other comments from Kevin Hilman and Santosh Shilimkar on v1. The discussion on v1 is present @
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129979.html
Note: The mailbox change will need slight rework once the driver is finalized.
arch/arm/mach-omap2/pm33xx.c | 469 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/pm33xx.h | 56 +++++ 2 files changed, 525 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-omap2/pm33xx.c create mode 100644 arch/arm/mach-omap2/pm33xx.h
arch/arm/mach-omap2/pm33xx.c new file +469 -0
@@ -0,0 +1,469 @@ +/* +* AM33XX Power Management Routines +* +* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ +* Vaibhav Bedia <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/firmware.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/suspend.h> +#include <linux/completion.h> +#include <linux/module.h> +#include <linux/mailbox.h> +#include <linux/interrupt.h> + +#include <asm/suspend.h> +#include <asm/proc-fns.h> +#include <asm/sizes.h> +#include <asm/fncpy.h> +#include <asm/system_misc.h> + +#include "pm.h" +#include "cm33xx.h" +#include "pm33xx.h" +#include "control.h" +#include "clockdomain.h" +#include "powerdomain.h" +#include "omap_hwmod.h" +#include "omap_device.h" +#include "soc.h" +#include "sram.h" + +void (*am33xx_do_wfi_sram)(void ); + +static void __iomem *am33xx_emif_base; +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm; +static struct clockdomain *gfx_l4ls_clkdm; +static struct omap_hwmod *usb_oh, *cpsw_oh, *tptc0_oh, *tptc1_oh, *tptc2_oh; +static struct wkup_m3_context *wkup_m3; + +static DECLARE_COMPLETION (wkup_m3_sync); + +#ifdef CONFIG_SUSPEND +static int am33xx_do_sram_idle (long unsigned int unused) +{ +am33xx_do_wfi_sram (); +return 0 ; +} + +static int am33xx_pm_suspend (void ) +{ +int status, ret =0 ; + +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled. To ensure +* that there no issues with or without the drivers being compiled +* in the kernel, we forcefully put these IPs to idle. +*/ +omap_hwmod_enable (usb_oh); +omap_hwmod_enable (tptc0_oh); +omap_hwmod_enable (tptc1_oh); +omap_hwmod_enable (tptc2_oh); +omap_hwmod_enable (cpsw_oh); + +omap_hwmod_idle (usb_oh); +omap_hwmod_idle (tptc0_oh); +omap_hwmod_idle (tptc1_oh); +omap_hwmod_idle (tptc2_oh); +omap_hwmod_idle (cpsw_oh); + +/* Try to put GFX to sleep */ +pwrdm_set_next_fpwrst (gfx_pwrdm,PWRDM_FUNC_PWRST_OFF ); + + ret =cpu_suspend (0 , am33xx_do_sram_idle); + + status =pwrdm_read_fpwrst (gfx_pwrdm); +if (status !=PWRDM_FUNC_PWRST_OFF ) +pr_err ("GFX domain did not transition\n" ); +else +pr_info ("GFX domain entered low power state\n" ); + +/* +* GFX_L4LS clock domain needs to be woken up to +* ensure thet L4LS clock domain does not get stuck in transition +* If that happens L3 module does not get disabled, thereby leading +* to PER power domain transition failing +* +* The clock framework should take care of ensuring +* that the clock domain is in the right state when +* GFX driver is active. +*/ +clkdm_wakeup (gfx_l4ls_clkdm); +clkdm_sleep (gfx_l4ls_clkdm); + +if (ret) { +pr_err ("Kernel suspend failure\n" ); + }else { + status =omap_ctrl_readl (AM33XX_CONTROL_IPC_MSG_REG1 ); + status &=IPC_RESP_MASK ; + status >>=__ffs (IPC_RESP_MASK ); + +switch (status) { +case 0 : +pr_info ("Successfully put all powerdomains to target state\n" ); +/* +* XXX: Leads to loss of logic state in PER power domain +* Use SOC specific ops for this? +*/ +break ; +case 1 : +pr_err ("Could not transition all powerdomains to target state\n" ); + ret =-1 ; +break ; +default : +pr_err ("Something went wrong :(\nStatus = %d\n" , + status); + ret =-1 ; + } + } + +return ret; +} + +static int am33xx_pm_enter (suspend_state_t suspend_state) +{ +int ret =0 ; + +switch (suspend_state) { +case PM_SUSPEND_STANDBY : +case PM_SUSPEND_MEM : + ret =am33xx_pm_suspend (); +break ; +default : + ret = -EINVAL ; + } + +return ret; +} + +static int am33xx_pm_begin (suspend_state_t state) +{ +int ret =0 ; +struct mailbox_msg dummy_msg; + +disable_hlt (); + +MAILBOX_FILL_HEADER_MSG (dummy_msg,0xABCDABCD ); + + wkup_m3->ipc_data.sleep_mode =IPC_CMD_DS0 ; + wkup_m3->ipc_data.param1 =DS_IPC_DEFAULT ; + wkup_m3->ipc_data.param2 =DS_IPC_DEFAULT ; + +am33xx_wkup_m3_ipc_cmd (&wkup_m3->ipc_data); + + wkup_m3->state =M3_STATE_MSG_FOR_LP ; + +mailbox_enable_irq (wkup_m3->mbox,IRQ_RX ); + + ret =mailbox_msg_send (wkup_m3->mbox, &dummy_msg); +if (ret) { +pr_err ("A8<->CM3 MSG for LP failed\n" ); +am33xx_m3_state_machine_reset (); + ret =-1 ; + } + +/* Give some time to M3 to respond. 500msec is a random value here */ +if (!wait_for_completion_timeout (&wkup_m3_sync, +msecs_to_jiffies (500 ))) { +pr_err ("A8<->CM3 sync failure\n" ); +am33xx_m3_state_machine_reset (); + ret =-1 ; + }else { +pr_debug ("Message sent for entering DeepSleep mode\n" ); +mailbox_disable_irq (wkup_m3->mbox,IRQ_RX ); + } + +return ret; +} + +static void am33xx_pm_end (void ) +{ +mailbox_enable_irq (wkup_m3->mbox,IRQ_RX ); + +am33xx_m3_state_machine_reset (); + +enable_hlt (); + +return ; +} + +static const struct platform_suspend_ops am33xx_pm_ops = { + .begin = am33xx_pm_begin, + .end = am33xx_pm_end, + .enter = am33xx_pm_enter, + .valid = suspend_valid_only_mem, +}; + +static void am33xx_m3_state_machine_reset (void ) +{ +int ret =0 ; +struct mailbox_msg dummy_msg; + +MAILBOX_FILL_HEADER_MSG (dummy_msg,0xABCDABCD ); + + wkup_m3->ipc_data.sleep_mode =IPC_CMD_RESET ; + wkup_m3->ipc_data.param1 =DS_IPC_DEFAULT ; + wkup_m3->ipc_data.param2 =DS_IPC_DEFAULT ; + +am33xx_wkup_m3_ipc_cmd (&wkup_m3->ipc_data); + + wkup_m3->state =M3_STATE_MSG_FOR_RESET ; + + ret =mailbox_msg_send (wkup_m3->mbox, &dummy_msg); +if (!ret) { +pr_debug ("Message sent for resetting M3 state machine\n" ); +/* Give some to M3 to respond. 500msec is a random value here */ +if (!wait_for_completion_timeout (&wkup_m3_sync, +msecs_to_jiffies (500 ))) +pr_err ("A8<->CM3 sync failure\n" ); + }else { +pr_err ("Could not reset M3 state machine!!!\n" ); + wkup_m3->state =M3_STATE_UNKNOWN ; + } +} +#endif /* CONFIG_SUSPEND */ + +/* +* Dummy notifier for the mailbox +* XXX: Get rid of this requirement once the MBX driver has been finalized +*/ +static int wkup_mbox_msg (struct notifier_block *self,unsigned long len, +void *msg) +{ +return 0 ; +} + +static struct notifier_block wkup_mbox_notifier = { + .notifier_call = wkup_mbox_msg, +}; + +static irqreturn_t wkup_m3_txev_handler (int irq,void *unused) +{ +am33xx_txev_eoi (); + +switch (wkup_m3->state) { +case M3_STATE_RESET : + wkup_m3->state =M3_STATE_INITED ; +break ; +case M3_STATE_MSG_FOR_RESET : + wkup_m3->state =M3_STATE_INITED ; +mailbox_rx_flush (wkup_m3->mbox); +complete (&wkup_m3_sync); +break ; +case M3_STATE_MSG_FOR_LP : +mailbox_rx_flush (wkup_m3->mbox); +complete (&wkup_m3_sync); +break ; +case M3_STATE_UNKNOWN : +pr_err ("IRQ %d with WKUP_M3 in unknown state\n" , irq); +mailbox_rx_flush (wkup_m3->mbox); +return IRQ_NONE ; + } + +am33xx_txev_enable (); +return IRQ_HANDLED ; +} + +static void am33xx_pm_firmware_cb (const struct firmware *fw,void *context) +{ +struct wkup_m3_context *wkup_m3_context = context; +struct platform_device *pdev =to_platform_device (wkup_m3_context->dev); +int ret =0 ; + +/* no firmware found */ +if (!fw) { +dev_err (wkup_m3_context->dev,"request_firmware failed\n" ); + goto err; + } + +memcpy ((void *)wkup_m3_context->code, fw->data, fw->size); +pr_info ("Copied the M3 firmware to UMEM\n" ); + + wkup_m3->state =M3_STATE_RESET ; + + ret =omap_device_deassert_hardreset (pdev,"wkup_m3" ); +if (ret) { +pr_err ("Could not deassert the reset for WKUP_M3\n" ); + goto err; + }else { +#ifdef CONFIG_SUSPEND +suspend_set_ops (&am33xx_pm_ops); +/* +* Physical resume address to be used by ROM code +*/ + wkup_m3->ipc_data.resume_addr = (AM33XX_OCMC_END - + am33xx_do_wfi_sz + am33xx_resume_offset +0x4 ); +#endif +return ; + } + +err: +mailbox_put (wkup_m3_context->mbox, &wkup_mbox_notifier); +} + +static int wkup_m3_init (void ) +{ +int irq, ret =0 ; +struct resource *mem; +struct platform_device *pdev =to_platform_device (wkup_m3->dev); + +omap_device_enable_hwmods (to_omap_device (pdev)); + +/* Reserve the MBOX for sending messages to M3 */ + wkup_m3->mbox =mailbox_get ("wkup_m3" , &wkup_mbox_notifier); +if (IS_ERR (wkup_m3->mbox)) { +pr_err ("Could not reserve mailbox for A8->M3 IPC\n" ); + ret = -ENODEV ; + goto exit; + } + + irq =platform_get_irq (pdev,0 ); +if (!irq) { +dev_err (wkup_m3->dev,"no irq resource\n" ); + ret = -ENXIO ; + goto err; + } + + mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!mem) { +dev_err (wkup_m3->dev,"no memory resource\n" ); + ret = -ENXIO ; + goto err; + } + + wkup_m3->code =devm_request_and_ioremap (wkup_m3->dev, mem); +if (!wkup_m3->code) { +dev_err (wkup_m3->dev,"could not ioremap\n" ); + ret = -EADDRNOTAVAIL ; + goto err; + } + + ret =devm_request_irq (wkup_m3->dev, irq, wkup_m3_txev_handler, +IRQF_DISABLED ,"wkup_m3_txev" ,NULL ); +if (ret) { +dev_err (wkup_m3->dev,"request_irq failed\n" ); + goto err; + }else { +am33xx_txev_enable (); + } + +pr_info ("Trying to load am335x-pm-firmware.bin" ); + +/* We don't want to delay boot */ +request_firmware_nowait (THIS_MODULE ,0 ,"am335x-pm-firmware.bin" , + wkup_m3->dev,GFP_KERNEL , wkup_m3, + am33xx_pm_firmware_cb); +return 0 ; + +err: +mailbox_put (wkup_m3->mbox, &wkup_mbox_notifier); +exit: +return ret; +} + +/* +* Push the minimal suspend-resume code to SRAM +*/ +void am33xx_push_sram_idle (void ) +{ + am33xx_do_wfi_sram = (void *)omap_sram_push + (am33xx_do_wfi, am33xx_do_wfi_sz); +} + +static int __init am33xx_map_emif (void ) +{ + am33xx_emif_base =ioremap (AM33XX_EMIF_BASE ,SZ_32K ); + +if (!am33xx_emif_base) +return -ENOMEM ; + +return 0 ; +} + +void __iomem *am33xx_get_emif_base (void ) +{ +return am33xx_emif_base; +} + +int __init am33xx_pm_init (void ) +{ +int ret; + +if (!soc_is_am33xx ()) +return -ENODEV ; + +pr_info ("Power Management for AM33XX family\n" ); + +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled +*/ + usb_oh =omap_hwmod_lookup ("usb_otg_hs" ); + tptc0_oh =omap_hwmod_lookup ("tptc0" ); + tptc1_oh =omap_hwmod_lookup ("tptc1" ); + tptc2_oh =omap_hwmod_lookup ("tptc2" ); + cpsw_oh =omap_hwmod_lookup ("cpgmac0" ); + + gfx_pwrdm =pwrdm_lookup ("gfx_pwrdm" ); + per_pwrdm =pwrdm_lookup ("per_pwrdm" ); + + gfx_l4ls_clkdm =clkdm_lookup ("gfx_l4ls_gfx_clkdm" ); + +if ((!usb_oh) || (!tptc0_oh) || (!tptc1_oh) || (!tptc2_oh) || + (!cpsw_oh) || (!gfx_pwrdm) || (!per_pwrdm) || + (!gfx_l4ls_clkdm)) { + ret = -ENODEV ; + goto err; + } + + wkup_m3 =kzalloc (sizeof (struct wkup_m3_context ),GFP_KERNEL ); +if (!wkup_m3) { +pr_err ("Memory allocation failed\n" ); + ret = -ENOMEM ; + goto err; + } + + ret =am33xx_map_emif (); +if (ret) { +pr_err ("Could not ioremap EMIF\n" ); + goto err; + } + + (void )clkdm_for_each (omap_pm_clkdms_setup,NULL ); + +/* CEFUSE domain can be turned off post bootup */ + cefuse_pwrdm =pwrdm_lookup ("cefuse_pwrdm" ); +if (cefuse_pwrdm) +pwrdm_set_next_fpwrst (cefuse_pwrdm,PWRDM_FUNC_PWRST_OFF ); +else +pr_err ("Failed to get cefuse_pwrdm\n" ); + + wkup_m3->dev =omap_device_get_by_hwmod_name ("wkup_m3" ); + + ret =wkup_m3_init (); +if (ret) +pr_err ("Could not initialise firmware loading\n" ); + +err: +return ret; +}
arch/arm/mach-omap2/pm33xx.h new file +56 -0
56 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"V" == Vaibhav Bedia <[email protected]> writes:
Hi,
V> +static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context) V> +{
V> + struct wkup_m3_context *wkup_m3_context = context;
V> + struct platform_device *pdev = to_platform_device(wkup_m3_context->dev);
V> + int ret = 0;
V> +
V> + /* no firmware found */
V> + if (!fw) {
V> + dev_err(wkup_m3_context->dev, "request_firmware failed\n");
V> + goto err;
V> + }
V> +
V> + memcpy((void *)wkup_m3_context->code, fw->data, fw->size);
A size check would be good. I don't know much about the finer details about the m3 and how it is connected, but don't you need to ensure data is flushed before resetting the m3?
V> + pr_info("Copied the M3 firmware to UMEM\n");
V> +
V> + wkup_m3->state = M3_STATE_RESET;
V> +
V> + ret = omap_device_deassert_hardreset(pdev, "wkup_m3");
V> + if (ret) {
V> + pr_err("Could not deassert the reset for WKUP_M3\n");
V> + goto err;
V> + } else {
V> +#ifdef CONFIG_SUSPEND
V> + suspend_set_ops(&am33xx_pm_ops);
V> + /*
V> + * Physical resume address to be used by ROM code
V> + */
V> + wkup_m3->ipc_data.resume_addr = (AM33XX_OCMC_END -
V> + am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
V> +#endif
V> + return;
V> + }
V> +
V> +err:
V> + mailbox_put(wkup_m3_context->mbox, &wkup_mbox_notifier);
V> +}
Signature · 1 line
Bye, Peter Korsgaard
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
Hi Peter,
Quoted 18 lines · Peter Korsgaard
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"V" == Vaibhav Bedia <[email protected]> writes:
Hi,
V> +static void
am33xx_pm_firmware_cb(const struct firmware *fw, void *context)V> +{
V> + structwkup_m3_context*wkup_m3_context= context;
V> + structplatform_device*pdev =to_platform_device(wkup_m3_context->dev);
V> + int ret = 0;
V> +
V> + /* no firmware found */
V> + if (!fw) {
V> +dev_err(wkup_m3_context->dev, "request_firmware failed\n");
V> + goto err;
V> + }
V> +
V> +memcpy((void *)wkup_m3_context->code, fw->data, fw->size);
Quoted 4 lines
A size check would be good. I don't know much about the finer details about the m3 and how it is connected, but don't you need to ensure data is flushed before resetting the m3?
Will add the reg property in the next version. The wkup-m3 memory is coming via ioremap() so AFAIK it should be ok. I realized that I do need to replace the memcpy() with memcpy_toio() here.
Thanks,
Vaibhav
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"V" == Bedia, Vaibhav <[email protected]> writes:
Hi,
V> + memcpy((void *)wkup_m3_context->code, fw->data, fw->size);
Quoted 5 lines
Quoted 5 lines
A size check would be good. I don't know much about the finer details about the m3 and how it is connected, but don't you need to ensure data is flushed before resetting the m3?
V> Will add the reg property in the next version. The wkup-m3 memory is V> coming via ioremap() so AFAIK it should be ok. I realized that I do V> need to replace the memcpy() with memcpy_toio() here.
Ok, thanks.
Signature · 1 line
Bye, Peter Korsgaard
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
In reply to Vaibhav BediaHi Viabhav,
Quoted 53 lines · Vaibhav Bedia
AM335x supports various low power modes as documented in section 8.1.4.3 of the AM335x TRM which is available @ http://www.ti.com/litv/pdf/spruh73f
DeepSleep0 mode offers the lowest power mode with limited wakeup sources without a system reboot and is mapped as the suspend state in the kernel. In this state, MPU and PER domains are turned off with the internal RAM held in retention to facilitate resume process. As part of the boot process, the assembly code is copied over to OCMCRAM using the OMAP SRAM code.
AM335x has a Cortex-M3 (
WKUP_M3) which assists the MPU in DeepSleep0 entry and exit.WKUP_M3takes care of the clockdomain and powerdomain transitions based on the intended low power state. MPU needs to load the appropriateWKUP_M3binary onto theWKUP_M3memory space before it can leverage any of the PM features like DeepSleep.The IPC mechanism between MPU and
WKUP_M3uses a mailbox sub-module and 8 IPC registers in the Control module. MPU uses the assigned Mailbox for issuing an interrupt toWKUP_M3which then goes and checks the IPC registers for the payload.WKUP_M3has the ability to trigger on interrupt to MPU by executing the "sev" instruction.In the current implementation when the suspend process is initiated MPU interrupts the
WKUP_M3to let it know about the intent of entering DeepSleep0 and waits for an ACK. When the ACK is received MPU continues with its suspend process to suspend all the drivers and then jumps to assembly in OCMC RAM. The assembly code puts the PLLs in bypass, puts the external RAM in self-refresh mode and then finally execute the WFI instruction. Execution of the WFI instruction triggers another interrupt to theWKUP_M3which then continues wiht the power down sequence wherein the clockdomain and powerdomain transition takes place. As part of the sleep sequence,WKUP_M3unmasks the interrupt lines for the wakeup sources. WFI execution onWKUP_M3causes the hardware to disable the main oscillator of the SoC.When a wakeup event occurs,
WKUP_M3starts the power-up sequence by switching on the power domains and finally enabling the clock to MPU. Since the MPU gets powered down as part of the sleep sequence in the resume path ROM code starts executing. The ROM code detects a wakeup from sleep and then jumps to the resume location in OCMC which was populated in one of the IPC registers as part of the suspend sequence.The low level code in OCMC relocks the PLLs, enables access to external RAM and then jumps to the
cpu_resumecode of the kernel to finish the resume process.
Quoted 6 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>
Thanks for the updated series here, and my apologies for the delayed review.
I've just had a quick scan of this patch, and have a few general comments, I'll probably have a few more comments after a closer look.
Quoted 59 lines
---
v1->v2:
Move assembly code addition, control module access and hookup in OMAP PM framework in separate patches. Address other comments from Kevin Hilman and Santosh Shilimkar on v1. The discussion on v1 is present @
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129979.html
Note: The mailbox change will need slight rework once the driver is finalized.arch/arm/mach-omap2/pm33xx.c | 469 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/pm33xx.h | 56 +++++ 2 files changed, 525 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-omap2/pm33xx.c create mode 100644 arch/arm/mach-omap2/pm33xx.harch/arm/mach-omap2/pm33xx.c new file +37
-0@@ -0,0 +1,469 @@ +/* +* AM33XX Power Management Routines +* +* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ +* Vaibhav Bedia <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/firmware.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/suspend.h> +#include <linux/completion.h> +#include <linux/module.h> +#include <linux/mailbox.h> +#include <linux/interrupt.h> + +#include <asm/suspend.h> +#include <asm/proc-fns.h> +#include <asm/sizes.h> +#include <asm/fncpy.h> +#include <asm/system_misc.h> + +#include "pm.h" +#include "cm33xx.h"
arch/arm/mach-omap2/pm33xx.c line 47
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+#include "pm33xx.h" +#include "control.h" +#include "clockdomain.h" +#include "powerdomain.h" +#include "omap_hwmod.h" +#include "omap_device.h" +#include "soc.h" +#include "sram.h" + +void (*am33xx_do_wfi_sram)(void );
static?
Quoted 28 lines
arch/arm/mach-omap2/pm33xx.c new file +28
-0+static void __iomem *am33xx_emif_base; +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm; +static struct clockdomain *gfx_l4ls_clkdm; +static struct omap_hwmod *usb_oh, *cpsw_oh, *tptc0_oh, *tptc1_oh, *tptc2_oh; +static struct wkup_m3_context *wkup_m3; + +static DECLARE_COMPLETION (wkup_m3_sync); + +#ifdef CONFIG_SUSPEND +static int am33xx_do_sram_idle (long unsigned int unused) +{ +am33xx_do_wfi_sram (); +return 0 ; +} + +static int am33xx_pm_suspend (void ) +{ +int status, ret =0 ; + +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled. To ensure +* that there no issues with or without the drivers being compiled +* in the kernel, we forcefully put these IPs to idle. +*/ +omap_hwmod_enable (usb_oh);
arch/arm/mach-omap2/pm33xx.c line 86
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+omap_hwmod_enable (tptc0_oh); +omap_hwmod_enable (tptc1_oh); +omap_hwmod_enable (tptc2_oh); +omap_hwmod_enable (cpsw_oh); + +omap_hwmod_idle (usb_oh); +omap_hwmod_idle (tptc0_oh); +omap_hwmod_idle (tptc1_oh); +omap_hwmod_idle (tptc2_oh); +omap_hwmod_idle (cpsw_oh);
I think I asked this in my review of v1, but why does this need to happen on every suspend attempt?
This should happen once on init, which will handle the case where there are no drivers, and if there are drivers, then the drivers need to handle this properly.
I don't like this happening here on every suspend attempt, because it will surely hide bugs where drivers are not properly managing their own PM.
arch/arm/mach-omap2/pm33xx.c line 97
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* Try to put GFX to sleep */ +pwrdm_set_next_fpwrst (gfx_pwrdm,PWRDM_FUNC_PWRST_OFF ); + + ret =cpu_suspend (0 , am33xx_do_sram_idle); + status =pwrdm_read_fpwrst (gfx_pwrdm); +if (status !=PWRDM_FUNC_PWRST_OFF ) +pr_err ("GFX domain did not transition\n" ); +else +pr_info ("GFX domain entered low power state\n" );
Do you really want this printed every time?
arch/arm/mach-omap2/pm33xx.c line 107
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* +* GFX_L4LS clock domain needs to be woken up to +* ensure thet L4LS clock domain does not get stuck in transition +* If that happens L3 module does not get disabled, thereby leading +* to PER power domain transition failing +* +* The clock framework should take care of ensuring +* that the clock domain is in the right state when +* GFX driver is active.
Are you suggesting that the clock framework is not doing this already?
arch/arm/mach-omap2/pm33xx.c line 115
Quoted 8 lines
arch/arm/mach-omap2/pm33xx.c new file +8
-0+*/ +clkdm_wakeup (gfx_l4ls_clkdm); +clkdm_sleep (gfx_l4ls_clkdm); + +if (ret) { +pr_err ("Kernel suspend failure\n" ); + }else { + status =omap_ctrl_readl (AM33XX_CONTROL_IPC_MSG_REG1 );
We're trying to git rid of direct control module register access, and consolidate them into control.c (for an eventual move to a driver.) I see you've mostly done that in other parts of the series, but here's one that needs to move.
arch/arm/mach-omap2/pm33xx.c line 125
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+ status &=IPC_RESP_MASK ; + status >>=__ffs (IPC_RESP_MASK ); + +switch (status) { +case 0 : +pr_info ("Successfully put all powerdomains to target state\n" ); +/* +* XXX: Leads to loss of logic state in PER power domain +* Use SOC specific ops for this? +*/
huh?
Quoted 48 lines
arch/arm/mach-omap2/pm33xx.c new file +48
-0+break ; +case 1 : +pr_err ("Could not transition all powerdomains to target state\n" ); + ret =-1 ; +break ; +default : +pr_err ("Something went wrong :(\nStatus = %d\n" , + status); + ret =-1 ; + } + } + +return ret; +} + +static int am33xx_pm_enter (suspend_state_t suspend_state) +{ +int ret =0 ; + +switch (suspend_state) { +case PM_SUSPEND_STANDBY : +case PM_SUSPEND_MEM : + ret =am33xx_pm_suspend (); +break ; +default : + ret = -EINVAL ; + } + +return ret; +} + +static int am33xx_pm_begin (suspend_state_t state) +{ +int ret =0 ; +struct mailbox_msg dummy_msg; + +disable_hlt (); + +MAILBOX_FILL_HEADER_MSG (dummy_msg,0xABCDABCD ); + + wkup_m3->ipc_data.sleep_mode =IPC_CMD_DS0 ; + wkup_m3->ipc_data.param1 =DS_IPC_DEFAULT ; + wkup_m3->ipc_data.param2 =DS_IPC_DEFAULT ; + +am33xx_wkup_m3_ipc_cmd (&wkup_m3->ipc_data); + + wkup_m3->state =M3_STATE_MSG_FOR_LP ; +
arch/arm/mach-omap2/pm33xx.c line 183
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+mailbox_enable_irq (wkup_m3->mbox,IRQ_RX ); + + ret =mailbox_msg_send (wkup_m3->mbox, &dummy_msg); +if (ret) { +pr_err ("A8<->CM3 MSG for LP failed\n" ); +am33xx_m3_state_machine_reset (); + ret =-1 ; + } + +/* Give some time to M3 to respond. 500msec is a random value here */
random? really?
Quoted 53 lines
arch/arm/mach-omap2/pm33xx.c new file +53
-0+if (!wait_for_completion_timeout (&wkup_m3_sync, +msecs_to_jiffies (500 ))) { +pr_err ("A8<->CM3 sync failure\n" ); +am33xx_m3_state_machine_reset (); + ret =-1 ; + }else { +pr_debug ("Message sent for entering DeepSleep mode\n" ); +mailbox_disable_irq (wkup_m3->mbox,IRQ_RX ); + } + +return ret; +} + +static void am33xx_pm_end (void ) +{ +mailbox_enable_irq (wkup_m3->mbox,IRQ_RX ); + +am33xx_m3_state_machine_reset (); + +enable_hlt (); + +return ; +} + +static const struct platform_suspend_ops am33xx_pm_ops = { + .begin = am33xx_pm_begin, + .end = am33xx_pm_end, + .enter = am33xx_pm_enter, + .valid = suspend_valid_only_mem, +}; + +static void am33xx_m3_state_machine_reset (void ) +{ +int ret =0 ; +struct mailbox_msg dummy_msg; + +MAILBOX_FILL_HEADER_MSG (dummy_msg,0xABCDABCD ); + + wkup_m3->ipc_data.sleep_mode =IPC_CMD_RESET ; + wkup_m3->ipc_data.param1 =DS_IPC_DEFAULT ; + wkup_m3->ipc_data.param2 =DS_IPC_DEFAULT ; + +am33xx_wkup_m3_ipc_cmd (&wkup_m3->ipc_data); + + wkup_m3->state =M3_STATE_MSG_FOR_RESET ; + + ret =mailbox_msg_send (wkup_m3->mbox, &dummy_msg); +if (!ret) { +pr_debug ("Message sent for resetting M3 state machine\n" ); +/* Give some to M3 to respond. 500msec is a random value here */ +if (!wait_for_completion_timeout (&wkup_m3_sync, +msecs_to_jiffies (500 ))) +pr_err ("A8<->CM3 sync failure\n" );
arch/arm/mach-omap2/pm33xx.c line 246
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+ } else { +pr_err ("Could not reset M3 state machine!!!\n" ); + wkup_m3->state =M3_STATE_UNKNOWN ; + } +} +#endif /* CONFIG_SUSPEND */ + +/* +* Dummy notifier for the mailbox +* XXX: Get rid of this requirement once the MBX driver has been finalized
IIRC, I suggested a trivial fix to the mailbox driver that would remove the need for this, which could be done today.
Quoted 72 lines
arch/arm/mach-omap2/pm33xx.c new file +72
-0+*/ +static int wkup_mbox_msg (struct notifier_block *self,unsigned long len, +void *msg) +{ +return 0 ; +} + +static struct notifier_block wkup_mbox_notifier = { + .notifier_call = wkup_mbox_msg, +}; + +static irqreturn_t wkup_m3_txev_handler (int irq,void *unused) +{ +am33xx_txev_eoi (); + +switch (wkup_m3->state) { +case M3_STATE_RESET : + wkup_m3->state =M3_STATE_INITED ; +break ; +case M3_STATE_MSG_FOR_RESET : + wkup_m3->state =M3_STATE_INITED ; +mailbox_rx_flush (wkup_m3->mbox); +complete (&wkup_m3_sync); +break ; +case M3_STATE_MSG_FOR_LP : +mailbox_rx_flush (wkup_m3->mbox); +complete (&wkup_m3_sync); +break ; +case M3_STATE_UNKNOWN : +pr_err ("IRQ %d with WKUP_M3 in unknown state\n" , irq); +mailbox_rx_flush (wkup_m3->mbox); +return IRQ_NONE ; + } + +am33xx_txev_enable (); +return IRQ_HANDLED ; +} + +static void am33xx_pm_firmware_cb (const struct firmware *fw,void *context) +{ +struct wkup_m3_context *wkup_m3_context = context; +struct platform_device *pdev =to_platform_device (wkup_m3_context->dev); +int ret =0 ; + +/* no firmware found */ +if (!fw) { +dev_err (wkup_m3_context->dev,"request_firmware failed\n" ); + goto err; + } + +memcpy ((void *)wkup_m3_context->code, fw->data, fw->size); +pr_info ("Copied the M3 firmware to UMEM\n" ); + + wkup_m3->state =M3_STATE_RESET ; + + ret =omap_device_deassert_hardreset (pdev,"wkup_m3" ); +if (ret) { +pr_err ("Could not deassert the reset for WKUP_M3\n" ); + goto err; + }else { +#ifdef CONFIG_SUSPEND +suspend_set_ops (&am33xx_pm_ops); +/* +* Physical resume address to be used by ROM code +*/ + wkup_m3->ipc_data.resume_addr = (AM33XX_OCMC_END - + am33xx_do_wfi_sz + am33xx_resume_offset +0x4 ); +#endif +return ; + } + +err:
arch/arm/mach-omap2/pm33xx.c line 328
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+mailbox_put (wkup_m3_context->mbox, &wkup_mbox_notifier); +} + +static int wkup_m3_init (void ) +{ +int irq, ret =0 ; +struct resource *mem; +struct platform_device *pdev =to_platform_device (wkup_m3->dev); + +omap_device_enable_hwmods (to_omap_device (pdev));
Why not omap_device_enable(pdev) ?
Quoted 42 lines
arch/arm/mach-omap2/pm33xx.c new file +42
-0+ +/* Reserve the MBOX for sending messages to M3 */ + wkup_m3->mbox =mailbox_get ("wkup_m3" , &wkup_mbox_notifier); +if (IS_ERR (wkup_m3->mbox)) { +pr_err ("Could not reserve mailbox for A8->M3 IPC\n" ); + ret = -ENODEV ; + goto exit; + } + + irq =platform_get_irq (pdev,0 ); +if (!irq) { +dev_err (wkup_m3->dev,"no irq resource\n" ); + ret = -ENXIO ; + goto err; + } + + mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!mem) { +dev_err (wkup_m3->dev,"no memory resource\n" ); + ret = -ENXIO ; + goto err; + } + + wkup_m3->code =devm_request_and_ioremap (wkup_m3->dev, mem); +if (!wkup_m3->code) { +dev_err (wkup_m3->dev,"could not ioremap\n" ); + ret = -EADDRNOTAVAIL ; + goto err; + } + + ret =devm_request_irq (wkup_m3->dev, irq, wkup_m3_txev_handler, +IRQF_DISABLED ,"wkup_m3_txev" ,NULL ); +if (ret) { +dev_err (wkup_m3->dev,"request_irq failed\n" ); + goto err; + }else { +am33xx_txev_enable (); + } + +pr_info ("Trying to load am335x-pm-firmware.bin" ); + +/* We don't want to delay boot */
arch/arm/mach-omap2/pm33xx.c line 380
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+request_firmware_nowait (THIS_MODULE ,0 ,"am335x-pm-firmware.bin" , + wkup_m3->dev,GFP_KERNEL , wkup_m3, + am33xx_pm_firmware_cb); +return 0 ; + +err: +mailbox_put (wkup_m3->mbox, &wkup_mbox_notifier); +exit: +return ret; +}
Kevin
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
Hi Kevin,
On Tue, Feb 12, 2013 at 06:57:50, Kevin Hilman wrote:
[...]
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ +void (*am33xx_do_wfi_sram)(void);static?
Will fix.
[...]
Quoted 24 lines
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+ +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled. To ensure +* that there no issues with or without the drivers being compiled +* in the kernel, we forcefully put these IPs to idle. +*/ +omap_hwmod_enable (usb_oh);arch/arm/mach-omap2/pm33xx.c line 86
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+omap_hwmod_enable (tptc0_oh); +omap_hwmod_enable (tptc1_oh); +omap_hwmod_enable (tptc2_oh); +omap_hwmod_enable (cpsw_oh); + +omap_hwmod_idle (usb_oh); +omap_hwmod_idle (tptc0_oh); +omap_hwmod_idle (tptc1_oh); +omap_hwmod_idle (tptc2_oh); +omap_hwmod_idle (cpsw_oh);I think I asked this in my review of v1, but why does this need to happen on every suspend attempt?
Quoted 7 lines
This should happen once on init, which will handle the case where there are no drivers, and if there are drivers, then the drivers need to handle this properly.
I don't like this happening here on every suspend attempt, because it will surely hide bugs where drivers are not properly managing their own PM.
By default these IPs don't have MSTANDBY asserted. When a low power transition happens, the peripheral power domain loses context and hence the forced MSTANDBY configuration in the IP is lost. To work around this problem we need to assert MSTANDBY in every suspend-resume iteration.
I agree that this might hide PM bugs in the driver but to solve this problem we need some mechanism for the PM code to know whether or not a driver is bound to the corresponding platform devices. Any suggestions on this?
Quoted 12 lines
arch/arm/mach-omap2/pm33xx.c line 97
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* Try to put GFX to sleep */ +pwrdm_set_next_fpwrst (gfx_pwrdm,PWRDM_FUNC_PWRST_OFF ); + + ret =cpu_suspend (0 , am33xx_do_sram_idle); + status =pwrdm_read_fpwrst (gfx_pwrdm); +if (status !=PWRDM_FUNC_PWRST_OFF ) +pr_err ("GFX domain did not transition\n" ); +else +pr_info ("GFX domain entered low power state\n" );Do you really want this printed every time?
Hmm... it could perhaps be clubbed with the overall status that's printed. I kept it here since the GFX power domain is completely under MPU control and hence this information would be useful in finding out if there's a problem with the GFX suspend-resume.
Quoted 12 lines
arch/arm/mach-omap2/pm33xx.c line 107
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* +* GFX_L4LS clock domain needs to be woken up to +* ensure thet L4LS clock domain does not get stuck in transition +* If that happens L3 module does not get disabled, thereby leading +* to PER power domain transition failing +* +* The clock framework should take care of ensuring +* that the clock domain is in the right state when +* GFX driver is active. Are you suggesting that the clock framework is not doing this already?
No. This clkdm_*() calls are here to work-around an issue that I observed when implementing suspend-resume. The force wakeup and sleep of the gfx_l4ls clock domain across every suspend-resume is something I don't think can be pushed to the clock framework.
Quoted 5 lines
Quoted 5 lines
arch/arm/mach-omap2/pm33xx.c new file +5
-0+*/ +clkdm_wakeup (gfx_l4ls_clkdm); +clkdm_sleep (gfx_l4ls_clkdm); + +if (ret) {
Quoted 8 lines
arch/arm/mach-omap2/pm33xx.c line 115
Quoted 3 lines
arch/arm/mach-omap2/pm33xx.c new file +3
-0+pr_err ("Kernel suspend failure\n" ); + }else { + status =omap_ctrl_readl (AM33XX_CONTROL_IPC_MSG_REG1 );We're trying to git rid of direct control module register access, and consolidate them into
control.c(for an eventual move to a driver.) I see you've mostly done that in other parts of the series, but here's one that needs to move.
Yes, I somehow missed this one. Will take care of it in the next version.
Quoted 14 lines
arch/arm/mach-omap2/pm33xx.c line 125
Quoted 11 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+ status &=IPC_RESP_MASK ; + status >>=__ffs (IPC_RESP_MASK ); + +switch (status) { +case 0 : +pr_info ("Successfully put all powerdomains to target state\n" ); +/* +* XXX: Leads to loss of logic state in PER power domain +* Use SOC specific ops for this? +*/ huh?
Ah... this is more of a TODO. There's no previous state entered information in the PRCM registers. So to ensure that the drivers get the right information when they check with the PM layer about the loss of context and hence the need to restore the registers, I need to update the logic and membank state counters for the PER power domain manually. I was thinking of leveraging the SoC specific power domain ops for doing this.
[...]
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ + /* Give some time to M3 to respond. 500msec is a random value here */random? really?
Sort of. I don't have any numbers from the h/w guys on the worst case delay in getting an interrupt from M3 to MPU. At the same time I want to handle the scenario where something goes wrong on the M3 side and it doesn't respond.
[...]
Quoted 8 lines
arch/arm/mach-omap2/pm33xx.c line 246
Quoted 4 lines
arch/arm/mach-omap2/pm33xx.c new file +4
-0+ +/* +* Dummy notifier for the mailbox +* XXX: Get rid of this requirement once the MBX driver has been finalized IIRC, I suggested a trivial fix to the mailbox driver that would remove the need for this, which could be done today.
Yes. I plan to do that once the mailbox code movement to drivers/ along with other changes to make it generic enough are finalized. It was adding in one more dependency and hence I kept this as a TODO in this version.
[...]
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c line 328
Quoted 7 lines
arch/arm/mach-omap2/pm33xx.c new file +7
-0+static int wkup_m3_init (void ) +{ +int irq, ret =0 ; +struct resource *mem; +struct platform_device *pdev =to_platform_device (wkup_m3->dev); + +omap_device_enable_hwmods (to_omap_device (pdev));Why not
omap_device_enable(pdev)?
The objective is to leverage the hwmod code to get the WKUP-M3 functional and not have OMAP runtime PM code coming in the way. Using omap_device_enable() triggers the following dev_warn() from omap_device_enable().
[ 2.033718] platform 44d00000.wkup_m3: omap_device_late_idle: enabled but no driver. Idling [ 2.042676] ------------[ cut here ]------------ [ 2.047572] WARNING: at arch/arm/mach-omap2/omap_hwmod.c:2187 _idle+0x164/0x1c0() [ 2.055459] omap_hwmod: wkup_m3: idle state can only be entered from enabled state [ 2.063435] Modules linked in: [ 2.066712] [<c001afe4>] (unwind_backtrace+0x0/0xf0) from [<c004380c>] (warn_slowpath_common+0x4c/0x64) [ 2.076626] [<c004380c>] (warn_slowpath_common+0x4c/0x64) from [<c00438b8>] (warn_slowpath_fmt+0x30/0x40) [ 2.086720] [<c00438b8>] (warn_slowpath_fmt+0x30/0x40) from [<c002aad0>] (_idle+0x164/0x1c0) [ 2.095624] [<c002aad0>] (_idle+0x164/0x1c0) from [<c002af98>] (omap_hwmod_idle+0x24/0x40) [ 2.104348] [<c002af98>] (omap_hwmod_idle+0x24/0x40) from [<c002bd60>] (omap_device_idle_hwmods+0x24/0x3c) [ 2.114536] [<c002bd60>] (omap_device_idle_hwmods+0x24/0x3c) from [<c002bf4c>] (_omap_device_deactivate+0x98/0x134) [ 2.125546] [<c002bf4c>] (_omap_device_deactivate+0x98/0x134) from [<c002c87c>] (omap_device_idle+0x28/0x54) [ 2.135921] [<c002c87c>] (omap_device_idle+0x28/0x54) from [<c06ec00c>] (omap_device_late_idle+0x44/0x54) [ 2.146025] [<c06ec00c>] (omap_device_late_idle+0x44/0x54) from [<c031f850>] (bus_for_each_dev+0x50/0x7c) [ 2.156120] [<c031f850>] (bus_for_each_dev+0x50/0x7c) from [<c06ebe10>] (omap_device_late_init+0x18/0x28) [ 2.166216] [<c06ebe10>] (omap_device_late_init+0x18/0x28) from [<c00086e4>] (do_one_initcall+0x34/0x180) [ 2.176314] [<c00086e4>] (do_one_initcall+0x34/0x180) from [<c06df8f8>] (kernel_init_freeable+0xfc/0x1cc) [ 2.186408] [<c06df8f8>] (kernel_init_freeable+0xfc/0x1cc) from [<c04d4b20>] (kernel_init+0x8/0xe4) [ 2.195962] [<c04d4b20>] (kernel_init+0x8/0xe4) from [<c0013410>] (ret_from_fork+0x14/0x24) [ 2.204905] ---[ end trace 8f61b319779f6e57 ]---
Regards,
Vaibhav
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
Quoted 41 lines · Vaibhav
Hi Kevin,
On Tue, Feb 12, 2013 at 06:57:50, Kevin Hilman wrote:
[...]Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ +void (*am33xx_do_wfi_sram)(void);static?
Will fix.
[...]
Quoted 28 lines
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+ +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled. To ensure +* that there no issues with or without the drivers being compiled +* in the kernel, we forcefully put these IPs to idle. +*/ +omap_hwmod_enable (usb_oh);arch/arm/mach-omap2/pm33xx.c line 86
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+omap_hwmod_enable (tptc0_oh); +omap_hwmod_enable (tptc1_oh); +omap_hwmod_enable (tptc2_oh); +omap_hwmod_enable (cpsw_oh); + +omap_hwmod_idle (usb_oh); +omap_hwmod_idle (tptc0_oh); +omap_hwmod_idle (tptc1_oh); +omap_hwmod_idle (tptc2_oh); +omap_hwmod_idle (cpsw_oh);I think I asked this in my review of v1, but why does this need to happen on every suspend attempt?
This should happen once on init, which will handle the case where there are no drivers, and if there are drivers, then the drivers need to handle this properly.
Quoted 5 lines
Quoted 3 lines
I don't like this happening here on every suspend attempt, because it will surely hide bugs where drivers are not properly managing their own PM.
By default these IPs don't have MSTANDBY asserted.
When you say "by default", I guess you mean after reset (and/or context loss), right?
Quoted 4 lines
When a low power transition happens, the peripheral power domain loses context and hence the forced MSTANDBY configuration in the IP is lost. To work around this problem we need to assert MSTANDBY in every suspend-resume iteration.
Yuck. More clever hardware. ;)
Quoted 3 lines
I agree that this might hide PM bugs in the driver but to solve this problem we need some mechanism for the PM code to know whether or not a driver is bound to the corresponding platform devices. Any suggestions on this?
Driver bound status can be tracked easily using bus notifiers. You can see an example in the omap_device core.
Quoted 13 lines
Quoted 12 lines
arch/arm/mach-omap2/pm33xx.c line 97
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* Try to put GFX to sleep */ +pwrdm_set_next_fpwrst (gfx_pwrdm,PWRDM_FUNC_PWRST_OFF ); + + ret =cpu_suspend (0 , am33xx_do_sram_idle); + status =pwrdm_read_fpwrst (gfx_pwrdm); +if (status !=PWRDM_FUNC_PWRST_OFF ) +pr_err ("GFX domain did not transition\n" ); +else +pr_info ("GFX domain entered low power state\n" );Do you really want this printed every time?
Quoted 4 lines
Hmm... it could perhaps be clubbed with the overall status that's printed. I kept it here since the GFX power domain is completely under MPU control and hence this information would be useful in finding out if there's a problem with the GFX suspend-resume.
OK.
Quoted 13 lines
Quoted 12 lines
arch/arm/mach-omap2/pm33xx.c line 107
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* +* GFX_L4LS clock domain needs to be woken up to +* ensure thet L4LS clock domain does not get stuck in transition +* If that happens L3 module does not get disabled, thereby leading +* to PER power domain transition failing +* +* The clock framework should take care of ensuring +* that the clock domain is in the right state when +* GFX driver is active. Are you suggesting that the clock framework is not doing this already?
Quoted 4 lines
No. This clkdm_*() calls are here to work-around an issue that I observed when implementing suspend-resume. The force wakeup and sleep of the
gfx_l4lsclock domain across every suspend-resume is something I don't think can be pushed to the clock framework.
I still don't follow what you're suggesting the clock framework "should" do. Are you describing the case when there is a GFX driver vs. when there isn't a driver? If so, it needs to be more clear.
Also, some more description about why the device gets 'stuck in transition' would be helpful. Is this an erratum workaround?
Quoted 31 lines
Quoted 5 lines
Quoted 5 lines
arch/arm/mach-omap2/pm33xx.c new file +5
-0+*/ +clkdm_wakeup (gfx_l4ls_clkdm); +clkdm_sleep (gfx_l4ls_clkdm); + +if (ret) {Quoted 8 lines
arch/arm/mach-omap2/pm33xx.c line 115
Quoted 3 lines
arch/arm/mach-omap2/pm33xx.c new file +3
-0+pr_err ("Kernel suspend failure\n" ); + }else { + status =omap_ctrl_readl (AM33XX_CONTROL_IPC_MSG_REG1 );We're trying to git rid of direct control module register access, and consolidate them into
control.c(for an eventual move to a driver.) I see you've mostly done that in other parts of the series, but here's one that needs to move.Yes, I somehow missed this one. Will take care of it in the next version.
Quoted 14 lines
arch/arm/mach-omap2/pm33xx.c line 125
Quoted 11 lines
arch/arm/mach-omap2/pm33xx.c new file +10
-0+ status &=IPC_RESP_MASK ; + status >>=__ffs (IPC_RESP_MASK ); + +switch (status) { +case 0 : +pr_info ("Successfully put all powerdomains to target state\n" ); +/* +* XXX: Leads to loss of logic state in PER power domain +* Use SOC specific ops for this? +*/ huh?
Quoted 8 lines
Ah... this is more of a TODO. There's no previous state entered information in the PRCM registers. So to ensure that the drivers get the right information when they check with the PM layer about the loss of context and hence the need to restore the registers, I need to update the logic and membank state counters for the PER power domain manually. I was thinking of leveraging the SoC specific power domain ops for doing this.
[...]
I see, then probably a TODO here with more description would be more helpful.
So, IIUC, without implemeting this, the drivers will never be able to detect loss of context, correct? Sounds like something that should be decribed in the changelog as that's a rather important limitation to this implementaion.
Quoted 9 lines
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ + /* Give some time to M3 to respond. 500msec is a random value here */random? really?
Sort of. I don't have any numbers from the h/w guys on the worst case delay in getting an interrupt from M3 to MPU. At the same time I want to handle the scenario where something goes wrong on the M3 side and it doesn't respond.
OK, then it's not random. You have some reasoning behind the number that should be documented.
That being said, in the absence of numbers from HW folks, can't you measure the typical times so you know roughly what's "normal".
Quoted 10 lines
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c line 246
Quoted 5 lines
arch/arm/mach-omap2/pm33xx.c new file +4
-0+ +/* +* Dummy notifier for the mailbox +* XXX: Get rid of this requirement once the MBX driver has been finalized IIRC, I suggested a trivial fix to the mailbox driver that would remove the need for this, which could be done today.
Quoted 3 lines
Yes. I plan to do that once the mailbox code movement to
drivers/along with other changes to make it generic enough are finalized. It was adding in one more dependency and hence I kept this as a TODO in this version.
OK, fair enough.
Quoted 11 lines
Quoted 10 lines
arch/arm/mach-omap2/pm33xx.c line 328
Quoted 7 lines
arch/arm/mach-omap2/pm33xx.c new file +7
-0+static int wkup_m3_init (void ) +{ +int irq, ret =0 ; +struct resource *mem; +struct platform_device *pdev =to_platform_device (wkup_m3->dev); + +omap_device_enable_hwmods (to_omap_device (pdev));Why not
omap_device_enable(pdev)?
Quoted 2 lines
The objective is to leverage the hwmod code to get the WKUP-M3 functional and not have OMAP runtime PM code coming in the way.
FWIW, it is not runtime PM getting in the way.
Quoted 2 lines
Using
omap_device_enable()triggers the followingdev_warn()fromomap_device_enable().
Looking closer at the trace, you'll see it's not omap_device_enable() that is triggering this warning. What is happening is that omap_device has a late_initcall which forcibly idles omap_devices that have been enabled, but that don't have a driver. You're hacking around that.
IMO, this would be a much cleaner implementation if you just created a small driver for the wkup_m3. You're already doing a bunch of driver-like stuff for it (requesting base/IRQs, mapping regions, firmware, etc.) I think this should separated out into a real driver. Then it will be bound to the right omap_device, and normal PM operations will work as expected.
Also, doing it this way will be more flexible for those wanting to use their own firmware on the M3, or customize the current firmware.
Quoted 21 lines
[ 2.033718] platform 44d00000.wkup_m3: omap_device_late_idle: enabled but no driver. Idling [ 2.042676] ------------[ cut here ]------------ [ 2.047572] WARNING: at arch/arm/mach-omap2/omap_hwmod.c:2187 _idle+0x164/0x1c0() [ 2.055459] omap_hwmod: wkup_m3: idle state can only be entered from enabled state [ 2.063435] Modules linked in: [ 2.066712] [<c001afe4>] (unwind_backtrace+0x0/0xf0) from [<c004380c>] (warn_slowpath_common+0x4c/0x64) [ 2.076626] [<c004380c>] (warn_slowpath_common+0x4c/0x64) from [<c00438b8>] (warn_slowpath_fmt+0x30/0x40) [ 2.086720] [<c00438b8>] (warn_slowpath_fmt+0x30/0x40) from [<c002aad0>] (_idle+0x164/0x1c0) [ 2.095624] [<c002aad0>] (_idle+0x164/0x1c0) from [<c002af98>] (omap_hwmod_idle+0x24/0x40) [ 2.104348] [<c002af98>] (omap_hwmod_idle+0x24/0x40) from [<c002bd60>] (omap_device_idle_hwmods+0x24/0x3c) [ 2.114536] [<c002bd60>] (omap_device_idle_hwmods+0x24/0x3c) from [<c002bf4c>] (_omap_device_deactivate+0x98/0x134) [ 2.125546] [<c002bf4c>] (_omap_device_deactivate+0x98/0x134) from [<c002c87c>] (omap_device_idle+0x28/0x54) [ 2.135921] [<c002c87c>] (omap_device_idle+0x28/0x54) from [<c06ec00c>] (omap_device_late_idle+0x44/0x54) [ 2.146025] [<c06ec00c>] (omap_device_late_idle+0x44/0x54) from [<c031f850>] (bus_for_each_dev+0x50/0x7c) [ 2.156120] [<c031f850>] (bus_for_each_dev+0x50/0x7c) from
Quoted 8 lines
[<
c06ebe10>] (omap_device_late_init+0x18/0x28)[ 2.166216] [<c06ebe10>] (omap_device_late_init+0x18/0x28) from [<c00086e4>] (do_one_initcall+0x34/0x180) [ 2.176314] [<c00086e4>] (do_one_initcall+0x34/0x180) from [<c06df8f8>] (kernel_init_freeable+0xfc/0x1cc) [ 2.186408] [<c06df8f8>] (kernel_init_freeable+0xfc/0x1cc) from [<c04d4b20>] (kernel_init+0x8/0xe4) [ 2.195962] [<c04d4b20>] (kernel_init+0x8/0xe4) from [<c0013410>] (ret_from_fork+0x14/0x24) [ 2.204905] ---[ end trace 8f61b319779f6e57 ]---
Kevin
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
On Mon, Feb 18, 2013 at 21:41:49, Kevin Hilman wrote:
[...]
Quoted 5 lines
Quoted 1 line
By default these IPs don't have MSTANDBY asserted.
When you say "by default", I guess you mean after reset (and/or context loss), right?
Yes
Quoted 6 lines
Quoted 4 lines
When a low power transition happens, the peripheral power domain loses context and hence the forced MSTANDBY configuration in the IP is lost. To work around this problem we need to assert MSTANDBY in every suspend-resume iteration.
Yuck. More clever hardware. ;)
We are getting this gradually :)
Quoted 7 lines
Quoted 4 lines
I agree that this might hide PM bugs in the driver but to solve this problem we need some mechanism for the PM code to know whether or not a driver is bound to the corresponding platform devices. Any suggestions on this?
Driver bound status can be tracked easily using bus notifiers. You can see an example in the
omap_devicecore.
Ok. I'll try to use the driver bound status in the next version.
[...]
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
arch/arm/mach-omap2/pm33xx.c line 107
Quoted 9 lines
arch/arm/mach-omap2/pm33xx.c new file +9
-0+/* +* GFX_L4LS clock domain needs to be woken up to +* ensure thet L4LS clock domain does not get stuck in transition +* If that happens L3 module does not get disabled, thereby leading +* to PER power domain transition failing +* +* The clock framework should take care of ensuring +* that the clock domain is in the right state when +* GFX driver is active. Are you suggesting that the clock framework is not doing this already?
Quoted 9 lines
Quoted 4 lines
No. This clkdm_*() calls are here to work-around an issue that I observed when implementing suspend-resume. The force wakeup and sleep of the
gfx_l4lsclock domain across every suspend-resume is something I don't think can be pushed to the clock framework.I still don't follow what you're suggesting the clock framework "should" do. Are you describing the case when there is a GFX driver vs. when there isn't a driver? If so, it needs to be more clear.
No. The issue with GFX_L4LS happens irrespective of the state of the GFX driver and needs to be handled in the suspend-resume sequence. I guess the second part of comment is what created the confusion. I'll get rid of that.
Quoted 3 lines
Also, some more description about why the device gets 'stuck in transition' would be helpful. Is this an erratum workaround?
I'll follow up with the design folks to find out more. From some past discussions this is not expected so looks like we need to an erratum published for this issue.
Quoted 9 lines
I see, then probably a TODO here with more description would be more helpful.
So, IIUC, without implemeting this, the drivers will never be able to detect loss of context, correct? Sounds like something that should be decribed in the changelog as that's a rather important limitation to this implementaion.
Ok. I'll address this limitation in the next version and improve the changelog.
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ + /* Give some time to M3 to respond. 500msec is a random value here */random? really?
Quoted 7 lines
Quoted 4 lines
Sort of. I don't have any numbers from the h/w guys on the worst case delay in getting an interrupt from M3 to MPU. At the same time I want to handle the scenario where something goes wrong on the M3 side and it doesn't respond.
OK, then it's not random. You have some reasoning behind the number that should be documented.
Will do.
Quoted 3 lines
That being said, in the absence of numbers from HW folks, can't you measure the typical times so you know roughly what's "normal".
I'll do some timer based profiling and get rough numbers for this.
[...]
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
Why not
omap_device_enable(pdev)?The objective is to leverage the hwmod code to get the WKUP-M3 functional and not have OMAP runtime PM code coming in the way.
FWIW, it is not runtime PM getting in the way.
Quoted 8 lines
Quoted 2 lines
Using
omap_device_enable()triggers the followingdev_warn()fromomap_device_enable().Looking closer at the trace, you'll see it's not
omap_device_enable()that is triggering this warning. What is happening is thatomap_devicehas alate_initcallwhich forcibly idlesomap_devicesthat have been enabled, but that don't have a driver. You're hacking around that.
Thanks for the explanation. I should have looked closer :(
Quoted 9 lines
IMO, this would be a much cleaner implementation if you just created a small driver for the
wkup_m3. You're already doing a bunch of driver-like stuff for it (requesting base/IRQs, mapping regions, firmware, etc.) I think this should separated out into a real driver. Then it will be bound to the rightomap_device, and normal PM operations will work as expected.Also, doing it this way will be more flexible for those wanting to use their own firmware on the M3, or customize the current firmware.
Hmm... that definitely sounds more flexible. It should also help in the next SoC AM437x which has a similar PM architecture. Where would you suggest placing this minimal driver?
Regards,
Vaibhav
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
"Bedia, Vaibhav" <[email protected]> writes:
[...]
Quoted 7 lines
Quoted 7 lines
IMO, this would be a much cleaner implementation if you just created a small driver for the
wkup_m3. You're already doing a bunch of driver-like stuff for it (requesting base/IRQs, mapping regions, firmware, etc.) I think this should separated out into a real driver. Then it will be bound to the rightomap_device, and normal PM operations will work as expected.
Quoted 6 lines
Quoted 2 lines
Also, doing it this way will be more flexible for those wanting to use their own firmware on the M3, or customize the current firmware.
Hmm... that definitely sounds more flexible. It should also help in the next SoC AM437x which has a similar PM architecture. Where would you suggest placing this minimal driver?
For now, just leave it in mach-omap2 and we can figure out the right home for it eventually.
Kevin
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
In reply to Vaibhav BediaHi Vaibhav,
Quoted 3 lines · Vaibhav Bedia
AM335x supports various low power modes as documented in section 8.1.4.3 of the AM335x TRM which is available @ http://www.ti.com/litv/pdf/spruh73f
May I ask about the plans for this series? Will you be re-spinning them for a current
tree, and what's the planned merge window for it?
Many thanks,
Daniel
Quoted 617 lines
DeepSleep0 mode offers the lowest power mode with limited wakeup sources without a system reboot and is mapped as the suspend state in the kernel. In this state, MPU and PER domains are turned off with the internal RAM held in retention to facilitate resume process. As part of the boot process, the assembly code is copied over to OCMCRAM using the OMAP SRAM code.
AM335x has a Cortex-M3 (
WKUP_M3) which assists the MPU in DeepSleep0 entry and exit.WKUP_M3takes care of the clockdomain and powerdomain transitions based on the intended low power state. MPU needs to load the appropriateWKUP_M3binary onto theWKUP_M3memory space before it can leverage any of the PM features like DeepSleep.The IPC mechanism between MPU and
WKUP_M3uses a mailbox sub-module and 8 IPC registers in the Control module. MPU uses the assigned Mailbox for issuing an interrupt toWKUP_M3which then goes and checks the IPC registers for the payload.WKUP_M3has the ability to trigger on interrupt to MPU by executing the "sev" instruction.In the current implementation when the suspend process is initiated MPU interrupts the
WKUP_M3to let it know about the intent of entering DeepSleep0 and waits for an ACK. When the ACK is received MPU continues with its suspend process to suspend all the drivers and then jumps to assembly in OCMC RAM. The assembly code puts the PLLs in bypass, puts the external RAM in self-refresh mode and then finally execute the WFI instruction. Execution of the WFI instruction triggers another interrupt to theWKUP_M3which then continues wiht the power down sequence wherein the clockdomain and powerdomain transition takes place. As part of the sleep sequence,WKUP_M3unmasks the interrupt lines for the wakeup sources. WFI execution onWKUP_M3causes the hardware to disable the main oscillator of the SoC.When a wakeup event occurs,
WKUP_M3starts the power-up sequence by switching on the power domains and finally enabling the clock to MPU. Since the MPU gets powered down as part of the sleep sequence in the resume path ROM code starts executing. The ROM code detects a wakeup from sleep and then jumps to the resume location in OCMC which was populated in one of the IPC registers as part of the suspend sequence.The low level code in OCMC relocks the PLLs, enables access to external RAM and then jumps to the
cpu_resumecode of the kernel to finish the resume process.Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>---
v1->v2:
Move assembly code addition, control module access and hookup in OMAP PM framework in separate patches. Address other comments from Kevin Hilman and Santosh Shilimkar on v1. The discussion on v1 is present @
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129979.html
Note: The mailbox change will need slight rework once the driver is finalized.arch/arm/mach-omap2/pm33xx.c | 469 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/pm33xx.h | 56 +++++ 2 files changed, 525 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-omap2/pm33xx.c create mode 100644 arch/arm/mach-omap2/pm33xx.harch/arm/mach-omap2/pm33xx.c new file +469
-0@@ -0,0 +1,469 @@ +/* +* AM33XX Power Management Routines +* +* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ +* Vaibhav Bedia <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/firmware.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/suspend.h> +#include <linux/completion.h> +#include <linux/module.h> +#include <linux/mailbox.h> +#include <linux/interrupt.h> + +#include <asm/suspend.h> +#include <asm/proc-fns.h> +#include <asm/sizes.h> +#include <asm/fncpy.h> +#include <asm/system_misc.h> + +#include "pm.h" +#include "cm33xx.h" +#include "pm33xx.h" +#include "control.h" +#include "clockdomain.h" +#include "powerdomain.h" +#include "omap_hwmod.h" +#include "omap_device.h" +#include "soc.h" +#include "sram.h" + +void (*am33xx_do_wfi_sram)(void ); + +static void __iomem *am33xx_emif_base; +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm; +static struct clockdomain *gfx_l4ls_clkdm; +static struct omap_hwmod *usb_oh, *cpsw_oh, *tptc0_oh, *tptc1_oh, *tptc2_oh; +static struct wkup_m3_context *wkup_m3; + +static DECLARE_COMPLETION (wkup_m3_sync); + +#ifdef CONFIG_SUSPEND +static int am33xx_do_sram_idle (long unsigned int unused) +{ +am33xx_do_wfi_sram (); +return 0 ; +} + +static int am33xx_pm_suspend (void ) +{ +int status, ret =0 ; + +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled. To ensure +* that there no issues with or without the drivers being compiled +* in the kernel, we forcefully put these IPs to idle. +*/ +omap_hwmod_enable (usb_oh); +omap_hwmod_enable (tptc0_oh); +omap_hwmod_enable (tptc1_oh); +omap_hwmod_enable (tptc2_oh); +omap_hwmod_enable (cpsw_oh); + +omap_hwmod_idle (usb_oh); +omap_hwmod_idle (tptc0_oh); +omap_hwmod_idle (tptc1_oh); +omap_hwmod_idle (tptc2_oh); +omap_hwmod_idle (cpsw_oh); + +/* Try to put GFX to sleep */ +pwrdm_set_next_fpwrst (gfx_pwrdm,PWRDM_FUNC_PWRST_OFF ); + + ret =cpu_suspend (0 , am33xx_do_sram_idle); + + status =pwrdm_read_fpwrst (gfx_pwrdm); +if (status !=PWRDM_FUNC_PWRST_OFF ) +pr_err ("GFX domain did not transition\n" ); +else +pr_info ("GFX domain entered low power state\n" ); + +/* +* GFX_L4LS clock domain needs to be woken up to +* ensure thet L4LS clock domain does not get stuck in transition +* If that happens L3 module does not get disabled, thereby leading +* to PER power domain transition failing +* +* The clock framework should take care of ensuring +* that the clock domain is in the right state when +* GFX driver is active. +*/ +clkdm_wakeup (gfx_l4ls_clkdm); +clkdm_sleep (gfx_l4ls_clkdm); + +if (ret) { +pr_err ("Kernel suspend failure\n" ); + }else { + status =omap_ctrl_readl (AM33XX_CONTROL_IPC_MSG_REG1 ); + status &=IPC_RESP_MASK ; + status >>=__ffs (IPC_RESP_MASK ); + +switch (status) { +case 0 : +pr_info ("Successfully put all powerdomains to target state\n" ); +/* +* XXX: Leads to loss of logic state in PER power domain +* Use SOC specific ops for this? +*/ +break ; +case 1 : +pr_err ("Could not transition all powerdomains to target state\n" ); + ret =-1 ; +break ; +default : +pr_err ("Something went wrong :(\nStatus = %d\n" , + status); + ret =-1 ; + } + } + +return ret; +} + +static int am33xx_pm_enter (suspend_state_t suspend_state) +{ +int ret =0 ; + +switch (suspend_state) { +case PM_SUSPEND_STANDBY : +case PM_SUSPEND_MEM : + ret =am33xx_pm_suspend (); +break ; +default : + ret = -EINVAL ; + } + +return ret; +} + +static int am33xx_pm_begin (suspend_state_t state) +{ +int ret =0 ; +struct mailbox_msg dummy_msg; + +disable_hlt (); + +MAILBOX_FILL_HEADER_MSG (dummy_msg,0xABCDABCD ); + + wkup_m3->ipc_data.sleep_mode =IPC_CMD_DS0 ; + wkup_m3->ipc_data.param1 =DS_IPC_DEFAULT ; + wkup_m3->ipc_data.param2 =DS_IPC_DEFAULT ; + +am33xx_wkup_m3_ipc_cmd (&wkup_m3->ipc_data); + + wkup_m3->state =M3_STATE_MSG_FOR_LP ; + +mailbox_enable_irq (wkup_m3->mbox,IRQ_RX ); + + ret =mailbox_msg_send (wkup_m3->mbox, &dummy_msg); +if (ret) { +pr_err ("A8<->CM3 MSG for LP failed\n" ); +am33xx_m3_state_machine_reset (); + ret =-1 ; + } + +/* Give some time to M3 to respond. 500msec is a random value here */ +if (!wait_for_completion_timeout (&wkup_m3_sync, +msecs_to_jiffies (500 ))) { +pr_err ("A8<->CM3 sync failure\n" ); +am33xx_m3_state_machine_reset (); + ret =-1 ; + }else { +pr_debug ("Message sent for entering DeepSleep mode\n" ); +mailbox_disable_irq (wkup_m3->mbox,IRQ_RX ); + } + +return ret; +} + +static void am33xx_pm_end (void ) +{ +mailbox_enable_irq (wkup_m3->mbox,IRQ_RX ); + +am33xx_m3_state_machine_reset (); + +enable_hlt (); + +return ; +} + +static const struct platform_suspend_ops am33xx_pm_ops = { + .begin = am33xx_pm_begin, + .end = am33xx_pm_end, + .enter = am33xx_pm_enter, + .valid = suspend_valid_only_mem, +}; + +static void am33xx_m3_state_machine_reset (void ) +{ +int ret =0 ; +struct mailbox_msg dummy_msg; + +MAILBOX_FILL_HEADER_MSG (dummy_msg,0xABCDABCD ); + + wkup_m3->ipc_data.sleep_mode =IPC_CMD_RESET ; + wkup_m3->ipc_data.param1 =DS_IPC_DEFAULT ; + wkup_m3->ipc_data.param2 =DS_IPC_DEFAULT ; + +am33xx_wkup_m3_ipc_cmd (&wkup_m3->ipc_data); + + wkup_m3->state =M3_STATE_MSG_FOR_RESET ; + + ret =mailbox_msg_send (wkup_m3->mbox, &dummy_msg); +if (!ret) { +pr_debug ("Message sent for resetting M3 state machine\n" ); +/* Give some to M3 to respond. 500msec is a random value here */ +if (!wait_for_completion_timeout (&wkup_m3_sync, +msecs_to_jiffies (500 ))) +pr_err ("A8<->CM3 sync failure\n" ); + }else { +pr_err ("Could not reset M3 state machine!!!\n" ); + wkup_m3->state =M3_STATE_UNKNOWN ; + } +} +#endif /* CONFIG_SUSPEND */ + +/* +* Dummy notifier for the mailbox +* XXX: Get rid of this requirement once the MBX driver has been finalized +*/ +static int wkup_mbox_msg (struct notifier_block *self,unsigned long len, +void *msg) +{ +return 0 ; +} + +static struct notifier_block wkup_mbox_notifier = { + .notifier_call = wkup_mbox_msg, +}; + +static irqreturn_t wkup_m3_txev_handler (int irq,void *unused) +{ +am33xx_txev_eoi (); + +switch (wkup_m3->state) { +case M3_STATE_RESET : + wkup_m3->state =M3_STATE_INITED ; +break ; +case M3_STATE_MSG_FOR_RESET : + wkup_m3->state =M3_STATE_INITED ; +mailbox_rx_flush (wkup_m3->mbox); +complete (&wkup_m3_sync); +break ; +case M3_STATE_MSG_FOR_LP : +mailbox_rx_flush (wkup_m3->mbox); +complete (&wkup_m3_sync); +break ; +case M3_STATE_UNKNOWN : +pr_err ("IRQ %d with WKUP_M3 in unknown state\n" , irq); +mailbox_rx_flush (wkup_m3->mbox); +return IRQ_NONE ; + } + +am33xx_txev_enable (); +return IRQ_HANDLED ; +} + +static void am33xx_pm_firmware_cb (const struct firmware *fw,void *context) +{ +struct wkup_m3_context *wkup_m3_context = context; +struct platform_device *pdev =to_platform_device (wkup_m3_context->dev); +int ret =0 ; + +/* no firmware found */ +if (!fw) { +dev_err (wkup_m3_context->dev,"request_firmware failed\n" ); + goto err; + } + +memcpy ((void *)wkup_m3_context->code, fw->data, fw->size); +pr_info ("Copied the M3 firmware to UMEM\n" ); + + wkup_m3->state =M3_STATE_RESET ; + + ret =omap_device_deassert_hardreset (pdev,"wkup_m3" ); +if (ret) { +pr_err ("Could not deassert the reset for WKUP_M3\n" ); + goto err; + }else { +#ifdef CONFIG_SUSPEND +suspend_set_ops (&am33xx_pm_ops); +/* +* Physical resume address to be used by ROM code +*/ + wkup_m3->ipc_data.resume_addr = (AM33XX_OCMC_END - + am33xx_do_wfi_sz + am33xx_resume_offset +0x4 ); +#endif +return ; + } + +err: +mailbox_put (wkup_m3_context->mbox, &wkup_mbox_notifier); +} + +static int wkup_m3_init (void ) +{ +int irq, ret =0 ; +struct resource *mem; +struct platform_device *pdev =to_platform_device (wkup_m3->dev); + +omap_device_enable_hwmods (to_omap_device (pdev)); + +/* Reserve the MBOX for sending messages to M3 */ + wkup_m3->mbox =mailbox_get ("wkup_m3" , &wkup_mbox_notifier); +if (IS_ERR (wkup_m3->mbox)) { +pr_err ("Could not reserve mailbox for A8->M3 IPC\n" ); + ret = -ENODEV ; + goto exit; + } + + irq =platform_get_irq (pdev,0 ); +if (!irq) { +dev_err (wkup_m3->dev,"no irq resource\n" ); + ret = -ENXIO ; + goto err; + } + + mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!mem) { +dev_err (wkup_m3->dev,"no memory resource\n" ); + ret = -ENXIO ; + goto err; + } + + wkup_m3->code =devm_request_and_ioremap (wkup_m3->dev, mem); +if (!wkup_m3->code) { +dev_err (wkup_m3->dev,"could not ioremap\n" ); + ret = -EADDRNOTAVAIL ; + goto err; + } + + ret =devm_request_irq (wkup_m3->dev, irq, wkup_m3_txev_handler, +IRQF_DISABLED ,"wkup_m3_txev" ,NULL ); +if (ret) { +dev_err (wkup_m3->dev,"request_irq failed\n" ); + goto err; + }else { +am33xx_txev_enable (); + } + +pr_info ("Trying to load am335x-pm-firmware.bin" ); + +/* We don't want to delay boot */ +request_firmware_nowait (THIS_MODULE ,0 ,"am335x-pm-firmware.bin" , + wkup_m3->dev,GFP_KERNEL , wkup_m3, + am33xx_pm_firmware_cb); +return 0 ; + +err: +mailbox_put (wkup_m3->mbox, &wkup_mbox_notifier); +exit: +return ret; +} + +/* +* Push the minimal suspend-resume code to SRAM +*/ +void am33xx_push_sram_idle (void ) +{ + am33xx_do_wfi_sram = (void *)omap_sram_push + (am33xx_do_wfi, am33xx_do_wfi_sz); +} + +static int __init am33xx_map_emif (void ) +{ + am33xx_emif_base =ioremap (AM33XX_EMIF_BASE ,SZ_32K ); + +if (!am33xx_emif_base) +return -ENOMEM ; + +return 0 ; +} + +void __iomem *am33xx_get_emif_base (void ) +{ +return am33xx_emif_base; +} + +int __init am33xx_pm_init (void ) +{ +int ret; + +if (!soc_is_am33xx ()) +return -ENODEV ; + +pr_info ("Power Management for AM33XX family\n" ); + +/* +* By default the following IPs do not have MSTANDBY asserted +* which is necessary for PER domain transition. If the drivers +* are not compiled into the kernel HWMOD code will not change the +* state of the IPs if the IP was not never enabled +*/ + usb_oh =omap_hwmod_lookup ("usb_otg_hs" ); + tptc0_oh =omap_hwmod_lookup ("tptc0" ); + tptc1_oh =omap_hwmod_lookup ("tptc1" ); + tptc2_oh =omap_hwmod_lookup ("tptc2" ); + cpsw_oh =omap_hwmod_lookup ("cpgmac0" ); + + gfx_pwrdm =pwrdm_lookup ("gfx_pwrdm" ); + per_pwrdm =pwrdm_lookup ("per_pwrdm" ); + + gfx_l4ls_clkdm =clkdm_lookup ("gfx_l4ls_gfx_clkdm" ); + +if ((!usb_oh) || (!tptc0_oh) || (!tptc1_oh) || (!tptc2_oh) || + (!cpsw_oh) || (!gfx_pwrdm) || (!per_pwrdm) || + (!gfx_l4ls_clkdm)) { + ret = -ENODEV ; + goto err; + } + + wkup_m3 =kzalloc (sizeof (struct wkup_m3_context ),GFP_KERNEL ); +if (!wkup_m3) { +pr_err ("Memory allocation failed\n" ); + ret = -ENOMEM ; + goto err; + } + + ret =am33xx_map_emif (); +if (ret) { +pr_err ("Could not ioremap EMIF\n" ); + goto err; + } + + (void )clkdm_for_each (omap_pm_clkdms_setup,NULL ); + +/* CEFUSE domain can be turned off post bootup */ + cefuse_pwrdm =pwrdm_lookup ("cefuse_pwrdm" ); +if (cefuse_pwrdm) +pwrdm_set_next_fpwrst (cefuse_pwrdm,PWRDM_FUNC_PWRST_OFF ); +else +pr_err ("Failed to get cefuse_pwrdm\n" ); + + wkup_m3->dev =omap_device_get_by_hwmod_name ("wkup_m3" ); + + ret =wkup_m3_init (); +if (ret) +pr_err ("Could not initialise firmware loading\n" ); + +err: +return ret; +}arch/arm/mach-omap2/pm33xx.h new file +56
-1@@ -0,0 +1,56 @@ +/* +* AM33XX Power Management Routines +* +* Copyright (C) 2012 Texas Instruments Inc. +* Vaibhav Bedia <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ +#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H +#define __ARCH_ARM_MACH_OMAP2_PM33XX_H + +#include "control.h" + +#ifndef __ASSEMBLER__ +struct wkup_m3_context { +struct am33xx_ipc_data ipc_data; +struct device *dev; +struct firmware *firmware; +struct mailbox *mbox; +void __iomem *code; +u8 state; +}; + +#ifdef CONFIG_SUSPEND +static void am33xx_m3_state_machine_reset (void ); +#else +static inline void am33xx_m3_state_machine_reset (void ) {} +#endif /* CONFIG_SUSPEND */ + +extern void __iomem *am33xx_get_emif_base (void ); +#endif + +#define IPC_CMD_DS0 0x3 +#define IPC_CMD_RESET 0xe +#define DS_IPC_DEFAULT 0xffffffff + +#define IPC_RESP_SHIFT 16 +#define IPC_RESP_MASK (0xffff << 16) + +#define M3_STATE_UNKNOWN 0 +#define M3_STATE_RESET 1 +#define M3_STATE_INITED 2 +#define M3_STATE_MSG_FOR_LP 3 +#define M3_STATE_MSG_FOR_RESET 4 + +#define AM33XX_OCMC_END 0x40310000 +#define AM33XX_EMIF_BASE 0x4C000000 + +#endif --1.7.0.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
RFC v2 16/18 ARM: OMAP2+: AM33XX: Basic suspend resume support
Hi Daniel,
Quoted 11 lines · Daniel Mack
Hi Vaibhav,
Quoted 3 lines · Vaibhav Bedia
AM335x supports various low power modes as documented in section 8.1.4.3 of the AM335x TRM which is available @ http://www.ti.com/litv/pdf/spruh73f
May I ask about the plans for this series? Will you be re-spinning them for a current
tree, and what's the planned merge window for it?
I am tied up in some other stuff right now. I plan to address Kevin's comments and repost the patches soon. Since rc5 is already out i think v3.10 is not a realistic target any more but I do hope to have this accepted for v3.11.
Regards,
Vaibhav
RFC v2 17/18 ARM: OMAP2+: AM33XX: Select Mailbox when PM is enabled
In reply to Vaibhav BediaPM services on AM33XX depend on mailbox for communication with WKUP-M3 core so ensure that the right config options are selected. Thanks to Kevin Hilman <[email protected]> for the suggestion on updating the Kconfig and not just the omap2plus_defconfig which was done in the previous version of the AM33XX suspend-resume support.
---v1->v2:
Update the Kconfig instead of the defconfig
arch/arm/mach-omap2/Kconfig | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/Kconfig +3 -1
@@ -114,9 +114,11 @@ config SOC_AM33XX bool "AM33XX support" default y select ARM_CPU_SUSPEND if PM + select COMMON_CLK select CPU_V7 + select MAILBOX if PM select MULTI_IRQ_HANDLER - select COMMON_CLK + select OMAP2PLUS_MBOX if PM config OMAP_PACKAGE_ZAF bool
Signature · 1 line
1.7.0.4
RFC v2 17/18 ARM: OMAP2+: AM33XX: Select Mailbox when PM is enabled
Quoted 7 lines · Vaibhav Bedia
PM services on AM33XX depend on mailbox for communication with WKUP-M3 core so ensure that the right config options are selected. Thanks to Kevin Hilman <[email protected]> for the suggestion on updating the
Kconfigand not just theomap2plus_defconfigwhich was done in the previous version of the AM33XX suspend-resume support.
Quoted 7 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>---
Unrelated to series. You can post this patch separately.
regards
Santosh
RFC v2 17/18 ARM: OMAP2+: AM33XX: Select Mailbox when PM is enabled
Quoted 8 lines · Santosh
Quoted 7 lines · Vaibhav Bedia
PM services on AM33XX depend on mailbox for communication with WKUP-M3 core so ensure that the right config options are selected. Thanks to Kevin Hilman <[email protected]> for the suggestion on updating the
Kconfigand not just theomap2plus_defconfigwhich was done in the previous version of the AM33XX suspend-resume support.
Quoted 9 lines
Quoted 7 lines
Signed-off-by Vaibhav Bedia <[email protected]>Cc Tony Lingren <[email protected]>Cc Santosh Shilimkar <[email protected]>Cc Benoit Cousson <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>---
Unrelated to series. You can post this patch separately.
Ok. I kept it in this series so that it does not look to be some random patch.
Regards,
Vaibhav
RFC v2 18/18 ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
In reply to Vaibhav BediaWith all the requisite changes in place we can now enable basic PM support on AM33XX. This patch updates the various OMAP files to enable suspend-resume on AM33XX.
---v1->v2:
This is a new patch in the series
arch/arm/mach-omap2/Makefile | 2 ++ arch/arm/mach-omap2/board-generic.c | 1 + arch/arm/mach-omap2/common.h | 10 ++++++++++ arch/arm/mach-omap2/io.c | 7 +++++++ arch/arm/mach-omap2/pm.h | 7 +++++++ arch/arm/mach-omap2/sram.c | 10 +++++++++- arch/arm/mach-omap2/sram.h | 2 ++ 7 files changed, 38 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/Makefile +2 -0
@@ -81,6 +81,7 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o +obj-$(CONFIG_SOC_AM33XX) += pm33xx.o sleep33xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o
@@ -88,6 +89,7 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec) +AFLAGS_sleep33xx.o :=-Wa,-march=armv7-a$(plus_sec) ifeq ($(CONFIG_PM_VERBOSE),y) CFLAGS_pm_bus.o += -DDEBUG
arch/arm/mach-omap2/board-generic.c +1 -0
@@ -136,6 +136,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)") .reserve = omap_reserve, .map_io = am33xx_map_io, .init_early = am33xx_init_early, + .init_late = am33xx_init_late, .init_irq = omap_intc_of_init, .handle_irq = omap3_intc_handle_irq, .init_machine = omap_generic_init,
arch/arm/mach-omap2/common.h +10 -0
@@ -68,6 +68,15 @@ static inline int omap4_pm_init(void) }#endif +#if defined(CONFIG_PM ) && defined(CONFIG_SOC_AM33XX ) +int am33xx_pm_init (void ); +#else +static inline int am33xx_pm_init (void ) +{ +return 0 ; +} +#endif +#ifdef CONFIG_OMAP_MUX int omap_mux_late_init (void );#else
@@ -106,6 +115,7 @@ void omap2430_init_late(void);void omap3430_init_late (void );void omap35xx_init_late (void );void omap3630_init_late (void ); +void am33xx_init_late (void );void am35xx_init_late (void );void ti81xx_init_late (void );void omap4430_init_late (void );
arch/arm/mach-omap2/io.c +7 -0
@@ -570,6 +570,13 @@ void __init am33xx_init_early(void)omap_hwmod_init_postsetup (); am33xx_clk_init(); } + +void __init am33xx_init_late (void ) +{ +omap_mux_late_init (); +omap2_common_pm_late_init (); +am33xx_pm_init (); +}#endif #ifdef CONFIG_ARCH_OMAP4
arch/arm/mach-omap2/pm.h +7 -0
@@ -76,6 +76,13 @@ extern unsigned int omap3_do_wfi_sz;/* ... and its pointer from SRAM after copy */ extern void (*omap3_do_wfi_sram)(void ); +/* am33xx_do_wfi function pointer and size, for copy to SRAM */ +extern void am33xx_do_wfi (void ); +extern unsigned int am33xx_do_wfi_sz; +extern unsigned int am33xx_resume_offset; +/* ... and its pointer from SRAM after copy */ +extern void (*am33xx_do_wfi_sram)(void ); +/* save_secure_ram_context function pointer and size, for copy to SRAM */ extern int save_secure_ram_context (u32 *addr);extern unsigned int save_secure_ram_context_sz;
arch/arm/mach-omap2/sram.c +9 -1
@@ -151,7 +151,7 @@ static void __init omap2_map_sram(void) omap_sram_size -= SZ_16K; }#endif -if (cpu_is_omap34xx ()) { +if (cpu_is_omap34xx () ||soc_is_am33xx ()) {/* * SRAM must be marked as non-cached on OMAP3 since the * CORE DPLL M2 divider change code (in SRAM) runs with the
@@ -282,10 +282,18 @@ static inline int omap34xx_sram_init(void) }#endif /* CONFIG_ARCH_OMAP3 */ +#ifdef CONFIG_SOC_AM33XX static inline int am33xx_sram_init (void ) { +am33xx_push_sram_idle ();return 0 ; } +#else +static inline int am33xx_sram_init (void ) +{ +return 0 ; +} +#endif int __init omap_sram_init (void ) {
arch/arm/mach-omap2/sram.h +2 -0
@@ -62,8 +62,10 @@ extern unsigned long omap3_sram_configure_core_dpll_sz;#ifdef CONFIG_PM extern void omap_push_sram_idle (void ); +extern void am33xx_push_sram_idle (void );#else static inline void omap_push_sram_idle (void ) {} +static inline void am33xx_push_sram_idle (void ) {}#endif /* CONFIG_PM */ #endif /* __ASSEMBLY__ */
Signature · 1 line
1.7.0.4
v2 cover ARM: OMAP2+: AM33XX: Add suspend-resume support
In reply to Vaibhav BediaVaibhav,
Quoted 27 lines · Vaibhav Bedia
Hi,
This is the second version of the patch series for adding suspend-resume support for AM33XX. Based on the feedback received on the previous patch series [1] almost all the patches have undergone a bit a rework.
The 1st two patches depend on the changes for mailbox code migration from
arch/arm/*-omap*/todrivers/mailbox/[2].The patch series also depends on recent changes to the OMAP PM framework by Paul Walmsley.
I found it easiest to apply the AM33XX suspend-resume patches on top of Paul's TEST_pwrdm_post_fpwrst_devel_a_3.9 branch + the patches @ [2].
With these dependencies met, the PM code uses the firmware interface and expects the userspace to load the
WKUP_M3binary before the suspend-resume functionality is made available. The binary file (and the source-code forWKUP_M3) can be obtained from the 'next' branch at [3]. TheWKUP_M3binary can either be loaded post bootup via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be included in the kernel image as part of the build process.DDR3 specific changes have been skipped for now since mainline U-Boot exhibited stability issues on all the DDR3 based AM335x boards that i could lay my hands on.
Quoted 9 lines
I have done basic testing along with power measurments on the different power rails on the AM335x EVM. PER domain transition on the BeagleBone fails if the CPSW driver is included in the kernel and is yet to be root caused. Along with this issue more extensive testing on other OMAP platforms is also pending right now.
For more details on the AM335x suspend-resume support please refer to the changelog in the different patches.
I still haven't reviewed patch 15, 16 and 18 which adds suspend support. Will do that in coming days since they need a bit a closer look.
But as mentioned in some of the patches, you need to split this series since except 15, 16 and 18 which adds suspend support, rest of the patches are
- data file fixes
- timer suspend/resume update
- mailbox support, control module update.
Would be good to split the series to help the reviews.
Regards
Santosh
v2 cover ARM: OMAP2+: AM33XX: Add suspend-resume support
Hi Santosh,
Quoted 42 lines · Santosh
Vaibhav,
Quoted 27 lines · Vaibhav Bedia
Hi,
This is the second version of the patch series for adding suspend-resume support for AM33XX. Based on the feedback received on the previous patch series [1] almost all the patches have undergone a bit a rework.
The 1st two patches depend on the changes for mailbox code migration from
arch/arm/*-omap*/todrivers/mailbox/[2].The patch series also depends on recent changes to the OMAP PM framework by Paul Walmsley.
I found it easiest to apply the AM33XX suspend-resume patches on top of Paul's TEST_pwrdm_post_fpwrst_devel_a_3.9 branch + the patches @ [2].
With these dependencies met, the PM code uses the firmware interface and expects the userspace to load the
WKUP_M3binary before the suspend-resume functionality is made available. The binary file (and the source-code forWKUP_M3) can be obtained from the 'next' branch at [3]. TheWKUP_M3binary can either be loaded post bootup via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be included in the kernel image as part of the build process.DDR3 specific changes have been skipped for now since mainline U-Boot exhibited stability issues on all the DDR3 based AM335x boards that i could lay my hands on.
Quoted 9 lines
I have done basic testing along with power measurments on the different power rails on the AM335x EVM. PER domain transition on the BeagleBone fails if the CPSW driver is included in the kernel and is yet to be root caused. Along with this issue more extensive testing on other OMAP platforms is also pending right now.
For more details on the AM335x suspend-resume support please refer to the changelog in the different patches.
I still haven't reviewed patch 15, 16 and 18 which adds suspend support. Will do that in coming days since they need a bit a closer look.
Quoted 9 lines
But as mentioned in some of the patches, you need to split this series since except 15, 16 and 18 which adds suspend support, rest of the patches are
- data file fixes
- timer suspend/resume update
- mailbox support, control module update.Would be good to split the series to help the reviews.
Sure. I'll split it up like you mentioned. Since all these changes are needed for a working suspend-resume I kept it in a single series to reduce dependencies and also to help set an initial context for the AM33xx PM changes.
Regards,
Vaibhav