예제 #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 = prm_read_mod_reg(module, wkst_off);
	wkst &= prm_read_mod_reg(module, grpsel_off);
	if (wkst) {
		iclk = cm_read_mod_reg(module, iclk_off);
		fclk = cm_read_mod_reg(module, fclk_off);
		while (wkst) {
			clken = wkst;
			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;
			cm_set_mod_reg_bits(clken, module, fclk_off);
			prm_write_mod_reg(wkst, module, wkst_off);
			wkst = prm_read_mod_reg(module, wkst_off);
			c++;
		}
		cm_write_mod_reg(iclk, module, iclk_off);
		cm_write_mod_reg(fclk, module, fclk_off);
	}

	return c;
}
예제 #2
0
u32 omap_prcm_get_reset_sources(void)
{
	/* XXX This presumably needs modification for 34XX */
	if (cpu_is_omap24xx() || cpu_is_omap34xx())
		return prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
	if (cpu_is_omap44xx())
		return prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
	return -EIO;
}
예제 #3
0
int omap4_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 ((prm_read_mod_reg(pwrdm->prcm_offs, OMAP4_PM_PWSTST) &
		OMAP_INTRANSITION_MASK) &&
		(c++ < PWRDM_TRANSITION_BAILOUT))
			udelay(1);

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

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

	return 0;
}
예제 #4
0
static void serial_console_sleep(int enable)
{
    if (console_iclk == NULL || console_fclk == NULL)
        return;

    if (enable) {
        BUG_ON(serial_console_clock_disabled);
        if (clk_get_usecount(console_fclk) == 0)
            return;
        if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
            return;
        serial_wait_tx();
        clk_disable(console_iclk);
        clk_disable(console_fclk);
        serial_console_clock_disabled = 1;
    } else {
        int serial_wakeup = 0;
        u32 l;

        switch (serial_console_uart)  {
        case 1:
            l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
            if (l & OMAP24XX_ST_UART1)
                serial_wakeup = 1;
            break;
        case 2:
            l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
            if (l & OMAP24XX_ST_UART2)
                serial_wakeup = 1;
            break;
        case 3:
            l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
            if (l & OMAP24XX_ST_UART3)
                serial_wakeup = 1;
            break;
        }
        if (serial_wakeup)
            serial_console_kick();
        if (!serial_console_clock_disabled)
            return;
        clk_enable(console_iclk);
        clk_enable(console_fclk);
        serial_console_clock_disabled = 0;
    }
}
예제 #5
0
static void pm_init_serial_console(void)
{
    const struct omap_serial_console_config *conf;
    char name[16];
    u32 l;

    conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
                           struct omap_serial_console_config);
    if (conf == NULL)
        return;
    if (conf->console_uart > 3 || conf->console_uart < 1)
        return;
    serial_console_uart = conf->console_uart;
    sprintf(name, "uart%d_fck", conf->console_uart);
    console_fclk = clk_get(NULL, name);
    if (IS_ERR(console_fclk))
        console_fclk = NULL;
    name[6] = 'i';
    console_iclk = clk_get(NULL, name);
    if (IS_ERR(console_fclk))
        console_iclk = NULL;
    if (console_fclk == NULL || console_iclk == NULL) {
        serial_console_uart = 0;
        return;
    }
    switch (serial_console_uart) {
    case 1:
        l = prm_read_mod_reg(CORE_MOD, PM_WKEN1);
        l |= OMAP24XX_ST_UART1;
        prm_write_mod_reg(l, CORE_MOD, PM_WKEN1);
        break;
    case 2:
        l = prm_read_mod_reg(CORE_MOD, PM_WKEN1);
        l |= OMAP24XX_ST_UART2;
        prm_write_mod_reg(l, CORE_MOD, PM_WKEN1);
        break;
    case 3:
        l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKEN2);
        l |= OMAP24XX_ST_UART3;
        prm_write_mod_reg(l, CORE_MOD, OMAP24XX_PM_WKEN2);
        break;
    }
}
예제 #6
0
/* Read a PRM register, AND it, and shift the result down to bit 0 */
u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
{
	u32 v;

	v = prm_read_mod_reg(domain, idx);
	v &= mask;
	v >>= __ffs(mask);

	return v;
}
예제 #7
0
/*
 * PRCM Interrupt Handler
 *
 * The PRM_IRQSTATUS_MPU register indicates if there are any pending
 * interrupts from the PRCM for the MPU. These bits must be cleared in
 * order to clear the PRCM interrupt. The PRCM interrupt handler is
 * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
 * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
 * register indicates that a wake-up event is pending for the MPU and
 * this bit can only be cleared if the all the wake-up events latched
 * in the various PM_WKST_x registers have been cleared. The interrupt
 * handler is implemented using a do-while loop so that if a wake-up
 * event occurred during the processing of the prcm interrupt handler
 * (setting a bit in the corresponding PM_WKST_x register and thus
 * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
 * this would be handled.
 */
