intel: agilex: Fix reliance on hard coded clock information
authorHadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
Wed, 14 Aug 2019 05:49:00 +0000 (13:49 +0800)
committerHadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
Wed, 14 Aug 2019 11:06:35 +0000 (19:06 +0800)
Extract clock information for UART, MMC & Watchdog from the clock manager

Signed-off-by: Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
Change-Id: I42d3d4ceeaf45788d457472f6ddcd3fe099f0133

plat/intel/soc/agilex/bl2_plat_setup.c
plat/intel/soc/agilex/include/agilex_clock_manager.h
plat/intel/soc/agilex/include/agilex_private.h
plat/intel/soc/agilex/include/agilex_system_manager.h
plat/intel/soc/agilex/soc/agilex_clock_manager.c

index 385065f95e5f14a6a5de46ba99dedd7f5c9f0e39..e9ab92850e8070aba1ddb89786d71e1fd06d53a8 100644 (file)
@@ -69,9 +69,9 @@ void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
        deassert_peripheral_reset();
        config_hps_hs_before_warm_reset();
 
-       watchdog_init(get_wdt_clk(&reverse_handoff_ptr));
+       watchdog_init(get_wdt_clk());
 
-       console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE,
+       console_16550_register(PLAT_UART0_BASE, get_uart_clk(), PLAT_BAUDRATE,
                &console);
 
        socfpga_delay_timer_init();
@@ -105,7 +105,7 @@ void bl2_el3_plat_arch_setup(void)
 
        enable_mmu_el3(0);
 
-       dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000);
+       dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000, get_mmc_clk());
 
        info.mmc_dev_type = MMC_IS_SD;
        info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
index c1a7546c7e592e3db888b1b20ed5c9304cbcdcfc..73e6c4e19a4bc64c53c830237bf470df890f1f82 100644 (file)
 #define CLKMGR_STAT_PERPLLLOCKED(x)            (((x) & 0x00010000) >> 16)
 #define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK    0x00000004
 #define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK     0x00000008
+#define CLKMGR_INTOSC_HZ                       460000000
 
 /* Main PLL Macros */
 #define CLKMGR_MAINPLL_EN_RESET                        0x000000ff
-#define CLKMGR_MAINPLL_PLLM_MDIV(x)            ((x) & 0x000003ff)
-#define CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK      0x00000001
-#define CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK     0x00000002
-
-#define CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(x)    (((x) & 0x00003f00) >> 8)
-#define CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(x)   (((x) & 0x00000f00) >> 8)
-#define CLKMGR_MAINPLL_PLLGLOB_DREFCLKDIV(x)   (((x) & 0x00003000) >> 12)
-
-#define CLKMGR_MAINPLL_PLLGLOB_PSRC(x)         (((x) & 0x00030000) >> 16)
-#define CLKMGR_MAINPLL_PLLGLOB_PSRC_EOSC1      0x0
-#define CLKMGR_MAINPLL_PLLGLOB_PSRC_INTOSC     0x1
-#define CLKMGR_MAINPLL_PLLGLOB_PSRC_F2S                0x2
-#define CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(x)   (((x) << 0) & 0x000003ff)
-#define CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(x)   (((x) << 16) & 0x00ff0000)
 
 /* Peripheral PLL Macros */
 #define CLKMGR_PERPLL_EN_RESET                 0x00000fff
-#define CLKMGR_PERPLL_PLLM_MDIV(x)             ((x) & 0x000003ff)
 #define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff)
-#define CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK       0x00000001
-
-#define CLKMGR_PERPLL_PLLGLOB_REFCLKDIV(x)     (((x) & 0x00003f00) >> 8)
-#define CLKMGR_PERPLL_PLLGLOB_AREFCLKDIV(x)    (((x) & 0x00000f00) >> 8)
-#define CLKMGR_PERPLL_PLLGLOB_DREFCLKDIV(x)    (((x) & 0x00003000) >> 12)
-
-#define CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK      0x00000002
-#define CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(x)    (((x) << 0) & 0x000003ff)
-#define CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(x)    (((x) << 16) & 0x00ff0000)
 
 /* Altera Macros */
 #define CLKMGR_ALTERA_EXTCNTRST_RESET          0xff
 
+/* Shared Macros */
+#define CLKMGR_PSRC(x)                         (((x) & 0x00030000) >> 16)
+#define CLKMGR_PSRC_MAIN                       0
+#define CLKMGR_PSRC_PER                                1
+
+#define CLKMGR_PLLGLOB_PSRC_EOSC1              0x0
+#define CLKMGR_PLLGLOB_PSRC_INTOSC             0x1
+#define CLKMGR_PLLGLOB_PSRC_F2S                        0x2
+
+#define CLKMGR_PLLM_MDIV(x)                    ((x) & 0x000003ff)
+#define CLKMGR_PLLGLOB_PD_SET_MSK              0x00000001
+#define CLKMGR_PLLGLOB_RST_SET_MSK             0x00000002
+
+#define CLKMGR_PLLGLOB_REFCLKDIV(x)            (((x) & 0x00003f00) >> 8)
+#define CLKMGR_PLLGLOB_AREFCLKDIV(x)           (((x) & 0x00000f00) >> 8)
+#define CLKMGR_PLLGLOB_DREFCLKDIV(x)           (((x) & 0x00003000) >> 12)
+
+#define CLKMGR_VCOCALIB_HSCNT_SET(x)           (((x) << 0) & 0x000003ff)
+#define CLKMGR_VCOCALIB_MSCNT_SET(x)           (((x) << 16) & 0x00ff0000)
+
 
 typedef struct {
        uint32_t  clk_freq_of_eosc1;
@@ -123,6 +120,8 @@ typedef struct {
 } CLOCK_SOURCE_CONFIG;
 
 void config_clkmgr_handoff(handoff *hoff_ptr);
-int get_wdt_clk(handoff *hoff_ptr);
+uint32_t get_wdt_clk(void);
+uint32_t get_uart_clk(void);
+uint32_t get_mmc_clk(void);
 
 #endif
index 5ccbc8c3a7cfdb20ecead9b4a9870990e1413e41..fc0e9fddffab8c714c28e09fba49f126a5320189 100644 (file)
 #define AGX_MMC_REG_BASE       0xff808000
 
 #define EMMC_DESC_SIZE         (1<<20)
-#define EMMC_INIT_PARAMS(base)                 \
+#define EMMC_INIT_PARAMS(base, clk)            \
        {       .bus_width = MMC_BUS_WIDTH_4,   \
-               .clk_rate = 50000000,           \
+               .clk_rate = (clk),              \
                .desc_base = (base),            \
                .desc_size = EMMC_DESC_SIZE,    \
                .flags = 0,                     \
-               .reg_base = AGX_MMC_REG_BASE,   \
-               \
+               .reg_base = AGX_MMC_REG_BASE    \
        }
 
 typedef enum {
@@ -26,7 +25,7 @@ typedef enum {
        BOOT_SOURCE_SDMMC,
        BOOT_SOURCE_NAND,
        BOOT_SOURCE_RSVD,
-       BOOT_SOURCE_QSPI,
+       BOOT_SOURCE_QSPI
 } boot_source_type;
 
 void enable_nonsecure_access(void);
index 6ec208426e5e5c4330691b6139968a53024ccd7b..381c2d3551bafc3baf71fe131e0656960d49dfe3 100644 (file)
 #define AGX_CCU_NOC_CPU0_RAMSPACE0_0           0xf7004688
 #define AGX_CCU_NOC_IOM_RAMSPACE0_0            0xf7018628
 
+#define AGX_SYSMGR_CORE(x)                      (0xffd12000 + (x))
+#define SYSMGR_BOOT_SCRATCH_COLD_0             0x200
+#define SYSMGR_BOOT_SCRATCH_COLD_1             0x204
+#define SYSMGR_BOOT_SCRATCH_COLD_2             0x208
+
 #define DISABLE_BRIDGE_FIREWALL                        0x0ffe0101
 #define DISABLE_L4_FIREWALL    (BIT(0) | BIT(16) | BIT(24))
 
index 6e7b43e0958cfe77b6ac343f368980f7149d3097..218676a98fd6ab567bfa2db9f0fe7f8f628d4898 100644 (file)
 
 #include "agilex_clock_manager.h"
 #include "agilex_handoff.h"
+#include "agilex_system_manager.h"
 
-static const CLOCK_SOURCE_CONFIG  clk_source = {
-       /* clk_freq_of_eosc1 */
-       (uint32_t) 25000000,
-       /* clk_freq_of_f2h_free */
-       (uint32_t) 400000000,
-       /* clk_freq_of_cb_intosc_ls */
-       (uint32_t) 50000000,
-};
 
 uint32_t wait_pll_lock(void)
 {
@@ -114,18 +107,18 @@ void config_clkmgr_handoff(handoff *hoff_ptr)
 
        /* Put both PLL in reset and power down */
        mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
-                       CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK |
-                       CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK);
+                       CLKMGR_PLLGLOB_PD_SET_MSK |
+                       CLKMGR_PLLGLOB_RST_SET_MSK);
        mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
-                       CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK |
-                       CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK);
+                       CLKMGR_PLLGLOB_PD_SET_MSK |
+                       CLKMGR_PLLGLOB_RST_SET_MSK);
 
        /* Setup main PLL dividers */
-       mdiv = CLKMGR_MAINPLL_PLLM_MDIV(hoff_ptr->main_pll_pllm);
+       mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm);
 
-       arefclk_div = CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(
+       arefclk_div = CLKMGR_PLLGLOB_AREFCLKDIV(
                        hoff_ptr->main_pll_pllglob);
-       drefclk_div = CLKMGR_MAINPLL_PLLGLOB_DREFCLKDIV(
+       drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
                        hoff_ptr->main_pll_pllglob);
 
        mscnt = 100 / (mdiv / BIT(drefclk_div));
@@ -134,8 +127,8 @@ void config_clkmgr_handoff(handoff *hoff_ptr)
        hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
 
        mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB,
-                       CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) |
-                       CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt));
+                       CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
+                       CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
 
        mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
                        hoff_ptr->main_pll_nocdiv);
@@ -159,11 +152,11 @@ void config_clkmgr_handoff(handoff *hoff_ptr)
                        hoff_ptr->main_pll_nocclk);
 
        /* Setup peripheral PLL dividers */
-       mdiv = CLKMGR_PERPLL_PLLM_MDIV(hoff_ptr->per_pll_pllm);
+       mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm);
 
-       arefclk_div = CLKMGR_PERPLL_PLLGLOB_AREFCLKDIV(
+       arefclk_div = CLKMGR_PLLGLOB_AREFCLKDIV(
                        hoff_ptr->per_pll_pllglob);
-       drefclk_div = CLKMGR_PERPLL_PLLGLOB_DREFCLKDIV(
+       drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
                        hoff_ptr->per_pll_pllglob);
 
        mscnt = 100 / (mdiv / BIT(drefclk_div));
@@ -172,8 +165,8 @@ void config_clkmgr_handoff(handoff *hoff_ptr)
        hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
 
        mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB,
-                       CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) |
-                       CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt));
+                       CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
+                       CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
 
        mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
                        hoff_ptr->per_pll_emacctl);
@@ -197,11 +190,11 @@ void config_clkmgr_handoff(handoff *hoff_ptr)
 
        /* Take both PLL out of reset and power up */
        mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
-                       CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK |
-                       CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK);
+                       CLKMGR_PLLGLOB_PD_SET_MSK |
+                       CLKMGR_PLLGLOB_RST_SET_MSK);
        mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
-                       CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK |
-                       CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK);
+                       CLKMGR_PLLGLOB_PD_SET_MSK |
+                       CLKMGR_PLLGLOB_RST_SET_MSK);
 
        wait_pll_lock();
 
@@ -256,24 +249,31 @@ void config_clkmgr_handoff(handoff *hoff_ptr)
                        CLKMGR_MAINPLL_EN_RESET);
        mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
                        CLKMGR_PERPLL_EN_RESET);
+
+       /* Pass clock source frequency into scratch register */
+       mmio_write_32(AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_1),
+               hoff_ptr->hps_osc_clk_h);
+       mmio_write_32(AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_2),
+               hoff_ptr->fpga_clk_hz);
 }
 
-int get_wdt_clk(handoff *hoff_ptr)
+/* Extract reference clock from platform clock source */
+uint32_t get_ref_clk(uint32_t pllglob)
 {
-       int main_noc_base_clk, l3_main_free_clk, l4_sys_free_clk;
-       int data32, mdiv, arefclkdiv, ref_clk;
-
-       data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB);
+       uint32_t arefclkdiv, ref_clk;
+       uint32_t scr_reg;
 
