From f5e48f3e59a5ff37f992ea7019ef7e3f856d30a7 Mon Sep 17 00:00:00 2001 From: Antony Arun T Date: Tue, 29 Jan 2019 10:22:32 +0530 Subject: [PATCH] ipq6018: Enabling Ethernet support Change-Id: If49c5b86fb08bda0ab29d7663fa0f8fca9a9f5bb Signed-off-by: Antony Arun T --- arch/arm/include/asm/arch-ipq6018/edma_regs.h | 398 ++++ board/qca/arm/ipq6018/ipq6018.c | 130 ++ drivers/net/Makefile | 3 + drivers/net/ipq6018/ipq6018_edma.c | 1881 +++++++++++++++++ drivers/net/ipq6018/ipq6018_edma.h | 327 +++ drivers/net/ipq6018/ipq6018_ppe.c | 1323 ++++++++++++ drivers/net/ipq6018/ipq6018_ppe.h | 251 +++ drivers/net/ipq6018/ipq6018_uniphy.c | 358 ++++ drivers/net/ipq6018/ipq6018_uniphy.h | 78 + include/configs/ipq6018.h | 21 + 10 files changed, 4770 insertions(+) create mode 100644 arch/arm/include/asm/arch-ipq6018/edma_regs.h create mode 100755 drivers/net/ipq6018/ipq6018_edma.c create mode 100644 drivers/net/ipq6018/ipq6018_edma.h create mode 100644 drivers/net/ipq6018/ipq6018_ppe.c create mode 100644 drivers/net/ipq6018/ipq6018_ppe.h create mode 100644 drivers/net/ipq6018/ipq6018_uniphy.c create mode 100644 drivers/net/ipq6018/ipq6018_uniphy.h diff --git a/arch/arm/include/asm/arch-ipq6018/edma_regs.h b/arch/arm/include/asm/arch-ipq6018/edma_regs.h new file mode 100644 index 0000000000..00cab172f0 --- /dev/null +++ b/arch/arm/include/asm/arch-ipq6018/edma_regs.h @@ -0,0 +1,398 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ************************************************************************** +*/ + +#ifndef __EDMA_REGS__ +#define __EDMA_REGS__ + +#define IPQ6018_EDMA_CFG_BASE 0x3ab00000 +/* + * IPQ6018 EDMA register offsets + */ +#define IPQ6018_EDMA_REG_MAS_CTRL 0x0 +#define IPQ6018_EDMA_REG_PORT_CTRL 0x4 +#define IPQ6018_EDMA_REG_VLAN_CTRL 0x8 +#define IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_0 0xc +#define IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_1 0x10 +#define IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_2 0x14 +#define IPQ6018_EDMA_REG_RXDESC2FILL_MAP_0 0x18 +#define IPQ6018_EDMA_REG_RXDESC2FILL_MAP_1 0x1c +#define IPQ6018_EDMA_REG_TXQ_CTRL 0x20 +#define IPQ6018_EDMA_REG_TXQ_CTRL_2 0x24 +#define IPQ6018_EDMA_REG_TXQ_FC_0 0x28 +#define IPQ6018_EDMA_REG_TXQ_FC_1 0x30 +#define IPQ6018_EDMA_REG_TXQ_FC_2 0x34 +#define IPQ6018_EDMA_REG_TXQ_FC_3 0x38 +#define IPQ6018_EDMA_REG_RXQ_CTRL 0x3c +#define IPQ6018_EDMA_REG_RX_TX_FULL_QID 0x40 +#define IPQ6018_EDMA_REG_RXQ_FC_THRE 0x44 +#define IPQ6018_EDMA_REG_DMAR_CTRL 0x48 +#define IPQ6018_EDMA_REG_AXIR_CTRL 0x4c +#define IPQ6018_EDMA_REG_AXIW_CTRL 0x50 +#define IPQ6018_EDMA_REG_MIN_MSS 0x54 +#define IPQ6018_EDMA_REG_LOOPBACK_CTRL 0x58 +#define IPQ6018_EDMA_REG_MISC_INT_STAT 0x5c +#define IPQ6018_EDMA_REG_MISC_INT_MASK 0x60 +#define IPQ6018_EDMA_REG_DBG_CTRL 0x64 +#define IPQ6018_EDMA_REG_DBG_DATA 0x68 +#define IPQ6018_EDMA_REG_TXDESC_BA(n) (0x1000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXDESC_PROD_IDX(n) (0x1004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXDESC_CONS_IDX(n) (0x1008 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXDESC_RING_SIZE(n) (0x100c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXDESC_CTRL(n) (0x1010 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_BA(n) (0x19000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_PROD_IDX(n) (0x19004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_CONS_IDX(n) (0x19008 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_RING_SIZE(n) (0x1900c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_UGT_THRE(n) (0x19010 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_CTRL(n) (0x19014 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TXCMPL_BPC(n) (0x19018 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TX_INT_STAT(n) (0x21000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TX_INT_MASK(n) (0x21004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TX_MOD_TIMER(n) (0x21008 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_TX_INT_CTRL(n) (0x2100c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_CONS_IDX(n) (0x29008 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_RING_SIZE(n) (0x2900c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_BUFFER1_SIZE(n) (0x29010 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_FC_THRE(n) (0x29014 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_UGT_THRE(n) (0x29018 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_RING_EN(n) (0x2901c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_DISABLE(n) (0x29020 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_DISABLE_DONE(n) (0x29024 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_INT_STAT(n) (0x31000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXFILL_INT_MASK(n) (0x31004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_BA(n) (0x39000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_PROD_IDX(n) (0x39004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_CONS_IDX(n) (0x39008 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_RING_SIZE(n) (0x3900c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_FC_THRE(n) (0x39010 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_UGT_THRE(n) (0x39014 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_BPC(n) (0x3901c + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_INT_STAT(n) (0x49000 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RXDESC_INT_MASK(n) (0x49004 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RX_MOD_TIMER(n) (0x49008 + (0x1000 * n)) +#define IPQ6018_EDMA_REG_RX_INT_CTRL(n) (0x4900c + (0x1000 * n)) +#define IPQ6018_EDMA_QID2RID_TABLE_MEM(q) (0x5a000 + (0x4 * q)) +#define IPQ6018_EDMA_REG_RXRING_PC(n) (0x5A200 + (0x10 * n)) +#define IPQ6018_EDMA_REG_RXRING_BC_0(n) (0x5A204 + (0x10 * n)) +#define IPQ6018_EDMA_REG_RXRING_BC_1(n) (0x5A208 + (0x10 * n)) +#define IPQ6018_EDMA_REG_TXRING_PC(n) (0x74000 + (0x10 * n)) +#define IPQ6018_EDMA_REG_TXRING_BC_0(n) (0x74004 + (0x10 * n)) +#define IPQ6018_EDMA_REG_TXRING_BC_1(n) (0x74008 + (0x10 * n)) + +/* + * EDMA_REG_PORT_CTRL register + */ +#define IPQ6018_EDMA_PORT_CTRL_EN 0x3 +#define IPQ6018_EDMA_PORT_CTRL_PAD_EN 0x1 + +/* + * EDMA_REG_TXQ_CTRL register + */ +#define IPQ6018_EDMA_TXDESC_PF_THRE_MASK 0xf +#define IPQ6018_EDMA_TXDESC_PF_THRE_SHIFT 0 +#define IPQ6018_EDMA_TXCMPL_WB_THRE_MASK 0xf +#define IPQ6018_EDMA_TXCMPL_WB_THRE_SHIFT 4 +#define IPQ6018_EDMA_TXDESC_PKT_SRAM_THRE_MASK 0xff +#define IPQ6018_EDMA_TXDESC_PKT_SRAM_THRE_SHIFT 8 +#define IPQ6018_EDMA_TXCMPL_WB_TIMER_MASK 0xffff +#define IPQ6018_EDMA_TXCMPL_WB_TIMER_SHIFT 16 + +/* + * EDMA_REG_RXQ_CTRL register + */ +#define IPQ6018_EDMA_RXFILL_PF_THRE_MASK 0xf +#define IPQ6018_EDMA_RXFILL_PF_THRE_SHIFT 0 +#define IPQ6018_EDMA_RXDESC_WB_THRE_MASK 0xf +#define IPQ6018_EDMA_RXDESC_WB_THRE_SHIFT 4 +#define IPQ6018_EDMA_RXDESC_WB_TIMER_MASK 0xffff +#define IPQ6018_EDMA_RXDESC_WB_TIMER_SHIFT 16 + +/* + * EDMA_REG_RX_TX_FULL_QID register + */ +#define IPQ6018_EDMA_RX_DESC_FULL_QID_MASK 0xff +#define IPQ6018_EDMA_RX_DESC_FULL_QID_SHIFT 0 +#define IPQ6018_EDMA_TX_CMPL_BUF_FULL_QID_MASK 0xff +#define IPQ6018_EDMA_TX_CMPL_BUF_FULL_QID_SHIFT 8 +#define IPQ6018_EDMA_TX_SRAM_FULL_QID_MASK 0x1f +#define IPQ6018_EDMA_TX_SRAM_FULL_QID_SHIFT 16 + +/* + * EDMA_REG_RXQ_FC_THRE reister + */ +#define IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE_MASK 0x1f +#define IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE_SHIFT 0 +#define IPQ6018_EDMA_DESC_FIFO_XOFF_THRE_MASK 0x3f +#define IPQ6018_EDMA_DESC_FIFO_XOFF_THRE_SHIFT 16 + +/* + * EDMA_REG_DMAR_CTRL register + */ +#define IPQ6018_EDMA_DMAR_REQ_PRI_MASK 0x7 +#define IPQ6018_EDMA_DMAR_REQ_PRI_SHIFT 0 +#define IPQ6018_EDMA_DMAR_BURST_LEN_MASK 0x1 +#define IPQ6018_EDMA_DMAR_BURST_LEN_SHIFT 3 +#define IPQ6018_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK 0x1f +#define IPQ6018_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT 4 +#define IPQ6018_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK 0x7 +#define IPQ6018_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT 9 +#define IPQ6018_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK 0x7 +#define IPQ6018_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT 12 + +/* + * EDMA DISABLE + */ +#define IPQ6018_EDMA_DISABLE 0 + +/* + * EDMA_REG_TXDESC_PROD_IDX register + */ +#define IPQ6018_EDMA_TXDESC_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_TXDESC_CONS_IDX register + */ +#define IPQ6018_EDMA_TXDESC_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_TXDESC_RING_SIZE register + */ +#define IPQ6018_EDMA_TXDESC_RING_SIZE_MASK 0xffff + +/* + * EDMA_REG_TXDESC_CTRL register + */ +#define IPQ6018_EDMA_TXDESC_ARB_GRP_ID_MASK 0x3 +#define IPQ6018_EDMA_TXDESC_ARB_GRP_ID_SHIFT 4 +#define IPQ6018_EDMA_TXDESC_FC_GRP_ID_MASK 0x7 +#define IPQ6018_EDMA_TXDESC_FC_GRP_ID_SHIFT 1 +#define IPQ6018_EDMA_TXDESC_TX_EN 0x1 + +/* + * EDMA_REG_TXCMPL_PROD_IDX register + */ +#define IPQ6018_EDMA_TXCMPL_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_CONS_IDX register + */ +#define IPQ6018_EDMA_TXCMPL_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_RING_SIZE register + */ +#define IPQ6018_EDMA_TXCMPL_RING_SIZE_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_UGT_THRE register + */ +#define IPQ6018_EDMA_TXCMPL_LOW_THRE_MASK 0xffff +#define IPQ6018_EDMA_TXCMPL_LOW_THRE_SHIFT 0 +#define IPQ6018_EDMA_TXCMPL_FC_THRE_MASK 0x3f +#define IPQ6018_EDMA_TXCMPL_FC_THRE_SHIFT 16 + +/* + * EDMA_REG_TXCMPL_CTRL register + */ +#define IPQ6018_EDMA_TXCMPL_RET_MODE_BUFF_ADDR 0x0 +#define IPQ6018_EDMA_TXCMPL_RET_MODE_OPAQUE 0x1 + +/* + * EDMA_REG_TX_MOD_TIMER register + */ +#define IPQ6018_EDMA_TX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ6018_EDMA_TX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA_REG_TX_INT_CTRL register + */ +#define IPQ6018_EDMA_TX_INT_MASK 0x3 + +/* + * EDMA_REG_RXFILL_PROD_IDX register + */ +#define IPQ6018_EDMA_RXFILL_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_RXFILL_CONS_IDX register + */ +#define IPQ6018_EDMA_RXFILL_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_RXFILL_RING_SIZE register + */ +#define IPQ6018_EDMA_RXFILL_RING_SIZE_MASK 0xffff +#define IPQ6018_EDMA_RXFILL_BUF_SIZE_MASK 0x3fff +#define IPQ6018_EDMA_RXFILL_BUF_SIZE_SHIFT 16 + +/* + * EDMA_REG_RXFILL_FC_THRE register + */ +#define IPQ6018_EDMA_RXFILL_FC_XON_THRE_MASK 0x7ff +#define IPQ6018_EDMA_RXFILL_FC_XON_THRE_SHIFT 12 +#define IPQ6018_EDMA_RXFILL_FC_XOFF_THRE_MASK 0x7ff +#define IPQ6018_EDMA_RXFILL_FC_XOFF_THRE_SHIFT 0 + +/* + * EDMA_REG_RXFILL_UGT_THRE register + */ +#define IPQ6018_EDMA_RXFILL_LOW_THRE_MASK 0xffff +#define IPQ6018_EDMA_RXFILL_LOW_THRE_SHIFT 0 + +/* + * EDMA_REG_RXFILL_RING_EN register + */ +#define IPQ6018_EDMA_RXFILL_RING_EN 0x1 + +/* + * EDMA_REG_RXFILL_INT_MASK register + */ +#define IPQ6018_EDMA_RXFILL_INT_MASK 0x1 + +/* + * EDMA_REG_RXDESC_PROD_IDX register + */ +#define IPQ6018_EDMA_RXDESC_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_RXDESC_CONS_IDX register + */ +#define IPQ6018_EDMA_RXDESC_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_RXDESC_RING_SIZE register + */ +#define IPQ6018_EDMA_RXDESC_RING_SIZE_MASK 0xffff +#define IPQ6018_EDMA_RXDESC_PL_OFFSET_MASK 0x1ff +#define IPQ6018_EDMA_RXDESC_PL_OFFSET_SHIFT 16 + +/* + * EDMA_REG_RXDESC_FC_THRE register + */ +#define IPQ6018_EDMA_RXDESC_FC_XON_THRE_MASK 0x7ff +#define IPQ6018_EDMA_RXDESC_FC_XON_THRE_SHIFT 12 +#define IPQ6018_EDMA_RXDESC_FC_XOFF_THRE_MASK 0x7ff +#define IPQ6018_EDMA_RXDESC_FC_XOFF_THRE_SHIFT 0 + +/* + * EDMA_REG_RXDESC_UGT_THRE register + */ +#define IPQ6018_EDMA_RXDESC_LOW_THRE_MASK 0xffff +#define IPQ6018_EDMA_RXDESC_LOW_THRE_SHIFT 0 + +/* + * EDMA_REG_RXDESC_CTRL register + */ +#define IPQ6018_EDMA_RXDESC_STAG_REMOVE_EN 0x8 +#define IPQ6018_EDMA_RXDESC_CTAG_REMOVE_EN 0x4 +#define IPQ6018_EDMA_RXDESC_QDISC_EN 0x2 +#define IPQ6018_EDMA_RXDESC_RX_EN 0x1 + +/* + * EDMA_REG_TX_INT_MASK register + */ +#define IPQ6018_EDMA_TX_INT_MASK_PKT_INT 0x1 +#define IPQ6018_EDMA_TX_INT_MASK_UGT_INT 0x2 + +/* + * EDMA_REG_RXDESC_INT_STAT register + */ +#define IPQ6018_EDMA_RXDESC_INT_STAT_PKT_INT 0x1 +#define IPQ6018_EDMA_RXDESC_INT_STAT_UGT_INT 0x2 + +/* + * EDMA_REG_RXDESC_INT_MASK register + */ +#define IPQ6018_EDMA_RXDESC_INT_MASK_PKT_INT 0x1 +#define IPQ6018_EDMA_RXDESC_INT_MASK_TIMER_INT_DIS 0x2 + +#define IPQ6018_EDMA_MASK_INT_DISABLE 0x0 +#define IPQ6018_EDMA_MASK_INT_CLEAR 0x0 + +/* + * EDMA_REG_RX_MOD_TIMER register + */ +#define IPQ6018_EDMA_RX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ6018_EDMA_RX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA QID2RID register sizes + */ +#define IPQ6018_EDMA_QID2RID_DEPTH 0x40 +#define IPQ6018_EDMA_QID2RID_QUEUES_PER_ENTRY 8 + +/* + * TXDESC shift values + */ +#define IPQ6018_EDMA_TXDESC_MORE_SHIFT 31 +#define IPQ6018_EDMA_TXDESC_TSO_EN_SHIFT 30 +#define IPQ6018_EDMA_TXDESC_PREHEADER_SHIFT 29 +#define IPQ6018_EDMA_TXDESC_POOL_ID_SHIFT 24 +#define IPQ6018_EDMA_TXDESC_POOL_ID_MASK 0x1f +#define IPQ6018_EDMA_TXDESC_DATA_OFFSET_SHIFT 16 +#define IPQ6018_EDMA_TXDESC_DATA_OFFSET_MASK 0xff +#define IPQ6018_EDMA_TXDESC_DATA_LENGTH_SHIFT 0 +#define IPQ6018_EDMA_TXDESC_DATA_LENGTH_MASK 0xffff + +#define IPQ6018_EDMA_PREHDR_DSTINFO_PORTID_IND 0x20 +#define IPQ6018_EDMA_PREHDR_PORTNUM_BITS 0x0fff +#define IPQ6018_EDMA_RING_DMA_MASK 0xffffffff +/* + * RXDESC shift values + */ +#define IPQ6018_EDMA_RXDESC_RX_RXFILL_CNT_MASK 0x000f +#define IPQ6018_EDMA_RXDESC_RX_RXFILL_CNT_SHIFT 16 + +#define IPQ6018_EDMA_RXDESC_PKT_SIZE_MASK 0x3fff +#define IPQ6018_EDMA_RXDESC_PKT_SIZE_SHIFT 0 + +#define IPQ6018_EDMA_RXDESC_RXD_VALID_MASK 0x1 +#define IPQ6018_EDMA_RXDESC_RXD_VALID_SHIFT 31 + +#define IPQ6018_EDMA_RXDESC_PACKET_LEN_MASK 0x3fff +#define IPQ6018_EDMA_RXDESC_RING_INT_STATUS_MASK 0x3 + +#define IPQ6018_EDMA_RING_DISABLE 0 +#define IPQ6018_EDMA_TXCMPL_RING_INT_STATUS_MASK 0x3 +#define IPQ6018_EDMA_TXCMPL_RETMODE_OPAQUE 0x0 +#define IPQ6018_EDMA_RXFILL_RING_INT_STATUS_MASK 0x1 + +/* + * TODO tune the timer and threshold values + */ +#define IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE 0x3 +#define IPQ6018_EDMA_RXFILL_PF_THRE 0x3 +#define IPQ6018_EDMA_RXDESC_WB_THRE 0x0 +#define IPQ6018_EDMA_RXDESC_WB_TIMER 0x2 + +#define IPQ6018_EDMA_RXDESC_XON_THRE 50 +#define IPQ6018_EDMA_RXDESC_XOFF_THRE 30 +#define IPQ6018_EDMA_RXDESC_LOW_THRE 0 +#define IPQ6018_EDMA_RX_MOD_TIMER_INIT 1000 + +#define IPQ6018_EDMA_TXDESC_PF_THRE 0x3 +#define IPQ6018_EDMA_TXCMPL_WB_THRE 0X0 +#define IPQ6018_EDMA_TXDESC_PKT_SRAM_THRE 0x20 +#define IPQ6018_EDMA_TXCMPL_WB_TIMER 0x2 + +#define IPQ6018_EDMA_TX_MOD_TIMER 150 + +#endif /* __EDMA_REGS__ */ diff --git a/board/qca/arm/ipq6018/ipq6018.c b/board/qca/arm/ipq6018/ipq6018.c index 945d12313d..0734d0e102 100644 --- a/board/qca/arm/ipq6018/ipq6018.c +++ b/board/qca/arm/ipq6018/ipq6018.c @@ -28,6 +28,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sdhci_host mmc_host; +extern int ipq6018_edma_init(void *cfg); const char *rsvd_node = "/reserved-memory"; const char *del_node[] = {"uboot", @@ -729,6 +730,135 @@ int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_fla return 0; } +int get_napa_gpio(int napa_gpio[2]) +{ + int napa_gpio_cnt = -1, node; + int res = -1; + + node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + if (node >= 0) { + napa_gpio_cnt = fdtdec_get_uint(gd->fdt_blob, node, "napa_gpio_cnt", -1); + if (napa_gpio_cnt >= 1) { + res = fdtdec_get_int_array(gd->fdt_blob, node, "napa_gpio", + (u32 *)napa_gpio, napa_gpio_cnt); + if (res >= 0) + return napa_gpio_cnt; + } + } + + return res; +} + +void napa_phy_reset_init(void) +{ + int napa_gpio[2] = {0}, napa_gpio_cnt, i; + unsigned int *napa_gpio_base; + + napa_gpio_cnt = get_napa_gpio(napa_gpio); + if (napa_gpio_cnt >= 1) { + for (i = 0; i < napa_gpio_cnt; i++) { + if (napa_gpio[i] >=0) { + napa_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(napa_gpio[i]); + writel(0x203, napa_gpio_base); + gpio_direction_output(napa_gpio[i], 0x0); + } + } + } +} + +void napa_phy_reset_init_done(void) +{ + int napa_gpio[2] = {0}, napa_gpio_cnt, i; + + napa_gpio_cnt = get_napa_gpio(napa_gpio); + if (napa_gpio_cnt >= 1) { + for (i = 0; i < napa_gpio_cnt; i++) + gpio_set_value(napa_gpio[i], 0x1); + } +} + +void eth_clock_enable(void) +{ + int tlmm_base = 0x1025000; + + /* + * ethernet clk rcgr block init -- start + * these clk init will be moved to sbl later + */ + + writel(0x100 ,0x01868024); + writel(0x1 ,0x01868020); + writel(0x2 ,0x01868020); + writel(0x100 ,0x0186802C); + writel(0x1 ,0x01868028); + writel(0x2 ,0x01868028); + writel(0x100 ,0x01868034); + writel(0x1 ,0x01868030); + writel(0x2 ,0x01868030); + writel(0x100 ,0x0186803C); + writel(0x1 ,0x01868038); + writel(0x2 ,0x01868038); + writel(0x100 ,0x01868044); + writel(0x1 ,0x01868040); + writel(0x2 ,0x01868040); + writel(0x100 ,0x0186804C); + writel(0x1 ,0x01868048); + writel(0x2 ,0x01868048); + writel(0x100 ,0x01868054); + writel(0x1 ,0x01868050); + writel(0x2 ,0x01868050); + writel(0x100 ,0x0186805C); + writel(0x1 ,0x01868058); + writel(0x2 ,0x01868058); + writel(0x100 ,0x01868064); + writel(0x1 ,0x01868060); + writel(0x2 ,0x01868060); + writel(0x100 ,0x0186806C); + writel(0x1 ,0x01868068); + writel(0x2 ,0x01868068); + writel(0x100 ,0x01868074); + writel(0x1 ,0x01868070); + writel(0x2 ,0x01868070); + writel(0x100 ,0x0186807C); + writel(0x1 ,0x01868078); + writel(0x2 ,0x01868078); + writel(0x101 ,0x01868084); + writel(0x1 ,0x01868080); + writel(0x2 ,0x01868080); + writel(0x100 ,0x0186808C); + writel(0x1 ,0x01868088); + writel(0x2 ,0x01868088); + + /* + * ethernet clk rcgr block init -- end + * these clk init will be moved to sbl later + */ + + /* bring phy out of reset */ + writel(7, tlmm_base + 0x1f000); + writel(7, tlmm_base + 0x20000); + writel(0x203, tlmm_base); + writel(0, tlmm_base + 0x4); + napa_phy_reset_init(); + mdelay(500); + writel(2, tlmm_base + 0x4); + napa_phy_reset_init_done(); + mdelay(500); +} + +int board_eth_init(bd_t *bis) +{ + int ret=0; + + eth_clock_enable(); + ret = ipq6018_edma_init(NULL); + + if (ret != 0) + printf("%s: ipq6018_edma_init failed : %d\n", __func__, ret); + + return ret; +} + unsigned long timer_read_counter(void) { return 0; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1b715bd510..78c7a373bb 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -83,6 +83,9 @@ obj-$(CONFIG_IPQ_SWITCH_QCA8511) += ipq806x/qca8511.o obj-$(CONFIG_IPQ807X_EDMA) += ipq807x/ipq807x_edma.o obj-$(CONFIG_IPQ807X_EDMA) += ipq807x/ipq807x_ppe.o obj-$(CONFIG_IPQ807X_EDMA) += ipq807x/ipq807x_uniphy.o +obj-$(CONFIG_IPQ6018_EDMA) += ipq6018/ipq6018_edma.o +obj-$(CONFIG_IPQ6018_EDMA) += ipq6018/ipq6018_ppe.o +obj-$(CONFIG_IPQ6018_EDMA) += ipq6018/ipq6018_uniphy.o obj-$(CONFIG_IPQ_MDIO) += ipq_common/ipq_mdio.o obj-$(CONFIG_QCA8075_PHY) += ipq_common/ipq_qca8075.o obj-$(CONFIG_QCA8033_PHY) += ipq_common/ipq_qca8033.o diff --git a/drivers/net/ipq6018/ipq6018_edma.c b/drivers/net/ipq6018/ipq6018_edma.c new file mode 100755 index 0000000000..b83af83d48 --- /dev/null +++ b/drivers/net/ipq6018/ipq6018_edma.c @@ -0,0 +1,1881 @@ +/* + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipq6018_edma.h" +#include "ipq_phy.h" + +DECLARE_GLOBAL_DATA_PTR; +#ifdef DEBUG +#define pr_debug(fmt, args...) printf(fmt, ##args); +#else +#define pr_debug(fmt, args...) +#endif + +#define pr_info(fmt, args...) printf(fmt, ##args); +#define pr_warn(fmt, args...) printf(fmt, ##args); + +#ifndef CONFIG_IPQ6018_BRIDGED_MODE +#define IPQ6018_EDMA_MAC_PORT_NO 3 +#endif + +static struct ipq6018_eth_dev *ipq6018_edma_dev[IPQ6018_EDMA_DEV]; + +uchar ipq6018_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD}; +phy_info_t *phy_info[PHY_MAX] = {0}; +int sgmii_mode[2] = {0}; + +extern void qca8075_ess_reset(void); +extern void psgmii_self_test(void); +extern void clear_self_test_config(void); +extern int ipq_sw_mdio_init(const char *); +extern void ipq_qca8075_dump_phy_regs(u32); +extern int ipq_mdio_read(int mii_id, + int regnum, ushort *data); +extern void ipq_qca8075_phy_map_ops(struct phy_ops **ops); +extern int ipq_qca8075_phy_init(struct phy_ops **ops); +extern void qca8075_phy_interface_set_mode(uint32_t phy_id, + uint32_t mode); +extern int ipq_qca8033_phy_init(struct phy_ops **ops, u32 phy_id); +extern int ipq_qca8081_phy_init(struct phy_ops **ops, u32 phy_id); +extern int ipq_board_fw_download(unsigned int phy_addr); +static int tftp_acl_our_port; + +/* + * EDMA hardware instance + */ +static u32 ipq6018_edma_hw_addr; + +void ipq6018_edma_dump_data(uchar *data, int len) +{ + int i; + + if (data == NULL) + return; + + pr_info("data address = 0x%x, len = %d \n", (unsigned int)data, len); + + for (i = 0; i < len; i++) { + if ((i % 16) == 0) + printf("\n"); + pr_info("%02x ", (unsigned int)data[i]); + } + + pr_info("\n\n"); +} + +/* + * ipq6018_edma_reg_read() + * Read EDMA register + */ +uint32_t ipq6018_edma_reg_read(uint32_t reg_off) +{ + return (uint32_t)readl(ipq6018_edma_hw_addr + reg_off); +} + +/* + * ipq6018_edma_reg_write() + * Write EDMA register + */ +void ipq6018_edma_reg_write(uint32_t reg_off, uint32_t val) +{ + pr_debug("%s: reg_off = %x, val =%x\n", __func__, reg_off, val); + writel(val, (ipq6018_edma_hw_addr + reg_off)); +} + +/* + * ipq6018_edma_alloc_rx_buffer() + * Alloc Rx buffers for one RxFill ring + */ +int ipq6018_edma_alloc_rx_buffer(struct ipq6018_edma_hw *ehw, + struct ipq6018_edma_rxfill_ring *rxfill_ring) +{ + uint16_t num_alloc = 0; + uint16_t cons, next, counter; + struct ipq6018_edma_rxfill_desc *rxfill_desc; + uint32_t reg_data; + struct ipq6018_edma_rx_preheader *rxph; + + /* + * Read RXFILL ring producer index + */ + reg_data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_RXFILL_PROD_IDX( + rxfill_ring->id)); + + next = reg_data & IPQ6018_EDMA_RXFILL_PROD_IDX_MASK; + + /* + * Read RXFILL ring consumer index + */ + reg_data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_RXFILL_CONS_IDX( + rxfill_ring->id)); + + cons = reg_data & IPQ6018_EDMA_RXFILL_CONS_IDX_MASK; + + while (1) { + + counter = next; + + if (++counter == rxfill_ring->count) + counter = 0; + + if (counter == cons) + break; + + if (counter >= CONFIG_SYS_RX_ETH_BUFFER) { + pr_info("%s: counter >= CONFIG_SYS_RX_ETH_BUFFER counter = %d\n", + __func__, counter); + break; + } + /* + * Get RXFILL descriptor + */ + rxfill_desc = IPQ6018_EDMA_RXFILL_DESC(rxfill_ring, next); + + /* + * Make room for Rx preheader + */ + rxph = (struct ipq6018_edma_rx_preheader *)rxfill_desc->buffer_addr; + + /* + * Fill the opaque value + */ + rxph->opaque = next; + + /* + * Save buffer size in RXFILL descriptor + */ + rxfill_desc->word1 = cpu_to_le32(IPQ6018_EDMA_RX_BUFF_SIZE & + IPQ6018_EDMA_RXFILL_BUF_SIZE_MASK); + + num_alloc++; + next = counter; + } + + if (num_alloc) { + /* + * Update RXFILL ring producer index + */ + reg_data = next & IPQ6018_EDMA_RXFILL_PROD_IDX_MASK; + + /* + * make sure the producer index updated before + * updating the hardware + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_PROD_IDX( + rxfill_ring->id), reg_data); + + pr_debug("%s: num_alloc = %d\n", __func__, num_alloc); + } + + return num_alloc; +} + +/* + * ipq6018_edma_clean_tx() + * Reap Tx descriptors + */ +uint32_t ipq6018_edma_clean_tx(struct ipq6018_edma_hw *ehw, + struct ipq6018_edma_txcmpl_ring *txcmpl_ring) +{ + struct ipq6018_edma_txcmpl_desc *txcmpl_desc; + uint16_t prod_idx, cons_idx; + uint32_t data; + uint32_t txcmpl_consumed = 0; + uchar *skb; + + /* + * Get TXCMPL ring producer index + */ + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_TXCMPL_PROD_IDX( + txcmpl_ring->id)); + prod_idx = data & IPQ6018_EDMA_TXCMPL_PROD_IDX_MASK; + + /* + * Get TXCMPL ring consumer index + */ + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_TXCMPL_CONS_IDX( + txcmpl_ring->id)); + cons_idx = data & IPQ6018_EDMA_TXCMPL_CONS_IDX_MASK; + + while (cons_idx != prod_idx) { + + txcmpl_desc = IPQ6018_EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); + + skb = (uchar *)txcmpl_desc->buffer_addr; + + if (unlikely(!skb)) { + pr_debug("Invalid skb: cons_idx:%u prod_idx:%u status %x\n", + cons_idx, prod_idx, txcmpl->status); + } + + if (++cons_idx == txcmpl_ring->count) + cons_idx = 0; + + txcmpl_consumed++; + } + + pr_debug("%s :%u txcmpl_consumed:%u prod_idx:%u cons_idx:%u\n", + __func__, txcmpl_ring->id, txcmpl_consumed, prod_idx, + cons_idx); + + if (txcmpl_consumed == 0) + return 0; + + /* + * Update TXCMPL ring consumer index + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXCMPL_CONS_IDX( + txcmpl_ring->id), cons_idx); + + return txcmpl_consumed; +} + +/* + * ipq6018_edma_clean_rx() + * Reap Rx descriptors + */ +uint32_t ipq6018_edma_clean_rx(struct ipq6018_edma_common_info *c_info, + struct ipq6018_edma_rxdesc_ring *rxdesc_ring) +{ + void *skb; + struct ipq6018_edma_rxdesc_desc *rxdesc_desc; + struct ipq6018_edma_rx_preheader *rxph; + uint16_t prod_idx, cons_idx; + int src_port_num; + int pkt_length; + int rx = CONFIG_SYS_RX_ETH_BUFFER; + u16 cleaned_count = 0; + struct ipq6018_edma_hw *ehw = &c_info->hw; + + pr_debug("%s: rxdesc_ring->id = %d\n", __func__, rxdesc_ring->id); + /* + * Read Rx ring consumer index + */ + cons_idx = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_RXDESC_CONS_IDX( + rxdesc_ring->id)) & + IPQ6018_EDMA_RXDESC_CONS_IDX_MASK; + + while (rx) { + /* + * Read Rx ring producer index + */ + prod_idx = ipq6018_edma_reg_read( + IPQ6018_EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->id)) + & IPQ6018_EDMA_RXDESC_PROD_IDX_MASK; + + if (cons_idx == prod_idx) { + pr_debug("%s: cons = prod \n", __func__); + break; + } + + rxdesc_desc = IPQ6018_EDMA_RXDESC_DESC(rxdesc_ring, cons_idx); + + skb = (void *)rxdesc_desc->buffer_addr; + + /* + * Get Rx preheader + */ + rxph = (struct ipq6018_edma_rx_preheader *)skb; + + rx--; + + /* + * Check src_info from Rx preheader + */ + if (IPQ6018_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) == + IPQ6018_EDMA_PREHDR_DSTINFO_PORTID_IND) { + src_port_num = rxph->src_info & + IPQ6018_EDMA_PREHDR_PORTNUM_BITS; + } else { + pr_warn("WARN: src_info_type:0x%x. Drop skb:%p\n", + IPQ6018_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph), + skb); + goto next_rx_desc; + } + + /* + * Get packet length + */ + pkt_length = rxdesc_desc->status & + IPQ6018_EDMA_RXDESC_PACKET_LEN_MASK; + + if (unlikely((src_port_num < IPQ6018_NSS_DP_START_PHY_PORT) || + (src_port_num > IPQ6018_NSS_DP_MAX_PHY_PORTS))) { + pr_warn("WARN: Port number error :%d. Drop skb:%p\n", + src_port_num, skb); + goto next_rx_desc; + } + + cleaned_count++; + + /* + * Remove Rx preheader + */ + skb = skb + IPQ6018_EDMA_RX_PREHDR_SIZE; + + pr_debug("%s: received pkt %p with length %d\n", + __func__, skb, pkt_length); + + net_process_received_packet(skb, pkt_length); +next_rx_desc: + /* + * Update consumer index + */ + if (++cons_idx == rxdesc_ring->count) + cons_idx = 0; + } + + if (cleaned_count) { + ipq6018_edma_alloc_rx_buffer(ehw, rxdesc_ring->rxfill); + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_CONS_IDX( + rxdesc_ring->id), cons_idx); + } + + return 0; +} + +/* + * ip6018_edma_rx_complete() + */ +static int ipq6018_edma_rx_complete(struct ipq6018_edma_common_info *c_info) +{ + struct ipq6018_edma_hw *ehw = &c_info->hw; + struct ipq6018_edma_txcmpl_ring *txcmpl_ring; + struct ipq6018_edma_rxdesc_ring *rxdesc_ring; + struct ipq6018_edma_rxfill_ring *rxfill_ring; + uint32_t misc_intr_status, reg_data; + int i; + + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + ipq6018_edma_clean_rx(c_info, rxdesc_ring); + } + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + ipq6018_edma_clean_tx(ehw, txcmpl_ring); + } + + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + ipq6018_edma_alloc_rx_buffer(ehw, rxfill_ring); + } + + /* + * Set RXDESC ring interrupt mask + */ + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + ipq6018_edma_reg_write( + IPQ6018_EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->id), + ehw->rxdesc_intr_mask); + } + + /* + * Set TXCMPL ring interrupt mask + */ + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TX_INT_MASK( + txcmpl_ring->id), + ehw->txcmpl_intr_mask); + } + + /* + * Set RXFILL ring interrupt mask + */ + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_INT_MASK( + rxfill_ring->id), + ehw->rxfill_intr_mask); + } + + /* + * Read Misc intr status + */ + reg_data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_MISC_INT_STAT); + misc_intr_status = reg_data & ehw->misc_intr_mask; + + if (misc_intr_status != 0) { + pr_info("%s: misc_intr_status = 0x%x\n", __func__, + misc_intr_status); + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_MISC_INT_MASK, + IPQ6018_EDMA_MASK_INT_DISABLE); + } + + return 0; +} + +#define MIN_PKT_SIZE 33 +/* + * ipq6018_eth_snd() + * Transmit a packet using an EDMA ring + */ +static int ipq6018_eth_snd(struct eth_device *dev, void *packet, int length) +{ + struct ipq6018_eth_dev *priv = dev->priv; + struct ipq6018_edma_common_info *c_info = priv->c_info; + struct ipq6018_edma_hw *ehw = &c_info->hw; + struct ipq6018_edma_txdesc_desc *txdesc; + struct ipq6018_edma_tx_preheader *txph; + struct ipq6018_edma_txdesc_ring *txdesc_ring; + uint16_t hw_next_to_use, hw_next_to_clean, chk_idx; + uint32_t data; + uchar *skb; + + txdesc_ring = ehw->txdesc_ring; + + if (tftp_acl_our_port != tftp_our_port) { + /* Allowing tftp packets */ + ipq6018_ppe_acl_set(3, 0x4, 0x1, tftp_our_port, 0xffff, 0, 0); + tftp_acl_our_port = tftp_our_port; + } + /* + * Read TXDESC ring producer index + */ + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id)); + + hw_next_to_use = data & IPQ6018_EDMA_TXDESC_PROD_IDX_MASK; + + pr_debug("%s: txdesc_ring->id = %d\n", __func__, txdesc_ring->id); + + /* + * Read TXDESC ring consumer index + */ + /* + * TODO - read to local variable to optimize uncached access + */ + data = ipq6018_edma_reg_read( + IPQ6018_EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id)); + + hw_next_to_clean = data & IPQ6018_EDMA_TXDESC_CONS_IDX_MASK; + + /* + * Check for available Tx descriptor + */ + chk_idx = (hw_next_to_use + 1) & (txdesc_ring->count-1); + + if (chk_idx == hw_next_to_clean) { + return NETDEV_TX_BUSY; + } + + /* + * Get Tx descriptor + */ + txdesc = IPQ6018_EDMA_TXDESC_DESC(txdesc_ring, hw_next_to_use); + + txdesc->word1 = 0; + + skb = (uchar *)txdesc->buffer_addr; + + pr_debug("%s: txdesc->buffer_addr = 0x%x length = %d \ + prod_idx = %d cons_idx = %d\n", + __func__, txdesc->buffer_addr, length, + hw_next_to_use, hw_next_to_clean); + + /* + * Make room for Tx preheader + */ + txph = (struct ipq6018_edma_tx_preheader *)skb; + + memset((void *)txph, 0, IPQ6018_EDMA_TX_PREHDR_SIZE); + +#ifdef CONFIG_IPQ6018_BRIDGED_MODE + /* VP 0x0 share vsi 2 with port 1-4 */ + txph->src_info = 0x2000; + txph->dst_info = 0x0; +#else + /* + * Populate Tx preheader dst info, port id is macid in dp_dev + */ + + txph->dst_info = (IPQ6018_EDMA_PREHDR_DSTINFO_PORTID_IND << 8) | + (IPQ6018_EDMA_MAC_PORT_NO & 0x0fff); + +#endif + + /* + * Set opaque field in preheader + */ + txph->opaque = cpu_to_le32(skb); + + /* + * copy the packet + */ + memcpy(skb + IPQ6018_EDMA_TX_PREHDR_SIZE, packet, length); + /* + * The EDMA HW is unable to process packets less than MIN_PKT_SIZE(33) bytes, + * then the EDMA stalls. This is to pad the packets up to MIN_PKT_SIZE. + */ + if (length < MIN_PKT_SIZE) { + memset(skb + IPQ6018_EDMA_TX_PREHDR_SIZE + length, 0x00, (MIN_PKT_SIZE - length)); + length = MIN_PKT_SIZE; + } + /* + * Populate Tx descriptor + */ + txdesc->word1 |= (1 << IPQ6018_EDMA_TXDESC_PREHEADER_SHIFT) + | ((IPQ6018_EDMA_TX_PREHDR_SIZE & + IPQ6018_EDMA_TXDESC_DATA_OFFSET_MASK) + << IPQ6018_EDMA_TXDESC_DATA_OFFSET_SHIFT); + txdesc->word1 |= ((length & IPQ6018_EDMA_TXDESC_DATA_LENGTH_MASK) + << IPQ6018_EDMA_TXDESC_DATA_LENGTH_SHIFT); + + /* + * Update producer index + */ + hw_next_to_use = (hw_next_to_use + 1) & (txdesc_ring->count - 1); + + /* + * make sure the hw_next_to_use is updated before the + * write to hardware + */ + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id), hw_next_to_use & + IPQ6018_EDMA_TXDESC_PROD_IDX_MASK); + + pr_debug("%s: successfull\n", __func__); + + return EDMA_TX_OK; +} + +static int ipq6018_eth_recv(struct eth_device *dev) +{ + struct ipq6018_eth_dev *priv = dev->priv; + struct ipq6018_edma_common_info *c_info = priv->c_info; + struct ipq6018_edma_rxdesc_ring *rxdesc_ring; + struct ipq6018_edma_hw *ehw = &c_info->hw; + volatile u32 reg_data; + u32 rxdesc_intr_status = 0; + int i; + + /* + * Read RxDesc intr status + */ + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + + reg_data = ipq6018_edma_reg_read( + IPQ6018_EDMA_REG_RXDESC_INT_STAT( + rxdesc_ring->id)); + rxdesc_intr_status |= reg_data & + IPQ6018_EDMA_RXDESC_RING_INT_STATUS_MASK; + + /* + * Disable RxDesc intr + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_INT_MASK( + rxdesc_ring->id), + IPQ6018_EDMA_MASK_INT_DISABLE); + } + + ipq6018_edma_rx_complete(c_info); + + return 0; +} + +/* + * ipq6018_edma_setup_ring_resources() + * Allocate/setup resources for EDMA rings + */ +static int ipq6018_edma_setup_ring_resources(struct ipq6018_edma_hw *ehw) +{ + struct ipq6018_edma_txcmpl_ring *txcmpl_ring; + struct ipq6018_edma_txdesc_ring *txdesc_ring; + struct ipq6018_edma_rxfill_ring *rxfill_ring; + struct ipq6018_edma_rxdesc_ring *rxdesc_ring; + struct ipq6018_edma_txdesc_desc *tx_desc; + struct ipq6018_edma_rxfill_desc *rxfill_desc; + int i, j, index; + void *tx_buf; + void *rx_buf; + + /* + * Allocate Rx fill ring descriptors + */ + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + rxfill_ring->count = IPQ6018_EDMA_RXFILL_RING_SIZE; + rxfill_ring->id = ehw->rxfill_ring_start + i; + rxfill_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq6018_edma_rxfill_desc) * + rxfill_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (rxfill_ring->desc == NULL) { + pr_info("%s: rxfill_ring->desc alloc error\n", __func__); + return -ENOMEM; + } + rxfill_ring->dma = virt_to_phys(rxfill_ring->desc); + rx_buf = (void *)noncached_alloc(PKTSIZE_ALIGN * + rxfill_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (rx_buf == NULL) { + pr_info("%s: rxfill_ring->desc buffer alloc error\n", + __func__); + return -ENOMEM; + } + + for (j = 0; j < rxfill_ring->count; j++) { + rxfill_desc = IPQ6018_EDMA_RXFILL_DESC(rxfill_ring, j); + rxfill_desc->buffer_addr = virt_to_phys(rx_buf); + rx_buf += PKTSIZE_ALIGN; + } + } + + /* + * Allocate RxDesc ring descriptors + */ + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + rxdesc_ring->count = IPQ6018_EDMA_RXDESC_RING_SIZE; + rxdesc_ring->id = ehw->rxdesc_ring_start + i; + + /* + * Create a mapping between RX Desc ring and Rx fill ring. + * Number of fill rings are lesser than the descriptor rings + * Share the fill rings across descriptor rings. + */ + + index = ehw->rxfill_ring_start + (i % ehw->rxfill_rings); + rxdesc_ring->rxfill = + &ehw->rxfill_ring[index - ehw->rxfill_ring_start]; + rxdesc_ring->rxfill = ehw->rxfill_ring; + + rxdesc_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq6018_edma_rxdesc_desc) * + rxdesc_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (rxdesc_ring->desc == NULL) { + pr_info("%s: rxdesc_ring->desc alloc error\n", __func__); + return -ENOMEM; + } + rxdesc_ring->dma = virt_to_phys(rxdesc_ring->desc); + } + + /* + * Allocate TxCmpl ring descriptors + */ + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + txcmpl_ring->count = IPQ6018_EDMA_TXCMPL_RING_SIZE; + txcmpl_ring->id = ehw->txcmpl_ring_start + i; + txcmpl_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq6018_edma_txcmpl_desc) * + txcmpl_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (txcmpl_ring->desc == NULL) { + pr_info("%s: txcmpl_ring->desc alloc error\n", __func__); + return -ENOMEM; + } + txcmpl_ring->dma = virt_to_phys(txcmpl_ring->desc); + } + + + /* + * Allocate TxDesc ring descriptors + */ + for (i = 0; i < ehw->txdesc_rings; i++) { + txdesc_ring = &ehw->txdesc_ring[i]; + txdesc_ring->count = IPQ6018_EDMA_TXDESC_RING_SIZE; + txdesc_ring->id = ehw->txdesc_ring_start + i; + txdesc_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq6018_edma_txdesc_desc) * + txdesc_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (txdesc_ring->desc == NULL) { + pr_info("%s: txdesc_ring->desc alloc error\n", __func__); + return -ENOMEM; + } + + txdesc_ring->dma = virt_to_phys(txdesc_ring->desc); + tx_buf = (void *)noncached_alloc(IPQ6018_EDMA_TX_BUF_SIZE * + txdesc_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (tx_buf == NULL) { + pr_info("%s: txdesc_ring->desc buffer alloc error\n", + __func__); + return -ENOMEM; + } + + for (j = 0; j < txdesc_ring->count; j++) { + tx_desc = IPQ6018_EDMA_TXDESC_DESC(txdesc_ring, j); + tx_desc->buffer_addr = virt_to_phys(tx_buf); + tx_buf += IPQ6018_EDMA_TX_BUF_SIZE; + } + } + + pr_info("%s: successfull\n", __func__); + + return 0; + +} + +/* + * ipq6018_edma_free_desc() + * Free EDMA desc memory + */ +static void ipq6018_edma_free_desc(struct ipq6018_edma_common_info *c_info) +{ + struct ipq6018_edma_hw *ehw = &c_info->hw; + struct ipq6018_edma_txcmpl_ring *txcmpl_ring; + struct ipq6018_edma_txdesc_ring *txdesc_ring; + struct ipq6018_edma_rxfill_ring *rxfill_ring; + struct ipq6018_edma_rxdesc_ring *rxdesc_ring; + struct ipq6018_edma_txdesc_desc *tx_desc; + int i; + + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + if (rxfill_ring->desc) + ipq6018_free_mem(rxfill_ring->desc); + } + + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + if (rxdesc_ring->desc) + ipq6018_free_mem(rxdesc_ring->desc); + } + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + if (txcmpl_ring->desc) { + ipq6018_free_mem(txcmpl_ring->desc); + } + } + + for (i = 0; i < ehw->txdesc_rings; i++) { + txdesc_ring = &ehw->txdesc_ring[i]; + if (txdesc_ring->desc) { + tx_desc = IPQ6018_EDMA_TXDESC_DESC(txdesc_ring, 0); + if (tx_desc->buffer_addr) + ipq6018_free_mem((void *)tx_desc->buffer_addr); + ipq6018_free_mem(txdesc_ring->desc); + } + } +} + +/* + * ipq6018_edma_free_rings() + * Free EDMA software rings + */ +static void ipq6018_edma_free_rings(struct ipq6018_edma_common_info *c_info) +{ + struct ipq6018_edma_hw *ehw = &c_info->hw; + ipq6018_free_mem(ehw->rxfill_ring); + ipq6018_free_mem(ehw->rxdesc_ring); + ipq6018_free_mem(ehw->txdesc_ring); + ipq6018_free_mem(ehw->txcmpl_ring); +} + +static void ipq6018_edma_disable_rings(struct ipq6018_edma_hw *edma_hw) +{ + int i, desc_index; + u32 data; + + /* + * Disable Rx rings + */ + for (i = 0; i < IPQ6018_EDMA_MAX_RXDESC_RINGS; i++) { + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_RXDESC_CTRL(i)); + data &= ~IPQ6018_EDMA_RXDESC_RX_EN; + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_CTRL(i), data); + } + + /* + * Disable RxFill Rings + */ + for (i = 0; i < IPQ6018_EDMA_MAX_RXFILL_RINGS; i++) { + data = ipq6018_edma_reg_read( + IPQ6018_EDMA_REG_RXFILL_RING_EN(i)); + data &= ~IPQ6018_EDMA_RXFILL_RING_EN; + ipq6018_edma_reg_write( + IPQ6018_EDMA_REG_RXFILL_RING_EN(i), data); + } + + /* + * Disable Tx rings + */ + for (desc_index = 0; desc_index < + IPQ6018_EDMA_MAX_TXDESC_RINGS; desc_index++) { + data = ipq6018_edma_reg_read( + IPQ6018_EDMA_REG_TXDESC_CTRL(desc_index)); + data &= ~IPQ6018_EDMA_TXDESC_TX_EN; + ipq6018_edma_reg_write( + IPQ6018_EDMA_REG_TXDESC_CTRL(desc_index), data); + } +} + +static void ipq6018_edma_disable_intr(struct ipq6018_edma_hw *ehw) +{ + int i; + + /* + * Disable interrupts + */ + for (i = 0; i < IPQ6018_EDMA_MAX_TXCMPL_RINGS; i++) + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TX_INT_MASK(i), 0); + + for (i = 0; i < IPQ6018_EDMA_MAX_RXFILL_RINGS; i++) + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_INT_MASK(i), 0); + + for (i = 0; i < IPQ6018_EDMA_MAX_RXDESC_RINGS; i++) + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RX_INT_CTRL(i), 0); + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_MISC_INT_MASK, + IPQ6018_EDMA_MASK_INT_DISABLE); +} + +static void set_sgmii_mode(int port_id, int sg_mode) +{ + if (port_id == 4) + sgmii_mode[0] = sg_mode; + else if (port_id == 5) + sgmii_mode[1] = sg_mode; +} + +static int get_sgmii_mode(int port_id) +{ + if (port_id == 4) + return sgmii_mode[0]; + else if (port_id == 5) + return sgmii_mode[1]; + else + return -1; +} + +static int ipq6018_eth_init(struct eth_device *eth_dev, bd_t *this) +{ + struct ipq6018_eth_dev *priv = eth_dev->priv; + struct ipq6018_edma_common_info *c_info = priv->c_info; + struct ipq6018_edma_hw *ehw = &c_info->hw; + int i; + uint32_t data; + u8 status; + struct phy_ops *phy_get_ops; + fal_port_speed_t speed; + fal_port_duplex_t duplex; + char *lstatus[] = {"up", "Down"}; + char *dp[] = {"Half", "Full"}; + int linkup=0; + int mac_speed = 0, speed_clock1 = 0, speed_clock2 = 0; + int phy_addr, port_8033 = -1, node; + int sfp_port = -1; + int phy_node = -1; + int ret_sgmii_mode; + + node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + if (node >= 0) + port_8033 = fdtdec_get_uint(gd->fdt_blob, node, "8033_port", -1); + + if (node >= 0) + sfp_port = fdtdec_get_uint(gd->fdt_blob, node, "sfp_port", -1); + + phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo"); + /* + * Check PHY link, speed, Duplex on all phys. + * we will proceed even if single link is up + * else we will return with -1; + */ + for (i = 0; i < PHY_MAX; i++) { + + if (i == sfp_port) { + status = phy_status_get_from_ppe(i); + speed = FAL_SPEED_10000; + duplex = FAL_FULL_DUPLEX; + } else { + if (!priv->ops[i]) { + printf ("Phy ops not mapped\n"); + continue; + } + phy_get_ops = priv->ops[i]; + + if (!phy_get_ops->phy_get_link_status || + !phy_get_ops->phy_get_speed || + !phy_get_ops->phy_get_duplex) { + printf ("Link status/Get speed/Get duplex not mapped\n"); + return -1; + } + + if (phy_node >= 0) { + phy_addr = phy_info[i]->phy_address; + } else { + + if (i == port_8033) + phy_addr = QCA8033_PHY_ADDR; + else + phy_addr = i; + } + status = phy_get_ops->phy_get_link_status(priv->mac_unit, phy_addr); + phy_get_ops->phy_get_speed(priv->mac_unit, phy_addr, &speed); + phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex); + } + + if (status == 0) + linkup++; + + switch (speed) { + case FAL_SPEED_10: + mac_speed = 0x0; + speed_clock1 = 0x109; + speed_clock2 = 0x9; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], speed, + dp[duplex]); + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) + set_sgmii_mode(i, 1); + } + break; + case FAL_SPEED_100: + mac_speed = 0x1; + if (i == port_8033) + speed_clock1 = 0x109; + else + speed_clock1 = 0x101; + if (i == port_8033) + speed_clock2 = 0x0; + else + speed_clock2 = 0x4; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], speed, + dp[duplex]); + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) + set_sgmii_mode(i, 1); + } + break; + case FAL_SPEED_1000: + mac_speed = 0x2; + speed_clock1 = 0x101; + speed_clock2 = 0x0; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], speed, + dp[duplex]); + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) + set_sgmii_mode(i, 1); + if ((phy_info[i]->phy_type == QCA8081_PHY_TYPE) && (i == 4)) + speed_clock1 = 0x301; + } + break; + case FAL_SPEED_10000: + mac_speed = 0x3; + if (i == 4) + speed_clock1 = 0x301; + else + speed_clock1 = 0x101; + speed_clock2 = 0x0; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], speed, + dp[duplex]); + break; + case FAL_SPEED_2500: + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) { + mac_speed = 0x2; + if (i == 4) + speed_clock1 = 0x301; + else if (i == 5) + speed_clock1 = 0x101; + set_sgmii_mode(i, 0); + speed_clock2 = 0x0; + } + if (phy_info[i]->phy_type == AQ_PHY_TYPE) { + mac_speed = 0x4; + if (i == 4) { + speed_clock1 = 0x301; + speed_clock2 = 0x3; + } else if (i == 5) { + speed_clock1 = 0x107; + speed_clock2 = 0x0; + } + } + } else { + speed_clock1 = 0x107; + mac_speed = 0x4; + speed_clock2 = 0x0; + } + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], speed, + dp[duplex]); + break; + case FAL_SPEED_5000: + mac_speed = 0x5; + if (i == 4) { + speed_clock1 = 0x301; + speed_clock2 = 0x1; + } else { + speed_clock1 = 0x103; + speed_clock2 = 0x0; + } + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], speed, + dp[duplex]); + break; + default: + printf("Unknown speed\n"); + break; + } + + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) { + ret_sgmii_mode = get_sgmii_mode(i); + if (ret_sgmii_mode == 1) { + ppe_port_bridge_txmac_set(i + 1, 1); + if (i == 4) + ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII0_RGMII4); + else if (i == 5) + ppe_uniphy_mode_set(0x2, PORT_WRAPPER_SGMII0_RGMII4); + + } else if (ret_sgmii_mode == 0) { + ppe_port_bridge_txmac_set(i + 1, 1); + if (i == 4) + ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII_PLUS); + else if (i == 5) + ppe_uniphy_mode_set(0x2, PORT_WRAPPER_SGMII_PLUS); + } + } + } + ipq6018_speed_clock_set(i, speed_clock1, speed_clock2); + if (i == sfp_port) + ipq6018_10g_r_speed_set(i, status); + else + ipq6018_pqsgmii_speed_set(i, mac_speed, status); + } + + if (linkup <= 0) { + /*No PHY link is alive*/ + return -1; + } + + /* + * Alloc Rx buffers + */ + ipq6018_edma_alloc_rx_buffer(ehw, ehw->rxfill_ring); + + /* + * Set DMA request priority + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_DMAR_CTRL, + (1 & IPQ6018_EDMA_DMAR_REQ_PRI_MASK) << + IPQ6018_EDMA_DMAR_REQ_PRI_SHIFT); + + /* + * Enable EDMA + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_PORT_CTRL, + IPQ6018_EDMA_PORT_CTRL_EN); + + /* + * Enable Rx rings + */ + for (i = ehw->rxdesc_ring_start; i < ehw->rxdesc_ring_end; i++) { + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_RXDESC_CTRL(i)); + data |= IPQ6018_EDMA_RXDESC_RX_EN; + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_CTRL(i), data); + } + + for (i = ehw->rxfill_ring_start; i < ehw->rxfill_ring_end; i++) { + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_RXFILL_RING_EN(i)); + data |= IPQ6018_EDMA_RXFILL_RING_EN; + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_RING_EN(i), data); + } + + /* + * Enable Tx rings + */ + for (i = ehw->txdesc_ring_start; i < ehw->txdesc_ring_end; i++) { + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_TXDESC_CTRL(i)); + data |= IPQ6018_EDMA_TXDESC_TX_EN; + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC_CTRL(i), data); + } + + pr_info("%s: done\n", __func__); + + return 0; +} + +static int ipq6018_edma_wr_macaddr(struct eth_device *dev) +{ + return 0; +} + +static void ipq6018_eth_halt(struct eth_device *dev) +{ + struct ipq6018_eth_dev *priv = dev->priv; + struct ipq6018_edma_common_info *c_info = priv->c_info; + struct ipq6018_edma_hw *ehw = &c_info->hw; + + ipq6018_edma_disable_intr(ehw); + ipq6018_edma_disable_rings(ehw); + + /* + * Disable EDMA + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_PORT_CTRL, IPQ6018_EDMA_DISABLE); + pr_info("%s: done\n", __func__); +} + +static void ipq6018_edma_set_ring_values(struct ipq6018_edma_hw *edma_hw) +{ + edma_hw->txdesc_ring_start = IPQ6018_EDMA_TX_DESC_RING_START; + edma_hw->txdesc_rings = IPQ6018_EDMA_TX_DESC_RING_NOS; + edma_hw->txdesc_ring_end = IPQ6018_EDMA_TX_DESC_RING_SIZE; + + edma_hw->txcmpl_ring_start = IPQ6018_EDMA_TX_CMPL_RING_START; + edma_hw->txcmpl_rings = IPQ6018_EDMA_RX_FILL_RING_NOS; + edma_hw->txcmpl_ring_end = IPQ6018_EDMA_TX_CMPL_RING_SIZE; + + edma_hw->rxfill_ring_start = IPQ6018_EDMA_RX_FILL_RING_START; + edma_hw->rxfill_rings = IPQ6018_EDMA_RX_FILL_RING_NOS; + edma_hw->rxfill_ring_end = IPQ6018_EDMA_RX_FILL_RING_SIZE; + + edma_hw->rxdesc_ring_start = IPQ6018_EDMA_RX_DESC_RING_START; + edma_hw->rxdesc_rings = IPQ6018_EDMA_RX_DESC_RING_NOS; + edma_hw->rxdesc_ring_end = IPQ6018_EDMA_RX_DESC_RING_SIZE; + + pr_info("Num rings - TxDesc:%u (%u-%u) TxCmpl:%u (%u-%u)\n", + edma_hw->txdesc_rings, edma_hw->txdesc_ring_start, + (edma_hw->txdesc_ring_start + edma_hw->txdesc_rings - 1), + edma_hw->txcmpl_rings, edma_hw->txcmpl_ring_start, + (edma_hw->txcmpl_ring_start + edma_hw->txcmpl_rings - 1)); + + pr_info("RxDesc:%u (%u-%u) RxFill:%u (%u-%u)\n", + edma_hw->rxdesc_rings, edma_hw->rxdesc_ring_start, + (edma_hw->rxdesc_ring_start + edma_hw->rxdesc_rings - 1), + edma_hw->rxfill_rings, edma_hw->rxfill_ring_start, + (edma_hw->rxfill_ring_start + edma_hw->rxfill_rings - 1)); +} + +/* + * ipq6018_edma_alloc_rings() + * Allocate EDMA software rings + */ +static int ipq6018_edma_alloc_rings(struct ipq6018_edma_hw *ehw) +{ + ehw->rxfill_ring = (void *)noncached_alloc((sizeof( + struct ipq6018_edma_rxfill_ring) * + ehw->rxfill_rings), + CONFIG_SYS_CACHELINE_SIZE); + + if (!ehw->rxfill_ring) { + pr_info("%s: rxfill_ring alloc error\n", __func__); + return -ENOMEM; + } + + ehw->rxdesc_ring = (void *)noncached_alloc((sizeof( + struct ipq6018_edma_rxdesc_ring) * + ehw->rxdesc_rings), + CONFIG_SYS_CACHELINE_SIZE); + + if (!ehw->rxdesc_ring) { + pr_info("%s: rxdesc_ring alloc error\n", __func__); + return -ENOMEM; + } + + ehw->txdesc_ring = (void *)noncached_alloc((sizeof( + struct ipq6018_edma_txdesc_ring) * + ehw->txdesc_rings), + CONFIG_SYS_CACHELINE_SIZE); + if (!ehw->txdesc_ring) { + pr_info("%s: txdesc_ring alloc error\n", __func__); + return -ENOMEM; + } + + ehw->txcmpl_ring = (void *)noncached_alloc((sizeof( + struct ipq6018_edma_txcmpl_ring) * + ehw->txcmpl_rings), + CONFIG_SYS_CACHELINE_SIZE); + + if (!ehw->txcmpl_ring) { + pr_info("%s: txcmpl_ring alloc error\n", __func__); + return -ENOMEM; + } + + pr_info("%s: successfull\n", __func__); + + return 0; + +} + + +/* + * ipq6018_edma_init_rings() + * Initialize EDMA rings + */ +static int ipq6018_edma_init_rings(struct ipq6018_edma_hw *ehw) +{ + int ret; + + /* + * Setup ring values + */ + ipq6018_edma_set_ring_values(ehw); + + /* + * Allocate desc rings + */ + ret = ipq6018_edma_alloc_rings(ehw); + if (ret) + return ret; + + /* + * Setup ring resources + */ + ret = ipq6018_edma_setup_ring_resources(ehw); + if (ret) + return ret; + + return 0; +} + +/* + * ipq6018_edma_configure_rx_threshold() + * Configure Rx threshold parameters + */ +static void ipq6018_edma_configure_rx_threshold(void) +{ + uint32_t rxq_fc_thre, rxq_ctrl; + + rxq_fc_thre = (IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE & + IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE_MASK) + << IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE_SHIFT; + + rxq_fc_thre |= (IPQ6018_EDMA_RXFILL_FIFO_XOFF_THRE & + IPQ6018_EDMA_DESC_FIFO_XOFF_THRE_MASK) + << IPQ6018_EDMA_DESC_FIFO_XOFF_THRE_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXQ_FC_THRE, rxq_fc_thre); + + rxq_ctrl = (IPQ6018_EDMA_RXFILL_PF_THRE & + IPQ6018_EDMA_RXFILL_PF_THRE_MASK) << + IPQ6018_EDMA_RXFILL_PF_THRE_SHIFT; + + rxq_ctrl |= (IPQ6018_EDMA_RXDESC_WB_THRE & + IPQ6018_EDMA_RXDESC_WB_THRE_MASK) << + IPQ6018_EDMA_RXDESC_WB_THRE_SHIFT; + + rxq_ctrl |= (IPQ6018_EDMA_RXDESC_WB_TIMER & + IPQ6018_EDMA_RXDESC_WB_TIMER_MASK) << + IPQ6018_EDMA_RXDESC_WB_TIMER_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXQ_CTRL, rxq_ctrl); +} + +/* + * ipq6018_edma_configure_tx_threshold() + * Configure global Tx threshold parameters + */ +static void ipq6018_edma_configure_tx_threshold(void) +{ + uint32_t txq_ctrl; + + txq_ctrl = (IPQ6018_EDMA_TXDESC_PF_THRE & + IPQ6018_EDMA_TXDESC_PF_THRE_MASK) << + IPQ6018_EDMA_TXDESC_PF_THRE_SHIFT; + + txq_ctrl |= (IPQ6018_EDMA_TXCMPL_WB_THRE & + IPQ6018_EDMA_TXCMPL_WB_THRE_MASK) << + IPQ6018_EDMA_TXCMPL_WB_THRE_SHIFT; + + txq_ctrl |= (IPQ6018_EDMA_TXDESC_PKT_SRAM_THRE & + IPQ6018_EDMA_TXDESC_PKT_SRAM_THRE_MASK) << + IPQ6018_EDMA_TXDESC_PKT_SRAM_THRE_SHIFT; + + txq_ctrl |= (IPQ6018_EDMA_TXCMPL_WB_TIMER & + IPQ6018_EDMA_TXCMPL_WB_TIMER_MASK) << + IPQ6018_EDMA_TXCMPL_WB_TIMER_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXQ_CTRL, txq_ctrl); +} + +/* + * ipq6018_edma_configure_txdesc_ring() + * Configure one TxDesc ring + */ +static void ipq6018_edma_configure_txdesc_ring(struct ipq6018_edma_hw *ehw, + struct ipq6018_edma_txdesc_ring *txdesc_ring) +{ + uint32_t data; + uint16_t hw_cons_idx; + + /* + * Configure TXDESC ring + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC_BA(txdesc_ring->id), + (uint32_t)(txdesc_ring->dma & + IPQ6018_EDMA_RING_DMA_MASK)); + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC_RING_SIZE( + txdesc_ring->id), (uint32_t)(txdesc_ring->count & + IPQ6018_EDMA_TXDESC_RING_SIZE_MASK)); + + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_TXDESC_CONS_IDX( + txdesc_ring->id)); + + data &= ~(IPQ6018_EDMA_TXDESC_CONS_IDX_MASK); + hw_cons_idx = data; + + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id)); + + data &= ~(IPQ6018_EDMA_TXDESC_PROD_IDX_MASK); + data |= hw_cons_idx & IPQ6018_EDMA_TXDESC_PROD_IDX_MASK; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id), data); +} + +/* + * ipq6018_edma_configure_txcmpl_ring() + * Configure one TxCmpl ring + */ +static void ipq6018_edma_configure_txcmpl_ring(struct ipq6018_edma_hw *ehw, + struct ipq6018_edma_txcmpl_ring *txcmpl_ring) +{ + uint32_t txcmpl_ugt_thre, low_thre = 0, txcmpl_fc_thre = 0; + uint32_t tx_mod_timer; + + /* + * Configure TxCmpl ring base address + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXCMPL_BA(txcmpl_ring->id), + (uint32_t)(txcmpl_ring->dma & + IPQ6018_EDMA_RING_DMA_MASK)); + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXCMPL_RING_SIZE( + txcmpl_ring->id), (uint32_t)(txcmpl_ring->count & + IPQ6018_EDMA_TXDESC_RING_SIZE_MASK)); + + /* + * Set TxCmpl ret mode to opaque + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id), + IPQ6018_EDMA_TXCMPL_RETMODE_OPAQUE); + + txcmpl_ugt_thre = (low_thre & IPQ6018_EDMA_TXCMPL_LOW_THRE_MASK) << + IPQ6018_EDMA_TXCMPL_LOW_THRE_SHIFT; + + txcmpl_ugt_thre |= (txcmpl_fc_thre & IPQ6018_EDMA_TXCMPL_FC_THRE_MASK) + << IPQ6018_EDMA_TXCMPL_FC_THRE_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXCMPL_UGT_THRE( + txcmpl_ring->id), txcmpl_ugt_thre); + + tx_mod_timer = (IPQ6018_EDMA_TX_MOD_TIMER & + IPQ6018_EDMA_TX_MOD_TIMER_INIT_MASK) << + IPQ6018_EDMA_TX_MOD_TIMER_INIT_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id), + tx_mod_timer); + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TX_INT_CTRL(txcmpl_ring->id), + 0x2); +} + +/* + * ipq6018_edma_configure_rxdesc_ring() + * Configure one RxDesc ring + */ +static void ipq6018_edma_configure_rxdesc_ring(struct ipq6018_edma_hw *ehw, + struct ipq6018_edma_rxdesc_ring *rxdesc_ring) +{ + uint32_t data; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_BA(rxdesc_ring->id), + (uint32_t)(rxdesc_ring->dma & 0xffffffff)); + + data = rxdesc_ring->count & IPQ6018_EDMA_RXDESC_RING_SIZE_MASK; + data |= (ehw->rx_payload_offset & + IPQ6018_EDMA_RXDESC_PL_OFFSET_MASK) << + IPQ6018_EDMA_RXDESC_PL_OFFSET_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_RING_SIZE( + rxdesc_ring->id), data); + + data = (IPQ6018_EDMA_RXDESC_XON_THRE & + IPQ6018_EDMA_RXDESC_FC_XON_THRE_MASK) << + IPQ6018_EDMA_RXDESC_FC_XON_THRE_SHIFT; + + data |= (IPQ6018_EDMA_RXDESC_XOFF_THRE & + IPQ6018_EDMA_RXDESC_FC_XOFF_THRE_MASK) << + IPQ6018_EDMA_RXDESC_FC_XOFF_THRE_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_FC_THRE( + rxdesc_ring->id), data); + + data = (IPQ6018_EDMA_RXDESC_LOW_THRE & + IPQ6018_EDMA_RXDESC_LOW_THRE_MASK) << + IPQ6018_EDMA_RXDESC_LOW_THRE_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC_UGT_THRE( + rxdesc_ring->id), data); + + data = (IPQ6018_EDMA_RX_MOD_TIMER_INIT & + IPQ6018_EDMA_RX_MOD_TIMER_INIT_MASK) << + IPQ6018_EDMA_RX_MOD_TIMER_INIT_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RX_MOD_TIMER( + rxdesc_ring->id), data); + + /* + * Enable ring. Set ret mode to 'opaque'. + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RX_INT_CTRL( + rxdesc_ring->id), 0x2); +} + +/* + * ipq6018_edma_configure_rxfill_ring() + * Configure one RxFill ring + */ +static void ipq6018_edma_configure_rxfill_ring(struct ipq6018_edma_hw *ehw, + struct ipq6018_edma_rxfill_ring *rxfill_ring) +{ + uint32_t rxfill_low_thre = (rxfill_ring->count / 4); + uint32_t rxfill_xon_thre = (rxfill_ring->count / 8); + uint32_t rxfill_xoff_thre = (rxfill_ring->count / 16); + uint32_t rxfill_fc_thre; + uint32_t rxfill_ugt_thre; + uint32_t data; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_BA(rxfill_ring->id), + (uint32_t)(rxfill_ring->dma & IPQ6018_EDMA_RING_DMA_MASK)); + + data = rxfill_ring->count & IPQ6018_EDMA_RXFILL_RING_SIZE_MASK; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->id), data); + + rxfill_fc_thre = (rxfill_xon_thre & IPQ6018_EDMA_RXFILL_FC_XON_THRE_MASK) + << IPQ6018_EDMA_RXFILL_FC_XON_THRE_SHIFT; + rxfill_fc_thre |= (rxfill_xoff_thre & IPQ6018_EDMA_RXFILL_FC_XOFF_THRE_MASK) + << IPQ6018_EDMA_RXFILL_FC_XOFF_THRE_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_FC_THRE(rxfill_ring->id), + rxfill_fc_thre); + + rxfill_ugt_thre = (rxfill_low_thre & IPQ6018_EDMA_RXFILL_LOW_THRE_MASK) + << IPQ6018_EDMA_RXFILL_LOW_THRE_SHIFT; + + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXFILL_UGT_THRE(rxfill_ring->id), + rxfill_ugt_thre); + +} + + +/* + * ipq6018_edma_configure_rings() + * Configure EDMA rings + */ +static void ipq6018_edma_configure_rings(struct ipq6018_edma_hw *ehw) +{ + int i; + + /* + * Configure TXDESC ring + */ + for (i = 0; i < ehw->txdesc_rings; i++) + ipq6018_edma_configure_txdesc_ring(ehw, &ehw->txdesc_ring[i]); + + /* + * Configure TXCMPL ring + */ + for (i = 0; i < ehw->txcmpl_rings; i++) + ipq6018_edma_configure_txcmpl_ring(ehw, &ehw->txcmpl_ring[i]); + + /* + * Configure RXFILL rings + */ + for (i = 0; i < ehw->rxfill_rings; i++) + ipq6018_edma_configure_rxfill_ring(ehw, &ehw->rxfill_ring[i]); + + /* + * Configure RXDESC ring + */ + for (i = 0; i < ehw->rxdesc_rings; i++) + ipq6018_edma_configure_rxdesc_ring(ehw, &ehw->rxdesc_ring[i]); + + pr_info("%s: successfull\n", __func__); +} + + +/* + * ipq6018_edma_hw_init() + * EDMA hw init + */ +int ipq6018_edma_hw_init(struct ipq6018_edma_hw *ehw) +{ + int ret, desc_index; + uint32_t i, reg; + volatile uint32_t data; + + struct ipq6018_edma_rxdesc_ring *rxdesc_ring = NULL; + + ipq6018_ppe_provision_init(); + + data = ipq6018_edma_reg_read(IPQ6018_EDMA_REG_MAS_CTRL); + printf("EDMA ver %d hw init\n", data); + + /* + * Setup private data structure + */ + ehw->rxfill_intr_mask = IPQ6018_EDMA_RXFILL_INT_MASK; + ehw->rxdesc_intr_mask = IPQ6018_EDMA_RXDESC_INT_MASK_PKT_INT; + ehw->txcmpl_intr_mask = IPQ6018_EDMA_TX_INT_MASK_PKT_INT | + IPQ6018_EDMA_TX_INT_MASK_UGT_INT; + ehw->misc_intr_mask = 0; + ehw->rx_payload_offset = IPQ6018_EDMA_RX_PREHDR_SIZE; + + ipq6018_edma_disable_intr(ehw); + ipq6018_edma_disable_rings(ehw); + + ret = ipq6018_edma_init_rings(ehw); + + if (ret) + return ret; + + ipq6018_edma_configure_rings(ehw); + + /* + * Clear the TXDESC2CMPL_MAP_xx reg before setting up + * the mapping. This register holds TXDESC to TXFILL ring + * mapping. + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_0, 0); + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_1, 0); + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_2, 0); + desc_index = ehw->txcmpl_ring_start; + + /* + * 3 registers to hold the completion mapping for total 24 + * TX desc rings (0-9,10-19 and rest). In each entry 3 bits hold + * the mapping for a particular TX desc ring. + */ + for (i = ehw->txdesc_ring_start; + i < ehw->txdesc_ring_end; i++) { + if (i >= 0 && i <= 9) + reg = IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_0; + else if (i >= 10 && i <= 19) + reg = IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_1; + else + reg = IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_2; + + pr_debug("Configure TXDESC:%u to use TXCMPL:%u\n", + i, desc_index); + + data = ipq6018_edma_reg_read(reg); + data |= (desc_index & 0x7) << ((i % 10) * 3); + ipq6018_edma_reg_write(reg, data); + + desc_index++; + if (desc_index == ehw->txcmpl_ring_end) + desc_index = ehw->txcmpl_ring_start; + } + + /* + * Set PPE QID to EDMA Rx ring mapping. + * When coming up use only queue 0. + * HOST EDMA rings. FW EDMA comes up and overwrites as required. + * Each entry can hold mapping for 8 PPE queues and entry size is + * 4 bytes + */ + desc_index = ehw->rxdesc_ring_start; + data = 0; + data |= (desc_index & 0xF); + ipq6018_edma_reg_write(IPQ6018_EDMA_QID2RID_TABLE_MEM(0), data); + pr_debug("Configure QID2RID reg:0x%x to 0x%x\n", reg, data); + + /* + * Configure Tx/Rx queue threshold parameters + */ + ipq6018_edma_configure_tx_threshold(); + ipq6018_edma_configure_rx_threshold(); + + /* + * Set RXDESC2FILL_MAP_xx reg. + * There are two registers RXDESC2FILL_0 and RXDESC2FILL_1 + * 3 bits holds the rx fill ring mapping for each of the + * rx descriptor ring. + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC2FILL_MAP_0, 0); + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_RXDESC2FILL_MAP_1, 0); + + for (i = ehw->rxdesc_ring_start; + i < ehw->rxdesc_ring_end; i++) { + if ((i >= 0) && (i <= 9)) + reg = IPQ6018_EDMA_REG_RXDESC2FILL_MAP_0; + else + reg = IPQ6018_EDMA_REG_RXDESC2FILL_MAP_1; + + rxdesc_ring = &ehw->rxdesc_ring[i - ehw->rxdesc_ring_start]; + + pr_debug("Configure RXDESC:%u to use RXFILL:%u\n", + rxdesc_ring->id, rxdesc_ring->rxfill->id); + + data = ipq6018_edma_reg_read(reg); + data |= (rxdesc_ring->rxfill->id & 0x7) << ((i % 10) * 3); + ipq6018_edma_reg_write(reg, data); + } + + reg = IPQ6018_EDMA_REG_RXDESC2FILL_MAP_0; + pr_debug("EDMA_REG_RXDESC2FILL_MAP_0: 0x%x\n", + ipq6018_edma_reg_read(reg)); + reg = IPQ6018_EDMA_REG_RXDESC2FILL_MAP_1; + pr_debug("EDMA_REG_RXDESC2FILL_MAP_1: 0x%x\n", + ipq6018_edma_reg_read(reg)); + + reg = IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_0; + pr_debug("EDMA_REG_TXDESC2CMPL_MAP_0: 0x%x\n", + ipq6018_edma_reg_read(reg)); + reg = IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_1; + pr_debug("EDMA_REG_TXDESC2CMPL_MAP_1: 0x%x\n", + ipq6018_edma_reg_read(reg)); + reg = IPQ6018_EDMA_REG_TXDESC2CMPL_MAP_2; + pr_debug("EDMA_REG_TXDESC2CMPL_MAP_2: 0x%x\n", + ipq6018_edma_reg_read(reg)); + + /* + * Enable MISC interrupt + */ + ipq6018_edma_reg_write(IPQ6018_EDMA_REG_MISC_INT_MASK, + ehw->misc_intr_mask); + + pr_info("%s: successfull\n", __func__); + return 0; +} + +void get_phy_address(int offset) +{ + int phy_type; + int phy_address; + int i; + + for (i = 0; i < PHY_MAX; i++) + phy_info[i] = ipq6018_alloc_mem(sizeof(phy_info_t)); + i = 0; + for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0; + offset = fdt_next_subnode(gd->fdt_blob, offset)) { + + phy_address = fdtdec_get_uint(gd->fdt_blob, + offset, "phy_address", 0); + phy_type = fdtdec_get_uint(gd->fdt_blob, + offset, "phy_type", 0); + phy_info[i]->phy_address = phy_address; + phy_info[i++]->phy_type = phy_type; + } +} + +int ipq6018_edma_init(void *edma_board_cfg) +{ + struct eth_device *dev[IPQ6018_EDMA_DEV]; + struct ipq6018_edma_common_info *c_info[IPQ6018_EDMA_DEV]; + struct ipq6018_edma_hw *hw[IPQ6018_EDMA_DEV]; + uchar enet_addr[IPQ6018_EDMA_DEV * 6]; + int i, phy_id; + uint32_t phy_chip_id, phy_chip_id1, phy_chip_id2; + int ret = -1; + ipq6018_edma_board_cfg_t ledma_cfg, *edma_cfg; + static int sw_init_done = 0; + int port_8033 = -1, node, phy_addr; + int mode, phy_node = -1; + + node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + if (node >= 0) + port_8033 = fdtdec_get_uint(gd->fdt_blob, node, "8033_port", -1); + + phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo"); + if (phy_node >= 0) + get_phy_address(phy_node); + + mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode", -1); + if (mode < 0) { + printf("Error: switch_mac_mode not specified in dts"); + return mode; + } + + memset(c_info, 0, (sizeof(c_info) * IPQ6018_EDMA_DEV)); + memset(enet_addr, 0, sizeof(enet_addr)); + memset(&ledma_cfg, 0, sizeof(ledma_cfg)); + edma_cfg = &ledma_cfg; + strlcpy(edma_cfg->phy_name, "IPQ MDIO0", sizeof(edma_cfg->phy_name)); + + /* Getting the MAC address from ART partition */ + ret = get_eth_mac_address(enet_addr, IPQ6018_EDMA_DEV); + + /* + * Register EDMA as single ethernet + * interface. + */ + for (i = 0; i < IPQ6018_EDMA_DEV; edma_cfg++, i++) { + dev[i] = ipq6018_alloc_mem(sizeof(struct eth_device)); + + if (!dev[i]) + goto init_failed; + + memset(dev[i], 0, sizeof(struct eth_device)); + + c_info[i] = ipq6018_alloc_mem( + sizeof(struct ipq6018_edma_common_info)); + + if (!c_info[i]) + goto init_failed; + + memset(c_info[i], 0, + sizeof(struct ipq6018_edma_common_info)); + + hw[i] = &c_info[i]->hw; + + c_info[i]->hw.hw_addr = (unsigned long __iomem *) + IPQ6018_EDMA_CFG_BASE; + + ipq6018_edma_dev[i] = ipq6018_alloc_mem( + sizeof(struct ipq6018_eth_dev)); + + if (!ipq6018_edma_dev[i]) + goto init_failed; + + memset (ipq6018_edma_dev[i], 0, + sizeof(struct ipq6018_eth_dev)); + + dev[i]->iobase = IPQ6018_EDMA_CFG_BASE; + dev[i]->init = ipq6018_eth_init; + dev[i]->halt = ipq6018_eth_halt; + dev[i]->recv = ipq6018_eth_recv; + dev[i]->send = ipq6018_eth_snd; + dev[i]->write_hwaddr = ipq6018_edma_wr_macaddr; + dev[i]->priv = (void *)ipq6018_edma_dev[i]; + + if ((ret < 0) || + (!is_valid_ethaddr(&enet_addr[edma_cfg->unit * 6]))) { + memcpy(&dev[i]->enetaddr[0], ipq6018_def_enetaddr, 6); + } else { + memcpy(&dev[i]->enetaddr[0], + &enet_addr[edma_cfg->unit * 6], 6); + } + + printf("MAC%x addr:%x:%x:%x:%x:%x:%x\n", + edma_cfg->unit, dev[i]->enetaddr[0], + dev[i]->enetaddr[1], + dev[i]->enetaddr[2], + dev[i]->enetaddr[3], + dev[i]->enetaddr[4], + dev[i]->enetaddr[5]); + + snprintf(dev[i]->name, sizeof(dev[i]->name), "eth%d", i); + + ipq6018_edma_dev[i]->dev = dev[i]; + ipq6018_edma_dev[i]->mac_unit = edma_cfg->unit; + ipq6018_edma_dev[i]->c_info = c_info[i]; + ipq6018_edma_hw_addr = IPQ6018_EDMA_CFG_BASE; + + ret = ipq_sw_mdio_init(edma_cfg->phy_name); + if (ret) + goto init_failed; + + for (phy_id = 0; phy_id < PHY_MAX; phy_id++) { + if (phy_node >= 0) { + phy_addr = phy_info[phy_id]->phy_address; + } else { + if (phy_id == port_8033) + phy_addr = QCA8033_PHY_ADDR; + else + phy_addr = phy_id; + } + + phy_chip_id1 = ipq_mdio_read(phy_addr, QCA_PHY_ID1, NULL); + phy_chip_id2 = ipq_mdio_read(phy_addr, QCA_PHY_ID2, NULL); + phy_chip_id = (phy_chip_id1 << 16) | phy_chip_id2; + switch(phy_chip_id) { + case QCA8075_PHY_V1_0_5P: + case QCA8075_PHY_V1_1_5P: + case QCA8075_PHY_V1_1_2P: + + if (!sw_init_done) { + if (ipq_qca8075_phy_init(&ipq6018_edma_dev[i]->ops[phy_id]) == 0) { + sw_init_done = 1; + } + } else { + ipq_qca8075_phy_map_ops(&ipq6018_edma_dev[i]->ops[phy_id]); + } + + if (mode == PORT_WRAPPER_PSGMII) + qca8075_phy_interface_set_mode(0x0, 0x0); + else if ( mode == PORT_WRAPPER_QSGMII) + qca8075_phy_interface_set_mode(0x0, 0x4); + break; + case QCA8033_PHY: + ipq_qca8033_phy_init(&ipq6018_edma_dev[i]->ops[phy_id], phy_addr); + break; + case QCA8081_PHY: + case QCA8081_1_1_PHY: + ipq_qca8081_phy_init(&ipq6018_edma_dev[i]->ops[phy_id], phy_addr); + break; + default: + ipq_qca8075_phy_map_ops(&ipq6018_edma_dev[i]->ops[phy_id]); + break; + } + } + + ret = ipq6018_edma_hw_init(hw[i]); + + if (ret) + goto init_failed; + + eth_register(dev[i]); + } + + return 0; + +init_failed: + printf("Error in allocating Mem\n"); + + for (i = 0; i < IPQ6018_EDMA_DEV; i++) { + if (dev[i]) { + eth_unregister(dev[i]); + ipq6018_free_mem(dev[i]); + } + if (c_info[i]) { + ipq6018_edma_free_desc(c_info[i]); + ipq6018_edma_free_rings(c_info[i]); + ipq6018_free_mem(c_info[i]); + } + if (ipq6018_edma_dev[i]) { + ipq6018_free_mem(ipq6018_edma_dev[i]); + } + } + + return -1; +} diff --git a/drivers/net/ipq6018/ipq6018_edma.h b/drivers/net/ipq6018/ipq6018_edma.h new file mode 100644 index 0000000000..3042088513 --- /dev/null +++ b/drivers/net/ipq6018/ipq6018_edma.h @@ -0,0 +1,327 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ************************************************************************** +*/ +#ifndef __IPQ6018_EDMA__ +#define __IPQ6018_EDMA__ + +#define IPQ6018_NSS_DP_START_PHY_PORT 1 +#define IPQ6018_NSS_DP_MAX_PHY_PORTS 6 + +#define IPQ6018_EDMA_BUF_SIZE 2000 +#define IPQ6018_EDMA_DEVICE_NODE_NAME "edma" +#define IPQ6018_EDMA_RX_BUFF_SIZE (IPQ6018_EDMA_BUF_SIZE + IPQ6018_EDMA_RX_PREHDR_SIZE) +#define IPQ6018_EDMA_RX_PREHDR_SIZE (sizeof(struct ipq6018_edma_rx_preheader)) +#define IPQ6018_EDMA_TX_PREHDR_SIZE (sizeof(struct ipq6018_edma_tx_preheader)) + +#define IPQ6018_EDMA_TXDESC_RING_SIZE 8 +#define IPQ6018_EDMA_TXCMPL_RING_SIZE 8 +#define IPQ6018_EDMA_RXDESC_RING_SIZE 16 +#define IPQ6018_EDMA_RXFILL_RING_SIZE 16 + +#define IPQ6018_EDMA_START_GMACS IPQ6018_NSS_DP_START_PHY_PORT +#define IPQ6018_EDMA_MAX_GMACS IPQ6018_NSS_DP_MAX_PHY_PORTS +#define IPQ6018_EDMA_TX_BUF_SIZE (1540 + IPQ6018_EDMA_TX_PREHDR_SIZE) + +#define IPQ6018_EDMA_MAX_TXCMPL_RINGS 8 /* Max TxCmpl rings */ +#define IPQ6018_EDMA_MAX_RXDESC_RINGS 16 /* Max RxDesc rings */ +#define IPQ6018_EDMA_MAX_RXFILL_RINGS 8 /* Max RxFill rings */ +#define IPQ6018_EDMA_MAX_TXDESC_RINGS 24 /* Max TxDesc rings */ + +#define IPQ6018_EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) +#define IPQ6018_EDMA_RXFILL_DESC(R, i) IPQ6018_EDMA_GET_DESC(R, i, struct ipq6018_edma_rxfill_desc) +#define IPQ6018_EDMA_RXDESC_DESC(R, i) IPQ6018_EDMA_GET_DESC(R, i, struct ipq6018_edma_rxdesc_desc) +#define IPQ6018_EDMA_TXDESC_DESC(R, i) IPQ6018_EDMA_GET_DESC(R, i, struct ipq6018_edma_txdesc_desc) +#define IPQ6018_EDMA_TXCMPL_DESC(R, i) IPQ6018_EDMA_GET_DESC(R, i, struct ipq6018_edma_txcmpl_desc) +#define IPQ6018_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) (((rxph)->src_info >> 8) & 0xf0) + +#define IPQ6018_EDMA_DEV 1 +#define IPQ6018_EDMA_TX_QUEUE 1 +#define IPQ6018_EDMA_RX_QUEUE 1 + +//#define IPQ6018_EDMA_TX_DESC_RING_START 23 +#define IPQ6018_EDMA_TX_DESC_RING_START 0 +#define IPQ6018_EDMA_TX_DESC_RING_NOS 1 +#define IPQ6018_EDMA_TX_DESC_RING_SIZE \ +(IPQ6018_EDMA_TX_DESC_RING_START + IPQ6018_EDMA_TX_DESC_RING_NOS) + +#define IPQ6018_EDMA_TX_CMPL_RING_START 7 +#define IPQ6018_EDMA_TX_CMPL_RING_NOS 1 +#define IPQ6018_EDMA_TX_CMPL_RING_SIZE \ +(IPQ6018_EDMA_TX_CMPL_RING_START + IPQ6018_EDMA_TX_CMPL_RING_NOS) + +#define IPQ6018_EDMA_RX_DESC_RING_START 15 +#define IPQ6018_EDMA_RX_DESC_RING_NOS 1 +#define IPQ6018_EDMA_RX_DESC_RING_SIZE \ +(IPQ6018_EDMA_RX_DESC_RING_START + IPQ6018_EDMA_RX_DESC_RING_NOS) + +#define IPQ6018_EDMA_RX_FILL_RING_START 7 +#define IPQ6018_EDMA_RX_FILL_RING_NOS 1 +#define IPQ6018_EDMA_RX_FILL_RING_SIZE \ +(IPQ6018_EDMA_RX_FILL_RING_START + IPQ6018_EDMA_RX_FILL_RING_NOS) + +#define IPQ6018_EDMA_TX_IMR_NORMAL_MASK 1 +#define IPQ6018_EDMA_RX_IMR_NORMAL_MASK 1 +#define IPQ6018_EDMA_INTR_CLEAR_TYPE 0 +#define IPQ6018_EDMA_INTR_SW_IDX_W_TYPE 0 +#define IPQ6018_EDMA_RSS_TYPE_NONE 0x1 + +#define NETDEV_TX_BUSY 1 + +#define PSGMIIPHY_PLL_VCO_RELATED_CTRL 0x0009878c +#define PSGMIIPHY_PLL_VCO_VAL 0x2803 + +#define PSGMIIPHY_VCO_CALIBRATION_CTRL 0x0009809c +#define PSGMIIPHY_VCO_VAL 0x4ADA +#define PSGMIIPHY_VCO_RST_VAL 0xADA + +#define RGMII_TCSR_ESS_CFG 0x01953000 +#define ESS_RGMII_CTRL 0x0C000004 +/* + * Tx descriptor + */ +struct ipq6018_edma_txdesc_desc { + uint32_t buffer_addr; + /* buffer address */ + uint32_t word1; + /* more bit, TSO, preheader, pool, offset and length */ +}; + +/* + * TxCmpl descriptor + */ +struct ipq6018_edma_txcmpl_desc { + uint32_t buffer_addr; /* buffer address/opaque */ + uint32_t status; /* status */ +}; + +/* + * Rx descriptor + */ +struct ipq6018_edma_rxdesc_desc { + uint32_t buffer_addr; /* buffer address */ + uint32_t status; /* status */ +}; + +/* + * RxFill descriptor + */ +struct ipq6018_edma_rxfill_desc { + uint32_t buffer_addr; /* Buffer address */ + uint32_t word1; /* opaque_ind and buffer size */ +}; + +/* + * Tx descriptor ring + */ +struct ipq6018_edma_txdesc_ring { + uint32_t id; /* TXDESC ring number */ + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + uint16_t count; /* number of descriptors */ +}; + +/* + * TxCmpl ring + */ +struct ipq6018_edma_txcmpl_ring { + uint32_t id; /* TXCMPL ring number */ + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + uint16_t count; /* number of descriptors in the ring */ +}; + +/* + * RxFill ring + */ +struct ipq6018_edma_rxfill_ring { + uint32_t id; /* RXFILL ring number */ + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + uint16_t count; /* number of descriptors in the ring */ +}; + +/* + * RxDesc ring + */ +struct ipq6018_edma_rxdesc_ring { + uint32_t id; /* RXDESC ring number */ + struct ipq6018_edma_rxfill_ring *rxfill; /* RXFILL ring used */ + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + uint16_t count; /* number of descriptors in the ring */ +}; + +/* + * EDMA Tx Preheader + */ +struct ipq6018_edma_tx_preheader { + uint32_t opaque; /* Opaque, contains skb pointer */ + uint16_t src_info; /* Src information */ + uint16_t dst_info; /* Dest information */ + uint32_t tx_pre2; /* SVLAN & CVLAN flag, drop prec, hash value */ + uint32_t tx_pre3; /* STAG, CTAG */ + uint32_t tx_pre4; /* CPU code, L3 & L4 offset, service code */ + uint32_t tx_pre5; /* IP addr index, ACL index */ + uint32_t tx_pre6; /* IP payload checksum, copy2cpu, timestamp, dscp */ + uint32_t tx_pre7; /* Timestamp, QoS TAG */ +}; + +/* + * EDMA Rx Preheader + */ +struct ipq6018_edma_rx_preheader { + uint32_t opaque; /* Opaque, contains skb pointer*/ + uint16_t src_info; /* Src information */ + uint16_t dst_info; /* Dest information */ + uint32_t rx_pre2; /* SVLAN & CVLAN flag, drop prec, hash value */ + uint32_t rx_pre3; /* STAG, CTAG */ + uint32_t rx_pre4; /* CPU code, L3 & L4 offset, service code */ + uint32_t rx_pre5; /* IP addr index, ACL index */ + uint32_t rx_pre6; /* IP payload checksum, copy2cpu, timestamp, dscp */ + uint32_t rx_pre7; /* Timestamp, QoS TAG */ +}; + +enum ipq6018_edma_tx { + EDMA_TX_OK = 0, /* Tx success */ + EDMA_TX_DESC = 1, /* Not enough descriptors */ + EDMA_TX_FAIL = 2, /* Tx failure */ +}; + + +/* per core queue related information */ +struct queue_per_cpu_info { + u32 tx_mask; /* tx interrupt mask */ + u32 rx_mask; /* rx interrupt mask */ + u32 tx_status; /* tx interrupt status */ + u32 rx_status; /* rx interrupt status */ + u32 tx_start; /* tx queue start */ + u32 rx_start; /* rx queue start */ + struct ipq6018_edma_common_info *c_info; /* edma common info */ +}; + +/* edma hw specific data */ +struct ipq6018_edma_hw { + unsigned long __iomem *hw_addr; /* inner register address */ + u8 intr_clear_type; /* interrupt clear */ + u8 intr_sw_idx_w; /* To do chk type interrupt software index */ + u16 rx_buff_size; /* To do chk type Rx buffer size */ + u8 rss_type; /* rss protocol type */ + uint16_t rx_payload_offset; /* start of the payload offset */ + uint32_t flags; /* internal flags */ + int active; /* status */ + struct ipq6018_edma_txdesc_ring *txdesc_ring; /* Tx Descriptor Ring, SW is producer */ + struct ipq6018_edma_txcmpl_ring *txcmpl_ring; /* Tx Completion Ring, SW is consumer */ + struct ipq6018_edma_rxdesc_ring *rxdesc_ring; /* Rx Descriptor Ring, SW is consumer */ + struct ipq6018_edma_rxfill_ring *rxfill_ring; /* Rx Fill Ring, SW is producer */ + uint32_t txdesc_rings; /* Number of TxDesc rings */ + uint32_t txdesc_ring_start; /* Id of first TXDESC ring */ + uint32_t txdesc_ring_end; /* Id of the last TXDESC ring */ + uint32_t txcmpl_rings; /* Number of TxCmpl rings */ + uint32_t txcmpl_ring_start; /* Id of first TXCMPL ring */ + uint32_t txcmpl_ring_end; /* Id of last TXCMPL ring */ + uint32_t rxfill_rings; /* Number of RxFill rings */ + uint32_t rxfill_ring_start; /* Id of first RxFill ring */ + uint32_t rxfill_ring_end; /* Id of last RxFill ring */ + uint32_t rxdesc_rings; /* Number of RxDesc rings */ + uint32_t rxdesc_ring_start; /* Id of first RxDesc ring */ + uint32_t rxdesc_ring_end; /* Id of last RxDesc ring */ + uint32_t tx_intr_mask; /* tx interrupt mask */ + uint32_t rx_intr_mask; /* rx interrupt mask */ + uint32_t rxfill_intr_mask; /* Rx fill ring interrupt mask */ + uint32_t rxdesc_intr_mask; /* Rx Desc ring interrupt mask */ + uint32_t txcmpl_intr_mask; /* Tx Cmpl ring interrupt mask */ + uint32_t misc_intr_mask; /* misc interrupt interrupt mask */ +}; + +struct ipq6018_edma_common_info { + struct ipq6018_edma_hw hw; +}; + +#define MAX_PHY 6 +struct ipq6018_eth_dev { + u8 *phy_address; + uint no_of_phys; + uint interface; + uint speed; + uint duplex; + uint sw_configured; + uint mac_unit; + uint mac_ps; + int link_printed; + u32 padding; + struct eth_device *dev; + struct ipq6018_edma_common_info *c_info; + struct phy_ops *ops[MAX_PHY]; + const char phy_name[MDIO_NAME_LEN]; +} __attribute__ ((aligned(8))); + +static inline void* ipq6018_alloc_mem(u32 size) +{ + void *p = malloc(size); + if (p != NULL) + memset(p, 0, size); + return p; +} + +static inline void* ipq6018_alloc_memalign(u32 size) +{ + void *p = memalign(CONFIG_SYS_CACHELINE_SIZE, size); + if (p != NULL) + memset(p, 0, size); + return p; +} + +static inline void ipq6018_free_mem(void *ptr) +{ + if (ptr) + free(ptr); +} + +//extern struct ipq6018_edma_hw ipq6018_edma_hw; + +uint32_t ipq6018_edma_reg_read(uint32_t reg_off); +void ipq6018_edma_reg_write(uint32_t reg_off, uint32_t val); + + +extern int get_eth_mac_address(uchar *enetaddr, uint no_of_macs); + +typedef struct { + uint count; + u8 addr[7]; +} ipq6018_edma_phy_addr_t; + +/* ipq6018 edma Paramaters */ +typedef struct { + uint base; + int unit; + uint mac_conn_to_phy; + phy_interface_t phy; + ipq6018_edma_phy_addr_t phy_addr; + char phy_name[MDIO_NAME_LEN]; +} ipq6018_edma_board_cfg_t; + +extern void ipq6018_ppe_provision_init(void); +extern void ipq6018_speed_clock_set(int port, int speed_clock1, int speed_clock2); +extern void ipq6018_pqsgmii_speed_set(int port, int speed, int status); +extern void ipq6018_uxsgmii_speed_set(int port, int speed, int duplex, int status); +extern void ppe_port_bridge_txmac_set(int port, int status); +extern void ipq6018_10g_r_speed_set(int port, int status); +extern int phy_status_get_from_ppe(int port_id); + +extern void ipq6018_ppe_acl_set(int rule_id, int rule_type, int pkt_type, int l4_port_no, int l4_port_mask, int permit, int deny); +extern void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode); +#endif /* ___IPQ6018_EDMA__ */ diff --git a/drivers/net/ipq6018/ipq6018_ppe.c b/drivers/net/ipq6018/ipq6018_ppe.c new file mode 100644 index 0000000000..ad2fbc0bb7 --- /dev/null +++ b/drivers/net/ipq6018/ipq6018_ppe.c @@ -0,0 +1,1323 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ************************************************************************** + */ + +#include +#include +#include "ipq6018_ppe.h" +#include "ipq6018_uniphy.h" +#include +#include "ipq_phy.h" + +DECLARE_GLOBAL_DATA_PTR; +#define pr_info(fmt, args...) printf(fmt, ##args); +/* + * ipq6018_ppe_gpio_reg_write() + */ +static inline void ipq6018_ppe_gpio_reg_write(u32 reg, u32 val) +{ + writel(val, IPQ6018_PPE_FPGA_GPIO_BASE_ADDR + reg); +} + +/* + * ipq6018_ppe_reg_read() + */ +static inline void ipq6018_ppe_reg_read(u32 reg, u32 *val) +{ + *val = readl((void *)(IPQ6018_PPE_BASE_ADDR + reg)); +} + +/* + * ipq6018_ppe_reg_write() + */ +static inline void ipq6018_ppe_reg_write(u32 reg, u32 val) +{ + writel(val, (void *)(IPQ6018_PPE_BASE_ADDR + reg)); +} + +void ppe_ipo_rule_reg_set(union ipo_rule_reg_u *hw_reg, int rule_id) +{ + int i; + + for (i = 0; i < 3; i++) { + ipq6018_ppe_reg_write(IPO_CSR_BASE_ADDR + IPO_RULE_REG_ADDRESS + + (rule_id * IPO_RULE_REG_INC) + (i * 4), hw_reg->val[i]); + } +} + +void ppe_ipo_mask_reg_set(union ipo_mask_reg_u *hw_mask, int rule_id) +{ + int i; + + for (i = 0; i < 2; i++) { + ipq6018_ppe_reg_write((IPO_CSR_BASE_ADDR + IPO_MASK_REG_ADDRESS + + (rule_id * IPO_MASK_REG_INC) + (i * 4)), hw_mask->val[i]); + } +} + +void ppe_ipo_action_set(union ipo_action_u *hw_act, int rule_id) +{ + int i; + + for (i = 0; i < 5; i++) { + ipq6018_ppe_reg_write((IPE_L2_BASE_ADDR + IPO_ACTION_ADDRESS + + (rule_id * IPO_ACTION_INC) + (i * 4)), hw_act->val[i]); + } +} + +void ipq6018_ppe_acl_set(int rule_id, int rule_type, int pkt_type, int l4_port_no, int l4_port_mask, int permit, int deny) +{ + union ipo_rule_reg_u hw_reg = {0}; + union ipo_mask_reg_u hw_mask = {0}; + union ipo_action_u hw_act = {0}; + + memset(&hw_reg, 0, sizeof(hw_reg)); + memset(&hw_mask, 0, sizeof(hw_mask)); + memset(&hw_act, 0, sizeof(hw_act)); + + if (rule_id < MAX_RULE) { + if (rule_type == ADPT_ACL_HPPE_IPV4_DIP_RULE) { + hw_reg.bf.rule_type = ADPT_ACL_HPPE_IPV4_DIP_RULE; + hw_reg.bf.rule_field_0 = l4_port_no; + hw_reg.bf.rule_field_1 = pkt_type<<17; + hw_mask.bf.maskfield_0 = l4_port_mask; + hw_mask.bf.maskfield_1 = 7<<17; + if (permit == 0x0) { + hw_act.bf.dest_info_change_en = 1; + hw_act.bf.fwd_cmd = 0;/*forward*/ + hw_reg.bf.pri = 0x1; + } + + if (deny == 0x1) { + hw_act.bf.dest_info_change_en = 1; + hw_act.bf.fwd_cmd = 1;/*drop*/ + hw_reg.bf.pri = 0x0; + + } + hw_reg.bf.src_0 = 0x6; + hw_reg.bf.src_1 = 0x7; + ppe_ipo_rule_reg_set(&hw_reg, rule_id); + ppe_ipo_mask_reg_set(&hw_mask, rule_id); + ppe_ipo_action_set(&hw_act, rule_id); + } + } +} + +/* + * ipq6018_ppe_vp_port_tbl_set() + */ +static void ipq6018_ppe_vp_port_tbl_set(int port, int vsi) +{ + u32 addr = IPQ6018_PPE_L3_VP_PORT_TBL_ADDR + + (port * IPQ6018_PPE_L3_VP_PORT_TBL_INC); + ipq6018_ppe_reg_write(addr, 0x0); + ipq6018_ppe_reg_write(addr + 0x4 , 1 << 9 | vsi << 10); + ipq6018_ppe_reg_write(addr + 0x8, 0x0); +} + +/* + * ipq6018_ppe_ucast_queue_map_tbl_queue_id_set() + */ +static void ipq6018_ppe_ucast_queue_map_tbl_queue_id_set(int queue, int port) +{ + uint32_t val; + + ipq6018_ppe_reg_read(IPQ6018_PPE_QM_UQM_TBL + + (port * IPQ6018_PPE_UCAST_QUEUE_MAP_TBL_INC), &val); + + val |= queue << 4; + + ipq6018_ppe_reg_write(IPQ6018_PPE_QM_UQM_TBL + + (port * IPQ6018_PPE_UCAST_QUEUE_MAP_TBL_INC), val); +} + +/* + * ipq6018_vsi_setup() + */ +static void ipq6018_vsi_setup(int vsi, uint8_t group_mask) +{ + uint32_t val = (group_mask << 24 | group_mask << 16 | group_mask << 8 + | group_mask); + + /* Set mask */ + ipq6018_ppe_reg_write(0x061800 + (vsi * 0x10), val); + + /* new addr lrn en | station move lrn en */ + ipq6018_ppe_reg_write(0x061804 + (vsi * 0x10), 0x9); +} + +/* + * ipq6018_gmac_enable() + */ + +static void ipq6018_gmac_enable(void) +{ + writel(0x0, 0x1008004); +} + +/* + * ipq6018_gmac_port_enable() + */ +static void ipq6018_gmac_port_enable(int port) +{ + ipq6018_ppe_reg_write(IPQ6018_PPE_MAC_ENABLE + (0x200 * port), 0x70); + ipq6018_ppe_reg_write(IPQ6018_PPE_MAC_SPEED + (0x200 * port), 0x2); + ipq6018_ppe_reg_write(IPQ6018_PPE_MAC_MIB_CTL + (0x200 * port), 0x1); +} + +void ipq6018_speed_clock_set(int port, int speed_clock1, int speed_clock2) +{ + int i; + + for (i = 0; i < 2; i++) + { + writel(speed_clock2, GCC_NSS_PORT1_RX_MISC + i*4 + port*0x10); + writel(speed_clock1, GCC_NSS_PORT1_RX_CFG_RCGR + i*8 + port*0x10); + writel(0x1, GCC_NSS_PORT1_RX_CMD_RCGR + i*8 + port*0x10); + } +} + +int phy_status_get_from_ppe(int port_id) +{ + uint32_t reg_field = 0; + + ipq6018_ppe_reg_read(PORT_PHY_STATUS_ADDRESS, ®_field); + if (port_id == (PORT5 - PPE_UNIPHY_INSTANCE1)) + reg_field >>= PORT_PHY_STATUS_PORT5_1_OFFSET; + else + reg_field >>= PORT_PHY_STATUS_PORT6_OFFSET; + + return ((reg_field >> 7) & 0x1) ? 0 : 1; +} + +void ppe_port_bridge_txmac_set(int port_id, int status) +{ + uint32_t reg_value = 0; + + ipq6018_ppe_reg_read(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS + + (port_id * PORT_BRIDGE_CTRL_INC), ®_value); + if (status == 0) + reg_value |= TX_MAC_EN; + else + reg_value &= ~TX_MAC_EN; + + ipq6018_ppe_reg_write(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS + + (port_id * PORT_BRIDGE_CTRL_INC), reg_value); + +} + +void ipq6018_pqsgmii_speed_set(int port, int speed, int status) +{ + ppe_port_bridge_txmac_set(port + 1, status); + ipq6018_ppe_reg_write(IPQ6018_PPE_MAC_SPEED + (0x200 * port), speed); + ipq6018_ppe_reg_write(IPQ6018_PPE_MAC_ENABLE + (0x200 * port), 0x73); +} + + + +void ppe_xgmac_speed_set(uint32_t uniphy_index, int speed) +{ + uint32_t reg_value = 0; + + ipq6018_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), ®_value); + + switch(speed) { + case 0: + case 1: + case 2: + reg_value &=~USS; + reg_value |=SS(XGMAC_SPEED_SELECT_1000M); + break; + case 3: + reg_value |=USS; + reg_value |=SS(XGMAC_SPEED_SELECT_10000M); + break; + case 4: + reg_value |=USS; + reg_value |=SS(XGMAC_SPEED_SELECT_2500M); + break; + case 5: + reg_value |=USS; + reg_value |=SS(XGMAC_SPEED_SELECT_5000M); + break; + } + reg_value |=JD; + ipq6018_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value); + +} + +void ppe_xgmac_10g_r_speed_set(uint32_t uniphy_index) +{ + uint32_t reg_value = 0; + + ipq6018_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), ®_value); + + reg_value |=JD; + ipq6018_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value); + +} + +void ppe_port_txmac_status_set(uint32_t uniphy_index) +{ + uint32_t reg_value = 0; + + ipq6018_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), ®_value); + + reg_value |=TE; + ipq6018_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value); + +} + +void ppe_port_rxmac_status_set(uint32_t uniphy_index) +{ + uint32_t reg_value = 0; + + ipq6018_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + MAC_RX_CONFIGURATION_ADDRESS + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION), ®_value); + + reg_value |= 0x5ee00c0; + reg_value |=RE; + reg_value |=ACS; + reg_value |=CST; + ipq6018_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + MAC_RX_CONFIGURATION_ADDRESS + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION), reg_value); + +} + +void ppe_mac_packet_filter_set(uint32_t uniphy_index) +{ + ipq6018_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + MAC_PACKET_FILTER_ADDRESS + + (uniphy_index * MAC_PACKET_FILTER_INC), 0x81); +} + +void ipq6018_10g_r_speed_set(int port, int status) +{ + uint32_t uniphy_index; + + /* Setting the speed only for PORT5 and PORT6 */ + if (port == (PORT5 - PPE_UNIPHY_INSTANCE1)) + uniphy_index = PPE_UNIPHY_INSTANCE1; + else if (port == (PORT6 - PPE_UNIPHY_INSTANCE1)) + uniphy_index = PPE_UNIPHY_INSTANCE2; + else + return; + + ppe_xgmac_10g_r_speed_set(uniphy_index - 1); + ppe_port_bridge_txmac_set(port + 1, status); + ppe_port_txmac_status_set(uniphy_index - 1); + ppe_port_rxmac_status_set(uniphy_index - 1); + ppe_mac_packet_filter_set(uniphy_index - 1); +} + +void ipq6018_uxsgmii_speed_set(int port, int speed, int duplex, + int status) +{ + uint32_t uniphy_index; + + /* Setting the speed only for PORT5 and PORT6 */ + if (port == (PORT5 - PPE_UNIPHY_INSTANCE1)) + uniphy_index = PPE_UNIPHY_INSTANCE1; + else if (port == (PORT6 - PPE_UNIPHY_INSTANCE1)) + uniphy_index = PPE_UNIPHY_INSTANCE2; + else + return; + + ppe_uniphy_usxgmii_autoneg_completed(uniphy_index); + ppe_uniphy_usxgmii_speed_set(uniphy_index, speed); + ppe_xgmac_speed_set(uniphy_index - 1, speed); + ppe_uniphy_usxgmii_duplex_set(uniphy_index, duplex); + ppe_uniphy_usxgmii_port_reset(uniphy_index); + ppe_port_bridge_txmac_set(port + 1, status); + ppe_port_txmac_status_set(uniphy_index - 1); + ppe_port_rxmac_status_set(uniphy_index - 1); + ppe_mac_packet_filter_set(uniphy_index - 1); +} +/* + * ipq6018_ppe_flow_port_map_tbl_port_num_set() + */ +static void ipq6018_ppe_flow_port_map_tbl_port_num_set(int queue, int port) +{ + ipq6018_ppe_reg_write(IPQ6018_PPE_L0_FLOW_PORT_MAP_TBL + + queue * IPQ6018_PPE_L0_FLOW_PORT_MAP_TBL_INC, port); + ipq6018_ppe_reg_write(IPQ6018_PPE_L1_FLOW_PORT_MAP_TBL + + port * IPQ6018_PPE_L1_FLOW_PORT_MAP_TBL_INC, port); +} + +/* + * ipq6018_ppe_flow_map_tbl_set() + */ +static void ipq6018_ppe_flow_map_tbl_set(int queue, int port) +{ + uint32_t val = port | 0x401000; /* c_drr_wt = 1, e_drr_wt = 1 */ + ipq6018_ppe_reg_write(IPQ6018_PPE_L0_FLOW_MAP_TBL + queue * IPQ6018_PPE_L0_FLOW_MAP_TBL_INC, + val); + + val = port | 0x100400; /* c_drr_wt = 1, e_drr_wt = 1 */ + ipq6018_ppe_reg_write(IPQ6018_PPE_L1_FLOW_MAP_TBL + port * IPQ6018_PPE_L1_FLOW_MAP_TBL_INC, + val); +} + +/* + * ipq6018_ppe_tdm_configuration + */ +static void ipq6018_ppe_tdm_configuration(void) +{ + int i = 0; + + /* + * TDM is configured with instructions for each tick + * Port/action are configured as given below + * + * 0x5:0x5 TDM_CFG_VALID 0:idle tick + * 0x4:0x4 TDM_CFG_DIR 0:ingress wr + * 1:egress rd + * 0x3:0x0 TDM_CFG_PORT_NUM 0:DMA + * 1~4:Ethernet 1G + * 5~6:Ethernet 5G + * 7~8:Security0/1 + */ + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_QCOM1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_QCOM3); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_QCOM2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_QCOM4); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID + | IPQ6018_PPE_TDM_CFG_DIR_EGRESS + | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_QCOM1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_QCOM3); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_QCOM2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_QCOM4); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_INGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ6018_PPE_TDM_CFG_VALID | + IPQ6018_PPE_TDM_CFG_DIR_EGRESS | + IPQ6018_PPE_PORT_CRYPTO1); + + /* Set TDM Depth to 100 entries */ + ipq6018_ppe_reg_write(IPQ6018_PPE_TDM_CFG_DEPTH_OFFSET, IPQ6018_PPE_TDM_CFG_DEPTH_VAL); +} + +/* + * ipq6018_ppe_sched_configuration + */ +static void ipq6018_ppe_sched_configuration(void) +{ + int i = 0; + + /* + * PSCH_TDM_CFG_TBL_DES_PORT : determine which egress port traffic + * will be selected and transmitted out + * PSCH_TDM_CFG_TBL_ENS_PORT : determine which port’s queue need + * to be linked to scheduler at the current tick + * PSCH_TDM_CFG_TBL_ENS_PORT_BITMAP : determine port bitmap + * for source of queue + * + * 0xf:0x8 PSCH_TDM_CFG_TBL_ENS_PORT_BITMAP 1110_1110 + * (Port:765-432) + * + * 0x7:0x4 PSCH_TDM_CFG_TBL_ENS_PORT 0:DMA + * 1~4:Ethernet 1G + * 5~6:Ethernet 5G + * 7~8:Security0/1 + * + * 0x3:0x0 PSCH_TDM_CFG_TBL_DES_PORT 0:DMA + * 1~4:Ethernet 1G + * 5~6:Ethernet 5G + * 7~8:Security0/1 + * + * For eg, 0xee60 =((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + * IPQ6018_PPE_PORT_XGMAC1_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + * IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + * IPQ6018_PPE_PORT_XGMAC2 | IPQ6018_PPE_PORT_EDMA); + */ + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_XGMAC1_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM3_BITPOS | IPQ6018_PPE_PORT_QCOM2_BITPOS | + IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM4 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_QCOM4_BITPOS | + IPQ6018_PPE_PORT_QCOM3_BITPOS | IPQ6018_PPE_PORT_QCOM2_BITPOS | + IPQ6018_PPE_PORT_QCOM1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_XGMAC2_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_CRYPTO1 << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_QCOM1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_QCOM2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_XGMAC1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_XGMAC2_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_CRYPTO1 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_QCOM3); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM3 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_XGMAC1_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_QCOM4); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_XGMAC2_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM4 << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_XGMAC2_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_CRYPTO1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_QCOM2_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_QCOM1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM1 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_QCOM2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_XGMAC2_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM2 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_XGMAC1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_CRYPTO1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_XGMAC2_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_CRYPTO1 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_QCOM3); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC2 << 4) | IPQ6018_PPE_PORT_EDMA); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC2_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_QCOM3 << 4) | IPQ6018_PPE_PORT_XGMAC1); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_EDMA_BITPOS | + IPQ6018_PPE_PORT_QCOM4_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_EDMA << 4) | IPQ6018_PPE_PORT_XGMAC2); + ipq6018_ppe_reg_write(IPQ6018_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ6018_PPE_PORT_CRYPTO1_BITPOS | IPQ6018_PPE_PORT_XGMAC1_BITPOS | + IPQ6018_PPE_PORT_EDMA_BITPOS | IPQ6018_PPE_PORT_QCOM3_BITPOS | + IPQ6018_PPE_PORT_QCOM2_BITPOS | IPQ6018_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ6018_PPE_PORT_XGMAC1 << 4) | IPQ6018_PPE_PORT_QCOM4); + + /* Set Sched Depth to 50 entries */ + ipq6018_ppe_reg_write(IPQ6018_PPE_TDM_SCHED_DEPTH_OFFSET, IPQ6018_PPE_TDM_SCHED_DEPTH_VAL); +} + +/* + * ipq6018_ppe_c_sp_cfg_tbl_drr_id_set + */ +static void ipq6018_ppe_c_sp_cfg_tbl_drr_id_set(int id) +{ + ipq6018_ppe_reg_write(IPQ6018_PPE_L0_C_SP_CFG_TBL + (id * 0x80), id * 2); + ipq6018_ppe_reg_write(IPQ6018_PPE_L1_C_SP_CFG_TBL + (id * 0x80), id * 2); +} + +/* + * ipq6018_ppe_e_sp_cfg_tbl_drr_id_set + */ +static void ipq6018_ppe_e_sp_cfg_tbl_drr_id_set(int id) +{ + ipq6018_ppe_reg_write(IPQ6018_PPE_L0_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1); + ipq6018_ppe_reg_write(IPQ6018_PPE_L1_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1); +} + +static void ppe_port_mux_set(int port_id, int port_type, int mode) +{ + union port_mux_ctrl_u port_mux_ctrl; + + ipq6018_ppe_reg_read(IPQ6018_PORT_MUX_CTRL, &(port_mux_ctrl.val)); + port_mux_ctrl.bf.port4_pcs_sel = PORT4_PCS_SEL_GMII_FROM_PCS0; + if (port_id == PORT5) { + if (port_type == PORT_GMAC_TYPE) { + if (mode == PORT_WRAPPER_SGMII_PLUS) + port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS1; + else + port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS0; + port_mux_ctrl.bf.port5_gmac_sel = PORT5_GMAC_SEL_GMAC; + } else if (port_type == PORT_XGMAC_TYPE) { + port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS1; + port_mux_ctrl.bf.port5_gmac_sel = PORT5_GMAC_SEL_XGMAC; + } + } else if (port_id == PORT6) { + if (port_type == PORT_GMAC_TYPE) { + port_mux_ctrl.bf.port6_pcs_sel = PORT6_PCS_SEL_GMII_FROM_PCS2; + port_mux_ctrl.bf.port6_gmac_sel = PORT6_GMAC_SEL_GMAC; + } else if (port_type == PORT_XGMAC_TYPE) { + port_mux_ctrl.bf.port6_pcs_sel = PORT6_PCS_SEL_GMII_FROM_PCS2; + port_mux_ctrl.bf.port6_gmac_sel = PORT6_GMAC_SEL_XGMAC; + } + } else + return; + + ipq6018_ppe_reg_write(IPQ6018_PORT_MUX_CTRL, port_mux_ctrl.val); +} + +static void ppe_port_mux_mac_type_set(int port_id, int mode) +{ + uint32_t port_type; + + switch(mode) + { + case PORT_WRAPPER_SGMII0_RGMII4: + port_type = PORT_GMAC_TYPE; + break; + case PORT_WRAPPER_SGMII_PLUS: + port_type = PORT_GMAC_TYPE; + break; + case PORT_WRAPPER_USXGMII: + port_type = PORT_XGMAC_TYPE; + break; + case PORT_WRAPPER_10GBASE_R: + port_type = PORT_XGMAC_TYPE; + break; + default: + return; + } + ppe_port_mux_set(port_id, port_type, mode); +} + + + +void ipq6018_ppe_interface_mode_init(void) +{ + uint32_t mode0, mode1, mode2; + int node; + + node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + if (node < 0) { + printf("Error: ess-switch not specified in dts"); + return; + } + + mode0 = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode", -1); + if (mode0 < 0) { + printf("Error: switch_mac_mode not specified in dts"); + return; + } + + mode1 = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode1", -1); + if (mode1 < 0) { + printf("Error: switch_mac_mode1 not specified in dts"); + return; + } + mode2 = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode2", -1); + if (mode2 < 0) { + printf("Error: switch_mac_mode2 not specified in dts"); + return; + } + + ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE0, mode0); + ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE1, mode1); + ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE2, mode2); + + /* Port 1-4 are used mac type as GMAC by default but Port5 and Port6 + * can be used as GMAC or XGMAC */ + ppe_port_mux_mac_type_set(PORT5, mode1); + ppe_port_mux_mac_type_set(PORT6, mode2); +} + +/* + * ipq6018_ppe_provision_init() + */ +void ipq6018_ppe_provision_init(void) +{ + int i; + uint32_t queue; + + /* Port4 Port5, Port6 port mux configuration, all GMAC */ + writel(0x3b, 0x3a000010); + + /* tdm/sched configuration */ + ipq6018_ppe_tdm_configuration(); + ipq6018_ppe_sched_configuration(); + + ipq6018_gmac_enable(); + + /* disable clock gating */ + ipq6018_ppe_reg_write(0x000008, 0x0); + + /* flow ctrl disable */ + ipq6018_ppe_reg_write(0x200368, 0xc88); + +#ifdef CONFIG_IPQ6018_BRIDGED_MODE + /* Add CPU port 0 to VSI 2 */ + ipq6018_ppe_vp_port_tbl_set(0, 2); + + /* Add port 1 - 4 to VSI 2 */ + ipq6018_ppe_vp_port_tbl_set(1, 2); + ipq6018_ppe_vp_port_tbl_set(2, 2); + ipq6018_ppe_vp_port_tbl_set(3, 2); + ipq6018_ppe_vp_port_tbl_set(4, 2); + ipq6018_ppe_vp_port_tbl_set(5, 2); + ipq6018_ppe_vp_port_tbl_set(6, 2); + +#else + ipq6018_ppe_vp_port_tbl_set(1, 2); + ipq6018_ppe_vp_port_tbl_set(2, 3); + ipq6018_ppe_vp_port_tbl_set(3, 4); + ipq6018_ppe_vp_port_tbl_set(4, 5); +#endif + + /* Unicast priority map */ + ipq6018_ppe_reg_write(IPQ6018_PPE_QM_UPM_TBL, 0); + + /* Port0 - 7 unicast queue settings */ + for (i = 0; i < 8; i++) { + if (i == 0) + queue = 0; + else + queue = ((i * 0x10) + 0x70); + + ipq6018_ppe_ucast_queue_map_tbl_queue_id_set(queue, i); + ipq6018_ppe_flow_port_map_tbl_port_num_set(queue, i); + ipq6018_ppe_flow_map_tbl_set(queue, i); + ipq6018_ppe_c_sp_cfg_tbl_drr_id_set(i); + ipq6018_ppe_e_sp_cfg_tbl_drr_id_set(i); + } + + /* Port0 multicast queue */ + ipq6018_ppe_reg_write(0x409000, 0x00000000); + ipq6018_ppe_reg_write(0x403000, 0x00401000); + + /* Port1 - 7 multicast queue */ + for (i = 1; i < 8; i++) { + ipq6018_ppe_reg_write(0x409100 + ((i - 1) * 0x40), i); + ipq6018_ppe_reg_write(0x403100 + ((i - 1) * 0x40), 0x401000 | i); + } + + /* + * Port0 - Port7 learn enable and isolation port bitmap and TX_EN + * Here please pay attention on bit16 (TX_EN) is not set on port7 + */ + for (i = 0; i < 7; i++) + ipq6018_ppe_reg_write(IPQ6018_PPE_PORT_BRIDGE_CTRL_OFFSET + (i * 4), + IPQ6018_PPE_PORT_BRIDGE_CTRL_PROMISC_EN | + IPQ6018_PPE_PORT_BRIDGE_CTRL_TXMAC_EN | + IPQ6018_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP | + IPQ6018_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN | + IPQ6018_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN); + + ipq6018_ppe_reg_write(IPQ6018_PPE_PORT_BRIDGE_CTRL_OFFSET + (7 * 4), + IPQ6018_PPE_PORT_BRIDGE_CTRL_PROMISC_EN | + IPQ6018_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP | + IPQ6018_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN | + IPQ6018_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN); + + /* Global learning */ + ipq6018_ppe_reg_write(0x060038, 0xc0); + +#ifdef CONFIG_IPQ6018_BRIDGED_MODE + ipq6018_vsi_setup(2, 0x7f); +#else + ipq6018_vsi_setup(2, 0x03); + ipq6018_vsi_setup(3, 0x05); + ipq6018_vsi_setup(4, 0x09); + ipq6018_vsi_setup(5, 0x11); +#endif + + /* Port 0-7 STP */ + for (i = 0; i < 8; i++) + ipq6018_ppe_reg_write(IPQ6018_PPE_STP_BASE + (0x4 * i), 0x3); + + ipq6018_ppe_interface_mode_init(); + /* Port 0-5 enable */ + for (i = 0; i < 6; i++) { + ipq6018_gmac_port_enable(i); + ppe_port_bridge_txmac_set(i + 1, 1); + } + + /* Allowing DHCP packets */ + ipq6018_ppe_acl_set(0, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 67, 0xffff, 0, 0); + ipq6018_ppe_acl_set(1, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 68, 0xffff, 0, 0); + /* Dropping all the UDP packets */ + ipq6018_ppe_acl_set(2, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 0, 0, 0, 1); +} diff --git a/drivers/net/ipq6018/ipq6018_ppe.h b/drivers/net/ipq6018/ipq6018_ppe.h new file mode 100644 index 0000000000..9f192dd5ec --- /dev/null +++ b/drivers/net/ipq6018/ipq6018_ppe.h @@ -0,0 +1,251 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define GCC_NSS_PORT1_RX_CMD_RCGR 0x01868020 +#define GCC_NSS_PORT1_RX_CFG_RCGR 0x01868024 +#define GCC_NSS_PORT1_RX_MISC 0x01868400 + +#define IPQ6018_PPE_BASE_ADDR 0x3a000000 +#define IPQ6018_PPE_REG_SIZE 0x1000000 + +#define PORT5 5 +#define PORT6 6 +#define PORT_GMAC_TYPE 1 +#define PORT_XGMAC_TYPE 2 +struct port_mux_ctrl { + uint32_t port4_pcs_sel:1; + uint32_t port5_pcs_sel:2; + uint32_t port5_gmac_sel:1; + uint32_t port6_pcs_sel:1; + uint32_t port6_gmac_sel:1; + uint32_t _reserved0:26; +}; +union port_mux_ctrl_u { + uint32_t val; + struct port_mux_ctrl bf; +}; + +enum { + TCP_PKT, + UDP_PKT, +}; + +#define ADPT_ACL_HPPE_IPV4_DIP_RULE 4 +#define MAX_RULE 512 + +struct ipo_rule_reg { + uint32_t rule_field_0:32; + uint32_t rule_field_1:20; + uint32_t fake_mac_header:1; + uint32_t range_en:1; + uint32_t inverse_en:1; + uint32_t rule_type:4; + uint32_t src_type:2; + uint32_t src_0:3; + uint32_t src_1:5; + uint32_t pri:9; + uint32_t res_chain:1; + uint32_t post_routing_en:1; + uint32_t _reserved0:16; +}; + +union ipo_rule_reg_u { + uint32_t val[3]; + struct ipo_rule_reg bf; +}; + +struct ipo_mask_reg { + uint32_t maskfield_0:32; + uint32_t maskfield_1:21; + uint32_t _reserved0:11; +}; + +union ipo_mask_reg_u { + uint32_t val[2]; + struct ipo_mask_reg bf; +}; + +struct ipo_action { + uint32_t dest_info_change_en:1; + uint32_t fwd_cmd:2; + uint32_t _reserved0:29; + uint32_t _reserved1:32; + uint32_t _reserved2:32; + uint32_t _reserved3:32; + uint32_t _reserved4:32; +}; + +union ipo_action_u { + uint32_t val[5]; + struct ipo_action bf; +}; + +#define IPQ6018_PORT_MUX_CTRL 0x10 +#define PORT4_PCS_SEL_GMII_FROM_PCS0 1 +#define PORT4_PCS_SEL_RGMII 0 +#define PORT5_PCS_SEL_RGMII 0 +#define PORT5_PCS_SEL_GMII_FROM_PCS0 1 +#define PORT5_PCS_SEL_GMII_FROM_PCS1 2 +#define PORT5_GMAC_SEL_GMAC 1 +#define PORT5_GMAC_SEL_XGMAC 0 +#define PORT6_PCS_SEL_RGMII 0 +#define PORT6_PCS_SEL_GMII_FROM_PCS2 1 +#define PORT6_GMAC_SEL_GMAC 1 +#define PORT6_GMAC_SEL_XGMAC 0 + +#define PORT_PHY_STATUS_ADDRESS 0x44 +#define PORT_PHY_STATUS_PORT5_1_OFFSET 8 +#define PORT_PHY_STATUS_PORT6_OFFSET 16 + +#define IPQ6018_PPE_IPE_L3_BASE_ADDR 0x200000 +#define IPQ6018_PPE_L3_VP_PORT_TBL_ADDR (IPQ6018_PPE_IPE_L3_BASE_ADDR + 0x1000) +#define IPQ6018_PPE_L3_VP_PORT_TBL_INC 0x10 + +#define IPQ6018_PPE_QUEUE_MANAGER_BASE_ADDR 0x800000 +#define IPQ6018_PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x10000 +#define IPQ6018_PPE_UCAST_QUEUE_MAP_TBL_INC 0x10 +#define IPQ6018_PPE_QM_UQM_TBL (IPQ6018_PPE_QUEUE_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_UCAST_QUEUE_MAP_TBL_ADDR) +#define IPQ6018_PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x42000 +#define IPQ6018_PPE_QM_UPM_TBL (IPQ6018_PPE_QUEUE_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_UCAST_PRIORITY_MAP_TBL_ADDR) + +#define IPQ6018_PPE_STP_BASE 0x060100 +#define IPQ6018_PPE_MAC_ENABLE 0x001000 +#define IPQ6018_PPE_MAC_SPEED 0x001004 +#define IPQ6018_PPE_MAC_MIB_CTL 0x001034 + +#define IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR 0x400000 + +#define IPQ6018_PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x8000 +#define IPQ6018_PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10 +#define IPQ6018_PPE_L0_FLOW_PORT_MAP_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L0_FLOW_PORT_MAP_TBL_ADDR) + +#define IPQ6018_PPE_L0_FLOW_MAP_TBL_ADDR 0x2000 +#define IPQ6018_PPE_L0_FLOW_MAP_TBL_INC 0x10 +#define IPQ6018_PPE_L0_FLOW_MAP_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L0_FLOW_MAP_TBL_ADDR) + +#define IPQ6018_PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x46000 +#define IPQ6018_PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10 +#define IPQ6018_PPE_L1_FLOW_PORT_MAP_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L1_FLOW_PORT_MAP_TBL_ADDR) + +#define IPQ6018_PPE_L1_FLOW_MAP_TBL_ADDR 0x40000 +#define IPQ6018_PPE_L1_FLOW_MAP_TBL_INC 0x10 +#define IPQ6018_PPE_L1_FLOW_MAP_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L1_FLOW_MAP_TBL_ADDR) + +#define IPQ6018_PPE_L0_C_SP_CFG_TBL_ADDR 0x4000 +#define IPQ6018_PPE_L0_C_SP_CFG_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L0_C_SP_CFG_TBL_ADDR) + +#define IPQ6018_PPE_L1_C_SP_CFG_TBL_ADDR 0x42000 +#define IPQ6018_PPE_L1_C_SP_CFG_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L1_C_SP_CFG_TBL_ADDR) + +#define IPQ6018_PPE_L0_E_SP_CFG_TBL_ADDR 0x6000 +#define IPQ6018_PPE_L0_E_SP_CFG_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L0_E_SP_CFG_TBL_ADDR) + +#define IPQ6018_PPE_L1_E_SP_CFG_TBL_ADDR 0x44000 +#define IPQ6018_PPE_L1_E_SP_CFG_TBL (IPQ6018_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ6018_PPE_L1_E_SP_CFG_TBL_ADDR) + +#define IPQ6018_PPE_FPGA_GPIO_BASE_ADDR 0x01008000 + +#define IPQ6018_PPE_MAC_PORT_MUX_OFFSET 0x10 +#define IPQ6018_PPE_FPGA_GPIO_OFFSET 0xc000 +#define IPQ6018_PPE_FPGA_SCHED_OFFSET 0x47a000 +#define IPQ6018_PPE_TDM_CFG_DEPTH_OFFSET 0xb000 +#define IPQ6018_PPE_TDM_SCHED_DEPTH_OFFSET 0x400000 +#define IPQ6018_PPE_PORT_BRIDGE_CTRL_OFFSET 0x060300 + +#define IPQ6018_PPE_TDM_CFG_DEPTH_VAL 0x80000064 +#define IPQ6018_PPE_MAC_PORT_MUX_OFFSET_VAL 0x15 +#define IPQ6018_PPE_TDM_SCHED_DEPTH_VAL 0x32 +#define IPQ6018_PPE_TDM_CFG_VALID 0x20 +#define IPQ6018_PPE_TDM_CFG_DIR_INGRESS 0x0 +#define IPQ6018_PPE_TDM_CFG_DIR_EGRESS 0x10 +#define IPQ6018_PPE_PORT_EDMA 0x0 +#define IPQ6018_PPE_PORT_QCOM1 0x1 +#define IPQ6018_PPE_PORT_QCOM2 0x2 +#define IPQ6018_PPE_PORT_QCOM3 0x3 +#define IPQ6018_PPE_PORT_QCOM4 0x4 +#define IPQ6018_PPE_PORT_XGMAC1 0x5 +#define IPQ6018_PPE_PORT_XGMAC2 0x6 +#define IPQ6018_PPE_PORT_CRYPTO1 0x7 +#define IPQ6018_PPE_PORT_BRIDGE_CTRL_PROMISC_EN 0x20000 +#define IPQ6018_PPE_PORT_BRIDGE_CTRL_TXMAC_EN 0x10000 +#define IPQ6018_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP 0x7f00 +#define IPQ6018_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN 0x8 +#define IPQ6018_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN 0x1 + +#define IPQ6018_PPE_PORT_EDMA_BITPOS 0x1 +#define IPQ6018_PPE_PORT_QCOM1_BITPOS (1 << IPQ6018_PPE_PORT_QCOM1) +#define IPQ6018_PPE_PORT_QCOM2_BITPOS (1 << IPQ6018_PPE_PORT_QCOM2) +#define IPQ6018_PPE_PORT_QCOM3_BITPOS (1 << IPQ6018_PPE_PORT_QCOM3) +#define IPQ6018_PPE_PORT_QCOM4_BITPOS (1 << IPQ6018_PPE_PORT_QCOM4) +#define IPQ6018_PPE_PORT_XGMAC1_BITPOS (1 << IPQ6018_PPE_PORT_XGMAC1) +#define IPQ6018_PPE_PORT_XGMAC2_BITPOS (1 << IPQ6018_PPE_PORT_XGMAC2) +#define IPQ6018_PPE_PORT_CRYPTO1_BITPOS (1 << IPQ6018_PPE_PORT_CRYPTO1) + +#define PPE_SWITCH_NSS_SWITCH_XGMAC0 0x3000 +#define NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION 0x4000 +#define USS (1 << 31) +#define SS(i) (i << 29) +#define JD (1 << 16) +#define TE (1 << 0) +#define NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION 0x4000 +#define MAC_RX_CONFIGURATION_ADDRESS 0x4 +#define RE (1 << 0) +#define ACS (1 << 1) +#define CST (1 << 2) +#define MAC_PACKET_FILTER_INC 0x4000 +#define MAC_PACKET_FILTER_ADDRESS 0x8 + +#define XGMAC_SPEED_SELECT_10000M 0 +#define XGMAC_SPEED_SELECT_5000M 1 +#define XGMAC_SPEED_SELECT_2500M 2 +#define XGMAC_SPEED_SELECT_1000M 3 + +#define IPE_L2_BASE_ADDR 0x060000 +#define PORT_BRIDGE_CTRL_ADDRESS 0x300 +#define PORT_BRIDGE_CTRL_INC 0x4 +#define TX_MAC_EN (1 << 16) + +#define IPO_CSR_BASE_ADDR 0x0b0000 + +#define IPO_RULE_REG_ADDRESS 0x0 +#define IPO_RULE_REG_INC 0x10 + +#define IPO_MASK_REG_ADDRESS 0x2000 +#define IPO_MASK_REG_INC 0x10 + +#define IPO_ACTION_ADDRESS 0x8000 +#define IPO_ACTION_INC 0x20 diff --git a/drivers/net/ipq6018/ipq6018_uniphy.c b/drivers/net/ipq6018/ipq6018_uniphy.c new file mode 100644 index 0000000000..64a9a6048e --- /dev/null +++ b/drivers/net/ipq6018/ipq6018_uniphy.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipq6018_edma.h" +#include "ipq6018_uniphy.h" +#include "ipq_phy.h" + +extern int ipq_mdio_write(int mii_id, + int regnum, u16 value); +extern int ipq_mdio_read(int mii_id, + int regnum, ushort *data); +extern void qca8075_phy_serdes_reset(u32 phy_id); + +void csr1_write(int phy_id, int addr, int value) +{ + int addr_h, addr_l, ahb_h, ahb_l, phy; + phy=phy_id<<(0x10); + addr_h=(addr&0xffffff)>>8; + addr_l=((addr&0xff)<<2)|(0x20<<(0xa)); + ahb_l=(addr_l&0xffff)|(0x7A00000|phy); + ahb_h=(0x7A083FC|phy); + writel(addr_h,ahb_h); + writel(value,ahb_l); +} + +int csr1_read(int phy_id, int addr ) +{ + int addr_h ,addr_l,ahb_h, ahb_l, phy; + phy=phy_id<<(0x10); + addr_h=(addr&0xffffff)>>8; + addr_l=((addr&0xff)<<2)|(0x20<<(0xa)); + ahb_l=(addr_l&0xffff)|(0x7A00000|phy); + ahb_h=(0x7A083FC|phy); + writel(addr_h, ahb_h); + return readl(ahb_l); +} + +static int ppe_uniphy_calibration(uint32_t uniphy_index) +{ + int retries = 100, calibration_done = 0; + uint32_t reg_value = 0; + + while(calibration_done != UNIPHY_CALIBRATION_DONE) { + mdelay(1); + if (retries-- == 0) { + printf("uniphy callibration time out!\n"); + return -1; + } + reg_value = readl(PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_OFFSET_CALIB_4); + calibration_done = (reg_value >> 0x7) & 0x1; + } + + return 0; +} + +static void ppe_gcc_uniphy_xpcs_reset(uint32_t uniphy_index, bool enable) +{ + uint32_t reg_value; + + if(enable) + reg_value = GCC_UNIPHY_USXGMII_XPCS_RESET; + else + reg_value = GCC_UNIPHY_USXGMII_XPCS_RELEASE_RESET; + + writel(reg_value, GCC_UNIPHY0_MISC + (uniphy_index * GCC_UNIPHY_REG_INC)); +} + +static void ppe_gcc_uniphy_soft_reset(uint32_t uniphy_index) +{ + uint32_t reg_value; + + reg_value = readl(GCC_UNIPHY0_MISC + (uniphy_index * GCC_UNIPHY_REG_INC)); + if (uniphy_index == PPE_UNIPHY_INSTANCE0) + reg_value |= GCC_UNIPHY_PSGMII_SOFT_RESET; + else + reg_value = GCC_UNIPHY_USXGMII_SOFT_RESET; + + writel(reg_value, GCC_UNIPHY0_MISC + (uniphy_index * GCC_UNIPHY_REG_INC)); + udelay(500); + if (uniphy_index == PPE_UNIPHY_INSTANCE0) + reg_value &= ~GCC_UNIPHY_PSGMII_SOFT_RESET; + else + reg_value = GCC_UNIPHY_USXGMII_XPCS_RESET; + + writel(reg_value, GCC_UNIPHY0_MISC + (uniphy_index * GCC_UNIPHY_REG_INC)); +} + +static void ppe_uniphy_psgmii_mode_set(uint32_t uniphy_index) +{ + ppe_gcc_uniphy_xpcs_reset(uniphy_index, true); + writel(0x220, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + ppe_gcc_uniphy_soft_reset(uniphy_index); + ppe_uniphy_calibration(uniphy_index); + qca8075_phy_serdes_reset(0); +} + +static void ppe_uniphy_qsgmii_mode_set(uint32_t uniphy_index) +{ + ppe_gcc_uniphy_xpcs_reset(uniphy_index, true); + writel(0x120, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + ppe_gcc_uniphy_soft_reset(uniphy_index); +} + +static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t channel) +{ + uint32_t reg_value; + + writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET); + writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET); + udelay(500); + writel(UNIPHY_PLL_RESET_REG_DEFAULT_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET); + ppe_gcc_uniphy_xpcs_reset(uniphy_index, true); + + reg_value = readl( PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + reg_value &= ~(UNIPHY_CH0_ATHR_CSCO_MODE_25M | UNIPHY_CH0_PSGMII_QSGMII); + if (uniphy_index == PPE_UNIPHY_INSTANCE0) { + reg_value &= ~UNIPHY_SG_MODE; + if (channel == 0) { + reg_value &= ~UNIPHY_CH1_CH0_SGMII; + reg_value &= ~UNIPHY_CH4_CH1_0_SGMII; + } else if (channel == 1) { + reg_value |= UNIPHY_CH1_CH0_SGMII; + reg_value &= ~UNIPHY_CH4_CH1_0_SGMII; + } else if (channel == 4) { + reg_value &= ~UNIPHY_CH1_CH0_SGMII; + reg_value |= UNIPHY_CH4_CH1_0_SGMII; + } + } else { + reg_value &= ~UNIPHY_SG_PLUS_MODE; + reg_value |= UNIPHY_SG_MODE; + } + writel(reg_value, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + ppe_gcc_uniphy_soft_reset(uniphy_index); +} + +static void ppe_uniphy_sgmii_plus_mode_set(uint32_t uniphy_index) +{ + writel(UNIPHY_MISC2_REG_SGMII_PLUS_MODE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET); + writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET); + udelay(500); + writel(UNIPHY_PLL_RESET_REG_DEFAULT_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET); + ppe_gcc_uniphy_xpcs_reset(uniphy_index, true); + + writel(0x800, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + ppe_gcc_uniphy_soft_reset(uniphy_index); + ppe_uniphy_calibration(uniphy_index); +} + +static int ppe_uniphy_10g_r_linkup(uint32_t uniphy_index) +{ + uint32_t reg_value = 0; + uint32_t retries = 100, linkup = 0; + + while (linkup != UNIPHY_10GR_LINKUP) { + mdelay(1); + if (retries-- == 0) + return -1; + reg_value = csr1_read(uniphy_index, SR_XS_PCS_KR_STS1_ADDRESS); + linkup = (reg_value >> 12) & UNIPHY_10GR_LINKUP; + } + mdelay(10); + return 0; +} + +static void ppe_uniphy_10g_r_mode_set(uint32_t uniphy_index) +{ + ppe_gcc_uniphy_xpcs_reset(uniphy_index, true); + writel(0x1021, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + writel(0x1C0, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + UNIPHY_INSTANCE_LINK_DETECT); + ppe_gcc_uniphy_soft_reset(uniphy_index); + ppe_uniphy_calibration(uniphy_index); + ppe_gcc_uniphy_xpcs_reset(uniphy_index, false); +} + + +static void ppe_uniphy_usxgmii_mode_set(uint32_t uniphy_index) +{ + uint32_t reg_value = 0; + + writel(UNIPHY_MISC2_REG_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET); + writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET); + mdelay(500); + writel(UNIPHY_PLL_RESET_REG_DEFAULT_VALUE, PPE_UNIPHY_BASE + + (uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET); + mdelay(500); + ppe_gcc_uniphy_xpcs_reset(uniphy_index, true); + writel(0x1021, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + ppe_gcc_uniphy_soft_reset(uniphy_index); + ppe_uniphy_calibration(uniphy_index); + ppe_gcc_uniphy_xpcs_reset(uniphy_index, false); + ppe_uniphy_10g_r_linkup(uniphy_index); + reg_value = csr1_read(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS); + reg_value |= USXG_EN; + csr1_write(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS, reg_value); + reg_value = csr1_read(uniphy_index, VR_MII_AN_CTRL_ADDRESS); + reg_value |= MII_AN_INTR_EN; + reg_value |= MII_CTRL; + csr1_write(uniphy_index, VR_MII_AN_CTRL_ADDRESS, reg_value); + reg_value = csr1_read(uniphy_index, SR_MII_CTRL_ADDRESS); + reg_value |= AN_ENABLE; + reg_value &= ~SS5; + reg_value |= SS6 | SS13 | DUPLEX_MODE; + csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value); + if (uniphy_index == PPE_UNIPHY_INSTANCE2); + ipq_mdio_write(0x7, ((1<<30) | (4<<16) | 0xc441), 8); +} + +void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode) +{ + switch(mode) { + case PORT_WRAPPER_PSGMII: + ppe_uniphy_psgmii_mode_set(uniphy_index); + break; + case PORT_WRAPPER_QSGMII: + ppe_uniphy_qsgmii_mode_set(uniphy_index); + break; + case PORT_WRAPPER_SGMII0_RGMII4: + ppe_uniphy_sgmii_mode_set(uniphy_index, 0); + break; + case PORT_WRAPPER_SGMII1_RGMII4: + ppe_uniphy_sgmii_mode_set(uniphy_index, 1); + break; + case PORT_WRAPPER_SGMII4_RGMII4: + ppe_uniphy_sgmii_mode_set(uniphy_index, 4); + break; + case PORT_WRAPPER_SGMII_PLUS: + ppe_uniphy_sgmii_plus_mode_set(uniphy_index); + break; + case PORT_WRAPPER_USXGMII: + ppe_uniphy_usxgmii_mode_set(uniphy_index); + break; + case PORT_WRAPPER_10GBASE_R: + ppe_uniphy_10g_r_mode_set(uniphy_index); + break; + default: + break; + } +} + +void ppe_uniphy_usxgmii_autoneg_completed(uint32_t uniphy_index) +{ + uint32_t autoneg_complete = 0, retries = 100; + uint32_t reg_value = 0; + + while (autoneg_complete != 0x1) { + mdelay(1); + if (retries-- == 0) + { + return; + } + reg_value = csr1_read(uniphy_index, VR_MII_AN_INTR_STS); + autoneg_complete = reg_value & 0x1; + } + reg_value &= ~CL37_ANCMPLT_INTR; + csr1_write(uniphy_index, VR_MII_AN_INTR_STS, reg_value); +} + +void ppe_uniphy_usxgmii_speed_set(uint32_t uniphy_index, int speed) +{ + uint32_t reg_value = 0; + + reg_value = csr1_read(uniphy_index, SR_MII_CTRL_ADDRESS); + reg_value |= DUPLEX_MODE; + + switch(speed) { + case 0: + reg_value &=~SS5; + reg_value &=~SS6; + reg_value &=~SS13; + break; + case 1: + reg_value &=~SS5; + reg_value &=~SS6; + reg_value |=SS13; + break; + case 2: + reg_value &=~SS5; + reg_value |=SS6; + reg_value &=~SS13; + break; + case 3: + reg_value &=~SS5; + reg_value |=SS6; + reg_value |=SS13; + break; + case 4: + reg_value |=SS5; + reg_value &=~SS6; + reg_value &=~SS13; + break; + case 5: + reg_value |=SS5; + reg_value &=~SS6; + reg_value |=SS13; + break; + } + csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value); + +} + +void ppe_uniphy_usxgmii_duplex_set(uint32_t uniphy_index, int duplex) +{ + uint32_t reg_value = 0; + + reg_value = csr1_read(uniphy_index, SR_MII_CTRL_ADDRESS); + + if (duplex & 0x1) + reg_value |= DUPLEX_MODE; + else + reg_value &= ~DUPLEX_MODE; + + csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value); +} + +void ppe_uniphy_usxgmii_port_reset(uint32_t uniphy_index) +{ + uint32_t reg_value = 0; + + reg_value = csr1_read(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS); + reg_value |= USRA_RST; + csr1_write(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS, reg_value); +} diff --git a/drivers/net/ipq6018/ipq6018_uniphy.h b/drivers/net/ipq6018/ipq6018_uniphy.h new file mode 100644 index 0000000000..1917c74010 --- /dev/null +++ b/drivers/net/ipq6018/ipq6018_uniphy.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#define PPE_UNIPHY_INSTANCE0 0 +#define PPE_UNIPHY_INSTANCE1 1 +#define PPE_UNIPHY_INSTANCE2 2 + +#define GCC_UNIPHY0_MISC 0x01856004 +#define GCC_UNIPHY_REG_INC 0x100 +#define GCC_UNIPHY_USXGMII_XPCS_RESET 0x4 +#define GCC_UNIPHY_USXGMII_XPCS_RELEASE_RESET 0x0 + +#define PPE_UNIPHY_OFFSET_CALIB_4 0x1E0 +#define UNIPHY_CALIBRATION_DONE 0x1 + +#define GCC_UNIPHY_PSGMII_SOFT_RESET 0x3ff2 +#define GCC_UNIPHY_USXGMII_SOFT_RESET 0x36 + +#define PPE_UNIPHY_BASE 0X07A00000 +#define PPE_UNIPHY_REG_INC 0x10000 +#define PPE_UNIPHY_MODE_CONTROL 0x46C +#define UNIPHY_XPCS_MODE (1 << 12) +#define UNIPHY_SG_PLUS_MODE (1 << 11) +#define UNIPHY_SG_MODE (1 << 10) +#define UNIPHY_CH0_PSGMII_QSGMII (1 << 9) +#define UNIPHY_CH0_QSGMII_SGMII (1 << 8) +#define UNIPHY_CH4_CH1_0_SGMII (1 << 2) +#define UNIPHY_CH1_CH0_SGMII (1 << 1) +#define UNIPHY_CH0_ATHR_CSCO_MODE_25M (1 << 0) + +#define UNIPHY_INSTANCE_LINK_DETECT 0x570 + +#define UNIPHY_MISC2_REG_OFFSET 0x218 +#define UNIPHY_MISC2_REG_SGMII_MODE 0x30 +#define UNIPHY_MISC2_REG_SGMII_PLUS_MODE 0x50 + +#define UNIPHY_MISC2_REG_VALUE 0x70 + +#define UNIPHY_PLL_RESET_REG_OFFSET 0x780 +#define UNIPHY_PLL_RESET_REG_VALUE 0x02bf +#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff + +#define SR_XS_PCS_KR_STS1_ADDRESS 0x30020 +#define UNIPHY_10GR_LINKUP 0x1 + +#define VR_XS_PCS_DIG_CTRL1_ADDRESS 0x38000 +#define USXG_EN (1 << 9) +#define USRA_RST (1 << 10) + +#define VR_MII_AN_CTRL_ADDRESS 0x1f8001 +#define MII_AN_INTR_EN (1 << 0) +#define MII_CTRL (1 << 8) + +#define SR_MII_CTRL_ADDRESS 0x1f0000 +#define AN_ENABLE (1 << 12) +#define SS5 (1 << 5) +#define SS6 (1 << 6) +#define SS13 (1 << 13) +#define DUPLEX_MODE (1 << 8) + +#define VR_MII_AN_INTR_STS 0x1f8002 +#define CL37_ANCMPLT_INTR (1 << 0) + +void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode); +void ppe_uniphy_usxgmii_port_reset(uint32_t uniphy_index); +void ppe_uniphy_usxgmii_duplex_set(uint32_t uniphy_index, int duplex); +void ppe_uniphy_usxgmii_speed_set(uint32_t uniphy_index, int speed); +void ppe_uniphy_usxgmii_autoneg_completed(uint32_t uniphy_index); diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h index 0441ee76fe..f11c693293 100644 --- a/include/configs/ipq6018.h +++ b/include/configs/ipq6018.h @@ -27,6 +27,8 @@ #define CONFIG_SYS_VSNPRINTF #define CONFIG_IPQ_NO_RELOC +#define CONFIG_SYS_NONCACHED_MEMORY (1 << 20) + #define CONFIG_IPQ6018_UART #define CONFIG_NR_DRAM_BANKS 1 #define CONFIG_SKIP_LOWLEVEL_INIT @@ -287,6 +289,25 @@ extern loff_t board_env_size; #define TZ_VERSION 1 #define RPM_VERSION 3 #endif + +#define CONFIG_IPQ6018_EDMA 1 +#define CONFIG_IPQ6018_BRIDGED_MODE 1 +#define CONFIG_NET_RETRY_COUNT 5 +#define CONFIG_SYS_RX_ETH_BUFFER 16 +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_MII +#define CONFIG_CMD_MII +#define CONFIG_IPADDR 192.168.10.10 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_SERVERIP 192.168.10.1 +#define CONFIG_CMD_TFTPPUT +#define CONFIG_IPQ_MDIO 1 +#define CONFIG_QCA8075_PHY 1 +#define CONFIG_QCA8033_PHY 1 +#define CONFIG_QCA8081_PHY 1 +#define CONFIG_IPQ_ETH_INIT_DEFER + /* L1 cache line size is 64 bytes, L2 cache line size is 128 bytes * Cache flush and invalidation based on L1 cache, so the cache line * size is configured to 64 */