From 6c40999ef70be26cc633e9dc0ff8c3c95401849a Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 18 Nov 2006 04:13:39 +0000 Subject: [PATCH] Properly setup Link/Act LED for rt2x61 chips. LED EEPROM configures and LED MCU data/command layout are obtained from Linux RT61 driver (the reference driver?). # This makes my Edimax EW-7608PG(rt2661d) LED shining as expected. --- sys/dev/netif/ral/rt2661.c | 85 ++++++++++++++++++++++++++++++++++++++++++- sys/dev/netif/ral/rt2661reg.h | 31 +++++++++++++++- sys/dev/netif/ral/rt2661var.h | 3 +- 3 files changed, 115 insertions(+), 4 deletions(-) diff --git a/sys/dev/netif/ral/rt2661.c b/sys/dev/netif/ral/rt2661.c index a4b30b5157..a50765edda 100644 --- a/sys/dev/netif/ral/rt2661.c +++ b/sys/dev/netif/ral/rt2661.c @@ -15,7 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD: src/sys/dev/ral/rt2661.c,v 1.4 2006/03/21 21:15:43 damien Exp $ - * $DragonFly: src/sys/dev/netif/ral/rt2661.c,v 1.4 2006/10/25 20:55:58 dillon Exp $ + * $DragonFly: src/sys/dev/netif/ral/rt2661.c,v 1.5 2006/11/18 04:13:39 sephe Exp $ */ /* @@ -64,7 +64,7 @@ #ifdef RAL_DEBUG #define DPRINTF(x) do { if (ral_debug > 0) printf x; } while (0) #define DPRINTFN(n, x) do { if (ral_debug >= (n)) printf x; } while (0) -int ral_debug = 0; +int ral_debug = 1; SYSCTL_INT(_debug, OID_AUTO, ral, CTLFLAG_RW, &ral_debug, 0, "ral debug level"); #else #define DPRINTF(x) @@ -158,6 +158,8 @@ static int rt2661_radar_stop(struct rt2661_softc *); static int rt2661_prepare_beacon(struct rt2661_softc *); static void rt2661_enable_tsf_sync(struct rt2661_softc *); static int rt2661_get_rssi(struct rt2661_softc *, uint8_t); +static void rt2661_led_newstate(struct rt2661_softc *, + enum ieee80211_state); /* * Supported rates for 802.11a/b/g modes (in 500Kbps unit). @@ -194,6 +196,25 @@ static const struct rfprog { RT2661_RF5225_2 }; +#define LED_EE2MCU(bit) { \ + .ee_bit = RT2661_EE_LED_##bit, \ + .mcu_bit = RT2661_MCU_LED_##bit \ +} +static const struct { + uint16_t ee_bit; + uint16_t mcu_bit; +} led_ee2mcu[] = { + LED_EE2MCU(RDYG), + LED_EE2MCU(RDYA), + LED_EE2MCU(ACT), + LED_EE2MCU(GPIO0), + LED_EE2MCU(GPIO1), + LED_EE2MCU(GPIO2), + LED_EE2MCU(GPIO3), + LED_EE2MCU(GPIO4) +}; +#undef LED_EE2MCU + struct rt2661_dmamap { bus_dma_segment_t segs[RT2661_MAX_SCATTER]; int nseg; @@ -313,6 +334,7 @@ rt2661_attach(device_t dev, int id) ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ ic->ic_state = IEEE80211_S_INIT; + rt2661_led_newstate(sc, IEEE80211_S_INIT); /* set device capabilities */ ic->ic_caps = @@ -886,6 +908,9 @@ rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) ostate = ic->ic_state; callout_stop(&sc->scan_ch); + if (ostate != nstate) + rt2661_led_newstate(sc, nstate); + switch (nstate) { case IEEE80211_S_INIT: callout_stop(&sc->rssadapt_ch); @@ -2469,6 +2494,24 @@ rt2661_read_eeprom(struct rt2661_softc *sc) DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg, sc->bbp_prom[i].val)); } + + val = rt2661_eeprom_read(sc, RT2661_EEPROM_LED_OFFSET); + DPRINTF(("LED %02x\n", val)); + if (val == 0xffff) { + sc->mcu_led = RT2661_MCU_LED_DEFAULT; + } else { +#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) + + for (i = 0; i < N(led_ee2mcu); ++i) { + if (val & led_ee2mcu[i].ee_bit) + sc->mcu_led |= led_ee2mcu[i].mcu_bit; + } + +#undef N + + sc->mcu_led |= ((val >> RT2661_EE_LED_MODE_SHIFT) & + RT2661_EE_LED_MODE_MASK); + } } static int @@ -2944,3 +2987,41 @@ rt2661_dma_map_mbuf(void *arg, bus_dma_segment_t *seg, int nseg, bcopy(seg, map->segs, nseg * sizeof(bus_dma_segment_t)); map->nseg = nseg; } + +static void +rt2661_led_newstate(struct rt2661_softc *sc, enum ieee80211_state nstate) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t off, on; + uint32_t mail = sc->mcu_led; + + if (RAL_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY) { + DPRINTF(("%s failed", __func__)); + return; + } + + switch (nstate) { + case IEEE80211_S_INIT: + mail &= ~(RT2661_MCU_LED_LINKA | RT2661_MCU_LED_LINKG | + RT2661_MCU_LED_RF); + break; + default: + if (ic->ic_curchan == NULL) + return; + + on = RT2661_MCU_LED_LINKG; + off = RT2661_MCU_LED_LINKA; + if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) { + on = RT2661_MCU_LED_LINKA; + off = RT2661_MCU_LED_LINKG; + } + + mail |= RT2661_MCU_LED_RF | on; + mail &= ~off; + break; + } + + RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR, + RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | mail); + RAL_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | RT2661_MCU_SET_LED); +} diff --git a/sys/dev/netif/ral/rt2661reg.h b/sys/dev/netif/ral/rt2661reg.h index a7799209c2..2658f3cd4b 100644 --- a/sys/dev/netif/ral/rt2661reg.h +++ b/sys/dev/netif/ral/rt2661reg.h @@ -15,7 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD: src/sys/dev/ral/rt2661reg.h,v 1.1 2006/03/05 20:36:56 damien Exp $ - * $DragonFly: src/sys/dev/netif/ral/rt2661reg.h,v 1.1 2006/05/20 09:13:09 sephe Exp $ + * $DragonFly: src/sys/dev/netif/ral/rt2661reg.h,v 1.2 2006/11/18 04:13:39 sephe Exp $ */ #define RT2661_TX_RING_COUNT 32 @@ -307,11 +307,40 @@ struct rt2661_rx_desc { #define RT2661_EEPROM_BBP_BASE 0x13 #define RT2661_EEPROM_TXPOWER 0x23 #define RT2661_EEPROM_FREQ_OFFSET 0x2f +#define RT2661_EEPROM_LED_OFFSET 0x30 #define RT2661_EEPROM_RSSI_2GHZ_OFFSET 0x4d #define RT2661_EEPROM_RSSI_5GHZ_OFFSET 0x4e +#define RT2661_EE_LED_RDYG 0x01 +#define RT2661_EE_LED_RDYA 0x02 +#define RT2661_EE_LED_ACT 0x04 +#define RT2661_EE_LED_GPIO0 0x08 +#define RT2661_EE_LED_GPIO1 0x10 +#define RT2661_EE_LED_GPIO2 0x20 +#define RT2661_EE_LED_GPIO3 0x40 +#define RT2661_EE_LED_GPIO4 0x80 +#define RT2661_EE_LED_MODE_SHIFT 8 +#define RT2661_EE_LED_MODE_MASK 0x1f + #define RT2661_EEPROM_DELAY 1 /* minimum hold time (microsecond) */ +#define RT2661_MCU_LED_RF (1 << 5) +#define RT2661_MCU_LED_LINKG (1 << 6) +#define RT2661_MCU_LED_LINKA (1 << 7) +#define RT2661_MCU_LED_GPIO0 (1 << 8) +#define RT2661_MCU_LED_GPIO1 (1 << 9) +#define RT2661_MCU_LED_GPIO2 (1 << 10) +#define RT2661_MCU_LED_GPIO3 (1 << 11) +#define RT2661_MCU_LED_GPIO4 (1 << 12) +#define RT2661_MCU_LED_ACT (1 << 13) +#define RT2661_MCU_LED_RDYG (1 << 14) +#define RT2661_MCU_LED_RDYA (1 << 15) + +#define RT2661_MCU_LED_DEFAULT \ + (RT2661_MCU_LED_GPIO0 | RT2661_MCU_LED_GPIO1 | RT2661_MCU_LED_GPIO2 | \ + RT2661_MCU_LED_GPIO3 | RT2661_MCU_LED_GPIO4 | RT2661_MCU_LED_ACT | \ + RT2661_MCU_LED_RDYG | RT2661_MCU_LED_RDYA) + /* * control and status registers access macros */ diff --git a/sys/dev/netif/ral/rt2661var.h b/sys/dev/netif/ral/rt2661var.h index 0efa8e19e9..cc9e17c531 100644 --- a/sys/dev/netif/ral/rt2661var.h +++ b/sys/dev/netif/ral/rt2661var.h @@ -15,7 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD: src/sys/dev/ral/rt2661var.h,v 1.1 2006/03/05 20:36:56 damien Exp $ - * $DragonFly: src/sys/dev/netif/ral/rt2661var.h,v 1.1 2006/05/20 09:13:09 sephe Exp $ + * $DragonFly: src/sys/dev/netif/ral/rt2661var.h,v 1.2 2006/11/18 04:13:39 sephe Exp $ */ struct rt2661_rx_radiotap_header { @@ -143,6 +143,7 @@ struct rt2661_softc { uint8_t bbp16; uint8_t bbp17; uint8_t bbp64; + uint16_t mcu_led; int dwelltime; -- 2.11.4.GIT