/**
* omap3_noncore_dpll_set_rate - set non-core DPLL rate
* @clk: struct clk * of DPLL to set
* @rate: rounded target rate
*
* Set the DPLL CLKOUT to the target rate. If the DPLL can enter
* low-power bypass, and the target rate is the bypass source clock
* rate, then configure the DPLL for bypass. Otherwise, round the
* target rate if it hasn't been done already, then program and lock
* the DPLL. Returns -EINVAL upon error, or 0 upon success.
*/
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
{
struct clk *new_parent = NULL;
u16 freqsel = 0;
struct dpll_data *dd;
int ret;
if (!clk || !rate)
return -EINVAL;
dd = clk->dpll_data;
if (!dd)
return -EINVAL;
if (rate == omap2_get_dpll_rate(clk))
return 0;
/*
* Ensure both the bypass and ref clocks are enabled prior to
* doing anything; we need the bypass clock running to reprogram
* the DPLL.
*/
omap2_clk_enable(dd->clk_bypass);
omap2_clk_enable(dd->clk_ref);
if (dd->clk_bypass->rate == rate &&
(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
ret = _omap3_noncore_dpll_bypass(clk);
if (!ret)
new_parent = dd->clk_bypass;
} else {
if (dd->last_rounded_rate != rate)
omap2_dpll_round_rate(clk, rate);
if (dd->last_rounded_rate == 0)
return -EINVAL;
/* No freqsel on OMAP4 or OMAP3630 */
if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
freqsel = _omap3_dpll_compute_freqsel(clk,
dd->last_rounded_n);
if (!freqsel)
WARN_ON(1);
}
pr_debug("clock: %s: set rate: locking rate to %lu.\n",
clk->name, rate);
ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
dd->last_rounded_n, freqsel);
if (!ret)
new_parent = dd->clk_ref;
}
if (!ret) {
/*
* Switch the parent clock in the heirarchy, and make sure
* that the new parent's usecount is correct. Note: we
* enable the new parent before disabling the old to avoid
* any unnecessary hardware disable->enable transitions.
*/
if (clk->usecount) {
omap2_clk_enable(new_parent);
omap2_clk_disable(clk->parent);
}
clk_reparent(clk, new_parent);
clk->rate = rate;
}
omap2_clk_disable(dd->clk_ref);
omap2_clk_disable(dd->clk_bypass);
return 0;
}
/**
* omap_hsmmc_reset() - Full reset of each HS-MMC controller
*
* Ensure that each MMC controller is fully reset. Controllers
* left in an unknown state (by bootloader) may prevent retention
* or OFF-mode. This is especially important in cases where the
* MMC driver is not enabled, _or_ built as a module.
*
* In order for reset to work, interface, functional and debounce
* clocks must be enabled. The debounce clock comes from func_32k_clk
* and is not under SW control, so we only enable i- and f-clocks.
**/
static void __init omap_hsmmc_reset(void)
{
u32 i, nr_controllers;
struct clk *iclk, *fclk;
if (cpu_is_omap242x())
return;
nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC :
(cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC);
for (i = 0; i < nr_controllers; i++) {
u32 v, base = 0;
struct device *dev = &dummy_pdev.dev;
switch (i) {
case 0:
base = OMAP2_MMC1_BASE;
break;
case 1:
base = OMAP2_MMC2_BASE;
break;
case 2:
base = OMAP3_MMC3_BASE;
break;
case 3:
if (!cpu_is_omap44xx())
return;
base = OMAP4_MMC4_BASE;
break;
case 4:
if (!cpu_is_omap44xx())
return;
base = OMAP4_MMC5_BASE;
break;
}
if (cpu_is_omap44xx())
base += OMAP4_MMC_REG_OFFSET;
dummy_pdev.id = i;
dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
iclk = clk_get(dev, "ick");
if (IS_ERR(iclk))
goto err1;
if (clk_enable(iclk))
goto err2;
fclk = clk_get(dev, "fck");
if (IS_ERR(fclk))
goto err3;
if (clk_enable(fclk))
goto err4;
omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
v = omap_readl(base + MMCHS_SYSSTATUS);
while (!(omap_readl(base + MMCHS_SYSSTATUS) &
MMCHS_SYSSTATUS_RESETDONE))
cpu_relax();
clk_disable(fclk);
clk_put(fclk);
clk_disable(iclk);
clk_put(iclk);
}
return;
err4:
clk_put(fclk);
err3:
clk_disable(iclk);
err2:
clk_put(iclk);
err1:
printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, "
"cannot reset.\n", __func__, i);
}
/*
* Here we start the McBSP, by enabling transmitter, receiver or both.
* If no transmitter or receiver is active prior calling, then sample-rate
* generator and frame sync are started.
*/
void omap_mcbsp_start(unsigned int id, int tx, int rx)
{
struct omap_mcbsp *mcbsp;
int enable_srg = 0;
u16 w;
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
return;
}
mcbsp = id_to_mcbsp_ptr(id);
if (cpu_is_omap34xx())
omap_st_start(mcbsp);
/* Only enable SRG, if McBSP is master */
w = MCBSP_READ_CACHE(mcbsp, PCR0);
if (w & (FSXM | FSRM | CLKXM | CLKRM))
enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
if (enable_srg) {
/* Start the sample generator */
w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
}
/* Enable transmitter and receiver */
tx &= 1;
w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w | tx);
rx &= 1;
w = MCBSP_READ_CACHE(mcbsp, SPCR1);
MCBSP_WRITE(mcbsp, SPCR1, w | rx);
/*
* Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
* REVISIT: 100us may give enough time for two CLKSRG, however
* due to some unknown PM related, clock gating etc. reason it
* is now at 500us.
*/
udelay(500);
if (enable_srg) {
/* Start frame sync */
w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
}
if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
/* Release the transmitter and receiver */
w = MCBSP_READ_CACHE(mcbsp, XCCR);
w &= ~(tx ? XDISABLE : 0);
MCBSP_WRITE(mcbsp, XCCR, w);
w = MCBSP_READ_CACHE(mcbsp, RCCR);
w &= ~(rx ? RDISABLE : 0);
MCBSP_WRITE(mcbsp, RCCR, w);
}
/* Dump McBSP Regs */
omap_mcbsp_dump_reg(id);
}
/* ------------------------------------------------------------------------*//**
* @FUNCTION mod44xx_get_autoidle_mode
* @BRIEF retrieve omap module's autoidle mode
* @RETURNS 1 if success
* 0 if omap module's registers NOT accessible
* OMAPCONF_ERR_ARG
* OMAPCONF_ERR_REG_ACCESS
* OMAPCONF_ERR_CPU
* OMAPCONF_ERR_NOT_AVAILABLE
* OMAPCONF_ERR_INTERNAL
* @param[in] module_id: omap module ID
* @param[in,out] mode: returned omap module's autoidle mode
* @DESCRIPTION retrieve omap module's autoidle mode
*//*------------------------------------------------------------------------ */
int mod44xx_get_autoidle_mode(mod44xx_id module_id,
mod_autoidle_mode *mode)
{
int ret_val = 0;
unsigned int sysconfig;
char name[MOD44XX_MAX_NAME_LENGTH];
mod_interface_type type;
*mode = MOD_AUTOIDLE_MODE_MAX;
if (!cpu_is_omap44xx())
return OMAPCONF_ERR_CPU;
if (module_id >= OMAP4_MODULE_ID_MAX)
return OMAPCONF_ERR_ARG;
mod44xx_get_interface_type(module_id, &type);
if (type == MOD_INTERFACE_NONE) {
dprintf("%s(): module #%d name = %s has no SYSCONFIG\n",
__func__, module_id,
mod44xx_get_name(module_id, name));
return OMAPCONF_ERR_NOT_AVAILABLE;
}
ret_val = mod44xx_is_accessible(module_id);
if (ret_val == 1) {
/* Module is accessible */
dprintf("%s(): module #%d name = %s is accessible\n",
__func__, module_id,
mod44xx_get_name(module_id, name));
if (mod44xx_info_table[module_id].sysconfig_addr != NULL) {
OMAP_READREG((unsigned int)
mod44xx_info_table[module_id].sysconfig_addr,
sysconfig);
dprintf(
"%s(): SYSCONFIG ADDR = 0x%08X SYSCONFIG = 0x%08X\n",
__func__,
(unsigned int)
mod44xx_info_table[module_id].sysconfig_addr,
sysconfig);
/* Check module's autoidle bit */
switch (module_id) {
case OMAP4_CONTROL_GEN_WKUP:
case OMAP4_CONTROL_PADCONF_WKUP:
case OMAP4_SYNCTIMER:
case OMAP4_WDT2:
case OMAP4_WDT3:
case OMAP4_TIMER3:
case OMAP4_TIMER4:
case OMAP4_TIMER5:
case OMAP4_TIMER6:
case OMAP4_TIMER7:
case OMAP4_TIMER8:
case OMAP4_TIMER9:
case OMAP4_TIMER11:
case OMAP4_MCASP:
case OMAP4_IVAHD:
case OMAP4_ICONT1:
case OMAP4_ICONT2:
case OMAP4_VDMA:
case OMAP4_IME3:
case OMAP4_ILF3:
case OMAP4_MC3:
case OMAP4_CALC3:
case OMAP4_ECD3:
case OMAP4_SMARTREFLEX_CORE:
case OMAP4_SMARTREFLEX_MPU:
case OMAP4_SMARTREFLEX_IVA:
case OMAP4_CONTROL_GEN_CORE:
case OMAP4_CONTROL_PADCONF_CORE:
case OMAP4_SYSTEM_MAILBOX:
case OMAP4_DMM:
case OMAP4_AESS:
case OMAP4_SIMCOP:
case OMAP4_SIMCOP_DMA:
case OMAP4_FDIF:
case OMAP4_HDMI:
case OMAP4_GFX:
case OMAP4_MMC1_HL:
case OMAP4_MMC2_HL:
case OMAP4_MMC3_HL:
case OMAP4_MMC4_HL:
case OMAP4_MMC5_HL:
//.........这里部分代码省略.........
//.........这里部分代码省略.........
"omapconf write PM_MPU_PWRSTCTRL 0xDEADBEEF\n");
printf("\n\tomapconf set bit [0x<physical address> | <name>] "
"<position>"
"\n");
printf("\t Set bit at <position> into any OMAP memory "
"address (register), given its <physical address> "
"or <name> as listed in TRM.\n");
printf("\t e.g: omapconf set bit 0x4A306300 1, "
"omapconf set bit PM_MPU_PWRSTCTRL 1\n");
printf("\n\tomapconf clear bit [0x<physical address> | <name>] "
"<position>\n");
printf("\t Clear bit at <position> into any OMAP memory "
"address (register), given its <physical address> "
"or <name> as listed in TRM.\n");
printf("\t e.g: omapconf clear bit 0x4A306300 1, "
"omapconf clear bit PM_MPU_PWRSTCTRL 1\n");
printf("\n\tomapconf dump 0x<start address> 0x<end address>\n");
printf("\t Dump a range of OMAP memory addresses, from "
"<start address> to <end address>.\n");
printf("\t Note all addresses within given range must be "
"valid and accessible.\n");
printf("\t e.g: omapconf dump 0x48243400 0x4824340C\n");
}
if ((cat == HELP_ALL) || (cat == HELP_RW) || (cat == HELP_I2C_RW)) {
printf("\n\t### WARNING ###: use the following I2C "
"[read | write] commands at your own risk!\n");
printf("\tNo address check done, may generate:\n");
printf("\t - I2C bus error (invalid or not accessible "
"<physical address>,\n");
printf("\t - platform crash/hang (bad <value>).\n");
printf("\n\tomapconf read i2c <bus> 0x<chip-addr> 0x<addr>\n");
printf("\t Read I2C register at address <addr> from I2C chip"
" at <chip-addr> on I2C <bus>.\n");
printf("\t e.g: omapconf i2c read 1 0x49 0x02\n");
printf("\n\tomapconf write i2c <bus> 0x<chip-addr> 0x<addr> "
"0x<value>\n");
printf("\t Write <value> in I2C register at address <addr> "
"from I2C chip at <chip-addr> on I2C <bus>.\n");
printf("\t e.g: omapconf i2c write 1 0x49 0x02 0xAA\n");
}
if ((cat == HELP_RW) || (cat == HELP_I2C_RW) ||
(cat == HELP_FORCEDETECT))
goto help_end;
/* OMAP4-specific commands */
if (cpu_is_omap44xx())
help44xx(cat, "all");
/* OMAP5-specific commands */
if (cpu_is_omap54xx())
help54xx(cat, "None");
/* DRA7-specific commands */
if (cpu_is_dra7xx())
help_dra7xx(cat, "None");
if (cat == HELP_ALL) {
printf("\nREPORTING BUGS\n");
printf("\tReport bugs to <[email protected]> "
"mailing-list.\n");
printf("\tYou do not have to be subsribed to the list to send "
"a message there.\n");
printf("\nSUGGESTIONS\n");
printf("\tSuggest any new idea to "
"<[email protected]> mailing-list.\n");
printf("\tYou do not have to be subsribed to the list to send "
"a message there.\n");
printf("\nCONTRIBUTIONS\n");
printf("\tSend patch to <[email protected]> "
"mailing-list.\n");
printf("\tYou do not have to be subsribed to the list to send "
"a message there.\n");
printf("\nNOTIFICATIONS\n");
printf("\tSubscribe to <[email protected]> "
"mailing-list for automatic update notification.\n");
printf("\tYou do not have to be subsribed to the list to send "
"a message there.\n");
printf("\nFURTHER DOCUMENTATION\n");
printf("\tVisit omapconf wiki:\n");
printf("\t\t<https://github.com/omapconf/omapconf/wiki>\n");
printf("\n");
}
help_end:
return;
}
请发表评论