Merge "drivers: net: Add switch mode support for QCA8084"

This commit is contained in:
Linux Build Service Account 2022-06-16 11:09:51 -07:00 committed by Gerrit - the friendly Code Review server
commit 7c3d106ddf
8 changed files with 2134 additions and 19 deletions

View file

@ -38,8 +38,6 @@
#define AQUANTIA_CTRL_RESTART_AUTONEGOTIATION 0x0200
#define AQ_PHY_AUTO_STATUS_REG 0x70001
#define PORT_LINK_DOWN 0
#define PORT_LINK_UP 1
#define AQ_PHY_LINK_STATUS_REG 0x7c800
#define SPEED_5G 5

View file

@ -21,6 +21,9 @@
#define IPQ9574_PHY_MAX 6
#define IPQ6018_PHY_MAX 5
#define DEVSOC_PHY_MAX 2
#define QCA8084_MAX_PORTS 6
#define MDIO_CTRL_0_REG 0x00090040
#define MDIO_CTRL_0_DIV(x) (x << 0)
#define MDIO_CTRL_0_MODE (1 << 8)
@ -29,6 +32,8 @@
#define MDIO_CTRL_0_GPHY(x) (x << 13)
#define MDIO_CTRL_0_RES1(x) (x << 17)
#define PORT_LINK_DOWN 0
#define PORT_LINK_UP 1
#define GP_PULL_DOWN 1
#define GP_OE_EN (1 << 9)
#define GP_VM_EN (1 << 11)
@ -145,6 +150,8 @@ enum phy_mode {
typedef struct {
u32 phy_address;
u32 phy_type;
u32 forced_speed;
u32 forced_duplex;
}phy_info_t;
struct phy_ops {

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,12 @@
#ifndef _QCA8084_PHY_H_
#define _QCA8084_PHY_H_
#include <linux/compat.h>
#ifdef __cplusplus
extern "C" {
#endif
/*MII register*/
#define QCA8084_PHY_FIFO_CONTROL 0x19
@ -63,10 +69,95 @@
#define QCA8084_DEBUG_PORT_DATA 30
#define QCA8084_PHY_CONTROL 0
#define QCA8084_AUTONEG_ADVERT 4
#define QCA8084_LINK_PARTNER_ABILITY 5
#define QCA8084_1000BASET_CONTROL 9
#define QCA8084_1000BASET_STATUS 10
#define QCA8084_PHY_SPEC_STATUS 17
#define QCA8084_CTRL_AUTONEGOTIATION_ENABLE 0x1000
#define QCA8084_CTRL_SOFTWARE_RESET 0x8000
#define QCA8084_STATUS_LINK_PASS 0x0400
#define PHY_INVALID_DATA 0xffff
#define QCA8084_PHY_MMD7_AUTONEGOTIATION_CONTROL 0x20
#define QCA8084_PHY_MMD7_LP_2500M_ABILITY 0x21
/* Auto-Negotiation Advertisement register. offset:4 */
#define QCA8084_ADVERTISE_SELECTOR_FIELD 0x0001
/* 10T Half Duplex Capable */
#define QCA8084_ADVERTISE_10HALF 0x0020
/* 10T Full Duplex Capable */
#define QCA8084_ADVERTISE_10FULL 0x0040
/* 100TX Half Duplex Capable */
#define QCA8084_ADVERTISE_100HALF 0x0080
/* 100TX Full Duplex Capable */
#define QCA8084_ADVERTISE_100FULL 0x0100
/* 100T4 Capable */
#define QCA8084_ADVERTISE_100T4 0x0200
/* Pause operation desired */
#define QCA8084_ADVERTISE_PAUSE 0x0400
/* Asymmetric Pause Direction bit */
#define QCA8084_ADVERTISE_ASYM_PAUSE 0x0800
/* Remote Fault detected */
#define QCA8084_ADVERTISE_REMOTE_FAULT 0x2000
/* 1000TX Half Duplex Capable */
#define QCA8084_ADVERTISE_1000HALF 0x0100
/* 1000TX Full Duplex Capable */
#define QCA8084_ADVERTISE_1000FULL 0x0200
/* 2500TX Full Duplex Capable */
#define QCA8084_ADVERTISE_2500FULL 0x80
#define QCA8084_ADVERTISE_ALL \
(QCA8084_ADVERTISE_10HALF | QCA8084_ADVERTISE_10FULL | \
QCA8084_ADVERTISE_100HALF | QCA8084_ADVERTISE_100FULL | \
QCA8084_ADVERTISE_1000FULL)
#define QCA8084_ADVERTISE_MEGA_ALL \
(QCA8084_ADVERTISE_10HALF | QCA8084_ADVERTISE_10FULL | \
QCA8084_ADVERTISE_100HALF | QCA8084_ADVERTISE_100FULL | \
QCA8084_ADVERTISE_PAUSE | QCA8084_ADVERTISE_ASYM_PAUSE)
/* FDX =1, half duplex =0 */
#define QCA8084_CTRL_FULL_DUPLEX 0x0100
/* Restart auto negotiation */
#define QCA8084_CTRL_RESTART_AUTONEGOTIATION 0x0200
/* 1=Duplex 0=Half Duplex */
#define QCA8084_STATUS_FULL_DUPLEX 0x2000
#define QCA8084_PHY_RX_FLOWCTRL_STATUS 0x4
#define QCA8084_PHY_TX_FLOWCTRL_STATUS 0x8
/* Speed, bits 9:7 */
#define QCA8084_STATUS_SPEED_MASK 0x380
/* 000=10Mbs */
#define QCA8084_STATUS_SPEED_10MBS 0x0000
/* 001=100Mbs */
#define QCA8084_STATUS_SPEED_100MBS 0x80
/* 010=1000Mbs */
#define QCA8084_STATUS_SPEED_1000MBS 0x100
/* 100=2500Mbs */
#define QCA8084_STATUS_SPEED_2500MBS 0x200
#define QCA8084_MII_ADDR_C45 (1<<30)
#define QCA8084_REG_C45_ADDRESS(dev_type, reg_num) (QCA8084_MII_ADDR_C45 | \
((dev_type & 0x1f) << 16) | (reg_num & 0xffff))
@ -77,4 +168,520 @@ typedef enum {
}
qca8084_adc_edge_t;
//phy autoneg adv
#define FAL_PHY_ADV_10T_HD 0x01
#define FAL_PHY_ADV_10T_FD 0x02
#define FAL_PHY_ADV_100TX_HD 0x04
#define FAL_PHY_ADV_100TX_FD 0x08
//#define FAL_PHY_ADV_1000T_HD 0x100
#define FAL_PHY_ADV_1000T_FD 0x200
#define FAL_PHY_ADV_1000BX_HD 0x400
#define FAL_PHY_ADV_1000BX_FD 0x800
#define FAL_PHY_ADV_2500T_FD 0x1000
#define FAL_PHY_ADV_5000T_FD 0x2000
#define FAL_PHY_ADV_10000T_FD 0x4000
#define FAL_PHY_ADV_10G_R_FD 0x8000
#define FAL_DEFAULT_MAX_FRAME_SIZE 0x5ee
#define FAL_PHY_ADV_PAUSE 0x10
#define FAL_PHY_ADV_ASY_PAUSE 0x20
/** Bit manipulation macros */
#ifndef BITSM
#define BITSM(_s, _n) (((1UL << (_n)) - 1) << _s)
#endif
#define SW_BIT_MASK_U32(nr) (~(0xFFFFFFFF << (nr)))
#define SW_FIELD_MASK_U32(offset, len) \
((SW_BIT_MASK_U32(len) << (offset)))
#define SW_FIELD_MASK_NOT_U32(offset,len) \
(~(SW_BIT_MASK_U32(len) << (offset)))
#define SW_FIELD_2_REG(field_val, bit_offset) \
(field_val << (bit_offset) )
#define SW_REG_2_FIELD(reg_val, bit_offset, field_len) \
(((reg_val) >> (bit_offset)) & ((1 << (field_len)) - 1))
#define SW_FIELD_GET_BY_REG_U32(reg_value, field_value, bit_offset, field_len)\
do { \
(field_value) = \
(((reg_value) >> (bit_offset)) & SW_BIT_MASK_U32(field_len)); \
} while (0)
#define SW_REG_SET_BY_FIELD_U32(reg_value, field_value, bit_offset, field_len)\
do { \
(reg_value) = \
(((reg_value) & SW_FIELD_MASK_NOT_U32((bit_offset),(field_len))) \
| (((field_value) & SW_BIT_MASK_U32(field_len)) << (bit_offset)));\
} while (0)
#define SW_GET_FIELD_BY_REG(reg, field, field_value, reg_value) \
SW_FIELD_GET_BY_REG_U32(reg_value, field_value, reg##_##field##_BOFFSET, \
reg##_##field##_BLEN)
#define SW_SET_REG_BY_FIELD(reg, field, field_value, reg_value) \
SW_REG_SET_BY_FIELD_U32(reg_value, field_value, reg##_##field##_BOFFSET, \
reg##_##field##_BLEN)
#define QCA8084_REG_ENTRY_GET(reg, index, value) \
*((u32 *) value) = ipq_mii_read(reg##_OFFSET + ((u32)index) * reg##_E_OFFSET);
#define QCA8084_REG_ENTRY_SET(reg, index, value) \
ipq_mii_write(reg##_OFFSET + ((u32)index) * reg##_E_OFFSET, *((u32 *) value));
#define QCA8084_REG_FIELD_GET(reg, index, field, value) \
do { \
qca8084_reg_field_get(reg##_OFFSET + ((u32)index) * reg##_E_OFFSET,\
reg##_##field##_BOFFSET, \
reg##_##field##_BLEN, (u8*)value);\
} while (0);
#define QCA8084_REG_FIELD_SET(reg, index, field, value) \
do { \
qca8084_reg_field_set(reg##_OFFSET + ((u32)index) * reg##_E_OFFSET,\
reg##_##field##_BOFFSET, \
reg##_##field##_BLEN, (u8*)value);\
} while (0);
/* Chip information */
#define QCA_VER_QCA8084 0x17
#define CHIP_QCA8084 0x13
/* Port Status Register */
#define PORT_STATUS
#define PORT_STATUS_OFFSET 0x007c
#define PORT_STATUS_E_LENGTH 4
#define PORT_STATUS_E_OFFSET 0x0004
#define PORT_STATUS_NR_E 7
#define DUPLEX_MODE
#define PORT_STATUS_DUPLEX_MODE_BOFFSET 6
#define PORT_STATUS_DUPLEX_MODE_BLEN 1
#define PORT_STATUS_DUPLEX_MODE_FLAG HSL_RW
#define SPEED_MODE
#define PORT_STATUS_SPEED_MODE_BOFFSET 0
#define PORT_STATUS_SPEED_MODE_BLEN 2
#define PORT_STATUS_SPEED_MODE_FLAG HSL_RW
#define LINK_EN
#define PORT_STATUS_LINK_EN_BOFFSET 9
#define PORT_STATUS_LINK_EN_BLEN 1
#define PORT_STATUS_LINK_EN_FLAG HSL_RW
#define RXMAC_EN
#define PORT_STATUS_RXMAC_EN_BOFFSET 3
#define PORT_STATUS_RXMAC_EN_BLEN 1
#define PORT_STATUS_RXMAC_EN_FLAG HSL_RW
#define TXMAC_EN
#define PORT_STATUS_TXMAC_EN_BOFFSET 2
#define PORT_STATUS_TXMAC_EN_BLEN 1
#define PORT_STATUS_TXMAC_EN_FLAG HSL_RW
#define RX_FLOW_EN
#define PORT_STATUS_RX_FLOW_EN_BOFFSET 5
#define PORT_STATUS_RX_FLOW_EN_BLEN 1
#define PORT_STATUS_RX_FLOW_EN_FLAG HSL_RW
#define TX_FLOW_EN
#define PORT_STATUS_TX_FLOW_EN_BOFFSET 4
#define PORT_STATUS_TX_FLOW_EN_BLEN 1
#define PORT_STATUS_TX_FLOW_EN_FLAG HSL_RW
#define TX_HALF_FLOW_EN
#define PORT_STATUS_TX_HALF_FLOW_EN_BOFFSET 7
#define PORT_STATUS_TX_HALF_FLOW_EN_BLEN 1
#define PORT_STATUS_TX_HALF_FLOW_EN_FLAG HSL_RW
#define QCA8084_PORT_SPEED_10M 0
#define QCA8084_PORT_SPEED_100M 1
#define QCA8084_PORT_SPEED_1000M 2
#define QCA8084_PORT_SPEED_2500M QCA8084_PORT_SPEED_1000M
#define QCA8084_PORT_HALF_DUPLEX 0
#define QCA8084_PORT_FULL_DUPLEX 1
/* Header Ctl Register */
#define HEADER_CTL
#define HEADER_CTL_OFFSET 0x0098
#define HEADER_CTL_E_LENGTH 4
#define HEADER_CTL_E_OFFSET 0x0004
#define HEADER_CTL_NR_E 1
#define TYPE_LEN
#define HEADER_CTL_TYPE_LEN_BOFFSET 16
#define HEADER_CTL_TYPE_LEN_BLEN 1
#define HEADER_CTL_TYPE_LEN_FLAG HSL_RW
#define TYPE_VAL
#define HEADER_CTL_TYPE_VAL_BOFFSET 0
#define HEADER_CTL_TYPE_VAL_BLEN 16
#define HEADER_CTL_TYPE_VAL_FLAG HSL_RW
/* Port Header Ctl Register */
#define PORT_HDR_CTL
#define PORT_HDR_CTL_OFFSET 0x009c
#define PORT_HDR_CTL_E_LENGTH 4
#define PORT_HDR_CTL_E_OFFSET 0x0004
#define PORT_HDR_CTL_NR_E 7
#define RXHDR_MODE
#define PORT_HDR_CTL_RXHDR_MODE_BOFFSET 2
#define PORT_HDR_CTL_RXHDR_MODE_BLEN 2
#define PORT_HDR_CTL_RXHDR_MODE_FLAG HSL_RW
#define TXHDR_MODE
#define PORT_HDR_CTL_TXHDR_MODE_BOFFSET 0
#define PORT_HDR_CTL_TXHDR_MODE_BLEN 2
#define PORT_HDR_CTL_TXHDR_MODE_FLAG HSL_RW
#define QCA8084_HEADER_TYPE_VAL 0xaaaa
typedef enum {
FAL_NO_HEADER_EN = 0,
FAL_ONLY_MANAGE_FRAME_EN,
FAL_ALL_TYPE_FRAME_EN
} port_header_mode_t;
struct port_phy_status
{
u32 link_status;
fal_port_speed_t speed;
fal_port_duplex_t duplex;
bool tx_flowctrl;
bool rx_flowctrl;
};
/****************************************************************************
*
* 1) PinCtrl/TLMM Register Definition
*
****************************************************************************/
/* TLMM_GPIO_CFGn */
#define TLMM_GPIO_CFGN
#define TLMM_GPIO_CFGN_OFFSET 0xC400000
#define TLMM_GPIO_CFGN_E_LENGTH 4
#define TLMM_GPIO_CFGN_E_OFFSET 0x1000
#define TLMM_GPIO_CFGN_NR_E 80
#define GPIO_HIHYS_EN
#define TLMM_GPIO_CFGN_GPIO_HIHYS_EN_BOFFSET 10
#define TLMM_GPIO_CFGN_GPIO_HIHYS_EN_BLEN 1
#define TLMM_GPIO_CFGN_GPIO_HIHYS_EN_FLAG HSL_RW
#define GPIO_OEA
#define TLMM_GPIO_CFGN_GPIO_OEA_BOFFSET 9
#define TLMM_GPIO_CFGN_GPIO_OEA_BLEN 1
#define TLMM_GPIO_CFGN_GPIO_OEA_FLAG HSL_RW
#define DRV_STRENGTH
#define TLMM_GPIO_CFGN_DRV_STRENGTH_BOFFSET 6
#define TLMM_GPIO_CFGN_DRV_STRENGTH_BLEN 3
#define TLMM_GPIO_CFGN_DRV_STRENGTH_FLAG HSL_RW
enum QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH {
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_2_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_4_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_6_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_8_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_10_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_12_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_14_MA,
QCA8084_TLMM_GPIO_CFGN_DRV_STRENGTH_16_MA,
};
#define FUNC_SEL
#define TLMM_GPIO_CFGN_FUNC_SEL_BOFFSET 2
#define TLMM_GPIO_CFGN_FUNC_SEL_BLEN 4
#define TLMM_GPIO_CFGN_FUNC_SEL_FLAG HSL_RW
#define GPIO_PULL
#define TLMM_GPIO_CFGN_GPIO_PULL_BOFFSET 0
#define TLMM_GPIO_CFGN_GPIO_PULL_BLEN 2
#define TLMM_GPIO_CFGN_GPIO_PULL_FLAG HSL_RW
enum QCA8084_QCA8084_PIN_CONFIG_PARAM {
QCA8084_TLMM_GPIO_CFGN_GPIO_PULL_DISABLE, //Disables all pull
QCA8084_TLMM_GPIO_CFGN_GPIO_PULL_DOWN,
QCA8084_TLMM_GPIO_CFGN_GPIO_PULL_BUS_HOLD, //Weak Keepers
QCA8084_TLMM_GPIO_CFGN_GPIO_PULL_UP,
};
/* TLMM_GPIO_IN_OUTn */
#define TLMM_GPIO_IN_OUTN
#define TLMM_GPIO_IN_OUTN_OFFSET 0xC400004
#define TLMM_GPIO_IN_OUTN_E_LENGTH 4
#define TLMM_GPIO_IN_OUTN_E_OFFSET 0x1000
#define TLMM_GPIO_IN_OUTN_NR_E 80
#define GPIO_OUTE
#define TLMM_GPIO_IN_OUTN_GPIO_OUTE_BOFFSET 1
#define TLMM_GPIO_IN_OUTN_GPIO_OUTE_BLEN 1
#define TLMM_GPIO_IN_OUTN_GPIO_OUTE_FLAG HSL_RW
#define GPIO_IN
#define TLMM_GPIO_IN_OUTN_GPIO_IN_BOFFSET 0
#define TLMM_GPIO_IN_OUTN_GPIO_IN_BLEN 1
#define TLMM_GPIO_IN_OUTN_GPIO_IN_FLAG HSL_R
/* TLMM_CLK_GATE_EN */
#define TLMM_CLK_GATE_EN
#define TLMM_CLK_GATE_EN_OFFSET 0xC500000
#define TLMM_CLK_GATE_EN_E_LENGTH 4
#define TLMM_CLK_GATE_EN_E_OFFSET 0
#define TLMM_CLK_GATE_EN_NR_E 1
#define AHB_HCLK_EN
#define TLMM_CLK_GATE_EN_AHB_HCLK_EN_BOFFSET 2
#define TLMM_CLK_GATE_EN_AHB_HCLK_EN_BLEN 1
#define TLMM_CLK_GATE_EN_AHB_HCLK_EN_FLAG HSL_RW
#define SUMMARY_INTR_EN
#define TLMM_CLK_GATE_EN_SUMMARY_INTR_EN_BOFFSET 1
#define TLMM_CLK_GATE_EN_SUMMARY_INTR_EN_BLEN 1
#define TLMM_CLK_GATE_EN_SUMMARY_INTR_EN_FLAG HSL_RW
#define CRIF_READ_EN
#define TLMM_CLK_GATE_EN_CRIF_READ_EN_BOFFSET 0
#define TLMM_CLK_GATE_EN_CRIF_READ_EN_BLEN 1
#define TLMM_CLK_GATE_EN_CRIF_READ_EN_FLAG HSL_RW
/* TLMM_HW_REVISION_NUMBER */
#define TLMM_HW_REVISION_NUMBER
#define TLMM_HW_REVISION_NUMBER_OFFSET 0xC510010
#define TLMM_HW_REVISION_NUMBER_E_LENGTH 4
#define TLMM_HW_REVISION_NUMBER_E_OFFSET 0
#define TLMM_HW_REVISION_NUMBER_NR_E 1
#define VERSION_ID
#define TLMM_HW_REVISION_NUMBER_VERSION_ID_BOFFSET 28
#define TLMM_HW_REVISION_NUMBER_VERSION_ID_BLEN 4
#define TLMM_HW_REVISION_NUMBER_VERSION_ID_FLAG HSL_R
#define PARTNUM
#define TLMM_HW_REVISION_NUMBER_PARTNUM_BOFFSET 12
#define TLMM_HW_REVISION_NUMBER_PARTNUM_BLEN 16
#define TLMM_HW_REVISION_NUMBER_PARTNUM_FLAG HSL_R
#define MFG_ID
#define TLMM_HW_REVISION_NUMBER_MFG_ID_BOFFSET 1
#define TLMM_HW_REVISION_NUMBER_MFG_ID_BLEN 11
#define TLMM_HW_REVISION_NUMBER_MFG_ID_FLAG HSL_R
#define START_BIT
#define TLMM_HW_REVISION_NUMBER_START_BIT_BOFFSET 0
#define TLMM_HW_REVISION_NUMBER_START_BIT_BLEN 1
#define TLMM_HW_REVISION_NUMBER_START_BIT_FLAG HSL_R
/****************************************************************************
*
* 2) PINs Functions Selection GPIO_CFG[5:2] (FUNC_SEL)
*
****************************************************************************/
/*GPIO*/
#define QCA8084_PIN_FUNC_GPIO0 0
#define QCA8084_PIN_FUNC_GPIO1 0
#define QCA8084_PIN_FUNC_GPIO2 0
#define QCA8084_PIN_FUNC_GPIO3 0
#define QCA8084_PIN_FUNC_GPIO4 0
#define QCA8084_PIN_FUNC_GPIO5 0
#define QCA8084_PIN_FUNC_GPIO6 0
#define QCA8084_PIN_FUNC_GPIO7 0
#define QCA8084_PIN_FUNC_GPIO8 0
#define QCA8084_PIN_FUNC_GPIO9 0
#define QCA8084_PIN_FUNC_GPIO10 0
#define QCA8084_PIN_FUNC_GPIO11 0
#define QCA8084_PIN_FUNC_GPIO12 0
#define QCA8084_PIN_FUNC_GPIO13 0
#define QCA8084_PIN_FUNC_GPIO14 0
#define QCA8084_PIN_FUNC_GPIO15 0
#define QCA8084_PIN_FUNC_GPIO16 0
#define QCA8084_PIN_FUNC_GPIO17 0
#define QCA8084_PIN_FUNC_GPIO18 0
#define QCA8084_PIN_FUNC_GPIO19 0
#define QCA8084_PIN_FUNC_GPIO20 0
#define QCA8084_PIN_FUNC_GPIO21 0
/*MINIMUM CONCURRENCY SET FUNCTION*/
#define QCA8084_PIN_FUNC_INTN_WOL 1
#define QCA8084_PIN_FUNC_INTN 1
#define QCA8084_PIN_FUNC_P0_LED_0 1
#define QCA8084_PIN_FUNC_P1_LED_0 1
#define QCA8084_PIN_FUNC_P2_LED_0 1
#define QCA8084_PIN_FUNC_P3_LED_0 1
#define QCA8084_PIN_FUNC_PPS_IN 1
#define QCA8084_PIN_FUNC_TOD_IN 1
#define QCA8084_PIN_FUNC_RTC_REFCLK_IN 1
#define QCA8084_PIN_FUNC_P0_PPS_OUT 1
#define QCA8084_PIN_FUNC_P1_PPS_OUT 1
#define QCA8084_PIN_FUNC_P2_PPS_OUT 1
#define QCA8084_PIN_FUNC_P3_PPS_OUT 1
#define QCA8084_PIN_FUNC_P0_TOD_OUT 1
#define QCA8084_PIN_FUNC_P0_CLK125_TDI 1
#define QCA8084_PIN_FUNC_P0_SYNC_CLKO_PTP 1
#define QCA8084_PIN_FUNC_P0_LED_1 1
#define QCA8084_PIN_FUNC_P1_LED_1 1
#define QCA8084_PIN_FUNC_P2_LED_1 1
#define QCA8084_PIN_FUNC_P3_LED_1 1
#define QCA8084_PIN_FUNC_MDC_M 1
#define QCA8084_PIN_FUNC_MDO_M 1
/*ALT FUNCTION K*/
#define QCA8084_PIN_FUNC_EVENT_TRG_I 2
#define QCA8084_PIN_FUNC_P0_EVENT_TRG_O 2
#define QCA8084_PIN_FUNC_P1_EVENT_TRG_O 2
#define QCA8084_PIN_FUNC_P2_EVENT_TRG_O 2
#define QCA8084_PIN_FUNC_P3_EVENT_TRG_O 2
#define QCA8084_PIN_FUNC_P1_TOD_OUT 2
#define QCA8084_PIN_FUNC_P1_CLK125_TDI 2
#define QCA8084_PIN_FUNC_P1_SYNC_CLKO_PTP 2
#define QCA8084_PIN_FUNC_P0_INTN_WOL 2
#define QCA8084_PIN_FUNC_P1_INTN_WOL 2
#define QCA8084_PIN_FUNC_P2_INTN_WOL 2
#define QCA8084_PIN_FUNC_P3_INTN_WOL 2
/*ALT FUNCTION L*/
#define QCA8084_PIN_FUNC_P2_TOD_OUT 3
#define QCA8084_PIN_FUNC_P2_CLK125_TDI 3
#define QCA8084_PIN_FUNC_P2_SYNC_CLKO_PTP 3
/*ALT FUNCTION M*/
#define QCA8084_PIN_FUNC_P3_TOD_OUT 4
#define QCA8084_PIN_FUNC_P3_CLK125_TDI 4
#define QCA8084_PIN_FUNC_P3_SYNC_CLKO_PTP 4
/*ALT FUNCTION N*/
#define QCA8084_PIN_FUNC_P0_LED_2 3
#define QCA8084_PIN_FUNC_P1_LED_2 2
#define QCA8084_PIN_FUNC_P2_LED_2 2
#define QCA8084_PIN_FUNC_P3_LED_2 3
/*ALT FUNCTION O*/
/*ALT FUNCTION DEBUG BUS OUT*/
#define QCA8084_PIN_FUNC_DBG_OUT_CLK 2
#define QCA8084_PIN_FUNC_DBG_BUS_OUT0 2
#define QCA8084_PIN_FUNC_DBG_BUS_OUT1 2
#define QCA8084_PIN_FUNC_DBG_BUS_OUT12 2
#define QCA8084_PIN_FUNC_DBG_BUS_OUT13 2
#define QCA8084_PIN_FUNC_DBG_BUS_OUT2 3
#define QCA8084_PIN_FUNC_DBG_BUS_OUT3 4
#define QCA8084_PIN_FUNC_DBG_BUS_OUT4 3
#define QCA8084_PIN_FUNC_DBG_BUS_OUT5 3
#define QCA8084_PIN_FUNC_DBG_BUS_OUT6 3
#define QCA8084_PIN_FUNC_DBG_BUS_OUT7 5
#define QCA8084_PIN_FUNC_DBG_BUS_OUT8 5
#define QCA8084_PIN_FUNC_DBG_BUS_OUT9 5
#define QCA8084_PIN_FUNC_DBG_BUS_OUT10 3
#define QCA8084_PIN_FUNC_DBG_BUS_OUT11 3
#define QCA8084_PIN_FUNC_DBG_BUS_OUT14 2
#define QCA8084_PIN_FUNC_DBG_BUS_OUT15 2
/****************************************************************************
*
* 2) PINs Functions Selection GPIO_CFG[5:2] (FUNC_SEL)
*
****************************************************************************/
struct qca8084_pinctrl_setting_mux {
u32 pin;
u32 func;
};
struct qca8084_pinctrl_setting_configs {
u32 pin;
u32 num_configs;
u64 *configs;
};
enum qca8084_pin_config_param {
QCA8084_PIN_CONFIG_BIAS_BUS_HOLD,
QCA8084_PIN_CONFIG_BIAS_DISABLE,
QCA8084_PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
QCA8084_PIN_CONFIG_BIAS_PULL_DOWN,
QCA8084_PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
QCA8084_PIN_CONFIG_BIAS_PULL_UP,
QCA8084_PIN_CONFIG_DRIVE_OPEN_DRAIN,
QCA8084_PIN_CONFIG_DRIVE_OPEN_SOURCE,
QCA8084_PIN_CONFIG_DRIVE_PUSH_PULL,
QCA8084_PIN_CONFIG_DRIVE_STRENGTH,
QCA8084_PIN_CONFIG_DRIVE_STRENGTH_UA,
QCA8084_PIN_CONFIG_INPUT_DEBOUNCE,
QCA8084_PIN_CONFIG_INPUT_ENABLE,
QCA8084_PIN_CONFIG_INPUT_SCHMITT,
QCA8084_PIN_CONFIG_INPUT_SCHMITT_ENABLE,
QCA8084_PIN_CONFIG_LOW_POWER_MODE,
QCA8084_PIN_CONFIG_OUTPUT_ENABLE,
QCA8084_PIN_CONFIG_OUTPUT,
QCA8084_PIN_CONFIG_POWER_SOURCE,
QCA8084_PIN_CONFIG_SLEEP_HARDWARE_STATE,
QCA8084_PIN_CONFIG_SLEW_RATE,
QCA8084_PIN_CONFIG_SKEW_DELAY,
QCA8084_PIN_CONFIG_PERSIST_STATE,
QCA8084_PIN_CONFIG_END = 0x7F,
QCA8084_PIN_CONFIG_MAX = 0xFF,
};
enum qca8084_pinctrl_map_type {
QCA8084_PIN_MAP_TYPE_INVALID,
QCA8084_PIN_MAP_TYPE_DUMMY_STATE,
QCA8084_PIN_MAP_TYPE_MUX_GROUP,
QCA8084_PIN_MAP_TYPE_CONFIGS_PIN,
QCA8084_PIN_MAP_TYPE_CONFIGS_GROUP,
};
struct qca8084_pinctrl_setting {
enum qca8084_pinctrl_map_type type;
union {
struct qca8084_pinctrl_setting_mux mux;
struct qca8084_pinctrl_setting_configs configs;
} data;
};
#define QCA8084_PIN_SETTING_MUX(pin_id, function) \
{ \
.type = QCA8084_PIN_MAP_TYPE_MUX_GROUP, \
.data.mux = { \
.pin = pin_id, \
.func = function \
}, \
}
#define QCA8084_PIN_SETTING_CONFIG(pin_id, cfgs) \
{ \
.type = QCA8084_PIN_MAP_TYPE_CONFIGS_PIN, \
.data.configs = { \
.pin = pin_id, \
.configs = cfgs, \
.num_configs = ARRAY_SIZE(cfgs) \
}, \
}
int qca8084_gpio_set_bit( u32 pin, u32 value);
int qca8084_gpio_get_bit( u32 pin, u32 *data);
int qca8084_gpio_pin_mux_set( u32 pin, u32 func);
int qca8084_gpio_pin_cfg_set_bias( u32 pin, u32 bias);
int qca8084_gpio_pin_cfg_get_bias( u32 pin, u32 *bias);
int qca8084_gpio_pin_cfg_set_drvs( u32 pin, u32 drvs);
int qca8084_gpio_pin_cfg_get_drvs( u32 pin, u32 *drvs);
int qca8084_gpio_pin_cfg_set_oe( u32 pin, bool oe);
int qca8084_gpio_pin_cfg_get_oe( u32 pin, bool *oe);
int ipq_qca8084_pinctrl_init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _QCA8084_PHY_H_ */

View file

@ -1073,14 +1073,17 @@ void qca8084_port_clk_en_set(uint32_t qca8084_port_id, uint8_t mask,
return;
}
void qca8084_gcc_common_clk_parent_enable(void)
void qca8084_gcc_common_clk_parent_enable(qca8084_work_mode_t clk_mode)
{
/* Switch core */
qca8084_clk_parent_set(QCA8084_SWITCH_CORE_CLK, QCA8084_P_UNIPHY1_TX312P5M);
qca8084_clk_rate_set(QCA8084_SWITCH_CORE_CLK, UQXGMII_SPEED_2500M_CLK);
/* Disable switch core clock to save power in phy mode */
qca8084_clk_disable(QCA8084_SWITCH_CORE_CLK);
if (QCA8084_PHY_UQXGMII_MODE == clk_mode || QCA8084_PHY_SGMII_UQXGMII_MODE == clk_mode)
qca8084_clk_disable(QCA8084_SWITCH_CORE_CLK);
else
qca8084_clk_enable(QCA8084_SWITCH_CORE_CLK);
qca8084_clk_enable(QCA8084_APB_BRIDGE_CLK);
@ -1100,7 +1103,10 @@ void qca8084_gcc_common_clk_parent_enable(void)
qca8084_clk_rate_set(QCA8084_SRDS0_SYS_CLK, QCA8084_SYS_CLK_RATE_25M);
/* Disable serdes0 clock to save power in phy mode */
qca8084_clk_disable(QCA8084_SRDS0_SYS_CLK);
if (QCA8084_PHY_UQXGMII_MODE == clk_mode || QCA8084_PHY_SGMII_UQXGMII_MODE == clk_mode)
qca8084_clk_disable(QCA8084_SRDS0_SYS_CLK);
else
qca8084_clk_enable(QCA8084_SRDS0_SYS_CLK);
qca8084_clk_enable(QCA8084_SRDS1_SYS_CLK);
qca8084_clk_enable(QCA8084_GEPHY0_SYS_CLK);
@ -1115,12 +1121,27 @@ void qca8084_gcc_common_clk_parent_enable(void)
qca8084_clk_enable(QCA8084_SEC_CTRL_SENSE_CLK);
}
void qca8084_gcc_port_clk_parent_set(uint32_t qca8084_port_id)
void qca8084_gcc_port_clk_parent_set(qca8084_work_mode_t clk_mode, uint32_t qca8084_port_id)
{
qca8084_clk_parent_t port_tx_parent, port_rx_parent;
char *tx_clk_id, *rx_clk_id;
port_tx_parent = QCA8084_P_UNIPHY1_RX312P5M;
/* Initialize the clock parent with port 1, 2, 3, clock parent is same for these ports;
* the clock parent will be updated for port 0, 4, 5.
*/
switch(clk_mode) {
case QCA8084_SWITCH_MODE:
case QCA8084_SWITCH_BYPASS_PORT5_MODE:
port_tx_parent = QCA8084_P_UNIPHY1_TX312P5M;
break;
case QCA8084_PHY_UQXGMII_MODE:
case QCA8084_PHY_SGMII_UQXGMII_MODE:
port_tx_parent = QCA8084_P_UNIPHY1_RX312P5M;
break;
default:
pr_debug("Unsupported clock mode %d\n", clk_mode);
return;
}
port_rx_parent = QCA8084_P_UNIPHY1_TX312P5M;
switch (qca8084_port_id) {
@ -1143,8 +1164,24 @@ void qca8084_gcc_port_clk_parent_set(uint32_t qca8084_port_id)
rx_clk_id = QCA8084_MAC3_RX_CLK;
break;
case PORT4:
port_tx_parent = QCA8084_P_UNIPHY1_RX312P5M;
port_rx_parent = QCA8084_P_UNIPHY1_TX312P5M;
switch(clk_mode) {
case QCA8084_SWITCH_BYPASS_PORT5_MODE:
case QCA8084_PHY_SGMII_UQXGMII_MODE:
port_tx_parent = QCA8084_P_UNIPHY0_RX;
port_rx_parent = QCA8084_P_UNIPHY0_TX;
break;
case QCA8084_SWITCH_MODE:
port_tx_parent = QCA8084_P_UNIPHY1_TX312P5M;
port_rx_parent = QCA8084_P_UNIPHY1_TX312P5M;
break;
case QCA8084_PHY_UQXGMII_MODE:
port_tx_parent = QCA8084_P_UNIPHY1_RX312P5M;
port_rx_parent = QCA8084_P_UNIPHY1_TX312P5M;
break;
default:
pr_debug("Unsupported clock mode %d\n", clk_mode);
return;
}
tx_clk_id = QCA8084_MAC4_TX_CLK;
rx_clk_id = QCA8084_MAC4_RX_CLK;
break;
@ -1153,7 +1190,19 @@ void qca8084_gcc_port_clk_parent_set(uint32_t qca8084_port_id)
port_rx_parent = QCA8084_P_UNIPHY0_RX;
tx_clk_id = QCA8084_MAC5_TX_CLK;
rx_clk_id = QCA8084_MAC5_RX_CLK;
qca8084_port5_uniphy0_clk_src_set(0);
switch (clk_mode) {
case QCA8084_SWITCH_BYPASS_PORT5_MODE:
case QCA8084_PHY_SGMII_UQXGMII_MODE:
qca8084_port5_uniphy0_clk_src_set(1);
break;
case QCA8084_SWITCH_MODE:
case QCA8084_PHY_UQXGMII_MODE:
qca8084_port5_uniphy0_clk_src_set(0);
break;
default:
pr_debug("Unsupported clock mode %d\n", clk_mode);
return;
}
break;
default:
pr_debug("Unsupported qca8084_port_id %d\n", qca8084_port_id);
@ -1164,7 +1213,7 @@ void qca8084_gcc_port_clk_parent_set(uint32_t qca8084_port_id)
qca8084_clk_parent_set(rx_clk_id, port_rx_parent);
}
void qca8084_gcc_clock_init(void)
void qca8084_gcc_clock_init(qca8084_work_mode_t clk_mode, u32 pbmp)
{
uint32_t qca8084_port_id = 0;
/* clock type mask value for 6 manhattan ports */
@ -1173,13 +1222,51 @@ void qca8084_gcc_clock_init(void)
uint8_t switch_flag = 0;
qca8084_clk_parent_t uniphy_index = QCA8084_P_UNIPHY0_RX;
clk_mask[PORT1] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT2] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT3] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT4] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
switch (clk_mode) {
case QCA8084_SWITCH_MODE:
case QCA8084_SWITCH_BYPASS_PORT5_MODE:
while (pbmp) {
if (pbmp & 1) {
if (qca8084_port_id == PORT0 ||
qca8084_port_id == PORT5) {
clk_mask[qca8084_port_id] = QCA8084_CLK_TYPE_MAC |
QCA8084_CLK_TYPE_UNIPHY;
} else {
clk_mask[qca8084_port_id] = QCA8084_CLK_TYPE_MAC |
QCA8084_CLK_TYPE_EPHY;
}
}
pbmp >>= 1;
qca8084_port_id++;
}
if (clk_mode == QCA8084_SWITCH_BYPASS_PORT5_MODE) {
/* For phy port 4 in switch bypass mode */
clk_mask[PORT4] = QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT5] = QCA8084_CLK_TYPE_UNIPHY;
}
switch_flag = 1;
break;
case QCA8084_PHY_UQXGMII_MODE:
case QCA8084_PHY_SGMII_UQXGMII_MODE:
clk_mask[PORT1] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT2] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT3] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT4] = QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY;
if (clk_mode == QCA8084_PHY_SGMII_UQXGMII_MODE) {
/* For phy port4 in PHY bypass mode */
clk_mask[PORT4] = QCA8084_CLK_TYPE_EPHY;
clk_mask[PORT5] = QCA8084_CLK_TYPE_UNIPHY;
}
break;
default:
pr_debug("Unsupported clock mode %d\n", clk_mode);
return;
}
if (!gcc_common_clk_init) {
qca8084_gcc_common_clk_parent_enable();
qca8084_gcc_common_clk_parent_enable(clk_mode);
gcc_common_clk_init = 1;
/* Initialize the uniphy raw clock, if the port4 is in bypass mode, the uniphy0
@ -1199,12 +1286,16 @@ void qca8084_gcc_clock_init(void)
qca8084_port_id = 0;
while (qca8084_port_id < ARRAY_SIZE(clk_mask)) {
if (clk_mask[qca8084_port_id] != 0) {
qca8084_gcc_port_clk_parent_set(qca8084_port_id);
qca8084_gcc_port_clk_parent_set(clk_mode, qca8084_port_id);
if (clk_mask[qca8084_port_id] & QCA8084_CLK_TYPE_MAC)
qca8084_port_clk_en_set(qca8084_port_id, QCA8084_CLK_TYPE_MAC, 1);
if (clk_mask[qca8084_port_id] & QCA8084_CLK_TYPE_UNIPHY && switch_flag == 1)
qca8084_port_clk_en_set(qca8084_port_id, QCA8084_CLK_TYPE_UNIPHY, 1);
pbmp |= BIT(qca8084_port_id);
}
qca8084_port_id++;
}
pr_debug("QCA8084 GCC CLK initialization with clock mode %d on port bmp 0x%x\n",
clk_mode, pbmp);
}

View file

@ -96,6 +96,8 @@
#define QCA8084_GEPHY_P1_MDC_SW_RST "qca8084_gephy_p1_mdc_sw_rst"
#define QCA8084_GEPHY_P0_MDC_SW_RST "qca8084_gephy_p0_mdc_sw_rst"
typedef enum {
QCA8084_P_XO,
QCA8084_P_UNIPHY0_RX,
@ -180,4 +182,72 @@ struct clk_lookup {
#define CBCR_CLK_RESET BIT(2)
#define CBCR_CLK_ENABLE BIT(0)
/* work mode */
#define WORK_MODE
#define WORK_MODE_ID 0
#define WORK_MODE_OFFSET 0xC90F030
#define WORK_MODE_E_LENGTH 4
#define WORK_MODE_E_OFFSET 0
#define WORK_MODE_NR_E 1
/* port5 sel */
#define WORK_MODE_PORT5_SEL
#define WORK_MODE_PORT5_SEL_BOFFSET 5
#define WORK_MODE_PORT5_SEL_BLEN 1
#define WORK_MODE_PORT5_SEL_FLAG HSL_RW
/* phy3 sel1 */
#define WORK_MODE_PHY3_SEL1
#define WORK_MODE_PHY3_SEL1_BOFFSET 4
#define WORK_MODE_PHY3_SEL1_BLEN 1
#define WORK_MODE_PHY3_SEL1_FLAG HSL_RW
/* phy3 sel0 */
#define WORK_MODE_PHY3_SEL0
#define WORK_MODE_PHY3_SEL0_BOFFSET 3
#define WORK_MODE_PHY3_SEL0_BLEN 1
#define WORK_MODE_PHY3_SEL0_FLAG HSL_RW
/* phy2 sel */
#define WORK_MODE_PHY2_SEL
#define WORK_MODE_PHY2_SEL_BOFFSET 2
#define WORK_MODE_PHY2_SEL_BLEN 1
#define WORK_MODE_PHY2_SEL_FLAG HSL_RW
/* phy1 sel */
#define WORK_MODE_PHY1_SEL
#define WORK_MODE_PHY1_SEL_BOFFSET 1
#define WORK_MODE_PHY1_SEL_BLEN 1
#define WORK_MODE_PHY1_SEL_FLAG HSL_RW
/* phy0 sel */
#define WORK_MODE_PHY0_SEL
#define WORK_MODE_PHY0_SEL_BOFFSET 0
#define WORK_MODE_PHY0_SEL_BLEN 1
#define WORK_MODE_PHY0_SEL_FLAG HSL_RW
#define QCA8084_WORK_MODE_MASK \
(BITSM(WORK_MODE_PHY0_SEL_BOFFSET, WORK_MODE_PORT5_SEL_BOFFSET + 1))
typedef enum {
QCA8084_SWITCH_MODE =
(BIT(WORK_MODE_PHY3_SEL1_BOFFSET)),
QCA8084_SWITCH_BYPASS_PORT5_MODE =
(BIT(WORK_MODE_PORT5_SEL_BOFFSET)),
QCA8084_PHY_UQXGMII_MODE =
(BIT(WORK_MODE_PORT5_SEL_BOFFSET) |
BIT(WORK_MODE_PHY3_SEL0_BOFFSET) |
BIT(WORK_MODE_PHY2_SEL_BOFFSET) |
BIT(WORK_MODE_PHY1_SEL_BOFFSET) |
BIT(WORK_MODE_PHY0_SEL_BOFFSET)),
QCA8084_PHY_SGMII_UQXGMII_MODE =
(BIT(WORK_MODE_PORT5_SEL_BOFFSET) |
BIT(WORK_MODE_PHY2_SEL_BOFFSET) |
BIT(WORK_MODE_PHY1_SEL_BOFFSET) |
BIT(WORK_MODE_PHY0_SEL_BOFFSET)),
QCA8084_WORK_MODE_MAX,
} qca8084_work_mode_t;
#endif /* _QCA8084_CLK_H_ */

View file

@ -38,6 +38,7 @@ extern void ipq_mii_update(uint32_t reg, uint32_t mask, uint32_t val);
extern void qca8084_port_clk_rate_set(uint32_t qca8084_port_id, uint32_t rate);
extern void qca8084_port_clk_en_set(uint32_t qca8084_port_id, uint8_t mask,
uint8_t enable);
extern void qca8084_uniphy_raw_clock_set(qca8084_clk_parent_t uniphy_clk, uint64_t rate);
extern void qca8084_clk_assert(const char *clock_id);
extern void qca8084_clk_deassert(const char *clock_id);
extern void qca8084_port_clk_reset(uint32_t qca8084_port_id, uint8_t mask);
@ -502,3 +503,153 @@ void qca8084_interface_uqxgmii_mode_set(void)
pr_debug("enable EEE for xpcs\n");
qca8084_uniphy_xpcs_8023az_enable();
}
void qca8084_uniphy_sgmii_function_reset(u32 uniphy_index)
{
u32 uniphy_addr = 0;
qca8084_serdes_addr_get(uniphy_index, &uniphy_addr);
/*sgmii channel0 adpt reset*/
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_CHANNEL0_CFG, QCA8084_UNIPHY_MMD1_SGMII_ADPT_RESET, 0);
mdelay(1);
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_CHANNEL0_CFG, QCA8084_UNIPHY_MMD1_SGMII_ADPT_RESET,
QCA8084_UNIPHY_MMD1_SGMII_ADPT_RESET);
/*ipg tune reset*/
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_USXGMII_RESET, QCA8084_UNIPHY_MMD1_SGMII_FUNC_RESET, 0);
mdelay(1);
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_USXGMII_RESET, QCA8084_UNIPHY_MMD1_SGMII_FUNC_RESET,
QCA8084_UNIPHY_MMD1_SGMII_FUNC_RESET);
}
void qca8084_interface_sgmii_mode_set(u32 uniphy_index, u32 qca8084_port_id, mac_config_t *config)
{
u32 uniphy_addr = 0, mode_ctrl = 0, speed_mode = 0;
u32 uniphy_port_id = 0, ethphy_clk_mask = 0;
u64 raw_clk = 0;
/*get the uniphy address*/
qca8084_serdes_addr_get(uniphy_index, &uniphy_addr);
if(config->mac_mode == QCA8084_MAC_MODE_SGMII)
{
mode_ctrl = QCA8084_UNIPHY_MMD1_SGMII_MODE;
raw_clk = UNIPHY_CLK_RATE_125M;
}
else
{
mode_ctrl = QCA8084_UNIPHY_MMD1_SGMII_PLUS_MODE;
raw_clk = UNIPHY_CLK_RATE_312M;
}
if(config->clock_mode == QCA8084_INTERFACE_CLOCK_MAC_MODE)
mode_ctrl |= QCA8084_UNIPHY_MMD1_SGMII_MAC_MODE;
else
{
mode_ctrl |= QCA8084_UNIPHY_MMD1_SGMII_PHY_MODE;
/*eththy clock should be accessed for phy mode*/
ethphy_clk_mask = QCA8084_CLK_TYPE_EPHY;
}
pr_debug("uniphy:%d,mode:%s,autoneg_en:%d,force_speed:%d,clk_mask:0x%x\n",
uniphy_index, (config->mac_mode == QCA8084_MAC_MODE_SGMII)?"sgmii":"sgmii plus",
config->auto_neg, config->force_speed,
ethphy_clk_mask);
/*GMII interface clock disable*/
pr_debug("GMII interface clock disable\n");
qca8084_port_clk_en_set(qca8084_port_id, ethphy_clk_mask, 0);
/*when access uniphy0 clock, port5 should be used, but for phy mode,
the port 4 connect to uniphy0, so need to change the port id*/
if(uniphy_index == QCA8084_UNIPHY_SGMII_0)
uniphy_port_id = PORT5;
else
uniphy_port_id = qca8084_port_id;
qca8084_port_clk_en_set(uniphy_port_id, QCA8084_CLK_TYPE_UNIPHY, 0);
/*uniphy1 xpcs reset, and configure raw clk*/
if(uniphy_index == QCA8084_UNIPHY_SGMII_1)
{
pr_debug("uniphy1 xpcs reset, confiugre raw clock as:%lld\n",
raw_clk);
qca8084_clk_assert(QCA8084_UNIPHY_XPCS_RST);
qca8084_uniphy_raw_clock_set(QCA8084_P_UNIPHY1_RX, raw_clk);
qca8084_uniphy_raw_clock_set(QCA8084_P_UNIPHY1_TX, raw_clk);
}
else
{
pr_debug("uniphy0 configure raw clock as %lld\n", raw_clk);
qca8084_uniphy_raw_clock_set(QCA8084_P_UNIPHY0_RX, raw_clk);
qca8084_uniphy_raw_clock_set(QCA8084_P_UNIPHY0_TX, raw_clk);
}
/*configure SGMII mode or SGMII+ mode*/
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_MODE_CTRL, QCA8084_UNIPHY_MMD1_SGMII_MODE_CTRL_MASK,
mode_ctrl);
/*GMII datapass selection, 0 is for SGMII, 1 is for USXGMII*/
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_GMII_DATAPASS_SEL, QCA8084_UNIPHY_MMD1_DATAPASS_MASK, QCA8084_UNIPHY_MMD1_DATAPASS_SGMII);
/*configue force or autoneg*/
if(!config->auto_neg)
{
qca8084_port_speed_clock_set(qca8084_port_id,
config->force_speed);
switch (config->force_speed)
{
case FAL_SPEED_10:
speed_mode = QCA8084_UNIPHY_MMD1_CH0_FORCE_ENABLE |
QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_10M;
break;
case FAL_SPEED_100:
speed_mode = QCA8084_UNIPHY_MMD1_CH0_FORCE_ENABLE |
QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_100M;
break;
case FAL_SPEED_1000:
case FAL_SPEED_2500:
speed_mode = QCA8084_UNIPHY_MMD1_CH0_FORCE_ENABLE |
QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_1G;
break;
default:
break;
}
}
else
{
speed_mode = QCA8084_UNIPHY_MMD1_CH0_AUTONEG_ENABLE;
}
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_CHANNEL0_CFG, QCA8084_UNIPHY_MMD1_CH0_FORCE_SPEED_MASK, speed_mode);
/*GMII interface clock reset and release\n*/
pr_debug("GMII interface clock reset and release\n");
qca8084_port_clk_reset(qca8084_port_id, ethphy_clk_mask);
qca8084_port_clk_reset(uniphy_port_id, QCA8084_CLK_TYPE_UNIPHY);
/*analog software reset and release*/
pr_debug("analog software reset and release\n");
qca8084_phy_modify_mii(uniphy_addr,
QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET, 0x40, QCA8084_UNIPHY_ANA_SOFT_RESET);
mdelay(1);
qca8084_phy_modify_mii(uniphy_addr,
QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET, 0x40, QCA8084_UNIPHY_ANA_SOFT_RELEASE);
/*wait uniphy calibration done*/
pr_debug("wait uniphy calibration done\n");
qca8084_uniphy_calibration(uniphy_addr);
/*GMII interface clock enable*/
pr_debug("GMII interface clock enable\n");
qca8084_port_clk_en_set(qca8084_port_id, ethphy_clk_mask, 1);
qca8084_port_clk_en_set(uniphy_port_id, QCA8084_CLK_TYPE_UNIPHY, 1);
return;
}

View file

@ -129,6 +129,12 @@
#define QCA8084_UNIPHY_MMD_XPC_SPEED_10 0
#define QCA8084_UNIPHY_MMD_TX_IPG_CHECK_DISABLE 0x1
#define UNIPHY_CLK_RATE_25M 25000000
#define UNIPHY_CLK_RATE_50M 50000000
#define UNIPHY_CLK_RATE_125M 125000000
#define UNIPHY_CLK_RATE_312M 312500000
#define UNIPHY_DEFAULT_RATE UNIPHY_CLK_RATE_125M
typedef enum {
QCA8084_UNIPHY_MAC = QCA8084_UNIPHY_MMD1_SGMII_MAC_MODE,
QCA8084_UNIPHY_PHY = QCA8084_UNIPHY_MMD1_SGMII_PHY_MODE,
@ -137,4 +143,29 @@ typedef enum {
QCA8084_UNIPHY_UQXGMII = QCA8084_UNIPHY_MMD1_XPCS_MODE,
} qca8084_uniphy_mode_t;
typedef enum {
QCA8084_INTERFACE_CLOCK_MAC_MODE = 0,
QCA8084_INTERFACE_CLOCK_PHY_MODE = 1,
} qca8084_clock_mode_t;
typedef enum {
QCA8084_MAC_MODE_RGMII = 0,
QCA8084_MAC_MODE_GMII,
QCA8084_MAC_MODE_MII,
QCA8084_MAC_MODE_SGMII,
QCA8084_MAC_MODE_FIBER,
QCA8084_MAC_MODE_RMII,
QCA8084_MAC_MODE_SGMII_PLUS,
QCA8084_MAC_MODE_DEFAULT
} qca8084_mac_mode_t;
typedef struct {
qca8084_mac_mode_t mac_mode;
qca8084_clock_mode_t clock_mode;
bool auto_neg;
u32 force_speed;
bool prbs_enable;
bool rem_phy_lpbk;
} mac_config_t;
#endif