blob: d7968d4fb7639692dac159fd24d696863dc1fc1b [file] [log] [blame]
/*
* Copyright (c) 2015-2017, The Linux Foundation. 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 <net.h>
#include <asm-generic/errno.h>
#include <asm/io.h>
#include <malloc.h>
#include <phy.h>
#include "ipq_qca8033.h"
#include "ipq_phy.h"
extern int ipq_mdio_write(int mii_id,
int regnum, u16 value);
extern int ipq_mdio_read(int mii_id,
int regnum, ushort *data);
static u16 qca8033_phy_reg_write(u32 dev_id, u32 phy_id,
u32 reg_id, u16 reg_val)
{
ipq_mdio_write(phy_id, reg_id, reg_val);
return 0;
}
u16 qca8033_phy_reg_read(u32 dev_id, u32 phy_id, u32 reg_id)
{
return ipq_mdio_read(phy_id, reg_id, NULL);
}
u8 qca8033_phy_get_link_status(u32 dev_id, u32 phy_id)
{
u16 phy_data;
phy_data = qca8033_phy_reg_read(dev_id,
phy_id, QCA8033_PHY_SPEC_STATUS);
if (phy_data & QCA8033_STATUS_LINK_PASS)
return 0;
return 1;
}
u32 qca8033_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex)
{
u16 phy_data;
phy_data = qca8033_phy_reg_read(dev_id, phy_id,
QCA8033_PHY_SPEC_STATUS);
/*
* Read duplex
*/
if (phy_data & QCA8033_STATUS_FULL_DUPLEX)
*duplex = FAL_FULL_DUPLEX;
else
*duplex = FAL_HALF_DUPLEX;
return 0;
}
u32 qca8033_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed)
{
u16 phy_data;
phy_data = qca8033_phy_reg_read(dev_id,
phy_id, QCA8033_PHY_SPEC_STATUS);
switch (phy_data & QCA8033_STATUS_SPEED_MASK) {
case QCA8033_STATUS_SPEED_1000MBS:
*speed = FAL_SPEED_1000;
break;
case QCA8033_STATUS_SPEED_100MBS:
*speed = FAL_SPEED_100;
break;
case QCA8033_STATUS_SPEED_10MBS:
*speed = FAL_SPEED_10;
break;
default:
return -EINVAL;
}
return 0;
}
int ipq_qca8033_phy_init(struct phy_ops **ops, u32 phy_id)
{
u16 phy_data;
struct phy_ops *qca8033_ops;
qca8033_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
if (!qca8033_ops)
return -ENOMEM;
qca8033_ops->phy_get_link_status = qca8033_phy_get_link_status;
qca8033_ops->phy_get_speed = qca8033_phy_get_speed;
qca8033_ops->phy_get_duplex = qca8033_phy_get_duplex;
*ops = qca8033_ops;
phy_data = qca8033_phy_reg_read(0x0, phy_id, QCA8033_PHY_ID1);
printf ("PHY ID1: 0x%x\n", phy_data);
phy_data = qca8033_phy_reg_read(0x0, phy_id, QCA8033_PHY_ID2);
printf ("PHY ID2: 0x%x\n", phy_data);
qca8033_phy_reg_write(0x0, phy_id, 0x1d, 0x5);
qca8033_phy_reg_write(0x0, phy_id, 0x1e, 0x2d47);
qca8033_phy_reg_write(0x0, phy_id, 0x1d, 0xb);
qca8033_phy_reg_write(0x0, phy_id, 0x1e, 0xbc40);
qca8033_phy_reg_write(0x0, phy_id, 0x1d, 0x0);
qca8033_phy_reg_write(0x0, phy_id, 0x1e, 0x82ee);
return 0;
}