Skip to content

Commit

Permalink
usb: musb: dsps: add support for suspend and resume
Browse files Browse the repository at this point in the history
The dsps platform needs to save save some registers at suspend time and
restore them after resume. This patch adds a struct for these registers,
and also lets the musb core know that the core registers need to be
saved as well.

We also have to explicitly de-assert the port reset upon resume on this
platform, but musb_port_reset() should not be called from glue layers.

Hence, introduce a flag in struct musb_hdrc_config for this.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Daniel Mack authored and Felipe Balbi committed Nov 26, 2013
1 parent b991f9b commit 869c597
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 2 deletions.
57 changes: 57 additions & 0 deletions drivers/usb/musb/musb_dsps.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ struct dsps_musb_wrapper {
u8 poll_seconds;
};

/*
* register shadow for suspend
*/
struct dsps_context {
u32 control;
u32 epintr;
u32 coreintr;
u32 phy_utmi;
u32 mode;
u32 tx_mode;
u32 rx_mode;
};

/**
* DSPS glue structure.
*/
Expand All @@ -122,6 +135,8 @@ struct dsps_glue {
const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
struct timer_list timer; /* otg_workaround timer */
unsigned long last_timer; /* last timer data for each instance */

struct dsps_context context;
};

static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
Expand Down Expand Up @@ -559,6 +574,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,

config->num_eps = get_int_prop(dn, "mentor,num-eps");
config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
config->host_port_deassert_reset_at_resume = 1;
pdata.mode = get_musb_port_mode(dev);
/* DT keeps this entry in mA, musb expects it as per USB spec */
pdata.power = get_int_prop(dn, "mentor,power") / 2;
Expand Down Expand Up @@ -683,11 +699,52 @@ static const struct of_device_id musb_dsps_of_match[] = {
};
MODULE_DEVICE_TABLE(of, musb_dsps_of_match);

#ifdef CONFIG_PM
static int dsps_suspend(struct device *dev)
{
struct dsps_glue *glue = dev_get_drvdata(dev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
struct musb *musb = platform_get_drvdata(glue->musb);
void __iomem *mbase = musb->ctrl_base;

glue->context.control = dsps_readl(mbase, wrp->control);
glue->context.epintr = dsps_readl(mbase, wrp->epintr_set);
glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set);
glue->context.phy_utmi = dsps_readl(mbase, wrp->phy_utmi);
glue->context.mode = dsps_readl(mbase, wrp->mode);
glue->context.tx_mode = dsps_readl(mbase, wrp->tx_mode);
glue->context.rx_mode = dsps_readl(mbase, wrp->rx_mode);

return 0;
}

static int dsps_resume(struct device *dev)
{
struct dsps_glue *glue = dev_get_drvdata(dev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
struct musb *musb = platform_get_drvdata(glue->musb);
void __iomem *mbase = musb->ctrl_base;

dsps_writel(mbase, wrp->control, glue->context.control);
dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
dsps_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
dsps_writel(mbase, wrp->mode, glue->context.mode);
dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);

return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);

static struct platform_driver dsps_usbss_driver = {
.probe = dsps_probe,
.remove = dsps_remove,
.driver = {
.name = "musb-dsps",
.pm = &dsps_pm_ops,
.of_match_table = musb_dsps_of_match,
},
};
Expand Down
7 changes: 6 additions & 1 deletion drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -2464,7 +2464,12 @@ static int musb_bus_suspend(struct usb_hcd *hcd)

static int musb_bus_resume(struct usb_hcd *hcd)
{
/* resuming child port does the work */
struct musb *musb = hcd_to_musb(hcd);

if (musb->config &&
musb->config->host_port_deassert_reset_at_resume)
musb_port_reset(musb, false);

return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/musb/musb_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ extern void musb_root_disconnect(struct musb *musb);
extern void musb_host_resume_root_hub(struct musb *musb);
extern void musb_host_poke_root_hub(struct musb *musb);
extern void musb_port_suspend(struct musb *musb, bool do_suspend);
extern void musb_port_reset(struct musb *musb, bool do_reset);
#else
static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
{
Expand Down Expand Up @@ -123,6 +124,7 @@ static inline void musb_host_resume_root_hub(struct musb *musb) {}
static inline void musb_host_poll_rh_status(struct musb *musb) {}
static inline void musb_host_poke_root_hub(struct musb *musb) {}
static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {}
static inline void musb_port_reset(struct musb *musb) {}
#endif

struct usb_hcd;
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/musb/musb_virthub.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
}
}

static void musb_port_reset(struct musb *musb, bool do_reset)
void musb_port_reset(struct musb *musb, bool do_reset)
{
u8 power;
void __iomem *mbase = musb->mregs;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/usb/musb.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ struct musb_hdrc_config {
unsigned dma:1 __deprecated; /* supports DMA */
unsigned vendor_req:1 __deprecated; /* vendor registers required */

/* need to explicitly de-assert the port reset after resume? */
unsigned host_port_deassert_reset_at_resume:1;

u8 num_eps; /* number of endpoints _with_ ep0 */
u8 dma_channels __deprecated; /* number of dma channels */
u8 dyn_fifo_size; /* dynamic size in bytes */
Expand Down

0 comments on commit 869c597

Please sign in to comment.