Skip to content

Commit

Permalink
ARM: OMAP AM33xx: powerdomains: add AM335x support
Browse files Browse the repository at this point in the history
Add offset & mask fields to struct powerdomain

In case of AM33xx family of devices, there is no consistency between
PWRSTCTRL & PWRSTST register offsers in PRM space, for example -

PRM_XXX           PWRSTCTRL     PWRSTST
=======================================
PRM_PER_MOD:      0x0C,         0x08
PRM_WKUP_MOD:     0x04,         0x08
PRM_MPU_MOD:      0x00,         0x04
PRM_DEVICE_MOD:   NA,           NA

And also, there is no consistency between bit-offsets inside
PWRSTCTRL & PWRSTST register, for example -

PRM_XXX           LOGICRET  MEMON  MEMRET
=======================================
GFX_PWRCTRL:      2,        17,    6
PER_PWRCTRL:      3,        25,    29
MPU_PWRCTRL:      2,        18,    22
WKUP_PWRCTRL:     3,        NA,    NA

This means, we need to maintain and pass on all this information
in powerdomain handle; so adding fields for,
   - PWRSTCTRL/ST register offset
   - Logic retention state mask
   - mem_on/ret/pwrst/retst mask

Currently, this fields is only applicable and used for AM33XX devices.

Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Rajendra Nayak <rnayak@ti.com>
[paul@pwsan.com: this patch is a combination of "Add offset & mask fields to
 struct powerdomain" and the powerdomain portions of "ARM: OMAP3+: am33xx:
 Add powerdomain & PRM support"; updated for 3.5]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
  • Loading branch information
Vaibhav Hiremath authored and Paul Walmsley committed Jun 18, 2012
1 parent f969a6d commit 3f0ea76
Show file tree
Hide file tree
Showing 5 changed files with 438 additions and 2 deletions.
2 changes: 2 additions & 0 deletions arch/arm/mach-omap2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ obj-$(CONFIG_ARCH_OMAP3) += powerdomains2xxx_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common)
obj-$(CONFIG_ARCH_OMAP4) += powerdomain44xx.o
obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o
obj-$(CONFIG_SOC_AM33XX) += powerdomain33xx.o
obj-$(CONFIG_SOC_AM33XX) += powerdomains33xx_data.o

# PRCM clockdomain control
clockdomain-common += clockdomain.o
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-omap2/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ void __init am33xx_init_early(void)
ti81xx_check_features();
omap_common_init_early();
am33xx_voltagedomains_init();
am33xx_powerdomains_init();
}
#endif

Expand Down
23 changes: 21 additions & 2 deletions arch/arm/mach-omap2/powerdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@

/*
* Maximum number of clockdomains that can be associated with a powerdomain.
* CORE powerdomain on OMAP4 is the worst case
* PER powerdomain on AM33XX is the worst case
*/
#define PWRDM_MAX_CLKDMS 9
#define PWRDM_MAX_CLKDMS 11

/* XXX A completely arbitrary number. What is reasonable here? */
#define PWRDM_TRANSITION_BAILOUT 100000
Expand All @@ -92,6 +92,15 @@ struct powerdomain;
* @pwrdm_clkdms: Clockdomains in this powerdomain
* @node: list_head linking all powerdomains
* @voltdm_node: list_head linking all powerdomains in a voltagedomain
* @pwrstctrl_offs: (AM33XX only) XXX_PWRSTCTRL reg offset from prcm_offs
* @pwrstst_offs: (AM33XX only) XXX_PWRSTST reg offset from prcm_offs
* @logicretstate_mask: (AM33XX only) mask for logic retention bitfield
* in @pwrstctrl_offs
* @mem_on_mask: (AM33XX only) mask for mem on bitfield in @pwrstctrl_offs
* @mem_ret_mask: (AM33XX only) mask for mem ret bitfield in @pwrstctrl_offs
* @mem_pwrst_mask: (AM33XX only) mask for mem state bitfield in @pwrstst_offs
* @mem_retst_mask: (AM33XX only) mask for mem retention state bitfield
* in @pwrstctrl_offs
* @state:
* @state_counter:
* @timer:
Expand Down Expand Up @@ -121,6 +130,14 @@ struct powerdomain {
unsigned ret_logic_off_counter;
unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];

