mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2026-03-05 08:51:31 +01:00
drivers: net: ipq5018: Add SFP 1G and 2.5G Support
Only one SFP port can be enabled at time with
either SGMII or SGMII PLUS mode.
Mode shall be specified from dts for 1G or 2.5G
support respectively. Add below change to enable
SFP as this change is not mainlined.
gmac_cfg {
gmac2_cfg {
unit = <1>;
base = <0x39D00000>;
- phy_address = <0x1c>;
- napa_gpio = <39>;
/*
* 6 - SGMII_PLUS (2.5G),
* 8 - SGMII_FIBER (1G)
*/
+ switch_mac_mode = <8>;
+ sfp_tx_gpio = <27>;
+ sfp_rx_gpio = <29>;
};
};
Change-Id: I507be2b84b1f932802659abffa3288e304e0d411
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
This commit is contained in:
parent
d4fab50cef
commit
d820c5abbc
6 changed files with 159 additions and 19 deletions
|
|
@ -266,6 +266,9 @@ struct ipq_eth_dev {
|
|||
uint ipq_swith;
|
||||
uint phy_external_link;
|
||||
int link_printed;
|
||||
u32 sfp_mode;
|
||||
u32 sfp_tx_gpio;
|
||||
u32 sfp_rx_gpio;
|
||||
u32 padding;
|
||||
ipq_gmac_desc_t *desc_tx[NO_OF_TX_DESC];
|
||||
ipq_gmac_desc_t *desc_rx[NO_OF_RX_DESC];
|
||||
|
|
|
|||
|
|
@ -770,6 +770,15 @@ static void set_ext_mdio_gpio(int node)
|
|||
}
|
||||
}
|
||||
|
||||
static void reset_sfp_gpio(int gpio)
|
||||
{
|
||||
unsigned int *sfp_gpio_base;
|
||||
|
||||
sfp_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(gpio);
|
||||
writel(0x2c3, sfp_gpio_base);
|
||||
writel(0x0, GPIO_IN_OUT_ADDR(gpio));
|
||||
}
|
||||
|
||||
static void reset_napa_phy_gpio(int gpio)
|
||||
{
|
||||
unsigned int *napa_gpio_base;
|
||||
|
|
@ -1172,6 +1181,18 @@ int board_eth_init(bd_t *bis)
|
|||
gmac_cfg[loop].phy_external_link = fdtdec_get_uint(gd->fdt_blob,
|
||||
offset, "phy_external_link", 0);
|
||||
|
||||
gmac_cfg[loop].sfp_mode = fdtdec_get_uint(gd->fdt_blob,
|
||||
offset, "switch_mac_mode", 0);
|
||||
gmac_cfg[loop].sfp_rx_gpio
|
||||
= fdtdec_get_uint(gd->fdt_blob, offset,
|
||||
"sfp_rx_gpio", 0);
|
||||
gmac_cfg[loop].sfp_tx_gpio
|
||||
= fdtdec_get_uint(gd->fdt_blob, offset,
|
||||
"sfp_tx_gpio", 0);
|
||||
if (gmac_cfg[loop].sfp_tx_gpio) {
|
||||
reset_sfp_gpio(gmac_cfg[loop].sfp_tx_gpio);
|
||||
}
|
||||
|
||||
gmac_cfg[loop].phy_napa_gpio = fdtdec_get_uint(gd->fdt_blob,
|
||||
offset, "napa_gpio", 0);
|
||||
if (gmac_cfg[loop].phy_napa_gpio){
|
||||
|
|
|
|||
|
|
@ -498,6 +498,9 @@ typedef struct {
|
|||
int phy_interface_mode;
|
||||
int phy_napa_gpio;
|
||||
int phy_8033_gpio;
|
||||
u32 sfp_tx_gpio;
|
||||
u32 sfp_rx_gpio;
|
||||
u32 sfp_mode;
|
||||
int phy_type;
|
||||
u32 mac_pwr;
|
||||
int ipq_swith;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,10 @@ extern int ipq_qca8081_phy_init(struct phy_ops **ops, u32 phy_id);
|
|||
extern int ipq_gephy_phy_init(struct phy_ops **ops, u32 phy_id);
|
||||
extern int ipq_sw_mdio_init(const char *);
|
||||
extern int ipq5018_sw_mdio_init(const char *);
|
||||
extern void ppe_uniphy_mode_set(uint32_t mode);
|
||||
extern void ppe_uniphy_mode_set(uint32_t mode, uint32_t phy_mode);
|
||||
extern void uniphy_channel0_input_output_6_get(int mode, u32 gpio, u8 *status,
|
||||
fal_port_speed_t *speed,
|
||||
fal_port_duplex_t *duplex);
|
||||
extern int ipq_athrs17_init(ipq_gmac_board_cfg_t *gmac_cfg);
|
||||
|
||||
static int ipq_eth_wr_macaddr(struct eth_device *dev)
|
||||
|
|
@ -354,6 +357,7 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
|
|||
char *dp[] = {"Half", "Full"};
|
||||
int speed_clock1 = 0, speed_clock2 = 0;
|
||||
int mode = PORT_WRAPPER_SGMII0_RGMII4;
|
||||
uint32_t phy_mode = 0x70;
|
||||
|
||||
phy_get_ops = priv->ops;
|
||||
|
||||
|
|
@ -363,17 +367,27 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
|
|||
status = ipq5018_s17c_Link_Update(priv);
|
||||
}
|
||||
|
||||
if (phy_get_ops != NULL &&
|
||||
phy_get_ops->phy_get_link_status != NULL &&
|
||||
phy_get_ops->phy_get_speed != NULL &&
|
||||
phy_get_ops->phy_get_duplex != NULL){
|
||||
if (priv->sfp_tx_gpio || phy_get_ops) {
|
||||
if (phy_get_ops &&
|
||||
phy_get_ops->phy_get_link_status != NULL &&
|
||||
phy_get_ops->phy_get_speed != NULL &&
|
||||
phy_get_ops->phy_get_duplex != NULL){
|
||||
|
||||
status = phy_get_ops->phy_get_link_status(priv->mac_unit,
|
||||
priv->phy_address);
|
||||
phy_get_ops->phy_get_speed(priv->mac_unit,
|
||||
priv->phy_address, &speed);
|
||||
phy_get_ops->phy_get_duplex(priv->mac_unit,
|
||||
priv->phy_address, &duplex);
|
||||
status = phy_get_ops->phy_get_link_status(priv->mac_unit,
|
||||
priv->phy_address);
|
||||
phy_get_ops->phy_get_speed(priv->mac_unit,
|
||||
priv->phy_address, &speed);
|
||||
phy_get_ops->phy_get_duplex(priv->mac_unit,
|
||||
priv->phy_address, &duplex);
|
||||
}
|
||||
|
||||
if (priv->sfp_tx_gpio) {
|
||||
mode = priv->sfp_mode;
|
||||
uniphy_channel0_input_output_6_get(priv->sfp_mode,
|
||||
priv->sfp_rx_gpio,
|
||||
&status,
|
||||
&speed, &duplex);
|
||||
}
|
||||
|
||||
switch (speed) {
|
||||
case FAL_SPEED_10:
|
||||
|
|
@ -398,6 +412,8 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
|
|||
priv->speed = SGMII_PORT_SELECT;
|
||||
speed_clock1 = 1;
|
||||
speed_clock2 = 0;
|
||||
if (priv->sfp_tx_gpio)
|
||||
phy_mode = 0x30;
|
||||
printf ("eth%d %s Speed :%d %s duplex\n",
|
||||
priv->mac_unit,
|
||||
lstatus[status], speed,
|
||||
|
|
@ -408,6 +424,11 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
|
|||
mode = PORT_WRAPPER_SGMII_PLUS;
|
||||
speed_clock1 = 1;
|
||||
speed_clock2 = 0;
|
||||
|
||||
if (priv->sfp_tx_gpio)
|
||||
phy_mode = 0x50;
|
||||
else
|
||||
phy_mode = 0x30;
|
||||
printf ("eth%d %s Speed :%d %s duplex\n",
|
||||
priv->mac_unit,
|
||||
lstatus[status], speed,
|
||||
|
|
@ -427,7 +448,7 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
|
|||
}
|
||||
|
||||
if (priv->mac_unit){
|
||||
ppe_uniphy_mode_set(mode);
|
||||
ppe_uniphy_mode_set(mode, phy_mode);
|
||||
} else {
|
||||
ipq5018_enable_gephy();
|
||||
}
|
||||
|
|
@ -724,7 +745,9 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg)
|
|||
uchar enet_addr[CONFIG_IPQ_NO_MACS * 6];
|
||||
int i;
|
||||
uint32_t phy_chip_id, phy_chip_id1, phy_chip_id2;
|
||||
uint32_t phy_mode = 0x70;
|
||||
int ret;
|
||||
|
||||
memset(enet_addr, 0, sizeof(enet_addr));
|
||||
|
||||
/* Mdio init */
|
||||
|
|
@ -786,6 +809,14 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg)
|
|||
ipq_gmac_macs[i]->interface = gmac_cfg->phy_interface_mode;
|
||||
ipq_gmac_macs[i]->phy_type = gmac_cfg->phy_type;
|
||||
ipq_gmac_macs[i]->phy_external_link = gmac_cfg->phy_external_link;
|
||||
ipq_gmac_macs[i]->sfp_tx_gpio = gmac_cfg->sfp_tx_gpio;
|
||||
ipq_gmac_macs[i]->sfp_rx_gpio = gmac_cfg->sfp_rx_gpio;
|
||||
ipq_gmac_macs[i]->sfp_mode = gmac_cfg->sfp_mode;
|
||||
|
||||
if (gmac_cfg->sfp_mode == PORT_WRAPPER_SGMII_PLUS)
|
||||
phy_mode = 0x50;
|
||||
else if (gmac_cfg->sfp_mode == PORT_WRAPPER_SGMII_FIBER)
|
||||
phy_mode = 0x30;
|
||||
|
||||
snprintf((char *)ipq_gmac_macs[i]->phy_name,
|
||||
sizeof(ipq_gmac_macs[i]->phy_name), "IPQ MDIO%d", i);
|
||||
|
|
@ -847,7 +878,12 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
printf("GMAC%d:Invalid PHY ID \n", i);
|
||||
if (gmac_cfg->sfp_tx_gpio) {
|
||||
ppe_uniphy_mode_set(gmac_cfg->sfp_mode,
|
||||
phy_mode);
|
||||
} else {
|
||||
printf("GMAC%d:Invalid PHY ID \n", i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Initialize 8337 switch */
|
||||
|
|
|
|||
|
|
@ -59,9 +59,74 @@ static void ppe_gcc_uniphy_soft_reset(void)
|
|||
writel(reg_value, GCC_UNIPHY0_MISC);
|
||||
}
|
||||
|
||||
static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
|
||||
void uniphy_channel0_input_output_6_get(int mode, u32 gpio, u8 *status,
|
||||
fal_port_speed_t *speed,
|
||||
fal_port_duplex_t *duplex)
|
||||
{
|
||||
uint32_t reg_value;
|
||||
int val;
|
||||
|
||||
*status = 1;
|
||||
*speed = FAL_SPEED_BUTT;
|
||||
*duplex = FAL_DUPLEX_BUTT;
|
||||
|
||||
reg_value = readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_6);
|
||||
|
||||
val = reg_value & CH0_LINK_MAC;
|
||||
|
||||
if (val) {
|
||||
switch(mode) {
|
||||
case PORT_WRAPPER_SGMII_FIBER:
|
||||
*status = 0; /* LINK UP */
|
||||
break;
|
||||
case PORT_WRAPPER_SGMII_PLUS:
|
||||
/*
|
||||
* get rx_los status
|
||||
* if, rx_los = 0, link up
|
||||
* else, link down
|
||||
*/
|
||||
if (gpio && !gpio_get_value(gpio)) {
|
||||
*status = 0;
|
||||
*speed = FAL_SPEED_2500;
|
||||
*duplex = FAL_FULL_DUPLEX;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
printf("%s: Invalid mode\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
val = (reg_value & CH0_SPEED_MODE_MAC) >> 4;
|
||||
|
||||
switch(val) {
|
||||
case UNIPHY_SPEED_1000M:
|
||||
*speed = FAL_SPEED_1000;
|
||||
break;
|
||||
case UNIPHY_SPEED_100M:
|
||||
*speed = FAL_SPEED_100;
|
||||
break;
|
||||
case UNIPHY_SPEED_10M:
|
||||
*speed = FAL_SPEED_10;
|
||||
break;
|
||||
default:
|
||||
*speed = FAL_SPEED_BUTT;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
val = (reg_value & CH0_DUPLEX_MODE_MAC) >> 6;
|
||||
|
||||
if (val)
|
||||
*duplex = FAL_FULL_DUPLEX;
|
||||
else
|
||||
*duplex = FAL_HALF_DUPLEX;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ppe_uniphy_sgmii_mode_set(uint32_t mode, uint32_t phy_mode)
|
||||
{
|
||||
uint32_t phy_mode = 0x70;
|
||||
writel(UNIPHY_MISC2_REG_SGMII_MODE,
|
||||
PPE_UNIPHY_BASE + UNIPHY_MISC2_REG_OFFSET);
|
||||
|
||||
|
|
@ -96,7 +161,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
|
|||
case PORT_WRAPPER_SGMII_PLUS:
|
||||
writel((UNIPHY_SG_PLUS_MODE | UNIPHY_PSGMII_MAC_MODE),
|
||||
PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL);
|
||||
phy_mode = 0x30;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -123,12 +187,12 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
|
|||
ppe_uniphy_calibration();
|
||||
}
|
||||
|
||||
void ppe_uniphy_mode_set(uint32_t mode)
|
||||
void ppe_uniphy_mode_set(uint32_t mode, uint32_t phy_mode)
|
||||
{
|
||||
/*
|
||||
* SGMII and SHMII plus confugure in same function
|
||||
*/
|
||||
ppe_uniphy_sgmii_mode_set(mode);
|
||||
ppe_uniphy_sgmii_mode_set(mode, phy_mode);
|
||||
}
|
||||
|
||||
void ppe_uniphy_set_forceMode(void)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#ifndef _IPQ5018_UNIPHY_H_
|
||||
#define _IPQ5018_UNIPHY_H
|
||||
#include "ipq_phy.h"
|
||||
|
||||
#define PPE_UNIPHY_INSTANCE0 0
|
||||
|
||||
|
|
@ -47,6 +48,11 @@
|
|||
#define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4 0x480
|
||||
#define UNIPHY_FORCE_SPEED_25M (1 << 3)
|
||||
|
||||
#define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_6 0x488
|
||||
#define CH0_LINK_MAC (1 << 7)
|
||||
#define CH0_DUPLEX_MODE_MAC (1 << 6)
|
||||
#define CH0_SPEED_MODE_MAC (3 << 4)
|
||||
|
||||
#define UNIPHY_REF_CLK_CTRL_REG 0x74
|
||||
|
||||
#define UNIPHY_INSTANCE_LINK_DETECT 0x570
|
||||
|
|
@ -61,7 +67,14 @@
|
|||
#define UNIPHY_PLL_RESET_REG_VALUE 0x02bf
|
||||
#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff
|
||||
|
||||
void ppe_uniphy_mode_set(uint32_t mode);
|
||||
#define UNIPHY_SPEED_10M 0
|
||||
#define UNIPHY_SPEED_100M 1
|
||||
#define UNIPHY_SPEED_1000M 2
|
||||
|
||||
void ppe_uniphy_mode_set(uint32_t mode, uint32_t phy_mode);
|
||||
void ppe_uniphy_set_forceMode(void);
|
||||
void ppe_uniphy_refclk_set(void);
|
||||
void uniphy_channel0_input_output_6_get(int mode, u32 gpio, u8 *status,
|
||||
fal_port_speed_t *speed,
|
||||
fal_port_duplex_t *duplex);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue