Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2092e5cc authored by Paul Walmsley's avatar Paul Walmsley
Browse files

OMAP2+: hwmod: add postsetup state



Allow board files and OMAP core code to control the state that some or
all of the hwmods end up in at the end of _setup() (called by
omap_hwmod_late_init() ).  Reimplement the old skip_setup_idle code in
terms of this new postsetup state code.

There are two use-cases for this patch: the !CONFIG_PM_RUNTIME case,
in which all IP blocks should stay enabled after _setup() finishes;
and the MPU watchdog case, in which the watchdog IP block should enter
idle if watchdog coverage of kernel initialization is desired, and
should be disabled otherwise.

Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
Cc: Benoît Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Charulatha Varadarajan <charu@ti.com>
parent e4dc8f50
Loading
Loading
Loading
Loading
+20 −12
Original line number Diff line number Diff line
@@ -312,6 +312,11 @@ static int __init _omap2_init_reprogram_sdrc(void)
	return v;
}

static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
{
	return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
}

/*
 * Initialize asm_irq_base for entry-macro.S
 */
@@ -333,6 +338,8 @@ static inline void omap_irq_base_init(void)

void __init omap2_init_common_infrastructure(void)
{
	u8 postsetup_state;

	pwrdm_init(powerdomains_omap);
	clkdm_init(clockdomains_omap, clkdm_autodeps);
	if (cpu_is_omap242x())
@@ -343,6 +350,16 @@ void __init omap2_init_common_infrastructure(void)
		omap3xxx_hwmod_init();
	else if (cpu_is_omap44xx())
		omap44xx_hwmod_init();
	else
		pr_err("Could not init hwmod data - unknown SoC\n");

	/* Set the default postsetup state for all hwmods */
#ifdef CONFIG_PM_RUNTIME
	postsetup_state = _HWMOD_STATE_IDLE;
#else
	postsetup_state = _HWMOD_STATE_ENABLED;
#endif
	omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);

	omap_pm_if_early_init();

@@ -355,25 +372,16 @@ void __init omap2_init_common_infrastructure(void)
	else if (cpu_is_omap44xx())
		omap4xxx_clk_init();
	else
		pr_err("Could not init clock framework - unknown CPU\n");
		pr_err("Could not init clock framework - unknown SoC\n");
}

/*
 * XXX Ideally, this function will dwindle into nothingness over time;
 * almost all device init code should be possible through initcalls
 * and other generalized mechanisms
 */
void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
				      struct omap_sdrc_params *sdrc_cs1)
{
	u8 skip_setup_idle = 0;

	omap_serial_early_init();

#ifndef CONFIG_PM_RUNTIME
	skip_setup_idle = 1;
#endif
	omap_hwmod_late_init(skip_setup_idle);
	omap_hwmod_late_init();

	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
		_omap2_init_reprogram_sdrc();
+63 −19
Original line number Diff line number Diff line
@@ -1313,23 +1313,15 @@ static int _shutdown(struct omap_hwmod *oh)
/**
 * _setup - do initial configuration of omap_hwmod
 * @oh: struct omap_hwmod *
 * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
 *
 * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
 * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
 * a system that will not call omap_hwmod_enable() to enable devices
 * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
 * is in the wrong state or returns 0.
 * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the
 * wrong state or returns 0.
 */
static int _setup(struct omap_hwmod *oh, void *data)
{
	int i, r;
	u8 skip_setup_idle;

	if (!oh || !data)
		return -EINVAL;

	skip_setup_idle = *(u8 *)data;
	u8 postsetup_state;

	/* Set iclk autoidle mode */
	if (oh->slaves_cnt > 0) {
@@ -1349,7 +1341,6 @@ static int _setup(struct omap_hwmod *oh, void *data)
		}
	}

	mutex_init(&oh->_mutex);
	oh->_state = _HWMOD_STATE_INITIALIZED;

