From 0679e63be76593063c1515e2e9b4309247a6fc1b Mon Sep 17 00:00:00 2001 From: Selvam Sathappan Periakaruppan Date: Sun, 1 Aug 2021 15:59:40 +0530 Subject: [PATCH] ipq9574: Clean up eth initialization This patch does the following: 1) Adds separate function for each init 2) Calls the above individual init functions from eth_init function which is then called in board_eth_init which is called from the core network driver stack during boot up. 3) Adds CMN_BLK init which is needed for NSS Change-Id: I0e5c07bf42f3473b80f524470217879f81c22b1b Signed-off-by: Selvam Sathappan Periakaruppan --- board/qca/arm/ipq9574/ipq9574.c | 251 +++++++++++++++++++++++++------- board/qca/arm/ipq9574/ipq9574.h | 36 +++++ 2 files changed, 235 insertions(+), 52 deletions(-) diff --git a/board/qca/arm/ipq9574/ipq9574.c b/board/qca/arm/ipq9574/ipq9574.c index baf2483e2e..9776b97a9b 100644 --- a/board/qca/arm/ipq9574/ipq9574.c +++ b/board/qca/arm/ipq9574/ipq9574.c @@ -744,97 +744,145 @@ void set_function_select_as_mdc_mdio(void) } } -void eth_clock_enable(void) +void nssnoc_init(void) { - int reg_val, reg_val1, mode, i; - int node; - - /* Clock init */ /* Enable required NSSNOC clocks */ writel(readl(GCC_MEM_NOC_NSSNOC_CLK) | GCC_CBCR_CLK_ENABLE, GCC_MEM_NOC_NSSNOC_CLK); + writel(readl(GCC_NSSCFG_CLK) | GCC_CBCR_CLK_ENABLE, GCC_NSSCFG_CLK); + writel(readl(GCC_NSSNOC_ATB_CLK) | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_ATB_CLK); + writel(readl(GCC_NSSNOC_MEM_NOC_1_CLK) | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_MEM_NOC_1_CLK); + writel(readl(GCC_NSSNOC_MEMNOC_CLK) | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_MEMNOC_CLK); + writel(readl(GCC_NSSNOC_QOSGEN_REF_CLK) | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_QOSGEN_REF_CLK); + writel(readl(GCC_NSSNOC_TIMEOUT_REF_CLK) | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_TIMEOUT_REF_CLK); +} + +void frequency_init(void) +{ + unsigned int nss_cc_cfg_addr; + unsigned int gcc_uniphy_sys_addr; + unsigned int gcc_pcnoc_addr; + unsigned int gcc_sysnoc_addr; + unsigned int reg_val; - /* Frequency init */ /* GCC NSS frequency 100M */ - reg_val = readl(0x39B28104 + 4); + nss_cc_cfg_addr = 0x39B28104; + reg_val = readl(nss_cc_cfg_addr + 4); reg_val &= ~0x7ff; - writel(reg_val | 0x20f, 0x39B28104 + 4); - reg_val = readl(0x39B28104); - writel(reg_val | 0x1, 0x39B28104); + writel(reg_val | 0x20f, nss_cc_cfg_addr + 4); + + reg_val = readl(nss_cc_cfg_addr); + writel(reg_val | 0x1, nss_cc_cfg_addr); /* GCC CC PPE frequency 353M */ reg_val = readl(NSS_CC_PPE_FREQUENCY_RCGR + 4); reg_val &= ~0x7ff; writel(reg_val | 0x101, NSS_CC_PPE_FREQUENCY_RCGR + 4); + reg_val = readl(NSS_CC_PPE_FREQUENCY_RCGR); writel(reg_val | 0x1, NSS_CC_PPE_FREQUENCY_RCGR); /* Uniphy SYS 24M */ - reg_val = readl(0x1817090 + 4); + gcc_uniphy_sys_addr = 0x1817090; + reg_val = readl(gcc_uniphy_sys_addr + 4); reg_val &= ~0x7ff; - writel(reg_val | 0x1, 0x1817090 + 4); + writel(reg_val | 0x1, gcc_uniphy_sys_addr + 4); /* Update Config */ - reg_val = readl(0x1817090); - writel(reg_val | 0x1, 0x1817090); + reg_val = readl(gcc_uniphy_sys_addr); + writel(reg_val | 0x1, gcc_uniphy_sys_addr); /* PCNOC frequency for Uniphy AHB 100M */ - reg_val = readl(0x1831004 + 4); + gcc_pcnoc_addr = 0x1831004; + reg_val = readl(gcc_pcnoc_addr + 4); reg_val &= ~0x7ff; - writel(reg_val | 0x10F, 0x1831004 + 4); + writel(reg_val | 0x10F, gcc_pcnoc_addr + 4); /* Update Config */ - reg_val = readl(0x1831004); - writel(reg_val | 0x1, 0x1831004); + reg_val = readl(gcc_pcnoc_addr); + writel(reg_val | 0x1, gcc_pcnoc_addr); /* SYSNOC frequency 343M */ - reg_val = readl(0x182E004 + 4); + gcc_sysnoc_addr = 0x182E004; + reg_val = readl(gcc_sysnoc_addr + 4); reg_val &= ~0x7ff; - writel(reg_val | 0x206, 0x182E004 + 4); + writel(reg_val | 0x206, gcc_sysnoc_addr + 4); /* Update Config */ - reg_val = readl(0x182E004); - writel(reg_val | 0x1, 0x182E004); + reg_val = readl(gcc_sysnoc_addr); + writel(reg_val | 0x1, gcc_sysnoc_addr); +} + +void fixed_nss_csr_clock_init(void) +{ + unsigned int gcc_nss_csr_addr; + unsigned int reg_val; /* NSS CSR and NSSNOC CSR Clock init */ - reg_val = readl(0x39B281D0); - writel(reg_val | GCC_CBCR_CLK_ENABLE, 0x39B281D0); + gcc_nss_csr_addr = 0x39B281D0; + reg_val = readl(gcc_nss_csr_addr); + writel(reg_val | GCC_CBCR_CLK_ENABLE, gcc_nss_csr_addr); /* NSSNOC CSR */ - reg_val = readl(0x39B281D0 + 4); - writel(reg_val | GCC_CBCR_CLK_ENABLE, 0x39B281D0 + 4); + reg_val = readl(gcc_nss_csr_addr + 0x4); + writel(reg_val | GCC_CBCR_CLK_ENABLE, gcc_nss_csr_addr + 0x4); +} + +void fixed_sys_clock_init(void) +{ + unsigned int reg_val; /* SYS Clock init */ /* Enable AHB and SYS clk of CMN */ reg_val = readl(GCC_CMN_BLK_ADDR + GCC_CMN_BLK_AHB_CBCR_OFFSET); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_CMN_BLK_ADDR + GCC_CMN_BLK_AHB_CBCR_OFFSET); + reg_val = readl(GCC_CMN_BLK_ADDR + GCC_CMN_BLK_SYS_CBCR_OFFSET); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_CMN_BLK_ADDR + GCC_CMN_BLK_SYS_CBCR_OFFSET); +} + +void fixed_uniphy_clock_init(void) +{ + int i; + unsigned int reg_val; /* Uniphy AHB AND SYS CBCR init */ for (i = 0; i < 3; i++) { reg_val = readl(GCC_UNIPHY_SYS_ADDR + i*0x10); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_UNIPHY_SYS_ADDR + i*0x10); + reg_val = readl((GCC_UNIPHY_SYS_ADDR + 0x4) + i*0x10); writel(reg_val | GCC_CBCR_CLK_ENABLE, (GCC_UNIPHY_SYS_ADDR + 0x4) + i*0x10); } +} + +void port_mac_clock_init(void) +{ + int i; + unsigned int reg_val; /* Port Mac Clock init */ for (i = 0; i < 6; i++) { reg_val = readl(GCC_PORT_MAC_ADDR + i*0x4); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_PORT_MAC_ADDR + i*0x4); } +} + +void cfg_clock_init(void) +{ + int i; + unsigned int reg_val; /* CFG Clock init */ for (i = 0; i < 8; i++) { @@ -844,42 +892,113 @@ void eth_clock_enable(void) } reg_val = readl(NSS_CC_PPE_SWITCH_BTQ_ADDR); writel(reg_val | GCC_CBCR_CLK_ENABLE, NSS_CC_PPE_SWITCH_BTQ_ADDR); +} + +void mdio_clock_init(void) +{ + unsigned int reg_val; /* MDIO Clock init */ reg_val = readl(GCC_MDIO_AHB_CBCR_ADDR); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_MDIO_AHB_CBCR_ADDR); +} + +void noc_clock_init(void) +{ + unsigned int reg_val; /* NOC Clock init */ reg_val = readl(GCC_NSSNOC_SNOC_CBCR); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_SNOC_CBCR); + reg_val = readl(GCC_NSSNOC_SNOC_1_CBCR); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_NSSNOC_SNOC_1_CBCR); + reg_val = readl(GCC_MEM_NOC_SNOC_AXI_CBCR); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_MEM_NOC_SNOC_AXI_CBCR); + reg_val = readl(GCC_IMEM_AXI_CBCR); writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_IMEM_AXI_CBCR); +} - /* Enable mac clock */ - for (i = 0; i < 6; i++) { - reg_val = readl(NSS_CC_PORT1_RX_CBCR + i*0x8); - writel(reg_val | GCC_CBCR_CLK_ENABLE, NSS_CC_PORT1_RX_CBCR + i*0x8); - reg_val = readl(NSS_CC_PORT1_RX_CBCR + 0x4 + i*0x8); - writel(reg_val | GCC_CBCR_CLK_ENABLE, NSS_CC_PORT1_RX_CBCR + 0x4 + i*0x8); +void fixed_clock_init(void) +{ + frequency_init(); + + fixed_nss_csr_clock_init(); + + fixed_sys_clock_init(); + + fixed_uniphy_clock_init(); + + port_mac_clock_init(); + + cfg_clock_init(); + + mdio_clock_init(); + + noc_clock_init(); +} + +void uniphy_clock_enable(enum uniphy_clk_type clk_type, bool enable) +{ + unsigned int reg_val, i; + + i = clk_type; + + if (clk_type <= NSS_PORT6_TX_CLK_E) { + reg_val = readl(NSS_CC_PORT1_RX_CBCR + i*0x4); + if (enable) + reg_val |= GCC_CBCR_CLK_ENABLE; + else + reg_val &= ~GCC_CBCR_CLK_ENABLE; + writel(reg_val, (NSS_CC_PORT1_RX_CBCR + i*0x4)); + } else { + if (i >= UNIPHY1_PORT5_RX_CLK_E) { + i = i - 2; + } + reg_val = readl(NSS_CC_UNIPHY_PORT1_RX_CBCR + (i - 12)*0x4); + if (enable) + reg_val |= GCC_CBCR_CLK_ENABLE; + else + reg_val &= ~GCC_CBCR_CLK_ENABLE; + writel(reg_val, (NSS_CC_UNIPHY_PORT1_RX_CBCR + (i - 12)*0x4)); } +} - /* Enable Uniphy clock */ - for (i = 0; i < 6; i++) { - reg_val = readl(NSS_CC_UNIPHY_PORT1_RX_CBCR + i*0x8); - writel(reg_val | GCC_CBCR_CLK_ENABLE, NSS_CC_UNIPHY_PORT1_RX_CBCR + i*0x8); - reg_val = readl(NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + i*0x8); - writel(reg_val | GCC_CBCR_CLK_ENABLE, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + i*0x8); - } - writel(0x1, NSS_CC_PORT5_RX_CMD_RCGR); - writel(0x2, NSS_CC_PORT5_RX_CMD_RCGR); - writel(0x1, NSS_CC_PORT5_TX_CMD_RCGR); - writel(0x2, NSS_CC_PORT5_TX_CMD_RCGR); +void uniphy_clk_init(void) +{ + int i; + /* Uniphy clock enable */ + for (i = NSS_PORT1_RX_CLK_E; i < PORT5_RX_SRC_E; i++) + uniphy_clock_enable(i, true); +} + +void cmnblk_init(void) +{ + uint32_t gcc_pll_base, reg_val; + + gcc_pll_base = CMN_BLK_ADDR; + reg_val = readl(gcc_pll_base + 4); + reg_val = (reg_val & FREQUENCY_MASK) | INTERNAL_48MHZ_CLOCK; + writel(reg_val, gcc_pll_base + 0x4); + reg_val = readl(gcc_pll_base); + reg_val = reg_val | 0x40; + writel(reg_val, gcc_pll_base); + mdelay(1); + reg_val = reg_val & (~0x40); + writel(reg_val, gcc_pll_base); + mdelay(1); + writel(0xbf, gcc_pll_base); + mdelay(1); + writel(0xff, gcc_pll_base); + mdelay(1); +} + +void uniphy_port5_clock_source_set(void) +{ + int reg_val, reg_val1, node, mode; - /* Uniphy Port5 clock source set */ reg_val = readl(NSS_CC_PORT_SPEED_DIVIDER + 0x64); reg_val1 = readl(NSS_CC_PORT_SPEED_DIVIDER + 0x70); @@ -893,30 +1012,33 @@ void eth_clock_enable(void) printf("\nError: switch_mac_mode1 not specified in dts"); return; } - if (mode == 0xFF) { /* PORT_WRAPPER_MAX */ + if (mode == PORT_WRAPPER_MAX) { /* PORT_WRAPPER_MAX */ reg_val |= 0x200; reg_val1 |= 0x300; } else { reg_val |= 0x400; - reg_val |= 0x500; + reg_val1 |= 0x500; } writel(reg_val, NSS_CC_PORT_SPEED_DIVIDER + 0x64); writel(0x1, NSS_CC_PORT_SPEED_DIVIDER + 0x60); writel(reg_val1, NSS_CC_PORT_SPEED_DIVIDER + 0x70); writel(0x1, NSS_CC_PORT_SPEED_DIVIDER + 0x6c); +} + +void nss_ppe_reset(void) +{ + unsigned int reg_val; - /* PPE Clock init and NSS PPE Assert/De-assert */ reg_val = readl(NSS_CC_PPE_RESET_ADDR); writel(reg_val | 0x1e0000, NSS_CC_PPE_RESET_ADDR); mdelay(500); writel(reg_val & (~0x1e0000), NSS_CC_PPE_RESET_ADDR); mdelay(100); +} - /* Set function select as MDI */ - set_function_select_as_mdc_mdio(); - - /* Bring PHY out of RESET */ +void bring_phy_out_of_reset(void) +{ qca807x_phy_reset_init(); aquantia_phy_reset_init(); qca808x_phy_reset_init(); @@ -926,6 +1048,31 @@ void eth_clock_enable(void) qca808x_phy_reset_init_done(); mdelay(500); } + +void eth_clock_init(void) +{ + nssnoc_init(); + + fixed_clock_init(); + + uniphy_clk_init(); + + cmnblk_init(); + + uniphy_port5_clock_source_set(); +} + +void ipq9574_eth_initialize(void) +{ + eth_clock_init(); + + nss_ppe_reset(); + + set_function_select_as_mdc_mdio(); + + bring_phy_out_of_reset(); +} + #endif #ifdef CONFIG_IPQ9574_EDMA @@ -934,7 +1081,7 @@ int board_eth_init(bd_t *bis) int ret = 0; #ifndef CONFIG_IPQ9574_RUMI - eth_clock_enable(); + ipq9574_eth_initialize(); #endif ret = ipq9574_edma_init(NULL); diff --git a/board/qca/arm/ipq9574/ipq9574.h b/board/qca/arm/ipq9574/ipq9574.h index 260f07cbe0..41b9758c03 100644 --- a/board/qca/arm/ipq9574/ipq9574.h +++ b/board/qca/arm/ipq9574/ipq9574.h @@ -18,6 +18,11 @@ #include #include +#define CMN_BLK_ADDR 0x0009B780 +#define FREQUENCY_MASK 0xfffffdf0 +#define INTERNAL_48MHZ_CLOCK 0x7 +#define PORT_WRAPPER_MAX 0xFF + /* * EDMA HW ASSERT and DEASSERT values */ @@ -213,6 +218,37 @@ #define USB3_PHY_SW_RESET 0x800 #define NOC_HANDSHAKE_FSM_EN (1 << 15) +enum uniphy_clk_type { + NSS_PORT1_RX_CLK_E = 0, + NSS_PORT1_TX_CLK_E, + NSS_PORT2_RX_CLK_E, + NSS_PORT2_TX_CLK_E, + NSS_PORT3_RX_CLK_E, + NSS_PORT3_TX_CLK_E, + NSS_PORT4_RX_CLK_E, + NSS_PORT4_TX_CLK_E, + NSS_PORT5_RX_CLK_E, + NSS_PORT5_TX_CLK_E, + NSS_PORT6_RX_CLK_E, + NSS_PORT6_TX_CLK_E, + UNIPHY0_PORT1_RX_CLK_E, + UNIPHY0_PORT1_TX_CLK_E, + UNIPHY0_PORT2_RX_CLK_E, + UNIPHY0_PORT2_TX_CLK_E, + UNIPHY0_PORT3_RX_CLK_E, + UNIPHY0_PORT3_TX_CLK_E, + UNIPHY0_PORT4_RX_CLK_E, + UNIPHY0_PORT4_TX_CLK_E, + UNIPHY0_PORT5_RX_CLK_E, + UNIPHY0_PORT5_TX_CLK_E, + UNIPHY1_PORT5_RX_CLK_E, + UNIPHY1_PORT5_TX_CLK_E, + UNIPHY2_PORT6_RX_CLK_E, + UNIPHY2_PORT6_TX_CLK_E, + PORT5_RX_SRC_E, + PORT5_TX_SRC_E, + UNIPHYT_CLK_MAX, +}; #ifdef CONFIG_PCI_IPQ void board_pci_init(int id);