Home | History | Annotate | Download | only in bcm235xx
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright 2014 Broadcom Corporation.
      4  */
      5 
      6 #include <common.h>
      7 #include <asm/io.h>
      8 #include <linux/errno.h>
      9 #include <asm/arch/sysmap.h>
     10 #include <asm/kona-common/clk.h>
     11 #include "clk-core.h"
     12 
     13 #define WR_ACCESS_ADDR			ESUB_CLK_BASE_ADDR
     14 #define WR_ACCESS_PASSWORD				0xA5A500
     15 
     16 #define PLLE_POST_RESETB_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000C00)
     17 
     18 #define PLLE_RESETB_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000C58)
     19 #define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK		0x00010000
     20 #define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK	0x00000001
     21 
     22 #define PLL_LOCK_ADDR			(ESUB_CLK_BASE_ADDR + 0x00000C38)
     23 #define PLL_LOCK_PLL_LOCK_PLLE_MASK			0x00000001
     24 
     25 #define ESW_SYS_DIV_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000A04)
     26 #define ESW_SYS_DIV_PLL_SELECT_MASK			0x00000300
     27 #define ESW_SYS_DIV_DIV_MASK				0x0000001C
     28 #define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT		0x00000100
     29 #define ESW_SYS_DIV_DIV_SELECT				0x4
     30 #define ESW_SYS_DIV_TRIGGER_MASK			0x00000001
     31 
     32 #define ESUB_AXI_DIV_DEBUG_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000E04)
     33 #define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK		0x0000001C
     34 #define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK	0x00000040
     35 #define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT	0x0
     36 #define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK			0x00000001
     37 
     38 #define PLL_MAX_RETRY	100
     39 
     40 /* Enable appropriate clocks for Ethernet */
     41 int clk_eth_enable(void)
     42 {
     43 	int rc = -1;
     44 	int retry_count = 0;
     45 	rc = clk_get_and_enable("esub_ccu_clk");
     46 
     47 	/* Enable Access to CCU registers */
     48 	writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR);
     49 
     50 	writel(readl(PLLE_POST_RESETB_ADDR) &
     51 	       ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
     52 	       PLLE_POST_RESETB_ADDR);
     53 
     54 	/* Take PLL out of reset and put into normal mode */
     55 	writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK,
     56 	       PLLE_RESETB_ADDR);
     57 
     58 	/* Wait for PLL lock */
     59 	rc = -1;
     60 	while (retry_count < PLL_MAX_RETRY) {
     61 		udelay(100);
     62 		if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) {
     63 			rc = 0;
     64 			break;
     65 		}
     66 		retry_count++;
     67 	}
     68 
     69 	if (rc == -1) {
     70 		printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n",
     71 		       __func__);
     72 		return -1;
     73 	}
     74 
     75 	writel(readl(PLLE_POST_RESETB_ADDR) |
     76 	       PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
     77 	       PLLE_POST_RESETB_ADDR);
     78 
     79 	/* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */
     80 	writel((readl(ESW_SYS_DIV_ADDR) &
     81 		~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) |
     82 	       ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT,
     83 	       ESW_SYS_DIV_ADDR);
     84 
     85 	writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK,
     86 	       ESW_SYS_DIV_ADDR);
     87 
     88 	/* Wait for trigger complete */
     89 	rc = -1;
     90 	retry_count = 0;
     91 	while (retry_count < PLL_MAX_RETRY) {
     92 		udelay(100);
     93 		if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) {
     94 			rc = 0;
     95 			break;
     96 		}
     97 		retry_count++;
     98 	}
     99 
    100 	if (rc == -1) {
    101 		printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n",
    102 		       __func__);
    103 		return -1;
    104 	}
    105 
    106 	/* switch Esub AXI clock to 208MHz */
    107 	writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) &
    108 		~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK |
    109 		  ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK |
    110 		  ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) |
    111 	       ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT |
    112 	       ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK,
    113 	       ESUB_AXI_DIV_DEBUG_ADDR);
    114 
    115 	writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) |
    116 	       ESUB_AXI_DIV_DEBUG_TRIGGER_MASK,
    117 	       ESUB_AXI_DIV_DEBUG_ADDR);
    118 
    119 	/* Wait for trigger complete */
    120 	rc = -1;
    121 	retry_count = 0;
    122 	while (retry_count < PLL_MAX_RETRY) {
    123 		udelay(100);
    124 		if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) &
    125 		      ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) {
    126 			rc = 0;
    127 			break;
    128 		}
    129 		retry_count++;
    130 	}
    131 
    132 	if (rc == -1) {
    133 		printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n",
    134 		       __func__);
    135 		return -1;
    136 	}
    137 
    138 	/* Disable Access to CCU registers */
    139 	writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR);
    140 
    141 	return rc;
    142 }
    143