Skip to content

Commit

Permalink
Merge branch 'renesas-soc-core' into renesas-sh7372
Browse files Browse the repository at this point in the history
* renesas-soc-core:
  ARM: shmobile: soc-core: add R-mobile PM domain common APIs
  ARM: mach-shmobile: Convert sh_clk_mstp32_register to sh_clk_mstp_register
  • Loading branch information
Rafael J. Wysocki committed Jul 6, 2012
2 parents 3abd69d + 8f45b11 commit de5c094
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 6 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-shmobile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o
obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-shmobile/clock-r8a7740.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ void __init r8a7740_clock_init(u8 md_ck)
ret = sh_clk_div6_register(div6_clks, DIV6_NR);

if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);

clkdev_add_table(lookups, ARRAY_SIZE(lookups));

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-shmobile/clock-r8a7779.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void __init r8a7779_clock_init(void)
ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);

if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);

for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
ret = clk_register(late_main_clks[k]);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-shmobile/clock-sh7367.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ void __init sh7367_clock_init(void)
ret = sh_clk_div6_register(div6_clks, DIV6_NR);

if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);

clkdev_add_table(lookups, ARRAY_SIZE(lookups));

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-shmobile/clock-sh7372.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ void __init sh7372_clock_init(void)
ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);

if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);

for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
ret = clk_register(late_main_clks[k]);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-shmobile/clock-sh7377.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ void __init sh7377_clock_init(void)
ret = sh_clk_div6_register(div6_clks, DIV6_NR);

if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);

clkdev_add_table(lookups, ARRAY_SIZE(lookups));

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-shmobile/clock-sh73a0.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ void __init sh73a0_clock_init(void)
ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);

if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);

for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
ret = clk_register(late_main_clks[k]);
Expand Down
44 changes: 44 additions & 0 deletions arch/arm/mach-shmobile/include/mach/pm-rmobile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2012 Renesas Solutions Corp.
*
* Kuninori Morimoto <morimoto.kuninori@renesas.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef PM_RMOBILE_H
#define PM_RMOBILE_H

#include <linux/pm_domain.h>

struct platform_device;

struct rmobile_pm_domain {
struct generic_pm_domain genpd;
struct dev_power_governor *gov;
int (*suspend)(void);
void (*resume)(void);
unsigned int bit_shift;
bool no_debug;
};

static inline
struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
{
return container_of(d, struct rmobile_pm_domain, genpd);
}

#ifdef CONFIG_PM
extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd);
extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
struct platform_device *pdev);
extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
struct rmobile_pm_domain *rmobile_sd);
#else
#define rmobile_init_pm_domain(pd) do { } while (0)
#define rmobile_add_device_to_domain(pd, pdev) do { } while (0)
#define rmobile_pm_add_subdomain(pd, sd) do { } while (0)
#endif /* CONFIG_PM */

#endif /* PM_RMOBILE_H */
167 changes: 167 additions & 0 deletions arch/arm/mach-shmobile/pm-rmobile.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* rmobile power management support
*
* Copyright (C) 2012 Renesas Solutions Corp.
* Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* based on pm-sh7372.c
* Copyright (C) 2011 Magnus Damm
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_clock.h>
#include <asm/io.h>
#include <mach/pm-rmobile.h>

/* SYSC */
#define SPDCR 0xe6180008
#define SWUCR 0xe6180014
#define PSTR 0xe6180080

#define PSTR_RETRIES 100
#define PSTR_DELAY_US 10

#ifdef CONFIG_PM
static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
{
struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
unsigned int mask = 1 << rmobile_pd->bit_shift;

if (rmobile_pd->suspend) {
int ret = rmobile_pd->suspend();

if (ret)
return ret;
}

if (__raw_readl(PSTR) & mask) {
unsigned int retry_count;
__raw_writel(mask, SPDCR);

for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
if (!(__raw_readl(SPDCR) & mask))
break;
cpu_relax();
}
}

if (!rmobile_pd->no_debug)
pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
genpd->name, mask, __raw_readl(PSTR));

return 0;
}

static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
bool do_resume)
{
unsigned int mask = 1 << rmobile_pd->bit_shift;
unsigned int retry_count;
int ret = 0;

if (__raw_readl(PSTR) & mask)
goto out;

__raw_writel(mask, SWUCR);

for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
if (!(__raw_readl(SWUCR) & mask))
break;
if (retry_count > PSTR_RETRIES)
udelay(PSTR_DELAY_US);
else
cpu_relax();
}
if (!retry_count)
ret = -EIO;

if (!rmobile_pd->no_debug)
pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
rmobile_pd->genpd.name, mask, __raw_readl(PSTR));

out:
if (ret == 0 && rmobile_pd->resume && do_resume)
rmobile_pd->resume();

return ret;
}

static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
{
return __rmobile_pd_power_up(to_rmobile_pd(genpd), true);
}

static bool rmobile_pd_active_wakeup(struct device *dev)
{
bool (*active_wakeup)(struct device *dev);

active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
return active_wakeup ? active_wakeup(dev) : true;
}

static int rmobile_pd_stop_dev(struct device *dev)
{
int (*stop)(struct device *dev);

stop = dev_gpd_data(dev)->ops.stop;
if (stop) {
int ret = stop(dev);
if (ret)
return ret;
}
return pm_clk_suspend(dev);
}

static int rmobile_pd_start_dev(struct device *dev)
{
int (*start)(struct device *dev);
int ret;

ret = pm_clk_resume(dev);
if (ret)
return ret;

start = dev_gpd_data(dev)->ops.start;
if (start)
ret = start(dev);

return ret;
}

void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
{
struct generic_pm_domain *genpd = &rmobile_pd->genpd;
struct dev_power_governor *gov = rmobile_pd->gov;

pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
genpd->dev_ops.stop = rmobile_pd_stop_dev;
genpd->dev_ops.start = rmobile_pd_start_dev;
genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
genpd->dev_irq_safe = true;
genpd->power_off = rmobile_pd_power_down;
genpd->power_on = rmobile_pd_power_up;
__rmobile_pd_power_up(rmobile_pd, false);
}

void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;

pm_genpd_add_device(&rmobile_pd->genpd, dev);
if (pm_clk_no_clocks(dev))
pm_clk_add(dev, NULL);
}

void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
struct rmobile_pm_domain *rmobile_sd)
{
pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd);
}
#endif /* CONFIG_PM */

0 comments on commit de5c094

Please sign in to comment.