-       switch (CLKMGR_MAINPLL_PLLGLOB_PSRC(data32)) {
-       case CLKMGR_MAINPLL_PLLGLOB_PSRC_EOSC1:
-               ref_clk = clk_source.clk_freq_of_eosc1;
+       switch (CLKMGR_PSRC(pllglob)) {
+       case CLKMGR_PLLGLOB_PSRC_EOSC1:
+               scr_reg = AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_1);
+               ref_clk = mmio_read_32(scr_reg);
                break;
-       case CLKMGR_MAINPLL_PLLGLOB_PSRC_INTOSC:
-               ref_clk = clk_source.clk_freq_of_cb_intosc_ls;
+       case CLKMGR_PLLGLOB_PSRC_INTOSC:
+               ref_clk = CLKMGR_INTOSC_HZ;
                break;
-       case CLKMGR_MAINPLL_PLLGLOB_PSRC_F2S:
-               ref_clk = clk_source.clk_freq_of_f2h_free;
+       case CLKMGR_PLLGLOB_PSRC_F2S:
+               scr_reg = AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_2);
+               ref_clk = mmio_read_32(scr_reg);
                break;
        default:
                ref_clk = 0;
@@ -281,13 +281,91 @@ int get_wdt_clk(handoff *hoff_ptr)
                break;
        }
 
-       arefclkdiv = CLKMGR_MAINPLL_PLLGLOB_AREFCLKDIV(data32);
-       mdiv = CLKMGR_MAINPLL_PLLM_MDIV(hoff_ptr->main_pll_pllm);
+       arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
+       ref_clk /= arefclkdiv;
+
+       return ref_clk;
+}
+
+/* Calculate clock frequency based on parameter */
+uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
+{
+       uint32_t clk_psrc, mdiv, ref_clk;
+       uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
+
+       clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
+
+       switch (CLKMGR_PSRC(clk_psrc)) {
+       case CLKMGR_PSRC_MAIN:
+               pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
+               pllc_reg = CLKMGR_MAINPLL + main_pllc;
+               pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
+               break;
+       case CLKMGR_PSRC_PER:
+               pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM;
+               pllc_reg = CLKMGR_PERPLL + per_pllc;
+               pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB;
+               break;
+       default:
+               return 0;
+       }
+
+       ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
+       mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
+       ref_clk *= mdiv;
+
+       pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
+
+       return ref_clk / pllc_div;
+}
+
+/* Return L3 interconnect clock */
+uint32_t get_l3_clk(void)
+{
+       uint32_t l3_clk;
+
+       l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
+                               CLKMGR_PERPLL_PLLC1);
+       return l3_clk;
+}
+
+/* Calculate clock frequency to be used for watchdog timer */
+uint32_t get_wdt_clk(void)
+{
+       uint32_t l3_clk, l4_sys_clk;
+
+       l3_clk = get_l3_clk();
+       l4_sys_clk = l3_clk / 4;
+
+       return l4_sys_clk;
+}
+
+/* Calculate clock frequency to be used for UART driver */
+uint32_t get_uart_clk(void)
+{
+       uint32_t data32, l3_clk, l4_sp_clk;
+
+       l3_clk = get_l3_clk();
+
+       data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
+       data32 = (data32 >> 16) & 0x3;
+
+       l4_sp_clk = l3_clk >> data32;
+
+       return l4_sp_clk;
+}
+
+/* Calculate clock frequency to be used for SDMMC driver */
+uint32_t get_mmc_clk(void)
+{
+       uint32_t data32, mmc_clk;
+
+       mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR,
+               CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
 
-       ref_clk = (ref_clk / arefclkdiv) * mdiv;
-       main_noc_base_clk = ref_clk / (hoff_ptr->main_pll_pllc1 & 0x7ff);
-       l3_main_free_clk = main_noc_base_clk / (hoff_ptr->main_pll_nocclk + 1);
-       l4_sys_free_clk = l3_main_free_clk / 4;
+       data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
+       data32 = (data32 & 0x7ff) + 1;
+       mmc_clk = (mmc_clk / data32) / 4;
 
-       return l4_sys_free_clk;
+       return mmc_clk;
 }