diff --git a/arch/arm/include/asm/arch-ipq9574/edma_regs.h b/arch/arm/include/asm/arch-ipq9574/edma_regs.h new file mode 100644 index 0000000000..4369ece545 --- /dev/null +++ b/arch/arm/include/asm/arch-ipq9574/edma_regs.h @@ -0,0 +1,395 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019, 2021, 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 IPQ9574_EDMA_CFG_BASE 0x3ab00000 +/* + * IPQ9574 EDMA register offsets + */ +#define IPQ9574_EDMA_REG_MAS_CTRL 0x0 +#define IPQ9574_EDMA_REG_PORT_CTRL 0x4 +#define IPQ9574_EDMA_REG_VLAN_CTRL 0x8 +#define IPQ9574_EDMA_REG_RXDESC2FILL_MAP_0 0x18 +#define IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1 0x1c +#define IPQ9574_EDMA_REG_TXQ_CTRL 0x20 +#define IPQ9574_EDMA_REG_TXQ_CTRL_2 0x24 +#define IPQ9574_EDMA_REG_TXQ_FC_0 0x28 +#define IPQ9574_EDMA_REG_TXQ_FC_1 0x30 +#define IPQ9574_EDMA_REG_TXQ_FC_2 0x34 +#define IPQ9574_EDMA_REG_TXQ_FC_3 0x38 +#define IPQ9574_EDMA_REG_RXQ_CTRL 0x3c +#define IPQ9574_EDMA_REG_RX_TX_FULL_QID 0x40 +#define IPQ9574_EDMA_REG_RXQ_FC_THRE 0x44 +#define IPQ9574_EDMA_REG_DMAR_CTRL 0x48 +#define IPQ9574_EDMA_REG_AXIR_CTRL 0x4c +#define IPQ9574_EDMA_REG_AXIW_CTRL 0x50 +#define IPQ9574_EDMA_REG_MIN_MSS 0x54 +#define IPQ9574_EDMA_REG_LOOPBACK_CTRL 0x58 +#define IPQ9574_EDMA_REG_MISC_INT_STAT 0x5c +#define IPQ9574_EDMA_REG_MISC_INT_MASK 0x60 +#define IPQ9574_EDMA_REG_DBG_CTRL 0x64 +#define IPQ9574_EDMA_REG_DBG_DATA 0x68 +#define IPQ9574_EDMA_REG_TXDESC_BA(n) (0x1000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXDESC_PROD_IDX(n) (0x1004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXDESC_CONS_IDX(n) (0x1008 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXDESC_RING_SIZE(n) (0x100c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXDESC_CTRL(n) (0x1010 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_BA(n) (0x79000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_PROD_IDX(n) (0x79004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_CONS_IDX(n) (0x79008 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_RING_SIZE(n) (0x7900c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_UGT_THRE(n) (0x79010 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_CTRL(n) (0x79014 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TXCMPL_BPC(n) (0x79018 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TX_INT_STAT(n) (0x91000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TX_INT_MASK(n) (0x91004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TX_MOD_TIMER(n) (0x91008 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TX_INT_CTRL(n) (0x9100c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_CONS_IDX(n) (0x29008 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_RING_SIZE(n) (0x2900c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_BUFFER1_SIZE(n) (0x29010 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_FC_THRE(n) (0x29014 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_UGT_THRE(n) (0x29018 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_RING_EN(n) (0x2901c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_DISABLE(n) (0x29020 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_DISABLE_DONE(n) (0x29024 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_INT_STAT(n) (0x31000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXFILL_INT_MASK(n) (0x31004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_BA(n) (0x39000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_PROD_IDX(n) (0x39004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_CONS_IDX(n) (0x39008 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_RING_SIZE(n) (0x3900c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_FC_THRE(n) (0x39010 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_UGT_THRE(n) (0x39014 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_BPC(n) (0x3901c + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_INT_STAT(n) (0x49000 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RXDESC_INT_MASK(n) (0x49004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RX_MOD_TIMER(n) (0x49008 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RX_INT_CTRL(n) (0x4900c + (0x1000 * n)) +#define IPQ9574_EDMA_QID2RID_TABLE_MEM(q) (0x5a000 + (0x4 * q)) +#define IPQ9574_EDMA_REG_RXRING_PC(n) (0x5A200 + (0x10 * n)) +#define IPQ9574_EDMA_REG_RXRING_BC_0(n) (0x5A204 + (0x10 * n)) +#define IPQ9574_EDMA_REG_RXRING_BC_1(n) (0x5A208 + (0x10 * n)) +#define IPQ9574_EDMA_REG_TXRING_PC(n) (0x74000 + (0x10 * n)) +#define IPQ9574_EDMA_REG_TXRING_BC_0(n) (0x74004 + (0x10 * n)) +#define IPQ9574_EDMA_REG_TXRING_BC_1(n) (0x74008 + (0x10 * n)) + +/* + * EDMA_REG_PORT_CTRL register + */ +#define IPQ9574_EDMA_PORT_CTRL_EN 0x3 +#define IPQ9574_EDMA_PORT_CTRL_PAD_EN 0x1 + +/* + * EDMA_REG_TXQ_CTRL register + */ +#define IPQ9574_EDMA_TXDESC_PF_THRE_MASK 0xf +#define IPQ9574_EDMA_TXDESC_PF_THRE_SHIFT 0 +#define IPQ9574_EDMA_TXCMPL_WB_THRE_MASK 0xf +#define IPQ9574_EDMA_TXCMPL_WB_THRE_SHIFT 4 +#define IPQ9574_EDMA_TXDESC_PKT_SRAM_THRE_MASK 0xff +#define IPQ9574_EDMA_TXDESC_PKT_SRAM_THRE_SHIFT 8 +#define IPQ9574_EDMA_TXCMPL_WB_TIMER_MASK 0xffff +#define IPQ9574_EDMA_TXCMPL_WB_TIMER_SHIFT 16 + +/* + * EDMA_REG_RXQ_CTRL register + */ +#define IPQ9574_EDMA_RXFILL_PF_THRE_MASK 0xf +#define IPQ9574_EDMA_RXFILL_PF_THRE_SHIFT 0 +#define IPQ9574_EDMA_RXDESC_WB_THRE_MASK 0xf +#define IPQ9574_EDMA_RXDESC_WB_THRE_SHIFT 4 +#define IPQ9574_EDMA_RXDESC_WB_TIMER_MASK 0xffff +#define IPQ9574_EDMA_RXDESC_WB_TIMER_SHIFT 16 + +/* + * EDMA_REG_RX_TX_FULL_QID register + */ +#define IPQ9574_EDMA_RX_DESC_FULL_QID_MASK 0xff +#define IPQ9574_EDMA_RX_DESC_FULL_QID_SHIFT 0 +#define IPQ9574_EDMA_TX_CMPL_BUF_FULL_QID_MASK 0xff +#define IPQ9574_EDMA_TX_CMPL_BUF_FULL_QID_SHIFT 8 +#define IPQ9574_EDMA_TX_SRAM_FULL_QID_MASK 0x1f +#define IPQ9574_EDMA_TX_SRAM_FULL_QID_SHIFT 16 + +/* + * EDMA_REG_RXQ_FC_THRE reister + */ +#define IPQ9574_EDMA_RXFILL_FIFO_XOFF_THRE_MASK 0x1f +#define IPQ9574_EDMA_RXFILL_FIFO_XOFF_THRE_SHIFT 0 +#define IPQ9574_EDMA_DESC_FIFO_XOFF_THRE_MASK 0x3f +#define IPQ9574_EDMA_DESC_FIFO_XOFF_THRE_SHIFT 16 + +/* + * EDMA_REG_DMAR_CTRL register + */ +#define IPQ9574_EDMA_DMAR_REQ_PRI_MASK 0x7 +#define IPQ9574_EDMA_DMAR_REQ_PRI_SHIFT 0 +#define IPQ9574_EDMA_DMAR_BURST_LEN_MASK 0x1 +#define IPQ9574_EDMA_DMAR_BURST_LEN_SHIFT 3 +#define IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK 0x1f +#define IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT 4 +#define IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK 0x7 +#define IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT 9 +#define IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK 0x7 +#define IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT 12 + +/* + * EDMA DISABLE + */ +#define IPQ9574_EDMA_DISABLE 0 + +/* + * EDMA_REG_TXDESC_PROD_IDX register + */ +#define IPQ9574_EDMA_TXDESC_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_TXDESC_CONS_IDX register + */ +#define IPQ9574_EDMA_TXDESC_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_TXDESC_RING_SIZE register + */ +#define IPQ9574_EDMA_TXDESC_RING_SIZE_MASK 0xffff + +/* + * EDMA_REG_TXDESC_CTRL register + */ +#define IPQ9574_EDMA_TXDESC_ARB_GRP_ID_MASK 0x3 +#define IPQ9574_EDMA_TXDESC_ARB_GRP_ID_SHIFT 4 +#define IPQ9574_EDMA_TXDESC_FC_GRP_ID_MASK 0x7 +#define IPQ9574_EDMA_TXDESC_FC_GRP_ID_SHIFT 1 +#define IPQ9574_EDMA_TXDESC_TX_EN 0x1 + +/* + * EDMA_REG_TXCMPL_PROD_IDX register + */ +#define IPQ9574_EDMA_TXCMPL_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_CONS_IDX register + */ +#define IPQ9574_EDMA_TXCMPL_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_RING_SIZE register + */ +#define IPQ9574_EDMA_TXCMPL_RING_SIZE_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_UGT_THRE register + */ +#define IPQ9574_EDMA_TXCMPL_LOW_THRE_MASK 0xffff +#define IPQ9574_EDMA_TXCMPL_LOW_THRE_SHIFT 0 +#define IPQ9574_EDMA_TXCMPL_FC_THRE_MASK 0x3f +#define IPQ9574_EDMA_TXCMPL_FC_THRE_SHIFT 16 + +/* + * EDMA_REG_TXCMPL_CTRL register + */ +#define IPQ9574_EDMA_TXCMPL_RET_MODE_BUFF_ADDR 0x0 +#define IPQ9574_EDMA_TXCMPL_RET_MODE_OPAQUE 0x1 + +/* + * EDMA_REG_TX_MOD_TIMER register + */ +#define IPQ9574_EDMA_TX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ9574_EDMA_TX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA_REG_TX_INT_CTRL register + */ +#define IPQ9574_EDMA_TX_INT_MASK 0x3 + +/* + * EDMA_REG_RXFILL_PROD_IDX register + */ +#define IPQ9574_EDMA_RXFILL_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_RXFILL_CONS_IDX register + */ +#define IPQ9574_EDMA_RXFILL_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_RXFILL_RING_SIZE register + */ +#define IPQ9574_EDMA_RXFILL_RING_SIZE_MASK 0xffff +#define IPQ9574_EDMA_RXFILL_BUF_SIZE_MASK 0x3fff +#define IPQ9574_EDMA_RXFILL_BUF_SIZE_SHIFT 16 + +/* + * EDMA_REG_RXFILL_FC_THRE register + */ +#define IPQ9574_EDMA_RXFILL_FC_XON_THRE_MASK 0x7ff +#define IPQ9574_EDMA_RXFILL_FC_XON_THRE_SHIFT 12 +#define IPQ9574_EDMA_RXFILL_FC_XOFF_THRE_MASK 0x7ff +#define IPQ9574_EDMA_RXFILL_FC_XOFF_THRE_SHIFT 0 + +/* + * EDMA_REG_RXFILL_UGT_THRE register + */ +#define IPQ9574_EDMA_RXFILL_LOW_THRE_MASK 0xffff +#define IPQ9574_EDMA_RXFILL_LOW_THRE_SHIFT 0 + +/* + * EDMA_REG_RXFILL_RING_EN register + */ +#define IPQ9574_EDMA_RXFILL_RING_EN 0x1 + +/* + * EDMA_REG_RXFILL_INT_MASK register + */ +#define IPQ9574_EDMA_RXFILL_INT_MASK 0x1 + +/* + * EDMA_REG_RXDESC_PROD_IDX register + */ +#define IPQ9574_EDMA_RXDESC_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_RXDESC_CONS_IDX register + */ +#define IPQ9574_EDMA_RXDESC_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_RXDESC_RING_SIZE register + */ +#define IPQ9574_EDMA_RXDESC_RING_SIZE_MASK 0xffff +#define IPQ9574_EDMA_RXDESC_PL_OFFSET_MASK 0x1ff +#define IPQ9574_EDMA_RXDESC_PL_OFFSET_SHIFT 16 + +/* + * EDMA_REG_RXDESC_FC_THRE register + */ +#define IPQ9574_EDMA_RXDESC_FC_XON_THRE_MASK 0x7ff +#define IPQ9574_EDMA_RXDESC_FC_XON_THRE_SHIFT 12 +#define IPQ9574_EDMA_RXDESC_FC_XOFF_THRE_MASK 0x7ff +#define IPQ9574_EDMA_RXDESC_FC_XOFF_THRE_SHIFT 0 + +/* + * EDMA_REG_RXDESC_UGT_THRE register + */ +#define IPQ9574_EDMA_RXDESC_LOW_THRE_MASK 0xffff +#define IPQ9574_EDMA_RXDESC_LOW_THRE_SHIFT 0 + +/* + * EDMA_REG_RXDESC_CTRL register + */ +#define IPQ9574_EDMA_RXDESC_STAG_REMOVE_EN 0x8 +#define IPQ9574_EDMA_RXDESC_CTAG_REMOVE_EN 0x4 +#define IPQ9574_EDMA_RXDESC_QDISC_EN 0x2 +#define IPQ9574_EDMA_RXDESC_RX_EN 0x1 + +/* + * EDMA_REG_TX_INT_MASK register + */ +#define IPQ9574_EDMA_TX_INT_MASK_PKT_INT 0x1 +#define IPQ9574_EDMA_TX_INT_MASK_UGT_INT 0x2 + +/* + * EDMA_REG_RXDESC_INT_STAT register + */ +#define IPQ9574_EDMA_RXDESC_INT_STAT_PKT_INT 0x1 +#define IPQ9574_EDMA_RXDESC_INT_STAT_UGT_INT 0x2 + +/* + * EDMA_REG_RXDESC_INT_MASK register + */ +#define IPQ9574_EDMA_RXDESC_INT_MASK_PKT_INT 0x1 +#define IPQ9574_EDMA_RXDESC_INT_MASK_TIMER_INT_DIS 0x2 + +#define IPQ9574_EDMA_MASK_INT_DISABLE 0x0 +#define IPQ9574_EDMA_MASK_INT_CLEAR 0x0 + +/* + * EDMA_REG_RX_MOD_TIMER register + */ +#define IPQ9574_EDMA_RX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ9574_EDMA_RX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA QID2RID register sizes + */ +#define IPQ9574_EDMA_QID2RID_DEPTH 0x40 +#define IPQ9574_EDMA_QID2RID_QUEUES_PER_ENTRY 8 + +/* + * TXDESC shift values + */ +#define IPQ9574_EDMA_TXDESC_MORE_SHIFT 31 +#define IPQ9574_EDMA_TXDESC_TSO_EN_SHIFT 30 +#define IPQ9574_EDMA_TXDESC_PREHEADER_SHIFT 29 +#define IPQ9574_EDMA_TXDESC_POOL_ID_SHIFT 24 +#define IPQ9574_EDMA_TXDESC_POOL_ID_MASK 0x1f +#define IPQ9574_EDMA_TXDESC_DATA_OFFSET_SHIFT 16 +#define IPQ9574_EDMA_TXDESC_DATA_OFFSET_MASK 0xff +#define IPQ9574_EDMA_TXDESC_DATA_LENGTH_SHIFT 0 +#define IPQ9574_EDMA_TXDESC_DATA_LENGTH_MASK 0xffff + +#define IPQ9574_EDMA_PREHDR_DSTINFO_PORTID_IND 0x20 +#define IPQ9574_EDMA_PREHDR_PORTNUM_BITS 0x0fff +#define IPQ9574_EDMA_RING_DMA_MASK 0xffffffff +/* + * RXDESC shift values + */ +#define IPQ9574_EDMA_RXDESC_RX_RXFILL_CNT_MASK 0x000f +#define IPQ9574_EDMA_RXDESC_RX_RXFILL_CNT_SHIFT 16 + +#define IPQ9574_EDMA_RXDESC_PKT_SIZE_MASK 0x3fff +#define IPQ9574_EDMA_RXDESC_PKT_SIZE_SHIFT 0 + +#define IPQ9574_EDMA_RXDESC_RXD_VALID_MASK 0x1 +#define IPQ9574_EDMA_RXDESC_RXD_VALID_SHIFT 31 + +#define IPQ9574_EDMA_RXDESC_PACKET_LEN_MASK 0x3fff +#define IPQ9574_EDMA_RXDESC_RING_INT_STATUS_MASK 0x3 + +#define IPQ9574_EDMA_RING_DISABLE 0 +#define IPQ9574_EDMA_TXCMPL_RING_INT_STATUS_MASK 0x3 +#define IPQ9574_EDMA_TXCMPL_RETMODE_OPAQUE 0x0 +#define IPQ9574_EDMA_RXFILL_RING_INT_STATUS_MASK 0x1 + +/* + * TODO tune the timer and threshold values + */ +#define IPQ9574_EDMA_RXFILL_FIFO_XOFF_THRE 0x3 +#define IPQ9574_EDMA_RXFILL_PF_THRE 0x3 +#define IPQ9574_EDMA_RXDESC_WB_THRE 0x0 +#define IPQ9574_EDMA_RXDESC_WB_TIMER 0x2 + +#define IPQ9574_EDMA_RXDESC_XON_THRE 50 +#define IPQ9574_EDMA_RXDESC_XOFF_THRE 30 +#define IPQ9574_EDMA_RXDESC_LOW_THRE 0 +#define IPQ9574_EDMA_RX_MOD_TIMER_INIT 1000 + +#define IPQ9574_EDMA_TXDESC_PF_THRE 0x3 +#define IPQ9574_EDMA_TXCMPL_WB_THRE 0X0 +#define IPQ9574_EDMA_TXDESC_PKT_SRAM_THRE 0x20 +#define IPQ9574_EDMA_TXCMPL_WB_TIMER 0x2 + +#define IPQ9574_EDMA_TX_MOD_TIMER 150 + +#endif /* __EDMA_REGS__ */ diff --git a/board/qca/arm/ipq9574/ipq9574.h b/board/qca/arm/ipq9574/ipq9574.h index a2743d50ad..4930a4c59a 100644 --- a/board/qca/arm/ipq9574/ipq9574.h +++ b/board/qca/arm/ipq9574/ipq9574.h @@ -18,6 +18,30 @@ #include #include +#define CLK_TOGGLE_ENABLE 0x1 +#define GCC_NSS_PPE_RESET 0x01868014 + +/* + * PPE ASSERT and DEASSERT values + */ +#define PPE_ASSERT 0xf0000 +#define PPE_DEASSERT 0x0 + +/* + * EDMA HW ASSERT and DEASSERT values + */ +#define GCC_EDMA_HW_RESET_ASSERT 0x300000 +#define GCC_EDMA_HW_RESET_DEASSERT 0x0 + +/* + * NSS Port ASSERT and DEASSERT values + */ +#define NSS_PORT1_ASSERT 0x1000003 +#define NSS_PORT2_ASSERT 0x200000c +#define NSS_PORT3_ASSERT 0x4000030 +#define NSS_PORT4_ASSERT 0x8000300 +#define NSS_PORT5_ASSERT 0x10000c00 + #define BLSP1_UART0_BASE 0x078AF000 #define UART_PORT_ID(reg) ((reg - BLSP1_UART0_BASE) / 0x1000) diff --git a/configs/ipq9574_defconfig b/configs/ipq9574_defconfig index 1fb92a903b..57c8a66569 100644 --- a/configs/ipq9574_defconfig +++ b/configs/ipq9574_defconfig @@ -95,6 +95,14 @@ CONFIG_CMD_NFS=y # CONFIG_CMD_DNS is not set # CONFIG_CMD_LINK_LOCAL is not set +# +# Network PHY +# +CONFIG_QCA8075_PHY=y +CONFIG_IPQ9574_QCA_AQUANTIA_PHY=y +# CONFIG_QCA8033_PHY is not set +CONFIG_QCA8081_PHY=y + # # Misc commands # diff --git a/drivers/net/Makefile b/drivers/net/Makefile index ee3de33e5b..f3677103c5 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -86,6 +86,9 @@ 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_IPQ9574_EDMA) += ipq9574/ipq9574_ppe.o +obj-$(CONFIG_IPQ9574_EDMA) += ipq9574/ipq9574_uniphy.o +obj-$(CONFIG_IPQ9574_EDMA) += ipq9574/ipq9574_edma.o obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/ipq5018_gmac.o obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/ipq5018_uniphy.o obj-$(CONFIG_IPQ5018_MDIO) += ipq5018/ipq5018_mdio.o diff --git a/drivers/net/ipq9574/ipq9574_aquantia_phy.c b/drivers/net/ipq9574/ipq9574_aquantia_phy.c new file mode 100644 index 0000000000..639fc3e4a9 --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_aquantia_phy.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2017-2019, 2021, 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 "ipq_phy.h" +#include "ipq9574_aquantia_phy.h" +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; +typedef struct { + unsigned int image_type; + unsigned int header_vsn_num; + unsigned int image_src; + unsigned char *image_dest_ptr; + unsigned int image_size; + unsigned int code_size; + unsigned char *signature_ptr; + unsigned int signature_size; + unsigned char *cert_chain_ptr; + unsigned int cert_chain_size; +} mbn_header_t; + +mbn_header_t *fwimg_header; +static int debug = 0; + +#ifdef CONFIG_QCA_MMC +extern qca_mmc mmc_host; +static qca_mmc *host = &mmc_host; +#endif + +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 int ipq_sw_mdio_init(const char *); +extern void eth_clock_enable(void); +static int program_ethphy_fw(unsigned int phy_addr, + uint32_t load_addr,uint32_t file_size ); +static qca_smem_flash_info_t *sfi = &qca_smem_flash_info; + +u16 aq_phy_reg_write(u32 dev_id, u32 phy_id, + u32 reg_id, u16 reg_val) +{ + ipq_mdio_write(phy_id, reg_id, reg_val); + return 0; +} + +u16 aq_phy_reg_read(u32 dev_id, u32 phy_id, u32 reg_id) +{ + return ipq_mdio_read(phy_id, reg_id, NULL); +} + +u8 aq_phy_get_link_status(u32 dev_id, u32 phy_id) +{ + u16 phy_data; + uint32_t reg; + + reg = AQ_PHY_AUTO_STATUS_REG | AQUANTIA_MII_ADDR_C45; + phy_data = aq_phy_reg_read(dev_id, phy_id, reg); + phy_data = aq_phy_reg_read(dev_id, phy_id, reg); + + if (((phy_data >> 2) & 0x1) & PORT_LINK_UP) + return 0; + + return 1; +} + +u32 aq_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex) +{ + u16 phy_data; + uint32_t reg; + + reg = AQ_PHY_LINK_STATUS_REG | AQUANTIA_MII_ADDR_C45; + phy_data = aq_phy_reg_read(dev_id, phy_id, reg); + + /* + * Read duplex + */ + phy_data = phy_data & 0x1; + if (phy_data & 0x1) + *duplex = FAL_FULL_DUPLEX; + else + *duplex = FAL_HALF_DUPLEX; + + return 0; +} + +u32 aq_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed) +{ + u16 phy_data; + uint32_t reg; + + reg = AQ_PHY_LINK_STATUS_REG | AQUANTIA_MII_ADDR_C45; + phy_data = aq_phy_reg_read(dev_id, phy_id, reg); + + switch ((phy_data >> 1) & 0x7) { + case SPEED_10G: + *speed = FAL_SPEED_10000; + break; + case SPEED_5G: + *speed = FAL_SPEED_5000; + break; + case SPEED_2_5G: + *speed = FAL_SPEED_2500; + break; + case SPEED_1000MBS: + *speed = FAL_SPEED_1000; + break; + case SPEED_100MBS: + *speed = FAL_SPEED_100; + break; + case SPEED_10MBS: + *speed = FAL_SPEED_10; + break; + default: + return -EINVAL; + } + return 0; +} + +void aquantia_phy_restart_autoneg(u32 phy_id) +{ + u16 phy_data; + + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS, + AQUANTIA_PHY_XS_USX_TRANSMIT)); + if (!(phy_data & AQUANTIA_PHY_USX_AUTONEG_ENABLE)) + aq_phy_reg_write(0x0, phy_id,AQUANTIA_REG_ADDRESS( + AQUANTIA_MMD_PHY_XS_REGISTERS, + AQUANTIA_PHY_XS_USX_TRANSMIT), + phy_data | AQUANTIA_PHY_USX_AUTONEG_ENABLE); + + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG, + AQUANTIA_AUTONEG_STANDARD_CONTROL1)); + + phy_data |= AQUANTIA_CTRL_AUTONEGOTIATION_ENABLE; + aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG, + AQUANTIA_AUTONEG_STANDARD_CONTROL1), + phy_data | AQUANTIA_CTRL_RESTART_AUTONEGOTIATION); +} + +int ipq_qca_aquantia_phy_init(struct phy_ops **ops, u32 phy_id) +{ + u16 phy_data; + struct phy_ops *aq_phy_ops; + aq_phy_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops)); + if (!aq_phy_ops) + return -ENOMEM; + aq_phy_ops->phy_get_link_status = aq_phy_get_link_status; + aq_phy_ops->phy_get_speed = aq_phy_get_speed; + aq_phy_ops->phy_get_duplex = aq_phy_get_duplex; + *ops = aq_phy_ops; + + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(1, QCA_PHY_ID1)); + printf ("PHY ID1: 0x%x\n", phy_data); + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(1, QCA_PHY_ID2)); + printf ("PHY ID2: 0x%x\n", phy_data); + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS, + AQUANTIA_PHY_XS_USX_TRANSMIT)); + phy_data |= AQUANTIA_PHY_USX_AUTONEG_ENABLE; + aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_PHY_XS_REGISTERS, + AQUANTIA_PHY_XS_USX_TRANSMIT), phy_data); + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG, + AQUANTIA_AUTONEG_TRANSMIT_VENDOR_INTR_MASK)); + phy_data |= AQUANTIA_INTR_LINK_STATUS_CHANGE; + aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_AUTONEG, + AQUANTIA_AUTONEG_TRANSMIT_VENDOR_INTR_MASK), phy_data); + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS, + AQUANTIA_GLOBAL_INTR_STANDARD_MASK)); + phy_data |= AQUANTIA_ALL_VENDOR_ALARMS_INTERRUPT_MASK; + aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS, + AQUANTIA_GLOBAL_INTR_STANDARD_MASK), phy_data); + phy_data = aq_phy_reg_read(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS, + AQUANTIA_GLOBAL_INTR_VENDOR_MASK)); + phy_data |= AQUANTIA_AUTO_AND_ALARMS_INTR_MASK; + aq_phy_reg_write(0x0, phy_id, AQUANTIA_REG_ADDRESS(AQUANTIA_MMD_GLOABLE_REGISTERS, + AQUANTIA_GLOBAL_INTR_VENDOR_MASK), phy_data); + return 0; +} + +static int do_aq_phy_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int phy_addr = AQU_PHY_ADDR; + if (argc > 2) + return CMD_RET_USAGE; + + if (argc == 2) + phy_addr = simple_strtoul(argv[1], NULL, 16); + + aquantia_phy_restart_autoneg(phy_addr); + return 0; +} + +int ipq_board_fw_download(unsigned int phy_addr) +{ + char runcmd[256]; + int ret,i=0; + uint32_t start; /* block number */ + uint32_t size; /* no. of blocks */ + qca_part_entry_t ethphyfw; + unsigned int *ethphyfw_load_addr = NULL; + struct { char *name; qca_part_entry_t *part; } entries[] = { + { "0:ETHPHYFW", ðphyfw }, + }; +#ifdef CONFIG_QCA_MMC + block_dev_desc_t *blk_dev; + disk_partition_t disk_info; +#endif + /* check the smem info to see which flash used for booting */ + if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) { + if (debug) { + printf("Using nor device \n"); + } + } else if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) { + if (debug) { + printf("Using nand device 0\n"); + } + } else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH) { + if (debug) { + printf("Using MMC device\n"); + } + } else { + printf("Unsupported BOOT flash type\n"); + return -1; + } + + ret = smem_getpart(entries[i].name, &start, &size); + if (ret < 0) { + debug("cdp: get part failed for %s\n", entries[i].name); + } else { + qca_set_part_entry(entries[i].name, sfi, entries[i].part, start, size); + } + + if ((sfi->flash_type == SMEM_BOOT_NAND_FLASH) || + (sfi->flash_type == SMEM_BOOT_SPI_FLASH)) { + ethphyfw_load_addr = (uint *)malloc(ethphyfw.size); + if (ethphyfw_load_addr == NULL) { + printf("ETHPHYFW Loading failed\n"); + return -1; + } else { + memset(ethphyfw_load_addr, 0, ethphyfw.size); + } + } + + if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) { + /* + * Kernel is in a separate partition + */ + snprintf(runcmd, sizeof(runcmd), + /* NOR is treated as psuedo NAND */ + "nand read 0x%p 0x%llx 0x%llx && ", + ethphyfw_load_addr, ethphyfw.offset, ethphyfw.size); + + if (debug) + printf("%s", runcmd); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) { + free(ethphyfw_load_addr); + return CMD_RET_FAILURE; + } + } else if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) { + snprintf(runcmd, sizeof(runcmd), + "sf probe && " "sf read 0x%p 0x%llx 0x%llx && ", + ethphyfw_load_addr, ethphyfw.offset, ethphyfw.size); + + if (debug) + printf("%s", runcmd); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) { + free(ethphyfw_load_addr); + return CMD_RET_FAILURE; + } +#ifdef CONFIG_QCA_MMC + } else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH ) { + blk_dev = mmc_get_dev(host->dev_num); + ret = get_partition_info_efi_by_name(blk_dev, + "0:ETHPHYFW", &disk_info); + + ethphyfw_load_addr = (uint *)malloc(((uint)disk_info.size) * + ((uint)disk_info.blksz)); + if (ethphyfw_load_addr == NULL) { + printf("ETHPHYFW Loading failed\n"); + return -1; + } else { + memset(ethphyfw_load_addr, 0, + (((uint)disk_info.size) * + ((uint)disk_info.blksz))); + } + + if (ret == 0) { + snprintf(runcmd, sizeof(runcmd), + "mmc read 0x%p 0x%X 0x%X", + ethphyfw_load_addr, + (uint)disk_info.start, (uint)disk_info.size); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) { + free(ethphyfw_load_addr); + return CMD_RET_FAILURE; + } + } +#endif + } + + fwimg_header = (mbn_header_t *)(ethphyfw_load_addr); + + if (fwimg_header->image_type == 0x13 && + fwimg_header->header_vsn_num == 0x3) { + program_ethphy_fw(phy_addr, + (uint32_t)(((uint32_t)ethphyfw_load_addr) + + sizeof(mbn_header_t)), + (uint32_t)(fwimg_header->image_size)); + } else { + printf("bad magic on ETHPHYFW partition\n"); + free(ethphyfw_load_addr); + return -1; + } + free(ethphyfw_load_addr); + return 0; +} + + +#define AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD 0x300 +static int program_ethphy_fw(unsigned int phy_addr, uint32_t load_addr, uint32_t file_size) +{ + int i; + uint8_t *buf; + uint16_t file_crc; + uint16_t computed_crc; + uint32_t reg1, reg2; + uint16_t recorded_ggp8_val; + uint16_t daisy_chain_dis; + uint32_t primary_header_ptr = 0x00000000; + uint32_t primary_iram_ptr = 0x00000000; + uint32_t primary_dram_ptr = 0x00000000; + uint32_t primary_iram_sz = 0x00000000; + uint32_t primary_dram_sz = 0x00000000; + uint32_t phy_img_hdr_off; + uint32_t byte_sz; + uint32_t dword_sz; + uint32_t byte_ptr; + uint16_t msw = 0; + uint16_t lsw = 0; + uint8_t msb1; + uint8_t msb2; + uint8_t lsb1; + uint8_t lsb2; + uint16_t mailbox_crc; + + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x300), 0xdead); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x301), 0xbeaf); + reg1 = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x300)); + reg2 = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x301)); + + if(reg1 != 0xdead && reg2 != 0xbeaf) { + printf("PHY::Scratchpad Read/Write test fail\n"); + return 0; + } + buf = (uint8_t *)load_addr; + file_crc = buf[file_size - 2] << 8 | buf[file_size - 1]; + computed_crc = cyg_crc16(buf, file_size - 2); + + if (file_crc != computed_crc) { + printf("CRC check failed on phy fw file\n"); + return 0; + } else { + printf ("CRC check good on phy fw file (0x%04X)\n",computed_crc); + } + + daisy_chain_dis = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc452)); + if (!(daisy_chain_dis & 0x1)) + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc452), 0x1); + + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc471), 0x40); + recorded_ggp8_val = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc447)); + if ((recorded_ggp8_val & 0x1f) != phy_addr) + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc447), phy_addr); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc441), 0x4000); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x41); + primary_header_ptr = (((buf[0x9] & 0x0F) << 8) | buf[0x8]) << 12; + phy_img_hdr_off = AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD; + primary_iram_ptr = (buf[primary_header_ptr + phy_img_hdr_off + 0x4 + 2] << 16) | + (buf[primary_header_ptr + phy_img_hdr_off + 0x4 + 1] << 8) | + buf[primary_header_ptr + phy_img_hdr_off + 0x4]; + primary_iram_sz = (buf[primary_header_ptr + phy_img_hdr_off + 0x7 + 2] << 16) | + (buf[primary_header_ptr + phy_img_hdr_off + 0x7 + 1] << 8) | + buf[primary_header_ptr + phy_img_hdr_off + 0x7]; + primary_dram_ptr = (buf[primary_header_ptr + phy_img_hdr_off + 0xA + 2] << 16) | + (buf[primary_header_ptr + phy_img_hdr_off + 0xA + 1] << 8) | + buf[primary_header_ptr + phy_img_hdr_off + 0xA]; + primary_dram_sz = (buf[primary_header_ptr + phy_img_hdr_off + 0xD + 2] << 16) | + (buf[primary_header_ptr + phy_img_hdr_off + 0xD + 1] << 8) | + buf[primary_header_ptr + phy_img_hdr_off + 0xD]; + primary_iram_ptr += primary_header_ptr; + primary_dram_ptr += primary_header_ptr; + + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0x1000); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0x0); + computed_crc = 0; + printf("PHYFW:Loading IRAM..........."); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x202), 0x4000); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x203), 0x0); + byte_sz = primary_iram_sz; + dword_sz = byte_sz >> 2; + byte_ptr = primary_iram_ptr; + for (i = 0; i < dword_sz; i++) { + lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + msw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000); + msb1 = msw >> 8; + msb2 = msw & 0xFF; + lsb1 = lsw >> 8; + lsb2 = lsw & 0xFF; + computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); + } + + switch (byte_sz & 0x3) { + case 0x1: + lsw = buf[byte_ptr++]; + msw = 0x0000; + break; + case 0x2: + lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + msw = 0x0000; + break; + case 0x3: + lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + msw = buf[byte_ptr++]; + break; + } + + if (byte_sz & 0x3) { + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000); + msb1 = msw >> 8; + msb2 = msw & 0xFF; + lsb1 = lsw >> 8; + lsb2 = lsw & 0xFF; + computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); + } + printf("done.\n"); + printf("PHYFW:Loading DRAM.............."); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x202), 0x3ffe); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x203), 0x0); + byte_sz = primary_dram_sz; + dword_sz = byte_sz >> 2; + byte_ptr = primary_dram_ptr; + for (i = 0; i < dword_sz; i++) { + lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + msw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000); + msb1 = msw >> 8; + msb2 = msw & 0xFF; + lsb1 = lsw >> 8; + lsb2 = lsw & 0xFF; + computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); + } + + switch (byte_sz & 0x3) { + case 0x1: + lsw = buf[byte_ptr++]; + msw = 0x0000; + break; + case 0x2: + lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + msw = 0x0000; + break; + case 0x3: + lsw = (buf[byte_ptr + 1] << 8) | buf[byte_ptr]; + byte_ptr += 2; + msw = buf[byte_ptr++]; + break; + } + + if (byte_sz & 0x3) { + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x204), msw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x205), lsw); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0xc000); + msb1 = msw >> 8; + msb2 = msw & 0xFF; + lsb1 = lsw >> 8; + lsb2 = lsw & 0xFF; + computed_crc = cyg_crc16_computed(&msb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); + computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); + } + printf("done.\n"); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc441), 0x2010); + mailbox_crc = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x201)); + if (mailbox_crc != computed_crc) { + printf("phy fw image load CRC-16 (0x%X) does not match calculated CRC-16 (0x%X)\n", mailbox_crc, computed_crc); + return 0; + } else + printf("phy fw image load good CRC-16 matches (0x%X)\n", mailbox_crc); + + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x0), 0x0); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x41); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x8041); + mdelay(100); + aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x40); + mdelay(100); + aquantia_phy_restart_autoneg(phy_addr); + return 0; +} + +static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int phy_addr = AQU_PHY_ADDR; + int node, aquantia_port; + + if (argc > 2) + return CMD_RET_USAGE; + + if (argc == 2) + phy_addr = simple_strtoul(argv[1], NULL, 16); + + node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + if (node < 0) { + printf("Error: ess-switch not specified in dts"); + return 0; + } + + aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_port", -1); + if (aquantia_port < 0) { + printf("Error: aquantia_port not specified in dts"); + return 0; + } + + aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_gpio", -1); + if (aquantia_port < 0) { + printf("Error: aquantia_gpio not specified in dts"); + return 0; + } + + miiphy_init(); + eth_clock_enable(); + ipq_sw_mdio_init("IPQ MDIO0"); + ipq_board_fw_download(phy_addr); + return 0; +} + +U_BOOT_CMD( + aq_load_fw, 5, 1, do_load_fw, + "LOAD aq-fw-binary", + "" +); + +U_BOOT_CMD( + aq_phy_restart, 5, 1, do_aq_phy_restart, + "Restart Aquantia phy", + "" +); diff --git a/drivers/net/ipq9574/ipq9574_aquantia_phy.h b/drivers/net/ipq9574/ipq9574_aquantia_phy.h new file mode 100644 index 0000000000..66383085f7 --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_aquantia_phy.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2019, 2021, 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 AQUANTIA_MII_ADDR_C45 (1<<30) +#define AQUANTIA_REG_ADDRESS(dev_ad, reg_num) (AQUANTIA_MII_ADDR_C45 |\ + ((dev_ad & 0x1f) << 16) | (reg_num & 0xFFFF)) + +#define AQUANTIA_MMD_PHY_XS_REGISTERS 4 +#define AQUANTIA_PHY_XS_USX_TRANSMIT 0xc441 +#define AQUANTIA_PHY_USX_AUTONEG_ENABLE 0x8 + +#define AQUANTIA_MMD_AUTONEG 0x7 +#define AQUANTIA_AUTONEG_TRANSMIT_VENDOR_INTR_MASK 0xD401 +#define AQUANTIA_INTR_LINK_STATUS_CHANGE 0x0001 + +#define AQUANTIA_MMD_GLOABLE_REGISTERS 0x1E +#define AQUANTIA_GLOBAL_INTR_STANDARD_MASK 0xff00 +#define AQUANTIA_ALL_VENDOR_ALARMS_INTERRUPT_MASK 0x0001 + +#define AQUANTIA_GLOBAL_INTR_VENDOR_MASK 0xff01 +#define AQUANTIA_AUTO_AND_ALARMS_INTR_MASK 0x1001 + +#define AQUANTIA_AUTONEG_STANDARD_CONTROL1 0 +#define AQUANTIA_CTRL_AUTONEGOTIATION_ENABLE 0x1000 +#define AQUANTIA_CTRL_RESTART_AUTONEGOTIATION 0x0200 + +#define AQ_PHY_AUTO_STATUS_REG 0x70001 +#define PORT_LINK_DOWN 0 +#define PORT_LINK_UP 1 + +#define AQ_PHY_LINK_STATUS_REG 0x7c800 +#define SPEED_5G 5 +#define SPEED_2_5G 4 +#define SPEED_10G 3 +#define SPEED_1000MBS 2 +#define SPEED_100MBS 1 +#define SPEED_10MBS 0 diff --git a/drivers/net/ipq9574/ipq9574_edma.c b/drivers/net/ipq9574/ipq9574_edma.c new file mode 100644 index 0000000000..992ea8a250 --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_edma.c @@ -0,0 +1,1889 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019, 2021, 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 "ipq9574_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_IPQ9574_BRIDGED_MODE +#define IPQ9574_EDMA_MAC_PORT_NO 3 +#endif + +static struct ipq9574_eth_dev *ipq9574_edma_dev[IPQ9574_EDMA_DEV]; + +uchar ipq9574_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD}; +phy_info_t *phy_info[IPQ9574_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_qca_aquantia_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 ipq9574_edma_hw_addr; + +void ipq9574_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"); +} + +/* + * ipq9574_edma_reg_read() + * Read EDMA register + */ +uint32_t ipq9574_edma_reg_read(uint32_t reg_off) +{ + return (uint32_t)readl(ipq9574_edma_hw_addr + reg_off); +} + +/* + * ipq9574_edma_reg_write() + * Write EDMA register + */ +void ipq9574_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, (ipq9574_edma_hw_addr + reg_off)); +} + +/* + * ipq9574_edma_alloc_rx_buffer() + * Alloc Rx buffers for one RxFill ring + */ +int ipq9574_edma_alloc_rx_buffer(struct ipq9574_edma_hw *ehw, + struct ipq9574_edma_rxfill_ring *rxfill_ring) +{ + uint16_t num_alloc = 0; + uint16_t cons, next, counter; + struct ipq9574_edma_rxfill_desc *rxfill_desc; + uint32_t reg_data; + struct ipq9574_edma_rx_preheader *rxph; + + /* + * Read RXFILL ring producer index + */ + reg_data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXFILL_PROD_IDX( + rxfill_ring->id)); + + next = reg_data & IPQ9574_EDMA_RXFILL_PROD_IDX_MASK & (rxfill_ring->count - 1); + + /* + * Read RXFILL ring consumer index + */ + reg_data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXFILL_CONS_IDX( + rxfill_ring->id)); + + cons = reg_data & IPQ9574_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 = IPQ9574_EDMA_RXFILL_DESC(rxfill_ring, next); + + /* + * Make room for Rx preheader + */ + rxph = (struct ipq9574_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(IPQ9574_EDMA_RX_BUFF_SIZE & + IPQ9574_EDMA_RXFILL_BUF_SIZE_MASK); + + num_alloc++; + next = counter; + } + + if (num_alloc) { + /* + * Update RXFILL ring producer index + */ + reg_data = next & IPQ9574_EDMA_RXFILL_PROD_IDX_MASK; + + /* + * make sure the producer index updated before + * updating the hardware + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_PROD_IDX( + rxfill_ring->id), reg_data); + + pr_debug("%s: num_alloc = %d\n", __func__, num_alloc); + } + + return num_alloc; +} + +/* + * ipq9574_edma_clean_tx() + * Reap Tx descriptors + */ +uint32_t ipq9574_edma_clean_tx(struct ipq9574_edma_hw *ehw, + struct ipq9574_edma_txcmpl_ring *txcmpl_ring) +{ + struct ipq9574_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 = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXCMPL_PROD_IDX( + txcmpl_ring->id)); + prod_idx = data & IPQ9574_EDMA_TXCMPL_PROD_IDX_MASK; + + /* + * Get TXCMPL ring consumer index + */ + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXCMPL_CONS_IDX( + txcmpl_ring->id)); + cons_idx = data & IPQ9574_EDMA_TXCMPL_CONS_IDX_MASK; + + while (cons_idx != prod_idx) { + + txcmpl_desc = IPQ9574_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_desc->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 + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXCMPL_CONS_IDX( + txcmpl_ring->id), cons_idx); + + return txcmpl_consumed; +} + +/* + * ipq9574_edma_clean_rx() + * Reap Rx descriptors + */ +uint32_t ipq9574_edma_clean_rx(struct ipq9574_edma_common_info *c_info, + struct ipq9574_edma_rxdesc_ring *rxdesc_ring) +{ + void *skb; + struct ipq9574_edma_rxdesc_desc *rxdesc_desc; + struct ipq9574_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 ipq9574_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 = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXDESC_CONS_IDX( + rxdesc_ring->id)) & + IPQ9574_EDMA_RXDESC_CONS_IDX_MASK; + + while (rx) { + /* + * Read Rx ring producer index + */ + prod_idx = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->id)) + & IPQ9574_EDMA_RXDESC_PROD_IDX_MASK; + + if (cons_idx == prod_idx) { + pr_debug("%s: cons = prod \n", __func__); + break; + } + + rxdesc_desc = IPQ9574_EDMA_RXDESC_DESC(rxdesc_ring, cons_idx); + + skb = (void *)rxdesc_desc->buffer_addr; + + /* + * Get Rx preheader + */ + rxph = (struct ipq9574_edma_rx_preheader *)skb; + + rx--; + + /* + * Check src_info from Rx preheader + */ + if (IPQ9574_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) == + IPQ9574_EDMA_PREHDR_DSTINFO_PORTID_IND) { + src_port_num = rxph->src_info & + IPQ9574_EDMA_PREHDR_PORTNUM_BITS; + } else { + pr_warn("WARN: src_info_type:0x%x. Drop skb:%p\n", + IPQ9574_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph), + skb); + goto next_rx_desc; + } + + /* + * Get packet length + */ + pkt_length = rxdesc_desc->status & + IPQ9574_EDMA_RXDESC_PACKET_LEN_MASK; + + if (unlikely((src_port_num < IPQ9574_NSS_DP_START_PHY_PORT) || + (src_port_num > IPQ9574_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 + IPQ9574_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) { + ipq9574_edma_alloc_rx_buffer(ehw, rxdesc_ring->rxfill); + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_CONS_IDX( + rxdesc_ring->id), cons_idx); + } + + return 0; +} + +/* + * ip9574_edma_rx_complete() + */ +static int ipq9574_edma_rx_complete(struct ipq9574_edma_common_info *c_info) +{ + struct ipq9574_edma_hw *ehw = &c_info->hw; + struct ipq9574_edma_txcmpl_ring *txcmpl_ring; + struct ipq9574_edma_rxdesc_ring *rxdesc_ring; + struct ipq9574_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]; + ipq9574_edma_clean_rx(c_info, rxdesc_ring); + } + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + ipq9574_edma_clean_tx(ehw, txcmpl_ring); + } + + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + ipq9574_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]; + ipq9574_edma_reg_write( + IPQ9574_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]; + ipq9574_edma_reg_write(IPQ9574_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]; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_INT_MASK( + rxfill_ring->id), + ehw->rxfill_intr_mask); + } + + /* + * Read Misc intr status + */ + reg_data = ipq9574_edma_reg_read(IPQ9574_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); + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_MISC_INT_MASK, + IPQ9574_EDMA_MASK_INT_DISABLE); + } + + return 0; +} + +/* + * ipq9574_eth_snd() + * Transmit a packet using an EDMA ring + */ +static int ipq9574_eth_snd(struct eth_device *dev, void *packet, int length) +{ + struct ipq9574_eth_dev *priv = dev->priv; + struct ipq9574_edma_common_info *c_info = priv->c_info; + struct ipq9574_edma_hw *ehw = &c_info->hw; + struct ipq9574_edma_txdesc_desc *txdesc; + struct ipq9574_edma_tx_preheader *txph; + struct ipq9574_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 */ + ipq9574_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 = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id)); + + hw_next_to_use = data & IPQ9574_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 = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id)); + + hw_next_to_clean = data & IPQ9574_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 = IPQ9574_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 ipq9574_edma_tx_preheader *)skb; + + memset((void *)txph, 0, IPQ9574_EDMA_TX_PREHDR_SIZE); + +#ifdef CONFIG_IPQ9574_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 = (IPQ9574_EDMA_PREHDR_DSTINFO_PORTID_IND << 8) | + (IPQ9574_EDMA_MAC_PORT_NO & 0x0fff); + +#endif + + /* + * Set opaque field in preheader + */ + txph->opaque = cpu_to_le32(skb); + + /* + * copy the packet + */ + memcpy(skb + IPQ9574_EDMA_TX_PREHDR_SIZE, packet, length); + + /* + * Populate Tx descriptor + */ + txdesc->word1 |= (1 << IPQ9574_EDMA_TXDESC_PREHEADER_SHIFT) + | ((IPQ9574_EDMA_TX_PREHDR_SIZE & + IPQ9574_EDMA_TXDESC_DATA_OFFSET_MASK) + << IPQ9574_EDMA_TXDESC_DATA_OFFSET_SHIFT); + txdesc->word1 |= ((length & IPQ9574_EDMA_TXDESC_DATA_LENGTH_MASK) + << IPQ9574_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 + */ + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id), hw_next_to_use & + IPQ9574_EDMA_TXDESC_PROD_IDX_MASK); + + pr_debug("%s: successfull\n", __func__); + + return EDMA_TX_OK; +} + +static int ipq9574_eth_recv(struct eth_device *dev) +{ + struct ipq9574_eth_dev *priv = dev->priv; + struct ipq9574_edma_common_info *c_info = priv->c_info; + struct ipq9574_edma_rxdesc_ring *rxdesc_ring; + struct ipq9574_edma_txcmpl_ring *txcmpl_ring; + struct ipq9574_edma_rxfill_ring *rxfill_ring; + struct ipq9574_edma_hw *ehw = &c_info->hw; + volatile u32 reg_data; + u32 rxdesc_intr_status = 0, txcmpl_intr_status = 0, rxfill_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 = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_RXDESC_INT_STAT( + rxdesc_ring->id)); + rxdesc_intr_status |= reg_data & + IPQ9574_EDMA_RXDESC_RING_INT_STATUS_MASK; + + /* + * Disable RxDesc intr + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_INT_MASK( + rxdesc_ring->id), + IPQ9574_EDMA_MASK_INT_DISABLE); + } + + /* + * Read TxCmpl intr status + */ + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + + reg_data = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_TX_INT_STAT( + txcmpl_ring->id)); + txcmpl_intr_status |= reg_data & + IPQ9574_EDMA_TXCMPL_RING_INT_STATUS_MASK; + + /* + * Disable TxCmpl intr + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_INT_MASK( + txcmpl_ring->id), + IPQ9574_EDMA_MASK_INT_DISABLE); + } + + /* + * Read RxFill intr status + */ + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + + reg_data = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_RXFILL_INT_STAT( + rxfill_ring->id)); + rxfill_intr_status |= reg_data & + IPQ9574_EDMA_RXFILL_RING_INT_STATUS_MASK; + + /* + * Disable RxFill intr + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_INT_MASK( + rxfill_ring->id), + IPQ9574_EDMA_MASK_INT_DISABLE); + } + + if ((rxdesc_intr_status != 0) || (txcmpl_intr_status != 0) || + (rxfill_intr_status != 0)) { + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_INT_MASK( + rxdesc_ring->id), + IPQ9574_EDMA_MASK_INT_DISABLE); + } + ipq9574_edma_rx_complete(c_info); + } + + return 0; +} + +/* + * ipq9574_edma_setup_ring_resources() + * Allocate/setup resources for EDMA rings + */ +static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) +{ + struct ipq9574_edma_txcmpl_ring *txcmpl_ring; + struct ipq9574_edma_txdesc_ring *txdesc_ring; + struct ipq9574_edma_rxfill_ring *rxfill_ring; + struct ipq9574_edma_rxdesc_ring *rxdesc_ring; + struct ipq9574_edma_txdesc_desc *tx_desc; + struct ipq9574_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 = IPQ9574_EDMA_RXFILL_RING_SIZE; + rxfill_ring->id = ehw->rxfill_ring_start + i; + rxfill_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq9574_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 = IPQ9574_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 = IPQ9574_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 ipq9574_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 = IPQ9574_EDMA_TXCMPL_RING_SIZE; + txcmpl_ring->id = ehw->txcmpl_ring_start + i; + txcmpl_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq9574_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 = IPQ9574_EDMA_TXDESC_RING_SIZE; + txdesc_ring->id = ehw->txdesc_ring_start + i; + txdesc_ring->desc = (void *)noncached_alloc( + sizeof(struct ipq9574_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(IPQ9574_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 = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, j); + tx_desc->buffer_addr = virt_to_phys(tx_buf); + tx_buf += IPQ9574_EDMA_TX_BUF_SIZE; + } + } + + pr_info("%s: successfull\n", __func__); + + return 0; + +} + +/* + * ipq9574_edma_free_desc() + * Free EDMA desc memory + */ +static void ipq9574_edma_free_desc(struct ipq9574_edma_common_info *c_info) +{ + struct ipq9574_edma_hw *ehw = &c_info->hw; + struct ipq9574_edma_txcmpl_ring *txcmpl_ring; + struct ipq9574_edma_txdesc_ring *txdesc_ring; + struct ipq9574_edma_rxfill_ring *rxfill_ring; + struct ipq9574_edma_rxdesc_ring *rxdesc_ring; + struct ipq9574_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) + ipq9574_free_mem(rxfill_ring->desc); + } + + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + if (rxdesc_ring->desc) + ipq9574_free_mem(rxdesc_ring->desc); + } + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + if (txcmpl_ring->desc) { + ipq9574_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 = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, 0); + if (tx_desc->buffer_addr) + ipq9574_free_mem((void *)tx_desc->buffer_addr); + ipq9574_free_mem(txdesc_ring->desc); + } + } +} + +/* + * ipq9574_edma_free_rings() + * Free EDMA software rings + */ +static void ipq9574_edma_free_rings(struct ipq9574_edma_common_info *c_info) +{ + struct ipq9574_edma_hw *ehw = &c_info->hw; + ipq9574_free_mem(ehw->rxfill_ring); + ipq9574_free_mem(ehw->rxdesc_ring); + ipq9574_free_mem(ehw->txdesc_ring); + ipq9574_free_mem(ehw->txcmpl_ring); +} + +static void ipq9574_edma_disable_rings(struct ipq9574_edma_hw *edma_hw) +{ + int i, desc_index; + u32 data; + + /* + * Disable Rx rings + */ + for (i = 0; i < IPQ9574_EDMA_MAX_RXDESC_RINGS; i++) { + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXDESC_CTRL(i)); + data &= ~IPQ9574_EDMA_RXDESC_RX_EN; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_CTRL(i), data); + } + + /* + * Disable RxFill Rings + */ + for (i = 0; i < IPQ9574_EDMA_MAX_RXFILL_RINGS; i++) { + data = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_RXFILL_RING_EN(i)); + data &= ~IPQ9574_EDMA_RXFILL_RING_EN; + ipq9574_edma_reg_write( + IPQ9574_EDMA_REG_RXFILL_RING_EN(i), data); + } + + /* + * Disable Tx rings + */ + for (desc_index = 0; desc_index < + IPQ9574_EDMA_MAX_TXDESC_RINGS; desc_index++) { + data = ipq9574_edma_reg_read( + IPQ9574_EDMA_REG_TXDESC_CTRL(desc_index)); + data &= ~IPQ9574_EDMA_TXDESC_TX_EN; + ipq9574_edma_reg_write( + IPQ9574_EDMA_REG_TXDESC_CTRL(desc_index), data); + } +} + +static void ipq9574_edma_disable_intr(struct ipq9574_edma_hw *ehw) +{ + int i; + + /* + * Disable interrupts + */ + for (i = 0; i < IPQ9574_EDMA_MAX_TXCMPL_RINGS; i++) + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_INT_MASK(i), 0); + + for (i = 0; i < IPQ9574_EDMA_MAX_RXFILL_RINGS; i++) + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_INT_MASK(i), 0); + + for (i = 0; i < IPQ9574_EDMA_MAX_RXDESC_RINGS; i++) + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RX_INT_CTRL(i), 0); + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_MISC_INT_MASK, + IPQ9574_EDMA_MASK_INT_DISABLE); +} + +static void set_sgmii_mode(int port_id, int sg_mode) +{ + if (port_id == 3) + sgmii_mode[0] = sg_mode; + else if (port_id == 4) + sgmii_mode[1] = sg_mode; +} + +static int get_sgmii_mode(int port_id) +{ + if (port_id == 3) + return sgmii_mode[0]; + else if (port_id == 4) + return sgmii_mode[1]; + else + return -1; +} + +static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this) +{ + struct ipq9574_eth_dev *priv = eth_dev->priv; + int i; + u8 status; + struct phy_ops *phy_get_ops; + static fal_port_speed_t old_speed[IPQ9574_PHY_MAX] = {[0 ... IPQ9574_PHY_MAX-1] = FAL_SPEED_BUTT}; + static fal_port_speed_t curr_speed[IPQ9574_PHY_MAX]; + 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, aquantia_port = -1; + int sfp_port = -1; + int phy_node = -1; + int ret_sgmii_mode; + int sfp_mode, sgmii_fiber = -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); + + if (node >= 0) + aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_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 < IPQ9574_PHY_MAX; i++) { + + if (i == sfp_port) { + status = phy_status_get_from_ppe(i); + duplex = FAL_FULL_DUPLEX; + sfp_mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode1", -1); + if (sfp_mode < 0) { + printf("\nError: switch_mac_mode1 not specified in dts"); + return sfp_mode; + } + if (sfp_mode == PORT_WRAPPER_SGMII_FIBER) { + sgmii_fiber = 1; + curr_speed[i] = FAL_SPEED_1000; + } else if (sfp_mode == PORT_WRAPPER_10GBASE_R) { + sgmii_fiber = 0; + curr_speed[i] = FAL_SPEED_10000; + } else { + + printf("\nError: wrong mode specified for SFP Port"); + return sfp_mode; + } + } 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 if (i == aquantia_port) + phy_addr = AQU_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, &curr_speed[i]); + phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex); + } + + if (status == 0) { + linkup++; + if (old_speed[i] == curr_speed[i]) { + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + dp[duplex]); + continue; + } else { + old_speed[i] = curr_speed[i]; + } + } else { + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + dp[duplex]); + continue; + } + + switch (curr_speed[i]) { + case FAL_SPEED_10: + mac_speed = 0x0; + if (i == aquantia_port) { + printf("10M speed not supported\n"); + ppe_port_bridge_txmac_set(i + 1, status); + continue; + } + speed_clock1 = 0x109; + speed_clock2 = 0x9; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + dp[duplex]); + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) { + set_sgmii_mode(i, 1); + if (i == 4) + speed_clock1 = 0x309; + } + } + break; + case FAL_SPEED_100: + mac_speed = 0x1; + if (i == aquantia_port) { + speed_clock1 = 0x309; + speed_clock2 = 0x4; + } else { + speed_clock1 = 0x109; + speed_clock2 = 0x0; + } + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + dp[duplex]); + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) { + set_sgmii_mode(i, 1); + if (i == 4) + speed_clock1 = 0x309; + } + } + break; + case FAL_SPEED_1000: + mac_speed = 0x2; + if (i == aquantia_port) + speed_clock1 = 0x304; + else if (i == sfp_port) + 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], curr_speed[i], + dp[duplex]); + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) { + set_sgmii_mode(i, 1); + if (i == 4) + speed_clock1 = 0x301; + } + } + break; + case FAL_SPEED_2500: + if (i == aquantia_port) { + mac_speed = 0x4; + speed_clock1 = 0x307; + speed_clock2 = 0x0; + } + if (phy_node >= 0) { + if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) { + mac_speed = 0x2; + set_sgmii_mode(i, 0); + if (i == 4) + speed_clock1 = 0x301; + else if (i == 3) + speed_clock1 = 0x101; + speed_clock2 = 0x0; + } + } + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + dp[duplex]); + break; + case FAL_SPEED_5000: + mac_speed = 0x5; + speed_clock1 = 0x303; + speed_clock2 = 0x0; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + dp[duplex]); + break; + case FAL_SPEED_10000: + mac_speed = 0x3; + speed_clock1 = 0x301; + speed_clock2 = 0x0; + printf ("eth%d PHY%d %s Speed :%d %s duplex\n", + priv->mac_unit, i, lstatus[status], curr_speed[i], + 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); + ppe_port_bridge_txmac_set(i + 1, 1); + if (ret_sgmii_mode == 1) { + if (i == 4) + ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII0_RGMII4); + else if (i == 3) + ppe_uniphy_mode_set(0x0, PORT_WRAPPER_SGMII0_RGMII4); + + } else if (ret_sgmii_mode == 0) { + if (i == 4) + ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII_PLUS); + else if (i == 3) + ppe_uniphy_mode_set(0x0, PORT_WRAPPER_SGMII_PLUS); + } + } + } + + if (i == sfp_port) { + if (sgmii_fiber) { + ppe_port_bridge_txmac_set(i + 1, 1); + ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII_FIBER); + ppe_port_mux_mac_type_set(i + 1, PORT_WRAPPER_SGMII_FIBER); + } else { + ppe_uniphy_mode_set(0x1, PORT_WRAPPER_10GBASE_R); + ppe_port_mux_mac_type_set(i + 1, PORT_WRAPPER_10GBASE_R); + } + } + + ipq9574_speed_clock_set(i, speed_clock1, speed_clock2); + + ipq9574_port_mac_clock_reset(i); + + if (i == aquantia_port) + ipq9574_uxsgmii_speed_set(i, mac_speed, duplex, status); + else if (i == sfp_port && sgmii_fiber == 0) + ipq9574_10g_r_speed_set(i, status); + else + ipq9574_pqsgmii_speed_set(i, mac_speed, status); + } + + if (linkup <= 0) { + /* No PHY link is alive */ + return -1; + } + + pr_info("%s: done\n", __func__); + + return 0; +} + +static int ipq9574_edma_wr_macaddr(struct eth_device *dev) +{ + return 0; +} + +static void ipq9574_eth_halt(struct eth_device *dev) +{ + pr_info("%s: done\n", __func__); +} + +static void ipq9574_edma_set_ring_values(struct ipq9574_edma_hw *edma_hw) +{ + edma_hw->txdesc_ring_start = IPQ9574_EDMA_TX_DESC_RING_START; + edma_hw->txdesc_rings = IPQ9574_EDMA_TX_DESC_RING_NOS; + edma_hw->txdesc_ring_end = IPQ9574_EDMA_TX_DESC_RING_SIZE; + + edma_hw->txcmpl_ring_start = IPQ9574_EDMA_TX_CMPL_RING_START; + edma_hw->txcmpl_rings = IPQ9574_EDMA_RX_FILL_RING_NOS; + edma_hw->txcmpl_ring_end = IPQ9574_EDMA_TX_CMPL_RING_SIZE; + + edma_hw->rxfill_ring_start = IPQ9574_EDMA_RX_FILL_RING_START; + edma_hw->rxfill_rings = IPQ9574_EDMA_RX_FILL_RING_NOS; + edma_hw->rxfill_ring_end = IPQ9574_EDMA_RX_FILL_RING_SIZE; + + edma_hw->rxdesc_ring_start = IPQ9574_EDMA_RX_DESC_RING_START; + edma_hw->rxdesc_rings = IPQ9574_EDMA_RX_DESC_RING_NOS; + edma_hw->rxdesc_ring_end = IPQ9574_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)); +} + +/* + * ipq9574_edma_alloc_rings() + * Allocate EDMA software rings + */ +static int ipq9574_edma_alloc_rings(struct ipq9574_edma_hw *ehw) +{ + ehw->rxfill_ring = (void *)noncached_alloc((sizeof( + struct ipq9574_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 ipq9574_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 ipq9574_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 ipq9574_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; + +} + + +/* + * ipq9574_edma_init_rings() + * Initialize EDMA rings + */ +static int ipq9574_edma_init_rings(struct ipq9574_edma_hw *ehw) +{ + int ret; + + /* + * Setup ring values + */ + ipq9574_edma_set_ring_values(ehw); + + /* + * Allocate desc rings + */ + ret = ipq9574_edma_alloc_rings(ehw); + if (ret) + return ret; + + /* + * Setup ring resources + */ + ret = ipq9574_edma_setup_ring_resources(ehw); + if (ret) + return ret; + + return 0; +} + +/* + * ipq9574_edma_configure_txdesc_ring() + * Configure one TxDesc ring + */ +static void ipq9574_edma_configure_txdesc_ring(struct ipq9574_edma_hw *ehw, + struct ipq9574_edma_txdesc_ring *txdesc_ring) +{ + uint32_t data; + uint16_t hw_cons_idx; + + /* + * Configure TXDESC ring + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_BA(txdesc_ring->id), + (uint32_t)(txdesc_ring->dma & + IPQ9574_EDMA_RING_DMA_MASK)); + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_RING_SIZE( + txdesc_ring->id), (uint32_t)(txdesc_ring->count & + IPQ9574_EDMA_TXDESC_RING_SIZE_MASK)); + + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXDESC_CONS_IDX( + txdesc_ring->id)); + + data &= ~(IPQ9574_EDMA_TXDESC_CONS_IDX_MASK); + hw_cons_idx = data; + + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id)); + + data &= ~(IPQ9574_EDMA_TXDESC_PROD_IDX_MASK); + data |= hw_cons_idx & IPQ9574_EDMA_TXDESC_PROD_IDX_MASK; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id), data); +} + +/* + * ipq9574_edma_configure_txcmpl_ring() + * Configure one TxCmpl ring + */ +static void ipq9574_edma_configure_txcmpl_ring(struct ipq9574_edma_hw *ehw, + struct ipq9574_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 + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXCMPL_BA(txcmpl_ring->id), + (uint32_t)(txcmpl_ring->dma & + IPQ9574_EDMA_RING_DMA_MASK)); + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXCMPL_RING_SIZE( + txcmpl_ring->id), (uint32_t)(txcmpl_ring->count & + IPQ9574_EDMA_TXDESC_RING_SIZE_MASK)); + + /* + * Set TxCmpl ret mode to opaque + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id), + IPQ9574_EDMA_TXCMPL_RETMODE_OPAQUE); + + txcmpl_ugt_thre = (low_thre & IPQ9574_EDMA_TXCMPL_LOW_THRE_MASK) << + IPQ9574_EDMA_TXCMPL_LOW_THRE_SHIFT; + + txcmpl_ugt_thre |= (txcmpl_fc_thre & IPQ9574_EDMA_TXCMPL_FC_THRE_MASK) + << IPQ9574_EDMA_TXCMPL_FC_THRE_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXCMPL_UGT_THRE( + txcmpl_ring->id), txcmpl_ugt_thre); + + tx_mod_timer = (IPQ9574_EDMA_TX_MOD_TIMER & + IPQ9574_EDMA_TX_MOD_TIMER_INIT_MASK) << + IPQ9574_EDMA_TX_MOD_TIMER_INIT_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id), + tx_mod_timer); + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_INT_CTRL(txcmpl_ring->id), + 0x2); +} + +/* + * ipq9574_edma_configure_rxdesc_ring() + * Configure one RxDesc ring + */ +static void ipq9574_edma_configure_rxdesc_ring(struct ipq9574_edma_hw *ehw, + struct ipq9574_edma_rxdesc_ring *rxdesc_ring) +{ + uint32_t data; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_BA(rxdesc_ring->id), + (uint32_t)(rxdesc_ring->dma & 0xffffffff)); + + data = rxdesc_ring->count & IPQ9574_EDMA_RXDESC_RING_SIZE_MASK; + data |= (ehw->rx_payload_offset & + IPQ9574_EDMA_RXDESC_PL_OFFSET_MASK) << + IPQ9574_EDMA_RXDESC_PL_OFFSET_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_RING_SIZE( + rxdesc_ring->id), data); + + data = (IPQ9574_EDMA_RXDESC_XON_THRE & + IPQ9574_EDMA_RXDESC_FC_XON_THRE_MASK) << + IPQ9574_EDMA_RXDESC_FC_XON_THRE_SHIFT; + + data |= (IPQ9574_EDMA_RXDESC_XOFF_THRE & + IPQ9574_EDMA_RXDESC_FC_XOFF_THRE_MASK) << + IPQ9574_EDMA_RXDESC_FC_XOFF_THRE_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_FC_THRE( + rxdesc_ring->id), data); + + data = (IPQ9574_EDMA_RXDESC_LOW_THRE & + IPQ9574_EDMA_RXDESC_LOW_THRE_MASK) << + IPQ9574_EDMA_RXDESC_LOW_THRE_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_UGT_THRE( + rxdesc_ring->id), data); + + data = (IPQ9574_EDMA_RX_MOD_TIMER_INIT & + IPQ9574_EDMA_RX_MOD_TIMER_INIT_MASK) << + IPQ9574_EDMA_RX_MOD_TIMER_INIT_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RX_MOD_TIMER( + rxdesc_ring->id), data); + + /* + * Enable ring. Set ret mode to 'opaque'. + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RX_INT_CTRL( + rxdesc_ring->id), 0x2); +} + +/* + * ipq9574_edma_configure_rxfill_ring() + * Configure one RxFill ring + */ +static void ipq9574_edma_configure_rxfill_ring(struct ipq9574_edma_hw *ehw, + struct ipq9574_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; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_BA(rxfill_ring->id), + (uint32_t)(rxfill_ring->dma & IPQ9574_EDMA_RING_DMA_MASK)); + + data = rxfill_ring->count & IPQ9574_EDMA_RXFILL_RING_SIZE_MASK; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->id), data); + + rxfill_fc_thre = (rxfill_xon_thre & IPQ9574_EDMA_RXFILL_FC_XON_THRE_MASK) + << IPQ9574_EDMA_RXFILL_FC_XON_THRE_SHIFT; + rxfill_fc_thre |= (rxfill_xoff_thre & IPQ9574_EDMA_RXFILL_FC_XOFF_THRE_MASK) + << IPQ9574_EDMA_RXFILL_FC_XOFF_THRE_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_FC_THRE(rxfill_ring->id), + rxfill_fc_thre); + + rxfill_ugt_thre = (rxfill_low_thre & IPQ9574_EDMA_RXFILL_LOW_THRE_MASK) + << IPQ9574_EDMA_RXFILL_LOW_THRE_SHIFT; + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_UGT_THRE(rxfill_ring->id), + rxfill_ugt_thre); + +} + + +/* + * ipq9574_edma_configure_rings() + * Configure EDMA rings + */ +static void ipq9574_edma_configure_rings(struct ipq9574_edma_hw *ehw) +{ + int i; + + /* + * Configure TXDESC ring + */ + for (i = 0; i < ehw->txdesc_rings; i++) + ipq9574_edma_configure_txdesc_ring(ehw, &ehw->txdesc_ring[i]); + + /* + * Configure TXCMPL ring + */ + for (i = 0; i < ehw->txcmpl_rings; i++) + ipq9574_edma_configure_txcmpl_ring(ehw, &ehw->txcmpl_ring[i]); + + /* + * Configure RXFILL rings + */ + for (i = 0; i < ehw->rxfill_rings; i++) + ipq9574_edma_configure_rxfill_ring(ehw, &ehw->rxfill_ring[i]); + + /* + * Configure RXDESC ring + */ + for (i = 0; i < ehw->rxdesc_rings; i++) + ipq9574_edma_configure_rxdesc_ring(ehw, &ehw->rxdesc_ring[i]); + + pr_info("%s: successfull\n", __func__); +} + +/* + * ipq9574_edma_hw_reset() + * EDMA hw reset + */ +void ipq9574_edma_hw_reset(void) +{ + writel(GCC_EDMA_HW_RESET_ASSERT, GCC_NSS_PPE_RESET); + udelay(100); + writel(GCC_EDMA_HW_RESET_DEASSERT, GCC_NSS_PPE_RESET); + udelay(100); +} + +/* + * ipq9574_edma_hw_init() + * EDMA hw init + */ +int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) +{ + int ret, desc_index; + uint32_t i, reg; + volatile uint32_t data; + + struct ipq9574_edma_rxdesc_ring *rxdesc_ring = NULL; + + ipq9574_ppe_provision_init(); + + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_MAS_CTRL); + printf("EDMA ver %d hw init\n", data); + + /* + * Setup private data structure + */ + ehw->rxfill_intr_mask = IPQ9574_EDMA_RXFILL_INT_MASK; + ehw->rxdesc_intr_mask = IPQ9574_EDMA_RXDESC_INT_MASK_PKT_INT; + ehw->txcmpl_intr_mask = IPQ9574_EDMA_TX_INT_MASK_PKT_INT | + IPQ9574_EDMA_TX_INT_MASK_UGT_INT; + ehw->misc_intr_mask = 0; + ehw->rx_payload_offset = IPQ9574_EDMA_RX_PREHDR_SIZE; + + /* + * Reset EDMA + */ + ipq9574_edma_hw_reset(); + + /* + * Disable interrupts + */ + ipq9574_edma_disable_intr(ehw); + + /* + * Disable rings + */ + ipq9574_edma_disable_rings(ehw); + + ret = ipq9574_edma_init_rings(ehw); + + if (ret) + return ret; + + ipq9574_edma_configure_rings(ehw); + + /* + * 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; + reg = IPQ9574_EDMA_QID2RID_TABLE_MEM(0); + data = 0; + data |= (desc_index & 0xF); + ipq9574_edma_reg_write(reg, data); + pr_debug("Configure QID2RID reg:0x%x to 0x%x\n", reg, data); + + /* + * 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. + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC2FILL_MAP_0, 0); + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1, 0); + + for (i = ehw->rxdesc_ring_start; + i < ehw->rxdesc_ring_end; i++) { + if ((i >= 0) && (i <= 9)) + reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_0; + else + reg = IPQ9574_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 = ipq9574_edma_reg_read(reg); + data |= (rxdesc_ring->rxfill->id & 0x7) << ((i % 10) * 3); + ipq9574_edma_reg_write(reg, data); + } + + reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_0; + pr_debug("EDMA_REG_RXDESC2FILL_MAP_0: 0x%x\n", + ipq9574_edma_reg_read(reg)); + reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1; + pr_debug("EDMA_REG_RXDESC2FILL_MAP_1: 0x%x\n", + ipq9574_edma_reg_read(reg)); + + /* + * Enable EDMA + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_PORT_CTRL, + IPQ9574_EDMA_PORT_CTRL_EN); + + /* + * Enable Rx rings + */ + for (i = ehw->rxdesc_ring_start; i < ehw->rxdesc_ring_end; i++) { + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXDESC_CTRL(i)); + data |= IPQ9574_EDMA_RXDESC_RX_EN; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_CTRL(i), data); + } + + for (i = ehw->rxfill_ring_start; i < ehw->rxfill_ring_end; i++) { + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXFILL_RING_EN(i)); + data |= IPQ9574_EDMA_RXFILL_RING_EN; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_RING_EN(i), data); + } + + /* + * Enable Tx rings + */ + for (i = ehw->txdesc_ring_start; i < ehw->txdesc_ring_end; i++) { + data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXDESC_CTRL(i)); + data |= IPQ9574_EDMA_TXDESC_TX_EN; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_CTRL(i), data); + } + + /* + * Enable MISC interrupt + */ + ipq9574_edma_reg_write(IPQ9574_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 < IPQ9574_PHY_MAX; i++) + phy_info[i] = ipq9574_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 ipq9574_edma_init(void *edma_board_cfg) +{ + struct eth_device *dev[IPQ9574_EDMA_DEV]; + struct ipq9574_edma_common_info *c_info[IPQ9574_EDMA_DEV]; + struct ipq9574_edma_hw *hw[IPQ9574_EDMA_DEV]; + uchar enet_addr[IPQ9574_EDMA_DEV * 6]; + int i, phy_id; + uint32_t phy_chip_id, phy_chip_id1, phy_chip_id2; + int ret = -1; + ipq9574_edma_board_cfg_t ledma_cfg, *edma_cfg; + static int sw_init_done = 0; + int port_8033 = -1, node, phy_addr, aquantia_port = -1; + 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); + + if (node >= 0) + aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_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) * IPQ9574_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, IPQ9574_EDMA_DEV); + + /* + * Register EDMA as single ethernet + * interface. + */ + for (i = 0; i < IPQ9574_EDMA_DEV; edma_cfg++, i++) { + dev[i] = ipq9574_alloc_mem(sizeof(struct eth_device)); + + if (!dev[i]) + goto init_failed; + + memset(dev[i], 0, sizeof(struct eth_device)); + + c_info[i] = ipq9574_alloc_mem( + sizeof(struct ipq9574_edma_common_info)); + + if (!c_info[i]) + goto init_failed; + + memset(c_info[i], 0, + sizeof(struct ipq9574_edma_common_info)); + + hw[i] = &c_info[i]->hw; + + c_info[i]->hw.hw_addr = (unsigned long __iomem *) + IPQ9574_EDMA_CFG_BASE; + + ipq9574_edma_dev[i] = ipq9574_alloc_mem( + sizeof(struct ipq9574_eth_dev)); + + if (!ipq9574_edma_dev[i]) + goto init_failed; + + memset (ipq9574_edma_dev[i], 0, + sizeof(struct ipq9574_eth_dev)); + + dev[i]->iobase = IPQ9574_EDMA_CFG_BASE; + dev[i]->init = ipq9574_eth_init; + dev[i]->halt = ipq9574_eth_halt; + dev[i]->recv = ipq9574_eth_recv; + dev[i]->send = ipq9574_eth_snd; + dev[i]->write_hwaddr = ipq9574_edma_wr_macaddr; + dev[i]->priv = (void *)ipq9574_edma_dev[i]; + + if ((ret < 0) || + (!is_valid_ethaddr(&enet_addr[edma_cfg->unit * 6]))) { + memcpy(&dev[i]->enetaddr[0], ipq9574_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); + + ipq9574_edma_dev[i]->dev = dev[i]; + ipq9574_edma_dev[i]->mac_unit = edma_cfg->unit; + ipq9574_edma_dev[i]->c_info = c_info[i]; + ipq9574_edma_hw_addr = IPQ9574_EDMA_CFG_BASE; + + ret = ipq_sw_mdio_init(edma_cfg->phy_name); + if (ret) + goto init_failed; + + for (phy_id = 0; phy_id < IPQ9574_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 if (phy_id == aquantia_port) + phy_addr = AQU_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; + if (phy_id == aquantia_port) { + phy_chip_id1 = ipq_mdio_read(phy_addr, (1<<30) |(1<<16) | QCA_PHY_ID1, NULL); + phy_chip_id2 = ipq_mdio_read(phy_addr, (1<<30) |(1<<16) | 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(&ipq9574_edma_dev[i]->ops[phy_id]) == 0) { + sw_init_done = 1; + } + } else { + ipq_qca8075_phy_map_ops(&ipq9574_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; +#ifdef CONFIG_QCA8033_PHY + case QCA8033_PHY: + ipq_qca8033_phy_init(&ipq9574_edma_dev[i]->ops[phy_id], phy_addr); + break; +#endif +#ifdef CONFIG_QCA8081_PHY + case QCA8081_PHY: + case QCA8081_1_1_PHY: + ipq_qca8081_phy_init(&ipq9574_edma_dev[i]->ops[phy_id], phy_addr); + break; +#endif +#ifdef CONFIG_IPQ9574_QCA_AQUANTIA_PHY + case AQUANTIA_PHY_107: + case AQUANTIA_PHY_109: + case AQUANTIA_PHY_111: + case AQUANTIA_PHY_112: + case AQUANTIA_PHY_111B0: + case AQUANTIA_PHY_112C: + ipq_board_fw_download(phy_addr); + ipq_qca_aquantia_phy_init(&ipq9574_edma_dev[i]->ops[phy_id], phy_addr); + break; +#endif + default: + ipq_qca8075_phy_map_ops(&ipq9574_edma_dev[i]->ops[phy_id]); + break; + } + } + + ret = ipq9574_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 < IPQ9574_EDMA_DEV; i++) { + if (dev[i]) { + eth_unregister(dev[i]); + ipq9574_free_mem(dev[i]); + } + if (c_info[i]) { + ipq9574_edma_free_desc(c_info[i]); + ipq9574_edma_free_rings(c_info[i]); + ipq9574_free_mem(c_info[i]); + } + if (ipq9574_edma_dev[i]) { + ipq9574_free_mem(ipq9574_edma_dev[i]); + } + } + + return -1; +} diff --git a/drivers/net/ipq9574/ipq9574_edma.h b/drivers/net/ipq9574/ipq9574_edma.h new file mode 100644 index 0000000000..a81118d763 --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_edma.h @@ -0,0 +1,327 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019, 2021, 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 __IPQ9574_EDMA__ +#define __IPQ9574_EDMA__ + +#define IPQ9574_NSS_DP_START_PHY_PORT 1 +#define IPQ9574_NSS_DP_MAX_PHY_PORTS 5 + +#define IPQ9574_EDMA_BUF_SIZE 2000 +#define IPQ9574_EDMA_DEVICE_NODE_NAME "edma" +#define IPQ9574_EDMA_RX_BUFF_SIZE (IPQ9574_EDMA_BUF_SIZE + IPQ9574_EDMA_RX_PREHDR_SIZE) +#define IPQ9574_EDMA_RX_PREHDR_SIZE (sizeof(struct ipq9574_edma_rx_preheader)) +#define IPQ9574_EDMA_TX_PREHDR_SIZE (sizeof(struct ipq9574_edma_tx_preheader)) + +#define IPQ9574_EDMA_TXDESC_RING_SIZE 8 +#define IPQ9574_EDMA_TXCMPL_RING_SIZE 8 +#define IPQ9574_EDMA_RXDESC_RING_SIZE 16 +#define IPQ9574_EDMA_RXFILL_RING_SIZE 16 + +#define IPQ9574_EDMA_START_GMACS IPQ9574_NSS_DP_START_PHY_PORT +#define IPQ9574_EDMA_MAX_GMACS IPQ9574_NSS_DP_MAX_PHY_PORTS +#define IPQ9574_EDMA_TX_BUF_SIZE (1540 + IPQ9574_EDMA_TX_PREHDR_SIZE) + +#define IPQ9574_EDMA_MAX_TXCMPL_RINGS 24 /* Max TxCmpl rings */ +#define IPQ9574_EDMA_MAX_RXDESC_RINGS 16 /* Max RxDesc rings */ +#define IPQ9574_EDMA_MAX_RXFILL_RINGS 8 /* Max RxFill rings */ +#define IPQ9574_EDMA_MAX_TXDESC_RINGS 24 /* Max TxDesc rings */ + +#define IPQ9574_EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) +#define IPQ9574_EDMA_RXFILL_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_rxfill_desc) +#define IPQ9574_EDMA_RXDESC_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_rxdesc_desc) +#define IPQ9574_EDMA_TXDESC_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_txdesc_desc) +#define IPQ9574_EDMA_TXCMPL_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_txcmpl_desc) +#define IPQ9574_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) (((rxph)->src_info >> 8) & 0xf0) + +#define IPQ9574_EDMA_DEV 1 +#define IPQ9574_EDMA_TX_QUEUE 1 +#define IPQ9574_EDMA_RX_QUEUE 1 + +#define IPQ9574_EDMA_TX_DESC_RING_START 0 +#define IPQ9574_EDMA_TX_DESC_RING_NOS 1 +#define IPQ9574_EDMA_TX_DESC_RING_SIZE \ +(IPQ9574_EDMA_TX_DESC_RING_START + IPQ9574_EDMA_TX_DESC_RING_NOS) + +#define IPQ9574_EDMA_TX_CMPL_RING_START 0 +#define IPQ9574_EDMA_TX_CMPL_RING_NOS 8 +#define IPQ9574_EDMA_TX_CMPL_RING_SIZE \ +(IPQ9574_EDMA_TX_CMPL_RING_START + IPQ9574_EDMA_TX_CMPL_RING_NOS) + +#define IPQ9574_EDMA_RX_DESC_RING_START 15 +#define IPQ9574_EDMA_RX_DESC_RING_NOS 1 +#define IPQ9574_EDMA_RX_DESC_RING_SIZE \ +(IPQ9574_EDMA_RX_DESC_RING_START + IPQ9574_EDMA_RX_DESC_RING_NOS) + +#define IPQ9574_EDMA_RX_FILL_RING_START 7 +#define IPQ9574_EDMA_RX_FILL_RING_NOS 1 +#define IPQ9574_EDMA_RX_FILL_RING_SIZE \ +(IPQ9574_EDMA_RX_FILL_RING_START + IPQ9574_EDMA_RX_FILL_RING_NOS) + +#define IPQ9574_EDMA_TX_IMR_NORMAL_MASK 1 +#define IPQ9574_EDMA_RX_IMR_NORMAL_MASK 1 +#define IPQ9574_EDMA_INTR_CLEAR_TYPE 0 +#define IPQ9574_EDMA_INTR_SW_IDX_W_TYPE 0 +#define IPQ9574_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 ipq9574_edma_txdesc_desc { + uint32_t buffer_addr; + /* buffer address */ + uint32_t word1; + /* more bit, TSO, preheader, pool, offset and length */ +}; + +/* + * TxCmpl descriptor + */ +struct ipq9574_edma_txcmpl_desc { + uint32_t buffer_addr; /* buffer address/opaque */ + uint32_t status; /* status */ +}; + +/* + * Rx descriptor + */ +struct ipq9574_edma_rxdesc_desc { + uint32_t buffer_addr; /* buffer address */ + uint32_t status; /* status */ +}; + +/* + * RxFill descriptor + */ +struct ipq9574_edma_rxfill_desc { + uint32_t buffer_addr; /* Buffer address */ + uint32_t word1; /* opaque_ind and buffer size */ +}; + +/* + * Tx descriptor ring + */ +struct ipq9574_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 ipq9574_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 ipq9574_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 ipq9574_edma_rxdesc_ring { + uint32_t id; /* RXDESC ring number */ + struct ipq9574_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 ipq9574_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 ipq9574_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 ipq9574_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 ipq9574_edma_common_info *c_info; /* edma common info */ +}; + +/* edma hw specific data */ +struct ipq9574_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 ipq9574_edma_txdesc_ring *txdesc_ring; /* Tx Descriptor Ring, SW is producer */ + struct ipq9574_edma_txcmpl_ring *txcmpl_ring; /* Tx Completion Ring, SW is consumer */ + struct ipq9574_edma_rxdesc_ring *rxdesc_ring; /* Rx Descriptor Ring, SW is consumer */ + struct ipq9574_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 ipq9574_edma_common_info { + struct ipq9574_edma_hw hw; +}; + +#define MAX_PHY 6 +struct ipq9574_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 ipq9574_edma_common_info *c_info; + struct phy_ops *ops[MAX_PHY]; + const char phy_name[MDIO_NAME_LEN]; +} __attribute__ ((aligned(8))); + +static inline void* ipq9574_alloc_mem(u32 size) +{ + void *p = malloc(size); + if (p != NULL) + memset(p, 0, size); + return p; +} + +static inline void* ipq9574_alloc_memalign(u32 size) +{ + void *p = memalign(CONFIG_SYS_CACHELINE_SIZE, size); + if (p != NULL) + memset(p, 0, size); + return p; +} + +static inline void ipq9574_free_mem(void *ptr) +{ + if (ptr) + free(ptr); +} + +uint32_t ipq9574_edma_reg_read(uint32_t reg_off); +void ipq9574_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]; +} ipq9574_edma_phy_addr_t; + +/* ipq9574 edma Paramaters */ +typedef struct { + uint base; + int unit; + uint mac_conn_to_phy; + phy_interface_t phy; + ipq9574_edma_phy_addr_t phy_addr; + char phy_name[MDIO_NAME_LEN]; +} ipq9574_edma_board_cfg_t; + +extern void ipq9574_ppe_provision_init(void); +extern void ipq9574_port_mac_clock_reset(int port); +extern void ipq9574_speed_clock_set(int port, int speed_clock1, int speed_clock2); +extern void ipq9574_pqsgmii_speed_set(int port, int speed, int status); +extern void ipq9574_uxsgmii_speed_set(int port, int speed, int duplex, int status); +extern void ppe_port_mux_mac_type_set(int port_id, int mode); +extern void ppe_port_bridge_txmac_set(int port, int status); +extern void ipq9574_10g_r_speed_set(int port, int status); +extern int phy_status_get_from_ppe(int port_id); + +extern void ipq9574_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 /* ___IPQ9574_EDMA__ */ diff --git a/drivers/net/ipq9574/ipq9574_ppe.c b/drivers/net/ipq9574/ipq9574_ppe.c new file mode 100644 index 0000000000..9a8b1f067a --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_ppe.c @@ -0,0 +1,1351 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019, 2021, 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 "ipq9574_ppe.h" +#include "ipq9574_uniphy.h" +#include +#include "ipq_phy.h" + +DECLARE_GLOBAL_DATA_PTR; +#define pr_info(fmt, args...) printf(fmt, ##args); +/* + * ipq9574_ppe_gpio_reg_write() + */ +static inline void ipq9574_ppe_gpio_reg_write(u32 reg, u32 val) +{ + writel(val, IPQ9574_PPE_FPGA_GPIO_BASE_ADDR + reg); +} + +/* + * ipq9574_ppe_reg_read() + */ +static inline void ipq9574_ppe_reg_read(u32 reg, u32 *val) +{ + *val = readl((void *)(IPQ9574_PPE_BASE_ADDR + reg)); +} + +/* + * ipq9574_ppe_reg_write() + */ +static inline void ipq9574_ppe_reg_write(u32 reg, u32 val) +{ + writel(val, (void *)(IPQ9574_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++) { + ipq9574_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++) { + ipq9574_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++) { + ipq9574_ppe_reg_write((IPE_L2_BASE_ADDR + IPO_ACTION_ADDRESS + + (rule_id * IPO_ACTION_INC) + (i * 4)), hw_act->val[i]); + } +} + +void ipq9574_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); + } + } +} + +/* + * ipq9574_ppe_vp_port_tbl_set() + */ +static void ipq9574_ppe_vp_port_tbl_set(int port, int vsi) +{ + u32 addr = IPQ9574_PPE_L3_VP_PORT_TBL_ADDR + + (port * IPQ9574_PPE_L3_VP_PORT_TBL_INC); + ipq9574_ppe_reg_write(addr, 0x0); + ipq9574_ppe_reg_write(addr + 0x4 , 1 << 9 | vsi << 10); + ipq9574_ppe_reg_write(addr + 0x8, 0x0); +} + +/* + * ipq9574_ppe_ucast_queue_map_tbl_queue_id_set() + */ +static void ipq9574_ppe_ucast_queue_map_tbl_queue_id_set(int queue, int port) +{ + uint32_t val; + + ipq9574_ppe_reg_read(IPQ9574_PPE_QM_UQM_TBL + + (port * IPQ9574_PPE_UCAST_QUEUE_MAP_TBL_INC), &val); + + val |= queue << 4; + + ipq9574_ppe_reg_write(IPQ9574_PPE_QM_UQM_TBL + + (port * IPQ9574_PPE_UCAST_QUEUE_MAP_TBL_INC), val); +} + +/* + * ipq9574_vsi_setup() + */ +static void ipq9574_vsi_setup(int vsi, uint8_t group_mask) +{ + uint32_t val = (group_mask << 24 | group_mask << 16 | group_mask << 8 + | group_mask); + + /* Set mask */ + ipq9574_ppe_reg_write(0x061800 + (vsi * 0x10), val); + + /* new addr lrn en | station move lrn en */ + ipq9574_ppe_reg_write(0x061804 + (vsi * 0x10), 0x9); +} + +/* + * ipq9574_gmac_port_enable() + */ +static void ipq9574_gmac_port_enable(int port) +{ + ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_ENABLE + (0x200 * port), 0x70); + ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_SPEED + (0x200 * port), 0x2); + ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_MIB_CTL + (0x200 * port), 0x1); +} + +/* + * ipq9574_port_mac_clock_reset() + */ +void ipq9574_port_mac_clock_reset(int port) +{ + switch(port) { + case 0: + writel(NSS_PORT1_ASSERT, GCC_NSS_PPE_RESET); + mdelay(150); + writel(PPE_DEASSERT, GCC_NSS_PPE_RESET); + break; + case 1: + writel(NSS_PORT2_ASSERT, GCC_NSS_PPE_RESET); + mdelay(150); + writel(PPE_DEASSERT, GCC_NSS_PPE_RESET); + break; + case 2: + writel(NSS_PORT3_ASSERT, GCC_NSS_PPE_RESET); + mdelay(150); + writel(PPE_DEASSERT, GCC_NSS_PPE_RESET); + break; + case 3: + writel(NSS_PORT4_ASSERT, GCC_NSS_PPE_RESET); + mdelay(150); + writel(PPE_DEASSERT, GCC_NSS_PPE_RESET); + break; + case 4: + writel(NSS_PORT5_ASSERT, GCC_NSS_PPE_RESET); + mdelay(150); + writel(PPE_DEASSERT, GCC_NSS_PPE_RESET); + break; + } +} + +void ipq9574_speed_clock_set(int port, int speed_clock1, int speed_clock2) +{ + int i; + uint32_t reg_value; + + for (i = 0; i < 2; i++) + { + /* gcc port first clock divider */ + reg_value = 0; + reg_value = readl(GCC_NSS_PORT1_RX_CFG_RCGR + i*8 + port*0x10); + reg_value &= ~0x71f; + reg_value |= speed_clock1; + writel(reg_value, GCC_NSS_PORT1_RX_CFG_RCGR + i*8 + port*0x10); + /* gcc port second clock divider */ + reg_value = 0; + reg_value = readl(GCC_NSS_PORT1_RX_MISC + i*4 + port*0x10); + reg_value &= ~0xf; + reg_value |= speed_clock2; + writel(reg_value, GCC_NSS_PORT1_RX_MISC + i*4 + port*0x10); + /* update above clock configuration */ + reg_value = 0; + reg_value = readl(GCC_NSS_PORT1_RX_CMD_RCGR + i*8 + port*0x10); + reg_value &= ~0x1; + reg_value |= 0x1; + writel(reg_value, GCC_NSS_PORT1_RX_CMD_RCGR + i*8 + port*0x10); + } +} + +int phy_status_get_from_ppe(int port_id) +{ + uint32_t reg_field = 0; + + ipq9574_ppe_reg_read(PORT_PHY_STATUS_ADDRESS, ®_field); + if (port_id == (PORT5 - PPE_UNIPHY_INSTANCE1)) + reg_field >>= PORT_PHY_STATUS_PORT5_1_OFFSET; + + return ((reg_field >> 7) & 0x1) ? 0 : 1; +} + +void ppe_port_bridge_txmac_set(int port_id, int status) +{ + uint32_t reg_value = 0; + + ipq9574_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; + + ipq9574_ppe_reg_write(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS + + (port_id * PORT_BRIDGE_CTRL_INC), reg_value); + +} + +void ipq9574_pqsgmii_speed_set(int port, int speed, int status) +{ + ppe_port_bridge_txmac_set(port + 1, status); + ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_SPEED + (0x200 * port), speed); + ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_ENABLE + (0x200 * port), 0x73); +} + +void ppe_xgmac_speed_set(uint32_t uniphy_index, int speed) +{ + uint32_t reg_value = 0; + + ipq9574_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; + ipq9574_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; + + ipq9574_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), ®_value); + + reg_value |=JD; + ipq9574_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; + + ipq9574_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + (uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), ®_value); + + reg_value |=TE; + ipq9574_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; + + ipq9574_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; + ipq9574_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) +{ + ipq9574_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 + + MAC_PACKET_FILTER_ADDRESS + + (uniphy_index * MAC_PACKET_FILTER_INC), 0x81); +} + +void ipq9574_10g_r_speed_set(int port, int status) +{ + uint32_t uniphy_index; + + /* Setting the speed only for PORT5 */ + uniphy_index = PPE_UNIPHY_INSTANCE1; + 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 ipq9574_uxsgmii_speed_set(int port, int speed, int duplex, + int status) +{ + uint32_t uniphy_index; + + /* Setting the speed only for PORT5 */ + uniphy_index = PPE_UNIPHY_INSTANCE1; + 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); +} +/* + * ipq9574_ppe_flow_port_map_tbl_port_num_set() + */ +static void ipq9574_ppe_flow_port_map_tbl_port_num_set(int queue, int port) +{ + ipq9574_ppe_reg_write(IPQ9574_PPE_L0_FLOW_PORT_MAP_TBL + + queue * IPQ9574_PPE_L0_FLOW_PORT_MAP_TBL_INC, port); + ipq9574_ppe_reg_write(IPQ9574_PPE_L1_FLOW_PORT_MAP_TBL + + port * IPQ9574_PPE_L1_FLOW_PORT_MAP_TBL_INC, port); +} + +/* + * ipq9574_ppe_flow_map_tbl_set() + */ +static void ipq9574_ppe_flow_map_tbl_set(int queue, int port) +{ + uint32_t val = port | 0x401000; /* c_drr_wt = 1, e_drr_wt = 1 */ + ipq9574_ppe_reg_write(IPQ9574_PPE_L0_FLOW_MAP_TBL + queue * IPQ9574_PPE_L0_FLOW_MAP_TBL_INC, + val); + + val = port | 0x100400; /* c_drr_wt = 1, e_drr_wt = 1 */ + ipq9574_ppe_reg_write(IPQ9574_PPE_L1_FLOW_MAP_TBL + port * IPQ9574_PPE_L1_FLOW_MAP_TBL_INC, + val); +} + +/* + * ipq9574_ppe_tdm_configuration + */ +static void ipq9574_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 + */ + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_QTI1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_QTI3); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_QTI2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_QTI4); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID + | IPQ9574_PPE_TDM_CFG_DIR_EGRESS + | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_QTI1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_QTI3); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_QTI2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_QTI4); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_INGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ9574_PPE_TDM_CFG_VALID | + IPQ9574_PPE_TDM_CFG_DIR_EGRESS | + IPQ9574_PPE_PORT_CRYPTO1); + + /* Set TDM Depth to 100 entries */ + ipq9574_ppe_reg_write(IPQ9574_PPE_TDM_CFG_DEPTH_OFFSET, IPQ9574_PPE_TDM_CFG_DEPTH_VAL); +} + +/* + * ipq9574_ppe_sched_configuration + */ +static void ipq9574_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 =((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + * IPQ9574_PPE_PORT_XGMAC1_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + * IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + * IPQ9574_PPE_PORT_XGMAC2 | IPQ9574_PPE_PORT_EDMA); + */ + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_XGMAC1_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI3_BITPOS | IPQ9574_PPE_PORT_QTI2_BITPOS | + IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI4 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_QTI4_BITPOS | + IPQ9574_PPE_PORT_QTI3_BITPOS | IPQ9574_PPE_PORT_QTI2_BITPOS | + IPQ9574_PPE_PORT_QTI1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_XGMAC2_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_CRYPTO1 << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_QTI1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_QTI2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_XGMAC1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_XGMAC2_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_CRYPTO1 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_QTI3); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI3 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_XGMAC1_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_QTI4); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_XGMAC2_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI4 << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_XGMAC2_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_CRYPTO1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_QTI2_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_QTI1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI1 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_QTI2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_XGMAC2_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI2 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_XGMAC1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_CRYPTO1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_XGMAC2_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_CRYPTO1 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_QTI3); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC2 << 4) | IPQ9574_PPE_PORT_EDMA); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC2_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_QTI3 << 4) | IPQ9574_PPE_PORT_XGMAC1); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_EDMA_BITPOS | + IPQ9574_PPE_PORT_QTI4_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_EDMA << 4) | IPQ9574_PPE_PORT_XGMAC2); + ipq9574_ppe_reg_write(IPQ9574_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ9574_PPE_PORT_CRYPTO1_BITPOS | IPQ9574_PPE_PORT_XGMAC1_BITPOS | + IPQ9574_PPE_PORT_EDMA_BITPOS | IPQ9574_PPE_PORT_QTI3_BITPOS | + IPQ9574_PPE_PORT_QTI2_BITPOS | IPQ9574_PPE_PORT_QTI1_BITPOS) << 8) | + (IPQ9574_PPE_PORT_XGMAC1 << 4) | IPQ9574_PPE_PORT_QTI4); + + /* Set Sched Depth to 50 entries */ + ipq9574_ppe_reg_write(IPQ9574_PPE_TDM_SCHED_DEPTH_OFFSET, IPQ9574_PPE_TDM_SCHED_DEPTH_VAL); +} + +/* + * ipq9574_ppe_c_sp_cfg_tbl_drr_id_set + */ +static void ipq9574_ppe_c_sp_cfg_tbl_drr_id_set(int id) +{ + ipq9574_ppe_reg_write(IPQ9574_PPE_L0_C_SP_CFG_TBL + (id * 0x80), id * 2); + ipq9574_ppe_reg_write(IPQ9574_PPE_L1_C_SP_CFG_TBL + (id * 0x80), id * 2); +} + +/* + * ipq9574_ppe_e_sp_cfg_tbl_drr_id_set + */ +static void ipq9574_ppe_e_sp_cfg_tbl_drr_id_set(int id) +{ + ipq9574_ppe_reg_write(IPQ9574_PPE_L0_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1); + ipq9574_ppe_reg_write(IPQ9574_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; + int nodeoff; + + nodeoff = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + + ipq9574_ppe_reg_read(IPQ9574_PORT_MUX_CTRL, &(port_mux_ctrl.val)); + + switch (port_id) { + case 3: + case 4: + if (mode == PORT_WRAPPER_SGMII_PLUS || mode == PORT_WRAPPER_SGMII0_RGMII4) { + port_mux_ctrl.bf.port3_pcs_sel = CPPE_PORT3_PCS_SEL_PCS0_CHANNEL2; + port_mux_ctrl.bf.port4_pcs_sel = CPPE_PORT4_PCS_SEL_PCS0_SGMIIPLUS; + port_mux_ctrl.bf.pcs0_ch0_sel = CPPE_PCS0_CHANNEL0_SEL_SGMIIPLUS; + port_mux_ctrl.bf.pcs0_ch4_sel = CPPE_PCS0_CHANNEL4_SEL_PORT5_CLOCK; + } else if (mode == PORT_WRAPPER_PSGMII || mode == PORT_WRAPPER_QSGMII) { + if (fdtdec_get_int(gd->fdt_blob, nodeoff, "malibu2port_phy", 0)) { + port_mux_ctrl.bf.port3_pcs_sel = CPPE_PORT3_PCS_SEL_PCS0_CHANNEL4; + port_mux_ctrl.bf.port4_pcs_sel = CPPE_PORT4_PCS_SEL_PCS0_CHANNEL3; + port_mux_ctrl.bf.pcs0_ch4_sel = CPPE_PCS0_CHANNEL4_SEL_PORT3_CLOCK; + } else { + port_mux_ctrl.bf.port3_pcs_sel = CPPE_PORT3_PCS_SEL_PCS0_CHANNEL2; + port_mux_ctrl.bf.port4_pcs_sel = CPPE_PORT4_PCS_SEL_PCS0_CHANNEL3; + port_mux_ctrl.bf.pcs0_ch0_sel = CPPE_PCS0_CHANNEL0_SEL_PSGMII; + port_mux_ctrl.bf.pcs0_ch4_sel = CPPE_PCS0_CHANNEL4_SEL_PORT5_CLOCK; + } + } + break; + case 5: + if (mode == PORT_WRAPPER_SGMII_PLUS || mode == PORT_WRAPPER_SGMII0_RGMII4 || + mode == PORT_WRAPPER_SGMII_FIBER) { + port_mux_ctrl.bf.port5_pcs_sel = CPPE_PORT5_PCS_SEL_PCS1_CHANNEL0; + port_mux_ctrl.bf.port5_gmac_sel = CPPE_PORT5_GMAC_SEL_GMAC; + } else if (mode == PORT_WRAPPER_PSGMII) { + port_mux_ctrl.bf.port5_pcs_sel = CPPE_PORT5_PCS_SEL_PCS0_CHANNEL4; + port_mux_ctrl.bf.port5_gmac_sel = CPPE_PORT5_GMAC_SEL_GMAC; + } else if (mode == PORT_WRAPPER_USXGMII || mode == PORT_WRAPPER_10GBASE_R) { + port_mux_ctrl.bf.port5_pcs_sel = CPPE_PORT5_PCS_SEL_PCS1_CHANNEL0; + port_mux_ctrl.bf.port5_gmac_sel = CPPE_PORT5_GMAC_SEL_XGMAC; + } + break; + default: + break; + } + + ipq9574_ppe_reg_write(IPQ9574_PORT_MUX_CTRL, port_mux_ctrl.val); +} + +void ppe_port_mux_mac_type_set(int port_id, int mode) +{ + uint32_t port_type; + + switch(mode) + { + case PORT_WRAPPER_PSGMII: + case PORT_WRAPPER_SGMII0_RGMII4: + case PORT_WRAPPER_SGMII_PLUS: + case PORT_WRAPPER_SGMII_FIBER: + port_type = PORT_GMAC_TYPE; + break; + case PORT_WRAPPER_USXGMII: + case PORT_WRAPPER_10GBASE_R: + port_type = PORT_XGMAC_TYPE; + break; + default: + return; + } + ppe_port_mux_set(port_id, port_type, mode); +} + + + +void ipq9574_ppe_interface_mode_init(void) +{ + uint32_t mode0, mode1; + 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; + } + + ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE0, mode0); + ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE1, mode1); + + ppe_port_mux_mac_type_set(4, mode0); + ppe_port_mux_mac_type_set(5, mode1); +} + +/* + * ipq9574_ppe_provision_init() + */ +void ipq9574_ppe_provision_init(void) +{ + int i; + uint32_t queue; + + /* tdm/sched configuration */ + ipq9574_ppe_tdm_configuration(); + ipq9574_ppe_sched_configuration(); + + /* disable clock gating */ + ipq9574_ppe_reg_write(0x000008, 0x0); + + /* flow ctrl disable */ + ipq9574_ppe_reg_write(0x200368, 0xc88); + +#ifdef CONFIG_IPQ9574_BRIDGED_MODE + /* Add CPU port 0 to VSI 2 */ + ipq9574_ppe_vp_port_tbl_set(0, 2); + + /* Add port 1 - 4 to VSI 2 */ + ipq9574_ppe_vp_port_tbl_set(1, 2); + ipq9574_ppe_vp_port_tbl_set(2, 2); + ipq9574_ppe_vp_port_tbl_set(3, 2); + ipq9574_ppe_vp_port_tbl_set(4, 2); + ipq9574_ppe_vp_port_tbl_set(5, 2); + +#else + ipq9574_ppe_vp_port_tbl_set(1, 2); + ipq9574_ppe_vp_port_tbl_set(2, 3); + ipq9574_ppe_vp_port_tbl_set(3, 4); + ipq9574_ppe_vp_port_tbl_set(4, 5); +#endif + + /* Unicast priority map */ + ipq9574_ppe_reg_write(IPQ9574_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); + + ipq9574_ppe_ucast_queue_map_tbl_queue_id_set(queue, i); + ipq9574_ppe_flow_port_map_tbl_port_num_set(queue, i); + ipq9574_ppe_flow_map_tbl_set(queue, i); + ipq9574_ppe_c_sp_cfg_tbl_drr_id_set(i); + ipq9574_ppe_e_sp_cfg_tbl_drr_id_set(i); + } + + /* Port0 multicast queue */ + ipq9574_ppe_reg_write(0x409000, 0x00000000); + ipq9574_ppe_reg_write(0x403000, 0x00401000); + + /* Port1 - 7 multicast queue */ + for (i = 1; i < 8; i++) { + ipq9574_ppe_reg_write(0x409100 + ((i - 1) * 0x40), i); + ipq9574_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++) + ipq9574_ppe_reg_write(IPQ9574_PPE_PORT_BRIDGE_CTRL_OFFSET + (i * 4), + IPQ9574_PPE_PORT_BRIDGE_CTRL_PROMISC_EN | + IPQ9574_PPE_PORT_BRIDGE_CTRL_TXMAC_EN | + IPQ9574_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP | + IPQ9574_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN | + IPQ9574_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN); + + ipq9574_ppe_reg_write(IPQ9574_PPE_PORT_BRIDGE_CTRL_OFFSET + (7 * 4), + IPQ9574_PPE_PORT_BRIDGE_CTRL_PROMISC_EN | + IPQ9574_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP | + IPQ9574_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN | + IPQ9574_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN); + + /* Global learning */ + ipq9574_ppe_reg_write(0x060038, 0xc0); + +#ifdef CONFIG_IPQ9574_BRIDGED_MODE + ipq9574_vsi_setup(2, 0x3f); +#else + ipq9574_vsi_setup(2, 0x03); + ipq9574_vsi_setup(3, 0x05); + ipq9574_vsi_setup(4, 0x09); + ipq9574_vsi_setup(5, 0x11); +#endif + + /* Port 0-7 STP */ + for (i = 0; i < 8; i++) + ipq9574_ppe_reg_write(IPQ9574_PPE_STP_BASE + (0x4 * i), 0x3); + + ipq9574_ppe_interface_mode_init(); + /* Port 0-4 disable */ + for (i = 0; i < 5; i++) { + ipq9574_gmac_port_enable(i); + ppe_port_bridge_txmac_set(i + 1, 1); + } + + /* Allowing DHCP packets */ + ipq9574_ppe_acl_set(0, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 67, 0xffff, 0, 0); + ipq9574_ppe_acl_set(1, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 68, 0xffff, 0, 0); + /* Dropping all the UDP packets */ + ipq9574_ppe_acl_set(2, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 0, 0, 0, 1); +} diff --git a/drivers/net/ipq9574/ipq9574_ppe.h b/drivers/net/ipq9574/ipq9574_ppe.h new file mode 100644 index 0000000000..63063bdc4e --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_ppe.h @@ -0,0 +1,255 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2019, 2021, 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 IPQ9574_PPE_BASE_ADDR 0x3a000000 +#define IPQ9574_PPE_REG_SIZE 0x1000000 + +#define PORT4 4 +#define PORT5 5 +#define PORT_GMAC_TYPE 1 +#define PORT_XGMAC_TYPE 2 + +struct port_mux_ctrl { + uint32_t port3_pcs_sel:2; + uint32_t port4_pcs_sel:2; + uint32_t port5_pcs_sel:2; + uint32_t port5_gmac_sel:1; + uint32_t pcs0_ch4_sel:1; + uint32_t pcs0_ch0_sel:1; + uint32_t _reserved0:23; +}; + +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 IPQ9574_PORT_MUX_CTRL 0x10 +#define CPPE_PORT3_PCS_SEL_PCS0_CHANNEL2 0 +#define CPPE_PORT3_PCS_SEL_PCS0_CHANNEL4 1 +#define CPPE_PORT4_PCS_SEL_PCS0_CHANNEL3 0 +#define CPPE_PORT4_PCS_SEL_PCS0_SGMIIPLUS 1 +#define CPPE_PORT5_PCS_SEL_PCS0_CHANNEL4 0 +#define CPPE_PORT5_PCS_SEL_PCS1_CHANNEL0 1 +#define CPPE_PORT5_GMAC_SEL_GMAC 0 +#define CPPE_PORT5_GMAC_SEL_XGMAC 1 +#define CPPE_PCS0_CHANNEL4_SEL_PORT5_CLOCK 0x0 +#define CPPE_PCS0_CHANNEL4_SEL_PORT3_CLOCK 0x1 +#define CPPE_PCS0_CHANNEL0_SEL_PSGMII 0x0 +#define CPPE_PCS0_CHANNEL0_SEL_SGMIIPLUS 0x1 +#define CPPE_DETECTION_PHY_FAILURE 0xFFFF + +#define PORT_PHY_STATUS_ADDRESS 0x44 +#define PORT_PHY_STATUS_PORT5_1_OFFSET 16 + +#define IPQ9574_PPE_IPE_L3_BASE_ADDR 0x200000 +#define IPQ9574_PPE_L3_VP_PORT_TBL_ADDR (IPQ9574_PPE_IPE_L3_BASE_ADDR + 0x1000) +#define IPQ9574_PPE_L3_VP_PORT_TBL_INC 0x10 + +#define IPQ9574_PPE_QUEUE_MANAGER_BASE_ADDR 0x800000 +#define IPQ9574_PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x10000 +#define IPQ9574_PPE_UCAST_QUEUE_MAP_TBL_INC 0x10 +#define IPQ9574_PPE_QM_UQM_TBL (IPQ9574_PPE_QUEUE_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_UCAST_QUEUE_MAP_TBL_ADDR) +#define IPQ9574_PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x42000 +#define IPQ9574_PPE_QM_UPM_TBL (IPQ9574_PPE_QUEUE_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_UCAST_PRIORITY_MAP_TBL_ADDR) + +#define IPQ9574_PPE_STP_BASE 0x060100 +#define IPQ9574_PPE_MAC_ENABLE 0x001000 +#define IPQ9574_PPE_MAC_SPEED 0x001004 +#define IPQ9574_PPE_MAC_MIB_CTL 0x001034 + +#define IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR 0x400000 + +#define IPQ9574_PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x8000 +#define IPQ9574_PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10 +#define IPQ9574_PPE_L0_FLOW_PORT_MAP_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L0_FLOW_PORT_MAP_TBL_ADDR) + +#define IPQ9574_PPE_L0_FLOW_MAP_TBL_ADDR 0x2000 +#define IPQ9574_PPE_L0_FLOW_MAP_TBL_INC 0x10 +#define IPQ9574_PPE_L0_FLOW_MAP_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L0_FLOW_MAP_TBL_ADDR) + +#define IPQ9574_PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x46000 +#define IPQ9574_PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10 +#define IPQ9574_PPE_L1_FLOW_PORT_MAP_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L1_FLOW_PORT_MAP_TBL_ADDR) + +#define IPQ9574_PPE_L1_FLOW_MAP_TBL_ADDR 0x40000 +#define IPQ9574_PPE_L1_FLOW_MAP_TBL_INC 0x10 +#define IPQ9574_PPE_L1_FLOW_MAP_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L1_FLOW_MAP_TBL_ADDR) + +#define IPQ9574_PPE_L0_C_SP_CFG_TBL_ADDR 0x4000 +#define IPQ9574_PPE_L0_C_SP_CFG_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L0_C_SP_CFG_TBL_ADDR) + +#define IPQ9574_PPE_L1_C_SP_CFG_TBL_ADDR 0x42000 +#define IPQ9574_PPE_L1_C_SP_CFG_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L1_C_SP_CFG_TBL_ADDR) + +#define IPQ9574_PPE_L0_E_SP_CFG_TBL_ADDR 0x6000 +#define IPQ9574_PPE_L0_E_SP_CFG_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L0_E_SP_CFG_TBL_ADDR) + +#define IPQ9574_PPE_L1_E_SP_CFG_TBL_ADDR 0x44000 +#define IPQ9574_PPE_L1_E_SP_CFG_TBL (IPQ9574_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ9574_PPE_L1_E_SP_CFG_TBL_ADDR) + +#define IPQ9574_PPE_FPGA_GPIO_BASE_ADDR 0x01008000 + +#define IPQ9574_PPE_MAC_PORT_MUX_OFFSET 0x10 +#define IPQ9574_PPE_FPGA_GPIO_OFFSET 0xc000 +#define IPQ9574_PPE_FPGA_SCHED_OFFSET 0x47a000 +#define IPQ9574_PPE_TDM_CFG_DEPTH_OFFSET 0xb000 +#define IPQ9574_PPE_TDM_SCHED_DEPTH_OFFSET 0x400000 +#define IPQ9574_PPE_PORT_BRIDGE_CTRL_OFFSET 0x060300 + +#define IPQ9574_PPE_TDM_CFG_DEPTH_VAL 0x80000064 +#define IPQ9574_PPE_MAC_PORT_MUX_OFFSET_VAL 0x15 +#define IPQ9574_PPE_TDM_SCHED_DEPTH_VAL 0x32 +#define IPQ9574_PPE_TDM_CFG_VALID 0x20 +#define IPQ9574_PPE_TDM_CFG_DIR_INGRESS 0x0 +#define IPQ9574_PPE_TDM_CFG_DIR_EGRESS 0x10 +#define IPQ9574_PPE_PORT_EDMA 0x0 +#define IPQ9574_PPE_PORT_QTI1 0x1 +#define IPQ9574_PPE_PORT_QTI2 0x2 +#define IPQ9574_PPE_PORT_QTI3 0x3 +#define IPQ9574_PPE_PORT_QTI4 0x4 +#define IPQ9574_PPE_PORT_XGMAC1 0x5 +#define IPQ9574_PPE_PORT_XGMAC2 0x6 +#define IPQ9574_PPE_PORT_CRYPTO1 0x7 +#define IPQ9574_PPE_PORT_BRIDGE_CTRL_PROMISC_EN 0x20000 +#define IPQ9574_PPE_PORT_BRIDGE_CTRL_TXMAC_EN 0x10000 +#define IPQ9574_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP 0x7f00 +#define IPQ9574_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN 0x8 +#define IPQ9574_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN 0x1 + +#define IPQ9574_PPE_PORT_EDMA_BITPOS 0x1 +#define IPQ9574_PPE_PORT_QTI1_BITPOS (1 << IPQ9574_PPE_PORT_QTI1) +#define IPQ9574_PPE_PORT_QTI2_BITPOS (1 << IPQ9574_PPE_PORT_QTI2) +#define IPQ9574_PPE_PORT_QTI3_BITPOS (1 << IPQ9574_PPE_PORT_QTI3) +#define IPQ9574_PPE_PORT_QTI4_BITPOS (1 << IPQ9574_PPE_PORT_QTI4) +#define IPQ9574_PPE_PORT_XGMAC1_BITPOS (1 << IPQ9574_PPE_PORT_XGMAC1) +#define IPQ9574_PPE_PORT_XGMAC2_BITPOS (1 << IPQ9574_PPE_PORT_XGMAC2) +#define IPQ9574_PPE_PORT_CRYPTO1_BITPOS (1 << IPQ9574_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/ipq9574/ipq9574_uniphy.c b/drivers/net/ipq9574/ipq9574_uniphy.c new file mode 100644 index 0000000000..5e33db195a --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_uniphy.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2017-2019, 2021, 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 "ipq9574_edma.h" +#include "ipq9574_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; + + reg_value = readl(GCC_UNIPHY0_MISC + (uniphy_index * GCC_UNIPHY_REG_INC)); + + if(enable) + reg_value |= GCC_UNIPHY_USXGMII_XPCS_RESET; + else + reg_value &= ~GCC_UNIPHY_USXGMII_XPCS_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 == 0) + reg_value |= GCC_UNIPHY_PSGMII_SOFT_RESET; + else + reg_value |= GCC_UNIPHY_SGMII_SOFT_RESET; + + writel(reg_value, GCC_UNIPHY0_MISC + (uniphy_index * GCC_UNIPHY_REG_INC)); + + udelay(500); + + if (uniphy_index == 0) + reg_value &= ~GCC_UNIPHY_PSGMII_SOFT_RESET; + else + reg_value &= ~GCC_UNIPHY_SGMII_SOFT_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 mode) +{ + 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); + 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); + + if (uniphy_index == 0) { + writel(0x0, GCC_UNIPHY0_PORT4_RX_CBCR); + writel(0x0, GCC_UNIPHY0_PORT4_TX_CBCR); + writel(0x0, GCC_NSS_PORT4_RX_CBCR); + writel(0x0, GCC_NSS_PORT4_TX_CBCR); + } else { + writel(0x0, GCC_UNIPHY1_PORT5_RX_CBCR); + writel(0x0, GCC_UNIPHY1_PORT5_TX_CBCR); + writel(0x0, GCC_NSS_PORT5_RX_CBCR); + writel(0x0, GCC_NSS_PORT5_RX_CBCR); + } + + switch (mode) { + case PORT_WRAPPER_SGMII_FIBER: + writel(0x400, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + break; + + case PORT_WRAPPER_SGMII0_RGMII4: + case PORT_WRAPPER_SGMII1_RGMII4: + case PORT_WRAPPER_SGMII4_RGMII4: + writel(0x420, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + break; + + case PORT_WRAPPER_SGMII_PLUS: + writel(0x820, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + PPE_UNIPHY_MODE_CONTROL); + break; + + default: + printf("SGMII Config. wrongly"); + break; + } + + ppe_gcc_uniphy_soft_reset(uniphy_index); + + if (uniphy_index == 0) { + writel(0x1, GCC_UNIPHY0_PORT4_RX_CBCR); + writel(0x1, GCC_UNIPHY0_PORT4_TX_CBCR); + writel(0x1, GCC_NSS_PORT4_RX_CBCR); + writel(0x1, GCC_NSS_PORT4_TX_CBCR); + } else { + writel(0x1, GCC_UNIPHY1_PORT5_RX_CBCR); + writel(0x1, GCC_UNIPHY1_PORT5_TX_CBCR); + writel(0x1, GCC_NSS_PORT5_RX_CBCR); + writel(0x1, GCC_NSS_PORT5_RX_CBCR); + } + + 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); +} + +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: + case PORT_WRAPPER_SGMII1_RGMII4: + case PORT_WRAPPER_SGMII4_RGMII4: + case PORT_WRAPPER_SGMII_PLUS: + case PORT_WRAPPER_SGMII_FIBER: + ppe_uniphy_sgmii_mode_set(uniphy_index, mode); + 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/ipq9574/ipq9574_uniphy.h b/drivers/net/ipq9574/ipq9574_uniphy.h new file mode 100644 index 0000000000..a48c17d7e0 --- /dev/null +++ b/drivers/net/ipq9574/ipq9574_uniphy.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017-2019, 2021, 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 GCC_UNIPHY1_PORT5_RX_CBCR 0x1856110 +#define GCC_UNIPHY1_PORT5_TX_CBCR 0x1856114 +#define GCC_NSS_PORT5_RX_CBCR 0x1868260 +#define GCC_NSS_PORT5_TX_CBCR 0x1868264 + +#define GCC_UNIPHY0_PORT4_RX_CBCR 0x1856028 +#define GCC_UNIPHY0_PORT4_TX_CBCR 0x185602C +#define GCC_NSS_PORT4_RX_CBCR 0x1868258 +#define GCC_NSS_PORT4_TX_CBCR 0x186825C + +#define GCC_UNIPHY0_MISC 0x01856004 +#define GCC_UNIPHY_REG_INC 0x100 +#define GCC_UNIPHY_USXGMII_XPCS_RESET 0x4 + +#define PPE_UNIPHY_OFFSET_CALIB_4 0x1E0 +#define UNIPHY_CALIBRATION_DONE 0x1 + +#define GCC_UNIPHY_PSGMII_SOFT_RESET 0x3ff2 +#define GCC_UNIPHY_SGMII_SOFT_RESET 0x32 + +#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/drivers/net/ipq_common/ipq_phy.h b/drivers/net/ipq_common/ipq_phy.h index 6ac7c224d9..1ff35cd196 100755 --- a/drivers/net/ipq_common/ipq_phy.h +++ b/drivers/net/ipq_common/ipq_phy.h @@ -18,6 +18,7 @@ #include #define PHY_MAX 6 +#define IPQ9574_PHY_MAX 5 #define IPQ6018_PHY_MAX 5 #define MDIO_CTRL_0_REG 0x00090040 #define MDIO_CTRL_0_DIV(x) (x << 0) diff --git a/include/configs/ipq9574.h b/include/configs/ipq9574.h index c6846c5893..146f72ee41 100644 --- a/include/configs/ipq9574.h +++ b/include/configs/ipq9574.h @@ -290,6 +290,21 @@ extern loff_t board_env_size; #define RPM_VERSION 3 #endif +#define CONFIG_IPQ9574_EDMA 1 +#define CONFIG_IPQ9574_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_IPQ_ETH_INIT_DEFER + /* * CRASH DUMP ENABLE */ diff --git a/include/dt-bindings/qcom/eth-ipq9574.h b/include/dt-bindings/qcom/eth-ipq9574.h new file mode 100644 index 0000000000..00e7f76c5e --- /dev/null +++ b/include/dt-bindings/qcom/eth-ipq9574.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, 2021, 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. + */ + +#ifndef __DT_BINDINGS_IPQ9574_ETH_H__ +#define __DT_BINDINGS_IPQ9574_ETH_H__ + +/* ESS Switch Mac Modes */ +#define PORT_WRAPPER_PSGMII 0x0 +#define PORT_WRAPPER_SGMII 0x1 +#define PORT_WRAPPER_USXGMII 0x2 +#define PORT_WRAPPER_QSGMII 0x5 +#define PORT_WRAPPER_SGMII_PLUS 0x6 +#define PORT_WRAPPER_10GBASE_R 0x7 +#define PORT_WRAPPER_SGMII_FIBER 0x8 +#define UNUSED 0xFF + +/* ETH PHY Types */ +#define MALIBU_PHY_TYPE 0x1 +#define QCA8081_PHY_TYPE 0x2 +#define AQ_PHY_TYPE 0x3 +#endif