Merge branch 'pm-domains' into pm-for-linus
* pm-domains: ARM: mach-shmobile: sh7372 A4R support (v4) ARM: mach-shmobile: sh7372 A3SP support (v4) PM / Sleep: Mark devices involved in wakeup signaling during suspend
This commit is contained in:
Коммит
d033e07856
|
@ -1409,6 +1409,11 @@ static void __init ap4evb_init(void)
|
|||
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
|
||||
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
|
||||
|
||||
hdmi_init_pm_clock();
|
||||
fsi_init_pm_clock();
|
||||
sh7372_pm_init();
|
||||
|
|
|
@ -1588,6 +1588,15 @@ static void __init mackerel_init(void)
|
|||
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
|
||||
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
|
||||
#endif
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
|
||||
|
||||
hdmi_init_pm_clock();
|
||||
sh7372_pm_init();
|
||||
|
|
|
@ -479,7 +479,12 @@ struct platform_device;
|
|||
|
||||
struct sh7372_pm_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
struct dev_power_governor *gov;
|
||||
void (*suspend)(void);
|
||||
void (*resume)(void);
|
||||
unsigned int bit_shift;
|
||||
bool no_debug;
|
||||
bool stay_on;
|
||||
};
|
||||
|
||||
static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
|
||||
|
@ -491,8 +496,10 @@ static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
|
|||
extern struct sh7372_pm_domain sh7372_a4lc;
|
||||
extern struct sh7372_pm_domain sh7372_a4mp;
|
||||
extern struct sh7372_pm_domain sh7372_d4;
|
||||
extern struct sh7372_pm_domain sh7372_a4r;
|
||||
extern struct sh7372_pm_domain sh7372_a3rv;
|
||||
extern struct sh7372_pm_domain sh7372_a3ri;
|
||||
extern struct sh7372_pm_domain sh7372_a3sp;
|
||||
extern struct sh7372_pm_domain sh7372_a3sg;
|
||||
|
||||
extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
|
||||
|
@ -506,4 +513,7 @@ extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
|
|||
#define sh7372_pm_add_subdomain(pd, sd) do { } while(0)
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
extern void sh7372_intcs_suspend(void);
|
||||
extern void sh7372_intcs_resume(void);
|
||||
|
||||
#endif /* __ASM_SH7372_H__ */
|
||||
|
|
|
@ -606,9 +606,16 @@ static void intcs_demux(unsigned int irq, struct irq_desc *desc)
|
|||
generic_handle_irq(intcs_evt2irq(evtcodeas));
|
||||
}
|
||||
|
||||
static void __iomem *intcs_ffd2;
|
||||
static void __iomem *intcs_ffd5;
|
||||
|
||||
void __init sh7372_init_irq(void)
|
||||
{
|
||||
void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
|
||||
void __iomem *intevtsa;
|
||||
|
||||
intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
|
||||
intevtsa = intcs_ffd2 + 0x100;
|
||||
intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
|
||||
|
||||
register_intc_controller(&intca_desc);
|
||||
register_intc_controller(&intcs_desc);
|
||||
|
@ -617,3 +624,46 @@ void __init sh7372_init_irq(void)
|
|||
irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
|
||||
irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
|
||||
}
|
||||
|
||||
static unsigned short ffd2[0x200];
|
||||
static unsigned short ffd5[0x100];
|
||||
|
||||
void sh7372_intcs_suspend(void)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0x00; k <= 0x30; k += 4)
|
||||
ffd2[k] = __raw_readw(intcs_ffd2 + k);
|
||||
|
||||
for (k = 0x80; k <= 0xb0; k += 4)
|
||||
ffd2[k] = __raw_readb(intcs_ffd2 + k);
|
||||
|
||||
for (k = 0x180; k <= 0x188; k += 4)
|
||||
ffd2[k] = __raw_readb(intcs_ffd2 + k);
|
||||
|
||||
for (k = 0x00; k <= 0x3c; k += 4)
|
||||
ffd5[k] = __raw_readw(intcs_ffd5 + k);
|
||||
|
||||
for (k = 0x80; k <= 0x9c; k += 4)
|
||||
ffd5[k] = __raw_readb(intcs_ffd5 + k);
|
||||
}
|
||||
|
||||
void sh7372_intcs_resume(void)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0x00; k <= 0x30; k += 4)
|
||||
__raw_writew(ffd2[k], intcs_ffd2 + k);
|
||||
|
||||
for (k = 0x80; k <= 0xb0; k += 4)
|
||||
__raw_writeb(ffd2[k], intcs_ffd2 + k);
|
||||
|
||||
for (k = 0x180; k <= 0x188; k += 4)
|
||||
__raw_writeb(ffd2[k], intcs_ffd2 + k);
|
||||
|
||||
for (k = 0x00; k <= 0x3c; k += 4)
|
||||
__raw_writew(ffd5[k], intcs_ffd5 + k);
|
||||
|
||||
for (k = 0x80; k <= 0x9c; k += 4)
|
||||
__raw_writeb(ffd5[k], intcs_ffd5 + k);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#define SPDCR 0xe6180008
|
||||
#define SWUCR 0xe6180014
|
||||
#define SBAR 0xe6180020
|
||||
#define WUPRMSK 0xe6180028
|
||||
#define WUPSMSK 0xe618002c
|
||||
#define WUPSMSK2 0xe6180048
|
||||
#define PSTR 0xe6180080
|
||||
|
@ -80,6 +81,12 @@ static int pd_power_down(struct generic_pm_domain *genpd)
|
|||
struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
|
||||
unsigned int mask = 1 << sh7372_pd->bit_shift;
|
||||
|
||||
if (sh7372_pd->suspend)
|
||||
sh7372_pd->suspend();
|
||||
|
||||
if (sh7372_pd->stay_on)
|
||||
return 0;
|
||||
|
||||
if (__raw_readl(PSTR) & mask) {
|
||||
unsigned int retry_count;
|
||||
|
||||
|
@ -92,8 +99,9 @@ static int pd_power_down(struct generic_pm_domain *genpd)
|
|||
}
|
||||
}
|
||||
|
||||
pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
|
||||
mask, __raw_readl(PSTR));
|
||||
if (!sh7372_pd->no_debug)
|
||||
pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
|
||||
mask, __raw_readl(PSTR));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -105,6 +113,9 @@ static int pd_power_up(struct generic_pm_domain *genpd)
|
|||
unsigned int retry_count;
|
||||
int ret = 0;
|
||||
|
||||
if (sh7372_pd->stay_on)
|
||||
goto out;
|
||||
|
||||
if (__raw_readl(PSTR) & mask)
|
||||
goto out;
|
||||
|
||||
|
@ -121,23 +132,42 @@ static int pd_power_up(struct generic_pm_domain *genpd)
|
|||
if (__raw_readl(SWUCR) & mask)
|
||||
ret = -EIO;
|
||||
|
||||
if (!sh7372_pd->no_debug)
|
||||
pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
|
||||
mask, __raw_readl(PSTR));
|
||||
|
||||
out:
|
||||
pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
|
||||
mask, __raw_readl(PSTR));
|
||||
if (ret == 0 && sh7372_pd->resume)
|
||||
sh7372_pd->resume();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sh7372_a4r_suspend(void)
|
||||
{
|
||||
sh7372_intcs_suspend();
|
||||
__raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
|
||||
}
|
||||
|
||||
static bool pd_active_wakeup(struct device *dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dev_power_governor sh7372_always_on_gov = {
|
||||
.power_down_ok = sh7372_power_down_forbidden,
|
||||
};
|
||||
|
||||
void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
|
||||
{
|
||||
struct generic_pm_domain *genpd = &sh7372_pd->genpd;
|
||||
|
||||
pm_genpd_init(genpd, NULL, false);
|
||||
pm_genpd_init(genpd, sh7372_pd->gov, false);
|
||||
genpd->stop_device = pm_clk_suspend;
|
||||
genpd->start_device = pm_clk_resume;
|
||||
genpd->dev_irq_safe = true;
|
||||
|
@ -175,6 +205,14 @@ struct sh7372_pm_domain sh7372_d4 = {
|
|||
.bit_shift = 3,
|
||||
};
|
||||
|
||||
struct sh7372_pm_domain sh7372_a4r = {
|
||||
.bit_shift = 5,
|
||||
.gov = &sh7372_always_on_gov,
|
||||
.suspend = sh7372_a4r_suspend,
|
||||
.resume = sh7372_intcs_resume,
|
||||
.stay_on = true,
|
||||
};
|
||||
|
||||
struct sh7372_pm_domain sh7372_a3rv = {
|
||||
.bit_shift = 6,
|
||||
};
|
||||
|
@ -183,6 +221,12 @@ struct sh7372_pm_domain sh7372_a3ri = {
|
|||
.bit_shift = 8,
|
||||
};
|
||||
|
||||
struct sh7372_pm_domain sh7372_a3sp = {
|
||||
.bit_shift = 11,
|
||||
.gov = &sh7372_always_on_gov,
|
||||
.no_debug = true,
|
||||
};
|
||||
|
||||
struct sh7372_pm_domain sh7372_a3sg = {
|
||||
.bit_shift = 13,
|
||||
};
|
||||
|
@ -422,6 +466,9 @@ void __init sh7372_pm_init(void)
|
|||
__raw_writel(0x0000a501, DBGREG9);
|
||||
__raw_writel(0x00000000, DBGREG1);
|
||||
|
||||
/* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
|
||||
__raw_writel(0, PDNSEL);
|
||||
|
||||
sh7372_suspend_init();
|
||||
sh7372_cpuidle_init();
|
||||
}
|
||||
|
|
|
@ -991,11 +991,14 @@ void __init sh7372_add_standard_devices(void)
|
|||
sh7372_init_pm_domain(&sh7372_a4lc);
|
||||
sh7372_init_pm_domain(&sh7372_a4mp);
|
||||
sh7372_init_pm_domain(&sh7372_d4);
|
||||
sh7372_init_pm_domain(&sh7372_a4r);
|
||||
sh7372_init_pm_domain(&sh7372_a3rv);
|
||||
sh7372_init_pm_domain(&sh7372_a3ri);
|
||||
sh7372_init_pm_domain(&sh7372_a3sg);
|
||||
sh7372_init_pm_domain(&sh7372_a3sp);
|
||||
|
||||
sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
|
||||
sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
|
||||
|
||||
platform_add_devices(sh7372_early_devices,
|
||||
ARRAY_SIZE(sh7372_early_devices));
|
||||
|
@ -1006,6 +1009,25 @@ void __init sh7372_add_standard_devices(void)
|
|||
sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
|
||||
sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
|
||||
}
|
||||
|
||||
void __init sh7372_add_early_devices(void)
|
||||
|
|
|
@ -714,7 +714,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (device_may_wakeup(dev)
|
||||
if (dev->power.wakeup_path
|
||||
&& genpd->active_wakeup && genpd->active_wakeup(dev))
|
||||
return 0;
|
||||
|
||||
|
@ -938,7 +938,7 @@ static int pm_genpd_dev_poweroff_noirq(struct device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (device_may_wakeup(dev)
|
||||
if (dev->power.wakeup_path
|
||||
&& genpd->active_wakeup && genpd->active_wakeup(dev))
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -917,7 +917,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
|||
}
|
||||
|
||||
End:
|
||||
dev->power.is_suspended = !error;
|
||||
if (!error) {
|
||||
dev->power.is_suspended = true;
|
||||
if (dev->power.wakeup_path && dev->parent)
|
||||
dev->parent->power.wakeup_path = true;
|
||||
}
|
||||
|
||||
device_unlock(dev);
|
||||
complete_all(&dev->power.completion);
|
||||
|
@ -1020,6 +1024,8 @@ static int device_prepare(struct device *dev, pm_message_t state)
|
|||
|
||||
device_lock(dev);
|
||||
|
||||
dev->power.wakeup_path = device_may_wakeup(dev);
|
||||
|
||||
if (dev->pm_domain) {
|
||||
pm_dev_dbg(dev, state, "preparing power domain ");
|
||||
if (dev->pm_domain->ops.prepare)
|
||||
|
|
|
@ -452,6 +452,7 @@ struct dev_pm_info {
|
|||
struct list_head entry;
|
||||
struct completion completion;
|
||||
struct wakeup_source *wakeup;
|
||||
bool wakeup_path:1;
|
||||
#else
|
||||
unsigned int should_wakeup:1;
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче