Skip to content

Commit

Permalink
Merge tag 'omap-devel-a-for-3.8' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/pjw/omap-pending into omap-for-v3.8/devel-pcrm

Some miscellaneous OMAP hwmod changes for 3.8, along with a PRM
change needed for one of the hwmod patches to function.

Basic test logs for this branch on top of Tony's
omap-for-v3.8/clock branch at commit
558a078 are here:

http://www.pwsan.com/omap/testlogs/hwmod_devel_a_3.8/20121121161522/

However, omap-for-v3.8/clock at 558a078 does not include some fixes
that are needed for a successful test.  With several reverts,
fixes, and workarounds applied, the following test logs were
obtained:

http://www.pwsan.com/omap/testlogs/TEST_hwmod_devel_a_3.8/20121121162719/

which indicate that the series tests cleanly.
  • Loading branch information
Tony Lindgren committed Nov 26, 2012
2 parents 558a078 + c567b05 commit 8b9c1ac
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 70 deletions.
8 changes: 8 additions & 0 deletions arch/arm/mach-omap2/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
#include "prcm_mpu44xx.h"
#include "prminst44xx.h"
#include "cminst44xx.h"
#include "prm2xxx.h"
#include "prm3xxx.h"
#include "prm44xx.h"

/*
* The machine specific code may provide the extra mapping besides the
* default mapping provided here.
Expand Down Expand Up @@ -392,6 +396,7 @@ void __init omap2420_init_early(void)
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE));
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE), NULL);
omap2xxx_check_revision();
omap2xxx_prm_init();
omap2xxx_cm_init();
omap_common_init_early();
omap2xxx_voltagedomains_init();
Expand Down Expand Up @@ -422,6 +427,7 @@ void __init omap2430_init_early(void)
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE));
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE), NULL);
omap2xxx_check_revision();
omap2xxx_prm_init();
omap2xxx_cm_init();
omap_common_init_early();
omap2xxx_voltagedomains_init();
Expand Down Expand Up @@ -457,6 +463,7 @@ void __init omap3_init_early(void)
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE), NULL);
omap3xxx_check_revision();
omap3xxx_check_features();
omap3xxx_prm_init();
omap3xxx_cm_init();
omap_common_init_early();
omap3xxx_voltagedomains_init();
Expand Down Expand Up @@ -591,6 +598,7 @@ void __init omap4430_init_early(void)
omap_cm_base_init();
omap4xxx_check_revision();
omap4xxx_check_features();
omap44xx_prm_init();
omap_common_init_early();
omap44xx_voltagedomains_init();
omap44xx_powerdomains_init();
Expand Down
87 changes: 55 additions & 32 deletions arch/arm/mach-omap2/omap_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,19 +441,21 @@ int omap_device_get_context_loss_count(struct platform_device *pdev)
/**
* omap_device_count_resources - count number of struct resource entries needed
* @od: struct omap_device *
* @flags: Type of resources to include when counting (IRQ/DMA/MEM)
*
* Count the number of struct resource entries needed for this
* omap_device @od. Used by omap_device_build_ss() to determine how
* much memory to allocate before calling
* omap_device_fill_resources(). Returns the count.
*/
static int omap_device_count_resources(struct omap_device *od)
static int omap_device_count_resources(struct omap_device *od,
unsigned long flags)
{
int c = 0;
int i;

for (i = 0; i < od->hwmods_cnt; i++)
c += omap_hwmod_count_resources(od->hwmods[i]);
c += omap_hwmod_count_resources(od->hwmods[i], flags);

pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
od->pdev->name, c, od->hwmods_cnt);
Expand Down Expand Up @@ -557,52 +559,73 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
od->hwmods = hwmods;
od->pdev = pdev;

res_count = omap_device_count_resources(od);
/*
* Non-DT Boot:
* Here, pdev->num_resources = 0, and we should get all the
* resources from hwmod.
*
* DT Boot:
* OF framework will construct the resource structure (currently
* does for MEM & IRQ resource) and we should respect/use these
* resources, killing hwmod dependency.
* If pdev->num_resources > 0, we assume that MEM & IRQ resources
* have been allocated by OF layer already (through DTB).
*
* Non-DT Boot:
* Here, pdev->num_resources = 0, and we should get all the
* resources from hwmod.
* As preparation for the future we examine the OF provided resources
* to see if we have DMA resources provided already. In this case
* there is no need to update the resources for the device, we use the
* OF provided ones.
*
* TODO: Once DMA resource is available from OF layer, we should
* kill filling any resources from hwmod.
*/
if (res_count > pdev->num_resources) {
/* Allocate resources memory to account for new resources */
res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
if (!res)
goto oda_exit3;

/*
* If pdev->num_resources > 0, then assume that,
* MEM and IRQ resources will only come from DT and only
* fill DMA resource from hwmod layer.
*/
if (pdev->num_resources && pdev->resource) {
dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n",
__func__, res_count);
memcpy(res, pdev->resource,
sizeof(struct resource) * pdev->num_resources);
_od_fill_dma_resources(od, &res[pdev->num_resources]);
} else {
dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
__func__, res_count);
omap_device_fill_resources(od, res);
if (!pdev->num_resources) {
/* Count all resources for the device */
res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
IORESOURCE_DMA |
IORESOURCE_MEM);
} else {
/* Take a look if we already have DMA resource via DT */
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];

/* We have it, no need to touch the resources */
if (r->flags == IORESOURCE_DMA)
goto have_everything;
}
/* Count only DMA resources for the device */
res_count = omap_device_count_resources(od, IORESOURCE_DMA);
/* The device has no DMA resource, no need for update */
if (!res_count)
goto have_everything;

ret = platform_device_add_resources(pdev, res, res_count);
kfree(res);
res_count += pdev->num_resources;
}

if (ret)
goto oda_exit3;
/* Allocate resources memory to account for new resources */
res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
if (!res)
goto oda_exit3;

if (!pdev->num_resources) {
dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
__func__, res_count);
omap_device_fill_resources(od, res);
} else {
dev_dbg(&pdev->dev,
"%s: appending %d DMA resources from hwmod\n",
__func__, res_count - pdev->num_resources);
memcpy(res, pdev->resource,
sizeof(struct resource) * pdev->num_resources);
_od_fill_dma_resources(od, &res[pdev->num_resources]);
}

ret = platform_device_add_resources(pdev, res, res_count);
kfree(res);

if (ret)
goto oda_exit3;

have_everything:
if (!pm_lats) {
pm_lats = omap_default_latency;
pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
Expand Down
82 changes: 67 additions & 15 deletions arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ struct omap_hwmod_soc_ops {
int (*is_hardreset_asserted)(struct omap_hwmod *oh,
struct omap_hwmod_rst_info *ohri);
int (*init_clkdm)(struct omap_hwmod *oh);
void (*update_context_lost)(struct omap_hwmod *oh);
int (*get_context_lost)(struct omap_hwmod *oh);
};

/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
Expand Down Expand Up @@ -1982,6 +1984,42 @@ static void _reconfigure_io_chain(void)
spin_unlock_irqrestore(&io_chain_lock, flags);
}

/**
* _omap4_update_context_lost - increment hwmod context loss counter if
* hwmod context was lost, and clear hardware context loss reg
* @oh: hwmod to check for context loss
*
* If the PRCM indicates that the hwmod @oh lost context, increment
* our in-memory context loss counter, and clear the RM_*_CONTEXT
* bits. No return value.
*/
static void _omap4_update_context_lost(struct omap_hwmod *oh)
{
if (oh->prcm.omap4.flags & HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT)
return;

if (!prm_was_any_context_lost_old(oh->clkdm->pwrdm.ptr->prcm_partition,
oh->clkdm->pwrdm.ptr->prcm_offs,
oh->prcm.omap4.context_offs))
return;

oh->prcm.omap4.context_lost_counter++;
prm_clear_context_loss_flags_old(oh->clkdm->pwrdm.ptr->prcm_partition,
oh->clkdm->pwrdm.ptr->prcm_offs,
oh->prcm.omap4.context_offs);
}

/**
* _omap4_get_context_lost - get context loss counter for a hwmod
* @oh: hwmod to get context loss counter for
*
* Returns the in-memory context loss counter for a hwmod.
*/
static int _omap4_get_context_lost(struct omap_hwmod *oh)
{
return oh->prcm.omap4.context_lost_counter;
}

/**
* _enable - enable an omap_hwmod
* @oh: struct omap_hwmod *
Expand Down Expand Up @@ -2065,6 +2103,9 @@ static int _enable(struct omap_hwmod *oh)
if (soc_ops.enable_module)
soc_ops.enable_module(oh);

if (soc_ops.update_context_lost)
soc_ops.update_context_lost(oh);

r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) :
-EINVAL;
if (!r) {
Expand Down Expand Up @@ -3386,7 +3427,7 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
/**
* omap_hwmod_count_resources - count number of struct resources needed by hwmod
* @oh: struct omap_hwmod *
* @res: pointer to the first element of an array of struct resource to fill
* @flags: Type of resources to include when counting (IRQ/DMA/MEM)
*
* Count the number of struct resource array elements necessary to
* contain omap_hwmod @oh resources. Intended to be called by code
Expand All @@ -3399,20 +3440,25 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
* resource IDs.
*
*/
int omap_hwmod_count_resources(struct omap_hwmod *oh)
int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags)
{
struct omap_hwmod_ocp_if *os;
struct list_head *p;
int ret;
int i = 0;
int ret = 0;

ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
if (flags & IORESOURCE_IRQ)
ret += _count_mpu_irqs(oh);

p = oh->slave_ports.next;
if (flags & IORESOURCE_DMA)
ret += _count_sdma_reqs(oh);

while (i < oh->slaves_cnt) {
os = _fetch_next_ocp_if(&p, &i);
ret += _count_ocp_if_addr_spaces(os);
if (flags & IORESOURCE_MEM) {
int i = 0;
struct omap_hwmod_ocp_if *os;
struct list_head *p = oh->slave_ports.next;

while (i < oh->slaves_cnt) {
os = _fetch_next_ocp_if(&p, &i);
ret += _count_ocp_if_addr_spaces(os);
}
}

return ret;
Expand Down Expand Up @@ -3907,17 +3953,21 @@ int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
* omap_hwmod_get_context_loss_count - get lost context count
* @oh: struct omap_hwmod *
*
* Query the powerdomain of of @oh to get the context loss
* count for this device.
* Returns the context loss count of associated @oh
* upon success, or zero if no context loss data is available.
*
* Returns the context loss count of the powerdomain assocated with @oh
* upon success, or zero if no powerdomain exists for @oh.
* On OMAP4, this queries the per-hwmod context loss register,
* assuming one exists. If not, or on OMAP2/3, this queries the
* enclosing powerdomain context loss count.
*/
int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
{
struct powerdomain *pwrdm;
int ret = 0;

if (soc_ops.get_context_lost)
return soc_ops.get_context_lost(oh);

pwrdm = omap_hwmod_get_pwrdm(oh);
if (pwrdm)
ret = pwrdm_get_context_loss_count(pwrdm);
Expand Down Expand Up @@ -4032,6 +4082,8 @@ void __init omap_hwmod_init(void)
soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
soc_ops.init_clkdm = _init_clkdm;
soc_ops.update_context_lost = _omap4_update_context_lost;
soc_ops.get_context_lost = _omap4_get_context_lost;
} else if (soc_is_am33xx()) {
soc_ops.enable_module = _am33xx_enable_module;
soc_ops.disable_module = _am33xx_disable_module;
Expand Down
12 changes: 8 additions & 4 deletions arch/arm/mach-omap2/omap_hwmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* omap_hwmod macros, structures
*
* Copyright (C) 2009-2011 Nokia Corporation
* Copyright (C) 2012 Texas Instruments, Inc.
* Copyright (C) 2011-2012 Texas Instruments, Inc.
* Paul Walmsley
*
* Created in collaboration with (alphabetical order): Benoît Cousson,
Expand Down Expand Up @@ -394,12 +394,15 @@ struct omap_hwmod_omap2_prcm {

/**
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
* @clkctrl_reg: PRCM address of the clock control register
* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
* @clkctrl_offs: offset of the PRCM clock control register
* @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM
* @context_offs: offset of the RM_*_CONTEXT register
* @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register
* @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
* @submodule_wkdep_bit: bit shift of the WKDEP range
* @flags: PRCM register capabilities for this IP block
* @modulemode: allowable modulemodes
* @context_lost_counter: Count of module level context lost
*
* If @lostcontext_mask is not defined, context loss check code uses
* whole register without masking. @lostcontext_mask should only be
Expand All @@ -415,6 +418,7 @@ struct omap_hwmod_omap4_prcm {
u8 submodule_wkdep_bit;
u8 modulemode;
u8 flags;
int context_lost_counter;
};


Expand Down Expand Up @@ -627,7 +631,7 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
int omap_hwmod_softreset(struct omap_hwmod *oh);

int omap_hwmod_count_resources(struct omap_hwmod *oh);
int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags);
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res);
int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
Expand Down
11 changes: 10 additions & 1 deletion arch/arm/mach-omap2/prm.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,25 @@ struct prm_reset_src_map {

/**
* struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
* @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
* @read_reset_sources: ptr to the SoC PRM-specific get_reset_source impl
* @was_any_context_lost_old: ptr to the SoC PRM context loss test fn
* @clear_context_loss_flags_old: ptr to the SoC PRM context loss flag clear fn
*
* XXX @was_any_context_lost_old and @clear_context_loss_flags_old are
* deprecated.
*/
struct prm_ll_data {
u32 (*read_reset_sources)(void);
bool (*was_any_context_lost_old)(u8 part, s16 inst, u16 idx);
void (*clear_context_loss_flags_old)(u8 part, s16 inst, u16 idx);
};

extern int prm_register(struct prm_ll_data *pld);
extern int prm_unregister(struct prm_ll_data *pld);

extern u32 prm_read_reset_sources(void);
extern bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx);
extern void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx);

#endif

Expand Down
3 changes: 1 addition & 2 deletions arch/arm/mach-omap2/prm2xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,13 @@ static struct prm_ll_data omap2xxx_prm_ll_data = {
.read_reset_sources = &omap2xxx_prm_read_reset_sources,
};

static int __init omap2xxx_prm_init(void)
int __init omap2xxx_prm_init(void)
{
if (!cpu_is_omap24xx())
return 0;

return prm_register(&omap2xxx_prm_ll_data);
}
subsys_initcall(omap2xxx_prm_init);

static void __exit omap2xxx_prm_exit(void)
{
Expand Down
Loading

0 comments on commit 8b9c1ac

Please sign in to comment.