/* * 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; }
/* * omap3_noncore_dpll_program - set non-core DPLL M,N values directly * @clk: struct clk * of DPLL to set * @m: DPLL multiplier to set * @n: DPLL divider to set * @freqsel: FREQSEL value to set * * Program the DPLL with the supplied M, N values, and wait for the DPLL to * lock.. Returns -EINVAL upon error, or 0 upon success. */ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) { struct dpll_data *dd; u32 v; if (!clk) return -EINVAL; dd = clk->dpll_data; if (!dd) return -EINVAL; /* * According to the 12-5 CDP code from TI, "Limitation 2.5" * on 3430ES1 prevents us from changing DPLL multipliers or dividers * on DPLL4. */ if (omap_rev() == OMAP3430_REV_ES1_0 && !strcmp("dpll4_ck", clk->name)) { printk(KERN_ERR "clock: DPLL4 cannot change rate due to " "silicon 'Limitation 2.5' on 3430ES1.\n"); return -EINVAL; } /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ _omap3_noncore_dpll_bypass(clk); /* Set jitter correction */ v = cm_read_mod_reg(clk->prcm_mod, dd->control_reg); v &= ~dd->freqsel_mask; v |= freqsel << __ffs(dd->freqsel_mask); cm_write_mod_reg(v, clk->prcm_mod, dd->control_reg); /* Set DPLL multiplier, divider */ v = cm_read_mod_reg(clk->prcm_mod, dd->mult_div1_reg); v &= ~(dd->mult_mask | dd->div1_mask); v |= m << __ffs(dd->mult_mask); v |= (n - 1) << __ffs(dd->div1_mask); if (dd->jtype) { u8 dco, sd_div; lookup_dco_sddiv(clk, &dco, &sd_div, m, n); v &= ~(dd->dco_sel_mask | dd->sd_div_mask); v |= dco << __ffs(dd->dco_sel_mask); v |= sd_div << __ffs(dd->sd_div_mask); } cm_write_mod_reg(v, clk->prcm_mod, dd->mult_div1_reg); /* We let the clock framework set the other output dividers later */ /* REVISIT: Set ramp-up delay? */ _omap3_noncore_dpll_lock(clk); return 0; }
/* Enable an APLL if off */ static int omap2_clk_fixed_enable(struct clk *clk) { u32 cval, apll_mask; apll_mask = EN_APLL_LOCKED << clk->enable_bit; cval = 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; cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); if (clk == &apll96_ck) cval = OMAP24XX_ST_96M_APLL; else if (clk == &apll54_ck) cval = OMAP24XX_ST_54M_APLL; omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval, clk->name); /* * REVISIT: Should we return an error code if omap2_wait_clock_ready() * fails? */ return 0; }
/* Stop APLL */ static void omap2_clk_fixed_disable(struct clk *clk) { u32 cval; cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); cval &= ~(EN_APLL_LOCKED << clk->enable_bit); cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); }
/* Read-modify-write a register in a CM module. Caller must lock */ u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) { u32 v; v = cm_read_mod_reg(module, idx); v &= ~mask; v |= bits; cm_write_mod_reg(v, module, idx); return v; }
/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits) { const struct dpll_data *dd; u32 v; dd = clk->dpll_data; v = cm_read_mod_reg(clk->prcm_mod, dd->control_reg); v &= ~dd->enable_mask; v |= clken_bits << __ffs(dd->enable_mask); cm_write_mod_reg(v, clk->prcm_mod, dd->control_reg); }
/** * omap3_dpll_deny_idle - prevent DPLL from automatically idling * @clk: struct clk * of the DPLL to operate on * * Disable DPLL automatic idle control. No return value. */ static void omap3_dpll_deny_idle(struct clk *clk) { const struct dpll_data *dd; u32 v; if (!clk || !clk->dpll_data) return; dd = clk->dpll_data; v = cm_read_mod_reg(clk->prcm_mod, dd->autoidle_reg); v &= ~dd->autoidle_mask; v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); cm_write_mod_reg(v, clk->prcm_mod, dd->autoidle_reg); }
/** * omap3_dpll_allow_idle - enable DPLL autoidle bits * @clk: struct clk * of the DPLL to operate on * * Enable DPLL automatic idle control. This automatic idle mode * switching takes effect only when the DPLL is locked, at least on * OMAP3430. The DPLL will enter low-power stop when its downstream * clocks are gated. No return value. */ static void omap3_dpll_allow_idle(struct clk *clk) { const struct dpll_data *dd; u32 v; if (!clk || !clk->dpll_data) return; dd = clk->dpll_data; /* * REVISIT: CORE DPLL can optionally enter low-power bypass * by writing 0x5 instead of 0x1. Add some mechanism to * optionally enter this mode. */ v = cm_read_mod_reg(clk->prcm_mod, dd->autoidle_reg); v &= ~dd->autoidle_mask; v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); cm_write_mod_reg(v, clk->prcm_mod, dd->autoidle_reg); }
/* 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 = 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; 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; }
static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; /* Enable autoidle */ prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD, OMAP24XX_PRM_SYSCONFIG_OFFSET); /* Set all domain wakeup dependencies */ prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP); prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP); prm_write_mod_reg(0, GFX_MOD, PM_WKDEP); prm_write_mod_reg(0, CORE_MOD, PM_WKDEP); if (cpu_is_omap2430()) prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP); /* * Set CORE powerdomain memory banks to retain their contents * during RETENTION */ num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); /* Set CORE powerdomain's next power state to RETENTION */ pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); /* * 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); /* Force-power down DSP, GFX powerdomains */ pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(gfx_clkdm); /* Enable clockdomain hardware-supervised control for all clkdms */ clkdm_for_each(_pm_clkdm_enable_hwsup, NULL); /* Enable clock autoidle for all domains */ cm_write_mod_reg(OMAP24XX_AUTO_CAM | OMAP24XX_AUTO_MAILBOXES | OMAP24XX_AUTO_WDT4 | OMAP2420_AUTO_WDT3 | OMAP24XX_AUTO_MSPRO | OMAP2420_AUTO_MMC | OMAP24XX_AUTO_FAC | OMAP2420_AUTO_EAC | OMAP24XX_AUTO_HDQ | OMAP24XX_AUTO_UART2 | OMAP24XX_AUTO_UART1 | OMAP24XX_AUTO_I2C2 | OMAP24XX_AUTO_I2C1 | OMAP24XX_AUTO_MCSPI2 | OMAP24XX_AUTO_MCSPI1 | OMAP24XX_AUTO_MCBSP2 | OMAP24XX_AUTO_MCBSP1 | OMAP24XX_AUTO_GPT12 | OMAP24XX_AUTO_GPT11 | OMAP24XX_AUTO_GPT10 | OMAP24XX_AUTO_GPT9 | OMAP24XX_AUTO_GPT8 | OMAP24XX_AUTO_GPT7 | OMAP24XX_AUTO_GPT6 | OMAP24XX_AUTO_GPT5 | OMAP24XX_AUTO_GPT4 | OMAP24XX_AUTO_GPT3 | OMAP24XX_AUTO_GPT2 | OMAP2420_AUTO_VLYNQ | OMAP24XX_AUTO_DSS, CORE_MOD, CM_AUTOIDLE1); cm_write_mod_reg(OMAP24XX_AUTO_UART3 | OMAP24XX_AUTO_SSI | OMAP24XX_AUTO_USB, CORE_MOD, CM_AUTOIDLE2); cm_write_mod_reg(OMAP24XX_AUTO_SDRC | OMAP24XX_AUTO_GPMC | OMAP24XX_AUTO_SDMA, CORE_MOD, CM_AUTOIDLE3); cm_write_mod_reg(OMAP24XX_AUTO_PKA | OMAP24XX_AUTO_AES | OMAP24XX_AUTO_RNG | OMAP24XX_AUTO_SHA | OMAP24XX_AUTO_DES, CORE_MOD, OMAP24XX_CM_AUTOIDLE4); cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE); /* Put DPLL and both APLLs into autoidle mode */ cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | (0x03 << OMAP24XX_AUTO_96M_SHIFT) | (0x03 << OMAP24XX_AUTO_54M_SHIFT), PLL_MOD, CM_AUTOIDLE); cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL | OMAP24XX_AUTO_WDT1 | OMAP24XX_AUTO_MPU_WDT | OMAP24XX_AUTO_GPIOS | OMAP24XX_AUTO_32KSYNC | OMAP24XX_AUTO_GPT1, WKUP_MOD, CM_AUTOIDLE); /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk * stabilisation */ prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKSSETUP_OFFSET); /* Configure automatic voltage transition */ prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP24XX_PRCM_VOLTSETUP_OFFSET); prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT | (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | OMAP24XX_MEMRETCTRL | (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), OMAP24XX_GR_MOD, OMAP24XX_PRCM_VOLTCTRL_OFFSET); /* Enable wake-up events */ prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN); }
void omap3_prcm_restore_context(void) { omap_ctrl_writel(prcm_context.control_padconf_sys_nirq, OMAP343X_CONTROL_PADCONF_SYSNIRQ); cm_write_mod_reg(prcm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD, CM_CLKSEL1); cm_write_mod_reg(prcm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD, CM_CLKSEL2); __raw_writel(prcm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG); cm_write_mod_reg(prcm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD, CM_CLKSEL); cm_write_mod_reg(prcm_context.dss_cm_clksel, OMAP3430_DSS_MOD, CM_CLKSEL); cm_write_mod_reg(prcm_context.cam_cm_clksel, OMAP3430_CAM_MOD, CM_CLKSEL); cm_write_mod_reg(prcm_context.per_cm_clksel, OMAP3430_PER_MOD, CM_CLKSEL); cm_write_mod_reg(prcm_context.emu_cm_clksel, OMAP3430_EMU_MOD, CM_CLKSEL1); cm_write_mod_reg(prcm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.pll_cm_autoidle2, PLL_MOD, CM_AUTOIDLE2); cm_write_mod_reg(prcm_context.pll_cm_clksel4, PLL_MOD, OMAP3430ES2_CM_CLKSEL4); cm_write_mod_reg(prcm_context.pll_cm_clksel5, PLL_MOD, OMAP3430ES2_CM_CLKSEL5); cm_write_mod_reg(prcm_context.pll_cm_clken2, PLL_MOD, OMAP3430ES2_CM_CLKEN2); __raw_writel(prcm_context.cm_polctrl, OMAP3430_CM_POLCTRL); cm_write_mod_reg(prcm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL); cm_write_mod_reg(prcm_context.core_cm_fclken1, CORE_MOD, CM_FCLKEN1); cm_write_mod_reg(prcm_context.core_cm_fclken3, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); cm_write_mod_reg(prcm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.dss_cm_fclken, OMAP3430_DSS_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.cam_cm_fclken, OMAP3430_CAM_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.per_cm_fclken, OMAP3430_PER_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.usbhost_cm_fclken, OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); cm_write_mod_reg(prcm_context.core_cm_iclken1, CORE_MOD, CM_ICLKEN1); cm_write_mod_reg(prcm_context.core_cm_iclken2, CORE_MOD, CM_ICLKEN2); cm_write_mod_reg(prcm_context.core_cm_iclken3, CORE_MOD, CM_ICLKEN3); cm_write_mod_reg(prcm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD, CM_ICLKEN); cm_write_mod_reg(prcm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN); cm_write_mod_reg(prcm_context.dss_cm_iclken, OMAP3430_DSS_MOD, CM_ICLKEN); cm_write_mod_reg(prcm_context.cam_cm_iclken, OMAP3430_CAM_MOD, CM_ICLKEN); cm_write_mod_reg(prcm_context.per_cm_iclken, OMAP3430_PER_MOD, CM_ICLKEN); cm_write_mod_reg(prcm_context.usbhost_cm_iclken, OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); cm_write_mod_reg(prcm_context.iva2_cm_autiidle2, OMAP3430_IVA2_MOD, CM_AUTOIDLE2); cm_write_mod_reg(prcm_context.mpu_cm_autoidle2, MPU_MOD, CM_AUTOIDLE2); cm_write_mod_reg(prcm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.mpu_cm_clkstctrl, MPU_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.core_cm_clkstctrl, CORE_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.per_cm_clkstctrl, OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.usbhost_cm_clkstctrl, OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL); cm_write_mod_reg(prcm_context.core_cm_autoidle1, CORE_MOD, CM_AUTOIDLE1); cm_write_mod_reg(prcm_context.core_cm_autoidle2, CORE_MOD, CM_AUTOIDLE2); cm_write_mod_reg(prcm_context.core_cm_autoidle3, CORE_MOD, CM_AUTOIDLE3); cm_write_mod_reg(prcm_context.wkup_cm_autoidle, WKUP_MOD, CM_AUTOIDLE); cm_write_mod_reg(prcm_context.dss_cm_autoidle, OMAP3430_DSS_MOD, CM_AUTOIDLE); cm_write_mod_reg(prcm_context.cam_cm_autoidle, OMAP3430_CAM_MOD, CM_AUTOIDLE); cm_write_mod_reg(prcm_context.per_cm_autoidle, OMAP3430_PER_MOD, CM_AUTOIDLE); cm_write_mod_reg(prcm_context.usbhost_cm_autoidle, OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE); cm_write_mod_reg(prcm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD, OMAP3430_CM_SLEEPDEP); cm_write_mod_reg(prcm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP); cm_write_mod_reg(prcm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP); cm_write_mod_reg(prcm_context.per_cm_sleepdep, OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP); cm_write_mod_reg(prcm_context.usbhost_cm_sleepdep, OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP); cm_write_mod_reg(prcm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD, OMAP3_CM_CLKOUT_CTRL_OFFSET); prm_write_mod_reg(prcm_context.prm_clkout_ctrl, OMAP3430_CCR_MOD, OMAP3_PRM_CLKOUT_CTRL_OFFSET); prm_write_mod_reg(prcm_context.sgx_pm_wkdep, OMAP3430ES2_SGX_MOD, PM_WKDEP); prm_write_mod_reg(prcm_context.dss_pm_wkdep, OMAP3430_DSS_MOD, PM_WKDEP); prm_write_mod_reg(prcm_context.cam_pm_wkdep, OMAP3430_CAM_MOD, PM_WKDEP); prm_write_mod_reg(prcm_context.per_pm_wkdep, OMAP3430_PER_MOD, PM_WKDEP); prm_write_mod_reg(prcm_context.neon_pm_wkdep, OMAP3430_NEON_MOD, PM_WKDEP); prm_write_mod_reg(prcm_context.usbhost_pm_wkdep, OMAP3430ES2_USBHOST_MOD, PM_WKDEP); prm_write_mod_reg(prcm_context.core_pm_mpugrpsel1, CORE_MOD, OMAP3430_PM_MPUGRPSEL1); prm_write_mod_reg(prcm_context.iva2_pm_ivagrpsel1, OMAP3430_IVA2_MOD, OMAP3430_PM_IVAGRPSEL1); prm_write_mod_reg(prcm_context.core_pm_mpugrpsel3, CORE_MOD, OMAP3430ES2_PM_MPUGRPSEL3); prm_write_mod_reg(prcm_context.core_pm_ivagrpsel3, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3); prm_write_mod_reg(prcm_context.wkup_pm_mpugrpsel, WKUP_MOD, OMAP3430_PM_MPUGRPSEL); prm_write_mod_reg(prcm_context.wkup_pm_ivagrpsel, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); prm_write_mod_reg(prcm_context.per_pm_mpugrpsel, OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL); prm_write_mod_reg(prcm_context.per_pm_ivagrpsel, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL); prm_write_mod_reg(prcm_context.wkup_pm_wken, WKUP_MOD, PM_WKEN); return; }
/* Sets basic clocks based on the specified rate */ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) { u32 cur_rate, done_rate, bypass = 0, tmp; struct prcm_config *prcm; unsigned long flags, found_speed; if (clk != &virt_prcm_set) return -EINVAL; found_speed = omap2xxx_clk_find_oppset_by_mpurate(rate, &prcm); if (!found_speed) { printk(KERN_INFO "Could not set MPU rate to %luMHz\n", rate / 1000000); return -EINVAL; } curr_prcm_set = prcm; cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate); if (prcm->dpll_speed == cur_rate / 2) { omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); } else if (prcm->dpll_speed == cur_rate * 2) { omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); } else if (prcm->dpll_speed != cur_rate) { local_irq_save(flags); if (prcm->dpll_speed == prcm->xtal_speed) bypass = 1; if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) == CORE_CLK_SRC_DPLL_X2) done_rate = CORE_CLK_SRC_DPLL_X2; else done_rate = CORE_CLK_SRC_DPLL; /* MPU divider */ cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL); /* dsp + iva1 div(2420), iva2.1(2430) */ cm_write_mod_reg(prcm->cm_clksel_dsp, OMAP24XX_DSP_MOD, CM_CLKSEL); cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL); /* Major subsystem dividers */ tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1); if (cpu_is_omap2430()) cm_write_mod_reg(prcm->cm_clksel_mdm, OMAP2430_MDM_MOD, CM_CLKSEL); /* x2 to enter omap2xxx_sdrc_init_params() */ omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, bypass); omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); omap2xxx_sdrc_reprogram(done_rate, 0); local_irq_restore(flags); } return 0; }
int request_gptimer12( struct gptimer12_timer *timer ) { int loop_count; int empty_slot = -1; unsigned int next_time = 0; unsigned int current_time = 0; //unsigned int temp; unsigned char update_flag = 0; // printk("request_gptimer12 called \n"); if ( gptimer12_count >= MAX_GPTIMER12_INSTANCE ) { printk( "Error... max gptimer12 instance" ); return -1; } //CM_ICLKEN_WKUP |= 1 << 1; cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val | ( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD, CM_ICLKEN1 ); //modify exist entry for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) { if( strcmp( timer_manager[loop_count].timer.name, timer->name ) == 0 ) { //printk("timer update \n"); memcpy( &( timer_manager[loop_count].timer ), timer, sizeof( struct gptimer12_timer ) ); timer_manager[loop_count].remain_time = timer->expire_time; update_flag = 1; } } } next_time = timer->expire_time; if ( update_flag == 0 ) { //add new entry for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { if ( ( timer_manager[loop_count].timer.name ) == NULL ) { empty_slot = loop_count; break; } } //printk("empty_slot : %d, loop_count : %d\n",empty_slot,loop_count); if ( empty_slot == -1 ) { printk("Error.. No empty slot "); return -1; } gptimer12_count++; memcpy(&(timer_manager[empty_slot].timer),timer, sizeof(struct gptimer12_timer)); timer_manager[empty_slot].remain_time = timer->expire_time; // printk("test3 : gptimer12_count : %d\n",gptimer12_count); if ( gptimer12_count == 1 ) { omap_dm_timer_enable( battery_timer ); prcm_wakeup_event_control( PRCM_GPT12, PRCM_ENABLE ); omap_dm_timer_write_status( battery_timer, OMAP_TIMER_INT_OVERFLOW ); omap_dm_timer_set_int_enable( battery_timer, OMAP_TIMER_INT_OVERFLOW ); for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) timer_manager[loop_count].remain_time -= next_time; } omap_dm_timer_set_load_start( battery_timer, 0, 0xffffffff - GP_TIMER12_SEC_TO_TICK(next_time) ); //CM_ICLKEN_WKUP &= ~(1 << 1); #if 0 cm_val = cm_read_mod_reg(WKUP_MOD,CM_ICLKEN1); cm_val = cm_val&~(1<<1); cm_write_mod_reg(cm_val,WKUP_MOD,CM_ICLKEN1); #endif timer->active = true; return 1; } } omap_dm_timer_stop( battery_timer ); //:commented this #if 1 current_time = GP_TIMER12_TICK_TO_SEC( 0xffffffff - omap_dm_timer_read_counter(battery_timer) ); #endif for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { timer_manager[loop_count].remain_time += current_time; #if 0 if((timer_manager[loop_count].timer.name) != 0) { if((timer_manager[loop_count].remain_time) == 0) timer_manager[loop_count].remain_time = current_time; } #endif } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) { next_time = timer_manager[loop_count].remain_time; break; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) { if ( next_time > timer_manager[loop_count].remain_time ) next_time = timer_manager[loop_count].remain_time; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL ) timer_manager[loop_count].remain_time -= next_time; } // timer prcm_wakeup_event_control( PRCM_GPT12, PRCM_ENABLE ); omap_dm_timer_set_int_enable( battery_timer, OMAP_TIMER_INT_OVERFLOW ); omap_dm_timer_set_load_start( battery_timer, 0, 0xffffffff - GP_TIMER12_SEC_TO_TICK(next_time) ); //CM_ICLKEN_WKUP &= ~(1 << 1); #if 0 cm_val = cm_read_mod_reg(WKUP_MOD,CM_ICLKEN1); cm_val = cm_val&~(1<<1); cm_write_mod_reg(cm_val,WKUP_MOD,CM_ICLKEN1); // printk("requested gptimer12_count : %d \n",gptimer12_count); #endif timer->active = true; return 1; }
int release_gptimer12(struct gptimer12_timer *timer) { int loop_count; int temp_count; int slot = -1; unsigned int next_time=0; int current_time; if ( gptimer12_count == 0 ) return -1; //printk ("\ntest 1 timer_instance_count : %d \n",gptimer12_count); for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if ( timer_manager[loop_count].timer.name != NULL) { if( strcmp( timer->name, timer_manager[loop_count].timer.name ) == 0 ) { slot = loop_count; break; } } } if ( slot == -1 ) return -1; // case : delete current working timer //CM_ICLKEN_WKUP |= 1 << 1; cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val | ( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD, CM_ICLKEN1 ); if ( timer_manager[slot].remain_time == 0 ) { //current timer .. omap_dm_timer_stop( battery_timer ); current_time = GP_TIMER12_TICK_TO_SEC( 0xffffffff - omap_dm_timer_read_counter( battery_timer ) ); //printk("test1 current_time : %d\n",current_time); for ( loop_count = 0; loop_count < MAX_GPTIMER12_INSTANCE; loop_count++ ) { timer_manager[loop_count].remain_time += current_time; #if 0 if((timer_manager[loop_count].timer.name) != 0) { if((timer_manager[loop_count].remain_time) == 0) timer_manager[loop_count].remain_time = current_time; } #endif } } memset ( &( timer_manager[slot] ), 0, sizeof( struct gptimer12_manager ) ); gptimer12_count--; if( gptimer12_count < 0 ) gptimer12_count = 0; //printk("released : timer_instance_count : %d\n",gptimer12_count); if ( gptimer12_count == 0 ) { //printk("\n\n M timer empty .. \n"); prcm_wakeup_event_control( PRCM_GPT12, PRCM_DISABLE ); //egkim finish_gptimer12(); //egkim omap_dm_timer_disable( battery_timer ); //CM_ICLKEN_WKUP &= ~(1 << 1); cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val & ~( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD,CM_ICLKEN1 ); /* change active state. */ timer->active = false; return 0; } for ( temp_count = 0 ; temp_count < MAX_GPTIMER12_INSTANCE ; temp_count++ ) { if( timer_manager[temp_count].timer.name != NULL ) { next_time = timer_manager[temp_count].remain_time; break; } } for ( temp_count = 0 ; temp_count < MAX_GPTIMER12_INSTANCE ; temp_count++ ) { if ( timer_manager[temp_count].timer.name != NULL ) { next_time = timer_manager[temp_count].remain_time; break; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if( timer_manager[loop_count].timer.name != NULL ) { if ( next_time > timer_manager[loop_count].remain_time ) next_time = timer_manager[loop_count].remain_time; } } for ( loop_count = 0 ; loop_count < MAX_GPTIMER12_INSTANCE ; loop_count++ ) { if( timer_manager[loop_count].timer.name != NULL ) timer_manager[loop_count].remain_time -= next_time; } printk( "\n\n\n next timeout : %d\n",next_time ); prcm_wakeup_event_control( PRCM_GPT12, PRCM_ENABLE ); omap_dm_timer_set_load_start( battery_timer, 0, 0xffffffff - GP_TIMER12_SEC_TO_TICK(next_time) ); //CM_ICLKEN_WKUP &= ~(1 << 1); cm_val = cm_read_mod_reg( WKUP_MOD, CM_ICLKEN1 ); cm_val = cm_val & ~( 1 << 1 ); cm_write_mod_reg( cm_val, WKUP_MOD,CM_ICLKEN1 ); timer->active = false; return 0; }
/** * usb_hcd_omap_probe - initialize OMAP-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ static int usb_hcd_omap_probe(const struct hc_driver *driver, struct platform_device *pdev) { int retval; int i; u32 uhh_hostconfig_value; u8 ohci_port_enable_mask = 0; struct usb_hcd *hcd = 0; struct ohci_hcd *ohci; struct ohci_omap_clock_defs *ohci_clocks; if (pdev->num_resources != 2) { printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", pdev->num_resources); return -ENODEV; } if (pdev->resource[0].flags != IORESOURCE_MEM || pdev->resource[1].flags != IORESOURCE_IRQ) { printk(KERN_ERR "hcd probe: invalid resource type\n"); return -ENODEV; } hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); if (!hcd) { retval = -ENOMEM; goto err0; } ohci_clocks = (struct ohci_omap_clock_defs *) (((char *)hcd_to_ohci(hcd)) + sizeof(struct ohci_hcd)); /* Enable Clocks for USBHOST */ ohci_clocks->usbhost_ick_clk = clk_get(&pdev->dev, USBHOST_ICLK); if (IS_ERR(ohci_clocks->usbhost_ick_clk)) return PTR_ERR(ohci_clocks->usbhost_ick_clk); clk_enable(ohci_clocks->usbhost_ick_clk); ohci_clocks->usbhost2_120m_fck_clk = clk_get(&pdev->dev, USBHOST_120M_FCLK); if (IS_ERR(ohci_clocks->usbhost2_120m_fck_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); return PTR_ERR(ohci_clocks->usbhost2_120m_fck_clk); } clk_enable(ohci_clocks->usbhost2_120m_fck_clk); ohci_clocks->usbhost1_48m_fck_clk = clk_get(&pdev->dev, USBHOST_48M_FCLK); if (IS_ERR(ohci_clocks->usbhost1_48m_fck_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); return PTR_ERR(ohci_clocks->usbhost1_48m_fck_clk); } clk_enable(ohci_clocks->usbhost1_48m_fck_clk); /* Configure TLL for 60Mhz clk for ULPI */ ohci_clocks->usbtll_fck_clk = clk_get(&pdev->dev, USBHOST_TLL_FCLK); if (IS_ERR(ohci_clocks->usbtll_fck_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); clk_disable(ohci_clocks->usbhost1_48m_fck_clk); clk_put(ohci_clocks->usbhost1_48m_fck_clk); return PTR_ERR(ohci_clocks->usbtll_fck_clk); } clk_enable(ohci_clocks->usbtll_fck_clk); ohci_clocks->usbtll_ick_clk = clk_get(&pdev->dev, USBHOST_TLL_ICLK); if (IS_ERR(ohci_clocks->usbtll_ick_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); clk_disable(ohci_clocks->usbhost1_48m_fck_clk); clk_put(ohci_clocks->usbhost1_48m_fck_clk); clk_disable(ohci_clocks->usbtll_fck_clk); clk_put(ohci_clocks->usbtll_fck_clk); return PTR_ERR(ohci_clocks->usbtll_ick_clk); } clk_enable(ohci_clocks->usbtll_ick_clk); ohci_clocks->suspended = 0; /* Disable Auto Idle of USBTLL */ cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT), CORE_MOD, CM_AUTOIDLE3); /* Wait for TLL to be Active */ while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3) & (1 << OMAP3430ES2_ST_USBTLL_SHIFT))); /* perform TLL soft reset, and wait until reset is complete */ omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT, OMAP_USBTLL_SYSCONFIG); /* Wait for TLL reset to complete */ while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT))); /* smart idle mode */ omap_writel((1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) | (2 << OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT) | (0 << OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT) | (1 << OMAP_USBTLL_SYSCONFIG_AUTOIDLE_SHIFT), OMAP_USBTLL_SYSCONFIG); /* Put UHH in SmartIdle/SmartStandby mode */ omap_writel((1 << OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_ENAWAKEUP_SHIFT) | (2 << OMAP_UHH_SYSCONFIG_SIDLEMODE_SHIFT) | (0 << OMAP_UHH_SYSCONFIG_CACTIVITY_SHIFT) | (2 << OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT), OMAP_UHH_SYSCONFIG); #ifdef CONFIG_OMAP_OHCI_PHY_MODE /* TLL in FS-PHY mode operation */ uhh_hostconfig_value = (1 << OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT) | (0 << OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT); if (is_sil_rev_greater_than(OMAP3430_REV_ES2_1)) { /* For ES 3, we have per-port control for the ULPI Bypass * The ULPI Bypass needs to be set to 0 only if the EHCI PHY Mode * is selected for that port. * Hence it is easier to make it conditional on EHCI_PHY_MODE * * ES 2 does not have per-port control. Hence it is not possible to have * EHCI in PHY Mode and OHCI both working at the same time * * FIXME: This common code should be moved elsewhere * */ #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT1 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT2 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P2_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT3 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P3_ULPI_BYPASS_SHIFT); #endif } else { uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); } omap_writel(uhh_hostconfig_value, OMAP_UHH_HOSTCONFIG); #if 0 /* Ensure BYPASS bit is not set */ while (!(omap_readl(OMAP_UHH_HOSTCONFIG) & (1 << OMAP_UHH_HOSTCONFIG_P3_ULPI_BYPASS_SHIFT))); #endif pr_debug("Entered UTMI PHY MODE: success"); /* Program Common TLL register */ omap_writel((1 << OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT) | (1 << OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT) | (0 << OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT) | (0 << OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT), OMAP_TLL_SHARED_CONF); #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT1) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT1) ohci_port_enable_mask |= (1 << 0); #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT2) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT2) ohci_port_enable_mask |= (1 << 1); #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT3) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT3) ohci_port_enable_mask |= (1 << 2); #endif #ifdef CONFIG_OMAP_OHCI_PHY_MODE_3PIN /* Program the 3 TLL channels upfront */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { /* Enable only required ports */ if (!(ohci_port_enable_mask & (1 << i))) continue; /* Disable AutoIdle */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1 << OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* Disable BitStuffing */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1 << OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* SDR Mode */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1 << OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* CHANMODE: UTMI-to-serial FS/LS mode */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1 << OMAP_TLL_CHANNEL_CONF_CHANMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); #if 0 /* Enable port 3 only. Not enabling ports 1 & 2 */ if (i != 2) continue; #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT1) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT2) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT3) /* FSLSMODE: 4-pin bidirectional PHY */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (3 << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT1) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT2) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT3) /* FSLSMODE: 3-pin bidirectional PHY */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (2 << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); #endif omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); } #else pr_debug("\nOnly 3-pin PHY mode is implemented"); #endif /* CONFIG_OMAP_OHCI_PHY_MODE_3PIN */ #else #error "FS-TLL Not implemented" #endif /* CONFIG_OMAP_OHCI_PHY_MODE */ hcd->rsrc_start = pdev->resource[0].start; hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; /* if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { dev_dbg(&pdev->dev, "request_mem_region failed\n"); retval = -EBUSY; goto err1; } */ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "can't ioremap OHCI HCD\n"); retval = -ENOMEM; goto err2; } /* pr_debug("\n\n-->VIRT-OHCI-BASE [0x%x], [0x%x] irq[%d]\n\n", hcd->regs, (unsigned int)io_p2v( 0x48064400 ), pdev->resource[1].start); */ ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); ohci_clocks->host_enabled = 1; //irq = platform_get_irq(pdev, 0); //if (irq < 0) { // retval = -ENXIO; // goto err3; //} retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED); if (retval) goto err3; return 0; err3: iounmap(hcd->regs); err2: // release_mem_region(hcd->rsrc_start, hcd->rsrc_len); //err1: usb_put_hcd(hcd); clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); clk_disable(ohci_clocks->usbhost1_48m_fck_clk); clk_put(ohci_clocks->usbhost1_48m_fck_clk); clk_disable(ohci_clocks->usbtll_fck_clk); clk_put(ohci_clocks->usbtll_fck_clk); clk_disable(ohci_clocks->usbtll_ick_clk); clk_put(ohci_clocks->usbtll_ick_clk); err0: // clk_put(usb_dc_ck); // clk_put(usb_host_ck); return retval; }
static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; /* Enable autoidle */ prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, OMAP2_PRCM_SYSCONFIG_OFFSET); /* * Set CORE powerdomain memory banks to retain their contents * during RETENTION */ num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); /* Set CORE powerdomain's next power state to RETENTION */ pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); /* * 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); /* Force-power down DSP, GFX powerdomains */ pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(gfx_clkdm); /* * Clear clockdomain wakeup dependencies and enable * hardware-supervised idle for all clkdms */ clkdm_for_each(clkdms_setup, NULL); clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); /* Enable clock autoidle for all domains */ cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK | OMAP24XX_AUTO_MAILBOXES_MASK | OMAP24XX_AUTO_WDT4_MASK | OMAP2420_AUTO_WDT3_MASK | OMAP24XX_AUTO_MSPRO_MASK | OMAP2420_AUTO_MMC_MASK | OMAP24XX_AUTO_FAC_MASK | OMAP2420_AUTO_EAC_MASK | OMAP24XX_AUTO_HDQ_MASK | OMAP24XX_AUTO_UART2_MASK | OMAP24XX_AUTO_UART1_MASK | OMAP24XX_AUTO_I2C2_MASK | OMAP24XX_AUTO_I2C1_MASK | OMAP24XX_AUTO_MCSPI2_MASK | OMAP24XX_AUTO_MCSPI1_MASK | OMAP24XX_AUTO_MCBSP2_MASK | OMAP24XX_AUTO_MCBSP1_MASK | OMAP24XX_AUTO_GPT12_MASK | OMAP24XX_AUTO_GPT11_MASK | OMAP24XX_AUTO_GPT10_MASK | OMAP24XX_AUTO_GPT9_MASK | OMAP24XX_AUTO_GPT8_MASK | OMAP24XX_AUTO_GPT7_MASK | OMAP24XX_AUTO_GPT6_MASK | OMAP24XX_AUTO_GPT5_MASK | OMAP24XX_AUTO_GPT4_MASK | OMAP24XX_AUTO_GPT3_MASK | OMAP24XX_AUTO_GPT2_MASK | OMAP2420_AUTO_VLYNQ_MASK | OMAP24XX_AUTO_DSS_MASK, CORE_MOD, CM_AUTOIDLE1); cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK | OMAP24XX_AUTO_SSI_MASK | OMAP24XX_AUTO_USB_MASK, CORE_MOD, CM_AUTOIDLE2); cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK | OMAP24XX_AUTO_GPMC_MASK | OMAP24XX_AUTO_SDMA_MASK, CORE_MOD, CM_AUTOIDLE3); cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK | OMAP24XX_AUTO_AES_MASK | OMAP24XX_AUTO_RNG_MASK | OMAP24XX_AUTO_SHA_MASK | OMAP24XX_AUTO_DES_MASK, CORE_MOD, OMAP24XX_CM_AUTOIDLE4); cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD, CM_AUTOIDLE); /* Put DPLL and both APLLs into autoidle mode */ cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | (0x03 << OMAP24XX_AUTO_96M_SHIFT) | (0x03 << OMAP24XX_AUTO_54M_SHIFT), PLL_MOD, CM_AUTOIDLE); cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK | OMAP24XX_AUTO_WDT1_MASK | OMAP24XX_AUTO_MPU_WDT_MASK | OMAP24XX_AUTO_GPIOS_MASK | OMAP24XX_AUTO_32KSYNC_MASK | OMAP24XX_AUTO_GPT1_MASK, WKUP_MOD, CM_AUTOIDLE); /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk * stabilisation */ prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_CLKSSETUP_OFFSET); /* Configure automatic voltage transition */ prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTSETUP_OFFSET); prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK | (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | OMAP24XX_MEMRETCTRL_MASK | (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET); /* Enable wake-up events */ prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK, WKUP_MOD, PM_WKEN); }
/* Sets basic clocks based on the specified rate */ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) { u32 cur_rate, done_rate, bypass = 0, tmp; struct prcm_config *prcm; unsigned long found_speed = 0; unsigned long flags; if (clk != &virt_prcm_set) return -EINVAL; for (prcm = rate_table; prcm->mpu_speed; prcm++) { if (!(prcm->flags & cpu_mask)) continue; if (prcm->xtal_speed != sys_ck.rate) continue; if (prcm->mpu_speed <= rate) { found_speed = prcm->mpu_speed; break; } } if (!found_speed) { printk(KERN_INFO "Could not set MPU rate to %luMHz\n", rate / 1000000); return -EINVAL; } curr_prcm_set = prcm; cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck); if (prcm->dpll_speed == cur_rate / 2) { omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1); } else if (prcm->dpll_speed == cur_rate * 2) { omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); } else if (prcm->dpll_speed != cur_rate) { local_irq_save(flags); if (prcm->dpll_speed == prcm->xtal_speed) bypass = 1; if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) == CORE_CLK_SRC_DPLL_X2) done_rate = CORE_CLK_SRC_DPLL_X2; else done_rate = CORE_CLK_SRC_DPLL; /* MPU divider */ cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL); /* dsp + iva1 div(2420), iva2.1(2430) */ cm_write_mod_reg(prcm->cm_clksel_dsp, OMAP24XX_DSP_MOD, CM_CLKSEL); cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL); /* Major subsystem dividers */ tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1); if (cpu_is_omap2430()) cm_write_mod_reg(prcm->cm_clksel_mdm, OMAP2430_MDM_MOD, CM_CLKSEL); /* x2 to enter init_mem */ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, bypass); omap2_init_memory_params(omap2_dll_force_needed()); omap2_reprogram_sdrc(done_rate, 0); local_irq_restore(flags); } omap2_dpll_recalc(&dpll_ck); return 0; }
/* omap_start_ehc * - Start the TI USBHOST controller */ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) { u32 uhh_hostconfig_value = 0; struct ehci_omap_clock_defs *ehci_clocks; dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n"); ehci_clocks = (struct ehci_omap_clock_defs *)( ((char *)hcd_to_ehci(hcd)) + sizeof(struct ehci_hcd)); /* Start DPLL5 Programming: * Clock Framework is not doing this now: * This will be done in clock framework later */ /* Enable DPLL 5 : Based on Input of 13Mhz*/ cm_write_mod_reg((12 << OMAP3430ES2_PERIPH2_DPLL_DIV_SHIFT)| (120 << OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT), PLL_MOD, OMAP3430ES2_CM_CLKSEL4); cm_write_mod_reg(1 << OMAP3430ES2_DIV_120M_SHIFT, PLL_MOD, OMAP3430ES2_CM_CLKSEL5); cm_write_mod_reg((7 << OMAP3430ES2_PERIPH2_DPLL_FREQSEL_SHIFT) | (7 << OMAP3430ES2_EN_PERIPH2_DPLL_SHIFT), PLL_MOD, OMAP3430ES2_CM_CLKEN2); #if 0 /* initialization stucks here when EHCI built as module */ while (!(cm_read_mod_reg(PLL_MOD, CM_IDLEST2) & OMAP3430ES2_ST_PERIPH2_CLK_MASK)) dev_dbg(hcd->self.controller, "idlest2 = 0x%x\n", cm_read_mod_reg(PLL_MOD, CM_IDLEST2)); #endif /* End DPLL5 programming */ /* PRCM settings for USBHOST: * Interface clk un-related to domain transition */ cm_write_mod_reg(0 << OMAP3430ES2_AUTO_USBHOST_SHIFT, OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE); /* Disable sleep dependency with MPU and IVA */ cm_write_mod_reg((0 << OMAP3430ES2_EN_MPU_SHIFT) | (0 << OMAP3430ES2_EN_IVA2_SHIFT), OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP); /* Disable Automatic transition of clock */ cm_write_mod_reg(0 << OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT, OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL); /* Enable Clocks for USBHOST */ ehci_clocks->usbhost_ick_clk = clk_get(&dev->dev, USBHOST_ICKL); if (IS_ERR(ehci_clocks->usbhost_ick_clk)) return PTR_ERR(ehci_clocks->usbhost_ick_clk); clk_enable(ehci_clocks->usbhost_ick_clk); ehci_clocks->usbhost2_120m_fck_clk = clk_get(&dev->dev, USBHOST_120M_FCLK); if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk)) return PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk); clk_enable(ehci_clocks->usbhost2_120m_fck_clk); ehci_clocks->usbhost1_48m_fck_clk = clk_get(&dev->dev, USBHOST_48M_FCLK); if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk)) return PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk); clk_enable(ehci_clocks->usbhost1_48m_fck_clk); /* get phy reset gpio number */ EXT_PHY_RESET_GPIO_PORT2 = omap3_ehci_phy_reset_gpio; #ifdef EXTERNAL_PHY_RESET /* Refer: ISSUE1 */ #ifdef CONFIG_OMAP3430SDP_750_2083_001 gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset"); gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0); gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 0); #endif gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset"); gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0); gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0); /* Hold the PHY in RESET for enough time till DIR is high */ udelay(EXT_PHY_RESET_DELAY); #endif /* Configure TLL for 60Mhz clk for ULPI */ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK); if (IS_ERR(ehci_clocks->usbtll_fck_clk)) return PTR_ERR(ehci_clocks->usbtll_fck_clk); clk_enable(ehci_clocks->usbtll_fck_clk); ehci_clocks->usbtll_ick_clk = clk_get(&dev->dev, USBHOST_TLL_ICKL); if (IS_ERR(ehci_clocks->usbtll_ick_clk)) return PTR_ERR(ehci_clocks->usbtll_ick_clk); clk_enable(ehci_clocks->usbtll_ick_clk); /* Disable Auto Idle of USBTLL */ cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT), CORE_MOD, CM_AUTOIDLE3); /* Wait for TLL to be Active */ while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3) & (1 << OMAP3430ES2_ST_USBTLL_SHIFT))) cpu_relax(); /* perform TLL soft reset, and wait until reset is complete */ omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT, OMAP_USBTLL_SYSCONFIG); /* Wait for TLL reset to complete */ while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT))) cpu_relax(); dev_dbg(hcd->self.controller, "TLL RESET DONE\n"); /* (1<<3) = no idle mode only for initial debugging */ omap_writel((1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) | (1 << OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT) | (1 << OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT), OMAP_USBTLL_SYSCONFIG); /* Put UHH in NoIdle/NoStandby mode */ omap_writel((0 << OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_ENAWAKEUP_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_SIDLEMODE_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_CACTIVITY_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT), OMAP_UHH_SYSCONFIG); /* Bypass the TLL module for PHY mode operation */ uhh_hostconfig_value = (1 << OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT) | (0 << OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT); /* For ES 3, we have per-port control for the ULPI Bypass * The ULPI Bypass needs to be set to 0 only if the EHCI PHY Mode * is selected for that port. * ES 2 does not have per-port control. Hence it is not possible to have * EHCI in PHY Mode and OHCI both working at the same time */ if (omap_rev_ge30()) { #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT1 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT2 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P2_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT3 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P3_ULPI_BYPASS_SHIFT); #endif } else { #if defined(CONFIG_OMAP_EHCI_PHY_MODE_PORT1) || \ defined(CONFIG_OMAP_EHCI_PHY_MODE_PORT2) || \ defined(CONFIG_OMAP_EHCI_PHY_MODE_PORT3) uhh_hostconfig_value |= (0 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #else uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #endif } omap_writel(uhh_hostconfig_value, OMAP_UHH_HOSTCONFIG); if (omap_rev_le21()) { /* Ensure that BYPASS is set */ while (omap_readl(OMAP_UHH_HOSTCONFIG) & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)) cpu_relax(); } dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success\n"); #if defined(CONFIG_OMAP_EHCI_TLL_MODE_PORT1) || \ defined(CONFIG_OMAP_EHCI_TLL_MODE_PORT2) || \ defined(CONFIG_OMAP_EHCI_TLL_MODE_PORT3) /* Enable UTMI mode for all selected TLL channels */ omap_usb_utmi_init(hcd, 0 #ifdef CONFIG_OMAP_EHCI_TLL_MODE_PORT1 | OMAP_TLL_CHANNEL_1_EN_MASK #endif #ifdef CONFIG_OMAP_EHCI_TLL_MODE_PORT2 | OMAP_TLL_CHANNEL_2_EN_MASK #endif #ifdef CONFIG_OMAP_EHCI_TLL_MODE_PORT3 | OMAP_TLL_CHANNEL_3_EN_MASK #endif ); #endif #ifdef EXTERNAL_PHY_RESET /* Refer ISSUE1: * Hold the PHY in RESET for enough time till PHY is settled and ready */ udelay(EXT_PHY_RESET_DELAY); #ifdef CONFIG_OMAP3430SDP_750_2083_001 gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1); #endif gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1); #endif #ifdef VBUS_INTERNAL_CHARGEPUMP_HACK /* Refer ISSUE2: LINK assumes external charge pump */ /* use Port1 VBUS to charge externally Port2: * So for PHY mode operation use Port2 only */ omap_writel((0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */ (0x26), EHCI_INSNREG05_ULPI); while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) cpu_relax(); #endif return 0; }