mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
drivers: net: add MDIO clause 45 support
Change-Id: Iba47a99967bed745083097a11a767062b26d21e3 Signed-off-by: Vandhiadevan Karunamoorthy <quic_vkarunam@quicinc.com>
This commit is contained in:
parent
0012c3f879
commit
1a4b370d2e
2 changed files with 229 additions and 6 deletions
|
|
@ -5,6 +5,8 @@
|
|||
* (C) Copyright 2001
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
|
||||
*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
|
|
@ -20,6 +22,17 @@
|
|||
|
||||
#define BB_MII_RELOCATE(v,off) (v += (v?off:0))
|
||||
|
||||
#define MDIO_READ 2
|
||||
#define MDIO_WRITE 1
|
||||
|
||||
#define MDIO_C45 (1<<15)
|
||||
#define MDIO_C45_ADDR (MDIO_C45 | 0)
|
||||
#define MDIO_C45_READ (MDIO_C45 | 3)
|
||||
#define MDIO_C45_WRITE (MDIO_C45 | 1)
|
||||
|
||||
#define MDIO_SETUP_TIME 10
|
||||
#define MDIO_HOLD_TIME 10
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_BITBANGMII_MULTI
|
||||
|
|
@ -150,8 +163,8 @@ static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname)
|
|||
* Utility to send the preamble, address, and register (common to read
|
||||
* and write).
|
||||
*/
|
||||
static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
|
||||
unsigned char addr, unsigned char reg)
|
||||
static void miiphy_pre(struct bb_miiphy_bus *bus, int read,
|
||||
unsigned int addr, unsigned int reg)
|
||||
{
|
||||
int j;
|
||||
|
||||
|
|
@ -172,24 +185,35 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
|
|||
bus->delay(bus);
|
||||
}
|
||||
|
||||
/* send the start bit (01) and the read opcode (10) or write (10) */
|
||||
/* send the start bit (01) and the read opcode (10) or write (10)
|
||||
* Clause 45 operation uses 00 for the start and 11, 10 for read/write
|
||||
*/
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, 0);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, 1);
|
||||
if (read & MDIO_C45)
|
||||
bus->set_mdio(bus, 0);
|
||||
else
|
||||
bus->set_mdio(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, read);
|
||||
if (read & MDIO_C45)
|
||||
bus->set_mdio(bus, ((read >> 1) & 1));
|
||||
else
|
||||
bus->set_mdio(bus, read);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, !read);
|
||||
if (read & MDIO_C45)
|
||||
bus->set_mdio(bus, ((read >> 0) & 1));
|
||||
else
|
||||
bus->set_mdio(bus, !read);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
|
|
@ -223,6 +247,135 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
|
|||
}
|
||||
}
|
||||
|
||||
static int bb_miiphy_cmd_addr(struct bb_miiphy_bus *bus, unsigned phy_addr,
|
||||
unsigned int reg_addr)
|
||||
{
|
||||
unsigned int dev_reg = (reg_addr >> 16) & 0x1F;
|
||||
unsigned int reg = reg_addr & 0xFFFF;
|
||||
int v, i;
|
||||
|
||||
miiphy_pre (bus, MDIO_C45_ADDR, phy_addr, dev_reg);
|
||||
|
||||
/* send the turnaround (10) */
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, 0);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
|
||||
for (i = 15; i >= 0; i--) {
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, ((reg >> i) & 1));
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
}
|
||||
|
||||
/* tri-state our MDIO I/O pin so we can read */
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->mdio_tristate(bus);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->get_mdio(bus, &v);
|
||||
bus->set_mdc(bus, 0);
|
||||
|
||||
return dev_reg;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Read a MII PHY register V2.
|
||||
* This API support C45 support
|
||||
* Returns:
|
||||
* 0 on success
|
||||
*/
|
||||
|
||||
|
||||
int bb_miiphy_read_v2(const char *devname, unsigned phy_addr,
|
||||
unsigned int reg, unsigned short *value)
|
||||
{
|
||||
short rdreg; /* register working value */
|
||||
int v;
|
||||
int j; /* counter */
|
||||
struct bb_miiphy_bus *bus;
|
||||
int phy_reg;
|
||||
|
||||
bus = bb_miiphy_getbus(devname);
|
||||
if (bus == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value == NULL) {
|
||||
puts("NULL value pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (reg & MII_ADDR_C45) {
|
||||
phy_reg = bb_miiphy_cmd_addr(bus, phy_addr, reg);
|
||||
miiphy_pre(bus, MDIO_C45_READ, phy_addr, phy_reg);
|
||||
} else {
|
||||
miiphy_pre(bus, 1, phy_addr, reg);
|
||||
}
|
||||
|
||||
/* tri-state our MDIO I/O pin so we can read */
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->mdio_tristate(bus);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
|
||||
/* check the turnaround bit: the PHY should be driving it to zero */
|
||||
bus->get_mdio(bus, &v);
|
||||
if (v != 0) {
|
||||
/* puts ("PHY didn't drive TA low\n"); */
|
||||
for (j = 0; j < 32; j++) {
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
}
|
||||
/* There is no PHY, set value to 0xFFFF and return */
|
||||
*value = 0xFFFF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->delay(bus);
|
||||
|
||||
/* read 16 bits of register data, MSB first */
|
||||
rdreg = 0;
|
||||
for (j = 0; j < 16; j++) {
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
rdreg <<= 1;
|
||||
bus->get_mdio(bus, &v);
|
||||
rdreg |= (v & 0x1);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->delay(bus);
|
||||
}
|
||||
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
|
||||
*value = rdreg;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("miiphy_read_v2(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Read a MII PHY register.
|
||||
|
|
@ -304,6 +457,71 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
|
|||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Write a MII PHY register V2.
|
||||
* This API support C45 support
|
||||
* Returns:
|
||||
* 0 on success
|
||||
*/
|
||||
int bb_miiphy_write_v2(const char *devname, unsigned int phy_addr,
|
||||
unsigned int reg, unsigned short value)
|
||||
{
|
||||
struct bb_miiphy_bus *bus;
|
||||
int j; /* counter */
|
||||
unsigned int phy_reg;
|
||||
|
||||
bus = bb_miiphy_getbus(devname);
|
||||
if (bus == NULL) {
|
||||
/* Bus not found! */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (reg & MII_ADDR_C45) {
|
||||
phy_reg = bb_miiphy_cmd_addr(bus, phy_addr, reg);
|
||||
miiphy_pre(bus, MDIO_C45_WRITE, phy_addr, phy_reg);
|
||||
} else {
|
||||
miiphy_pre(bus, 0, phy_addr, reg);
|
||||
}
|
||||
|
||||
/* send the turnaround (10) */
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->set_mdio(bus, 0);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
|
||||
/* write 16 bits of register data, MSB first */
|
||||
for (j = 0; j < 16; j++) {
|
||||
bus->set_mdc(bus, 0);
|
||||
if ((value & 0x00008000) == 0) {
|
||||
bus->set_mdio(bus, 0);
|
||||
} else {
|
||||
bus->set_mdio(bus, 1);
|
||||
}
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
value <<= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tri-state the MDIO line.
|
||||
*/
|
||||
bus->mdio_tristate(bus);
|
||||
bus->set_mdc(bus, 0);
|
||||
bus->delay(bus);
|
||||
bus->set_mdc(bus, 1);
|
||||
bus->delay(bus);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Write a MII PHY register.
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
|
|||
unsigned char reg, unsigned short *value);
|
||||
int bb_miiphy_write(const char *devname, unsigned char addr,
|
||||
unsigned char reg, unsigned short value);
|
||||
int bb_miiphy_read_v2(const char *devname, unsigned int addr,
|
||||
unsigned int reg, unsigned short *value);
|
||||
int bb_miiphy_write_v2(const char *devname, unsigned int addr,
|
||||
unsigned int reg, unsigned short value);
|
||||
|
||||
#endif
|
||||
|
||||
/* phy seed setup */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue