]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/arm926ejs/mxs/clock.c
mxs: clock: add XBUS (APBX) clock to list of supported clocks
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / mxs / clock.c
index bfea6abeb0714e38dc02351bb32fd6ec7031fef2..102ef7b1924dc1e76bbec0eb39e2e43a50f31972 100644 (file)
 #define        PLL_FREQ_MHZ    (PLL_FREQ_KHZ / 1000)
 #define        XTAL_FREQ_MHZ   (XTAL_FREQ_KHZ / 1000)
 
+static struct mxs_clkctrl_regs *clkctrl_regs = (void *)MXS_CLKCTRL_BASE;
+
 static uint32_t mx28_get_pclk(void)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
-
        uint32_t clkctrl, clkseq, div;
        uint8_t clkfrac, frac;
 
@@ -75,9 +74,6 @@ static uint32_t mx28_get_pclk(void)
 
 static uint32_t mx28_get_hclk(void)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
-
        uint32_t div;
        uint32_t clkctrl;
 
@@ -93,9 +89,6 @@ static uint32_t mx28_get_hclk(void)
 
 static uint32_t mx28_get_emiclk(void)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
-
        uint32_t clkctrl, clkseq, div;
        uint8_t clkfrac, frac;
 
@@ -118,9 +111,6 @@ static uint32_t mx28_get_emiclk(void)
 
 static uint32_t mx28_get_gpmiclk(void)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
-
        uint32_t clkctrl, clkseq, div;
        uint8_t clkfrac, frac;
 
@@ -145,8 +135,6 @@ static uint32_t mx28_get_gpmiclk(void)
  */
 void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
        uint32_t div;
        int io_reg;
 
@@ -178,14 +166,14 @@ void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
  */
 static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
        uint8_t ret;
        int io_reg;
 
-       if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
+       if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) {
+               printf("%s: IO clock selector %u out of range %u..%u\n",
+                       __func__, io, MXC_IOCLK0, MXC_IOCLK1);
                return 0;
-
+       }
        io_reg = CLKCTRL_FRAC0_IO0 - io;        /* Register order is reversed */
 
        ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) &
@@ -199,8 +187,6 @@ static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
  */
 void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
        uint32_t clk, clkreg;
 
        if (ssp > MXC_SSPCLK3)
@@ -243,9 +229,7 @@ void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
  */
 static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
-       uint32_t clkreg;
+       uint32_t *clkreg;
        uint32_t clk, tmp;
 
        if (ssp > MXC_SSPCLK3)
@@ -255,16 +239,14 @@ static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
        if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
                return XTAL_FREQ_KHZ;
 
-       clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
-                       (ssp * sizeof(struct mxs_register_32));
+       clkreg = &clkctrl_regs->hw_clkctrl_ssp0 +
+                       ssp * sizeof(struct mxs_register_32);
 
        tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
-
        if (tmp == 0)
                return 0;
 
        clk = mx28_get_ioclk(ssp >> 1);
-
        return clk / tmp;
 }
 
@@ -309,6 +291,23 @@ void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
                bus, tgtclk, freq);
 }
 
+static uint32_t mx28_get_xbus_clk(void)
+{
+       struct mxs_clkctrl_regs *clkctrl_regs =
+               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+       uint32_t div;
+       uint32_t clkctrl;
+       uint32_t refclk = mx28_get_pclk();
+
+       clkctrl = readl(&clkctrl_regs->hw_clkctrl_xbus);
+       div = clkctrl & CLKCTRL_XBUS_DIV_MASK;
+
+       if (clkctrl & CLKCTRL_XBUS_DIV_FRAC_EN)
+               return 0;
+
+       return refclk / div;
+}
+
 uint32_t mxc_get_clock(enum mxc_clock clk)
 {
        switch (clk) {
@@ -333,6 +332,12 @@ uint32_t mxc_get_clock(enum mxc_clock clk)
                return mx28_get_sspclk(MXC_SSPCLK2);
        case MXC_SSP3_CLK:
                return mx28_get_sspclk(MXC_SSPCLK3);
+       case MXC_XTAL_CLK:
+               return XTAL_FREQ_KHZ * 1000;
+       case MXC_XBUS_CLK:
+               return mx28_get_xbus_clk() * 1000000;
+       default:
+               printf("Invalid clock selector %u\n", clk);
        }
 
        return 0;