diff --git a/arch/arm/include/asm/arch-ipq807x/edma_regs.h b/arch/arm/include/asm/arch-ipq807x/edma_regs.h new file mode 100644 index 0000000000..837e997129 --- /dev/null +++ b/arch/arm/include/asm/arch-ipq807x/edma_regs.h @@ -0,0 +1,398 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2017 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 IPQ807X_EDMA_CFG_BASE 0x3ab00000 +/* + * IPQ807X EDMA register offsets + */ +#define IPQ807X_EDMA_REG_MAS_CTRL 0x0 +#define IPQ807X_EDMA_REG_PORT_CTRL 0x4 +#define IPQ807X_EDMA_REG_VLAN_CTRL 0x8 +#define IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_0 0xc +#define IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_1 0x10 +#define IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_2 0x14 +#define IPQ807X_EDMA_REG_RXDESC2FILL_MAP_0 0x18 +#define IPQ807X_EDMA_REG_RXDESC2FILL_MAP_1 0x1c +#define IPQ807X_EDMA_REG_TXQ_CTRL 0x20 +#define IPQ807X_EDMA_REG_TXQ_CTRL_2 0x24 +#define IPQ807X_EDMA_REG_TXQ_FC_0 0x28 +#define IPQ807X_EDMA_REG_TXQ_FC_1 0x30 +#define IPQ807X_EDMA_REG_TXQ_FC_2 0x34 +#define IPQ807X_EDMA_REG_TXQ_FC_3 0x38 +#define IPQ807X_EDMA_REG_RXQ_CTRL 0x3c +#define IPQ807X_EDMA_REG_RX_TX_FULL_QID 0x40 +#define IPQ807X_EDMA_REG_RXQ_FC_THRE 0x44 +#define IPQ807X_EDMA_REG_DMAR_CTRL 0x48 +#define IPQ807X_EDMA_REG_AXIR_CTRL 0x4c +#define IPQ807X_EDMA_REG_AXIW_CTRL 0x50 +#define IPQ807X_EDMA_REG_MIN_MSS 0x54 +#define IPQ807X_EDMA_REG_LOOPBACK_CTRL 0x58 +#define IPQ807X_EDMA_REG_MISC_INT_STAT 0x5c +#define IPQ807X_EDMA_REG_MISC_INT_MASK 0x60 +#define IPQ807X_EDMA_REG_DBG_CTRL 0x64 +#define IPQ807X_EDMA_REG_DBG_DATA 0x68 +#define IPQ807X_EDMA_REG_TXDESC_BA(n) (0x1000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXDESC_PROD_IDX(n) (0x1004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXDESC_CONS_IDX(n) (0x1008 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXDESC_RING_SIZE(n) (0x100c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXDESC_CTRL(n) (0x1010 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_BA(n) (0x19000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_PROD_IDX(n) (0x19004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_CONS_IDX(n) (0x19008 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_RING_SIZE(n) (0x1900c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_UGT_THRE(n) (0x19010 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_CTRL(n) (0x19014 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TXCMPL_BPC(n) (0x19018 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TX_INT_STAT(n) (0x21000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TX_INT_MASK(n) (0x21004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TX_MOD_TIMER(n) (0x21008 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_TX_INT_CTRL(n) (0x2100c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_CONS_IDX(n) (0x29008 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_RING_SIZE(n) (0x2900c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_BUFFER1_SIZE(n) (0x29010 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_FC_THRE(n) (0x29014 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_UGT_THRE(n) (0x29018 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_RING_EN(n) (0x2901c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_DISABLE(n) (0x29020 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_DISABLE_DONE(n) (0x29024 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_INT_STAT(n) (0x31000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXFILL_INT_MASK(n) (0x31004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_BA(n) (0x39000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_PROD_IDX(n) (0x39004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_CONS_IDX(n) (0x39008 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_RING_SIZE(n) (0x3900c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_FC_THRE(n) (0x39010 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_UGT_THRE(n) (0x39014 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_BPC(n) (0x3901c + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_INT_STAT(n) (0x49000 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RXDESC_INT_MASK(n) (0x49004 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RX_MOD_TIMER(n) (0x49008 + (0x1000 * n)) +#define IPQ807X_EDMA_REG_RX_INT_CTRL(n) (0x4900c + (0x1000 * n)) +#define IPQ807X_EDMA_QID2RID_TABLE_MEM(q) (0x5a000 + (0x4 * q)) +#define IPQ807X_EDMA_REG_RXRING_PC(n) (0x5A200 + (0x10 * n)) +#define IPQ807X_EDMA_REG_RXRING_BC_0(n) (0x5A204 + (0x10 * n)) +#define IPQ807X_EDMA_REG_RXRING_BC_1(n) (0x5A208 + (0x10 * n)) +#define IPQ807X_EDMA_REG_TXRING_PC(n) (0x74000 + (0x10 * n)) +#define IPQ807X_EDMA_REG_TXRING_BC_0(n) (0x74004 + (0x10 * n)) +#define IPQ807X_EDMA_REG_TXRING_BC_1(n) (0x74008 + (0x10 * n)) + +/* + * EDMA_REG_PORT_CTRL register + */ +#define IPQ807X_EDMA_PORT_CTRL_EN 0x3 +#define IPQ807X_EDMA_PORT_CTRL_PAD_EN 0x1 + +/* + * EDMA_REG_TXQ_CTRL register + */ +#define IPQ807X_EDMA_TXDESC_PF_THRE_MASK 0xf +#define IPQ807X_EDMA_TXDESC_PF_THRE_SHIFT 0 +#define IPQ807X_EDMA_TXCMPL_WB_THRE_MASK 0xf +#define IPQ807X_EDMA_TXCMPL_WB_THRE_SHIFT 4 +#define IPQ807X_EDMA_TXDESC_PKT_SRAM_THRE_MASK 0xff +#define IPQ807X_EDMA_TXDESC_PKT_SRAM_THRE_SHIFT 8 +#define IPQ807X_EDMA_TXCMPL_WB_TIMER_MASK 0xffff +#define IPQ807X_EDMA_TXCMPL_WB_TIMER_SHIFT 16 + +/* + * EDMA_REG_RXQ_CTRL register + */ +#define IPQ807X_EDMA_RXFILL_PF_THRE_MASK 0xf +#define IPQ807X_EDMA_RXFILL_PF_THRE_SHIFT 0 +#define IPQ807X_EDMA_RXDESC_WB_THRE_MASK 0xf +#define IPQ807X_EDMA_RXDESC_WB_THRE_SHIFT 4 +#define IPQ807X_EDMA_RXDESC_WB_TIMER_MASK 0xffff +#define IPQ807X_EDMA_RXDESC_WB_TIMER_SHIFT 16 + +/* + * EDMA_REG_RX_TX_FULL_QID register + */ +#define IPQ807X_EDMA_RX_DESC_FULL_QID_MASK 0xff +#define IPQ807X_EDMA_RX_DESC_FULL_QID_SHIFT 0 +#define IPQ807X_EDMA_TX_CMPL_BUF_FULL_QID_MASK 0xff +#define IPQ807X_EDMA_TX_CMPL_BUF_FULL_QID_SHIFT 8 +#define IPQ807X_EDMA_TX_SRAM_FULL_QID_MASK 0x1f +#define IPQ807X_EDMA_TX_SRAM_FULL_QID_SHIFT 16 + +/* + * EDMA_REG_RXQ_FC_THRE reister + */ +#define IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE_MASK 0x1f +#define IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE_SHIFT 0 +#define IPQ807X_EDMA_DESC_FIFO_XOFF_THRE_MASK 0x3f +#define IPQ807X_EDMA_DESC_FIFO_XOFF_THRE_SHIFT 16 + +/* + * EDMA_REG_DMAR_CTRL register + */ +#define IPQ807X_EDMA_DMAR_REQ_PRI_MASK 0x7 +#define IPQ807X_EDMA_DMAR_REQ_PRI_SHIFT 0 +#define IPQ807X_EDMA_DMAR_BURST_LEN_MASK 0x1 +#define IPQ807X_EDMA_DMAR_BURST_LEN_SHIFT 3 +#define IPQ807X_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK 0x1f +#define IPQ807X_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT 4 +#define IPQ807X_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK 0x7 +#define IPQ807X_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT 9 +#define IPQ807X_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK 0x7 +#define IPQ807X_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT 12 + +/* + * EDMA DISABLE + */ +#define IPQ807X_EDMA_DISABLE 0 + +/* + * EDMA_REG_TXDESC_PROD_IDX register + */ +#define IPQ807X_EDMA_TXDESC_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_TXDESC_CONS_IDX register + */ +#define IPQ807X_EDMA_TXDESC_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_TXDESC_RING_SIZE register + */ +#define IPQ807X_EDMA_TXDESC_RING_SIZE_MASK 0xffff + +/* + * EDMA_REG_TXDESC_CTRL register + */ +#define IPQ807X_EDMA_TXDESC_ARB_GRP_ID_MASK 0x3 +#define IPQ807X_EDMA_TXDESC_ARB_GRP_ID_SHIFT 4 +#define IPQ807X_EDMA_TXDESC_FC_GRP_ID_MASK 0x7 +#define IPQ807X_EDMA_TXDESC_FC_GRP_ID_SHIFT 1 +#define IPQ807X_EDMA_TXDESC_TX_EN 0x1 + +/* + * EDMA_REG_TXCMPL_PROD_IDX register + */ +#define IPQ807X_EDMA_TXCMPL_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_CONS_IDX register + */ +#define IPQ807X_EDMA_TXCMPL_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_RING_SIZE register + */ +#define IPQ807X_EDMA_TXCMPL_RING_SIZE_MASK 0xffff + +/* + * EDMA_REG_TXCMPL_UGT_THRE register + */ +#define IPQ807X_EDMA_TXCMPL_LOW_THRE_MASK 0xffff +#define IPQ807X_EDMA_TXCMPL_LOW_THRE_SHIFT 0 +#define IPQ807X_EDMA_TXCMPL_FC_THRE_MASK 0x3f +#define IPQ807X_EDMA_TXCMPL_FC_THRE_SHIFT 16 + +/* + * EDMA_REG_TXCMPL_CTRL register + */ +#define IPQ807X_EDMA_TXCMPL_RET_MODE_BUFF_ADDR 0x0 +#define IPQ807X_EDMA_TXCMPL_RET_MODE_OPAQUE 0x1 + +/* + * EDMA_REG_TX_MOD_TIMER register + */ +#define IPQ807X_EDMA_TX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ807X_EDMA_TX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA_REG_TX_INT_CTRL register + */ +#define IPQ807X_EDMA_TX_INT_MASK 0x3 + +/* + * EDMA_REG_RXFILL_PROD_IDX register + */ +#define IPQ807X_EDMA_RXFILL_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_RXFILL_CONS_IDX register + */ +#define IPQ807X_EDMA_RXFILL_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_RXFILL_RING_SIZE register + */ +#define IPQ807X_EDMA_RXFILL_RING_SIZE_MASK 0xffff +#define IPQ807X_EDMA_RXFILL_BUF_SIZE_MASK 0x3fff +#define IPQ807X_EDMA_RXFILL_BUF_SIZE_SHIFT 16 + +/* + * EDMA_REG_RXFILL_FC_THRE register + */ +#define IPQ807X_EDMA_RXFILL_FC_XON_THRE_MASK 0x7ff +#define IPQ807X_EDMA_RXFILL_FC_XON_THRE_SHIFT 12 +#define IPQ807X_EDMA_RXFILL_FC_XOFF_THRE_MASK 0x7ff +#define IPQ807X_EDMA_RXFILL_FC_XOFF_THRE_SHIFT 0 + +/* + * EDMA_REG_RXFILL_UGT_THRE register + */ +#define IPQ807X_EDMA_RXFILL_LOW_THRE_MASK 0xffff +#define IPQ807X_EDMA_RXFILL_LOW_THRE_SHIFT 0 + +/* + * EDMA_REG_RXFILL_RING_EN register + */ +#define IPQ807X_EDMA_RXFILL_RING_EN 0x1 + +/* + * EDMA_REG_RXFILL_INT_MASK register + */ +#define IPQ807X_EDMA_RXFILL_INT_MASK 0x1 + +/* + * EDMA_REG_RXDESC_PROD_IDX register + */ +#define IPQ807X_EDMA_RXDESC_PROD_IDX_MASK 0xffff + +/* + * EDMA_REG_RXDESC_CONS_IDX register + */ +#define IPQ807X_EDMA_RXDESC_CONS_IDX_MASK 0xffff + +/* + * EDMA_REG_RXDESC_RING_SIZE register + */ +#define IPQ807X_EDMA_RXDESC_RING_SIZE_MASK 0xffff +#define IPQ807X_EDMA_RXDESC_PL_OFFSET_MASK 0x1ff +#define IPQ807X_EDMA_RXDESC_PL_OFFSET_SHIFT 16 + +/* + * EDMA_REG_RXDESC_FC_THRE register + */ +#define IPQ807X_EDMA_RXDESC_FC_XON_THRE_MASK 0x7ff +#define IPQ807X_EDMA_RXDESC_FC_XON_THRE_SHIFT 12 +#define IPQ807X_EDMA_RXDESC_FC_XOFF_THRE_MASK 0x7ff +#define IPQ807X_EDMA_RXDESC_FC_XOFF_THRE_SHIFT 0 + +/* + * EDMA_REG_RXDESC_UGT_THRE register + */ +#define IPQ807X_EDMA_RXDESC_LOW_THRE_MASK 0xffff +#define IPQ807X_EDMA_RXDESC_LOW_THRE_SHIFT 0 + +/* + * EDMA_REG_RXDESC_CTRL register + */ +#define IPQ807X_EDMA_RXDESC_STAG_REMOVE_EN 0x8 +#define IPQ807X_EDMA_RXDESC_CTAG_REMOVE_EN 0x4 +#define IPQ807X_EDMA_RXDESC_QDISC_EN 0x2 +#define IPQ807X_EDMA_RXDESC_RX_EN 0x1 + +/* + * EDMA_REG_TX_INT_MASK register + */ +#define IPQ807X_EDMA_TX_INT_MASK_PKT_INT 0x1 +#define IPQ807X_EDMA_TX_INT_MASK_UGT_INT 0x2 + +/* + * EDMA_REG_RXDESC_INT_STAT register + */ +#define IPQ807X_EDMA_RXDESC_INT_STAT_PKT_INT 0x1 +#define IPQ807X_EDMA_RXDESC_INT_STAT_UGT_INT 0x2 + +/* + * EDMA_REG_RXDESC_INT_MASK register + */ +#define IPQ807X_EDMA_RXDESC_INT_MASK_PKT_INT 0x1 +#define IPQ807X_EDMA_RXDESC_INT_MASK_TIMER_INT_DIS 0x2 + +#define IPQ807X_EDMA_MASK_INT_DISABLE 0x0 +#define IPQ807X_EDMA_MASK_INT_CLEAR 0x0 + +/* + * EDMA_REG_RX_MOD_TIMER register + */ +#define IPQ807X_EDMA_RX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ807X_EDMA_RX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA QID2RID register sizes + */ +#define IPQ807X_EDMA_QID2RID_DEPTH 0x40 +#define IPQ807X_EDMA_QID2RID_QUEUES_PER_ENTRY 8 + +/* + * TXDESC shift values + */ +#define IPQ807X_EDMA_TXDESC_MORE_SHIFT 31 +#define IPQ807X_EDMA_TXDESC_TSO_EN_SHIFT 30 +#define IPQ807X_EDMA_TXDESC_PREHEADER_SHIFT 29 +#define IPQ807X_EDMA_TXDESC_POOL_ID_SHIFT 24 +#define IPQ807X_EDMA_TXDESC_POOL_ID_MASK 0x1f +#define IPQ807X_EDMA_TXDESC_DATA_OFFSET_SHIFT 16 +#define IPQ807X_EDMA_TXDESC_DATA_OFFSET_MASK 0xff +#define IPQ807X_EDMA_TXDESC_DATA_LENGTH_SHIFT 0 +#define IPQ807X_EDMA_TXDESC_DATA_LENGTH_MASK 0xffff + +#define IPQ807X_EDMA_PREHDR_DSTINFO_PORTID_IND 0x20 +#define IPQ807X_EDMA_PREHDR_PORTNUM_BITS 0x0fff +#define IPQ807X_EDMA_RING_DMA_MASK 0xffffffff +/* + * RXDESC shift values + */ +#define IPQ807X_EDMA_RXDESC_RX_RXFILL_CNT_MASK 0x000f +#define IPQ807X_EDMA_RXDESC_RX_RXFILL_CNT_SHIFT 16 + +#define IPQ807X_EDMA_RXDESC_PKT_SIZE_MASK 0x3fff +#define IPQ807X_EDMA_RXDESC_PKT_SIZE_SHIFT 0 + +#define IPQ807X_EDMA_RXDESC_RXD_VALID_MASK 0x1 +#define IPQ807X_EDMA_RXDESC_RXD_VALID_SHIFT 31 + +#define IPQ807X_EDMA_RXDESC_PACKET_LEN_MASK 0x3fff +#define IPQ807X_EDMA_RXDESC_RING_INT_STATUS_MASK 0x3 + +#define IPQ807X_EDMA_RING_DISABLE 0 +#define IPQ807X_EDMA_TXCMPL_RING_INT_STATUS_MASK 0x3 +#define IPQ807X_EDMA_TXCMPL_RETMODE_OPAQUE 0x0 +#define IPQ807X_EDMA_RXFILL_RING_INT_STATUS_MASK 0x1 + +/* + * TODO tune the timer and threshold values + */ +#define IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE 0x3 +#define IPQ807X_EDMA_RXFILL_PF_THRE 0x3 +#define IPQ807X_EDMA_RXDESC_WB_THRE 0x0 +#define IPQ807X_EDMA_RXDESC_WB_TIMER 0x2 + +#define IPQ807X_EDMA_RXDESC_XON_THRE 50 +#define IPQ807X_EDMA_RXDESC_XOFF_THRE 30 +#define IPQ807X_EDMA_RXDESC_LOW_THRE 0 +#define IPQ807X_EDMA_RX_MOD_TIMER_INIT 1000 + +#define IPQ807X_EDMA_TXDESC_PF_THRE 0x3 +#define IPQ807X_EDMA_TXCMPL_WB_THRE 0X0 +#define IPQ807X_EDMA_TXDESC_PKT_SRAM_THRE 0x20 +#define IPQ807X_EDMA_TXCMPL_WB_TIMER 0x2 + +#define IPQ807X_EDMA_TX_MOD_TIMER 150 + +#endif /* __EDMA_REGS__ */ diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c index f7e14eb105..32182f8b55 100644 --- a/board/qca/arm/ipq807x/ipq807x.c +++ b/board/qca/arm/ipq807x/ipq807x.c @@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; qca_mmc mmc_host; extern int ipq_spi_init(u16); +extern int ipq807x_edma_init(void *cfg); const char *rsvd_node = "/reserved-memory"; const char *del_node[] = {"uboot", @@ -94,6 +95,18 @@ void emmc_clock_config(int mode) udelay(10); } +int board_eth_init(bd_t *bis) +{ + int ret; + + ret = ipq807x_edma_init(NULL); + + if (ret != 0) + printf("%s: ipq807x_edma_init failed : %d\n", __func__, ret); + + return ret; +} + int board_mmc_init(bd_t *bis) { int ret; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 2e956ab840..ba5d63b0d4 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -82,3 +82,5 @@ obj-$(CONFIG_IPQ40XX_MDIO) += ipq40xx/ipq40xx_mdio.o obj-$(CONFIG_IPQ_SNPS_GMAC) += ipq806x/ipq_gmac_eth.o obj-$(CONFIG_IPQ_SWITCH_ATHRS17) += ipq806x/athrs17_phy.o obj-$(CONFIG_IPQ_SWITCH_QCA8511) += ipq806x/qca8511.o +obj-$(CONFIG_IPQ807X_EDMA) += ipq807x/ipq807x_edma.o +obj-$(CONFIG_IPQ807X_EDMA) += ipq807x/ipq807x_ppe.o diff --git a/drivers/net/ipq807x/ipq807x_edma.c b/drivers/net/ipq807x/ipq807x_edma.c new file mode 100644 index 0000000000..4c38e7f321 --- /dev/null +++ b/drivers/net/ipq807x/ipq807x_edma.c @@ -0,0 +1,1563 @@ +/* + * Copyright (c) 2016-2017 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 "ipq807x_edma.h" + +#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); + +#define IPQ807X_EDMA_MAC_PORT_NO 3 + +static struct ipq807x_eth_dev *ipq807x_edma_dev[IPQ807X_EDMA_DEV]; + +uchar ipq807x_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD}; + +/* + * EDMA hardware instance + */ +static u32 ipq807x_edma_hw_addr; + +void ipq807x_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"); +} + +/* + * ipq807x_edma_reg_read() + * Read EDMA register + */ +uint32_t ipq807x_edma_reg_read(uint32_t reg_off) +{ + return (uint32_t)readl(ipq807x_edma_hw_addr + reg_off); +} + +/* + * ipq807x_edma_reg_write() + * Write EDMA register + */ +void ipq807x_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, (ipq807x_edma_hw_addr + reg_off)); +} + +/* + * ipq807x_edma_alloc_rx_buffer() + * Alloc Rx buffers for one RxFill ring + */ +int ipq807x_edma_alloc_rx_buffer(struct ipq807x_edma_hw *ehw, + struct ipq807x_edma_rxfill_ring *rxfill_ring) +{ + u32 skb; + uint16_t num_alloc = 0; + uint16_t cons, next, counter; + struct ipq807x_edma_rxfill_desc *rxfill_desc; + uint32_t reg_data; + struct ipq807x_edma_rx_preheader *rxph; + + /* + * Read RXFILL ring producer index + */ + reg_data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_RXFILL_PROD_IDX( + rxfill_ring->id)); + + next = reg_data & IPQ807X_EDMA_RXFILL_PROD_IDX_MASK; + + /* + * Read RXFILL ring consumer index + */ + reg_data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_RXFILL_CONS_IDX( + rxfill_ring->id)); + + cons = reg_data & IPQ807X_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; + } + /* + * Allocate buffer + */ + skb = virt_to_phys(net_rx_packets[counter]); + + /* + * Get RXFILL descriptor + */ + rxfill_desc = IPQ807X_EDMA_RXFILL_DESC(rxfill_ring, next); + + /* + * Make room for Rx preheader + */ + rxph = (struct ipq807x_edma_rx_preheader *)skb; + + /* + * Fill the opaque value + */ + rxph->opaque = cpu_to_le32(skb); + + /* + * Save buffer size in RXFILL descriptor + */ + rxfill_desc->word1 = cpu_to_le32(IPQ807X_EDMA_RX_BUFF_SIZE & + IPQ807X_EDMA_RXFILL_BUF_SIZE_MASK); + + /* + * Map Rx buffer for DMA + */ + rxfill_desc->buffer_addr = cpu_to_le32(skb); + + num_alloc++; + next = counter; + } + + if (num_alloc) { + /* + * Update RXFILL ring producer index + */ + reg_data = next & IPQ807X_EDMA_RXFILL_PROD_IDX_MASK; + + /* + * make sure the producer index updated before + * updating the hardware + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_PROD_IDX( + rxfill_ring->id), reg_data); + + pr_debug("%s: num_alloc = %d\n", __func__, num_alloc); + } + + return num_alloc; +} + +/* + * ipq807x_edma_clean_tx() + * Reap Tx descriptors + */ +uint32_t ipq807x_edma_clean_tx(struct ipq807x_edma_hw *ehw, + struct ipq807x_edma_txcmpl_ring *txcmpl_ring) +{ + struct ipq807x_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 = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_TXCMPL_PROD_IDX( + txcmpl_ring->id)); + prod_idx = data & IPQ807X_EDMA_TXCMPL_PROD_IDX_MASK; + + /* + * Get TXCMPL ring consumer index + */ + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_TXCMPL_CONS_IDX( + txcmpl_ring->id)); + cons_idx = data & IPQ807X_EDMA_TXCMPL_CONS_IDX_MASK; + + while (cons_idx != prod_idx) { + + txcmpl_desc = IPQ807X_EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); + + skb = (uchar *)txcmpl_desc->buffer_addr; + + if (unlikely(!skb)) { + pr_debug("Invalid skb: cons_idx:%u prod_idx:%u status %x\n", + cons_idx, prod_idx, txcmpl->status); + } + + if (++cons_idx == txcmpl_ring->count) + cons_idx = 0; + + txcmpl_consumed++; + } + + pr_debug("%s :%u txcmpl_consumed:%u prod_idx:%u cons_idx:%u\n", + __func__, txcmpl_ring->id, txcmpl_consumed, prod_idx, + cons_idx); + + if (txcmpl_consumed == 0) + return 0; + + /* + * Update TXCMPL ring consumer index + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXCMPL_CONS_IDX( + txcmpl_ring->id), cons_idx); + + return txcmpl_consumed; +} + +/* + * ipq807x_edma_clean_rx() + * Reap Rx descriptors + */ +static uint32_t ipq807x_edma_clean_rx(struct ipq807x_edma_common_info *c_info, + struct ipq807x_edma_rxdesc_ring *rxdesc_ring) +{ + void *skb; + struct ipq807x_edma_rxdesc_desc *rxdesc_desc; + struct ipq807x_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 ipq807x_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 = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_RXDESC_CONS_IDX( + rxdesc_ring->id)) & + IPQ807X_EDMA_RXDESC_CONS_IDX_MASK; + + while (rx) { + /* + * Read Rx ring producer index + */ + prod_idx = ipq807x_edma_reg_read( + IPQ807X_EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->id)) + & IPQ807X_EDMA_RXDESC_PROD_IDX_MASK; + + if (cons_idx == prod_idx) { + pr_debug("%s: cons = prod \n", __func__); + break; + } + + rxdesc_desc = IPQ807X_EDMA_RXDESC_DESC(rxdesc_ring, cons_idx); + + skb = (void *)rxdesc_desc->buffer_addr; + + /* + * Get Rx preheader + */ + rxph = (struct ipq807x_edma_rx_preheader *)skb; + + rx--; + + /* + * Check src_info from Rx preheader + */ + if (IPQ807X_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) == + IPQ807X_EDMA_PREHDR_DSTINFO_PORTID_IND) { + src_port_num = rxph->src_info & + IPQ807X_EDMA_PREHDR_PORTNUM_BITS; + } else { + pr_warn("WARN: src_info_type:0x%x. Drop skb:%p\n", + IPQ807X_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph), + skb); + goto next_rx_desc; + } + + /* + * Get packet length + */ + pkt_length = rxdesc_desc->status & + IPQ807X_EDMA_RXDESC_PACKET_LEN_MASK; + + if (unlikely((src_port_num < IPQ807X_NSS_DP_START_PHY_PORT) || + (src_port_num > IPQ807X_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 + IPQ807X_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) { + ipq807x_edma_alloc_rx_buffer(ehw, rxdesc_ring->rxfill); + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_CONS_IDX( + rxdesc_ring->id), cons_idx); + } + + return 0; +} + +/* + * ip807x_edma_rx_complete() + */ +static int ipq807x_edma_rx_complete(struct ipq807x_edma_common_info *c_info) +{ + struct ipq807x_edma_hw *ehw = &c_info->hw; + struct ipq807x_edma_txcmpl_ring *txcmpl_ring; + struct ipq807x_edma_rxdesc_ring *rxdesc_ring; + struct ipq807x_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]; + ipq807x_edma_clean_rx(c_info, rxdesc_ring); + } + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + ipq807x_edma_clean_tx(ehw, txcmpl_ring); + } + + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + ipq807x_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]; + ipq807x_edma_reg_write( + IPQ807X_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]; + ipq807x_edma_reg_write(IPQ807X_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]; + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_INT_MASK( + rxfill_ring->id), + ehw->rxfill_intr_mask); + } + + /* + * Read Misc intr status + */ + reg_data = ipq807x_edma_reg_read(IPQ807X_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); + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_MISC_INT_MASK, + IPQ807X_EDMA_MASK_INT_DISABLE); + } + + return 0; +} + +/* + * ipq807x_eth_snd() + * Transmit a packet using an EDMA ring + */ +static int ipq807x_eth_snd(struct eth_device *dev, void *packet, int length) +{ + struct ipq807x_eth_dev *priv = dev->priv; + struct ipq807x_edma_common_info *c_info = priv->c_info; + struct ipq807x_edma_hw *ehw = &c_info->hw; + struct ipq807x_edma_txdesc_desc *txdesc; + struct ipq807x_edma_tx_preheader *txph; + struct ipq807x_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; + + /* + * Read TXDESC ring producer index + */ + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id)); + + hw_next_to_use = data & IPQ807X_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 = ipq807x_edma_reg_read( + IPQ807X_EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id)); + + hw_next_to_clean = data & IPQ807X_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 = IPQ807X_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 ipq807x_edma_tx_preheader *)skb; + + memset((void *)txph, 0, IPQ807X_EDMA_TX_PREHDR_SIZE); + +#ifdef CONFIG_IPQ807X_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 = (IPQ807X_EDMA_PREHDR_DSTINFO_PORTID_IND << 8) | + (IPQ807X_EDMA_MAC_PORT_NO & 0x0fff); + +#endif + + /* + * Set opaque field in preheader + */ + txph->opaque = cpu_to_le32(skb); + + /* + * copy the packet + */ + memcpy(skb + IPQ807X_EDMA_TX_PREHDR_SIZE, packet, length); + + /* + * Populate Tx descriptor + */ + txdesc->word1 |= (1 << IPQ807X_EDMA_TXDESC_PREHEADER_SHIFT) + | ((IPQ807X_EDMA_TX_PREHDR_SIZE & + IPQ807X_EDMA_TXDESC_DATA_OFFSET_MASK) + << IPQ807X_EDMA_TXDESC_DATA_OFFSET_SHIFT); + txdesc->word1 |= ((length & IPQ807X_EDMA_TXDESC_DATA_LENGTH_MASK) + << IPQ807X_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 + */ + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id), hw_next_to_use & + IPQ807X_EDMA_TXDESC_PROD_IDX_MASK); + + pr_debug("%s: successfull\n", __func__); + + return EDMA_TX_OK; +} + +static int ipq807x_eth_recv(struct eth_device *dev) +{ + struct ipq807x_eth_dev *priv = dev->priv; + struct ipq807x_edma_common_info *c_info = priv->c_info; + struct ipq807x_edma_rxdesc_ring *rxdesc_ring; + struct ipq807x_edma_hw *ehw = &c_info->hw; + volatile u32 reg_data; + u32 rxdesc_intr_status; + int i; + + /* + * Read RxDesc intr status + */ + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + reg_data = ipq807x_edma_reg_read( + IPQ807X_EDMA_REG_RXDESC_INT_STAT( + rxdesc_ring->id)); + rxdesc_intr_status |= reg_data & + IPQ807X_EDMA_RXDESC_RING_INT_STATUS_MASK; + + /* + * Disable RxDesc intr + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_INT_MASK( + rxdesc_ring->id), + IPQ807X_EDMA_MASK_INT_DISABLE); + } + + ipq807x_edma_rx_complete(c_info); + + return 0; +} + +/* + * ipq807x_edma_setup_ring_resources() + * Allocate/setup resources for EDMA rings + */ +static int ipq807x_edma_setup_ring_resources(struct ipq807x_edma_hw *ehw) +{ + struct ipq807x_edma_txcmpl_ring *txcmpl_ring; + struct ipq807x_edma_txdesc_ring *txdesc_ring; + struct ipq807x_edma_rxfill_ring *rxfill_ring; + struct ipq807x_edma_rxdesc_ring *rxdesc_ring; + struct ipq807x_edma_txdesc_desc *tx_desc; + int i, j, index; + void *tx_buf; + + /* + * Allocate Rx fill ring descriptors + */ + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + rxfill_ring->count = IPQ807X_EDMA_RXFILL_RING_SIZE; + rxfill_ring->id = ehw->rxfill_ring_start + i; + rxfill_ring->desc = ipq807x_alloc_mem( + sizeof(struct ipq807x_edma_rxfill_desc) * + rxfill_ring->count); + + if (rxfill_ring->desc == NULL) { + pr_info("%s: rxfill_ring->desc alloc error\n", __func__); + goto rxfill_ring_fail; + } + rxfill_ring->dma = virt_to_phys(rxfill_ring->desc); + } + + /* + * Allocate RxDesc ring descriptors + */ + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + rxdesc_ring->count = IPQ807X_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 = ipq807x_alloc_mem( + sizeof(struct ipq807x_edma_rxdesc_desc) * + rxdesc_ring->count); + + if (rxdesc_ring->desc == NULL) { + pr_info("%s: rxdesc_ring->desc alloc error\n", __func__); + goto rxdesc_ring_fail; + } + 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 = IPQ807X_EDMA_TXCMPL_RING_SIZE; + txcmpl_ring->id = ehw->txcmpl_ring_start + i; + txcmpl_ring->desc = ipq807x_alloc_mem( + sizeof(struct ipq807x_edma_txcmpl_desc) * + txcmpl_ring->count); + + if (txcmpl_ring->desc == NULL) { + pr_info("%s: txcmpl_ring->desc alloc error\n", __func__); + goto txcmpl_ring_fail; + } + 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 = IPQ807X_EDMA_TXDESC_RING_SIZE; + txdesc_ring->id = ehw->txdesc_ring_start + i; + txdesc_ring->desc = ipq807x_alloc_mem( + sizeof(struct ipq807x_edma_txdesc_desc) * + txdesc_ring->count); + + if (txdesc_ring->desc == NULL) { + pr_info("%s: txdesc_ring->desc alloc error\n", __func__); + goto txdesc_ring_desc_fail; + } + + txdesc_ring->dma = virt_to_phys(txdesc_ring->desc); + tx_buf = ipq807x_alloc_mem(IPQ807X_EDMA_TX_BUF_SIZE * + txdesc_ring->count); + + if (tx_buf == NULL) { + pr_info("%s: txdesc_ring->desc buffer alloc error\n", + __func__); + goto txdesc_ring_desc_fail; + } + + for (j = 0; j < txdesc_ring->count; j++) { + tx_desc = IPQ807X_EDMA_TXDESC_DESC(txdesc_ring, j); + tx_desc->buffer_addr = virt_to_phys(tx_buf); + tx_buf += IPQ807X_EDMA_TX_BUF_SIZE; + } + } + + pr_info("%s: successfull\n", __func__); + + return 0; + +txdesc_ring_desc_fail: + for (i = 0; i < ehw->txdesc_rings; i++) { + txdesc_ring = &ehw->txdesc_ring[i]; + if (txdesc_ring->desc) { + tx_desc = IPQ807X_EDMA_TXDESC_DESC(txdesc_ring, 0); + if (tx_desc->buffer_addr) + ipq807x_free_mem((void *)tx_desc->buffer_addr); + ipq807x_free_mem(txdesc_ring->desc); + } + } +txcmpl_ring_fail: + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + if (txcmpl_ring->desc) { + ipq807x_free_mem(txcmpl_ring->desc); + } + } +rxdesc_ring_fail: + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + if (rxdesc_ring->desc) + ipq807x_free_mem(rxdesc_ring->desc); + } +rxfill_ring_fail: + for (i = 0; i < ehw->rxfill_rings; i++) { + rxfill_ring = &ehw->rxfill_ring[i]; + if (rxfill_ring->desc) + ipq807x_free_mem(rxfill_ring->desc); + } + return -ENOMEM; +} + +/* + * ipq807x_edma_free_desc() + * Free EDMA desc memory + */ +static void ipq807x_edma_free_desc(struct ipq807x_edma_common_info *c_info) +{ + struct ipq807x_edma_hw *ehw = &c_info->hw; + struct ipq807x_edma_txcmpl_ring *txcmpl_ring; + struct ipq807x_edma_txdesc_ring *txdesc_ring; + struct ipq807x_edma_rxfill_ring *rxfill_ring; + struct ipq807x_edma_rxdesc_ring *rxdesc_ring; + struct ipq807x_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) + ipq807x_free_mem(rxfill_ring->desc); + } + + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + if (rxdesc_ring->desc) + ipq807x_free_mem(rxdesc_ring->desc); + } + + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + if (txcmpl_ring->desc) { + ipq807x_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 = IPQ807X_EDMA_TXDESC_DESC(txdesc_ring, 0); + if (tx_desc->buffer_addr) + ipq807x_free_mem((void *)tx_desc->buffer_addr); + ipq807x_free_mem(txdesc_ring->desc); + } + } +} + +/* + * ipq807x_edma_free_rings() + * Free EDMA software rings + */ +static void ipq807x_edma_free_rings(struct ipq807x_edma_common_info *c_info) +{ + struct ipq807x_edma_hw *ehw = &c_info->hw; + ipq807x_free_mem(ehw->rxfill_ring); + ipq807x_free_mem(ehw->rxdesc_ring); + ipq807x_free_mem(ehw->txdesc_ring); + ipq807x_free_mem(ehw->txcmpl_ring); +} + +static void ipq807x_edma_disable_rings(struct ipq807x_edma_hw *edma_hw) +{ + int i, desc_index; + u32 data; + + /* + * Disable Rx rings + */ + for (i = 0; i < IPQ807X_EDMA_MAX_RXDESC_RINGS; i++) { + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_RXDESC_CTRL(i)); + data &= ~IPQ807X_EDMA_RXDESC_RX_EN; + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_CTRL(i), data); + } + + /* + * Disable RxFill Rings + */ + for (i = 0; i < IPQ807X_EDMA_MAX_RXFILL_RINGS; i++) { + data = ipq807x_edma_reg_read( + IPQ807X_EDMA_REG_RXFILL_RING_EN(i)); + data &= ~IPQ807X_EDMA_RXFILL_RING_EN; + ipq807x_edma_reg_write( + IPQ807X_EDMA_REG_RXFILL_RING_EN(i), data); + } + + /* + * Disable Tx rings + */ + for (desc_index = 0; desc_index < + IPQ807X_EDMA_MAX_TXDESC_RINGS; desc_index++) { + data = ipq807x_edma_reg_read( + IPQ807X_EDMA_REG_TXDESC_CTRL(desc_index)); + data &= ~IPQ807X_EDMA_TXDESC_TX_EN; + ipq807x_edma_reg_write( + IPQ807X_EDMA_REG_TXDESC_CTRL(desc_index), data); + } +} + +static void ipq807x_edma_disable_intr(struct ipq807x_edma_hw *ehw) +{ + int i; + + /* + * Disable interrupts + */ + for (i = 0; i < IPQ807X_EDMA_MAX_TXCMPL_RINGS; i++) + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TX_INT_MASK(i), 0); + + for (i = 0; i < IPQ807X_EDMA_MAX_RXFILL_RINGS; i++) + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_INT_MASK(i), 0); + + for (i = 0; i < IPQ807X_EDMA_MAX_RXDESC_RINGS; i++) + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RX_INT_CTRL(i), 0); + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_MISC_INT_MASK, + IPQ807X_EDMA_MASK_INT_DISABLE); +} + +static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this) +{ + struct ipq807x_eth_dev *priv = eth_dev->priv; + struct ipq807x_edma_common_info *c_info = priv->c_info; + struct ipq807x_edma_hw *ehw = &c_info->hw; + int i; + uint32_t data; + + /* + * Alloc Rx buffers + */ + ipq807x_edma_alloc_rx_buffer(ehw, ehw->rxfill_ring); + + /* + * Set DMA request priority + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_DMAR_CTRL, + (1 & IPQ807X_EDMA_DMAR_REQ_PRI_MASK) << + IPQ807X_EDMA_DMAR_REQ_PRI_SHIFT); + + /* + * Enable EDMA + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_PORT_CTRL, + IPQ807X_EDMA_PORT_CTRL_EN); + + /* + * Enable Rx rings + */ + for (i = ehw->rxdesc_ring_start; i < ehw->rxdesc_ring_end; i++) { + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_RXDESC_CTRL(i)); + data |= IPQ807X_EDMA_RXDESC_RX_EN; + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_CTRL(i), data); + } + + for (i = ehw->rxfill_ring_start; i < ehw->rxfill_ring_end; i++) { + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_RXFILL_RING_EN(i)); + data |= IPQ807X_EDMA_RXFILL_RING_EN; + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_RING_EN(i), data); + } + + /* + * Enable Tx rings + */ + for (i = ehw->txdesc_ring_start; i < ehw->txdesc_ring_end; i++) { + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_TXDESC_CTRL(i)); + data |= IPQ807X_EDMA_TXDESC_TX_EN; + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC_CTRL(i), data); + } + + pr_info("%s: done\n", __func__); + + return 0; +} + +static int ipq807x_edma_wr_macaddr(struct eth_device *dev) +{ + return 0; +} + +static void ipq807x_eth_halt(struct eth_device *dev) +{ + struct ipq807x_eth_dev *priv = dev->priv; + struct ipq807x_edma_common_info *c_info = priv->c_info; + struct ipq807x_edma_hw *ehw = &c_info->hw; + + ipq807x_edma_disable_intr(ehw); + ipq807x_edma_disable_rings(ehw); + + /* + * Disable EDMA + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_PORT_CTRL, IPQ807X_EDMA_DISABLE); + pr_info("%s: done\n", __func__); +} + +static void ipq807x_edma_set_ring_values(struct ipq807x_edma_hw *edma_hw) +{ + edma_hw->txdesc_ring_start = IPQ807X_EDMA_TX_DESC_RING_START; + edma_hw->txdesc_rings = IPQ807X_EDMA_TX_DESC_RING_NOS; + edma_hw->txdesc_ring_end = IPQ807X_EDMA_TX_DESC_RING_SIZE; + + edma_hw->txcmpl_ring_start = IPQ807X_EDMA_TX_CMPL_RING_START; + edma_hw->txcmpl_rings = IPQ807X_EDMA_RX_FILL_RING_NOS; + edma_hw->txcmpl_ring_end = IPQ807X_EDMA_TX_CMPL_RING_SIZE; + + edma_hw->rxfill_ring_start = IPQ807X_EDMA_RX_FILL_RING_START; + edma_hw->rxfill_rings = IPQ807X_EDMA_RX_FILL_RING_NOS; + edma_hw->rxfill_ring_end = IPQ807X_EDMA_RX_FILL_RING_SIZE; + + edma_hw->rxdesc_ring_start = IPQ807X_EDMA_RX_DESC_RING_START; + edma_hw->rxdesc_rings = IPQ807X_EDMA_RX_DESC_RING_NOS; + edma_hw->rxdesc_ring_end = IPQ807X_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)); +} + +/* + * ipq807x_edma_alloc_rings() + * Allocate EDMA software rings + */ +static int ipq807x_edma_alloc_rings(struct ipq807x_edma_hw *ehw) +{ + ehw->rxfill_ring = ipq807x_alloc_mem((sizeof( + struct ipq807x_edma_rxfill_ring) * + ehw->rxfill_rings)); + + if (!ehw->rxfill_ring) { + pr_info("%s: rxfill_ring alloc error\n", __func__); + return -1; + } + + ehw->rxdesc_ring = ipq807x_alloc_mem((sizeof( + struct ipq807x_edma_rxdesc_ring) * + ehw->rxdesc_rings)); + + if (!ehw->rxdesc_ring) { + pr_info("%s: rxdesc_ring alloc error\n", __func__); + goto rxdesc_ring_alloc_fail; + } + + ehw->txdesc_ring = ipq807x_alloc_mem((sizeof( + struct ipq807x_edma_txdesc_ring) * + ehw->txdesc_rings)); + if (!ehw->txdesc_ring) { + pr_info("%s: txdesc_ring alloc error\n", __func__); + goto txdesc_ring_alloc_fail; + } + + ehw->txcmpl_ring = ipq807x_alloc_mem((sizeof( + struct ipq807x_edma_txcmpl_ring) * + ehw->txcmpl_rings)); + + if (!ehw->txcmpl_ring) { + pr_info("%s: txcmpl_ring alloc error\n", __func__); + goto txcmpl_ring_alloc_fail; + } + + pr_info("%s: successfull\n", __func__); + + return 0; + +txcmpl_ring_alloc_fail: + ipq807x_free_mem(ehw->txdesc_ring); +txdesc_ring_alloc_fail: + ipq807x_free_mem(ehw->rxdesc_ring); +rxdesc_ring_alloc_fail: + ipq807x_free_mem(ehw->rxfill_ring); + return -ENOMEM; +} + + +/* + * ipq807x_edma_init_rings() + * Initialize EDMA rings + */ +static int ipq807x_edma_init_rings(struct ipq807x_edma_hw *ehw) +{ + int ret; + + /* + * Setup ring values + */ + ipq807x_edma_set_ring_values(ehw); + + /* + * Allocate desc rings + */ + ret = ipq807x_edma_alloc_rings(ehw); + if (ret) + return ret; + + /* + * Setup ring resources + */ + ret = ipq807x_edma_setup_ring_resources(ehw); + if (ret) + return ret; + + return 0; +} + +/* + * ipq807x_edma_configure_rx_threshold() + * Configure Rx threshold parameters + */ +static void ipq807x_edma_configure_rx_threshold(void) +{ + uint32_t rxq_fc_thre, rxq_ctrl; + + rxq_fc_thre = (IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE & + IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE_MASK) + << IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE_SHIFT; + + rxq_fc_thre |= (IPQ807X_EDMA_RXFILL_FIFO_XOFF_THRE & + IPQ807X_EDMA_DESC_FIFO_XOFF_THRE_MASK) + << IPQ807X_EDMA_DESC_FIFO_XOFF_THRE_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXQ_FC_THRE, rxq_fc_thre); + + rxq_ctrl = (IPQ807X_EDMA_RXFILL_PF_THRE & + IPQ807X_EDMA_RXFILL_PF_THRE_MASK) << + IPQ807X_EDMA_RXFILL_PF_THRE_SHIFT; + + rxq_ctrl |= (IPQ807X_EDMA_RXDESC_WB_THRE & + IPQ807X_EDMA_RXDESC_WB_THRE_MASK) << + IPQ807X_EDMA_RXDESC_WB_THRE_SHIFT; + + rxq_ctrl |= (IPQ807X_EDMA_RXDESC_WB_TIMER & + IPQ807X_EDMA_RXDESC_WB_TIMER_MASK) << + IPQ807X_EDMA_RXDESC_WB_TIMER_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXQ_CTRL, rxq_ctrl); +} + +/* + * ipq807x_edma_configure_tx_threshold() + * Configure global Tx threshold parameters + */ +static void ipq807x_edma_configure_tx_threshold(void) +{ + uint32_t txq_ctrl; + + txq_ctrl = (IPQ807X_EDMA_TXDESC_PF_THRE & + IPQ807X_EDMA_TXDESC_PF_THRE_MASK) << + IPQ807X_EDMA_TXDESC_PF_THRE_SHIFT; + + txq_ctrl |= (IPQ807X_EDMA_TXCMPL_WB_THRE & + IPQ807X_EDMA_TXCMPL_WB_THRE_MASK) << + IPQ807X_EDMA_TXCMPL_WB_THRE_SHIFT; + + txq_ctrl |= (IPQ807X_EDMA_TXDESC_PKT_SRAM_THRE & + IPQ807X_EDMA_TXDESC_PKT_SRAM_THRE_MASK) << + IPQ807X_EDMA_TXDESC_PKT_SRAM_THRE_SHIFT; + + txq_ctrl |= (IPQ807X_EDMA_TXCMPL_WB_TIMER & + IPQ807X_EDMA_TXCMPL_WB_TIMER_MASK) << + IPQ807X_EDMA_TXCMPL_WB_TIMER_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXQ_CTRL, txq_ctrl); +} + +/* + * ipq807x_edma_configure_txdesc_ring() + * Configure one TxDesc ring + */ +static void ipq807x_edma_configure_txdesc_ring(struct ipq807x_edma_hw *ehw, + struct ipq807x_edma_txdesc_ring *txdesc_ring) +{ + uint32_t data; + uint16_t hw_cons_idx; + + /* + * Configure TXDESC ring + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC_BA(txdesc_ring->id), + (uint32_t)(txdesc_ring->dma & + IPQ807X_EDMA_RING_DMA_MASK)); + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC_RING_SIZE( + txdesc_ring->id), (uint32_t)(txdesc_ring->count & + IPQ807X_EDMA_TXDESC_RING_SIZE_MASK)); + + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_TXDESC_CONS_IDX( + txdesc_ring->id)); + + data &= ~(IPQ807X_EDMA_TXDESC_CONS_IDX_MASK); + hw_cons_idx = data; + + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id)); + + data &= ~(IPQ807X_EDMA_TXDESC_PROD_IDX_MASK); + data |= hw_cons_idx & IPQ807X_EDMA_TXDESC_PROD_IDX_MASK; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC_PROD_IDX( + txdesc_ring->id), data); +} + +/* + * ipq807x_edma_configure_txcmpl_ring() + * Configure one TxCmpl ring + */ +static void ipq807x_edma_configure_txcmpl_ring(struct ipq807x_edma_hw *ehw, + struct ipq807x_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 + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXCMPL_BA(txcmpl_ring->id), + (uint32_t)(txcmpl_ring->dma & + IPQ807X_EDMA_RING_DMA_MASK)); + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXCMPL_RING_SIZE( + txcmpl_ring->id), (uint32_t)(txcmpl_ring->count & + IPQ807X_EDMA_TXDESC_RING_SIZE_MASK)); + + /* + * Set TxCmpl ret mode to opaque + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id), + IPQ807X_EDMA_TXCMPL_RETMODE_OPAQUE); + + txcmpl_ugt_thre = (low_thre & IPQ807X_EDMA_TXCMPL_LOW_THRE_MASK) << + IPQ807X_EDMA_TXCMPL_LOW_THRE_SHIFT; + + txcmpl_ugt_thre |= (txcmpl_fc_thre & IPQ807X_EDMA_TXCMPL_FC_THRE_MASK) + << IPQ807X_EDMA_TXCMPL_FC_THRE_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXCMPL_UGT_THRE( + txcmpl_ring->id), txcmpl_ugt_thre); + + tx_mod_timer = (IPQ807X_EDMA_TX_MOD_TIMER & + IPQ807X_EDMA_TX_MOD_TIMER_INIT_MASK) << + IPQ807X_EDMA_TX_MOD_TIMER_INIT_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id), + tx_mod_timer); + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TX_INT_CTRL(txcmpl_ring->id), + 0x2); +} + +/* + * ipq807x_edma_configure_rxdesc_ring() + * Configure one RxDesc ring + */ +static void ipq807x_edma_configure_rxdesc_ring(struct ipq807x_edma_hw *ehw, + struct ipq807x_edma_rxdesc_ring *rxdesc_ring) +{ + uint32_t data; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_BA(rxdesc_ring->id), + (uint32_t)(rxdesc_ring->dma & 0xffffffff)); + + data = rxdesc_ring->count & IPQ807X_EDMA_RXDESC_RING_SIZE_MASK; + data |= (ehw->rx_payload_offset & + IPQ807X_EDMA_RXDESC_PL_OFFSET_MASK) << + IPQ807X_EDMA_RXDESC_PL_OFFSET_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_RING_SIZE( + rxdesc_ring->id), data); + + data = (IPQ807X_EDMA_RXDESC_XON_THRE & + IPQ807X_EDMA_RXDESC_FC_XON_THRE_MASK) << + IPQ807X_EDMA_RXDESC_FC_XON_THRE_SHIFT; + + data |= (IPQ807X_EDMA_RXDESC_XOFF_THRE & + IPQ807X_EDMA_RXDESC_FC_XOFF_THRE_MASK) << + IPQ807X_EDMA_RXDESC_FC_XOFF_THRE_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_FC_THRE( + rxdesc_ring->id), data); + + data = (IPQ807X_EDMA_RXDESC_LOW_THRE & + IPQ807X_EDMA_RXDESC_LOW_THRE_MASK) << + IPQ807X_EDMA_RXDESC_LOW_THRE_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC_UGT_THRE( + rxdesc_ring->id), data); + + data = (IPQ807X_EDMA_RX_MOD_TIMER_INIT & + IPQ807X_EDMA_RX_MOD_TIMER_INIT_MASK) << + IPQ807X_EDMA_RX_MOD_TIMER_INIT_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RX_MOD_TIMER( + rxdesc_ring->id), data); + + /* + * Enable ring. Set ret mode to 'opaque'. + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RX_INT_CTRL( + rxdesc_ring->id), 0x2); +} + +/* + * ipq807x_edma_configure_rxfill_ring() + * Configure one RxFill ring + */ +static void ipq807x_edma_configure_rxfill_ring(struct ipq807x_edma_hw *ehw, + struct ipq807x_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; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_BA(rxfill_ring->id), + (uint32_t)(rxfill_ring->dma & IPQ807X_EDMA_RING_DMA_MASK)); + + data = rxfill_ring->count & IPQ807X_EDMA_RXFILL_RING_SIZE_MASK; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->id), data); + + rxfill_fc_thre = (rxfill_xon_thre & IPQ807X_EDMA_RXFILL_FC_XON_THRE_MASK) + << IPQ807X_EDMA_RXFILL_FC_XON_THRE_SHIFT; + rxfill_fc_thre |= (rxfill_xoff_thre & IPQ807X_EDMA_RXFILL_FC_XOFF_THRE_MASK) + << IPQ807X_EDMA_RXFILL_FC_XOFF_THRE_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_FC_THRE(rxfill_ring->id), + rxfill_fc_thre); + + rxfill_ugt_thre = (rxfill_low_thre & IPQ807X_EDMA_RXFILL_LOW_THRE_MASK) + << IPQ807X_EDMA_RXFILL_LOW_THRE_SHIFT; + + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXFILL_UGT_THRE(rxfill_ring->id), + rxfill_ugt_thre); + +} + + +/* + * ipq807x_edma_configure_rings() + * Configure EDMA rings + */ +static void ipq807x_edma_configure_rings(struct ipq807x_edma_hw *ehw) +{ + int i; + + /* + * Configure TXDESC ring + */ + for (i = 0; i < ehw->txdesc_rings; i++) + ipq807x_edma_configure_txdesc_ring(ehw, &ehw->txdesc_ring[i]); + + /* + * Configure TXCMPL ring + */ + for (i = 0; i < ehw->txcmpl_rings; i++) + ipq807x_edma_configure_txcmpl_ring(ehw, &ehw->txcmpl_ring[i]); + + /* + * Configure RXFILL rings + */ + for (i = 0; i < ehw->rxfill_rings; i++) + ipq807x_edma_configure_rxfill_ring(ehw, &ehw->rxfill_ring[i]); + + /* + * Configure RXDESC ring + */ + for (i = 0; i < ehw->rxdesc_rings; i++) + ipq807x_edma_configure_rxdesc_ring(ehw, &ehw->rxdesc_ring[i]); + + pr_info("%s: successfull\n", __func__); +} + + +/* + * ipq807x_edma_hw_init() + * EDMA hw init + */ +int ipq807x_edma_hw_init(struct ipq807x_edma_hw *ehw) +{ + int ret, desc_index; + uint32_t i, reg; + volatile uint32_t data; + + struct ipq807x_edma_rxdesc_ring *rxdesc_ring = NULL; + + ipq807x_ppe_provision_init(); + + data = ipq807x_edma_reg_read(IPQ807X_EDMA_REG_MAS_CTRL); + printf("EDMA ver %d hw init\n", data); + + /* + * Setup private data structure + */ + ehw->rxfill_intr_mask = IPQ807X_EDMA_RXFILL_INT_MASK; + ehw->rxdesc_intr_mask = IPQ807X_EDMA_RXDESC_INT_MASK_PKT_INT; + ehw->txcmpl_intr_mask = IPQ807X_EDMA_TX_INT_MASK_PKT_INT | + IPQ807X_EDMA_TX_INT_MASK_UGT_INT; + ehw->misc_intr_mask = 0; + ehw->rx_payload_offset = IPQ807X_EDMA_RX_PREHDR_SIZE; + + ipq807x_edma_disable_intr(ehw); + ipq807x_edma_disable_rings(ehw); + + ret = ipq807x_edma_init_rings(ehw); + + if (ret) + return ret; + + ipq807x_edma_configure_rings(ehw); + + /* + * Clear the TXDESC2CMPL_MAP_xx reg before setting up + * the mapping. This register holds TXDESC to TXFILL ring + * mapping. + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_0, 0); + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_1, 0); + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_2, 0); + desc_index = ehw->txcmpl_ring_start; + + /* + * 3 registers to hold the completion mapping for total 24 + * TX desc rings (0-9,10-19 and rest). In each entry 3 bits hold + * the mapping for a particular TX desc ring. + */ + for (i = ehw->txdesc_ring_start; + i < ehw->txdesc_ring_end; i++) { + if (i >= 0 && i <= 9) + reg = IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_0; + else if (i >= 10 && i <= 19) + reg = IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_1; + else + reg = IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_2; + + pr_debug("Configure TXDESC:%u to use TXCMPL:%u\n", + i, desc_index); + + data = ipq807x_edma_reg_read(reg); + data |= (desc_index & 0x7) << ((i % 10) * 3); + ipq807x_edma_reg_write(reg, data); + + desc_index++; + if (desc_index == ehw->txcmpl_ring_end) + desc_index = ehw->txcmpl_ring_start; + } + + /* + * Set PPE QID to EDMA Rx ring mapping. + * When coming up use only queue 0. + * HOST EDMA rings. FW EDMA comes up and overwrites as required. + * Each entry can hold mapping for 8 PPE queues and entry size is + * 4 bytes + */ + desc_index = ehw->rxdesc_ring_start; + data = 0; + data |= (desc_index & 0xF); + ipq807x_edma_reg_write(IPQ807X_EDMA_QID2RID_TABLE_MEM(0), data); + pr_debug("Configure QID2RID reg:0x%x to 0x%x\n", reg, data); + + /* + * Configure Tx/Rx queue threshold parameters + */ + ipq807x_edma_configure_tx_threshold(); + ipq807x_edma_configure_rx_threshold(); + + /* + * Set RXDESC2FILL_MAP_xx reg. + * There are two registers RXDESC2FILL_0 and RXDESC2FILL_1 + * 3 bits holds the rx fill ring mapping for each of the + * rx descriptor ring. + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC2FILL_MAP_0, 0); + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_RXDESC2FILL_MAP_1, 0); + + for (i = ehw->rxdesc_ring_start; + i < ehw->rxdesc_ring_end; i++) { + if ((i >= 0) && (i <= 9)) + reg = IPQ807X_EDMA_REG_RXDESC2FILL_MAP_0; + else + reg = IPQ807X_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 = ipq807x_edma_reg_read(reg); + data |= (rxdesc_ring->rxfill->id & 0x7) << ((i % 10) * 3); + ipq807x_edma_reg_write(reg, data); + } + + reg = IPQ807X_EDMA_REG_RXDESC2FILL_MAP_0; + pr_debug("EDMA_REG_RXDESC2FILL_MAP_0: 0x%x\n", + ipq807x_edma_reg_read(reg)); + reg = IPQ807X_EDMA_REG_RXDESC2FILL_MAP_1; + pr_debug("EDMA_REG_RXDESC2FILL_MAP_1: 0x%x\n", + ipq807x_edma_reg_read(reg)); + + reg = IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_0; + pr_debug("EDMA_REG_TXDESC2CMPL_MAP_0: 0x%x\n", + ipq807x_edma_reg_read(reg)); + reg = IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_1; + pr_debug("EDMA_REG_TXDESC2CMPL_MAP_1: 0x%x\n", + ipq807x_edma_reg_read(reg)); + reg = IPQ807X_EDMA_REG_TXDESC2CMPL_MAP_2; + pr_debug("EDMA_REG_TXDESC2CMPL_MAP_2: 0x%x\n", + ipq807x_edma_reg_read(reg)); + + /* + * Enable MISC interrupt + */ + ipq807x_edma_reg_write(IPQ807X_EDMA_REG_MISC_INT_MASK, + ehw->misc_intr_mask); + + pr_info("%s: successfull\n", __func__); + return 0; +} + +int ipq807x_edma_init(void *edma_board_cfg) +{ + struct eth_device *dev[IPQ807X_EDMA_DEV]; + struct ipq807x_edma_common_info *c_info[IPQ807X_EDMA_DEV]; + struct ipq807x_edma_hw *hw[IPQ807X_EDMA_DEV]; + uchar enet_addr[IPQ807X_EDMA_DEV * 6]; + int i; + int ret = -1; + ipq807x_edma_board_cfg_t ledma_cfg, *edma_cfg; + + + memset(c_info, 0, (sizeof(c_info) * IPQ807X_EDMA_DEV)); + memset(enet_addr, 0, sizeof(enet_addr)); + memset(&ledma_cfg, 0, sizeof(ledma_cfg)); + edma_cfg = &ledma_cfg; + + /* Getting the MAC address from ART partition */ + /* ret = get_eth_mac_address(enet_addr, IPQ807X_EDMA_DEV); */ + + /* + * Register EDMA as single ethernet + * interface. + */ + for (i = 0; i < IPQ807X_EDMA_DEV; edma_cfg++, i++) { + dev[i] = ipq807x_alloc_mem(sizeof(struct eth_device)); + + if (!dev[i]) + goto init_failed; + + memset(dev[i], 0, sizeof(struct eth_device)); + + c_info[i] = ipq807x_alloc_mem( + sizeof(struct ipq807x_edma_common_info)); + + if (!c_info[i]) + goto init_failed; + + memset(c_info[i], 0, + sizeof(struct ipq807x_edma_common_info)); + + hw[i] = &c_info[i]->hw; + + c_info[i]->hw.hw_addr = (unsigned long __iomem *) + IPQ807X_EDMA_CFG_BASE; + + ipq807x_edma_dev[i] = ipq807x_alloc_mem( + sizeof(struct ipq807x_eth_dev)); + + if (!ipq807x_edma_dev[i]) + goto init_failed; + + memset (ipq807x_edma_dev[i], 0, + sizeof(struct ipq807x_eth_dev)); + + dev[i]->iobase = IPQ807X_EDMA_CFG_BASE; + dev[i]->init = ipq807x_eth_init; + dev[i]->halt = ipq807x_eth_halt; + dev[i]->recv = ipq807x_eth_recv; + dev[i]->send = ipq807x_eth_snd; + dev[i]->write_hwaddr = ipq807x_edma_wr_macaddr; + dev[i]->priv = (void *)ipq807x_edma_dev[i]; + + if ((ret < 0) || + (!is_valid_ethaddr(&enet_addr[edma_cfg->unit * 6]))) { + memcpy(&dev[i]->enetaddr[0], ipq807x_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]); + + sprintf(dev[i]->name, "eth%d", i); + + ipq807x_edma_dev[i]->dev = dev[i]; + ipq807x_edma_dev[i]->mac_unit = edma_cfg->unit; + ipq807x_edma_dev[i]->c_info = c_info[i]; + ipq807x_edma_hw_addr = IPQ807X_EDMA_CFG_BASE; + + ret = ipq807x_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 < IPQ807X_EDMA_DEV; i++) { + if (dev[i]) { + eth_unregister(dev[i]); + ipq807x_free_mem(dev[i]); + } + if (c_info[i]) { + ipq807x_edma_free_desc(c_info[i]); + ipq807x_edma_free_rings(c_info[i]); + ipq807x_free_mem(c_info[i]); + } + if (ipq807x_edma_dev[i]) { + ipq807x_free_mem(ipq807x_edma_dev[i]); + } + } + + return -1; +} diff --git a/drivers/net/ipq807x/ipq807x_edma.h b/drivers/net/ipq807x/ipq807x_edma.h new file mode 100644 index 0000000000..fadc71bb20 --- /dev/null +++ b/drivers/net/ipq807x/ipq807x_edma.h @@ -0,0 +1,301 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2017 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 __IPQ807X_EDMA__ +#define __IPQ807X_EDMA__ + +#define IPQ807X_NSS_DP_START_PHY_PORT 1 +#define IPQ807X_NSS_DP_MAX_PHY_PORTS 6 + +#define IPQ807X_EDMA_BUF_SIZE 2000 +#define IPQ807X_EDMA_DEVICE_NODE_NAME "edma" +#define IPQ807X_EDMA_RX_BUFF_SIZE (IPQ807X_EDMA_BUF_SIZE + IPQ807X_EDMA_RX_PREHDR_SIZE) +#define IPQ807X_EDMA_RX_PREHDR_SIZE (sizeof(struct ipq807x_edma_rx_preheader)) +#define IPQ807X_EDMA_TX_PREHDR_SIZE (sizeof(struct ipq807x_edma_tx_preheader)) + +#define IPQ807X_EDMA_TXDESC_RING_SIZE 8 +#define IPQ807X_EDMA_TXCMPL_RING_SIZE 8 +#define IPQ807X_EDMA_RXDESC_RING_SIZE 16 +#define IPQ807X_EDMA_RXFILL_RING_SIZE 16 + +#define IPQ807X_EDMA_START_GMACS IPQ807X_NSS_DP_START_PHY_PORT +#define IPQ807X_EDMA_MAX_GMACS IPQ807X_NSS_DP_MAX_PHY_PORTS +#define IPQ807X_EDMA_TX_BUF_SIZE (1540 + IPQ807X_EDMA_TX_PREHDR_SIZE) + +#define IPQ807X_EDMA_MAX_TXCMPL_RINGS 8 /* Max TxCmpl rings */ +#define IPQ807X_EDMA_MAX_RXDESC_RINGS 16 /* Max RxDesc rings */ +#define IPQ807X_EDMA_MAX_RXFILL_RINGS 8 /* Max RxFill rings */ +#define IPQ807X_EDMA_MAX_TXDESC_RINGS 24 /* Max TxDesc rings */ + +#define IPQ807X_EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) +#define IPQ807X_EDMA_RXFILL_DESC(R, i) IPQ807X_EDMA_GET_DESC(R, i, struct ipq807x_edma_rxfill_desc) +#define IPQ807X_EDMA_RXDESC_DESC(R, i) IPQ807X_EDMA_GET_DESC(R, i, struct ipq807x_edma_rxdesc_desc) +#define IPQ807X_EDMA_TXDESC_DESC(R, i) IPQ807X_EDMA_GET_DESC(R, i, struct ipq807x_edma_txdesc_desc) +#define IPQ807X_EDMA_TXCMPL_DESC(R, i) IPQ807X_EDMA_GET_DESC(R, i, struct ipq807x_edma_txcmpl_desc) +#define IPQ807X_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) (((rxph)->src_info >> 8) & 0xf0) + +#define IPQ807X_EDMA_DEV 1 +#define IPQ807X_EDMA_TX_QUEUE 1 +#define IPQ807X_EDMA_RX_QUEUE 1 + +//#define IPQ807X_EDMA_TX_DESC_RING_START 23 +#define IPQ807X_EDMA_TX_DESC_RING_START 0 +#define IPQ807X_EDMA_TX_DESC_RING_NOS 1 +#define IPQ807X_EDMA_TX_DESC_RING_SIZE \ +(IPQ807X_EDMA_TX_DESC_RING_START + IPQ807X_EDMA_TX_DESC_RING_NOS) + +#define IPQ807X_EDMA_TX_CMPL_RING_START 7 +#define IPQ807X_EDMA_TX_CMPL_RING_NOS 1 +#define IPQ807X_EDMA_TX_CMPL_RING_SIZE \ +(IPQ807X_EDMA_TX_CMPL_RING_START + IPQ807X_EDMA_TX_CMPL_RING_NOS) + +#define IPQ807X_EDMA_RX_DESC_RING_START 15 +#define IPQ807X_EDMA_RX_DESC_RING_NOS 1 +#define IPQ807X_EDMA_RX_DESC_RING_SIZE \ +(IPQ807X_EDMA_RX_DESC_RING_START + IPQ807X_EDMA_RX_DESC_RING_NOS) + +#define IPQ807X_EDMA_RX_FILL_RING_START 7 +#define IPQ807X_EDMA_RX_FILL_RING_NOS 1 +#define IPQ807X_EDMA_RX_FILL_RING_SIZE \ +(IPQ807X_EDMA_RX_FILL_RING_START + IPQ807X_EDMA_RX_FILL_RING_NOS) + +#define IPQ807X_EDMA_TX_IMR_NORMAL_MASK 1 +#define IPQ807X_EDMA_RX_IMR_NORMAL_MASK 1 +#define IPQ807X_EDMA_INTR_CLEAR_TYPE 0 +#define IPQ807X_EDMA_INTR_SW_IDX_W_TYPE 0 +#define IPQ807X_EDMA_RSS_TYPE_NONE 0x1 + +#define NETDEV_TX_BUSY 1 + +/* + * Tx descriptor + */ +struct ipq807x_edma_txdesc_desc { + uint32_t buffer_addr; + /* buffer address */ + uint32_t word1; + /* more bit, TSO, preheader, pool, offset and length */ +}; + +/* + * TxCmpl descriptor + */ +struct ipq807x_edma_txcmpl_desc { + uint32_t buffer_addr; /* buffer address/opaque */ + uint32_t status; /* status */ +}; + +/* + * Rx descriptor + */ +struct ipq807x_edma_rxdesc_desc { + uint32_t buffer_addr; /* buffer address */ + uint32_t status; /* status */ +}; + +/* + * RxFill descriptor + */ +struct ipq807x_edma_rxfill_desc { + uint32_t buffer_addr; /* Buffer address */ + uint32_t word1; /* opaque_ind and buffer size */ +}; + +/* + * Tx descriptor ring + */ +struct ipq807x_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 ipq807x_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 ipq807x_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 ipq807x_edma_rxdesc_ring { + uint32_t id; /* RXDESC ring number */ + struct ipq807x_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 ipq807x_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 ipq807x_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 ipq807x_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 ipq807x_edma_common_info *c_info; /* edma common info */ +}; + +/* edma hw specific data */ +struct ipq807x_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 ipq807x_edma_txdesc_ring *txdesc_ring; /* Tx Descriptor Ring, SW is producer */ + struct ipq807x_edma_txcmpl_ring *txcmpl_ring; /* Tx Completion Ring, SW is consumer */ + struct ipq807x_edma_rxdesc_ring *rxdesc_ring; /* Rx Descriptor Ring, SW is consumer */ + struct ipq807x_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 ipq807x_edma_common_info { + struct ipq807x_edma_hw hw; +}; + +struct ipq807x_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 ipq807x_edma_common_info *c_info; + struct phy_ops *ops; + const char phy_name[MDIO_NAME_LEN]; +} __attribute__ ((aligned(8))); + +static inline void* ipq807x_alloc_mem(u32 size) +{ + void *p = malloc(size); + if (p != NULL) + memset(p, 0, size); + return p; +} + +static inline void ipq807x_free_mem(void *ptr) +{ + if (ptr) + free(ptr); +} + +//extern struct ipq807x_edma_hw ipq807x_edma_hw; + +uint32_t ipq807x_edma_reg_read(uint32_t reg_off); +void ipq807x_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]; +} ipq807x_edma_phy_addr_t; + +/* ipq807x edma Paramaters */ +typedef struct { + uint base; + int unit; + uint mac_conn_to_phy; + phy_interface_t phy; + ipq807x_edma_phy_addr_t phy_addr; + const char phy_name[MDIO_NAME_LEN]; +} ipq807x_edma_board_cfg_t; + +extern void ipq807x_ppe_provision_init(void); + +#endif /* ___IPQ807X_EDMA__ */ diff --git a/drivers/net/ipq807x/ipq807x_ppe.c b/drivers/net/ipq807x/ipq807x_ppe.c new file mode 100644 index 0000000000..4fad3f3906 --- /dev/null +++ b/drivers/net/ipq807x/ipq807x_ppe.c @@ -0,0 +1,969 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2017 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 "ipq807x_ppe.h" + +#define pr_info(fmt, args...) printf(fmt, ##args); + +/* + * ipq807x_ppe_gpio_reg_write() + */ +static inline void ipq807x_ppe_gpio_reg_write(u32 reg, u32 val) +{ + writel(val, IPQ807X_PPE_FPGA_GPIO_BASE_ADDR + reg); +} + +/* + * ipq807x_ppe_reg_read() + */ +static inline void ipq807x_ppe_reg_read(u32 reg, u32 *val) +{ + *val = readl((void *)(IPQ807X_PPE_BASE_ADDR + reg)); +} + +/* + * ipq807x_ppe_reg_write() + */ +static inline void ipq807x_ppe_reg_write(u32 reg, u32 val) +{ + writel(val, (void *)(IPQ807X_PPE_BASE_ADDR + reg)); +} + +/* + * ipq807x_ppe_vp_port_tbl_set() + */ +static void ipq807x_ppe_vp_port_tbl_set(int port, int vsi) +{ + u32 addr = IPQ807X_PPE_L3_VP_PORT_TBL_ADDR + + (port * IPQ807X_PPE_L3_VP_PORT_TBL_INC); + ipq807x_ppe_reg_write(addr, 0x0); + ipq807x_ppe_reg_write(addr + 0x4 , 1 << 9 | vsi << 10); + ipq807x_ppe_reg_write(addr + 0x8, 0x0); +} + +/* + * ipq807x_ppe_ucast_queue_map_tbl_queue_id_set() + */ +static void ipq807x_ppe_ucast_queue_map_tbl_queue_id_set(int queue, int port) +{ + uint32_t val; + + ipq807x_ppe_reg_read(IPQ807X_PPE_QM_UQM_TBL + + (port * IPQ807X_PPE_UCAST_QUEUE_MAP_TBL_INC), &val); + + val |= queue << 4; + + ipq807x_ppe_reg_write(IPQ807X_PPE_QM_UQM_TBL + + (port * IPQ807X_PPE_UCAST_QUEUE_MAP_TBL_INC), val); +} + +/* + * ipq807x_vsi_setup() + */ +static void ipq807x_vsi_setup(int vsi, uint8_t group_mask) +{ + uint32_t val = (group_mask << 24 | group_mask << 16 | group_mask << 8 + | group_mask); + + /* Set mask */ + ipq807x_ppe_reg_write(0x061800 + (vsi * 0x10), val); + + /* new addr lrn en | station move lrn en */ + ipq807x_ppe_reg_write(0x061804 + (vsi * 0x10), 0x9); +} + +/* + * ipq807x_gmac_enable() + */ + +static void ipq807x_gmac_enable(void) +{ + writel(0x0, 0x1008004); +} + +/* + * ipq807x_gmac_port_enable() + */ +static void ipq807x_gmac_port_enable(int port) +{ + ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_ENABLE + (0x200 * port), 0x13); + ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_SPEED + (0x200 * port), 0x2); + ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_MIB_CTL + (0x200 * port), 0x1); +} + +/* + * ipq807x_ppe_flow_port_map_tbl_port_num_set() + */ +static void ipq807x_ppe_flow_port_map_tbl_port_num_set(int queue, int port) +{ + ipq807x_ppe_reg_write(IPQ807X_PPE_L0_FLOW_PORT_MAP_TBL + + queue * IPQ807X_PPE_L0_FLOW_PORT_MAP_TBL_INC, port); + ipq807x_ppe_reg_write(IPQ807X_PPE_L1_FLOW_PORT_MAP_TBL + + port * IPQ807X_PPE_L1_FLOW_PORT_MAP_TBL_INC, port); +} + +/* + * ipq807x_ppe_flow_map_tbl_set() + */ +static void ipq807x_ppe_flow_map_tbl_set(int queue, int port) +{ + uint32_t val = port | 0x401000; /* c_drr_wt = 1, e_drr_wt = 1 */ + ipq807x_ppe_reg_write(IPQ807X_PPE_L0_FLOW_MAP_TBL + queue * IPQ807X_PPE_L0_FLOW_MAP_TBL_INC, + val); + + val = port | 0x100400; /* c_drr_wt = 1, e_drr_wt = 1 */ + ipq807x_ppe_reg_write(IPQ807X_PPE_L1_FLOW_MAP_TBL + port * IPQ807X_PPE_L1_FLOW_MAP_TBL_INC, + val); +} + +/* + * ipq807x_ppe_tdm_configuration + */ +static void ipq807x_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 + */ + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_QCOM1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_QCOM3); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_QCOM2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_QCOM4); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID + | IPQ807X_PPE_TDM_CFG_DIR_EGRESS + | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_QCOM1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_QCOM3); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_QCOM2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_QCOM4); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_INGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_GPIO_OFFSET + (i++ * 0x10), + IPQ807X_PPE_TDM_CFG_VALID | + IPQ807X_PPE_TDM_CFG_DIR_EGRESS | + IPQ807X_PPE_PORT_CRYPTO1); + + /* Set TDM Depth to 100 entries */ + ipq807x_ppe_reg_write(IPQ807X_PPE_TDM_CFG_DEPTH_OFFSET, IPQ807X_PPE_TDM_CFG_DEPTH_VAL); +} + +/* + * ipq807x_ppe_sched_configuration + */ +static void ipq807x_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 =((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + * IPQ807X_PPE_PORT_XGMAC1_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + * IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + * IPQ807X_PPE_PORT_XGMAC2 | IPQ807X_PPE_PORT_EDMA); + */ + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_XGMAC1_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM3_BITPOS | IPQ807X_PPE_PORT_QCOM2_BITPOS | + IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM4 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_QCOM4_BITPOS | + IPQ807X_PPE_PORT_QCOM3_BITPOS | IPQ807X_PPE_PORT_QCOM2_BITPOS | + IPQ807X_PPE_PORT_QCOM1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_XGMAC2_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_CRYPTO1 << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_QCOM1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_QCOM2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_XGMAC1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_XGMAC2_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_CRYPTO1 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_QCOM3); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM3 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_XGMAC1_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_QCOM4); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_XGMAC2_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM4 << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_XGMAC2_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_CRYPTO1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_QCOM2_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_QCOM1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM1 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_QCOM2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_XGMAC2_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM2 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_XGMAC1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_CRYPTO1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_XGMAC2_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_CRYPTO1 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_QCOM3); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC2 << 4) | IPQ807X_PPE_PORT_EDMA); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC2_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_QCOM3 << 4) | IPQ807X_PPE_PORT_XGMAC1); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_EDMA_BITPOS | + IPQ807X_PPE_PORT_QCOM4_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_EDMA << 4) | IPQ807X_PPE_PORT_XGMAC2); + ipq807x_ppe_reg_write(IPQ807X_PPE_FPGA_SCHED_OFFSET + (i++ * 0x10), + ((IPQ807X_PPE_PORT_CRYPTO1_BITPOS | IPQ807X_PPE_PORT_XGMAC1_BITPOS | + IPQ807X_PPE_PORT_EDMA_BITPOS | IPQ807X_PPE_PORT_QCOM3_BITPOS | + IPQ807X_PPE_PORT_QCOM2_BITPOS | IPQ807X_PPE_PORT_QCOM1_BITPOS) << 8) | + (IPQ807X_PPE_PORT_XGMAC1 << 4) | IPQ807X_PPE_PORT_QCOM4); + + /* Set Sched Depth to 50 entries */ + ipq807x_ppe_reg_write(IPQ807X_PPE_TDM_SCHED_DEPTH_OFFSET, IPQ807X_PPE_TDM_SCHED_DEPTH_VAL); +} + +/* + * ipq807x_ppe_c_sp_cfg_tbl_drr_id_set + */ +static void ipq807x_ppe_c_sp_cfg_tbl_drr_id_set(int id) +{ + ipq807x_ppe_reg_write(IPQ807X_PPE_L0_C_SP_CFG_TBL + (id * 0x80), id * 2); + ipq807x_ppe_reg_write(IPQ807X_PPE_L1_C_SP_CFG_TBL + (id * 0x80), id * 2); +} + +/* + * ipq807x_ppe_e_sp_cfg_tbl_drr_id_set + */ +static void ipq807x_ppe_e_sp_cfg_tbl_drr_id_set(int id) +{ + ipq807x_ppe_reg_write(IPQ807X_PPE_L0_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1); + ipq807x_ppe_reg_write(IPQ807X_PPE_L1_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1); +} + +/* + * ipq807x_ppe_provision_init() + */ +void ipq807x_ppe_provision_init(void) +{ + int i; + uint32_t queue; + + /* Port4 Port5, Port6 port mux configuration, all GMAC */ + writel(0x3d, 0x3a000010); + + /* tdm/sched configuration */ + ipq807x_ppe_tdm_configuration(); + ipq807x_ppe_sched_configuration(); + + ipq807x_gmac_enable(); + + /* disable clock gating */ + ipq807x_ppe_reg_write(0x000008, 0x0); + + /* flow ctrl disable */ + ipq807x_ppe_reg_write(0x200368, 0xc88); + +#ifdef CONFIG_IPQ807X_BRIDGED_MODE + /* Add CPU port 0 to VSI 2 */ + ipq807x_ppe_vp_port_tbl_set(0, 2); + + /* Add port 1 - 4 to VSI 2 */ + ipq807x_ppe_vp_port_tbl_set(1, 2); + ipq807x_ppe_vp_port_tbl_set(2, 2); + ipq807x_ppe_vp_port_tbl_set(3, 2); + ipq807x_ppe_vp_port_tbl_set(4, 2); + +#else + ipq807x_ppe_vp_port_tbl_set(1, 2); + ipq807x_ppe_vp_port_tbl_set(2, 3); + ipq807x_ppe_vp_port_tbl_set(3, 4); + ipq807x_ppe_vp_port_tbl_set(4, 5); +#endif + + /* Unicast priority map */ + ipq807x_ppe_reg_write(IPQ807X_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); + + ipq807x_ppe_ucast_queue_map_tbl_queue_id_set(queue, i); + ipq807x_ppe_flow_port_map_tbl_port_num_set(queue, i); + ipq807x_ppe_flow_map_tbl_set(queue, i); + ipq807x_ppe_c_sp_cfg_tbl_drr_id_set(i); + ipq807x_ppe_e_sp_cfg_tbl_drr_id_set(i); + } + + /* Port0 multicast queue */ + ipq807x_ppe_reg_write(0x409000, 0x00000000); + ipq807x_ppe_reg_write(0x403000, 0x00401000); + + /* Port1 - 7 multicast queue */ + for (i = 1; i < 8; i++) { + ipq807x_ppe_reg_write(0x409100 + ((i - 1) * 0x40), i); + ipq807x_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++) + ipq807x_ppe_reg_write(IPQ807X_PPE_PORT_BRIDGE_CTRL_OFFSET + (i * 4), + IPQ807X_PPE_PORT_BRIDGE_CTRL_PROMISC_EN | + IPQ807X_PPE_PORT_BRIDGE_CTRL_TXMAC_EN | + IPQ807X_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP | + IPQ807X_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN | + IPQ807X_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN); + + ipq807x_ppe_reg_write(IPQ807X_PPE_PORT_BRIDGE_CTRL_OFFSET + (7 * 4), + IPQ807X_PPE_PORT_BRIDGE_CTRL_PROMISC_EN | + IPQ807X_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP | + IPQ807X_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN | + IPQ807X_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN); + + /* Global learning */ + ipq807x_ppe_reg_write(0x060038, 0xc0); + +#ifdef CONFIG_IPQ807X_BRIDGED_MODE + ipq807x_vsi_setup(2, 0x1f); +#else + ipq807x_vsi_setup(2, 0x03); + ipq807x_vsi_setup(3, 0x05); + ipq807x_vsi_setup(4, 0x09); + ipq807x_vsi_setup(5, 0x11); +#endif + + /* Port 0-7 STP */ + for (i = 0; i < 8; i++) + ipq807x_ppe_reg_write(IPQ807X_PPE_STP_BASE + (0x4 * i), 0x3); + + /* Port 0-5 enable */ + for (i = 0; i < 6; i++) + ipq807x_gmac_port_enable(i); +} diff --git a/drivers/net/ipq807x/ipq807x_ppe.h b/drivers/net/ipq807x/ipq807x_ppe.h new file mode 100644 index 0000000000..b79529e57a --- /dev/null +++ b/drivers/net/ipq807x/ipq807x_ppe.h @@ -0,0 +1,124 @@ +/* + ************************************************************************** + * Copyright (c) 2016-2017 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 IPQ807X_PPE_BASE_ADDR 0x3a000000 +#define IPQ807X_PPE_REG_SIZE 0x1000000 + +#define IPQ807X_PPE_IPE_L3_BASE_ADDR 0x200000 +#define IPQ807X_PPE_L3_VP_PORT_TBL_ADDR (IPQ807X_PPE_IPE_L3_BASE_ADDR + 0x1000) +#define IPQ807X_PPE_L3_VP_PORT_TBL_INC 0x10 + +#define IPQ807X_PPE_QUEUE_MANAGER_BASE_ADDR 0x800000 +#define IPQ807X_PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x10000 +#define IPQ807X_PPE_UCAST_QUEUE_MAP_TBL_INC 0x10 +#define IPQ807X_PPE_QM_UQM_TBL (IPQ807X_PPE_QUEUE_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_UCAST_QUEUE_MAP_TBL_ADDR) +#define IPQ807X_PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x42000 +#define IPQ807X_PPE_QM_UPM_TBL (IPQ807X_PPE_QUEUE_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_UCAST_PRIORITY_MAP_TBL_ADDR) + +#define IPQ807X_PPE_STP_BASE 0x060100 +#define IPQ807X_PPE_MAC_ENABLE 0x001000 +#define IPQ807X_PPE_MAC_SPEED 0x001004 +#define IPQ807X_PPE_MAC_MIB_CTL 0x001034 + +#define IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR 0x400000 + +#define IPQ807X_PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x8000 +#define IPQ807X_PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10 +#define IPQ807X_PPE_L0_FLOW_PORT_MAP_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L0_FLOW_PORT_MAP_TBL_ADDR) + +#define IPQ807X_PPE_L0_FLOW_MAP_TBL_ADDR 0x2000 +#define IPQ807X_PPE_L0_FLOW_MAP_TBL_INC 0x10 +#define IPQ807X_PPE_L0_FLOW_MAP_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L0_FLOW_MAP_TBL_ADDR) + +#define IPQ807X_PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x46000 +#define IPQ807X_PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10 +#define IPQ807X_PPE_L1_FLOW_PORT_MAP_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L1_FLOW_PORT_MAP_TBL_ADDR) + +#define IPQ807X_PPE_L1_FLOW_MAP_TBL_ADDR 0x40000 +#define IPQ807X_PPE_L1_FLOW_MAP_TBL_INC 0x10 +#define IPQ807X_PPE_L1_FLOW_MAP_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L1_FLOW_MAP_TBL_ADDR) + +#define IPQ807X_PPE_L0_C_SP_CFG_TBL_ADDR 0x4000 +#define IPQ807X_PPE_L0_C_SP_CFG_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L0_C_SP_CFG_TBL_ADDR) + +#define IPQ807X_PPE_L1_C_SP_CFG_TBL_ADDR 0x42000 +#define IPQ807X_PPE_L1_C_SP_CFG_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L1_C_SP_CFG_TBL_ADDR) + +#define IPQ807X_PPE_L0_E_SP_CFG_TBL_ADDR 0x6000 +#define IPQ807X_PPE_L0_E_SP_CFG_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L0_E_SP_CFG_TBL_ADDR) + +#define IPQ807X_PPE_L1_E_SP_CFG_TBL_ADDR 0x44000 +#define IPQ807X_PPE_L1_E_SP_CFG_TBL (IPQ807X_PPE_TRAFFIC_MANAGER_BASE_ADDR +\ + IPQ807X_PPE_L1_E_SP_CFG_TBL_ADDR) + +#define IPQ807X_PPE_FPGA_GPIO_BASE_ADDR 0x01008000 + +#define IPQ807X_PPE_MAC_PORT_MUX_OFFSET 0x10 +#define IPQ807X_PPE_FPGA_GPIO_OFFSET 0xc000 +#define IPQ807X_PPE_FPGA_SCHED_OFFSET 0x47a000 +#define IPQ807X_PPE_TDM_CFG_DEPTH_OFFSET 0xb000 +#define IPQ807X_PPE_TDM_SCHED_DEPTH_OFFSET 0x400000 +#define IPQ807X_PPE_PORT_BRIDGE_CTRL_OFFSET 0x060300 + +#define IPQ807X_PPE_TDM_CFG_DEPTH_VAL 0x80000064 +#define IPQ807X_PPE_MAC_PORT_MUX_OFFSET_VAL 0x15 +#define IPQ807X_PPE_TDM_SCHED_DEPTH_VAL 0x32 +#define IPQ807X_PPE_TDM_CFG_VALID 0x20 +#define IPQ807X_PPE_TDM_CFG_DIR_INGRESS 0x0 +#define IPQ807X_PPE_TDM_CFG_DIR_EGRESS 0x10 +#define IPQ807X_PPE_PORT_EDMA 0x0 +#define IPQ807X_PPE_PORT_QCOM1 0x1 +#define IPQ807X_PPE_PORT_QCOM2 0x2 +#define IPQ807X_PPE_PORT_QCOM3 0x3 +#define IPQ807X_PPE_PORT_QCOM4 0x4 +#define IPQ807X_PPE_PORT_XGMAC1 0x5 +#define IPQ807X_PPE_PORT_XGMAC2 0x6 +#define IPQ807X_PPE_PORT_CRYPTO1 0x7 +#define IPQ807X_PPE_PORT_BRIDGE_CTRL_PROMISC_EN 0x20000 +#define IPQ807X_PPE_PORT_BRIDGE_CTRL_TXMAC_EN 0x10000 +#define IPQ807X_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP 0x7f00 +#define IPQ807X_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN 0x8 +#define IPQ807X_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN 0x1 + +#define IPQ807X_PPE_PORT_EDMA_BITPOS 0x1 +#define IPQ807X_PPE_PORT_QCOM1_BITPOS (1 << IPQ807X_PPE_PORT_QCOM1) +#define IPQ807X_PPE_PORT_QCOM2_BITPOS (1 << IPQ807X_PPE_PORT_QCOM2) +#define IPQ807X_PPE_PORT_QCOM3_BITPOS (1 << IPQ807X_PPE_PORT_QCOM3) +#define IPQ807X_PPE_PORT_QCOM4_BITPOS (1 << IPQ807X_PPE_PORT_QCOM4) +#define IPQ807X_PPE_PORT_XGMAC1_BITPOS (1 << IPQ807X_PPE_PORT_XGMAC1) +#define IPQ807X_PPE_PORT_XGMAC2_BITPOS (1 << IPQ807X_PPE_PORT_XGMAC2) +#define IPQ807X_PPE_PORT_CRYPTO1_BITPOS (1 << IPQ807X_PPE_PORT_CRYPTO1) + diff --git a/include/configs/ipq807x.h b/include/configs/ipq807x.h index 87c6697528..b038a1d72b 100644 --- a/include/configs/ipq807x.h +++ b/include/configs/ipq807x.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 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 @@ -112,7 +112,7 @@ extern loff_t board_env_offset; #define CONFIG_ENV_OFFSET board_env_offset #define CONFIG_ENV_SIZE 0x2000 #define CONFIG_ENV_SIZE_MAX (256 << 10) /* 256 KB */ -#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE_MAX + (256 << 10)) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE_MAX + (512 << 10)) #define CONFIG_ENV_IS_IN_NAND 1 @@ -238,6 +238,19 @@ extern loff_t board_env_offset; #define CONFIG_PCI_SCAN_SHOW #endif +#define CONFIG_IPQ807X_EDMA 1 +#define CONFIG_IPQ807X_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 + /* * CRASH DUMP ENABLE */