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:
parent
1c7792950c
commit
aa15e881bb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=232518
@ -221,6 +221,9 @@
|
|||||||
phy0: ethernet-phy@0 {
|
phy0: ethernet-phy@0 {
|
||||||
reg = <0x8>;
|
reg = <0x8>;
|
||||||
};
|
};
|
||||||
|
phy1: ethernet-phy@1 {
|
||||||
|
reg = <0x9>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -234,17 +237,7 @@
|
|||||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||||
interrupts = <45 46 47 44 70>;
|
interrupts = <45 46 47 44 70>;
|
||||||
interrupt-parent = <&PIC>;
|
interrupt-parent = <&PIC>;
|
||||||
phy-handle = <&phy0>;
|
phy-handle = <&phy1>;
|
||||||
|
|
||||||
mdio@0 {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
compatible = "mrvl,mdio";
|
|
||||||
|
|
||||||
phy0: ethernet-phy@0 {
|
|
||||||
reg = <0x9>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
serial0: serial@12000 {
|
serial0: serial@12000 {
|
||||||
|
@ -542,11 +542,13 @@ fdt_intr_to_rl(phandle_t node, struct resource_list *rl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
phandle_t phy_node;
|
||||||
ihandle_t phy_ihandle;
|
ihandle_t phy_ihandle;
|
||||||
pcell_t phy_handle, phy_reg;
|
pcell_t phy_handle, phy_reg;
|
||||||
|
uint32_t i;
|
||||||
|
device_t parent, child;
|
||||||
|
|
||||||
if (OF_getprop(node, "phy-handle", (void *)&phy_handle,
|
if (OF_getprop(node, "phy-handle", (void *)&phy_handle,
|
||||||
sizeof(phy_handle)) <= 0)
|
sizeof(phy_handle)) <= 0)
|
||||||
@ -561,6 +563,47 @@ fdt_get_phyaddr(phandle_t node, int *phy_addr)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
*phy_addr = fdt32_to_cpu(phy_reg);
|
*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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *);
|
|||||||
int fdt_data_verify(void *, int);
|
int fdt_data_verify(void *, int);
|
||||||
phandle_t fdt_find_compatible(phandle_t, const char *, 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_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_immr_addr(vm_offset_t);
|
||||||
int fdt_regsize(phandle_t, u_long *, u_long *);
|
int fdt_regsize(phandle_t, u_long *, u_long *);
|
||||||
int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
|
int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
|
||||||
|
@ -79,9 +79,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "miibus_if.h"
|
#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_probe(device_t dev);
|
||||||
static int mge_attach(device_t dev);
|
static int mge_attach(device_t dev);
|
||||||
static int mge_detach(device_t dev);
|
static int mge_detach(device_t dev);
|
||||||
@ -635,14 +632,11 @@ mge_attach(device_t dev)
|
|||||||
sc->dev = dev;
|
sc->dev = dev;
|
||||||
sc->node = ofw_bus_get_node(dev);
|
sc->node = ofw_bus_get_node(dev);
|
||||||
|
|
||||||
if (device_get_unit(dev) == 0)
|
|
||||||
sc_mge0 = sc;
|
|
||||||
|
|
||||||
/* Set chip version-dependent parameters */
|
/* Set chip version-dependent parameters */
|
||||||
mge_ver_params(sc);
|
mge_ver_params(sc);
|
||||||
|
|
||||||
/* Get phy address from fdt */
|
/* Get phy address and used softc from fdt */
|
||||||
if (fdt_get_phyaddr(sc->node, &phy) != 0)
|
if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) != 0)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
/* Initialize mutexes */
|
/* Initialize mutexes */
|
||||||
@ -1294,17 +1288,18 @@ mge_miibus_readreg(device_t dev, int phy, int reg)
|
|||||||
|
|
||||||
sc = device_get_softc(dev);
|
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)));
|
(MGE_SMI_READ | (reg << 21) | (phy << 16)));
|
||||||
|
|
||||||
retries = MGE_SMI_READ_RETRIES;
|
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);
|
DELAY(MGE_SMI_READ_DELAY);
|
||||||
|
|
||||||
if (retries == 0)
|
if (retries == 0)
|
||||||
device_printf(dev, "Timeout while reading from PHY\n");
|
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
|
static int
|
||||||
@ -1315,11 +1310,11 @@ mge_miibus_writereg(device_t dev, int phy, int reg, int value)
|
|||||||
|
|
||||||
sc = device_get_softc(dev);
|
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)));
|
(MGE_SMI_WRITE | (reg << 21) | (phy << 16) | (value & 0xffff)));
|
||||||
|
|
||||||
retries = MGE_SMI_WRITE_RETRIES;
|
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);
|
DELAY(MGE_SMI_WRITE_DELAY);
|
||||||
|
|
||||||
if (retries == 0)
|
if (retries == 0)
|
||||||
|
@ -103,6 +103,8 @@ struct mge_softc {
|
|||||||
uint32_t mge_tx_tok_cnt;
|
uint32_t mge_tx_tok_cnt;
|
||||||
uint16_t mge_mtu;
|
uint16_t mge_mtu;
|
||||||
int mge_ver;
|
int mge_ver;
|
||||||
|
|
||||||
|
struct mge_softc *phy_sc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,8 +106,6 @@ static void tsec_offload_process_frame(struct tsec_softc *sc,
|
|||||||
static void tsec_setup_multicast(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);
|
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;
|
devclass_t tsec_devclass;
|
||||||
DRIVER_MODULE(miibus, tsec, miibus_driver, miibus_devclass, 0, 0);
|
DRIVER_MODULE(miibus, tsec, miibus_driver, miibus_devclass, 0, 0);
|
||||||
MODULE_DEPEND(tsec, ether, 1, 1, 1);
|
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);
|
TSEC_WRITE(sc, TSEC_REG_TBIPA, 5);
|
||||||
|
|
||||||
/* Step 6: Reset the management interface */
|
/* 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 */
|
/* 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 */
|
/* Step 8: Read MII Mgmt indicator register and check for Busy = 0 */
|
||||||
timeout = TSEC_READ_RETRY;
|
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))
|
TSEC_MIIMIND_BUSY))
|
||||||
DELAY(TSEC_READ_DELAY);
|
DELAY(TSEC_READ_DELAY);
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
@ -1561,21 +1559,21 @@ tsec_miibus_readreg(device_t dev, int phy, int reg)
|
|||||||
struct tsec_softc *sc;
|
struct tsec_softc *sc;
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
|
|
||||||
sc = tsec0_sc;
|
sc = device_get_softc(dev);
|
||||||
|
|
||||||
TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
|
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
|
||||||
TSEC_WRITE(sc, TSEC_REG_MIIMCOM, 0);
|
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, 0);
|
||||||
TSEC_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
|
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
|
||||||
|
|
||||||
timeout = TSEC_READ_RETRY;
|
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))
|
(TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY))
|
||||||
DELAY(TSEC_READ_DELAY);
|
DELAY(TSEC_READ_DELAY);
|
||||||
|
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
device_printf(dev, "Timeout while reading from PHY!\n");
|
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
|
int
|
||||||
@ -1584,13 +1582,13 @@ tsec_miibus_writereg(device_t dev, int phy, int reg, int value)
|
|||||||
struct tsec_softc *sc;
|
struct tsec_softc *sc;
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
|
|
||||||
sc = tsec0_sc;
|
sc = device_get_softc(dev);
|
||||||
|
|
||||||
TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
|
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
|
||||||
TSEC_WRITE(sc, TSEC_REG_MIIMCON, value);
|
TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCON, value);
|
||||||
|
|
||||||
timeout = TSEC_READ_RETRY;
|
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))
|
TSEC_MIIMIND_BUSY))
|
||||||
DELAY(TSEC_READ_DELAY);
|
DELAY(TSEC_READ_DELAY);
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ struct tsec_softc {
|
|||||||
struct mbuf *frame;
|
struct mbuf *frame;
|
||||||
|
|
||||||
int phyaddr;
|
int phyaddr;
|
||||||
|
struct tsec_softc *phy_sc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* interface to get/put generic objects */
|
/* interface to get/put generic objects */
|
||||||
|
@ -68,8 +68,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#define TSEC_RID_RXIRQ 1
|
#define TSEC_RID_RXIRQ 1
|
||||||
#define TSEC_RID_ERRIRQ 2
|
#define TSEC_RID_ERRIRQ 2
|
||||||
|
|
||||||
extern struct tsec_softc *tsec0_sc;
|
|
||||||
|
|
||||||
static int tsec_fdt_probe(device_t dev);
|
static int tsec_fdt_probe(device_t dev);
|
||||||
static int tsec_fdt_attach(device_t dev);
|
static int tsec_fdt_attach(device_t dev);
|
||||||
static int tsec_fdt_detach(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->dev = dev;
|
||||||
sc->node = ofw_bus_get_node(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 */
|
/* 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);
|
return (ENXIO);
|
||||||
|
|
||||||
/* Init timer */
|
/* Init timer */
|
||||||
|
Loading…
Reference in New Issue
Block a user