|
@@ -27,6 +27,49 @@
|
|
|
#include <asm/arch/clk.h>
|
|
|
#include <asm/arch/periph.h>
|
|
|
|
|
|
+/* *
|
|
|
+ * This structure is to store the src bit, div bit and prediv bit
|
|
|
+ * positions of the peripheral clocks of the src and div registers
|
|
|
+ */
|
|
|
+struct clk_bit_info {
|
|
|
+ int8_t src_bit;
|
|
|
+ int8_t div_bit;
|
|
|
+ int8_t prediv_bit;
|
|
|
+};
|
|
|
+
|
|
|
+/* src_bit div_bit prediv_bit */
|
|
|
+static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = {
|
|
|
+ {0, 0, -1},
|
|
|
+ {4, 4, -1},
|
|
|
+ {8, 8, -1},
|
|
|
+ {12, 12, -1},
|
|
|
+ {0, 0, 8},
|
|
|
+ {4, 16, 24},
|
|
|
+ {8, 0, 8},
|
|
|
+ {12, 16, 24},
|
|
|
+ {-1, -1, -1},
|
|
|
+ {16, 0, 8},
|
|
|
+ {20, 16, 24},
|
|
|
+ {24, 0, 8},
|
|
|
+ {0, 0, 4},
|
|
|
+ {4, 12, 16},
|
|
|
+ {-1, -1, -1},
|
|
|
+ {-1, -1, -1},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {-1, 24, 0},
|
|
|
+ {24, 0, -1},
|
|
|
+ {24, 0, -1},
|
|
|
+ {24, 0, -1},
|
|
|
+ {24, 0, -1},
|
|
|
+ {24, 0, -1},
|
|
|
+};
|
|
|
+
|
|
|
/* Epll Clock division values to achive different frequency output */
|
|
|
static struct set_epll_con_val exynos5_epll_div[] = {
|
|
|
{ 192000000, 0, 48, 3, 1, 0 },
|
|
@@ -201,6 +244,107 @@ static unsigned long exynos5_get_pll_clk(int pllreg)
|
|
|
return fout;
|
|
|
}
|
|
|
|
|
|
+static unsigned long exynos5_get_periph_rate(int peripheral)
|
|
|
+{
|
|
|
+ struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
|
|
|
+ unsigned long sclk, sub_clk;
|
|
|
+ unsigned int src, div, sub_div;
|
|
|
+ struct exynos5_clock *clk =
|
|
|
+ (struct exynos5_clock *)samsung_get_base_clock();
|
|
|
+
|
|
|
+ switch (peripheral) {
|
|
|
+ case PERIPH_ID_UART0:
|
|
|
+ case PERIPH_ID_UART1:
|
|
|
+ case PERIPH_ID_UART2:
|
|
|
+ case PERIPH_ID_UART3:
|
|
|
+ src = readl(&clk->src_peric0);
|
|
|
+ div = readl(&clk->div_peric0);
|
|
|
+ break;
|
|
|
+ case PERIPH_ID_PWM0:
|
|
|
+ case PERIPH_ID_PWM1:
|
|
|
+ case PERIPH_ID_PWM2:
|
|
|
+ case PERIPH_ID_PWM3:
|
|
|
+ case PERIPH_ID_PWM4:
|
|
|
+ src = readl(&clk->src_peric0);
|
|
|
+ div = readl(&clk->div_peric3);
|
|
|
+ break;
|
|
|
+ case PERIPH_ID_SPI0:
|
|
|
+ case PERIPH_ID_SPI1:
|
|
|
+ src = readl(&clk->src_peric1);
|
|
|
+ div = readl(&clk->div_peric1);
|
|
|
+ break;
|
|
|
+ case PERIPH_ID_SPI2:
|
|
|
+ src = readl(&clk->src_peric1);
|
|
|
+ div = readl(&clk->div_peric2);
|
|
|
+ break;
|
|
|
+ case PERIPH_ID_SPI3:
|
|
|
+ case PERIPH_ID_SPI4:
|
|
|
+ src = readl(&clk->sclk_src_isp);
|
|
|
+ div = readl(&clk->sclk_div_isp);
|
|
|
+ break;
|
|
|
+ case PERIPH_ID_SDMMC0:
|
|
|
+ case PERIPH_ID_SDMMC1:
|
|
|
+ case PERIPH_ID_SDMMC2:
|
|
|
+ case PERIPH_ID_SDMMC3:
|
|
|
+ src = readl(&clk->src_fsys);
|
|
|
+ div = readl(&clk->div_fsys1);
|
|
|
+ break;
|
|
|
+ case PERIPH_ID_I2C0:
|
|
|
+ case PERIPH_ID_I2C1:
|
|
|
+ case PERIPH_ID_I2C2:
|
|
|
+ case PERIPH_ID_I2C3:
|
|
|
+ case PERIPH_ID_I2C4:
|
|
|
+ case PERIPH_ID_I2C5:
|
|
|
+ case PERIPH_ID_I2C6:
|
|
|
+ case PERIPH_ID_I2C7:
|
|
|
+ sclk = exynos5_get_pll_clk(MPLL);
|
|
|
+ sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
|
|
|
+ & 0x7) + 1;
|
|
|
+ div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
|
|
|
+ & 0x7) + 1;
|
|
|
+ return (sclk / sub_div) / div;
|
|
|
+ default:
|
|
|
+ debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
|
+ return -1;
|
|
|
+ };
|
|
|
+
|
|
|
+ src = (src >> bit_info->src_bit) & 0xf;
|
|
|
+
|
|
|
+ switch (src) {
|
|
|
+ case EXYNOS_SRC_MPLL:
|
|
|
+ sclk = exynos5_get_pll_clk(MPLL);
|
|
|
+ break;
|
|
|
+ case EXYNOS_SRC_EPLL:
|
|
|
+ sclk = exynos5_get_pll_clk(EPLL);
|
|
|
+ break;
|
|
|
+ case EXYNOS_SRC_VPLL:
|
|
|
+ sclk = exynos5_get_pll_clk(VPLL);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Ratio clock division for this peripheral */
|
|
|
+ sub_div = (div >> bit_info->div_bit) & 0xf;
|
|
|
+ sub_clk = sclk / (sub_div + 1);
|
|
|
+
|
|
|
+ /* Pre-ratio clock division for SDMMC0 and 2 */
|
|
|
+ if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) {
|
|
|
+ div = (div >> bit_info->prediv_bit) & 0xff;
|
|
|
+ return sub_clk / (div + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return sub_clk;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned long clock_get_periph_rate(int peripheral)
|
|
|
+{
|
|
|
+ if (cpu_is_exynos5())
|
|
|
+ return exynos5_get_periph_rate(peripheral);
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/* exynos4: return ARM clock frequency */
|
|
|
static unsigned long exynos4_get_arm_clk(void)
|
|
|
{
|