Respect phy-handle property in Ethernet nodes of the device tree.

This lets specify whereabouts of the parent PHY for a given MAC node
(and get rid of ugly kludges in mge(4) and tsec(4)).

Obtained from:	Semihalf
MFC after:	1 week
This commit is contained in:
Rafal Jaworowski 2012-03-04 19:22:52 +00:00
parent 1c7792950c
commit aa15e881bb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232518
8 changed files with 75 additions and 48 deletions

View File

@ -221,6 +221,9 @@
phy0: ethernet-phy@0 {
reg = <0x8>;
};
phy1: ethernet-phy@1 {
reg = <0x9>;
};
};
};
@ -234,17 +237,7 @@
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <45 46 47 44 70>;
interrupt-parent = <&PIC>;
phy-handle = <&phy0>;
mdio@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "mrvl,mdio";
phy0: ethernet-phy@0 {
reg = <0x9>;
};
};
phy-handle = <&phy1>;
};
serial0: serial@12000 {

View File

@ -542,11 +542,13 @@ fdt_intr_to_rl(phandle_t node, struct resource_list *rl,
}
int
fdt_get_phyaddr(phandle_t node, int *phy_addr)
fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
{
phandle_t phy_node;
ihandle_t phy_ihandle;
pcell_t phy_handle, phy_reg;
uint32_t i;
device_t parent, child;
if (OF_getprop(node, "phy-handle", (void *)&phy_handle,
sizeof(phy_handle)) <= 0)
@ -561,6 +563,47 @@ fdt_get_phyaddr(phandle_t node, int *phy_addr)
return (ENXIO);
*phy_addr = fdt32_to_cpu(phy_reg);
/*
* Search for softc used to communicate with phy.
*/
/*
* Step 1: Search for ancestor of the phy-node with a "phy-handle"
* property set.
*/
phy_node = OF_parent(phy_node);
while (phy_node != 0) {
if (OF_getprop(phy_node, "phy-handle", (void *)&phy_handle,
sizeof(phy_handle)) > 0)
break;
phy_node = OF_parent(phy_node);
}
if (phy_node == 0)
return (ENXIO);
/*
* Step 2: For each device with the same parent and name as ours
* compare its node with the one found in step 1, ancestor of phy
* node (stored in phy_node).
*/
parent = device_get_parent(dev);
i = 0;
child = device_find_child(parent, device_get_name(dev), i);
while (child != NULL) {
if (ofw_bus_get_node(child) == phy_node)
break;
i++;
child = device_find_child(parent, device_get_name(dev), i);
}
if (child == NULL)
return (ENXIO);
/*
* Use softc of the device found.
*/
*phy_sc = (void *)device_get_softc(child);
return (0);
}

View File

@ -89,7 +89,7 @@ int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *);
int fdt_data_verify(void *, int);
phandle_t fdt_find_compatible(phandle_t, const char *, int);
int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
int fdt_get_phyaddr(phandle_t node, int *);
int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
int fdt_immr_addr(vm_offset_t);
int fdt_regsize(phandle_t, u_long *, u_long *);
int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);

View File

@ -79,9 +79,6 @@ __FBSDID("$FreeBSD$");
#include "miibus_if.h"
/* PHY registers are in the address space of the first mge unit */
static struct mge_softc *sc_mge0 = NULL;
static int mge_probe(device_t dev);
static int mge_attach(device_t dev);
static int mge_detach(device_t dev);
@ -635,14 +632,11 @@ mge_attach(device_t dev)
sc->dev = dev;
sc->node = ofw_bus_get_node(dev);
if (device_get_unit(dev) == 0)
sc_mge0 = sc;
/* Set chip version-dependent parameters */
mge_ver_params(sc);
/* Get phy address from fdt */
if (fdt_get_phyaddr(sc->node, &phy) != 0)
/* Get phy address and used softc from fdt */
if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) != 0)
return (ENXIO);
/* Initialize mutexes */
@ -1294,17 +1288,18 @@ mge_miibus_readreg(device_t dev, int phy, int reg)
sc = device_get_softc(dev);
MGE_WRITE(sc_mge0, MGE_REG_SMI, 0x1fffffff &
MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff &
(MGE_SMI_READ | (reg << 21) | (phy << 16)));
retries = MGE_SMI_READ_RETRIES;
while (--retries && !(MGE_READ(sc_mge0, MGE_REG_SMI) & MGE_SMI_READVALID))
while (--retries &&
!(MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_READVALID))
DELAY(MGE_SMI_READ_DELAY);
if (retries == 0)
device_printf(dev, "Timeout while reading from PHY\n");
return (MGE_READ(sc_mge0, MGE_REG_SMI) & 0xffff);
return (MGE_READ(sc->phy_sc, MGE_REG_SMI) & 0xffff);
}
static int
@ -1315,11 +1310,11 @@ mge_miibus_writereg(device_t dev, int phy, int reg, int value)
sc = device_get_softc(dev);
MGE_WRITE(sc_mge0, MGE_REG_SMI, 0x1fffffff &
MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff &
(MGE_SMI_WRITE | (reg << 21) | (phy << 16) | (value & 0xffff)));
retries = MGE_SMI_WRITE_RETRIES;
while (--retries && MGE_READ(sc_mge0, MGE_REG_SMI) & MGE_SMI_BUSY)
while (--retries && MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_BUSY)
DELAY(MGE_SMI_WRITE_DELAY);
if (retries == 0)

View File

@ -103,6 +103,8 @@ struct mge_softc {
uint32_t mge_tx_tok_cnt;
uint16_t mge_mtu;
int mge_ver;
struct mge_softc *phy_sc;
};

View File

@ -106,8 +106,6 @@ static void tsec_offload_process_frame(struct tsec_softc *sc,
static void tsec_setup_multicast(struct tsec_softc *sc);
static int tsec_set_mtu(struct tsec_softc *sc, unsigned int mtu);
struct tsec_softc *tsec0_sc = NULL; /* XXX ugly hack! */
devclass_t tsec_devclass;
DRIVER_MODULE(miibus, tsec, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(tsec, ether, 1, 1, 1);
@ -406,14 +404,14 @@ tsec_init_locked(struct tsec_softc *sc)
TSEC_WRITE(sc, TSEC_REG_TBIPA, 5);
/* Step 6: Reset the management interface */
TSEC_WRITE(tsec0_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
/* Step 7: Setup the MII Mgmt clock speed */
TSEC_WRITE(tsec0_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
/* Step 8: Read MII Mgmt indicator register and check for Busy = 0 */
timeout = TSEC_READ_RETRY;
while (--timeout && (TSEC_READ(tsec0_sc, TSEC_REG_MIIMIND) &
while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
if (timeout == 0) {
@ -1561,21 +1559,21 @@ tsec_miibus_readreg(device_t dev, int phy, int reg)
struct tsec_softc *sc;
uint32_t timeout;
sc = tsec0_sc;
sc = device_get_softc(dev);
TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
TSEC_WRITE(sc, TSEC_REG_MIIMCOM, 0);
TSEC_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, 0);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
timeout = TSEC_READ_RETRY;
while (--timeout && TSEC_READ(sc, TSEC_REG_MIIMIND) &
while (--timeout && TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
(TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
if (timeout == 0)
device_printf(dev, "Timeout while reading from PHY!\n");
return (TSEC_READ(sc, TSEC_REG_MIIMSTAT));
return (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMSTAT));
}
int
@ -1584,13 +1582,13 @@ tsec_miibus_writereg(device_t dev, int phy, int reg, int value)
struct tsec_softc *sc;
uint32_t timeout;
sc = tsec0_sc;
sc = device_get_softc(dev);
TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
TSEC_WRITE(sc, TSEC_REG_MIIMCON, value);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCON, value);
timeout = TSEC_READ_RETRY;
while (--timeout && (TSEC_READ(sc, TSEC_REG_MIIMIND) &
while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);

View File

@ -133,6 +133,7 @@ struct tsec_softc {
struct mbuf *frame;
int phyaddr;
struct tsec_softc *phy_sc;
};
/* interface to get/put generic objects */

View File

@ -68,8 +68,6 @@ __FBSDID("$FreeBSD$");
#define TSEC_RID_RXIRQ 1
#define TSEC_RID_ERRIRQ 2
extern struct tsec_softc *tsec0_sc;
static int tsec_fdt_probe(device_t dev);
static int tsec_fdt_attach(device_t dev);
static int tsec_fdt_detach(device_t dev);
@ -156,12 +154,9 @@ tsec_fdt_attach(device_t dev)
sc->dev = dev;
sc->node = ofw_bus_get_node(dev);
/* XXX add comment on weird FSL's MII registers access design */
if (device_get_unit(dev) == 0)
tsec0_sc = sc;
/* Get phy address from fdt */
if (fdt_get_phyaddr(sc->node, &sc->phyaddr) != 0)
if (fdt_get_phyaddr(sc->node, sc->dev, &sc->phyaddr,
(void **)&sc->phy_sc) != 0)
return (ENXIO);
/* Init timer */