Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / arm / mach-tegra / tegra114 / clock.c
index 5e805a7baf032b5749df17601c377af653f42d8a..167589d1bb762345387f4b859bbd04a714df6f01 100644 (file)
@@ -1,13 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2010-2015
  * NVIDIA Corporation <www.nvidia.com>
- *
- * SPDX-License-Identifier:     GPL-2.0+
  */
 
 /* Tegra114 Clock control functions */
 
 #include <common.h>
+#include <init.h>
+#include <log.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sysctr.h>
@@ -16,6 +17,7 @@
 #include <asm/arch-tegra/timer.h>
 #include <div64.h>
 #include <fdtdec.h>
+#include <linux/delay.h>
 
 /*
  * Clock types that we can use as a source. The Tegra114 has muxes for the
@@ -496,6 +498,51 @@ u32 *get_periph_source_reg(enum periph_id periph_id)
                return &clkrst->crc_clk_src[internal_id];
 }
 
+int get_periph_clock_info(enum periph_id periph_id, int *mux_bits,
+                         int *divider_bits, int *type)
+{
+       enum periphc_internal_id internal_id;
+
+       if (!clock_periph_id_isvalid(periph_id))
+               return -1;
+
+       internal_id = periph_id_to_internal_id[periph_id];
+       if (!periphc_internal_id_isvalid(internal_id))
+               return -1;
+
+       *type = clock_periph_type[internal_id];
+       if (!clock_type_id_isvalid(*type))
+               return -1;
+
+       *mux_bits = clock_source[*type][CLOCK_MAX_MUX];
+
+       if (*type == CLOCK_TYPE_PCMT16)
+               *divider_bits = 16;
+       else
+               *divider_bits = 8;
+
+       return 0;
+}
+
+enum clock_id get_periph_clock_id(enum periph_id periph_id, int source)
+{
+       enum periphc_internal_id internal_id;
+       int type;
+
+       if (!clock_periph_id_isvalid(periph_id))
+               return CLOCK_ID_NONE;
+
+       internal_id = periph_id_to_internal_id[periph_id];
+       if (!periphc_internal_id_isvalid(internal_id))
+               return CLOCK_ID_NONE;
+
+       type = clock_periph_type[internal_id];
+       if (!clock_type_id_isvalid(type))
+               return CLOCK_ID_NONE;
+
+       return clock_source[type][source];
+}
+
 /**
  * Given a peripheral ID and the required source clock, this returns which
  * value should be programmed into the source mux for that peripheral.
@@ -512,23 +559,10 @@ int get_periph_clock_source(enum periph_id periph_id,
        enum clock_id parent, int *mux_bits, int *divider_bits)
 {
        enum clock_type_id type;
-       enum periphc_internal_id internal_id;
-       int mux;
-
-       assert(clock_periph_id_isvalid(periph_id));
-
-       internal_id = periph_id_to_internal_id[periph_id];
-       assert(periphc_internal_id_isvalid(internal_id));
-
-       type = clock_periph_type[internal_id];
-       assert(clock_type_id_isvalid(type));
-
-       *mux_bits = clock_source[type][CLOCK_MAX_MUX];
+       int mux, err;
 
-       if (type == CLOCK_TYPE_PCMT16)
-               *divider_bits = 16;
-       else
-               *divider_bits = 8;
+       err = get_periph_clock_info(periph_id, mux_bits, divider_bits, &type);
+       assert(!err);
 
        for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
                if (clock_source[type][mux] == parent)
@@ -629,6 +663,11 @@ void clock_early_init(void)
 
        tegra30_set_up_pllp();
 
+       /* clear IDDQ before accessing any other PLLC registers */
+       pllinfo = &tegra_pll_info_table[CLOCK_ID_CGENERAL];
+       clrbits_le32(&clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc, PLLC_IDDQ);
+       udelay(2);
+
        /*
         * PLLC output frequency set to 600Mhz
         * PLLD output frequency set to 925Mhz
@@ -679,8 +718,8 @@ void arch_timer_init(void)
        struct sysctr_ctlr *sysctr = (struct sysctr_ctlr *)NV_PA_TSC_BASE;
        u32 freq, val;
 
-       freq = clock_get_rate(CLOCK_ID_OSC);
-       debug("%s: osc freq is %dHz [0x%08X]\n", __func__, freq, freq);
+       freq = clock_get_rate(CLOCK_ID_CLK_M);
+       debug("%s: clk_m freq is %dHz [0x%08X]\n", __func__, freq, freq);
 
        /* ARM CNTFRQ */
        asm("mcr p15, 0, %0, c14, c0, 0\n" : : "r" (freq));
@@ -694,3 +733,26 @@ void arch_timer_init(void)
        writel(val, &sysctr->cntcr);
        debug("%s: TSC CNTCR = 0x%08X\n", __func__, val);
 }
+
+struct periph_clk_init periph_clk_init_table[] = {
+       { PERIPH_ID_SBC1, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SBC2, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SBC3, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SBC4, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SBC5, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SBC6, CLOCK_ID_PERIPH },
+       { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH },
+       { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL },
+       { PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH },
+       { PERIPH_ID_SDMMC4, CLOCK_ID_PERIPH },
+       { PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ },
+       { PERIPH_ID_I2C1, CLOCK_ID_PERIPH },
+       { PERIPH_ID_I2C2, CLOCK_ID_PERIPH },
+       { PERIPH_ID_I2C3, CLOCK_ID_PERIPH },
+       { PERIPH_ID_I2C4, CLOCK_ID_PERIPH },
+       { PERIPH_ID_I2C5, CLOCK_ID_PERIPH },
+       { -1, },
+};