Exemplo n.º 1
0
/*
 * PRCM Interrupt Handler Helper Function
 *
 * The purpose of this function is to clear any wake-up events latched
 * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
 * may occur whilst attempting to clear a PM_WKST_x register and thus
 * set another bit in this register. A while loop is used to ensure
 * that any peripheral wake-up events occurring while attempting to
 * clear the PM_WKST_x are detected and cleared.
 */
static int prcm_clear_mod_irqs(s16 module, u8 regs)
{
	u32 wkst, fclk, iclk, clken;
	u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
	u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
	u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
	u16 grpsel_off = (regs == 3) ?
		OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
	int c = 0;

	wkst = omap2_prm_read_mod_reg(module, wkst_off);
	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
	if (wkst) {
		iclk = omap2_cm_read_mod_reg(module, iclk_off);
		fclk = omap2_cm_read_mod_reg(module, fclk_off);
		while (wkst) {
			clken = wkst;
			omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
			/*
			 * For USBHOST, we don't know whether HOST1 or
			 * HOST2 woke us up, so enable both f-clocks
			 */
			if (module == OMAP3430ES2_USBHOST_MOD)
				clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
			omap2_prm_write_mod_reg(wkst, module, wkst_off);
			wkst = omap2_prm_read_mod_reg(module, wkst_off);
			c++;
		}
		omap2_cm_write_mod_reg(iclk, module, iclk_off);
		omap2_cm_write_mod_reg(fclk, module, fclk_off);
	}

	return c;
}
Exemplo n.º 2
0
int omap2xxx_cm_fclks_active(void)
{
	u32 f1, f2;

	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);

	return (f1 | f2) ? 1 : 0;
}
Exemplo n.º 3
0
/* Populate the scratchpad structure with restore structure */
void omap3_save_scratchpad_contents(void)
{
	void  __iomem *scratchpad_address;
	u32 arm_context_addr;
	struct omap3_scratchpad scratchpad_contents;
	struct omap3_scratchpad_prcm_block prcm_block_contents;
	struct omap3_scratchpad_sdrc_block sdrc_block_contents;

	/*
	 * Populate the Scratchpad contents
	 *
	 * The "get_*restore_pointer" functions are used to provide a
	 * physical restore address where the ROM code jumps while waking
	 * up from MPU OFF/OSWR state.
	 * The restore pointer is stored into the scratchpad.
	 */
	scratchpad_contents.boot_config_ptr = 0x0;
	if (cpu_is_omap3630())
		scratchpad_contents.public_restore_ptr =
			virt_to_phys(omap3_restore_3630);
	else if (omap_rev() != OMAP3430_REV_ES3_0 &&
					omap_rev() != OMAP3430_REV_ES3_1)
		scratchpad_contents.public_restore_ptr =
			virt_to_phys(omap3_restore);
	else
		scratchpad_contents.public_restore_ptr =
			virt_to_phys(omap3_restore_es3);

	if (omap_type() == OMAP2_DEVICE_TYPE_GP)
		scratchpad_contents.secure_ram_restore_ptr = 0x0;
	else
		scratchpad_contents.secure_ram_restore_ptr =
			(u32) __pa(omap3_secure_ram_storage);
	scratchpad_contents.sdrc_module_semaphore = 0x0;
	scratchpad_contents.prcm_block_offset = 0x2C;
	scratchpad_contents.sdrc_block_offset = 0x64;

	/* Populate the PRCM block contents */
	prcm_block_contents.prm_clksrc_ctrl =
		omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
				       OMAP3_PRM_CLKSRC_CTRL_OFFSET);
	prcm_block_contents.prm_clksel =
		omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
				       OMAP3_PRM_CLKSEL_OFFSET);
	prcm_block_contents.cm_clksel_core =
			omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
	prcm_block_contents.cm_clksel_wkup =
			omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
	prcm_block_contents.cm_clken_pll =
			omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
	/*
	 * As per erratum i671, ROM code does not respect the PER DPLL
	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
	 * Then,  in anycase, clear these bits to avoid extra latencies.
	 */
	prcm_block_contents.cm_autoidle_pll =
			omap2_cm_read_mod_reg(PLL_
static int omap2_fclks_active(void)
{
	u32 f1, f2;

	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);

	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
	f1 &= ~(OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_UART2_MASK);
	f2 &= ~OMAP24XX_EN_UART3_MASK;

	if (f1 | f2)
		return 1;
	return 0;
}
/*
 * Uses the current prcm set to tell if a rate is valid.
 * You can go slower, but not faster within a given rate set.
 */
