aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <loos@FreeBSD.org>2023-08-21 09:59:25 +0000
committerKristof Provost <kp@FreeBSD.org>2023-08-21 15:26:17 +0000
commit2c135a2aecdb979e34d651f33b2440372d7529d7 (patch)
tree5f723e0fd88a85fabee1f9a0646c1cd53c6fa41b
parentfeaae6ba1ace0091384ac371423976cd15e59e5a (diff)
downloadsrc-2c135a2aecdb979e34d651f33b2440372d7529d7.tar.gz
src-2c135a2aecdb979e34d651f33b2440372d7529d7.zip
e6000sw: support building without FDT
This enables the use of this driver on platorms without device tree, such as Netgate's XG-7100. Sponsored by: Rubicon Communications, LLC ("Netgate")
-rw-r--r--sys/dev/etherswitch/e6000sw/e6000sw.c103
1 files changed, 101 insertions, 2 deletions
diff --git a/sys/dev/etherswitch/e6000sw/e6000sw.c b/sys/dev/etherswitch/e6000sw/e6000sw.c
index a7deaf1baf0b..768d1b927e3e 100644
--- a/sys/dev/etherswitch/e6000sw/e6000sw.c
+++ b/sys/dev/etherswitch/e6000sw/e6000sw.c
@@ -27,6 +27,8 @@
*/
#include <sys/cdefs.h>
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/errno.h>
@@ -45,8 +47,12 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#ifdef FDT
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#else
+#include <machine/stdarg.h>
+#endif
#include "e6000swreg.h"
#include "etherswitch_if.h"
@@ -72,7 +78,9 @@ MALLOC_DEFINE(M_E6000SW, "e6000sw", "e6000sw switch");
typedef struct e6000sw_softc {
device_t dev;
+#ifdef FDT
phandle_t node;
+#endif
struct sx sx;
if_t ifp[E6000SW_MAX_PORTS];
@@ -102,8 +110,10 @@ static etherswitch_info_t etherswitch_info = {
static void e6000sw_identify(driver_t *, device_t);
static int e6000sw_probe(device_t);
+#ifdef FDT
static int e6000sw_parse_fixed_link(e6000sw_softc_t *, phandle_t, uint32_t);
static int e6000sw_parse_ethernet(e6000sw_softc_t *, phandle_t, uint32_t);
+#endif
static int e6000sw_attach(device_t);
static int e6000sw_detach(device_t);
static int e6000sw_read_xmdio(device_t, int, int, int);
@@ -202,9 +212,16 @@ e6000sw_probe(device_t dev)
{
e6000sw_softc_t *sc;
const char *description;
+#ifdef FDT
phandle_t switch_node;
+#else
+ int is_6190;
+#endif
sc = device_get_softc(dev);
+ sc->dev = dev;
+
+#ifdef FDT
switch_node = ofw_bus_find_compatible(OF_finddevice("/"),
"marvell,mv88e6085");
if (switch_node == 0) {
@@ -224,12 +241,26 @@ e6000sw_probe(device_t dev)
if (bootverbose)
device_printf(dev, "Found switch_node: 0x%x\n", switch_node);
- sc->dev = dev;
sc->node = switch_node;
if (OF_getencprop(sc->node, "reg", &sc->sw_addr,
sizeof(sc->sw_addr)) < 0)
return (ENXIO);
+#else
+ if (resource_int_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev), "addr", &sc->sw_addr) != 0)
+ return (ENXIO);
+ if (resource_int_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev), "is6190", &is_6190) != 0)
+ /*
+ * Check "is8190" to keep backward compatibility with
+ * older setups.
+ */
+ resource_int_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev), "is8190", &is_6190);
+ if (is_6190 != 0)
+ sc->swid = MV88E6190;
+#endif
if (sc->sw_addr < 0 || sc->sw_addr > 32)
return (ENXIO);
@@ -280,6 +311,7 @@ e6000sw_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
+#ifdef FDT
static int
e6000sw_parse_fixed_link(e6000sw_softc_t *sc, phandle_t node, uint32_t port)
{
@@ -355,6 +387,63 @@ e6000sw_parse_child_fdt(e6000sw_softc_t *sc, phandle_t child, int *pport)
return (0);
}
+#else
+
+static int
+e6000sw_check_hint_val(device_t dev, int *val, char *fmt, ...)
+{
+ char *resname;
+ int err, len;
+ va_list ap;
+
+ len = min(strlen(fmt) * 2, 128);
+ if (len == 0)
+ return (-1);
+ resname = malloc(len, M_E6000SW, M_WAITOK);
+ memset(resname, 0, len);
+ va_start(ap, fmt);
+ vsnprintf(resname, len - 1, fmt, ap);
+ va_end(ap);
+ err = resource_int_value(device_get_name(dev), device_get_unit(dev),
+ resname, val);
+ free(resname, M_E6000SW);
+
+ return (err);
+}
+
+static int
+e6000sw_parse_hinted_port(e6000sw_softc_t *sc, int port)
+{
+ int err, val;
+
+ err = e6000sw_check_hint_val(sc->dev, &val, "port%ddisabled", port);
+ if (err == 0 && val != 0)
+ return (1);
+
+ err = e6000sw_check_hint_val(sc->dev, &val, "port%dcpu", port);
+ if (err == 0 && val != 0) {
+ sc->cpuports_mask |= (1 << port);
+ sc->fixed_mask |= (1 << port);
+ if (bootverbose)
+ device_printf(sc->dev, "CPU port at %d\n", port);
+ }
+ err = e6000sw_check_hint_val(sc->dev, &val, "port%dspeed", port);
+ if (err == 0 && val != 0) {
+ sc->fixed_mask |= (1 << port);
+ if (val == 2500)
+ sc->fixed25_mask |= (1 << port);
+ }
+
+ if (bootverbose) {
+ if ((sc->fixed_mask & (1 << port)) != 0)
+ device_printf(sc->dev, "fixed port at %d\n", port);
+ else
+ device_printf(sc->dev, "PHY at port %d\n", port);
+ }
+
+ return (0);
+}
+#endif
static int
e6000sw_init_interface(e6000sw_softc_t *sc, int port)
@@ -425,7 +514,9 @@ e6000sw_attach(device_t dev)
{
bool sgmii;
e6000sw_softc_t *sc;
+#ifdef FDT
phandle_t child, ports;
+#endif
int err, port;
uint32_t reg;
@@ -447,7 +538,7 @@ e6000sw_attach(device_t dev)
E6000SW_LOCK(sc);
e6000sw_setup(dev, sc);
- ports = ofw_bus_find_child(sc->node, "ports");
+
sc->sc_tq = taskqueue_create("e6000sw_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->sc_tq);
@@ -455,6 +546,8 @@ e6000sw_attach(device_t dev)
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(dev));
+#ifdef FDT
+ ports = ofw_bus_find_child(sc->node, "ports");
if (ports == 0) {
device_printf(dev, "failed to parse DTS: no ports found for "
"switch\n");
@@ -468,6 +561,12 @@ e6000sw_attach(device_t dev)
device_printf(sc->dev, "failed to parse DTS\n");
goto out_fail;
}
+#else
+ for (port = 0; port < sc->num_ports; port++) {
+ err = e6000sw_parse_hinted_port(sc, port);
+ if (err != 0)
+ continue;
+#endif
/* Port is in use. */
sc->ports_mask |= (1 << port);