drivers: net: devsoc: added eth support for devsoc

Change-Id: I4d646c1a89d90febd573ae92980e0c665b1dc060
Signed-off-by: Ram Kumar D <quic_ramd@quicinc.com>
This commit is contained in:
Ram Kumar D 2022-04-25 16:02:00 +05:30
parent 6761f6cf0d
commit a95cba141c
14 changed files with 4503 additions and 0 deletions

View file

@ -169,4 +169,9 @@
xhci@8a00000 {
qcom,emulation = <1>;
};
ess-switch {
switch_mac_mode0 = <PORT_WRAPPER_USXGMII>;
switch_mac_mode1 = <PORT_WRAPPER_USXGMII>;
};
};

View file

@ -15,6 +15,7 @@
#include "skeleton.dtsi"
#include <dt-bindings/qcom/gpio-devsoc.h>
#include <dt-bindings/qcom/eth-devsoc.h>
/ {
serial@78AF000 {

View file

@ -0,0 +1,256 @@
/*
**************************************************************************
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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 DEVSOC_EDMA_CFG_BASE 0x3ab00000
/*
* DEVSOC EDMA register offsets
*/
#define DEVSOC_EDMA_REG_MAS_CTRL 0x0
#define DEVSOC_EDMA_REG_PORT_CTRL 0x4
#define DEVSOC_EDMA_REG_RXDESC2FILL_MAP_0 0x14
#define DEVSOC_EDMA_REG_RXDESC2FILL_MAP_1 0x18
#define DEVSOC_EDMA_REG_DMAR_CTRL 0x48
#define DEVSOC_EDMA_REG_MISC_INT_STAT 0x5c
#define DEVSOC_EDMA_REG_MISC_INT_MASK 0x60
#define DEVSOC_EDMA_REG_TXDESC2CMPL_MAP_0 0x8c
#define DEVSOC_EDMA_REG_TXDESC2CMPL_MAP_1 0x90
#define DEVSOC_EDMA_REG_TXDESC2CMPL_MAP_2 0x94
#define DEVSOC_EDMA_REG_TXDESC2CMPL_MAP_3 0x98
#define DEVSOC_EDMA_REG_MDIO_SLV_PASUE_MAP_0 0xA4
#define DEVSOC_EDMA_REG_MDIO_SLV_PASUE_MAP_1 0xA8
#define DEVSOC_EDMA_REG_TXDESC_BA(n) (0x1000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXDESC_PROD_IDX(n) (0x1004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXDESC_CONS_IDX(n) (0x1008 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXDESC_RING_SIZE(n) (0x100c + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXDESC_CTRL(n) (0x1010 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXDESC_BA2(n) (0x1014 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_CONS_IDX(n) (0x29008 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_RING_SIZE(n) (0x2900c + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_RING_EN(n) (0x2901c + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_INT_STAT(n) (0x31000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXFILL_INT_MASK(n) (0x31004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_BA(n) (0x39000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_PROD_IDX(n) (0x39004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_CONS_IDX(n) (0x39008 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_RING_SIZE(n) (0x3900c + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_FC_THRE(n) (0x39010 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_BA2(n) (0x39028 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_INT_STAT(n) (0x59000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RXDESC_INT_MASK(n) (0x59004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_RX_INT_CTRL(n) (0x5900c + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXCMPL_BA(n) (0x79000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXCMPL_PROD_IDX(n) (0x79004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXCMPL_CONS_IDX(n) (0x79008 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXCMPL_RING_SIZE(n) (0x7900c + (0x1000 * n))
#define DEVSOC_EDMA_REG_TXCMPL_CTRL(n) (0x79014 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TX_INT_STAT(n) (0x99000 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TX_INT_MASK(n) (0x99004 + (0x1000 * n))
#define DEVSOC_EDMA_REG_TX_INT_CTRL(n) (0x9900c + (0x1000 * n))
/*
* EDMA QID2RID configuration
*/
#define DEVSOC_EDMA_QID2RID_TABLE_MEM(q) (0xb9000 + (0x4 * q))
#define DEVSOC_EDMA_CPU_PORT_MC_QID_MIN 256
#define DEVSOC_EDMA_CPU_PORT_MC_QID_MAX 271
#define DEVSOC_EDMA_QID2RID_NUM_PER_REG 4
/*
* EDMA_REG_DMAR_CTRL register
*/
#define DEVSOC_EDMA_DMAR_REQ_PRI_MASK 0x7
#define DEVSOC_EDMA_DMAR_REQ_PRI_SHIFT 0x0
#define DEVSOC_EDMA_DMAR_BURST_LEN_MASK 0x1
#define DEVSOC_EDMA_DMAR_BURST_LEN_SHIFT 3
#define DEVSOC_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK 0x1f
#define DEVSOC_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT 4
#define DEVSOC_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK 0x7
#define DEVSOC_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT 9
#define DEVSOC_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK 0x7
#define DEVSOC_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT 12
#define DEVSOC_EDMA_DMAR_REQ_PRI_SET(x) (((x) & DEVSOC_EDMA_DMAR_REQ_PRI_MASK) \
<< DEVSOC_EDMA_DMAR_REQ_PRI_SHIFT)
#define DEVSOC_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SET(x) (((x) & DEVSOC_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK) \
<< DEVSOC_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT)
#define DEVSOC_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SET(x) (((x) & DEVSOC_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK) \
<< DEVSOC_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT)
#define DEVSOC_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SET(x) (((x) & DEVSOC_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK) \
<< DEVSOC_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT)
#define DEVSOC_EDMA_DMAR_BURST_LEN_SET(x) (((x) & DEVSOC_EDMA_DMAR_BURST_LEN_MASK) \
<< DEVSOC_EDMA_DMAR_BURST_LEN_SHIFT)
#define DEVSOC_EDMA_BURST_LEN_ENABLE 0x0
/*
* EDMA_REG_PORT_CTRL register
*/
#define DEVSOC_EDMA_PORT_CTRL_EN 0x3
/*
* EDMA_REG_TXDESC_PROD_IDX register
*/
#define DEVSOC_EDMA_TXDESC_PROD_IDX_MASK 0xffff
/*
* EDMA_REG_TXDESC_CONS_IDX register
*/
#define DEVSOC_EDMA_TXDESC_CONS_IDX_MASK 0xffff
/*
* EDMA_REG_TXDESC_RING_SIZE register
*/
#define DEVSOC_EDMA_TXDESC_RING_SIZE_MASK 0xffff
/*
* EDMA_REG_TXDESC_CTRL register
*/
#define DEVSOC_EDMA_TXDESC_TX_EN 0x1
/*
* EDMA_REG_TXCMPL_PROD_IDX register
*/
#define DEVSOC_EDMA_TXCMPL_PROD_IDX_MASK 0xffff
/*
* EDMA_REG_TXCMPL_CONS_IDX register
*/
#define DEVSOC_EDMA_TXCMPL_CONS_IDX_MASK 0xffff
/*
* EDMA_REG_TX_INT_CTRL register
*/
#define DEVSOC_EDMA_TX_INT_MASK 0x3
/*
* EDMA_REG_RXFILL_PROD_IDX register
*/
#define DEVSOC_EDMA_RXFILL_PROD_IDX_MASK 0xffff
/*
* EDMA_REG_RXFILL_CONS_IDX register
*/
#define DEVSOC_EDMA_RXFILL_CONS_IDX_MASK 0xffff
/*
* EDMA_REG_RXFILL_RING_SIZE register
*/
#define DEVSOC_EDMA_RXFILL_RING_SIZE_MASK 0xffff
#define DEVSOC_EDMA_RXFILL_BUF_SIZE_MASK 0xffff0000
#define DEVSOC_EDMA_RXFILL_BUF_SIZE_SHIFT 16
/*
* EDMA_REG_RXFILL_RING_EN register
*/
#define DEVSOC_EDMA_RXFILL_RING_EN 0x1
/*
* EDMA_REG_RXFILL_INT_MASK register
*/
#define DEVSOC_EDMA_RXFILL_INT_MASK 0x1
/*
* EDMA_REG_RXDESC_PROD_IDX register
*/
#define DEVSOC_EDMA_RXDESC_PROD_IDX_MASK 0xffff
/*
* EDMA_REG_RXDESC_CONS_IDX register
*/
#define DEVSOC_EDMA_RXDESC_CONS_IDX_MASK 0xffff
/*
* EDMA_REG_RXDESC_RING_SIZE register
*/
#define DEVSOC_EDMA_RXDESC_RING_SIZE_MASK 0xffff
#define DEVSOC_EDMA_RXDESC_PL_OFFSET_MASK 0x1ff
#define DEVSOC_EDMA_RXDESC_PL_OFFSET_SHIFT 16
/*
* EDMA_REG_RXDESC_CTRL register
*/
#define DEVSOC_EDMA_RXDESC_RX_EN 0x1
/*
* EDMA_REG_TX_INT_MASK register
*/
#define DEVSOC_EDMA_TX_INT_MASK_PKT_INT 0x1
#define DEVSOC_EDMA_TX_INT_MASK_UGT_INT 0x2
/*
* EDMA_REG_RXDESC_INT_MASK register
*/
#define DEVSOC_EDMA_RXDESC_INT_MASK_PKT_INT 0x1
#define DEVSOC_EDMA_MASK_INT_DISABLE 0x0
/*
* TXDESC shift values
*/
#define DEVSOC_EDMA_TXDESC_DATA_OFFSET_SHIFT 0
#define DEVSOC_EDMA_TXDESC_DATA_OFFSET_MASK 0xfff
#define DEVSOC_EDMA_TXDESC_DATA_LENGTH_SHIFT 0
#define DEVSOC_EDMA_TXDESC_DATA_LENGTH_MASK 0x1ffff
#define DEVSOC_EDMA_DST_PORT_TYPE 2
#define DEVSOC_EDMA_DST_PORT_TYPE_SHIFT 28
#define DEVSOC_EDMA_DST_PORT_TYPE_MASK (0xf << DEVSOC_EDMA_DST_PORT_TYPE_SHIFT)
#define DEVSOC_EDMA_DST_PORT_ID_SHIFT 16
#define DEVSOC_EDMA_DST_PORT_ID_MASK (0xfff << DEVSOC_EDMA_DST_PORT_ID_SHIFT)
#define DEVSOC_EDMA_DST_PORT_TYPE_SET(x) (((x) << DEVSOC_EDMA_DST_PORT_TYPE_SHIFT) & DEVSOC_EDMA_DST_PORT_TYPE_MASK)
#define DEVSOC_EDMA_DST_PORT_ID_SET(x) (((x) << EDMA_DST_PORT_ID_SHIFT) & EDMA_DST_PORT_ID_MASK)
#define DEVSOC_EDMA_RXDESC_SRCINFO_TYPE_PORTID 0x2000
#define DEVSOC_EDMA_RXDESC_SRCINFO_TYPE_SHIFT 8
#define DEVSOC_EDMA_RXDESC_SRCINFO_TYPE_MASK 0xf000
#define DEVSOC_EDMA_RXDESC_PORTNUM_BITS 0x0FFF
#define DEVSOC_EDMA_RING_DMA_MASK 0xffffffff
/*
* RXDESC shift values
*/
#define DEVSOC_EDMA_RXDESC_PKT_SIZE_MASK 0x3ffff
#define DEVSOC_EDMA_RXDESC_PKT_SIZE_SHIFT 0
#define DEVSOC_EDMA_RXDESC_SRC_INFO_GET(x) (x & 0xFFFF)
#define DEVSOC_EDMA_RXDESC_RING_INT_STATUS_MASK 0x3
#define DEVSOC_EDMA_RXFILL_RING_INT_STATUS_MASK 0x1
#define DEVSOC_EDMA_TXCMPL_RING_INT_STATUS_MASK 0x3
#define DEVSOC_EDMA_TXCMPL_RETMODE_OPAQUE 0x0
#define DEVSOC_EDMA_TX_NE_INT_EN 0x2
#define DEVSOC_EDMA_RX_NE_INT_EN 0x2
#define DEVSOC_EDMA_TX_INITIAL_PROD_IDX 0x0
#endif /* __EDMA_REGS__ */

