void __init_or_cpufreq s3c2443_setup_clocks(void) { unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); struct clk *xtal_clk; unsigned long xtal; unsigned long pll; unsigned long fclk; unsigned long hclk; unsigned long pclk; xtal_clk = clk_get(NULL, "xtal"); xtal = clk_get_rate(xtal_clk); clk_put(xtal_clk); pll = s3c2443_get_mpll(mpllcon, xtal); clk_msysclk.rate = pll; fclk = pll / s3c2443_fclk_div(clkdiv0); hclk = s3c2443_prediv_getrate(&clk_prediv); hclk /= s3c2443_get_hdiv(clkdiv0); pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); s3c24xx_setup_clocks(fclk, hclk, pclk); printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on", print_mhz(pll), print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); s3c24xx_setup_clocks(fclk, hclk, pclk); }
void __init s3c2443_init_clocks(int xtal) { unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); unsigned long pll; unsigned long fclk; unsigned long hclk; unsigned long pclk; struct clk *clkp; int ret; int ptr; /* s3c2443 parents h and p clocks from prediv */ clk_h.parent = &clk_prediv; clk_p.parent = &clk_prediv; pll = s3c2443_get_mpll(mpllcon, xtal); clk_msysclk.rate = pll; fclk = pll / s3c2443_fclk_div(clkdiv0); hclk = s3c2443_prediv_getrate(&clk_prediv); hclk /= s3c2443_get_hdiv(clkdiv0); pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on", print_mhz(pll), print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); s3c2443_clk_initparents(); for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { clkp = clks[ptr]; ret = s3c24xx_register_clock(clkp); if (ret < 0) { printk(KERN_ERR "Failed to register clock %s (%d)\n", clkp->name, ret); } } clk_epll.rate = s3c2443_get_epll(epllcon, xtal); clk_usb_bus.parent = &clk_usb_bus_host; /* ensure usb bus clock is within correct rate of 48MHz */ if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) { printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); clk_set_rate(&clk_usb_bus_host, 48*1000*1000); } printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", (epllcon & S3C2443_PLLCON_OFF) ? "off":"on", print_mhz(clk_get_rate(&clk_epll)), print_mhz(clk_get_rate(&clk_usb_bus))); /* register clocks from clock array */ clkp = init_clocks; for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { ret = s3c24xx_register_clock(clkp); if (ret < 0) { printk(KERN_ERR "Failed to register clock %s (%d)\n", clkp->name, ret); } } /* We must be careful disabling the clocks we are not intending to * be using at boot time, as subsystems such as the LCD which do * their own DMA requests to the bus can cause the system to lockup * if they where in the middle of requesting bus access. * * Disabling the LCD clock if the LCD is active is very dangerous, * and therefore the bootloader should be careful to not enable * the LCD clock if it is not needed. */ /* install (and disable) the clocks we do not need immediately */ clkp = init_clocks_disable; for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { ret = s3c24xx_register_clock(clkp); if (ret < 0) { printk(KERN_ERR "Failed to register clock %s (%d)\n", clkp->name, ret); } (clkp->enable)(clkp, 0); } }