static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
{
	u32 irqenable_mpu, irqstatus_mpu;
	int c = 0;
	int ct = 0;

	irqenable_mpu = prm_read_mod_reg(OCP_MOD,
					 OMAP3_PRM_IRQENABLE_MPU_OFFSET);
	irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
					 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
	irqstatus_mpu &= irqenable_mpu;

	do {
		if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK |
				     OMAP3430_IO_ST_MASK)) {
			c = _prcm_int_handle_wakeup();
			ct++;

			/*
			 * Is the MPU PRCM interrupt handler racing with the
			 * IVA2 PRCM interrupt handler ?
			 */
			WARN(!c && (ct == 1), "prcm: WARNING: PRCM indicated "
				"MPU wakeup but no wakeup sources are "
				"marked\n");
		} else {
			/* XXX we need to expand our PRCM interrupt handler */
			WARN(1, "prcm: WARNING: PRCM interrupt received, but "
			     "no code to handle it (%08x)\n", irqstatus_mpu);
		}

		prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);

		irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
		irqstatus_mpu &= irqenable_mpu;

	} while (irqstatus_mpu);

	return IRQ_HANDLED;
}
예제 #8
0
/* Read-modify-write a register in a PRM module. Caller must lock */
u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
{
	u32 v;

	v = prm_read_mod_reg(module, idx);
	v &= ~mask;
	v |= bits;
	prm_write_mod_reg(v, module, idx);

	return v;
}
예제 #9
0
static u32 omap2_get_sysclkdiv(void)
{
    u32 div;

    div = prm_read_mod_reg(OMAP24XX_GR_MOD,
                           OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET);
    div &= OMAP_SYSCLKDIV_MASK;
    div >>= OMAP_SYSCLKDIV_SHIFT;

    return div;
}
예제 #10
0
int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
{
	u32 reg;

	prm_rmw_mod_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
			0x3 << OMAP4430_LASTPOWERSTATEENTERED_SHIFT,
				pwrdm->prcm_offs, OMAP4_PM_PWSTST);
	reg = prm_read_mod_reg(pwrdm->prcm_offs, pwrdm->context_offset);
	prm_write_mod_reg(reg, pwrdm->prcm_offs, pwrdm->context_offset);

	return 0;
}
예제 #11
0
static void omap3_enable_io_chain(void)
{
	int timeout = 0;

	if (omap_rev() >= OMAP3430_REV_ES3_1) {
		prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
				     PM_WKEN);
		/* Do a readback to assure write has been done */
		prm_read_mod_reg(WKUP_MOD, PM_WKEN);

		while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) &
			 OMAP3430_ST_IO_CHAIN_MASK)) {
			timeout++;
			if (timeout > 1000) {
				printk(KERN_ERR "Wake up daisy chain "
				       "activation failed.\n");
				return;
			}
		}
	}
}
예제 #12
0
파일: clock.c 프로젝트: Aircell/asp-kernel
/**
 * _omap2xxx_clk_commit - commit clock parent/rate changes in hardware
 * @clk: struct clk *
 *
 * If @clk has the DELAYED_APP flag set, meaning that parent/rate changes
 * don't take effect until the VALID_CONFIG bit is written, write the
 * VALID_CONFIG bit and wait for the write to complete.  No return value.
 */