View file

@ -38,6 +38,7 @@
DECLARE_GLOBAL_DATA_PTR;
extern int devsoc_edma_init(void *cfg);
extern int ipq_spi_init(u16);
const char *rsvd_node = "/reserved-memory";
@ -499,3 +500,16 @@ void ipq_fdt_fixup_usb_device_mode(void *blob)
{
return;
}
#ifdef CONFIG_DEVSOC_EDMA
int board_eth_init(bd_t *bis)
{
int ret = 0;
ret = devsoc_edma_init(NULL);
if (ret != 0)
printf("%s: devsoc_edma_init failed : %d\n", __func__, ret);
return ret;
}
#endif

View file

@ -93,6 +93,13 @@ obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/ipq5018_gmac.o
obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/ipq5018_uniphy.o
obj-$(CONFIG_IPQ5018_MDIO) += ipq5018/ipq5018_mdio.o
obj-$(CONFIG_IPQ5018_GMAC) += ipq5018/athrs17_phy.o
obj-$(CONFIG_DEVSOC_EDMA) += devsoc/devsoc_edma.o
obj-$(CONFIG_DEVSOC_EDMA) += devsoc/devsoc_ppe.o
ifndef CONFIG_DEVSOC_RUMI
obj-$(CONFIG_DEVSOC_EDMA) += devsoc/devsoc_uniphy.o
endif
obj-$(CONFIG_IPQ_MDIO) += ipq_common/ipq_mdio.o
obj-$(CONFIG_GEPHY) += ipq_common/ipq_gephy.o
obj-$(CONFIG_QCA8075_PHY) += ipq_common/ipq_qca8075.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,341 @@
/*
**************************************************************************
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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 __DEVSOC_EDMA__
#define __DEVSOC_EDMA__
#define DEVSOC_NSS_DP_START_PHY_PORT 1
#define DEVSOC_NSS_DP_MAX_PHY_PORTS 2
#define DEVSOC_EDMA_DEVICE_NODE_NAME "edma"
/* Number of descriptors in each ring is defined with below macro */
#define DEVSOC_EDMA_TX_RING_SIZE 128
#define DEVSOC_EDMA_RX_RING_SIZE 128
/* Number of byte in a descriptor is defined with below macros for each of
* the rings respectively */
#define DEVSOC_EDMA_TXDESC_DESC_SIZE (sizeof(struct devsoc_edma_txdesc_desc))
#define DEVSOC_EDMA_TXCMPL_DESC_SIZE (sizeof(struct devsoc_edma_txcmpl_desc))
#define DEVSOC_EDMA_RXDESC_DESC_SIZE (sizeof(struct devsoc_edma_rxdesc_desc))
#define DEVSOC_EDMA_RXFILL_DESC_SIZE (sizeof(struct devsoc_edma_rxfill_desc))
#define DEVSOC_EDMA_RX_SEC_DESC_SIZE (sizeof(struct devsoc_edma_rx_sec_desc))
#define DEVSOC_EDMA_TX_SEC_DESC_SIZE (sizeof(struct devsoc_edma_tx_sec_desc))
#define DEVSOC_EDMA_START_GMACS DEVSOC_NSS_DP_START_PHY_PORT
#define DEVSOC_EDMA_MAX_GMACS DEVSOC_NSS_DP_MAX_PHY_PORTS
#define DEVSOC_EDMA_TX_BUFF_SIZE 2048
#define DEVSOC_EDMA_RX_BUFF_SIZE 2048
/* Max number of rings of each type is defined with below macro */
#define DEVSOC_EDMA_MAX_TXCMPL_RINGS 24 /* Max TxCmpl rings */
#define DEVSOC_EDMA_MAX_TXDESC_RINGS 24 /* Max TxDesc rings */
#define DEVSOC_EDMA_MAX_RXDESC_RINGS 16 /* Max RxDesc rings */
#define DEVSOC_EDMA_MAX_RXFILL_RINGS 8 /* Max RxFill rings */
#define DEVSOC_EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
#define DEVSOC_EDMA_RXFILL_DESC(R, i) DEVSOC_EDMA_GET_DESC(R, i, struct devsoc_edma_rxfill_desc)
#define DEVSOC_EDMA_RXDESC_DESC(R, i) DEVSOC_EDMA_GET_DESC(R, i, struct devsoc_edma_rxdesc_desc)
#define DEVSOC_EDMA_TXDESC_DESC(R, i) DEVSOC_EDMA_GET_DESC(R, i, struct devsoc_edma_txdesc_desc)
#define DEVSOC_EDMA_TXCMPL_DESC(R, i) DEVSOC_EDMA_GET_DESC(R, i, struct devsoc_edma_txcmpl_desc)
#define DEVSOC_EDMA_DEV 1
/* Only 1 ring of each type will be used in U-Boot which is defined with
* below macros */
#define DEVSOC_EDMA_TX_DESC_RING_START 23
#define DEVSOC_EDMA_TX_DESC_RING_NOS 1
#define DEVSOC_EDMA_TX_DESC_RING_SIZE \
(DEVSOC_EDMA_TX_DESC_RING_START + DEVSOC_EDMA_TX_DESC_RING_NOS)
#define DEVSOC_EDMA_TX_CMPL_RING_START 23
#define DEVSOC_EDMA_TX_CMPL_RING_NOS 1
#define DEVSOC_EDMA_TX_CMPL_RING_SIZE \
(DEVSOC_EDMA_TX_CMPL_RING_START + DEVSOC_EDMA_TX_CMPL_RING_NOS)
#define DEVSOC_EDMA_RX_DESC_RING_START 15
#define DEVSOC_EDMA_RX_DESC_RING_NOS 1
#define DEVSOC_EDMA_RX_DESC_RING_SIZE \
(DEVSOC_EDMA_RX_DESC_RING_START + DEVSOC_EDMA_RX_DESC_RING_NOS)
#define DEVSOC_EDMA_RX_FILL_RING_START 7
#define DEVSOC_EDMA_RX_FILL_RING_NOS 1
#define DEVSOC_EDMA_RX_FILL_RING_SIZE \
(DEVSOC_EDMA_RX_FILL_RING_START + DEVSOC_EDMA_RX_FILL_RING_NOS)
#define NETDEV_TX_BUSY 1
/*
* RxDesc descriptor
*/
struct devsoc_edma_rxdesc_desc {
uint32_t rdes0; /* Contains buffer address */
uint32_t rdes1; /* Contains more bit, priority bit, service code */
uint32_t rdes2; /* Contains opaque */
uint32_t rdes3; /* Contains opaque high bits */
uint32_t rdes4; /* Contains destination and source information */
uint32_t rdes5; /* Contains WiFi QoS, data length */
uint32_t rdes6; /* Contains hash value, check sum status */
uint32_t rdes7; /* Contains DSCP, packet offsets */
};
/*
* EDMA Rx Secondary Descriptor
*/
struct devsoc_edma_rx_sec_desc {
uint32_t rx_sec0; /* Contains timestamp */
uint32_t rx_sec1; /* Contains secondary checksum status */
uint32_t rx_sec2; /* Contains QoS tag */
uint32_t rx_sec3; /* Contains flow index details */
uint32_t rx_sec4; /* Contains secondary packet offsets */
uint32_t rx_sec5; /* Contains multicast bit, checksum */
uint32_t rx_sec6; /* Contains SVLAN, CVLAN */
uint32_t rx_sec7; /* Contains secondary SVLAN, CVLAN */
};
/*
* RxFill descriptor
*/
struct devsoc_edma_rxfill_desc {
uint32_t rdes0; /* Contains buffer address */
uint32_t rdes1; /* Contains buffer size */
uint32_t rdes2; /* Contains opaque */
uint32_t rdes3; /* Contains opaque high bits */
};
/*
* TxDesc descriptor
*/
struct devsoc_edma_txdesc_desc {
uint32_t tdes0; /* Low 32-bit of buffer address */
uint32_t tdes1; /* Buffer recycling, PTP tag flag, PRI valid flag */
uint32_t tdes2; /* Low 32-bit of opaque value */
uint32_t tdes3; /* High 32-bit of opaque value */
uint32_t tdes4; /* Source/Destination port info */
uint32_t tdes5; /* VLAN offload, csum_mode, ip_csum_en, tso_en, data length */
uint32_t tdes6; /* MSS/hash_value/PTP tag, data offset */
uint32_t tdes7; /* L4/L3 offset, PROT type, L2 type, CVLAN/SVLAN tag, service code */
};
/*
* EDMA Tx Secondary Descriptor
*/
struct devsoc_edma_tx_sec_desc {
uint32_t tx_sec0; /* Reserved */
uint32_t tx_sec1; /* Custom csum offset, payload offset, TTL/NAT action */
uint32_t rx_sec2; /* NAPT translated port, DSCP value, TTL value */
uint32_t rx_sec3; /* Flow index value and valid flag */
uint32_t rx_sec4; /* Reserved */
uint32_t rx_sec5; /* Reserved */
uint32_t rx_sec6; /* CVLAN/SVLAN command */
uint32_t rx_sec7; /* CVLAN/SVLAN tag value */
};
/*
* TxCmpl descriptor
*/
struct devsoc_edma_txcmpl_desc {
uint32_t tdes0; /* Low 32-bit opaque value */
uint32_t tdes1; /* High 32-bit opaque value */
uint32_t tdes2; /* More fragment, transmit ring id, pool id */
uint32_t tdes3; /* Error indications */
};
/*
* Tx descriptor ring
*/
struct devsoc_edma_txdesc_ring {
uint32_t prod_idx; /* Producer index */
uint32_t avail_desc; /* Number of available descriptor to process */
uint32_t id; /* TXDESC ring number */
struct devsoc_edma_txdesc_desc *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
struct devsoc_edma_tx_sec_desc *sdesc; /* Secondary descriptor ring virtual addr */
dma_addr_t sdma; /* Secondary descriptor ring physical address */
uint16_t count; /* number of descriptors */
};
/*
* TxCmpl ring
*/
struct devsoc_edma_txcmpl_ring {
uint32_t cons_idx; /* Consumer index */
uint32_t avail_pkt; /* Number of available packets to process */
struct devsoc_edma_txcmpl_desc *desc; /* descriptor ring virtual address */
uint32_t id; /* TXCMPL ring number */
dma_addr_t dma; /* descriptor ring physical address */
uint32_t count; /* Number of descriptors in the ring */
};
/*
* RxFill ring
*/
struct devsoc_edma_rxfill_ring {
uint32_t id; /* RXFILL ring number */
uint32_t count; /* number of descriptors in the ring */
uint32_t prod_idx; /* Ring producer index */
struct devsoc_edma_rxfill_desc *desc; /* descriptor ring virtual address */
dma_addr_t dma; /* descriptor ring physical address */
};
/*
* RxDesc ring
*/
struct devsoc_edma_rxdesc_ring {
uint32_t id; /* RXDESC ring number */
uint32_t count; /* number of descriptors in the ring */
uint32_t cons_idx; /* Ring consumer index */
struct devsoc_edma_rxdesc_desc *desc; /* Primary descriptor ring virtual addr */
struct devsoc_edma_sec_rxdesc_ring *sdesc; /* Secondary desc ring VA */
struct devsoc_edma_rxfill_ring *rxfill; /* RXFILL ring used */
dma_addr_t dma; /* Primary descriptor ring physical address */
dma_addr_t sdma; /* Secondary descriptor ring physical address */
};
enum devsoc_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 devsoc_edma_common_info *c_info; /* edma common info */
};
/* edma hw specific data */
struct devsoc_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 devsoc_edma_txdesc_ring *txdesc_ring; /* Tx Descriptor Ring, SW is producer */
struct devsoc_edma_txcmpl_ring *txcmpl_ring; /* Tx Completion Ring, SW is consumer */
struct devsoc_edma_rxdesc_ring *rxdesc_ring; /* Rx Descriptor Ring, SW is consumer */
struct devsoc_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 devsoc_edma_common_info {
struct devsoc_edma_hw hw;
};
#define MAX_PHY 6
struct devsoc_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 devsoc_edma_common_info *c_info;
struct phy_ops *ops[MAX_PHY];
const char phy_name[MDIO_NAME_LEN];
} __attribute__ ((aligned(8)));
static inline void* devsoc_alloc_mem(u32 size)
{
void *p = malloc(size);
if (p != NULL)
memset(p, 0, size);
return p;
}
static inline void* devsoc_alloc_memalign(u32 size)
{
void *p = memalign(CONFIG_SYS_CACHELINE_SIZE, size);
if (p != NULL)
memset(p, 0, size);
return p;
}
static inline void devsoc_free_mem(void *ptr)
{
if (ptr)
free(ptr);
}
uint32_t devsoc_edma_reg_read(uint32_t reg_off);
void devsoc_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];
} devsoc_edma_phy_addr_t;
/* devsoc edma Paramaters */
typedef struct {
uint base;
int unit;
uint mac_conn_to_phy;
phy_interface_t phy;
devsoc_edma_phy_addr_t phy_addr;
char phy_name[MDIO_NAME_LEN];
} devsoc_edma_board_cfg_t;
extern void devsoc_ppe_provision_init(void);
extern void devsoc_port_mac_clock_reset(int port);
extern void devsoc_speed_clock_set(int port, int clk[4]);
extern void devsoc_pqsgmii_speed_set(int port, int speed, int status);
extern void devsoc_uxsgmii_speed_set(int port, int speed, int duplex, int status);
extern void ppe_port_mux_mac_type_set(int port_id, int mode);
extern void ppe_port_bridge_txmac_set(int port, int status);
extern void devsoc_10g_r_speed_set(int port, int status);
extern int phy_status_get_from_ppe(int port_id);
extern void devsoc_ppe_acl_set(int rule_id, int rule_type, int pkt_type, int l4_port_no, int l4_port_mask, int permit, int deny);
extern void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode);
#endif /* ___DEVSOC_EDMA__ */

