ipq807x: Add the multiple phy support

Change-Id: I8d22e267ccad0f8f14532e46f379e45faf32bad5
Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org>
This commit is contained in:
Sham Muthayyan 2017-08-31 17:49:28 +05:30 committed by Gerrit - the friendly Code Review server
parent 11d70f9af5
commit 6a012e63d6
6 changed files with 81 additions and 64 deletions

View file

@ -40,7 +40,6 @@ extern loff_t board_env_size;
extern int ipq_spi_init(u16);
extern int ipq807x_edma_init(void *cfg);
extern int ipq_qca8075_phy_init(struct phy_ops **ops);
const char *rsvd_node = "/reserved-memory";
const char *del_node[] = {"uboot",
@ -231,8 +230,6 @@ int board_eth_init(bd_t *bis)
int ret=0;
int tlmm_base = 0x1025000;
ipq807x_register_switch(ipq_qca8075_phy_init);
/*
* ethernet clk rcgr block init -- start
* these clk init will be moved to sbl later

View file

@ -43,17 +43,15 @@ static struct ipq807x_eth_dev *ipq807x_edma_dev[IPQ807X_EDMA_DEV];
uchar ipq807x_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD};
static int (*ipq807x_switch_init)(struct phy_ops **ops);
extern void qca8075_ess_reset(void);
extern void psgmii_self_test(void);
extern void clear_self_test_config(void);
extern int ipq_sw_mdio_init(const char *);
extern void ipq_qca8075_dump_phy_regs(u32);
void ipq807x_register_switch(int(*sw_init)(struct phy_ops **ops))
{
ipq807x_switch_init = sw_init;
}
extern int ipq_mdio_read(int mii_id,
int regnum, ushort *data);
extern void ipq_qca8075_phy_map_ops(struct phy_ops **ops);
extern int ipq_qca8075_phy_init(struct phy_ops **ops);
/*
* EDMA hardware instance
@ -868,20 +866,7 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
char *lstatus[] = {"up", "Down"};
char *dp[] = {"Half", "Full"};
int linkup=0;
int mac_speed = 0, speed_clock1 = 0, speed_clock2 = 0;
if (!priv->ops) {
printf ("Phy ops not mapped\n");
return -1;
}
phy_get_ops = priv->ops;
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf ("Link status/Get speed/Get duplex not mapped\n");
return -1;
}
int mac_speed, speed_clock1, speed_clock2;
/*
* Check PHY link, speed, Duplex on all phys.
@ -889,39 +874,52 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
* else we will return with -1;
*/
for (i = 0; i < PHY_MAX; i++) {
if (!priv->ops[i]) {
printf ("Phy ops not mapped\n");
return -1;
}
phy_get_ops = priv->ops[i];
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf ("Link status/Get speed/Get duplex not mapped\n");
return -1;
}
status = phy_get_ops->phy_get_link_status(priv->mac_unit, i);
if (status == 0)
linkup++;
phy_get_ops->phy_get_speed(priv->mac_unit, i, &speed);
phy_get_ops->phy_get_duplex(priv->mac_unit, i, &duplex);
switch (speed) {
case FAL_SPEED_10:
mac_speed = 0x0;
speed_clock1 = 0x109;
speed_clock2 = 0x9;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_100:
mac_speed = 0x1;
speed_clock1 = 0x101;
speed_clock2 = 0x4;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_1000:
mac_speed = 0x2;
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;
default:
printf("Unknown speed\n");
break;
case FAL_SPEED_10:
mac_speed = 0x0;
speed_clock1 = 0x109;
speed_clock2 = 0x9;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_100:
mac_speed = 0x1;
speed_clock1 = 0x101;
speed_clock2 = 0x4;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
dp[duplex]);
break;
case FAL_SPEED_1000:
mac_speed = 0x2;
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;
default:
printf("Unknown speed\n");
break;
}
ipq807x_pqsgmii_speed_clock_set(i, mac_speed, speed_clock1, speed_clock2);
}
@ -1536,12 +1534,12 @@ int ipq807x_edma_init(void *edma_board_cfg)
struct ipq807x_edma_common_info *c_info[IPQ807X_EDMA_DEV];
struct ipq807x_edma_hw *hw[IPQ807X_EDMA_DEV];
uchar enet_addr[IPQ807X_EDMA_DEV * 6];
int i;
int i, phy_id;
uint32_t phy_chip_id, phy_chip_id1, phy_chip_id2;
int ret = -1;
ipq807x_edma_board_cfg_t ledma_cfg, *edma_cfg;
static int sw_init_done = 0;
memset(c_info, 0, (sizeof(c_info) * IPQ807X_EDMA_DEV));
memset(enet_addr, 0, sizeof(enet_addr));
memset(&ledma_cfg, 0, sizeof(ledma_cfg));
@ -1621,13 +1619,27 @@ int ipq807x_edma_init(void *edma_board_cfg)
if (ret)
goto init_failed;
for (phy_id = 0; phy_id < PHY_MAX; phy_id++) {
if (!sw_init_done) {
if (ipq807x_switch_init(&ipq807x_edma_dev[i]->ops) == 0) {
sw_init_done = 1;
} else {
printf ("SW inits failed\n");
goto init_failed;
phy_chip_id1 = ipq_mdio_read(phy_id, QCA_PHY_ID1, NULL);
phy_chip_id2 = ipq_mdio_read(phy_id, QCA_PHY_ID2, NULL);
phy_chip_id = (phy_chip_id1 << 16) | phy_chip_id2;
switch(phy_chip_id) {
case QCA8075_PHY_V1_0_5P:
case QCA8075_PHY_V1_1_5P:
case QCA8075_PHY_V1_1_2P:
if (!sw_init_done) {
if (ipq_qca8075_phy_init(&ipq807x_edma_dev[i]->ops[phy_id]) == 0) {
sw_init_done = 1;
}
} else {
ipq_qca8075_phy_map_ops(&ipq807x_edma_dev[i]->ops[phy_id]);
}
break;
default:
ipq_qca8075_phy_map_ops(&ipq807x_edma_dev[i]->ops[phy_id]);
break;
}
}

View file

@ -251,6 +251,7 @@ struct ipq807x_edma_common_info {
struct ipq807x_edma_hw hw;
};
#define MAX_PHY 6
struct ipq807x_eth_dev {
u8 *phy_address;
uint no_of_phys;
@ -264,7 +265,7 @@ struct ipq807x_eth_dev {
u32 padding;
struct eth_device *dev;
struct ipq807x_edma_common_info *c_info;
struct phy_ops *ops;
struct phy_ops *ops[MAX_PHY];
const char phy_name[MDIO_NAME_LEN];
} __attribute__ ((aligned(8)));

View file

@ -32,6 +32,12 @@
#define GP_PU_RES(x) (x << 13)
#define QCA8075_RST_VAL (GP_PULL_DOWN | GP_OE_EN | \
GP_VM_EN | GP_PU_RES(2))
#define QCA8075_PHY_V1_0_5P 0x004DD0B0
#define QCA8075_PHY_V1_1_5P 0x004DD0B1
#define QCA8075_PHY_V1_1_2P 0x004DD0B2
#define QCA_PHY_ID1 0x2
#define QCA_PHY_ID2 0x3
/* Phy preferred medium type */
typedef enum {

View file

@ -25,6 +25,7 @@ extern int ipq_mdio_write(int mii_id,
extern int ipq_mdio_read(int mii_id,
int regnum, ushort *data);
struct phy_ops *qca8075_ops;
static u32 qca8075_id;
static u16 qca8075_phy_reg_write(u32 dev_id, u32 phy_id,
u32 reg_id, u16 reg_val)
@ -728,11 +729,15 @@ void ipq_qca8075_dump_phy_regs(u32 phy_id)
#undef REG_LEN
}
void ipq_qca8075_phy_map_ops(struct phy_ops **ops)
{
*ops = qca8075_ops;
}
int ipq_qca8075_phy_init(struct phy_ops **ops)
{
u16 phy_data;
u32 phy_id = 0;
struct phy_ops *qca8075_ops;
qca8075_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
if (!qca8075_ops)

View file

@ -14,10 +14,6 @@
#ifndef _QCA8075_PHY_H_
#define _QCA8075_PHY_H_
#define QCA8075_PHY_V1_0_5P 0x004DD0B0
#define QCA8075_PHY_V1_1_5P 0x004DD0B1
#define QCA8075_PHY_V1_1_2P 0x004DD0B2
#define QCA8075_PHY_CONTROL 0
#define QCA8075_PHY_STATUS 1
#define QCA8075_PHY_ID1 2