ipq807x: Added the USXMII speed and clock

Change-Id: Ieb3e01eef27807091e0a1670d6b7c25334bed396
Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org>
This commit is contained in:
Sham Muthayyan 2017-09-12 15:45:59 +05:30 committed by Gerrit - the friendly Code Review server
parent 92f52b796e
commit b89040defa
6 changed files with 277 additions and 7 deletions

View file

@ -872,11 +872,14 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
char *dp[] = {"Half", "Full"};
int linkup=0;
int mac_speed, speed_clock1, speed_clock2;
int phy_addr, port_8033 = -1, node;
int phy_addr, port_8033 = -1, node, aquantia_port = -1;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0)
port_8033 = fdtdec_get_uint(gd->fdt_blob, node, "8033_port", -1);
if (node >= 0)
aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_port", -1);
/*
* Check PHY link, speed, Duplex on all phys.
* we will proceed even if single link is up
@ -898,6 +901,8 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
if (i == port_8033)
phy_addr = QCA8033_PHY_ADDR;
else if (i == aquantia_port)
phy_addr = AQU_PHY_ADDR;
else
phy_addr = i;
@ -908,6 +913,10 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
switch (speed) {
case FAL_SPEED_10:
if (i == aquantia_port) {
printf("10M speed not supported\n");
continue;
}
mac_speed = 0x0;
speed_clock1 = 0x109;
speed_clock2 = 0x9;
@ -917,7 +926,10 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
break;
case FAL_SPEED_100:
mac_speed = 0x1;
speed_clock1 = 0x101;
if (i == aquantia_port)
speed_clock1 = 0x109;
else
speed_clock1 = 0x101;
speed_clock2 = 0x4;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
@ -925,17 +937,48 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
break;
case FAL_SPEED_1000:
mac_speed = 0x2;
if (i == aquantia_port)
speed_clock1 = 0x104;
else
speed_clock1 = 0x101;
speed_clock2 = 0x0;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_10000:
mac_speed = 0x3;
speed_clock1 = 0x101;
speed_clock2 = 0x0;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_2500:
mac_speed = 0x4;
speed_clock1 = 0x107;
speed_clock2 = 0x0;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_5000:
mac_speed = 0x5;
speed_clock1 = 0x103;
speed_clock2 = 0x0;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
default:
printf("Unknown speed\n");
break;
}
ipq807x_pqsgmii_speed_clock_set(i, mac_speed, speed_clock1, speed_clock2);
ipq807x_speed_clock_set(i, speed_clock1, speed_clock2);
if (i == aquantia_port)
ipq807x_uxsgmii_speed_set(i, mac_speed, duplex);
else
ipq807x_pqsgmii_speed_set(i, mac_speed);
}
if (linkup <= 0) {

View file

@ -307,6 +307,8 @@ typedef struct {
} ipq807x_edma_board_cfg_t;
extern void ipq807x_ppe_provision_init(void);
extern void ipq807x_pqsgmii_speed_clock_set(int port, int speed, int speed_clock1, int speed_clock2);
extern void ipq807x_speed_clock_set(int port, int speed_clock1, int speed_clock2);
extern void ipq807x_pqsgmii_speed_set(int port, int speed);
extern void ipq807x_uxsgmii_speed_set(int port, int speed, int duplex);
#endif /* ___IPQ807X_EDMA__ */

View file

@ -106,11 +106,12 @@ static void ipq807x_gmac_enable(void)
*/
static void ipq807x_gmac_port_enable(int port)
{
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_ENABLE + (0x200 * port), 0x13);
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_ENABLE + (0x200 * port), 0x70);
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_SPEED + (0x200 * port), 0x2);
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_MIB_CTL + (0x200 * port), 0x1);
}
void ipq807x_pqsgmii_speed_clock_set(int port, int speed, int speed_clock1, int speed_clock2)
void ipq807x_speed_clock_set(int port, int speed_clock1, int speed_clock2)
{
int i;
@ -120,9 +121,122 @@ void ipq807x_pqsgmii_speed_clock_set(int port, int speed, int speed_clock1, int
writel(speed_clock1, GCC_NSS_PORT1_RX_CFG_RCGR + i*8 + port*0x10);
writel(0x1, GCC_NSS_PORT1_RX_CMD_RCGR + i*8 + port*0x10);
}
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_SPEED + (0x200 * port), speed);
}
void ipq807x_pqsgmii_speed_set(int port, int speed)
{
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_SPEED + (0x200 * port), speed);
ipq807x_ppe_reg_write(IPQ807X_PPE_MAC_ENABLE + (0x200 * port), 0x73);
}
void ppe_xgmac_speed_set(uint32_t uniphy_index, int speed)
{
uint32_t reg_value = 0;
ipq807x_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(uniphy_index * 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;
ipq807x_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value);
}
void ppe_port_bridge_txmac_set(int port_id)
{
uint32_t reg_value = 0;
ipq807x_ppe_reg_read(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS +
(port_id * PORT_BRIDGE_CTRL_INC), &reg_value);
reg_value |= TX_MAC_EN;
ipq807x_ppe_reg_write(IPE_L2_BASE_ADDR + PORT_BRIDGE_CTRL_ADDRESS +
(port_id * PORT_BRIDGE_CTRL_INC), reg_value);
}
void ppe_port_txmac_status_set(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
ipq807x_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), &reg_value);
reg_value |=TE;
ipq807x_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value);
}
void ppe_port_rxmac_status_set(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
ipq807x_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION +
(uniphy_index * MAC_RX_CONFIGURATION_ADDRESS), &reg_value);
reg_value |= 0x5ee00c0;
reg_value |=RE;
reg_value |=ACS;
reg_value |=CST;
ipq807x_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION +
(uniphy_index * MAC_RX_CONFIGURATION_ADDRESS), reg_value);
}
void ppe_mac_packet_filter_set(uint32_t uniphy_index)
{
ipq807x_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
MAC_PACKET_FILTER_ADDRESS +
(uniphy_index * MAC_PACKET_FILTER_INC), 0x81);
}
void ipq807x_uxsgmii_speed_set(int port, int speed, int duplex,
int speed_clock1, int speed_clock2)
{
uint32_t uniphy_index;
/* Setting the speed only for PORT5 and PORT6 */
if (port == (PORT5 - PPE_UNIPHY_INSTANCE1))
uniphy_index = PPE_UNIPHY_INSTANCE1;
if (port == (PORT6 - PPE_UNIPHY_INSTANCE1))
uniphy_index = PPE_UNIPHY_INSTANCE2;
else
return;
ppe_uniphy_usxgmii_autoneg_completed(uniphy_index);
ppe_uniphy_usxgmii_speed_set(uniphy_index, speed);
ppe_xgmac_speed_set(uniphy_index - 1, speed);
ppe_uniphy_usxgmii_duplex_set(uniphy_index, duplex);
ppe_uniphy_usxgmii_port_reset(uniphy_index);
ppe_port_bridge_txmac_set(port + 1);
ppe_port_txmac_status_set(uniphy_index - 1);
ppe_port_rxmac_status_set(uniphy_index - 1);
ppe_mac_packet_filter_set(uniphy_index - 1);
}
/*
* ipq807x_ppe_flow_port_map_tbl_port_num_set()
*/

View file

@ -156,4 +156,27 @@ union port_mux_ctrl_u {
#define IPQ807X_PPE_PORT_XGMAC2_BITPOS (1 << IPQ807X_PPE_PORT_XGMAC2)
#define IPQ807X_PPE_PORT_CRYPTO1_BITPOS (1 << IPQ807X_PPE_PORT_CRYPTO1)
#define PPE_SWITCH_NSS_SWITCH_XGMAC0 0x3000
#define NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION 0x4000
#define USS (1 << 31)
#define SS(i) (i << 29)
#define JD (1 << 16)
#define TE (1 << 0)
#define NSS_SWITCH_XGMAC_MAC_RX_CONFIGURATION 0x4000
#define MAC_RX_CONFIGURATION_ADDRESS 0x4
#define RE (1 << 0)
#define ACS (1 << 1)
#define CST (1 << 2)
#define MAC_PACKET_FILTER_INC 0x4000
#define MAC_PACKET_FILTER_ADDRESS 0x8
#define XGMAC_SPEED_SELECT_10000M 0
#define XGMAC_SPEED_SELECT_5000M 1
#define XGMAC_SPEED_SELECT_2500M 2
#define XGMAC_SPEED_SELECT_1000M 3
#define IPE_L2_BASE_ADDR 0x060000
#define PORT_BRIDGE_CTRL_ADDRESS 0x300
#define PORT_BRIDGE_CTRL_INC 0x4
#define TX_MAC_EN (1 << 16)

View file

@ -193,3 +193,87 @@ void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode)
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

@ -67,3 +67,7 @@ enum port_wrapper_cfg {
#define CL37_ANCMPLT_INTR (1 << 0)
void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode);
void ppe_uniphy_usxgmii_port_reset(uint32_t uniphy_index);
void ppe_uniphy_usxgmii_duplex_set(uint32_t uniphy_index, int duplex);
void ppe_uniphy_usxgmii_speed_set(uint32_t uniphy_index, int speed);
void ppe_uniphy_usxgmii_autoneg_completed(uint32_t uniphy_index);