static void _omap2xxx_clk_commit(struct clk *clk)
{
	if (!cpu_is_omap24xx())
		return;

	if (!(clk->flags & DELAYED_APP))
		return;

	prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD,
		OMAP2_PRCM_CLKCFG_CTRL_OFFSET);
	/* OCP barrier */
	prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP2_PRCM_CLKCFG_CTRL_OFFSET);
}
static int prcm_wakeup_event_control ( u32 reg_bit, u8 operation )
{
	volatile u32 prcm_val=0;

	prcm_val = prm_read_mod_reg( WKUP_MOD, PM_WKEN1 );
	if ( operation )
		prcm_val = prcm_val | reg_bit;
	else
		prcm_val = prcm_val & ~reg_bit;

	prm_write_mod_reg( prcm_val, WKUP_MOD, PM_WKEN1 );

	return 0;
}
예제 #14
0
/*
 * Clears the scratchpad contents in case of cold boot-
 * called during bootup
 */
void omap3_clear_scratchpad_contents(void)
{
	u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
	u32 *v_addr;
	u32 offset = 0;
	v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
	if (prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
		OMAP3430_GLOBAL_COLD_RST) {
		for ( ; offset <= max_offset; offset += 0x4)
			__raw_writel(0x0, (v_addr + offset));
		prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST, OMAP3430_GR_MOD,
			OMAP3_PRM_RSTST_OFFSET);
	}
}
예제 #15
0
static void iommu_disable(struct iommu *obj)
{
	u32 reg;

	if (!obj)
		return;

	if (cpu_is_omap44xx() && !strcmp(obj->name, "ducati")) {
		reg = prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
		prm_write_mod_reg((reg | RM_M3_RST1ST | RM_M3_RST2ST),
					OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
	}
	if (cpu_is_omap44xx() && !strcmp(obj->name, "tesla")) {
		reg = prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
		prm_write_mod_reg((reg | RM_TESLA_RST1ST),
					OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
	}

	if (!cpu_is_omap44xx())
		clk_enable(obj->clk);

	arch_iommu->disable(obj);

	if (!cpu_is_omap44xx())
		clk_disable(obj->clk);

	if (cpu_is_omap44xx() && !strcmp(obj->name, "ducati")) {
		pr_info("iommu_disable: Ducati Assert RST1, RST2 and RST3\n");
		reg = prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
		prm_write_mod_reg((reg | RM_M3_MPU_ALL_RESETS),
					OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
		pr_info("iommu_disable: Ducati Reset Status RSTST = 0x%x\n",
			prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTST_OFFSET));
	}
	if (cpu_is_omap44xx() && !strcmp(obj->name, "tesla")) {
		pr_info("iommu_disable: Tesla Assert DSP RST1 and RST2\n");
		reg = prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
		prm_write_mod_reg((reg | RM_TESLA_ALL_RESETS),
					OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
		pr_info("iommu_disable: Tesla Reset Status RSTST = 0x%x\n",
			prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTST_OFFSET));
	}
}
예제 #16
0
static int omap2_pm_suspend(void)
{
	u32 wken_wkup, mir1;

	wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
	prm_write_mod_reg(wken_wkup & ~OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN);

	/* Mask GPT1 */
	mir1 = omap_readl(0x480fe0a4);
	omap_writel(1 << 5, 0x480fe0ac);

	omap2_enter_full_retention();

	omap_writel(mir1, 0x480fe0a4);
	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);

	return 0;
}
예제 #17
0
/* Read-modify-write a register in a PRM module. Caller must lock */
u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
{
	u32 v;

	/* CHIRON CPU0/1 domains are not part of PRM */
	if (cpu_is_omap44xx() &&
			((module == OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD) ||
			(module == OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD)))
		v = chiron_read_mod_reg(module, idx);
	else
		v = prm_read_mod_reg(module, idx);

	v &= ~mask;
	v |= bits;

	if (cpu_is_omap44xx() &&
			((module == OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD) ||
			(module == OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD)))
		chiron_write_mod_reg(v, module, idx);
	else
		prm_write_mod_reg(v, module, idx);

	return v;
}
예제 #18
0
static void omap2_enter_full_retention(void)
{
	u32 l;
	struct timespec ts_preidle, ts_postidle, ts_idle;

	/* There is 1 reference hold for all children of the oscillator
	 * clock, the following will remove it. If no one else uses the
	 * oscillator itself it will be disabled if/when we enter retention
	 * mode.
	 */
	clk_disable(osc_ck);

	/* Clear old wake-up events */
	/* REVISIT: These write to reserved bits? */
	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);

	/*
	 * Set MPU powerdomain's next power state to RETENTION;
	 * preserve logic state during retention
	 */
	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);

	/* Workaround to kill USB */
	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);

	omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);

	if (omap2_pm_debug) {
		omap2_pm_dump(0, 0, 0);
		getnstimeofday(&ts_preidle);
	}

	/* One last check for pending IRQs to avoid extra latency due
	 * to sleeping unnecessarily. */
	if (omap_irq_pending())
		goto no_sleep;

	omap_uart_prepare_idle(0);
	omap_uart_prepare_idle(1);
	omap_uart_prepare_idle(2);

	/* Jump to SRAM suspend code */
	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
				OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
				OMAP_SDRC_REGADDR(SDRC_POWER));