static long omap2_dpllcore_round_rate(unsigned long target_rate)
{
	u32 high, low, core_clk_src;

	core_clk_src = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;

	if (core_clk_src == CORE_CLK_SRC_DPLL) {	/* DPLL clockout */
		high = curr_prcm_set->dpll_speed * 2;
		low = curr_prcm_set->dpll_speed;
	} else {				/* DPLL clockout x 2 */
		high = curr_prcm_set->dpll_speed;
		low = curr_prcm_set->dpll_speed / 2;
	}

#ifdef DOWN_VARIABLE_DPLL
	if (target_rate > high)
		return high;
	else
		return target_rate;
#else
	if (target_rate > low)
		return high;
	else
		return low;
#endif

}
static int omap2_i2c_active(void)
{
	u32 l;

	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
	return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK);
}
Exemplo n.º 7
0
/**
 * omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby
 * @prcm_mod: PRCM module offset
 * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
 * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
 *
 * XXX document
 */
int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
{
	int ena = 0, i = 0;
	u8 cm_idlest_reg;
	u32 mask;

	if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs)))
		return -EINVAL;

	cm_idlest_reg = cm_idlest_offs[idlest_id - 1];

	mask = 1 << idlest_shift;

	if (cpu_is_omap24xx())
		ena = mask;
	else if (cpu_is_omap34xx())
		ena = 0;
	else
		BUG();

	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
			  MAX_MODULE_READY_TIME, i);

	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
}
Exemplo n.º 8
0
int omap2xxx_cm_mpu_retention_allowed(void)
{
	u32 l;

	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
		return 0;
	/* Check for UART3. */
	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
	if (l & OMAP24XX_EN_UART3_MASK)
		return 0;

	return 1;
}
Exemplo n.º 9
0
/* Stop APLL */
static void _omap2xxx_apll_disable(u8 enable_bit)
{
	u32 v;

	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
	v &= ~(EN_APLL_LOCKED << enable_bit);
	omap2_cm_write_mod_reg(v, PLL_MOD, CM_CLKEN);
}
Exemplo n.º 10
0
static unsigned long omap3_l3_get_rate(struct device *dev)
{
	int l3_div;

	l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
			OMAP3430_CLKSEL_L3_MASK;
	return dpll3_clk->rate / l3_div;
}
/* Stop APLL */
static void omap2_clk_apll_disable(struct clk *clk)
{
    u32 cval;

    cval = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
    cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
    omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
}
Exemplo n.º 12
0
u32 omap2xxx_cm_get_core_clk_src(void)
{
	u32 v;

	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	v &= OMAP24XX_CORE_CLK_SRC_MASK;

	return v;
}
Exemplo n.º 13
0
static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
{
	u32 v;

	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
	v &= ~mask;
	v |= m << __ffs(mask);
	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
}
Exemplo n.º 14
0
static void _omap2xxx_set_dpll_autoidle(u8 m)
{
	u32 v;

	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
	v &= ~OMAP24XX_AUTO_DPLL_MASK;
	v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
}
Exemplo n.º 15
0
static int omap3_l3_set_rate(struct device *dev, unsigned long rate)
{
	int l3_div;

	l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
			OMAP3430_CLKSEL_L3_MASK;

	return clk_set_rate(dpll3_clk, rate * l3_div);
}
Exemplo n.º 16
0
static void _ti81xx_write_clktrctrl(u8 c, s16 module, u16 idx, u32 mask)
{
	u32 v;

	v = omap2_cm_read_mod_reg(module, idx);
	v &= ~mask;
	v |= c << __ffs(mask);
	omap2_cm_write_mod_reg(v, module, idx);
}
Exemplo n.º 17
0
static void _write_clktrctrl(u8 c, s16 module, u32 mask)
{
	u32 v;

	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
	v &= ~mask;
	v |= c << __ffs(mask);
	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
}
Exemplo n.º 18
0
static int omap2_allow_mpu_retention(void)
{
	u32 l;

	
	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
		return 0;
	
	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
	if (l & OMAP24XX_EN_UART3_MASK)
		return 0;
	if (sti_console_enabled)
		return 0;

	return 1;
}
Exemplo n.º 19
0
bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
{
	u32 v;

	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
	v &= mask;
	v >>= __ffs(mask);

	return (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
}
Exemplo n.º 20
0
/**
 * omap2xxx_clk_apll_locked - is the APLL locked?
 * @hw: struct clk_hw * of the APLL to check
 *
 * If the APLL IP block referred to by @hw indicates that it's locked,
 * return true; otherwise, return false.
 */
static bool omap2xxx_clk_apll_locked(struct clk_hw *hw)
{
    struct clk_hw_omap *clk = to_clk_hw_omap(hw);
    u32 r, apll_mask;

    apll_mask = EN_APLL_LOCKED << clk->enable_bit;

    r = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);

    return ((r & apll_mask) == apll_mask) ? true : false;
}
Exemplo n.º 21
0
/* Read-modify-write a register in a CM module. Caller must lock */
u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
{
	u32 v;

	v = omap2_cm_read_mod_reg(module, idx);
	v &= ~mask;
	v |= bits;
	omap2_cm_write_mod_reg(v, module, idx);

	return v;
}
Exemplo n.º 22
0
void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core, u32 mdm)
{
	u32 tmp;

	omap2_cm_write_mod_reg(mpu, MPU_MOD, CM_CLKSEL);
	omap2_cm_write_mod_reg(dsp, OMAP24XX_DSP_MOD, CM_CLKSEL);
	omap2_cm_write_mod_reg(gfx, GFX_MOD, CM_CLKSEL);
	tmp = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) &
		OMAP24XX_CLKSEL_DSS2_MASK;
	omap2_cm_write_mod_reg(core | tmp, CORE_MOD, CM_CLKSEL1);
	if (cpu_is_omap2430())
		omap2_cm_write_mod_reg(mdm, OMAP2430_MDM_MOD, CM_CLKSEL);
}
/**
 * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
 * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
 *
 * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
 * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
 * (the latter is unusual).  This currently should be called with
 * struct clk *dpll_ck, which is a composite clock of dpll_ck and
 * core_ck.
 */
unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
{
	long long core_clk;
	u32 v;

	core_clk = omap2_get_dpll_rate(clk);

	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
	v &= OMAP24XX_CORE_CLK_SRC_MASK;

	if (v == CORE_CLK_SRC_32K)
		core_clk = 32768;
	else
		core_clk *= v;

	return core_clk;
}
u32 omap2xxx_get_apll_clkin(void)
{
    u32 aplls, srate = 0;

    aplls = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
    aplls &= OMAP24XX_APLLS_CLKIN_MASK;
    aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;

    if (aplls == APLLS_CLKIN_19_2MHZ)
        srate = 19200000;
    else if (aplls == APLLS_CLKIN_13MHZ)
        srate = 13000000;
    else if (aplls == APLLS_CLKIN_12MHZ)
        srate = 12000000;

    return srate;
}
Exemplo n.º 25
0
static void omap_st_off(struct omap_mcbsp *mcbsp)
{
	unsigned int w;
	struct omap_device *od;

	od = find_omap_device_by_dev(mcbsp->dev);

	w = MCBSP_ST_READ(mcbsp, SSELCR);
	MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));

	w = MCBSP_READ(mcbsp, SSELCR);
	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));

	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
	w |= 1 << (mcbsp->id - 2);
	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
}
Exemplo n.º 26
0
bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
{
	u32 v;
	bool ret = 0;

	BUG_ON(!cpu_is_omap24xx() && !cpu_is_omap34xx());

	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
	v &= mask;
	v >>= __ffs(mask);

	if (cpu_is_omap24xx())
		ret = (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
	else
		ret = (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;

	return ret;
}
Exemplo n.º 27
0
/**
 * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
 * @part: PRCM partition, ignored for OMAP3
 * @prcm_mod: PRCM module offset
 * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
 * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
 *
 * Wait for the PRCM to indicate that the module identified by
 * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
 * success or -EBUSY if the module doesn't enable in time.
 */
static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
					 u8 idlest_shift)
{
	int ena = 0, i = 0;
	u8 cm_idlest_reg;
	u32 mask;

	if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
		return -EINVAL;

	cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];

	mask = 1 << idlest_shift;
	ena = 0;

	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
			    mask) == ena), MAX_MODULE_READY_TIME, i);

	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
}
Exemplo n.º 28
0
/* Enable an APLL if off */
static int _omap2xxx_apll_enable(u8 enable_bit, u8 status_bit)
{
	u32 v, m;

	m = EN_APLL_LOCKED << enable_bit;

	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
	if (v & m)
		return 0;   /* apll already enabled */

	v |= m;
	omap2_cm_write_mod_reg(v, PLL_MOD, CM_CLKEN);

	omap2xxx_cm_wait_module_ready(PLL_MOD, 1, status_bit);

	/*
	 * REVISIT: Should we return an error code if
	 * omap2xxx_cm_wait_module_ready() fails?
	 */
	return 0;
}
Exemplo n.º 29
0
static void omap_st_on(struct omap_mcbsp *mcbsp)
{
	unsigned int w;
	struct omap_device *od;

	od = find_omap_device_by_dev(mcbsp->dev);

	/*
	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
	 * are enabled or sidetones start sounding ugly.
	 */
	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
	w &= ~(1 << (mcbsp->id - 2));
	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);

	/* Enable McBSP Sidetone */
	w = MCBSP_READ(mcbsp, SSELCR);
	MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);

	/* Enable Sidetone from Sidetone Core */
	w = MCBSP_ST_READ(mcbsp, SSELCR);
	MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
}
/* Enable an APLL if off */
static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
{
    u32 cval, apll_mask;

    apll_mask = EN_APLL_LOCKED << clk->enable_bit;

    cval = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);

    if ((cval & apll_mask) == apll_mask)
        return 0;   /* apll already enabled */

    cval &= ~apll_mask;
    cval |= apll_mask;
    omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);

    omap2_cm_wait_idlest(cm_idlest_pll, status_mask,
                         OMAP24XX_CM_IDLEST_VAL, clk->name);

    /*
     * REVISIT: Should we return an error code if omap2_wait_clock_ready()
     * fails?
     */
    return 0;
}