View file

@ -0,0 +1,885 @@
/*
**************************************************************************
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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 <common.h>
#include <asm/global_data.h>
#include "devsoc_ppe.h"
#ifndef CONFIG_DEVSOC_RUMI
#include "devsoc_uniphy.h"
#endif
#include <fdtdec.h>
#include "ipq_phy.h"
DECLARE_GLOBAL_DATA_PTR;
#ifdef DEBUG
#define pr_debug(fmt, args...) printf(fmt, ##args);
#else
#define pr_debug(fmt, args...)
#endif
#define pr_info(fmt, args...) printf(fmt, ##args);
extern int is_uniphy_enabled(int uniphy_index);
extern void uniphy_port5_clock_source_set(void);
/*
* devsoc_ppe_reg_read()
*/
static inline void devsoc_ppe_reg_read(u32 reg, u32 *val)
{
*val = readl((void *)(DEVSOC_PPE_BASE_ADDR + reg));
}
/*
* devsoc_ppe_reg_write()
*/
static inline void devsoc_ppe_reg_write(u32 reg, u32 val)
{
writel(val, (void *)(DEVSOC_PPE_BASE_ADDR + reg));
}
void ppe_ipo_rule_reg_set(union ipo_rule_reg_u *hw_reg, int rule_id)
{
int i;
for (i = 0; i < 3; i++) {
devsoc_ppe_reg_write(IPO_CSR_BASE_ADDR + IPO_RULE_REG_ADDRESS +
(rule_id * IPO_RULE_REG_INC) + (i * 4), hw_reg->val[i]);
}
}
void ppe_ipo_mask_reg_set(union ipo_mask_reg_u *hw_mask, int rule_id)
{
int i;
for (i = 0; i < 2; i++) {
devsoc_ppe_reg_write((IPO_CSR_BASE_ADDR + IPO_MASK_REG_ADDRESS +
(rule_id * IPO_MASK_REG_INC) + (i * 4)), hw_mask->val[i]);
}
}
void ppe_ipo_action_set(union ipo_action_u *hw_act, int rule_id)
{
int i;
for (i = 0; i < 5; i++) {
devsoc_ppe_reg_write((IPE_L2_BASE_ADDR + IPO_ACTION_ADDRESS +
(rule_id * IPO_ACTION_INC) + (i * 4)), hw_act->val[i]);
}
}
void devsoc_ppe_acl_set(int rule_id, int rule_type, int field0, int field1, int mask, int permit, int deny)
{
union ipo_rule_reg_u hw_reg = {0};
union ipo_mask_reg_u hw_mask = {0};
union ipo_action_u hw_act = {0};
memset(&hw_reg, 0, sizeof(hw_reg));
memset(&hw_mask, 0, sizeof(hw_mask));
memset(&hw_act, 0, sizeof(hw_act));
if (rule_id < MAX_RULE) {
hw_act.bf.dest_info_change_en = 1;
hw_mask.bf.maskfield_0 = mask;
hw_reg.bf.rule_type = rule_type;
if (rule_type == ADPT_ACL_HPPE_IPV4_DIP_RULE) {
hw_reg.bf.rule_field_0 = field1;
hw_reg.bf.rule_field_1 = field0<<17;
hw_mask.bf.maskfield_1 = 7<<17;
if (permit == 0x0) {
hw_act.bf.fwd_cmd = 0;/* forward */
hw_reg.bf.pri = 0x1;
}
if (deny == 0x1) {
hw_act.bf.fwd_cmd = 1;/* drop */
hw_reg.bf.pri = 0x0;
}
} else if (rule_type == ADPT_ACL_HPPE_MAC_SA_RULE) {
/* src mac AC rule */
hw_reg.bf.rule_field_0 = field1;
hw_reg.bf.rule_field_1 = field0;
hw_mask.bf.maskfield_1 = 0xffff;
hw_act.bf.fwd_cmd = 1;/* drop */
hw_reg.bf.pri = 0x2;
/* bypass fdb lean and fdb freash */
hw_act.bf.bypass_bitmap_0 = 0x1800;
} else if (rule_type == ADPT_ACL_HPPE_MAC_DA_RULE) {
/* dest mac AC rule */
hw_reg.bf.rule_field_0 = field1;
hw_reg.bf.rule_field_1 = field0;
hw_mask.bf.maskfield_1 = 0xffff;
hw_act.bf.fwd_cmd = 1;/* drop */
hw_reg.bf.pri = 0x2;
}
/* bind port1-port6 */
hw_reg.bf.src_0 = 0x0;
hw_reg.bf.src_1 = 0x3F;
ppe_ipo_rule_reg_set(&hw_reg, rule_id);
ppe_ipo_mask_reg_set(&hw_mask, rule_id);
ppe_ipo_action_set(&hw_act, rule_id);
}
}
/*
* devsoc_ppe_vp_port_tbl_set()
*/
static void devsoc_ppe_vp_port_tbl_set(int port, int vsi)
{
u32 addr = DEVSOC_PPE_L3_VP_PORT_TBL_ADDR +
(port * DEVSOC_PPE_L3_VP_PORT_TBL_INC);
devsoc_ppe_reg_write(addr, 0x0);
devsoc_ppe_reg_write(addr + 0x4 , 1 << 9 | vsi << 10);
devsoc_ppe_reg_write(addr + 0x8, 0x0);
devsoc_ppe_reg_write(addr + 0xc, 0x0);
}
/*
* devsoc_ppe_ucast_queue_map_tbl_queue_id_set()
*/
static void devsoc_ppe_ucast_queue_map_tbl_queue_id_set(int queue, int port)
{
uint32_t val;
devsoc_ppe_reg_read(DEVSOC_PPE_QM_UQM_TBL +
(port * DEVSOC_PPE_UCAST_QUEUE_MAP_TBL_INC), &val);
val |= queue << 4;
devsoc_ppe_reg_write(DEVSOC_PPE_QM_UQM_TBL +
(port * DEVSOC_PPE_UCAST_QUEUE_MAP_TBL_INC), val);
}
/*
* devsoc_vsi_setup()
*/
static void devsoc_vsi_setup(int vsi, uint8_t group_mask)
{
uint32_t val = (group_mask << 24 | group_mask << 16 | group_mask << 8
| group_mask);
/* Set mask */
devsoc_ppe_reg_write(0x063800 + (vsi * 0x10), val);
/* new addr lrn en | station move lrn en */
devsoc_ppe_reg_write(0x063804 + (vsi * 0x10), 0x9);
}
/*
* devsoc_gmac_port_disable()
*/
static void devsoc_gmac_port_disable(int port)
{
devsoc_ppe_reg_write(DEVSOC_PPE_MAC_ENABLE + (0x200 * port), 0x70);
devsoc_ppe_reg_write(DEVSOC_PPE_MAC_SPEED + (0x200 * port), 0x2);
devsoc_ppe_reg_write(DEVSOC_PPE_MAC_MIB_CTL + (0x200 * port), 0x1);
}
/*
* ppe_port_bridge_txmac_set()
* TXMAC should be disabled for all ports by default
* TXMAC should be enabled for all ports that are link up alone
*/
void ppe_port_bridge_txmac_set(int port_id, int status)
{
uint32_t reg_value = 0;
devsoc_ppe_reg_read(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS +
(port_id * PORT_BRIDGE_CTRL_INC), &reg_value);
if (status == 0)
reg_value |= TX_MAC_EN;
else
reg_value &= ~TX_MAC_EN;
devsoc_ppe_reg_write(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS +
(port_id * PORT_BRIDGE_CTRL_INC), reg_value);
}
#ifndef CONFIG_DEVSOC_RUMI
/*
* devsoc_port_mac_clock_reset()
*/
void devsoc_port_mac_clock_reset(int port)
{
int reg_val, reg_val1;
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
switch(port) {
case 0:
/* Assert */
reg_val |= GCC_PPE_PORT1_MAC_ARES;
reg_val1 |= GCC_PORT1_ARES;
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
/* De-Assert */
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
reg_val &= ~GCC_PPE_PORT1_MAC_ARES;
reg_val1 &= ~GCC_PORT1_ARES;
break;
case 1:
/* Assert */
reg_val |= GCC_PPE_PORT2_MAC_ARES;
reg_val1 |= GCC_PORT2_ARES;
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
/* De-Assert */
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
reg_val &= ~GCC_PPE_PORT2_MAC_ARES;
reg_val1 &= ~GCC_PORT2_ARES;
break;
case 2:
/* Assert */
reg_val |= GCC_PPE_PORT3_MAC_ARES;
reg_val1 |= GCC_PORT3_ARES;
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
/* De-Assert */
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
reg_val &= ~GCC_PPE_PORT3_MAC_ARES;
reg_val1 &= ~GCC_PORT3_ARES;
break;
case 3:
/* Assert */
reg_val |= GCC_PPE_PORT4_MAC_ARES;
reg_val1 |= GCC_PORT4_ARES;
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
/* De-Assert */
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
reg_val &= ~GCC_PPE_PORT4_MAC_ARES;
reg_val1 &= ~GCC_PORT4_ARES;
break;
case 4:
/* Assert */
reg_val |= GCC_PPE_PORT5_MAC_ARES;
reg_val1 |= GCC_PORT5_ARES;
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
/* De-Assert */
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
reg_val &= ~GCC_PPE_PORT5_MAC_ARES;
reg_val1 &= ~GCC_PORT5_ARES;
break;
case 5:
/* Assert */
reg_val |= GCC_PPE_PORT6_MAC_ARES;
reg_val1 |= GCC_PORT6_ARES;
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
/* De-Assert */
reg_val = readl(NSS_CC_PPE_RESET_ADDR);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
reg_val &= ~GCC_PPE_PORT6_MAC_ARES;
reg_val1 &= ~GCC_PORT6_ARES;
break;
default:
break;
}
writel(reg_val, NSS_CC_PPE_RESET_ADDR);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
mdelay(150);
}
void devsoc_speed_clock_set(int port_id, int clk[4])
{
int i;
int reg_val[6];
for (i = 0; i < 6; i++)
{
reg_val[i] = readl(NSS_CC_PORT1_RX_CMD_RCGR + (i * 0x4) + (port_id * 0x18));
}
reg_val[0] &= ~0x1;
reg_val[1] &= ~0x71f;
reg_val[2] &= ~0x1ff;
reg_val[3] &= ~0x1;
reg_val[4] &= ~0x71f;
reg_val[5] &= ~0x1ff;
reg_val[1] |= clk[0];
reg_val[2] |= clk[1];
reg_val[4] |= clk[2];
reg_val[5] |= clk[3];
/* Port Rx direction speed clock cfg */
writel(reg_val[1], NSS_CC_PORT1_RX_CMD_RCGR + 0x4 + (port_id * 0x18));
writel(reg_val[2], NSS_CC_PORT1_RX_CMD_RCGR + 0x8 + (port_id * 0x18));
writel(reg_val[0] | 0x1 , NSS_CC_PORT1_RX_CMD_RCGR + (port_id * 0x18));
/* Port Tx direction speed clock cfg */
writel(reg_val[4], NSS_CC_PORT1_RX_CMD_RCGR + 0x10 + (port_id * 0x18));
writel(reg_val[5], NSS_CC_PORT1_RX_CMD_RCGR + 0x14 + (port_id * 0x18));
writel(reg_val[3] | 0x1, NSS_CC_PORT1_RX_CMD_RCGR + 0xc + (port_id * 0x18));
}
int phy_status_get_from_ppe(int port_id)
{
uint32_t reg_field = 0;
devsoc_ppe_reg_read(PORT_PHY_STATUS_ADDRESS, &reg_field);
if (port_id == (PORT5 - PPE_UNIPHY_INSTANCE1))
reg_field >>= PORT_PHY_STATUS_PORT5_1_OFFSET;
else
reg_field >>= PORT_PHY_STATUS_PORT6_OFFSET;
return ((reg_field >> 7) & 0x1) ? 0 : 1;
}
void ppe_xgmac_10g_r_speed_set(uint32_t port)
{
uint32_t reg_value = 0;
pr_debug("DEBUGGING 10g_r_speed_set......... PORTID = %d\n", port);
devsoc_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), &reg_value);
reg_value |=JD;
devsoc_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value);
pr_debug("NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION Address = 0x%x -> Value = %u\n",
PPE_SWITCH_NSS_SWITCH_XGMAC0 + (port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION),
reg_value);
}
void devsoc_10g_r_speed_set(int port, int status)
{
ppe_xgmac_10g_r_speed_set(port);
ppe_port_bridge_txmac_set(port + 1, status);
ppe_port_txmac_status_set(port);
ppe_port_rxmac_status_set(port);
ppe_mac_packet_filter_set(port);
}
#endif
void ppe_xgmac_speed_set(uint32_t port, int speed)
{
uint32_t reg_value = 0;
pr_debug("\nDEBUGGING xgmac_speed_set......... PORTID = %d\n", port);
devsoc_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), &reg_value);
switch(speed) {
case 0:
case 1:
case 2:
reg_value &=~USS;
reg_value |=SS(XGMAC_SPEED_SELECT_1000M);
break;
case 3:
reg_value |=USS;
reg_value |=SS(XGMAC_SPEED_SELECT_10000M);
break;
case 4:
reg_value |=USS;
reg_value |=SS(XGMAC_SPEED_SELECT_2500M);
break;
case 5:
reg_value |=USS;
reg_value |=SS(XGMAC_SPEED_SELECT_5000M);
break;
}
reg_value |=JD;
devsoc_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value);
pr_debug("NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION Address = 0x%x -> Value = %u\n",
PPE_SWITCH_NSS_SWITCH_XGMAC0 + (port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION),
reg_value);
}
void ppe_port_txmac_status_set(uint32_t port)
{
uint32_t reg_value = 0;
pr_debug("DEBUGGING txmac_status_set......... PORTID = %d\n", port);
devsoc_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), &reg_value);
reg_value |=TE;
devsoc_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value);
pr_debug("NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION Address = 0x%x -> Value = %u\n",
PPE_SWITCH_NSS_SWITCH_XGMAC0 + (port * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION),
reg_value);
}
void ppe_port_rxmac_status_set(uint32_t port)
{
uint32_t reg_value = 0;
pr_debug("DEBUGGING rxmac_status_set......... PORTID = %d\n", port);
devsoc_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
MAC_RX_CONFIGURATION_ADDRESS +
(port * NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION), &reg_value);
reg_value |= 0x5ee00c0;
reg_value |=RE;
reg_value |=ACS;
reg_value |=CST;
devsoc_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
MAC_RX_CONFIGURATION_ADDRESS +
(port * NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION), reg_value);
pr_debug("NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION Address = 0x%x -> Value = %u\n",
PPE_SWITCH_NSS_SWITCH_XGMAC0 + MAC_RX_CONFIGURATION_ADDRESS +
(port * NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION),
reg_value);
}
void ppe_mac_packet_filter_set(uint32_t port)
{
pr_debug("DEBUGGING mac_packet_filter_set......... PORTID = %d\n", port);
devsoc_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
MAC_PACKET_FILTER_ADDRESS +
(port * MAC_PACKET_FILTER_INC), 0x81);
pr_debug("NSS_SWITCH_XGMAC_MAC_PACKET_FILTER Address = 0x%x -> Value = %u\n",
PPE_SWITCH_NSS_SWITCH_XGMAC0 + MAC_PACKET_FILTER_ADDRESS +
(port * MAC_PACKET_FILTER_ADDRESS),
0x81);
}
void devsoc_uxsgmii_speed_set(int port, int speed, int duplex,
int status)
{
#ifndef CONFIG_DEVSOC_RUMI
uint32_t uniphy_index;
/* Setting the speed only for PORT5 and PORT6 */
if (port == (PORT5 - PPE_UNIPHY_INSTANCE1))
uniphy_index = PPE_UNIPHY_INSTANCE1;
else if (port == (PORT6 - PPE_UNIPHY_INSTANCE1))
uniphy_index = PPE_UNIPHY_INSTANCE2;
else
uniphy_index = PPE_UNIPHY_INSTANCE0;
ppe_uniphy_usxgmii_autoneg_completed(uniphy_index);
ppe_uniphy_usxgmii_speed_set(uniphy_index, speed);
#endif
ppe_xgmac_speed_set(port, speed);
#ifndef CONFIG_DEVSOC_RUMI
ppe_uniphy_usxgmii_duplex_set(uniphy_index, duplex);
ppe_uniphy_usxgmii_port_reset(uniphy_index);
#endif
ppe_port_bridge_txmac_set(port + 1, status);
ppe_port_txmac_status_set(port);
ppe_port_rxmac_status_set(port);
ppe_mac_packet_filter_set(port);
}
void devsoc_pqsgmii_speed_set(int port, int speed, int status)
{
ppe_port_bridge_txmac_set(port + 1, status);
devsoc_ppe_reg_write(DEVSOC_PPE_MAC_SPEED + (0x200 * port), speed);
devsoc_ppe_reg_write(DEVSOC_PPE_MAC_ENABLE + (0x200 * port), 0x73);
devsoc_ppe_reg_write(DEVSOC_PPE_MAC_MIB_CTL + (0x200 * port), 0x1);
}
/*
* devsoc_ppe_flow_port_map_tbl_port_num_set()
*/
static void devsoc_ppe_flow_port_map_tbl_port_num_set(int queue, int port)
{
devsoc_ppe_reg_write(DEVSOC_PPE_L0_FLOW_PORT_MAP_TBL +
queue * DEVSOC_PPE_L0_FLOW_PORT_MAP_TBL_INC, port);
devsoc_ppe_reg_write(DEVSOC_PPE_L1_FLOW_PORT_MAP_TBL +
port * DEVSOC_PPE_L1_FLOW_PORT_MAP_TBL_INC, port);
}
/*
* devsoc_ppe_flow_map_tbl_set()
*/
static void devsoc_ppe_flow_map_tbl_set(int queue, int port)
{
uint32_t val = port | 0x401000; /* c_drr_wt = 1, e_drr_wt = 1 */
devsoc_ppe_reg_write(DEVSOC_PPE_L0_FLOW_MAP_TBL + queue * DEVSOC_PPE_L0_FLOW_MAP_TBL_INC,
val);
val = port | 0x100400; /* c_drr_wt = 1, e_drr_wt = 1 */
devsoc_ppe_reg_write(DEVSOC_PPE_L1_FLOW_MAP_TBL + port * DEVSOC_PPE_L1_FLOW_MAP_TBL_INC,
val);
}
/*
* devsoc_ppe_tdm_configuration
*/
static void devsoc_ppe_tdm_configuration(void)
{
devsoc_ppe_reg_write(0xc000, 0x20);
devsoc_ppe_reg_write(0xc010, 0x32);
devsoc_ppe_reg_write(0xc020, 0x21);
devsoc_ppe_reg_write(0xc030, 0x30);
devsoc_ppe_reg_write(0xc040, 0x22);
devsoc_ppe_reg_write(0xc050, 0x31);
devsoc_ppe_reg_write(0xb000, 0x80000006);
devsoc_ppe_reg_write(0x47a000, 0xfa10);
devsoc_ppe_reg_write(0x47a010, 0xfc21);
devsoc_ppe_reg_write(0x47a020, 0xf902);
devsoc_ppe_reg_write(0x400000, 0x3);
}
/*
* devsoc_ppe_queue_ac_enable
*/
static void devsoc_ppe_queue_ac_enable(void)
{
int i;
/* ucast queue */
for (i = 0; i < 256; i++) {
devsoc_ppe_reg_write(DEVSOC_PPE_UCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10), 0x32120001);
devsoc_ppe_reg_write(DEVSOC_PPE_UCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10) + 0x4, 0x0);
devsoc_ppe_reg_write(DEVSOC_PPE_UCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10) + 0x8, 0x0);
devsoc_ppe_reg_write(DEVSOC_PPE_UCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10) + 0xc, 0x48000);
}
/* mcast queue */
for (i = 0; i < 44; i++) {
devsoc_ppe_reg_write(DEVSOC_PPE_MCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10), 0x00fa0001);
devsoc_ppe_reg_write(DEVSOC_PPE_MCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10) + 0x4, 0x0);
devsoc_ppe_reg_write(DEVSOC_PPE_MCAST_QUEUE_AC_EN_BASE_ADDR
+ (i * 0x10) + 0x8, 0x1200);
}
}
/*
* devsoc_ppe_enable_port_counter
*/
static void devsoc_ppe_enable_port_counter(void)
{
int i;
uint32_t reg = 0;
for (i = 0; i < 7; i++) {
/* MRU_MTU_CTRL_TBL.rx_cnt_en, MRU_MTU_CTRL_TBL.tx_cnt_en */
devsoc_ppe_reg_read(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10), &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10), reg);
devsoc_ppe_reg_read(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10) + 0x4, &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10) + 0x4, reg | 0x284303);
devsoc_ppe_reg_read(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10) + 0x8, &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10) + 0x8, reg);
devsoc_ppe_reg_read(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10) + 0xc, &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR
+ (i * 0x10) + 0xc, reg);
/* MC_MTU_CTRL_TBL.tx_cnt_en */
devsoc_ppe_reg_read(DEVSOC_PPE_MC_MTU_CTRL_TBL_ADDR
+ (i * 0x4), &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_MC_MTU_CTRL_TBL_ADDR
+ (i * 0x4), reg | 0x10000);
/* PORT_EG_VLAN.tx_counting_en */
devsoc_ppe_reg_read(DEVSOC_PPE_PORT_EG_VLAN_TBL_ADDR
+ (i * 0x4), &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_PORT_EG_VLAN_TBL_ADDR
+ (i * 0x4), reg | 0x100);
/* TL_PORT_VP_TBL.rx_cnt_en */
devsoc_ppe_reg_read(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10), &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10), reg);
devsoc_ppe_reg_read(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10) + 0x4, &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10) + 0x4, reg);
devsoc_ppe_reg_read(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10) + 0x8, &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10) + 0x8, reg | 0x20000);
devsoc_ppe_reg_read(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10) + 0xc, &reg);
devsoc_ppe_reg_write(DEVSOC_PPE_TL_PORT_VP_TBL_ADDR
+ (i * 0x10) + 0xc, reg);
}
}
/*
* devsoc_ppe_c_sp_cfg_tbl_drr_id_set
*/
static void devsoc_ppe_c_sp_cfg_tbl_drr_id_set(int id)
{
devsoc_ppe_reg_write(DEVSOC_PPE_L0_C_SP_CFG_TBL + (id * 0x80), id * 2);
devsoc_ppe_reg_write(DEVSOC_PPE_L1_C_SP_CFG_TBL + (id * 0x80), id * 2);
}
/*
* devsoc_ppe_e_sp_cfg_tbl_drr_id_set
*/
static void devsoc_ppe_e_sp_cfg_tbl_drr_id_set(int id)
{
devsoc_ppe_reg_write(DEVSOC_PPE_L0_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1);
devsoc_ppe_reg_write(DEVSOC_PPE_L1_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1);
}
static void ppe_port_mux_set(int port_id, int port_type, int mode)
{
uint32_t mux_mac_type = 0;
union port_mux_ctrl_u port_mux_ctrl;
pr_debug("\nport id is: %d, port type is %d, mode is %d",
port_id, port_type, mode);
if (port_type == PORT_GMAC_TYPE)
mux_mac_type = DEVSOC_PORT_MUX_MAC_TYPE;
else if (port_type == PORT_XGMAC_TYPE)
mux_mac_type = DEVSOC_PORT_MUX_XMAC_TYPE;
else
printf("\nAttention!!!..Port type configured wrongly..port_id = %d, mode = %d, port_type = %d",
port_id, mode, port_type);
port_mux_ctrl.val = 0;
devsoc_ppe_reg_read(DEVSOC_PORT_MUX_CTRL, &(port_mux_ctrl.val));
pr_debug("\nBEFORE UPDATE: Port MUX CTRL value is %u", port_mux_ctrl.val);
switch (port_id) {
case PORT1:
port_mux_ctrl.bf.port1_mac_sel = mux_mac_type;
port_mux_ctrl.bf.port1_pcs_sel = 0;
break;
case PORT2:
port_mux_ctrl.bf.port2_mac_sel = mux_mac_type;
port_mux_ctrl.bf.port2_pcs_sel = 0;
break;
default:
break;
}
devsoc_ppe_reg_write(DEVSOC_PORT_MUX_CTRL, port_mux_ctrl.val);
pr_debug("\nAFTER UPDATE: Port MUX CTRL value is %u", port_mux_ctrl.val);
}
void ppe_port_mux_mac_type_set(int port_id, int mode)
{
uint32_t port_type;
switch(mode)
{
case EPORT_WRAPPER_PSGMII:
case EPORT_WRAPPER_SGMII0_RGMII4:
case EPORT_WRAPPER_SGMII_PLUS:
case EPORT_WRAPPER_SGMII_FIBER:
port_type = PORT_GMAC_TYPE;
break;
case EPORT_WRAPPER_USXGMII:
case EPORT_WRAPPER_10GBASE_R:
port_type = PORT_XGMAC_TYPE;
break;
default:
printf("\nError during port_type set: mode is %d, port_id is: %d",
mode, port_id);
return;
}
ppe_port_mux_set(port_id, port_type, mode);
}
void devsoc_ppe_interface_mode_init(void)
{
uint32_t mode0, mode1;
int node;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node < 0) {
printf("\nError: ess-switch not specified in dts");
return;
}
mode0 = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode0", -1);
if (mode0 < 0) {
printf("\nError: switch_mac_mode0 not specified in dts");
return;
}
mode1 = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode1", -1);
if (mode1 < 0) {
printf("\nError: switch_mac_mode1 not specified in dts");
return;
}
#ifndef CONFIG_DEVSOC_RUMI
ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE0, mode0);
ppe_uniphy_mode_set(PPE_UNIPHY_INSTANCE1, mode1);
#endif
/*
* Port1 and Port2 can be used as GMAC or XGMAC.
*/
ppe_port_mux_mac_type_set(PORT1, mode0);
ppe_port_mux_mac_type_set(PORT2, mode0);
}
/*
* devsoc_ppe_provision_init()
*/
void devsoc_ppe_provision_init(void)
{
int i;
uint32_t queue;
/* tdm/sched configuration */
devsoc_ppe_tdm_configuration();
#ifdef CONFIG_DEVSOC_BRIDGED_MODE
/* Add CPU port 0 to VSI 2 */
devsoc_ppe_vp_port_tbl_set(0, 2);
/* Add port 1 - 4 to VSI 2 */
devsoc_ppe_vp_port_tbl_set(1, 2);
devsoc_ppe_vp_port_tbl_set(2, 2);
devsoc_ppe_vp_port_tbl_set(3, 2);
devsoc_ppe_vp_port_tbl_set(4, 2);
devsoc_ppe_vp_port_tbl_set(5, 2);
devsoc_ppe_vp_port_tbl_set(6, 2);
#else
devsoc_ppe_vp_port_tbl_set(1, 2);
devsoc_ppe_vp_port_tbl_set(2, 3);
devsoc_ppe_vp_port_tbl_set(3, 4);
devsoc_ppe_vp_port_tbl_set(4, 5);
devsoc_ppe_vp_port_tbl_set(5, 6);
devsoc_ppe_vp_port_tbl_set(6, 7);
#endif
/* Unicast priority map */
devsoc_ppe_reg_write(DEVSOC_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);
devsoc_ppe_ucast_queue_map_tbl_queue_id_set(queue, i);
devsoc_ppe_flow_port_map_tbl_port_num_set(queue, i);
devsoc_ppe_flow_map_tbl_set(queue, i);
devsoc_ppe_c_sp_cfg_tbl_drr_id_set(i);
devsoc_ppe_e_sp_cfg_tbl_drr_id_set(i);
}
/* Port0 multicast queue */
devsoc_ppe_reg_write(0x409000, 0x00000000);
devsoc_ppe_reg_write(0x403000, 0x00401000);
/* Port1 - 7 multicast queue */
for (i = 1; i < 8; i++) {
devsoc_ppe_reg_write(0x409100 + ((i - 1) * 0x40), i);
devsoc_ppe_reg_write(0x403100 + ((i - 1) * 0x40), 0x401000 | i);
}
/* ac enable for queues - disable queue tail drop */
devsoc_ppe_queue_ac_enable();
/* enable queue counter */
devsoc_ppe_reg_write(0x020044,0x4);
/* assign the ac group 0 with buffer number */
devsoc_ppe_reg_write(0x84c000, 0x0);
devsoc_ppe_reg_write(0x84c004, 0x7D00);
devsoc_ppe_reg_write(0x84c008, 0x0);
devsoc_ppe_reg_write(0x84c00c, 0x0);
/* enable physical/virtual port TX/RX counters for all ports (0-6) */
devsoc_ppe_enable_port_counter();
/*
* Port0 - TX_EN is set by default, Port1 - LRN_EN is set
* Port0 -> CPU Port
* Port1-6 -> Ethernet Ports
* Port7 -> EIP197
*/
for (i = 0; i < 8; i++) {
if (i == 0)
devsoc_ppe_reg_write(DEVSOC_PPE_PORT_BRIDGE_CTRL_OFFSET + (i * 4),
DEVSOC_PPE_PORT_BRIDGE_CTRL_PROMISC_EN |
DEVSOC_PPE_PORT_BRIDGE_CTRL_TXMAC_EN |
DEVSOC_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP |
DEVSOC_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN |
DEVSOC_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN);
else if (i == 7)
devsoc_ppe_reg_write(DEVSOC_PPE_PORT_BRIDGE_CTRL_OFFSET + (i * 4),
DEVSOC_PPE_PORT_BRIDGE_CTRL_PROMISC_EN |
DEVSOC_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP |
DEVSOC_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN |
DEVSOC_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN);
else
devsoc_ppe_reg_write(DEVSOC_PPE_PORT_BRIDGE_CTRL_OFFSET + (i * 4),
DEVSOC_PPE_PORT_BRIDGE_CTRL_PROMISC_EN |
DEVSOC_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP);
}
/* Global learning */
devsoc_ppe_reg_write(0x060038, 0xc0);
#ifdef CONFIG_DEVSOC_BRIDGED_MODE
devsoc_vsi_setup(2, 0x7f);
#else
devsoc_vsi_setup(2, 0x03);
devsoc_vsi_setup(3, 0x05);
devsoc_vsi_setup(4, 0x09);
devsoc_vsi_setup(5, 0x11);
devsoc_vsi_setup(6, 0x21);
devsoc_vsi_setup(7, 0x41);
#endif
/* Port 0-7 STP */
for (i = 0; i < 8; i++)
devsoc_ppe_reg_write(DEVSOC_PPE_STP_BASE + (0x4 * i), 0x3);
devsoc_ppe_interface_mode_init();
/* Port 1-2 disable */
for (i = 0; i < 2; i++) {
devsoc_gmac_port_disable(i);
ppe_port_bridge_txmac_set(i + 1, 1);
}
/* Allowing DHCP packets */
devsoc_ppe_acl_set(0, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 67, 0xffff, 0, 0);
devsoc_ppe_acl_set(1, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 68, 0xffff, 0, 0);
/* Dropping all the UDP packets */
devsoc_ppe_acl_set(2, ADPT_ACL_HPPE_IPV4_DIP_RULE, UDP_PKT, 0, 0, 0, 1);
}

View file

@ -0,0 +1,266 @@
/*
**************************************************************************
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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 <common.h>
#include <net.h>
#include <asm-generic/errno.h>
#include <asm/io.h>
#include <malloc.h>
#include <phy.h>
#include <net.h>
#include <miiphy.h>
#define DEVSOC_PPE_BASE_ADDR 0x3a000000
#define PORT1 1
#define PORT2 2
#define DEVSOC_PORT5_MUX_PCS_UNIPHY0 0x0
#define DEVSOC_PORT5_MUX_PCS_UNIPHY1 0x1
#define PORT_GMAC_TYPE 1
#define PORT_XGMAC_TYPE 2
#define DEVSOC_PORT_MUX_MAC_TYPE 0
#define DEVSOC_PORT_MUX_XMAC_TYPE 1
struct port_mux_ctrl {
uint32_t port1_pcs_sel:1;
uint32_t port2_pcs_sel:1;
uint32_t _reserved0:6;
uint32_t port1_mac_sel:1;
uint32_t port2_mac_sel:1;
uint32_t _reserved1:22;
};
union port_mux_ctrl_u {
uint32_t val;
struct port_mux_ctrl bf;
};
enum {
TCP_PKT,
UDP_PKT,
};
#define ADPT_ACL_HPPE_IPV4_DIP_RULE 4
#define ADPT_ACL_HPPE_MAC_SA_RULE 1
#define ADPT_ACL_HPPE_MAC_DA_RULE 0
#define MAX_RULE 512
struct ipo_rule_reg {
uint32_t rule_field_0:32;
uint32_t rule_field_1:20;
uint32_t fake_mac_header:1;
uint32_t range_en:1;
uint32_t inverse_en:1;
uint32_t rule_type:5;
uint32_t src_type:3;
uint32_t src_0:1;
uint32_t src_1:7;
uint32_t pri:9;
uint32_t res_chain:1;
uint32_t post_routing_en:1;
uint32_t _reserved0:14;
};
union ipo_rule_reg_u {
uint32_t val[3];
struct ipo_rule_reg bf;
};
struct ipo_mask_reg {
uint32_t maskfield_0:32;
uint32_t maskfield_1:21;
uint32_t _reserved0:11;
};
union ipo_mask_reg_u {
uint32_t val[2];
struct ipo_mask_reg bf;
};
struct ipo_action {
uint32_t dest_info_change_en:1;
uint32_t fwd_cmd:2;
uint32_t _reserved0:15;
uint32_t bypass_bitmap_0:14;
uint32_t bypass_bitmap_1:18;
uint32_t _reserved1:14;
uint32_t _reserved2:32;
uint32_t _reserved3:32;
uint32_t _reserved4:32;
};
union ipo_action_u {
uint32_t val[5];
struct ipo_action bf;
};
#define DEVSOC_PORT_MUX_CTRL 0x10
#define DEVSOC_PORT_MUX_CTRL_NUM 1
#define DEVSOC_PORT_MUX_CTRL_INC 0x4
#define DEVSOC_PORT_MUX_CTRL_DEFAULT 0x0
#define PORT_PHY_STATUS_ADDRESS 0x44
#define PORT_PHY_STATUS_PORT5_1_OFFSET 8
#define PORT_PHY_STATUS_PORT6_OFFSET 16
#define DEVSOC_PPE_IPE_L3_BASE_ADDR 0x200000
#define DEVSOC_PPE_L3_VP_PORT_TBL_ADDR (DEVSOC_PPE_IPE_L3_BASE_ADDR + 0x4000)
#define DEVSOC_PPE_L3_VP_PORT_TBL_INC 0x10
#define DEVSOC_PPE_TL_PORT_VP_TBL_ADDR 0x302000
#define DEVSOC_PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000
#define DEVSOC_PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00
#define DEVSOC_PPE_PORT_EG_VLAN_TBL_ADDR 0x20020
#define DEVSOC_PPE_UCAST_QUEUE_AC_EN_BASE_ADDR 0x848000
#define DEVSOC_PPE_MCAST_QUEUE_AC_EN_BASE_ADDR 0x84a000
#define DEVSOC_PPE_QUEUE_MANAGER_BASE_ADDR 0x800000
#define DEVSOC_PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x10000
#define DEVSOC_PPE_UCAST_QUEUE_MAP_TBL_INC 0x10
#define DEVSOC_PPE_QM_UQM_TBL (DEVSOC_PPE_QUEUE_MANAGER_BASE_ADDR +\
DEVSOC_PPE_UCAST_QUEUE_MAP_TBL_ADDR)
#define DEVSOC_PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x42000
#define DEVSOC_PPE_QM_UPM_TBL (DEVSOC_PPE_QUEUE_MANAGER_BASE_ADDR +\
DEVSOC_PPE_UCAST_PRIORITY_MAP_TBL_ADDR)
#define DEVSOC_PPE_STP_BASE 0x060100
#define DEVSOC_PPE_MAC_ENABLE 0x001000
#define DEVSOC_PPE_MAC_SPEED 0x001004
#define DEVSOC_PPE_MAC_MIB_CTL 0x001034
#define DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR 0x400000
#define DEVSOC_PPE_TM_SHP_CFG_L0_OFFSET 0x00000030
#define DEVSOC_PPE_TM_SHP_CFG_L1_OFFSET 0x00000034
#define DEVSOC_PPE_TM_SHP_CFG_L0 DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_TM_SHP_CFG_L0_OFFSET
#define DEVSOC_PPE_TM_SHP_CFG_L1 DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_TM_SHP_CFG_L1_OFFSET
#define DEVSOC_PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x10000
#define DEVSOC_PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10
#define DEVSOC_PPE_L0_FLOW_PORT_MAP_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L0_FLOW_PORT_MAP_TBL_ADDR)
#define DEVSOC_PPE_L0_FLOW_MAP_TBL_ADDR 0x2000
#define DEVSOC_PPE_L0_FLOW_MAP_TBL_INC 0x10
#define DEVSOC_PPE_L0_FLOW_MAP_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L0_FLOW_MAP_TBL_ADDR)
#define DEVSOC_PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x46000
#define DEVSOC_PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10
#define DEVSOC_PPE_L1_FLOW_PORT_MAP_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L1_FLOW_PORT_MAP_TBL_ADDR)
#define DEVSOC_PPE_L1_FLOW_MAP_TBL_ADDR 0x40000
#define DEVSOC_PPE_L1_FLOW_MAP_TBL_INC 0x10
#define DEVSOC_PPE_L1_FLOW_MAP_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L1_FLOW_MAP_TBL_ADDR)
#define DEVSOC_PPE_L0_C_SP_CFG_TBL_ADDR 0x4000
#define DEVSOC_PPE_L0_C_SP_CFG_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L0_C_SP_CFG_TBL_ADDR)
#define DEVSOC_PPE_L1_C_SP_CFG_TBL_ADDR 0x42000
#define DEVSOC_PPE_L1_C_SP_CFG_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L1_C_SP_CFG_TBL_ADDR)
#define DEVSOC_PPE_L0_E_SP_CFG_TBL_ADDR 0x6000
#define DEVSOC_PPE_L0_E_SP_CFG_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L0_E_SP_CFG_TBL_ADDR)
#define DEVSOC_PPE_L1_E_SP_CFG_TBL_ADDR 0x44000
#define DEVSOC_PPE_L1_E_SP_CFG_TBL (DEVSOC_PPE_TRAFFIC_MANAGER_BASE_ADDR +\
DEVSOC_PPE_L1_E_SP_CFG_TBL_ADDR)
#define DEVSOC_PPE_FPGA_GPIO_BASE_ADDR 0x01008000
#define DEVSOC_PPE_MAC_PORT_MUX_OFFSET 0x10
#define DEVSOC_PPE_FPGA_GPIO_OFFSET 0xc000
#define DEVSOC_PPE_FPGA_SCHED_OFFSET 0x47a000
#define DEVSOC_PPE_TDM_CFG_DEPTH_OFFSET 0xb000
#define DEVSOC_PPE_TDM_SCHED_DEPTH_OFFSET 0x400000
#define DEVSOC_PPE_PORT_BRIDGE_CTRL_OFFSET 0x060300
#define DEVSOC_PPE_TDM_CFG_DEPTH_VAL 0x80000064
#define DEVSOC_PPE_MAC_PORT_MUX_OFFSET_VAL 0x15
#define DEVSOC_PPE_TDM_SCHED_DEPTH_VAL 0x32
#define DEVSOC_PPE_TDM_CFG_VALID 0x20
#define DEVSOC_PPE_TDM_CFG_DIR_INGRESS 0x0
#define DEVSOC_PPE_TDM_CFG_DIR_EGRESS 0x10
#define DEVSOC_PPE_PORT_EDMA 0x0
#define DEVSOC_PPE_PORT_QTI1 0x1
#define DEVSOC_PPE_PORT_QTI2 0x2
#define DEVSOC_PPE_PORT_QTI3 0x3
#define DEVSOC_PPE_PORT_QTI4 0x4
#define DEVSOC_PPE_PORT_XGMAC1 0x5
#define DEVSOC_PPE_PORT_XGMAC2 0x6
#define DEVSOC_PPE_PORT_CRYPTO1 0x7
#define DEVSOC_PPE_PORT_BRIDGE_CTRL_PROMISC_EN 0x20000
#define DEVSOC_PPE_PORT_BRIDGE_CTRL_TXMAC_EN 0x10000
#define DEVSOC_PPE_PORT_BRIDGE_CTRL_PORT_ISOLATION_BMP 0x7f00
#define DEVSOC_PPE_PORT_BRIDGE_CTRL_STATION_LRN_EN 0x8
#define DEVSOC_PPE_PORT_BRIDGE_CTRL_NEW_ADDR_LRN_EN 0x1
#define DEVSOC_PPE_PORT_EDMA_BITPOS 0x1
#define DEVSOC_PPE_PORT_QTI1_BITPOS (1 << DEVSOC_PPE_PORT_QTI1)
#define DEVSOC_PPE_PORT_QTI2_BITPOS (1 << DEVSOC_PPE_PORT_QTI2)
#define DEVSOC_PPE_PORT_QTI3_BITPOS (1 << DEVSOC_PPE_PORT_QTI3)
#define DEVSOC_PPE_PORT_QTI4_BITPOS (1 << DEVSOC_PPE_PORT_QTI4)
#define DEVSOC_PPE_PORT_XGMAC1_BITPOS (1 << DEVSOC_PPE_PORT_XGMAC1)
#define DEVSOC_PPE_PORT_XGMAC2_BITPOS (1 << DEVSOC_PPE_PORT_XGMAC2)
#define DEVSOC_PPE_PORT_CRYPTO1_BITPOS (1 << DEVSOC_PPE_PORT_CRYPTO1)
#define PPE_SWITCH_NSS_SWITCH_XGMAC0 0x500000
#define NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION 0x4000
#define USS (1 << 31)
#define SS(i) (i << 29)
#define JD (1 << 16)
#define TE (1 << 0)
#define NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION 0x4000
#define MAC_RX_CONFIGURATION_ADDRESS 0x4
#define RE (1 << 0)
#define ACS (1 << 1)
#define CST (1 << 2)
#define MAC_PACKET_FILTER_INC 0x4000
#define MAC_PACKET_FILTER_ADDRESS 0x8
#define XGMAC_SPEED_SELECT_10000M 0
#define XGMAC_SPEED_SELECT_5000M 1
#define XGMAC_SPEED_SELECT_2500M 2
#define XGMAC_SPEED_SELECT_1000M 3
#define IPE_L2_BASE_ADDR 0x060000
#define PORT_BRIDGE_CTRL_ADDRESS 0x300
#define PORT_BRIDGE_CTRL_INC 0x4
#define TX_MAC_EN (1 << 16)
#define IPO_CSR_BASE_ADDR 0x0b0000
#define IPO_RULE_REG_ADDRESS 0x0
#define IPO_RULE_REG_INC 0x10
#define IPO_MASK_REG_ADDRESS 0x2000
#define IPO_MASK_REG_INC 0x10
#define IPO_ACTION_ADDRESS 0x8000
#define IPO_ACTION_INC 0x20

View file

@ -0,0 +1,557 @@
/*
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <asm/global_data.h>
#include <net.h>
#include <asm-generic/errno.h>
#include <asm/io.h>
#include <malloc.h>
#include <phy.h>
#include <net.h>
#include <miiphy.h>
#include <asm/arch-devsoc/edma_regs.h>
#include "devsoc_edma.h"
#include "devsoc_uniphy.h"
#include "devsoc_ppe.h"
#include <fdtdec.h>
#include "ipq_phy.h"
extern int is_uniphy_enabled(int uniphy_index);
DECLARE_GLOBAL_DATA_PTR;
extern int ipq_mdio_write(int mii_id,
int regnum, u16 value);
extern int ipq_mdio_read(int mii_id,
int regnum, ushort *data);
extern void devsoc_qca8075_phy_serdes_reset(u32 phy_id);
void csr1_write(int phy_id, int addr, int value)
{
int addr_h, addr_l, ahb_h, ahb_l, phy;
phy=phy_id<<(0x10);
addr_h=(addr&0xffffff)>>8;
addr_l=((addr&0xff)<<2)|(0x20<<(0xa));
ahb_l=(addr_l&0xffff)|(0x7A00000|phy);
ahb_h=(0x7A083FC|phy);
writel(addr_h,ahb_h);
writel(value,ahb_l);
}
int csr1_read(int phy_id, int addr )
{
int addr_h ,addr_l,ahb_h, ahb_l, phy;
phy=phy_id<<(0x10);
addr_h=(addr&0xffffff)>>8;
addr_l=((addr&0xff)<<2)|(0x20<<(0xa));
ahb_l=(addr_l&0xffff)|(0x7A00000|phy);
ahb_h=(0x7A083FC|phy);
writel(addr_h, ahb_h);
return readl(ahb_l);
}
static int ppe_uniphy_calibration(uint32_t uniphy_index)
{
int retries = 100, calibration_done = 0;
uint32_t reg_value = 0;
while(calibration_done != UNIPHY_CALIBRATION_DONE) {
mdelay(1);
if (retries-- == 0) {
printf("uniphy callibration time out!\n");
return -1;
}
reg_value = readl(PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_OFFSET_CALIB_4);
calibration_done = (reg_value >> 0x7) & 0x1;
}
return 0;
}
static void ppe_uniphy_reset(enum uniphy_reset_type rst_type, bool enable)
{
uint32_t mode, node;
uint32_t reg_val, reg_val1;
switch(rst_type) {
case UNIPHY0_SOFT_RESET:
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node < 0) {
printf("\nError: ess-switch not specified in dts");
return;
}
mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode1", -1);
if (mode < 0) {
printf("\nError: switch_mac_mode1 not specified in dts");
return;
}
reg_val = readl(GCC_UNIPHY0_MISC);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
if (mode == EPORT_WRAPPER_MAX) {
if (enable) {
reg_val |= 0x1;
reg_val1 |= 0xffc000;
} else {
reg_val &= ~0x1;
reg_val1 &= ~0xffc000;
}
} else {
if (enable) {
reg_val |= 0x1;
reg_val1 |= 0xff0000;
} else {
reg_val &= ~0x1;
reg_val1 &= ~0xff0000;
}
}
writel(reg_val, GCC_UNIPHY0_MISC);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
break;
case UNIPHY0_XPCS_RESET:
reg_val = readl(GCC_UNIPHY0_MISC);
if (enable)
reg_val |= 0x4;
else
reg_val &= ~0x4;
writel(reg_val, GCC_UNIPHY0_MISC);
break;
case UNIPHY1_SOFT_RESET:
reg_val = readl(GCC_UNIPHY0_MISC + GCC_UNIPHY_REG_INC);
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
if (enable) {
reg_val |= 0x1;
reg_val1 |= 0xC000;
} else {
reg_val &= ~0x1;
reg_val1 &= ~0xC000;
}
writel(reg_val, GCC_UNIPHY0_MISC + GCC_UNIPHY_REG_INC);
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
break;
case UNIPHY1_XPCS_RESET:
reg_val = readl(GCC_UNIPHY0_MISC + GCC_UNIPHY_REG_INC);
if (enable)
reg_val |= 0x4;
else
reg_val &= ~0x4;
writel(reg_val, GCC_UNIPHY0_MISC + GCC_UNIPHY_REG_INC);
break;
case UNIPHY2_SOFT_RESET:
reg_val = readl(GCC_UNIPHY0_MISC + (2 * GCC_UNIPHY_REG_INC));
reg_val1 = readl(NSS_CC_UNIPHY_MISC_RESET);
if (enable) {
reg_val |= 0x1;
reg_val1 |= 0x3000;
} else {
reg_val &= ~0x1;
reg_val1 &= ~0x3000;
}
writel(reg_val, GCC_UNIPHY0_MISC + (2 * GCC_UNIPHY_REG_INC));
writel(reg_val1, NSS_CC_UNIPHY_MISC_RESET);
break;
case UNIPHY2_XPCS_RESET:
reg_val = readl(GCC_UNIPHY0_MISC + (2 * GCC_UNIPHY_REG_INC));
if (enable)
reg_val |= 0x4;
else
reg_val &= ~0x4;
writel(reg_val, GCC_UNIPHY0_MISC + (2 * GCC_UNIPHY_REG_INC));
break;
default:
break;
}
}
static void ppe_uniphy_psgmii_mode_set(uint32_t uniphy_index)
{
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, true);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, true);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, true);
mdelay(100);
writel(0x220, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
if (uniphy_index == 0) {
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, false);
} else if (uniphy_index == 1) {
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, false);
} else {
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, false);
}
mdelay(100);
ppe_uniphy_calibration(uniphy_index);
#ifdef CONFIG_DEVSOC_QCA8075_PHY
devsoc_qca8075_phy_serdes_reset(0x10);
#endif
}
static void ppe_uniphy_qsgmii_mode_set(uint32_t uniphy_index)
{
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, true);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, true);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, true);
mdelay(100);
writel(0x120, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
if (uniphy_index == 0) {
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, false);
} else if (uniphy_index == 1) {
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, false);
} else {
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, false);
}
mdelay(100);
}
static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
{
writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET);
mdelay(500);
writel(UNIPHY_PLL_RESET_REG_DEFAULT_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET);
mdelay(500);
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, true);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, true);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, true);
mdelay(100);
if (uniphy_index == 1) {
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + (PORT5 - 1) * 0x8);
writel(0x0, NSS_CC_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
writel(0x0, NSS_CC_PORT1_RX_CBCR + 0x4 + (PORT5 - 1) * 0x8);
} else if (uniphy_index == 2) {
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + (PORT6 - 1) * 0x8);
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + (PORT6 - 1) * 8);
writel(0x0, NSS_CC_PORT1_RX_CBCR + (PORT6 - 1) * 0x8);
writel(0x0, NSS_CC_PORT1_RX_CBCR + 0x4 + (PORT6 - 1) * 0x8);
}
switch (mode) {
case EPORT_WRAPPER_SGMII_FIBER:
writel(0x400, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
break;
case EPORT_WRAPPER_SGMII0_RGMII4:
case EPORT_WRAPPER_SGMII1_RGMII4:
case EPORT_WRAPPER_SGMII4_RGMII4:
writel(0x420, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
break;
case EPORT_WRAPPER_SGMII_PLUS:
writel(0x820, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
break;
default:
printf("SGMII Config. wrongly");
break;
}
if (uniphy_index == 0) {
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, false);
} else if (uniphy_index == 1) {
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, false);
} else {
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, false);
}
mdelay(100);
if (uniphy_index == 1) {
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + (PORT5 - 1) * 0x8);
writel(0x1, NSS_CC_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
writel(0x1, NSS_CC_PORT1_RX_CBCR + 0x4 + (PORT5 - 1) * 0x8);
} else if (uniphy_index == 2) {
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + (PORT6 - 1) * 0x8);
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + (PORT6 - 1) * 8);
writel(0x1, NSS_CC_PORT1_RX_CBCR + (PORT6 - 1) * 0x8);
writel(0x1, NSS_CC_PORT1_RX_CBCR + 0x4 + (PORT6 - 1) * 0x8);
}
ppe_uniphy_calibration(uniphy_index);
}
static int ppe_uniphy_10g_r_linkup(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
uint32_t retries = 100, linkup = 0;
while (linkup != UNIPHY_10GR_LINKUP) {
mdelay(1);
if (retries-- == 0)
return -1;
reg_value = csr1_read(uniphy_index, SR_XS_PCS_KR_STS1_ADDRESS);
linkup = (reg_value >> 12) & UNIPHY_10GR_LINKUP;
}
mdelay(10);
return 0;
}
static void ppe_uniphy_10g_r_mode_set(uint32_t uniphy_index)
{
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, true);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, true);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, true);
writel(0x1021, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
writel(0x1C0, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ UNIPHY_INSTANCE_LINK_DETECT);
if (uniphy_index == 0) {
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, false);
} else if (uniphy_index == 1) {
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, false);
} else {
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, false);
}
mdelay(100);
ppe_uniphy_calibration(uniphy_index);
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, false);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, false);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, false);
}
static void ppe_uniphy_usxgmii_mode_set(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
writel(UNIPHY_MISC2_REG_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET);
mdelay(500);
writel(UNIPHY_PLL_RESET_REG_DEFAULT_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET);
mdelay(500);
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, true);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, true);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, true);
mdelay(100);
writel(0x1021, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
if (uniphy_index == 0) {
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY0_SOFT_RESET, false);
} else if (uniphy_index == 1) {
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY1_SOFT_RESET, false);
} else {
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, true);
mdelay(100);
ppe_uniphy_reset(UNIPHY2_SOFT_RESET, false);
}
mdelay(100);
ppe_uniphy_calibration(uniphy_index);
if (uniphy_index == 0)
ppe_uniphy_reset(UNIPHY0_XPCS_RESET, false);
else if (uniphy_index == 1)
ppe_uniphy_reset(UNIPHY1_XPCS_RESET, false);
else
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, false);
mdelay(100);
ppe_uniphy_10g_r_linkup(uniphy_index);
reg_value = csr1_read(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS);
reg_value |= USXG_EN;
csr1_write(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS, reg_value);
reg_value = csr1_read(uniphy_index, VR_MII_AN_CTRL_ADDRESS);
reg_value |= MII_AN_INTR_EN;
reg_value |= MII_CTRL;
csr1_write(uniphy_index, VR_MII_AN_CTRL_ADDRESS, reg_value);
reg_value = csr1_read(uniphy_index, SR_MII_CTRL_ADDRESS);
reg_value |= AN_ENABLE;
reg_value &= ~SS5;
reg_value |= SS6 | SS13 | DUPLEX_MODE;
csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value);
}
void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode)
{
if (!is_uniphy_enabled(uniphy_index)) {
printf("Uniphy %u is disabled\n", uniphy_index);
return;
}
switch(mode) {
case EPORT_WRAPPER_PSGMII:
ppe_uniphy_psgmii_mode_set(uniphy_index);
break;
case EPORT_WRAPPER_QSGMII:
ppe_uniphy_qsgmii_mode_set(uniphy_index);
break;
case EPORT_WRAPPER_SGMII0_RGMII4:
case EPORT_WRAPPER_SGMII1_RGMII4:
case EPORT_WRAPPER_SGMII4_RGMII4:
case EPORT_WRAPPER_SGMII_PLUS:
case EPORT_WRAPPER_SGMII_FIBER:
ppe_uniphy_sgmii_mode_set(uniphy_index, mode);
break;
case EPORT_WRAPPER_USXGMII:
ppe_uniphy_usxgmii_mode_set(uniphy_index);
break;
case EPORT_WRAPPER_10GBASE_R:
ppe_uniphy_10g_r_mode_set(uniphy_index);
break;
default:
break;
}
}
void ppe_uniphy_usxgmii_autoneg_completed(uint32_t uniphy_index)
{
uint32_t autoneg_complete = 0, retries = 100;
uint32_t reg_value = 0;
while (autoneg_complete != 0x1) {
mdelay(1);
if (retries-- == 0)
{
return;
}
reg_value = csr1_read(uniphy_index, VR_MII_AN_INTR_STS);
autoneg_complete = reg_value & 0x1;
}
reg_value &= ~CL37_ANCMPLT_INTR;
csr1_write(uniphy_index, VR_MII_AN_INTR_STS, reg_value);
}
void ppe_uniphy_usxgmii_speed_set(uint32_t uniphy_index, int speed)
{
uint32_t reg_value = 0;
reg_value = csr1_read(uniphy_index, SR_MII_CTRL_ADDRESS);
reg_value |= DUPLEX_MODE;
switch(speed) {
case 0:
reg_value &=~SS5;
reg_value &=~SS6;
reg_value &=~SS13;
break;
case 1:
reg_value &=~SS5;
reg_value &=~SS6;
reg_value |=SS13;
break;
case 2:
reg_value &=~SS5;
reg_value |=SS6;
reg_value &=~SS13;
break;
case 3:
reg_value &=~SS5;
reg_value |=SS6;
reg_value |=SS13;
break;
case 4:
reg_value |=SS5;
reg_value &=~SS6;
reg_value &=~SS13;
break;
case 5:
reg_value |=SS5;
reg_value &=~SS6;
reg_value |=SS13;
break;
}
csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value);
}
void ppe_uniphy_usxgmii_duplex_set(uint32_t uniphy_index, int duplex)
{
uint32_t reg_value = 0;
reg_value = csr1_read(uniphy_index, SR_MII_CTRL_ADDRESS);
if (duplex & 0x1)
reg_value |= DUPLEX_MODE;
else
reg_value &= ~DUPLEX_MODE;
csr1_write(uniphy_index, SR_MII_CTRL_ADDRESS, reg_value);
}
void ppe_uniphy_usxgmii_port_reset(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
reg_value = csr1_read(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS);
reg_value |= USRA_RST;
csr1_write(uniphy_index, VR_XS_PCS_DIG_CTRL1_ADDRESS, reg_value);
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define PPE_UNIPHY_INSTANCE0 0
#define PPE_UNIPHY_INSTANCE1 1
#define GCC_UNIPHY_REG_INC 0x10
#define PPE_UNIPHY_OFFSET_CALIB_4 0x1E0
#define UNIPHY_CALIBRATION_DONE 0x1
#define PPE_UNIPHY_BASE 0X07A00000
#define PPE_UNIPHY_REG_INC 0x10000
#define PPE_UNIPHY_MODE_CONTROL 0x46C
#define UNIPHY_XPCS_MODE (1 << 12)
#define UNIPHY_SG_PLUS_MODE (1 << 11)
#define UNIPHY_SG_MODE (1 << 10)
#define UNIPHY_CH0_PSGMII_QSGMII (1 << 9)
#define UNIPHY_CH0_QSGMII_SGMII (1 << 8)
#define UNIPHY_CH4_CH1_0_SGMII (1 << 2)
#define UNIPHY_CH1_CH0_SGMII (1 << 1)
#define UNIPHY_CH0_ATHR_CSCO_MODE_25M (1 << 0)
#define UNIPHY_INSTANCE_LINK_DETECT 0x570
#define UNIPHY_MISC2_REG_OFFSET 0x218
#define UNIPHY_MISC2_REG_SGMII_MODE 0x30
#define UNIPHY_MISC2_REG_SGMII_PLUS_MODE 0x50
#define UNIPHY_MISC2_REG_VALUE 0x70
#define UNIPHY_PLL_RESET_REG_OFFSET 0x780
#define UNIPHY_PLL_RESET_REG_VALUE 0x02bf
#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff
#define SR_XS_PCS_KR_STS1_ADDRESS 0x30020
#define UNIPHY_10GR_LINKUP 0x1
#define VR_XS_PCS_DIG_CTRL1_ADDRESS 0x38000
#define USXG_EN (1 << 9)
#define USRA_RST (1 << 10)
#define VR_MII_AN_CTRL_ADDRESS 0x1f8001
#define MII_AN_INTR_EN (1 << 0)
#define MII_CTRL (1 << 8)
#define SR_MII_CTRL_ADDRESS 0x1f0000
#define AN_ENABLE (1 << 12)
#define SS5 (1 << 5)
#define SS6 (1 << 6)
#define SS13 (1 << 13)
#define DUPLEX_MODE (1 << 8)
#define VR_MII_AN_INTR_STS 0x1f8002
#define CL37_ANCMPLT_INTR (1 << 0)
enum uniphy_reset_type {
UNIPHY0_SOFT_RESET = 0,
UNIPHY0_XPCS_RESET,
UNIPHY1_SOFT_RESET,
UNIPHY1_XPCS_RESET,
UNIPHY2_SOFT_RESET,
UNIPHY2_XPCS_RESET,
UNIPHY_RST_MAX
};
void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode);
void ppe_uniphy_usxgmii_port_reset(uint32_t uniphy_index);
void ppe_uniphy_usxgmii_duplex_set(uint32_t uniphy_index, int duplex);
void ppe_uniphy_usxgmii_speed_set(uint32_t uniphy_index, int speed);
void ppe_uniphy_usxgmii_autoneg_completed(uint32_t uniphy_index);

View file

@ -20,6 +20,7 @@
#define PHY_MAX 6
#define IPQ9574_PHY_MAX 6
#define IPQ6018_PHY_MAX 5
#define DEVSOC_PHY_MAX 2
#define MDIO_CTRL_0_REG 0x00090040
#define MDIO_CTRL_0_DIV(x) (x << 0)
#define MDIO_CTRL_0_MODE (1 << 8)

View file

@ -21,11 +21,14 @@
#endif
#define CONFIG_DEVSOC
#define CONFIG_DEVSOC_RUMI
#undef CONFIG_QCA_DISABLE_SCM
#define CONFIG_SPI_FLASH_CYPRESS
#define CONFIG_SYS_NO_FLASH
#define CONFIG_IPQ_NO_RELOC
#define CONFIG_SYS_NONCACHED_MEMORY (1 << 20)
#define CONFIG_SYS_VSNPRINTF
/*
@ -191,6 +194,27 @@ extern loff_t board_env_size;
/* Mii command support */
#define CONFIG_CMD_MII
/*
* Ethernet Configs
*/
#define CONFIG_DEVSOC_EDMA
#ifdef CONFIG_DEVSOC_EDMA
#define CONFIG_DEVSOC_BRIDGED_MODE 1
#define CONFIG_NET_RETRY_COUNT 5
#define CONFIG_SYS_RX_ETH_BUFFER 128
#define CONFIG_TFTP_BLOCKSIZE 1280
#define CONFIG_CMD_PING
#define CONFIG_CMD_DHCP
#define CONFIG_MII
#define CONFIG_CMD_MII
#define CONFIG_IPADDR 192.168.10.10
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.10.1
#define CONFIG_CMD_TFTPPUT
#define CONFIG_IPQ_MDIO 1
#define CONFIG_IPQ_ETH_INIT_DEFER
#endif
/* L1 cache line size is 64 bytes, L2 cache line size is 128 bytes
* Cache flush and invalidation based on L1 cache, so the cache line
* size is configured to 64 */

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DT_BINDINGS_DEVSOC_ETH_H__
#define __DT_BINDINGS_DEVSOC_ETH_H__
/* ESS Switch Mac Modes */
#define PORT_WRAPPER_PSGMII 0
#define PORT_WRAPPER_PSGMII_RGMII5 1
#define PORT_WRAPPER_SGMII0_RGMII5 2
#define PORT_WRAPPER_SGMII1_RGMII5 3
#define PORT_WRAPPER_PSGMII_RMII0 4
#define PORT_WRAPPER_PSGMII_RMII1 5
#define PORT_WRAPPER_PSGMII_RMII0_RMII1 6
#define PORT_WRAPPER_PSGMII_RGMII4 7
#define PORT_WRAPPER_SGMII0_RGMII4 8
#define PORT_WRAPPER_SGMII1_RGMII4 9
#define PORT_WRAPPER_SGMII4_RGMII4 10
#define PORT_WRAPPER_QSGMII 11
#define PORT_WRAPPER_SGMII_PLUS 12
#define PORT_WRAPPER_USXGMII 13
#define PORT_WRAPPER_10GBASE_R 14
#define PORT_WRAPPER_SGMII_CHANNEL0 15
#define PORT_WRAPPER_SGMII_CHANNEL1 16
#define PORT_WRAPPER_SGMII_CHANNEL4 17
#define PORT_WRAPPER_RGMII 18
#define PORT_WRAPPER_PSGMII_FIBER 19
#define PORT_WRAPPER_SGMII_FIBER 20
#define PORT_WRAPPER_MAX 0xFF
/* ETH PHY Types */
#define MALIBU_PHY_TYPE 0x1
#define QCA8081_PHY_TYPE 0x2
#define AQ_PHY_TYPE 0x3
#define QCA8033_PHY_TYPE 0x4
#define SFP_PHY_TYPE 0x5
#endif