/* return the current oscillator clock frequency */
 enum clock_osc_freq clock_get_osc_freq(void);
 
+/* return the clk_m frequency */
+unsigned int clk_m_get_rate(unsigned int parent_rate);
+
 /**
  * Start PLL using the provided configuration parameters.
  *
 
 void tegra30_set_up_pllp(void);
 
-/* Number of PLL-based clocks (i.e. not OSC or 32KHz) */
-#define CLOCK_ID_PLL_COUNT     (CLOCK_ID_COUNT - 2)
+/* Number of PLL-based clocks (i.e. not OSC, MCLK or 32KHz) */
+#define CLOCK_ID_PLL_COUNT     (CLOCK_ID_COUNT - 3)
 
 struct clk_pll_info {
        u32     m_shift:5;      /* DIVM_SHIFT */
 
        /* These are the base clocks (inputs to the Tegra SOC) */
        CLOCK_ID_32KHZ,
        CLOCK_ID_OSC,
+       CLOCK_ID_CLK_M,
 
        CLOCK_ID_COUNT, /* number of PLLs */
        CLOCK_ID_DISPLAY2,      /* placeholder */
 
        /* These are the base clocks (inputs to the Tegra SoC) */
        CLOCK_ID_32KHZ,
        CLOCK_ID_OSC,
+       CLOCK_ID_CLK_M,
 
        CLOCK_ID_COUNT, /* number of PLLs */
 
 
        /* These are the base clocks (inputs to the Tegra SOC) */
        CLOCK_ID_32KHZ,
        CLOCK_ID_OSC,
+       CLOCK_ID_CLK_M,
 
        CLOCK_ID_COUNT, /* number of clocks */
        CLOCK_ID_NONE = -1,
 
        /* These are the base clocks (inputs to the Tegra SoC) */
        CLOCK_ID_32KHZ,
        CLOCK_ID_OSC,
+       CLOCK_ID_CLK_M,
 
        CLOCK_ID_COUNT, /* number of PLLs */
 
 
        /* These are the base clocks (inputs to the Tegra SOC) */
        CLOCK_ID_32KHZ,
        CLOCK_ID_OSC,
+       CLOCK_ID_CLK_M,
 
        CLOCK_ID_COUNT, /* number of PLLs */
        CLOCK_ID_DISPLAY2,      /* Tegra3, placeholder */
 
                writel(mask, &clkrst->crc_cpu_cmplx_clr);
 }
 
+unsigned int __weak clk_m_get_rate(unsigned int parent_rate)
+{
+       return parent_rate;
+}
+
 unsigned clock_get_rate(enum clock_id clkid)
 {
        struct clk_pll *pll;
        if (clkid == CLOCK_ID_OSC)
                return parent_rate;
 
+       if (clkid == CLOCK_ID_CLK_M)
+               return clk_m_get_rate(parent_rate);
+
        pll = get_pll(clkid);
        if (!pll)
                return 0;
        pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU);
        pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
        pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
+       pll_rate[CLOCK_ID_CLK_M] = clock_get_rate(CLOCK_ID_CLK_M);
 
        debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
+       debug("CLKM = %d\n", pll_rate[CLOCK_ID_CLK_M]);
        debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]);
        debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
        debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
 
        udelay(2);
 }
 
+unsigned int clk_m_get_rate(unsigned parent_rate)
+{
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 value, div;
+
+       value = readl(&clkrst->crc_spare_reg0);
+       div = ((value >> 2) & 0x3) + 1;
+
+       return parent_rate / div;
+}
+
 void arch_timer_init(void)
 {
        struct sysctr_ctlr *sysctr = (struct sysctr_ctlr *)NV_PA_TSC_BASE;