const u8 pwrstctrl_offs;
const u8 pwrstst_offs;
const u32 logicretstate_mask;
const u32 mem_on_mask[PWRDM_MAX_MEM_BANKS];
const u32 mem_ret_mask[PWRDM_MAX_MEM_BANKS];
const u32 mem_pwrst_mask[PWRDM_MAX_MEM_BANKS];
const u32 mem_retst_mask[PWRDM_MAX_MEM_BANKS];

#ifdef CONFIG_PM_DEBUG
s64 timer;
s64 state_timer[PWRDM_MAX_PWRSTS];
Expand Down Expand Up @@ -222,10 +239,12 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
extern void omap242x_powerdomains_init(void);
extern void omap243x_powerdomains_init(void);
extern void omap3xxx_powerdomains_init(void);
extern void am33xx_powerdomains_init(void);
extern void omap44xx_powerdomains_init(void);

extern struct pwrdm_ops omap2_pwrdm_operations;
extern struct pwrdm_ops omap3_pwrdm_operations;
extern struct pwrdm_ops am33xx_pwrdm_operations;
extern struct pwrdm_ops omap4_pwrdm_operations;

/* Common Internal functions used across OMAP rev's */
Expand Down
229 changes: 229 additions & 0 deletions arch/arm/mach-omap2/powerdomain33xx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* AM33XX Powerdomain control
*
* Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
*
* Derived from mach-omap2/powerdomain44xx.c written by Rajendra Nayak
* <rnayak@ti.com>
*
* 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/io.h>
#include <linux/errno.h>
#include <linux/delay.h>

#include <plat/prcm.h>

#include "powerdomain.h"
#include "prm33xx.h"
#include "prm-regbits-33xx.h"


static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
{
am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
(pwrst << OMAP_POWERSTATE_SHIFT),
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
return 0;
}

static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
{
u32 v;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
v &= OMAP_POWERSTATE_MASK;
v >>= OMAP_POWERSTATE_SHIFT;

return v;
}

static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
{
u32 v;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
v &= OMAP_POWERSTATEST_MASK;
v >>= OMAP_POWERSTATEST_SHIFT;

return v;
}

static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
{
u32 v;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;

return v;
}

static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
{
am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
(1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
return 0;
}

static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
{
am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
AM33XX_LASTPOWERSTATEENTERED_MASK,
pwrdm->prcm_offs, pwrdm->pwrstst_offs);
return 0;
}

static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
{
u32 m;

m = pwrdm->logicretstate_mask;
if (!m)
return -EINVAL;

am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);

return 0;
}

static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
{
u32 v;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
v &= AM33XX_LOGICSTATEST_MASK;
v >>= AM33XX_LOGICSTATEST_SHIFT;

return v;
}

static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
{
u32 v, m;

m = pwrdm->logicretstate_mask;
if (!m)
return -EINVAL;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
v &= m;
v >>= __ffs(m);

return v;
}

static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
u8 pwrst)
{
u32 m;

m = pwrdm->mem_on_mask[bank];
if (!m)
return -EINVAL;

am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);

return 0;
}

static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
u8 pwrst)
{
u32 m;

m = pwrdm->mem_ret_mask[bank];
if (!m)
return -EINVAL;

am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);

return 0;
}

static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
{
u32 m, v;

m = pwrdm->mem_pwrst_mask[bank];
if (!m)
return -EINVAL;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
v &= m;
v >>= __ffs(m);

return v;
}

static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
{
u32 m, v;

m = pwrdm->mem_retst_mask[bank];
if (!m)
return -EINVAL;

v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
v &= m;
v >>= __ffs(m);

return v;
}

static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
{
u32 c = 0;

/*
* REVISIT: pwrdm_wait_transition() may be better implemented
* via a callback and a periodic timer check -- how long do we expect
* powerdomain transitions to take?
*/

/* XXX Is this udelay() value meaningful? */
while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
& OMAP_INTRANSITION_MASK) &&
(c++ < PWRDM_TRANSITION_BAILOUT))
udelay(1);

if (c > PWRDM_TRANSITION_BAILOUT) {
pr_err("powerdomain: %s: waited too long to complete transition\n",
pwrdm->name);
return -EAGAIN;
}

pr_debug("powerdomain: completed transition in %d loops\n", c);

return 0;
}

struct pwrdm_ops am33xx_pwrdm_operations = {
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
.pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
.pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
.pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
.pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
.pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
.pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
.pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
.pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
.pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
.pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
.pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
.pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
};
Loading

0 comments on commit 3f0ea76

Please sign in to comment.