no_sleep:
	omap_uart_resume_idle(2);
	omap_uart_resume_idle(1);
	omap_uart_resume_idle(0);

	if (omap2_pm_debug) {
		unsigned long long tmp;

		getnstimeofday(&ts_postidle);
		ts_idle = timespec_sub(ts_postidle, ts_preidle);
		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
		omap2_pm_dump(0, 1, tmp);
	}
	omap2_gpio_resume_after_idle();

	clk_enable(osc_ck);

	/* clear CORE wake-up events */
	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);

	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);

	/* MPU domain wake events */
	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
	if (l & 0x01)
		prm_write_mod_reg(0x01, OCP_MOD,
				OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
	if (l & 0x20)
		prm_write_mod_reg(0x20, OCP_MOD,
				OMAP2_PRM_IRQSTATUS_MPU_OFFSET);

	/* Mask future PRCM-to-MPU interrupts */
	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
}
예제 #19
0
int __init omap2_pm_init(void)
{
	u32 l;

	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
	l = prm_read_mod_reg(OCP_MOD, OMAP24XX_PRM_REVISION_OFFSET);
	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);

	/* Look up important powerdomains, clockdomains */

	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
	if (!mpu_pwrdm)
		pr_err("PM: mpu_pwrdm not found\n");

	core_pwrdm = pwrdm_lookup("core_pwrdm");
	if (!core_pwrdm)
		pr_err("PM: core_pwrdm not found\n");

	dsp_clkdm = clkdm_lookup("dsp_clkdm");
	if (!dsp_clkdm)
		pr_err("PM: mpu_clkdm not found\n");

	gfx_clkdm = clkdm_lookup("gfx_clkdm");
	if (!gfx_clkdm)
		pr_err("PM: gfx_clkdm not found\n");


	osc_ck = clk_get(NULL, "osc_ck");
	if (IS_ERR(osc_ck)) {
		printk(KERN_ERR "could not get osc_ck\n");
		return -ENODEV;
	}

	if (cpu_is_omap242x()) {
		emul_ck = clk_get(NULL, "emul_ck");
		if (IS_ERR(emul_ck)) {
			printk(KERN_ERR "could not get emul_ck\n");
			clk_put(osc_ck);
			return -ENODEV;
		}
	}

	prcm_setup_regs();

	/* Hack to prevent MPU retention when STI console is enabled. */
	{
		const struct omap_sti_console_config *sti;

		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
				      struct omap_sti_console_config);
		if (sti != NULL && sti->enable)
			sti_console_enabled = 1;
	}

	/*
	 * We copy the assembler sleep/wakeup routines to SRAM.
	 * These routines need to be in SRAM as that's the only
	 * memory the MPU can see when it wakes up.
	 */
	if (cpu_is_omap24xx()) {
		omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
						 omap24xx_idle_loop_suspend_sz);

		omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
						    omap24xx_cpu_suspend_sz);
	}

	suspend_set_ops(&omap_pm_ops);
	pm_idle = omap2_pm_idle;

	return 0;
}
예제 #20
0
void omap3_prcm_save_context(void)
{
	prcm_context.control_padconf_sys_nirq =
			 omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ);
	prcm_context.iva2_cm_clksel1 =
			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
	prcm_context.iva2_cm_clksel2 =
			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
	prcm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
	prcm_context.sgx_cm_clksel =
			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
	prcm_context.dss_cm_clksel =
			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
	prcm_context.cam_cm_clksel =
			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
	prcm_context.per_cm_clksel =
			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
	prcm_context.emu_cm_clksel =
			 cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
	prcm_context.emu_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.pll_cm_autoidle2 =
			 cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
	prcm_context.pll_cm_clksel4 =
			cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
	prcm_context.pll_cm_clksel5 =
			 cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
	prcm_context.pll_cm_clken2 =
			cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
	prcm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
	prcm_context.iva2_cm_fclken =
			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
	prcm_context.iva2_cm_clken_pll = cm_read_mod_reg(OMAP3430_IVA2_MOD,
			OMAP3430_CM_CLKEN_PLL);
	prcm_context.core_cm_fclken1 =
			 cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
	prcm_context.core_cm_fclken3 =
			 cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
	prcm_context.sgx_cm_fclken =
			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
	prcm_context.wkup_cm_fclken =
			 cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
	prcm_context.dss_cm_fclken =
			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
	prcm_context.cam_cm_fclken =
			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
	prcm_context.per_cm_fclken =
			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
	prcm_context.usbhost_cm_fclken =
			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
	prcm_context.core_cm_iclken1 =
			 cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
	prcm_context.core_cm_iclken2 =
			 cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
	prcm_context.core_cm_iclken3 =
			 cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
	prcm_context.sgx_cm_iclken =
			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
	prcm_context.wkup_cm_iclken =
			 cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
	prcm_context.dss_cm_iclken =
			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
	prcm_context.cam_cm_iclken =
			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
	prcm_context.per_cm_iclken =
			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
	prcm_context.usbhost_cm_iclken =
			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
	prcm_context.iva2_cm_autiidle2 =
			 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
	prcm_context.mpu_cm_autoidle2 =
			 cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
	prcm_context.iva2_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.mpu_cm_clkstctrl =
			 cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.core_cm_clkstctrl =
			 cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.sgx_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
						OMAP2_CM_CLKSTCTRL);
	prcm_context.dss_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.cam_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.per_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.neon_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
	prcm_context.usbhost_cm_clkstctrl =
			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
						OMAP2_CM_CLKSTCTRL);
	prcm_context.core_cm_autoidle1 =
			 cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
	prcm_context.core_cm_autoidle2 =
			 cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
	prcm_context.core_cm_autoidle3 =
			 cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
	prcm_context.wkup_cm_autoidle =
			 cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
	prcm_context.dss_cm_autoidle =
			 cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
	prcm_context.cam_cm_autoidle =
			 cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
	prcm_context.per_cm_autoidle =
			 cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
	prcm_context.usbhost_cm_autoidle =
			 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
	prcm_context.sgx_cm_sleepdep =
		 cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP3430_CM_SLEEPDEP);
	prcm_context.dss_cm_sleepdep =
		 cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
	prcm_context.cam_cm_sleepdep =
		 cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
	prcm_context.per_cm_sleepdep =
		 cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
	prcm_context.usbhost_cm_sleepdep =
		 cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
	prcm_context.cm_clkout_ctrl = cm_read_mod_reg(OMAP3430_CCR_MOD,
		 OMAP3_CM_CLKOUT_CTRL_OFFSET);
	prcm_context.prm_clkout_ctrl = prm_read_mod_reg(OMAP3430_CCR_MOD,
		OMAP3_PRM_CLKOUT_CTRL_OFFSET);
	prcm_context.sgx_pm_wkdep =
		 prm_read_mod_reg(OMAP3430ES2_SGX_MOD, PM_WKDEP);
	prcm_context.dss_pm_wkdep =
		 prm_read_mod_reg(OMAP3430_DSS_MOD, PM_WKDEP);
	prcm_context.cam_pm_wkdep =
		 prm_read_mod_reg(OMAP3430_CAM_MOD, PM_WKDEP);
	prcm_context.per_pm_wkdep =
		 prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKDEP);
	prcm_context.neon_pm_wkdep =
		 prm_read_mod_reg(OMAP3430_NEON_MOD, PM_WKDEP);
	prcm_context.usbhost_pm_wkdep =
		 prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
	prcm_context.core_pm_mpugrpsel1 =
		 prm_read_mod_reg(CORE_MOD, OMAP3430_PM_MPUGRPSEL1);
	prcm_context.iva2_pm_ivagrpsel1 =
		 prm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_PM_IVAGRPSEL1);
	prcm_context.core_pm_mpugrpsel3 =
		 prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_MPUGRPSEL3);
	prcm_context.core_pm_ivagrpsel3 =
		 prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
	prcm_context.wkup_pm_mpugrpsel =
		 prm_read_mod_reg(WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
	prcm_context.wkup_pm_ivagrpsel =
		 prm_read_mod_reg(WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
	prcm_context.per_pm_mpugrpsel =
		 prm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
	prcm_context.per_pm_ivagrpsel =
		 prm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
	prcm_context.wkup_pm_wken = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
	return;
}
예제 #21
0
static int iommu_enable(struct iommu *obj)
{
	int err;
	u32 reg;

	if (!obj)
		return -EINVAL;

	if (cpu_is_omap44xx() && !strcmp(obj->name, "ducati")) {
		/* Check that releasing resets would indeed be effective */
		reg = prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
		pr_info("iommu_enable: OMAP4_RM_DUCATI_RSTCTRL_OFFSET = 0x%x",
			reg);
		if ((reg & RM_M3_MPU_ALL_RESETS) != RM_M3_MPU_ALL_RESETS) {
			pr_info("iommu_enable: Ducati Resets in not proper "
				"state!\n");
			pr_info("iommu_enable: Ducati Asserting RST1, RST2, "
				"and RST3...\n");
			prm_write_mod_reg(RM_M3_MPU_ALL_RESETS,
					OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
			while (prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
				OMAP4_RM_DUCATI_RSTCTRL_OFFSET) !=
						 RM_M3_MPU_ALL_RESETS);
		}

		/* De-assert RST3, and clear the Reset status */
		pr_info("iommu_enable: De-assert Ducati RST3\n");
		reg = prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
		pr_info("iommu_enable: Ducati RSTCTRL = 0x%x\n", reg);
		prm_write_mod_reg(RM_M3_REL_RST3_MASK, OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTCTRL_OFFSET);
		while (!(prm_read_mod_reg(OMAP4430_PRM_CORE_MOD,
				OMAP4_RM_DUCATI_RSTST_OFFSET) & RM_M3_RST3ST));
		pr_info("iommu_enable: Ducati RST3 released!");
		prm_write_mod_reg(RM_M3_RST3ST, OMAP4430_PRM_CORE_MOD,
					OMAP4_RM_DUCATI_RSTST_OFFSET);
		pr_info("iommu_enable: Ducati %s %d\n", __func__, __LINE__);
	}
	if (cpu_is_omap44xx() && !strcmp(obj->name, "tesla")) {
		/* Check that releasing resets would indeed be effective */
		reg = prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
		pr_info("iommu_enable: OMAP4_RM_TESLA_RSTCTRL_OFFSET = 0x%x",
			reg);
		if ((reg & RM_TESLA_ALL_RESETS) != RM_TESLA_ALL_RESETS) {
			pr_info("iommu_enable: Tesla Resets in not proper "
				"state!\n");
			pr_info("iommu_enable: Tesla Assert RST1 and RST2.n");
			prm_write_mod_reg(RM_TESLA_ALL_RESETS,
					OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
			while (prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET) !=
					RM_TESLA_ALL_RESETS);
		}

		/* De-assert RST2, and clear the Reset status */
		pr_info("iommu_enable: De-assert Tesla RST2\n");
		reg = prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
		pr_info("iommu_enable: Tesla RSTCTRL = 0x%x\n", reg);
		prm_write_mod_reg(RM_TESLA_REL_RST2_MASK,
					OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTCTRL_OFFSET);
		while (!(prm_read_mod_reg(OMAP4430_PRM_TESLA_MOD,
				OMAP4_RM_TESLA_RSTST_OFFSET) &
				RM_TESLA_RST2ST));
		pr_info("iommu_enable: Tesla RST2 released!");
		prm_write_mod_reg(RM_TESLA_RST2ST, OMAP4430_PRM_TESLA_MOD,
					OMAP4_RM_TESLA_RSTST_OFFSET);
		pr_info("iommu_enable: Tesla %s %d\n", __func__, __LINE__);
	}

	if (!cpu_is_omap44xx())
		clk_enable(obj->clk);

	err = arch_iommu->enable(obj);

	if (!cpu_is_omap44xx())
		clk_disable(obj->clk);

	return err;
}
예제 #22
0
u32 omap_prcm_get_reset_sources(void)
{
	/* XXX This presumably needs modification for 34XX */
	return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
}
예제 #23
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 */
	scratchpad_contents.boot_config_ptr = 0x0;
	if (cpu_is_omap3630())
		scratchpad_contents.public_restore_ptr =
			virt_to_phys(get_omap3630_restore_pointer());
	else if (omap_rev() != OMAP3430_REV_ES3_0 &&
					omap_rev() != OMAP3430_REV_ES3_1)
		scratchpad_contents.public_restore_ptr =
			virt_to_phys(get_restore_pointer());
	else
		scratchpad_contents.public_restore_ptr =
			virt_to_phys(get_es3_restore_pointer());
	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 = prm_read_mod_reg(OMAP3430_GR_MOD,
			OMAP3_PRM_CLKSRC_CTRL_OFFSET);
	prcm_block_contents.prm_clksel = prm_read_mod_reg(OMAP3430_CCR_MOD,
			OMAP3_PRM_CLKSEL_OFFSET);
	prcm_block_contents.cm_clksel_core =
			cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
	prcm_block_contents.cm_clksel_wkup =
			cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
	prcm_block_contents.cm_clken_pll =
			cm_read_mod_reg(PLL_MOD, CM_CLKEN);
	prcm_block_contents.cm_autoidle_pll =
			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
	prcm_block_contents.cm_clksel1_pll =
			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
	prcm_block_contents.cm_clksel2_pll =
			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
	prcm_block_contents.cm_clksel3_pll =
			cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
	prcm_block_contents.cm_clken_pll_mpu =
			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
	prcm_block_contents.cm_autoidle_pll_mpu =
			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
	prcm_block_contents.cm_clksel1_pll_mpu =
			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
	prcm_block_contents.cm_clksel2_pll_mpu =
			cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
	prcm_block_contents.prcm_block_size = 0x0;

	/* Populate the SDRC block contents */
	sdrc_block_contents.sysconfig =
			(sdrc_read_reg(SDRC_SYSCONFIG) & 0xFFFF);
	sdrc_block_contents.cs_cfg =
			(sdrc_read_reg(SDRC_CS_CFG) & 0xFFFF);
	sdrc_block_contents.sharing =
			(sdrc_read_reg(SDRC_SHARING) & 0xFFFF);
	sdrc_block_contents.err_type =
			(sdrc_read_reg(SDRC_ERR_TYPE) & 0xFFFF);
	sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL);
	sdrc_block_contents.dll_b_ctrl = 0x0;
	/*
	 * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should
	 * be programed to issue automatic self refresh on timeout
	 * of AUTO_CNT = 1 prior to any transition to OFF mode.
	 */
	if ((omap_type() != OMAP2_DEVICE_TYPE_GP)
			&& (omap_rev() >= OMAP3430_REV_ES3_0))
		sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) &
				~(SDRC_POWER_AUTOCOUNT_MASK|
				SDRC_POWER_CLKCTRL_MASK)) |
				(1 << SDRC_POWER_AUTOCOUNT_SHIFT) |
				SDRC_SELF_REFRESH_ON_AUTOCOUNT;
	else
		sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER);

	sdrc_block_contents.cs_0 = 0x0;
	sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0);
	sdrc_block_contents.mr_0 = (sdrc_read_reg(SDRC_MR_0) & 0xFFFF);
	sdrc_block_contents.emr_1_0 = 0x0;
	sdrc_block_contents.emr_2_0 = 0x0;
	sdrc_block_contents.emr_3_0 = 0x0;
	sdrc_block_contents.actim_ctrla_0 =
			sdrc_read_reg(SDRC_ACTIM_CTRL_A_0);
	sdrc_block_contents.actim_ctrlb_0 =
			sdrc_read_reg(SDRC_ACTIM_CTRL_B_0);
	sdrc_block_contents.rfr_ctrl_0 =
			sdrc_read_reg(SDRC_RFR_CTRL_0);
	sdrc_block_contents.cs_1 = 0x0;
	sdrc_block_contents.mcfg_1 = sdrc_read_reg(SDRC_MCFG_1);
	sdrc_block_contents.mr_1 = sdrc_read_reg(SDRC_MR_1) & 0xFFFF;
	sdrc_block_contents.emr_1_1 = 0x0;
	sdrc_block_contents.emr_2_1 = 0x0;
	sdrc_block_contents.emr_3_1 = 0x0;
	sdrc_block_contents.actim_ctrla_1 =
			sdrc_read_reg(SDRC_ACTIM_CTRL_A_1);
	sdrc_block_contents.actim_ctrlb_1 =
			sdrc_read_reg(SDRC_ACTIM_CTRL_B_1);
	sdrc_block_contents.rfr_ctrl_1 =
			sdrc_read_reg(SDRC_RFR_CTRL_1);
	sdrc_block_contents.dcdl_1_ctrl = 0x0;
	sdrc_block_contents.dcdl_2_ctrl = 0x0;
	sdrc_block_contents.flags = 0x0;
	sdrc_block_contents.block_size = 0x0;

	arm_context_addr = virt_to_phys(omap3_arm_context);

	/* Copy all the contents to the scratchpad location */
	scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
	memcpy_toio(scratchpad_address, &scratchpad_contents,
		 sizeof(scratchpad_contents));
	/* Scratchpad contents being 32 bits, a divide by 4 done here */
	memcpy_toio(scratchpad_address +
		scratchpad_contents.prcm_block_offset,
		&prcm_block_contents, sizeof(prcm_block_contents));
	memcpy_toio(scratchpad_address +
		scratchpad_contents.sdrc_block_offset,
		&sdrc_block_contents, sizeof(sdrc_block_contents));
	/*
	 * Copies the address of the location in SDRAM where ARM
	 * registers get saved during a MPU OFF transition.
	 */
	memcpy_toio(scratchpad_address +
		scratchpad_contents.sdrc_block_offset +
		sizeof(sdrc_block_contents), &arm_context_addr, 4);
}
예제 #24
0
static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
{
	return prm_read_mod_reg(mod, offset);
}