	/*
@@ -1383,8 +1374,25 @@ static int _setup(struct omap_hwmod *oh, void *data)
		}
	}

	if (!(oh->flags & HWMOD_INIT_NO_IDLE) && !skip_setup_idle)
	postsetup_state = oh->_postsetup_state;
	if (postsetup_state == _HWMOD_STATE_UNKNOWN)
		postsetup_state = _HWMOD_STATE_ENABLED;

	/*
	 * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
	 * it should be set by the core code as a runtime flag during startup
	 */
	if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
	    (postsetup_state == _HWMOD_STATE_IDLE))
		postsetup_state = _HWMOD_STATE_ENABLED;

	if (postsetup_state == _HWMOD_STATE_IDLE)
		_omap_hwmod_idle(oh);
	else if (postsetup_state == _HWMOD_STATE_DISABLED)
		_shutdown(oh);
	else if (postsetup_state != _HWMOD_STATE_ENABLED)
		WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
		     oh->name, postsetup_state);

	return 0;
}
@@ -1485,6 +1493,8 @@ int omap_hwmod_register(struct omap_hwmod *oh)

	list_add_tail(&oh->node, &omap_hwmod_list);

	mutex_init(&oh->_mutex);

	oh->_state = _HWMOD_STATE_REGISTERED;

	ret = 0;
@@ -1585,13 +1595,12 @@ int omap_hwmod_init(struct omap_hwmod **ohs)

/**
 * omap_hwmod_late_init - do some post-clock framework initialization
 * @skip_setup_idle: if 1, do not idle hwmods in _setup()
 *
 * Must be called after omap2_clk_init().  Resolves the struct clk names
 * to struct clk pointers for each registered omap_hwmod.  Also calls
 * _setup() on each hwmod.  Returns 0.
 */
int omap_hwmod_late_init(u8 skip_setup_idle)
int omap_hwmod_late_init(void)
{
	int r;

@@ -1603,10 +1612,7 @@ int omap_hwmod_late_init(u8 skip_setup_idle)
	WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
	     MPU_INITIATOR_NAME);

	if (skip_setup_idle)
		pr_debug("omap_hwmod: will leave hwmods enabled during setup\n");

	omap_hwmod_for_each(_setup, &skip_setup_idle);
	omap_hwmod_for_each(_setup, NULL);

	return 0;
}
@@ -2132,3 +2138,41 @@ int omap_hwmod_for_each_by_class(const char *classname,
	return ret;
}

/**
 * omap_hwmod_set_postsetup_state - set the post-_setup() state for this hwmod
 * @oh: struct omap_hwmod *
 * @state: state that _setup() should leave the hwmod in
 *
 * Sets the hwmod state that @oh will enter at the end of _setup() (called by
 * omap_hwmod_late_init()).  Only valid to call between calls to
 * omap_hwmod_init() and omap_hwmod_late_init().  Returns 0 upon success or
 * -EINVAL if there is a problem with the arguments or if the hwmod is
 * in the wrong state.
 */
int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
{
	int ret;

	if (!oh)
		return -EINVAL;

	if (state != _HWMOD_STATE_DISABLED &&
	    state != _HWMOD_STATE_ENABLED &&
	    state != _HWMOD_STATE_IDLE)
		return -EINVAL;

	mutex_lock(&oh->_mutex);

	if (oh->_state != _HWMOD_STATE_REGISTERED) {
		ret = -EINVAL;
		goto ohsps_unlock;
	}

	oh->_postsetup_state = state;
	ret = 0;

ohsps_unlock:
	mutex_unlock(&oh->_mutex);

	return ret;
}
+5 −1
Original line number Diff line number Diff line
@@ -462,6 +462,7 @@ struct omap_hwmod_class {
 * @response_lat: device OCP response latency (in interface clock cycles)
 * @_int_flags: internal-use hwmod flags
 * @_state: internal-use hwmod state
 * @_postsetup_state: internal-use state to leave the hwmod in after _setup()
 * @flags: hwmod flags (documented below)
 * @omap_chip: OMAP chips this hwmod is present on
 * @_mutex: mutex serializing operations on this hwmod
@@ -510,6 +511,7 @@ struct omap_hwmod {
	u8				hwmods_cnt;
	u8				_int_flags;
	u8				_state;
	u8				_postsetup_state;
	const struct omap_chip_id	omap_chip;
};

@@ -519,7 +521,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh);
struct omap_hwmod *omap_hwmod_lookup(const char *name);
int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
			void *data);
int omap_hwmod_late_init(u8 skip_setup_idle);
int omap_hwmod_late_init(void);

int omap_hwmod_enable(struct omap_hwmod *oh);
int _omap_hwmod_enable(struct omap_hwmod *oh);
@@ -566,6 +568,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
					   void *user),
				 void *user);

int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);

/*
 * Chip variant-specific hwmod init routines - XXX should be converted
 * to use initcalls once the initial boot ordering is straightened out