📄 clock.c
字号:
l = omap_readl(MOD_CONF_CTRL_1); l &= ~(7 << 17); l |= div << 17; omap_writel(l, MOD_CONF_CTRL_1); clk->rate = p_rate / (div + 1); if (unlikely(clk->flags & RATE_PROPAGATES)) propagate_rate(clk); return 0;}static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate){ return 96000000 / calc_ext_dsor(rate);}static void omap1_init_ext_clk(struct clk * clk){ unsigned dsor; __u16 ratio_bits; /* Determine current rate and ensure clock is based on 96MHz APLL */ ratio_bits = omap_readw(clk->enable_reg) & ~1; omap_writew(ratio_bits, clk->enable_reg); ratio_bits = (ratio_bits & 0xfc) >> 2; if (ratio_bits > 6) dsor = (ratio_bits - 6) * 2 + 8; else dsor = ratio_bits + 2; clk-> rate = 96000000 / dsor;}static int omap1_clk_enable(struct clk *clk){ int ret = 0; if (clk->usecount++ == 0) { if (likely(clk->parent)) { ret = omap1_clk_enable(clk->parent); if (unlikely(ret != 0)) { clk->usecount--; return ret; } if (clk->flags & CLOCK_NO_IDLE_PARENT) omap1_clk_deny_idle(clk->parent); } ret = clk->enable(clk); if (unlikely(ret != 0) && clk->parent) { omap1_clk_disable(clk->parent); clk->usecount--; } } return ret;}static void omap1_clk_disable(struct clk *clk){ if (clk->usecount > 0 && !(--clk->usecount)) { clk->disable(clk); if (likely(clk->parent)) { omap1_clk_disable(clk->parent); if (clk->flags & CLOCK_NO_IDLE_PARENT) omap1_clk_allow_idle(clk->parent); } }}static int omap1_clk_enable_generic(struct clk *clk){ __u16 regval16; __u32 regval32; if (clk->flags & ALWAYS_ENABLED) return 0; if (unlikely(clk->enable_reg == 0)) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", clk->name); return -EINVAL; } if (clk->flags & ENABLE_REG_32BIT) { if (clk->flags & VIRTUAL_IO_ADDRESS) { regval32 = __raw_readl(clk->enable_reg); regval32 |= (1 << clk->enable_bit); __raw_writel(regval32, clk->enable_reg); } else { regval32 = omap_readl(clk->enable_reg); regval32 |= (1 << clk->enable_bit); omap_writel(regval32, clk->enable_reg); } } else { if (clk->flags & VIRTUAL_IO_ADDRESS) { regval16 = __raw_readw(clk->enable_reg); regval16 |= (1 << clk->enable_bit); __raw_writew(regval16, clk->enable_reg); } else { regval16 = omap_readw(clk->enable_reg); regval16 |= (1 << clk->enable_bit); omap_writew(regval16, clk->enable_reg); } } return 0;}static void omap1_clk_disable_generic(struct clk *clk){ __u16 regval16; __u32 regval32; if (clk->enable_reg == 0) return; if (clk->flags & ENABLE_REG_32BIT) { if (clk->flags & VIRTUAL_IO_ADDRESS) { regval32 = __raw_readl(clk->enable_reg); regval32 &= ~(1 << clk->enable_bit); __raw_writel(regval32, clk->enable_reg); } else { regval32 = omap_readl(clk->enable_reg); regval32 &= ~(1 << clk->enable_bit); omap_writel(regval32, clk->enable_reg); } } else { if (clk->flags & VIRTUAL_IO_ADDRESS) { regval16 = __raw_readw(clk->enable_reg); regval16 &= ~(1 << clk->enable_bit); __raw_writew(regval16, clk->enable_reg); } else { regval16 = omap_readw(clk->enable_reg); regval16 &= ~(1 << clk->enable_bit); omap_writew(regval16, clk->enable_reg); } }}static long omap1_clk_round_rate(struct clk *clk, unsigned long rate){ int dsor_exp; if (clk->flags & RATE_FIXED) return clk->rate; if (clk->flags & RATE_CKCTL) { dsor_exp = calc_dsor_exp(clk, rate); if (dsor_exp < 0) return dsor_exp; if (dsor_exp > 3) dsor_exp = 3; return clk->parent->rate / (1 << dsor_exp); } if(clk->round_rate != 0) return clk->round_rate(clk, rate); return clk->rate;}static int omap1_clk_set_rate(struct clk *clk, unsigned long rate){ int ret = -EINVAL; int dsor_exp; __u16 regval; if (clk->set_rate) ret = clk->set_rate(clk, rate); else if (clk->flags & RATE_CKCTL) { dsor_exp = calc_dsor_exp(clk, rate); if (dsor_exp > 3) dsor_exp = -EINVAL; if (dsor_exp < 0) return dsor_exp; regval = omap_readw(ARM_CKCTL); regval &= ~(3 << clk->rate_offset); regval |= dsor_exp << clk->rate_offset; regval = verify_ckctl_value(regval); omap_writew(regval, ARM_CKCTL); clk->rate = clk->parent->rate / (1 << dsor_exp); ret = 0; } if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) propagate_rate(clk); return ret;}/*------------------------------------------------------------------------- * Omap1 clock reset and init functions *-------------------------------------------------------------------------*/#ifdef CONFIG_OMAP_RESET_CLOCKSstatic void __init omap1_clk_disable_unused(struct clk *clk){ __u32 regval32; /* Clocks in the DSP domain need api_ck. Just assume bootloader * has not enabled any DSP clocks */ if ((u32)clk->enable_reg == DSP_IDLECT2) { printk(KERN_INFO "Skipping reset check for DSP domain " "clock \"%s\"\n", clk->name); return; } /* Is the clock already disabled? */ if (clk->flags & ENABLE_REG_32BIT) { if (clk->flags & VIRTUAL_IO_ADDRESS) regval32 = __raw_readl(clk->enable_reg); else regval32 = omap_readl(clk->enable_reg); } else { if (clk->flags & VIRTUAL_IO_ADDRESS) regval32 = __raw_readw(clk->enable_reg); else regval32 = omap_readw(clk->enable_reg); } if ((regval32 & (1 << clk->enable_bit)) == 0) return; /* FIXME: This clock seems to be necessary but no-one * has asked for its activation. */ if (clk == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera || clk == &ck_dpll1out.clk // FIX: SoSSI, SSR || clk == &arm_gpio_ck // FIX: GPIO code for 1510 ) { printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n", clk->name); return; } printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name); clk->disable(clk); printk(" done\n");}#else#define omap1_clk_disable_unused NULL#endifstatic struct clk_functions omap1_clk_functions = { .clk_enable = omap1_clk_enable, .clk_disable = omap1_clk_disable, .clk_round_rate = omap1_clk_round_rate, .clk_set_rate = omap1_clk_set_rate, .clk_disable_unused = omap1_clk_disable_unused,};int __init omap1_clk_init(void){ struct clk ** clkp; const struct omap_clock_config *info; int crystal_type = 0; /* Default 12 MHz */ u32 reg;#ifdef CONFIG_DEBUG_LL /* Resets some clocks that may be left on from bootloader, * but leaves serial clocks on. */ omap_writel(0x3 << 29, MOD_CONF_CTRL_0);#endif /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ reg = omap_readw(SOFT_REQ_REG) & (1 << 4); omap_writew(reg, SOFT_REQ_REG); if (!cpu_is_omap15xx()) omap_writew(0, SOFT_REQ_REG2); clk_init(&omap1_clk_functions); /* By default all idlect1 clocks are allowed to idle */ arm_idlect1_mask = ~0; for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) { if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) { clk_register(*clkp); continue; } if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) { clk_register(*clkp); continue; } if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) { clk_register(*clkp); continue; } if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) { clk_register(*clkp); continue; } } info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); if (info != NULL) { if (!cpu_is_omap15xx()) crystal_type = info->system_clock_type; }#if defined(CONFIG_ARCH_OMAP730) ck_ref.rate = 13000000;#elif defined(CONFIG_ARCH_OMAP16XX) if (crystal_type == 2) ck_ref.rate = 19200000;#endif printk("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n", omap_readw(ARM_SYSST), omap_readw(DPLL_CTL), omap_readw(ARM_CKCTL)); /* We want to be in syncronous scalable mode */ omap_writew(0x1000, ARM_SYSST);#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER /* Use values set by bootloader. Determine PLL rate and recalculate * dependent clocks as if kernel had changed PLL or divisors. */ { unsigned pll_ctl_val = omap_readw(DPLL_CTL); ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */ if (pll_ctl_val & 0x10) { /* PLL enabled, apply multiplier and divisor */ if (pll_ctl_val & 0xf80) ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7; ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1; } else { /* PLL disabled, apply bypass divisor */ switch (pll_ctl_val & 0xc) { case 0: break; case 0x4: ck_dpll1.rate /= 2; break; default: ck_dpll1.rate /= 4; break; } } } propagate_rate(&ck_dpll1);#else /* Find the highest supported frequency and enable it */ if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { printk(KERN_ERR "System frequencies not set. Check your config.\n"); /* Guess sane values (60MHz) */ omap_writew(0x2290, DPLL_CTL); omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL); ck_dpll1.rate = 60000000; propagate_rate(&ck_dpll1); }#endif /* Cache rates for clocks connected to ck_ref (not dpll1) */ propagate_rate(&ck_ref); printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) /* Select slicer output as OMAP input clock */ omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);#endif /* Amstrad Delta wants BCLK high when inactive */ if (machine_is_ams_delta()) omap_writel(omap_readl(ULPD_CLOCK_CTRL) | (1 << SDW_MCLK_INV_BIT), ULPD_CLOCK_CTRL); /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ /* (on 730, bit 13 must not be cleared) */ if (cpu_is_omap730()) omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL); else omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); /* Put DSP/MPUI into reset until needed */ omap_writew(0, ARM_RSTCT1); omap_writew(1, ARM_RSTCT2); omap_writew(0x400, ARM_IDLECT1); /* * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8) * of the ARM_IDLECT2 register must be set to zero. The power-on * default value of this bit is one. */ omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */ /* * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ clk_enable(&armper_ck.clk); clk_enable(&armxor_ck.clk); clk_enable(&armtim_ck.clk); /* This should be done by timer code */ if (cpu_is_omap15xx()) clk_enable(&arm_gpio_ck); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -