/* * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include /** * Calculate the current M-PLL clock. * @return Current frequency in Hz */ uint32_t s3c_get_mpllclk(void) { uint32_t m, p, s, reg_val; reg_val = readl(S3C_MPLLCON); m = ((reg_val & 0xFF000) >> 12) + 8; p = ((reg_val & 0x003F0) >> 4) + 2; s = reg_val & 0x3; #ifdef CONFIG_CPU_S3C2410 return (S3C24XX_CLOCK_REFERENCE * m) / (p << s); #endif #ifdef CONFIG_CPU_S3C2440 return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s)); #endif } /** * Calculate the current U-PLL clock * @return Current frequency in Hz */ uint32_t s3c_get_upllclk(void) { uint32_t m, p, s, reg_val; reg_val = readl(S3C_UPLLCON); m = ((reg_val & 0xFF000) >> 12) + 8; p = ((reg_val & 0x003F0) >> 4) + 2; s = reg_val & 0x3; return (S3C24XX_CLOCK_REFERENCE * m) / (p << s); } /** * Calculate the FCLK frequency used for the ARM CPU core * @return Current frequency in Hz */ uint32_t s3c_get_fclk(void) { return s3c_get_mpllclk(); } /** * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral) * @return Current frequency in Hz */ uint32_t s3c_get_hclk(void) { uint32_t f_clk; f_clk = s3c_get_fclk(); #ifdef CONFIG_CPU_S3C2410 if (readl(S3C_CLKDIVN) & 0x02) return f_clk >> 1; #endif #ifdef CONFIG_CPU_S3C2440 switch(readl(S3C_CLKDIVN) & 0x06) { case 2: return f_clk >> 1; case 4: return f_clk >> 2; /* TODO consider CAMDIVN */ case 6: return f_clk / 3; /* TODO consider CAMDIVN */ } #endif return f_clk; } /** * Calculate the PCLK frequency used for the slower peripherals * @return Current frequency in Hz */ uint32_t s3c_get_pclk(void) { uint32_t p_clk; p_clk = s3c_get_hclk(); if (readl(S3C_CLKDIVN) & 0x01) return p_clk >> 1; return p_clk; } /** * Calculate the UCLK frequency used by the USB host device * @return Current frequency in Hz */ uint32_t s3c24_get_uclk(void) { return s3c_get_upllclk(); } /** * Return correct UART frequency based on the UCON register */ unsigned s3c_get_uart_clk(unsigned src) { switch (src & 3) { case 0: case 2: return s3c_get_pclk(); case 1: return 0; /* TODO UEXTCLK */ case 3: return 0; /* TODO FCLK/n */ } return 0; /* not reached, to make compiler happy */ } /** * Show the user the current clock settings */ int s3c24xx_dump_clocks(void) { printf("refclk: %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000); printf("mpll: %7d kHz\n", s3c_get_mpllclk() / 1000); printf("upll: %7d kHz\n", s3c_get_upllclk() / 1000); printf("fclk: %7d kHz\n", s3c_get_fclk() / 1000); printf("hclk: %7d kHz\n", s3c_get_hclk() / 1000); printf("pclk: %7d kHz\n", s3c_get_pclk() / 1000); printf("SDRAM1: CL%d@%dMHz\n", ((readl(S3C_BANKCON6) & 0xc) >> 2) + 2, s3c_get_hclk() / 1000000); if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15)) printf("SDRAM2: CL%d@%dMHz\n", ((readl(S3C_BANKCON7) & 0xc) >> 2) + 2, s3c_get_hclk() / 1000000); return 0; } late_initcall(s3c24xx_dump_clocks);