📄 clock.c
字号:
.name = "ck_pll3", .parent = &ck_pll1, .flags = NEEDS_INITIALIZATION, .round_rate = &pll3_round_rate, .set_rate = &pll160_set_rate, .scale_reg = DSPPLLCTRL_REG, .enable_reg = DSPCLKCTRL_REG, .enable_shift = 3, .enable_reg1 = DSPCLKCTRL_REG, .enable_shift1 = 2, .parent_switch_reg = DSPCLKCTRL_REG, .set_parent = &set_13MHz_parent,};static struct clk hclk_ck = { .name = "hclk_ck", .parent = &ck_pll4, .flags = PARENT_SET_RATE, .set_rate = &hclk_set_rate, .round_rate = &hclk_round_rate, .scale_reg = HCLKDIVCTRL_REG, .rate = 2, .user_rate = 2,};static struct clk per_ck = { .name = "per_ck", .parent = &ck_pll4, .flags = FIXED_RATE, .propagate_next = &hclk_ck, .set_rate = &per_clk_set_rate, .round_rate = &per_clk_round_rate, .scale_reg = HCLKDIVCTRL_REG, .rate = CLK_RATE_13MHZ, .user_rate = CLK_RATE_13MHZ,};static struct clk m2hclk_ck = { .name = "m2hclk_ck", .parent = &hclk_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_inv_set_rate, .rate = 1, .enable_shift = 6, .enable_reg = PWRCTRL_REG,};static struct clk vfp9_ck = { .name = "vfp9_ck", .parent = &ck_pll4, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .rate = 1, .enable_shift = 4, .enable_reg = VFP9CLKCTRL_REG,};static struct clk keyscan_ck = { .name = "keyscan_ck", .parent = &osc_32KHz, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = KEYCLKCTRL_REG,};static struct clk touch_ck = { .name = "touch_ck", .parent = &osc_32KHz, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = TSCLKCTRL_REG,};static struct clk pwm1_ck = { .name = "pwm1_ck", .parent = &osc_32KHz, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = PWMCLKCTRL_REG,};static struct clk pwm2_ck = { .name = "pwm2_ck", .parent = &osc_32KHz, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 2, .enable_reg = PWMCLKCTRL_REG,};static struct clk jpeg_ck = { .name = "jpeg_ck", .parent = &hclk_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = JPEGCLKCTRL_REG,};static struct clk ms_ck = { .name = "ms_ck", .parent = &ck_pll4, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 5, .enable_reg = MSCTRL_REG,};static struct clk dum_ck = { .name = "dum_ck", .parent = &hclk_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = DUMCLKCTRL_REG,};static struct clk flash_ck = { .name = "flash_ck", .parent = &hclk_ck, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 1, /* Only MLC clock supported */ .enable_reg = FLASHCLKCTRL_REG,};static struct clk i2c0_ck = { .name = "i2c0_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = I2CCLKCTRL_REG,};static struct clk i2c1_ck = { .name = "i2c1_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 1, .enable_reg = I2CCLKCTRL_REG,};static struct clk i2c2_ck = { .name = "i2c2_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 2, .enable_reg = USB_OTG_CLKCTRL_REG,};static struct clk spi0_ck = { .name = "spi0_ck", .parent = &hclk_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = SPICTRL_REG,};static struct clk spi1_ck = { .name = "spi1_ck", .parent = &hclk_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 4, .enable_reg = SPICTRL_REG,};static struct clk dma_ck = { .name = "dma_ck", .parent = &hclk_ck, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = DMACLKCTRL_REG,};static struct clk uart3_ck = { .name = "uart3_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .rate = 1, .enable_shift = 0, .enable_reg = UARTCLKCTRL_REG,};static struct clk uart4_ck = { .name = "uart4_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 1, .enable_reg = UARTCLKCTRL_REG,};static struct clk uart5_ck = { .name = "uart5_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .rate = 1, .enable_shift = 2, .enable_reg = UARTCLKCTRL_REG,};static struct clk uart6_ck = { .name = "uart6_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 3, .enable_reg = UARTCLKCTRL_REG,};static struct clk wdt_ck = { .name = "wdt_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, .round_rate = &on_off_round_rate, .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = TIMCLKCTRL_REG,};/* These clocks are visible outside this module * and can be initialized */static struct clk *onchip_clks[] = { &ck_13MHz, &ck_pll1, &ck_pll4, &ck_pll5, &ck_pll3, &vfp9_ck, &m2hclk_ck, &hclk_ck, &dma_ck, &flash_ck, &dum_ck, &keyscan_ck, &pwm1_ck, &pwm2_ck, &jpeg_ck, &ms_ck, &touch_ck, &i2c0_ck, &i2c1_ck, &i2c2_ck, &spi0_ck, &spi1_ck, &uart3_ck, &uart4_ck, &uart5_ck, &uart6_ck, &wdt_ck,};static int local_clk_enable(struct clk *clk){ int ret = 0; if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate && clk->user_rate) ret = clk->set_rate(clk, clk->user_rate); return ret;}static void local_clk_disable(struct clk *clk){ if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) clk->set_rate(clk, 0);}static void local_clk_unuse(struct clk *clk){ if (clk->usecount > 0 && !(--clk->usecount)) { local_clk_disable(clk); if (clk->parent) local_clk_unuse(clk->parent); }}static int local_clk_use(struct clk *clk){ int ret = 0; if (clk->usecount++ == 0) { if (clk->parent) ret = local_clk_use(clk->parent); if (ret != 0) { clk->usecount--; goto out; } ret = local_clk_enable(clk); if (ret != 0 && clk->parent) { local_clk_unuse(clk->parent); clk->usecount--; } }out: return ret;}static int local_set_rate(struct clk *clk, u32 rate){ int ret = -EINVAL; if (clk->set_rate) { if (clk->user_rate == clk->rate && clk->parent->rate) { /* if clock enabled or rate not set */ clk->user_rate = clk->round_rate(clk, rate); ret = clk->set_rate(clk, clk->user_rate); } else clk->user_rate = clk->round_rate(clk, rate); ret = 0; } return ret;}int clk_set_rate(struct clk *clk, unsigned long rate){ int ret = -EINVAL; if (clk->flags & FIXED_RATE) goto out; clock_lock(); if ((clk->flags & PARENT_SET_RATE) && clk->parent) { clk->user_rate = clk->round_rate(clk, rate); /* parent clock needs to be refreshed for the setting to take effect */ } else { ret = local_set_rate(clk, rate); } ret = 0; clock_unlock();out: return ret;}EXPORT_SYMBOL(clk_set_rate);struct clk *clk_get(struct device *dev, const char *id){ struct clk *clk = ERR_PTR(-ENOENT); struct clk **clkp; clock_lock(); for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); clkp++) { if (strcmp(id, (*clkp)->name) == 0 && try_module_get((*clkp)->owner)) { clk = (*clkp); break; } } clock_unlock(); return clk;}EXPORT_SYMBOL(clk_get);void clk_put(struct clk *clk){ clock_lock(); if (clk && !IS_ERR(clk)) module_put(clk->owner); clock_unlock();}EXPORT_SYMBOL(clk_put);unsigned long clk_get_rate(struct clk *clk){ unsigned long ret; clock_lock(); ret = clk->rate; clock_unlock(); return ret;}EXPORT_SYMBOL(clk_get_rate);int clk_enable(struct clk *clk){ int ret = 0; clock_lock(); ret = local_clk_use(clk); clock_unlock(); return ret;}EXPORT_SYMBOL(clk_enable);void clk_disable(struct clk *clk){ clock_lock(); local_clk_unuse(clk); clock_unlock();}EXPORT_SYMBOL(clk_disable);long clk_round_rate(struct clk *clk, unsigned long rate){ long ret; clock_lock(); if (clk->round_rate) ret = clk->round_rate(clk, rate); else ret = clk->rate; clock_unlock(); return ret;}EXPORT_SYMBOL(clk_round_rate);int clk_set_parent(struct clk *clk, struct clk *parent){ int ret = -ENODEV; if (!clk->set_parent) goto out; clock_lock(); ret = clk->set_parent(clk, parent); if (!ret) clk->parent = parent; clock_unlock();out: return ret;}EXPORT_SYMBOL(clk_set_parent);static int __init clk_init(void){ struct clk **clkp; /* Disable autoclocking, as it doesn't seem to work */ __raw_writel(0xff, AUTOCLK_CTRL); for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); clkp++) { if (((*clkp)->flags & NEEDS_INITIALIZATION) && ((*clkp)->set_rate)) { (*clkp)->user_rate = (*clkp)->rate; local_set_rate((*clkp), (*clkp)->user_rate); if ((*clkp)->set_parent) (*clkp)->set_parent((*clkp), (*clkp)->parent); } pr_debug("%s: clock %s, rate %ld\n", __FUNCTION__, (*clkp)->name, (*clkp)->rate); } local_clk_use(&ck_pll4); /* if ck_13MHz is not used, disable it. */ if (ck_13MHz.usecount == 0) local_clk_disable(&ck_13MHz); /* Disable autoclocking */ __raw_writeb(0xff, AUTOCLK_CTRL); return 0;}arch_initcall(clk_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -