Date: Thu, 4 Aug 2016 17:45:36 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r303751 - in head/sys/dev/etherswitch: . arswitch Message-ID: <201608041745.u74HjaHA036188@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Thu Aug 4 17:45:35 2016 New Revision: 303751 URL: https://svnweb.freebsd.org/changeset/base/303751 Log: [etherswitch] add in an initial API for controlling per-port LED behaviour. This is just implemented for the AR8327 for now. Submitted by: Dan Nelson <dnelson_1901@yahoo.com> Modified: head/sys/dev/etherswitch/arswitch/arswitch.c head/sys/dev/etherswitch/arswitch/arswitch_8327.c head/sys/dev/etherswitch/arswitch/arswitch_8327.h head/sys/dev/etherswitch/arswitch/arswitchvar.h head/sys/dev/etherswitch/etherswitch.h Modified: head/sys/dev/etherswitch/arswitch/arswitch.c ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch.c Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitch.c Thu Aug 4 17:45:35 2016 (r303751) @@ -77,6 +77,14 @@ static SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch"); #endif +/* Map ETHERSWITCH_PORT_LED_* to Atheros pattern codes */ +static int led_pattern_table[] = { + [ETHERSWITCH_PORT_LED_DEFAULT] = 0x3, + [ETHERSWITCH_PORT_LED_ON] = 0x2, + [ETHERSWITCH_PORT_LED_OFF] = 0x0, + [ETHERSWITCH_PORT_LED_BLINK] = 0x1 +}; + static inline int arswitch_portforphy(int phy); static void arswitch_tick(void *arg); static int arswitch_ifmedia_upd(struct ifnet *); @@ -85,6 +93,8 @@ static int ar8xxx_port_vlan_setup(struct etherswitch_port_t *p); static int ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p); +static int arswitch_setled(struct arswitch_softc *sc, int phy, int led, + int style); static int arswitch_probe(device_t dev) @@ -188,9 +198,23 @@ arswitch_attach_phys(struct arswitch_sof device_printf(sc->sc_dev, "attaching PHY %d failed\n", phy); + return (err); + } + + if (AR8X16_IS_SWITCH(sc, AR8327)) { + int led; + char ledname[IFNAMSIZ+4]; + + for (led = 0; led < 3; led++) { + sprintf(ledname, "%s%dled%d", name, + arswitch_portforphy(phy), led+1); + sc->dev_led[phy][led].sc = sc; + sc->dev_led[phy][led].phy = phy; + sc->dev_led[phy][led].lednum = led; + } } } - return (err); + return (0); } static int @@ -683,6 +707,38 @@ arswitch_getport(device_t dev, etherswit } else { return (ENXIO); } + + if (!arswitch_is_cpuport(sc, p->es_port) && + AR8X16_IS_SWITCH(sc, AR8327)) { + int led; + p->es_nleds = 3; + + for (led = 0; led < p->es_nleds; led++) + { + int style; + uint32_t val; + + /* Find the right style enum for our pattern */ + val = arswitch_readreg(dev, + ar8327_led_mapping[p->es_port-1][led].reg); + val = (val>>ar8327_led_mapping[p->es_port-1][led].shift)&0x03; + + for (style = 0; style < ETHERSWITCH_PORT_LED_MAX; style++) + { + if (led_pattern_table[style] == val) break; + } + + /* can't happen */ + if (style == ETHERSWITCH_PORT_LED_MAX) + style = ETHERSWITCH_PORT_LED_DEFAULT; + + p->es_led[led] = style; + } + } else + { + p->es_nleds = 0; + } + return (0); } @@ -727,7 +783,7 @@ ar8xxx_port_vlan_setup(struct arswitch_s static int arswitch_setport(device_t dev, etherswitch_port_t *p) { - int err; + int err, i; struct arswitch_softc *sc; struct ifmedia *ifm; struct mii_data *mii; @@ -744,9 +800,20 @@ arswitch_setport(device_t dev, etherswit return (err); } - /* Do not allow media changes on CPU port. */ + /* Do not allow media or led changes on CPU port. */ if (arswitch_is_cpuport(sc, p->es_port)) return (0); + + if (AR8X16_IS_SWITCH(sc, AR8327)) + { + for (i = 0; i < 3; i++) + { + int err; + err = arswitch_setled(sc, p->es_port-1, i, p->es_led[i]); + if (err) + return (err); + } + } mii = arswitch_miiforport(sc, p->es_port); if (mii == NULL) @@ -758,6 +825,23 @@ arswitch_setport(device_t dev, etherswit return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA)); } +static int +arswitch_setled(struct arswitch_softc *sc, int phy, int led, int style) +{ + int shift; + + if (phy < 0 || phy > sc->numphys) + return EINVAL; + + if (style < 0 || style > ETHERSWITCH_PORT_LED_MAX) + return (EINVAL); + + shift = ar8327_led_mapping[phy][led].shift; + return (arswitch_modifyreg(sc->sc_dev, + ar8327_led_mapping[phy][led].reg, + 0x03 << shift, led_pattern_table[style] << shift)); +} + static void arswitch_statchg(device_t dev) { Modified: head/sys/dev/etherswitch/arswitch/arswitch_8327.c ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch_8327.c Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitch_8327.c Thu Aug 4 17:45:35 2016 (r303751) @@ -75,6 +75,36 @@ * lead to traffic storms/loops. */ +/* Map port+led to register+shift */ +struct ar8327_led_mapping ar8327_led_mapping[AR8327_NUM_PHYS][ETHERSWITCH_PORT_MAX_LEDS] = +{ + { /* PHY0 */ + {AR8327_REG_LED_CTRL0, 14 }, + {AR8327_REG_LED_CTRL1, 14 }, + {AR8327_REG_LED_CTRL2, 14 } + }, + { /* PHY1 */ + {AR8327_REG_LED_CTRL3, 8 }, + {AR8327_REG_LED_CTRL3, 10 }, + {AR8327_REG_LED_CTRL3, 12 } + }, + { /* PHY2 */ + {AR8327_REG_LED_CTRL3, 14 }, + {AR8327_REG_LED_CTRL3, 16 }, + {AR8327_REG_LED_CTRL3, 18 } + }, + { /* PHY3 */ + {AR8327_REG_LED_CTRL3, 20 }, + {AR8327_REG_LED_CTRL3, 22 }, + {AR8327_REG_LED_CTRL3, 24 } + }, + { /* PHY4 */ + {AR8327_REG_LED_CTRL0, 30 }, + {AR8327_REG_LED_CTRL1, 30 }, + {AR8327_REG_LED_CTRL2, 30 } + } +}; + static int ar8327_vlan_op(struct arswitch_softc *sc, uint32_t op, uint32_t vid, uint32_t data) Modified: head/sys/dev/etherswitch/arswitch/arswitch_8327.h ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitch_8327.h Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitch_8327.h Thu Aug 4 17:45:35 2016 (r303751) @@ -85,6 +85,11 @@ struct ar8327_port_cfg { uint32_t rxpause; }; +extern struct ar8327_led_mapping { + int reg; + int shift; +} ar8327_led_mapping[AR8327_NUM_PHYS][ETHERSWITCH_PORT_MAX_LEDS]; + extern void ar8327_attach(struct arswitch_softc *sc); #endif /* __ARSWITCH_8327_H__ */ Modified: head/sys/dev/etherswitch/arswitch/arswitchvar.h ============================================================================== --- head/sys/dev/etherswitch/arswitch/arswitchvar.h Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/arswitch/arswitchvar.h Thu Aug 4 17:45:35 2016 (r303751) @@ -48,6 +48,15 @@ typedef enum { #define ARSWITCH_NUM_PORTS MAX(AR8327_NUM_PORTS, AR8X16_NUM_PORTS) #define ARSWITCH_NUM_PHYS MAX(AR8327_NUM_PHYS, AR8X16_NUM_PHYS) +#define ARSWITCH_NUM_LEDS 3 + +struct arswitch_dev_led { + struct arswitch_softc *sc; + struct cdev *led; + int phy; + int lednum; +}; + struct arswitch_softc { struct mtx sc_mtx; /* serialize access to softc */ device_t sc_dev; @@ -66,6 +75,7 @@ struct arswitch_softc { char *ifname[ARSWITCH_NUM_PHYS]; device_t miibus[ARSWITCH_NUM_PHYS]; struct ifnet *ifp[ARSWITCH_NUM_PHYS]; + struct arswitch_dev_led dev_led[ARSWITCH_NUM_PHYS][ARSWITCH_NUM_LEDS]; struct callout callout_tick; etherswitch_info_t info; Modified: head/sys/dev/etherswitch/etherswitch.h ============================================================================== --- head/sys/dev/etherswitch/etherswitch.h Thu Aug 4 17:29:42 2016 (r303750) +++ head/sys/dev/etherswitch/etherswitch.h Thu Aug 4 17:45:35 2016 (r303751) @@ -14,7 +14,7 @@ extern driver_t etherswitch_driv struct etherswitch_reg { uint16_t reg; - uint16_t val; + uint32_t val; }; typedef struct etherswitch_reg etherswitch_reg_t; @@ -64,10 +64,23 @@ typedef struct etherswitch_conf etherswi #define ETHERSWITCH_PORT_FLAGS_BITS \ "\020\1CPUPORT\2STRIPTAG\3ADDTAG\4FIRSTLOCK\5DROPUNTAGGED\6QinQ\7INGRESS" +#define ETHERSWITCH_PORT_MAX_LEDS 3 + +enum etherswitch_port_led { + ETHERSWITCH_PORT_LED_DEFAULT, + ETHERSWITCH_PORT_LED_ON, + ETHERSWITCH_PORT_LED_OFF, + ETHERSWITCH_PORT_LED_BLINK, + ETHERSWITCH_PORT_LED_MAX +}; +typedef enum etherswitch_port_led etherswitch_port_led_t; + struct etherswitch_port { int es_port; int es_pvid; + int es_nleds; uint32_t es_flags; + etherswitch_port_led_t es_led[ETHERSWITCH_PORT_MAX_LEDS]; union { struct ifreq es_uifr; struct ifmediareq es_uifmr;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608041745.u74HjaHA036188>