summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2007-01-07 00:29:45 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2007-01-07 00:29:45 +0000
commit86b0f17855378f6250a6ea7d315e2cf9bb65b5ef (patch)
tree64b33bf865bf5a487ca363c239b9f19800244471
parent09639b2939765b5d8d5be9ef6c684c6e218dfbbb (diff)
Initialize GPIO.
-rw-r--r--sys/dev/ic/bcw.c73
-rw-r--r--sys/dev/ic/bcwreg.h9
-rw-r--r--sys/dev/ic/bcwvar.h39
3 files changed, 118 insertions, 3 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c
index b09bc3ad4e3..dc2aaab86b9 100644
--- a/sys/dev/ic/bcw.c
+++ b/sys/dev/ic/bcw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcw.c,v 1.33 2007/01/06 20:33:09 mglocker Exp $ */
+/* $OpenBSD: bcw.c,v 1.34 2007/01/07 00:29:44 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -106,6 +106,8 @@ int bcw_load_firmware(struct bcw_softc *);
int bcw_write_initvals(struct bcw_softc *,
const struct bcw_initval *, const unsigned int);
int bcw_load_initvals(struct bcw_softc *);
+void bcw_leds_switch_all(struct bcw_softc *, int);
+int bcw_gpio_init(struct bcw_softc *);
struct cfdriver bcw_cd = {
NULL, "bcw", DV_IFNET
@@ -1153,6 +1155,10 @@ bcw_init(struct ifnet *ifp)
return (1);
}
+ /* initialize GPIO */
+ if ((error = bcw_gpio_init(sc)))
+ return (error);
+
/* load init values */
if ((error = bcw_load_initvals(sc)))
return (error);
@@ -2503,3 +2509,68 @@ bcw_load_initvals(struct bcw_softc *sc)
fail: free(ucode, M_DEVBUF);
return (EIO);
}
+
+void
+bcw_leds_switch_all(struct bcw_softc *sc, int on)
+{
+ struct bcw_led *led;
+ uint16_t ledctl;
+ int i, bit_on;
+
+ ledctl = BCW_READ16(sc, BCW_GPIO_CTRL);
+
+ for (i = 0; i < BCW_NR_LEDS; i++) {
+ led = &(sc->leds[i]);
+ if (led->behaviour == BCW_LED_INACTIVE)
+ continue;
+ if (on)
+ bit_on = led->activelow ? 0 : 1;
+ else
+ bit_on = led->activelow ? 0 : 1;
+ if (bit_on)
+ ledctl |= (1 << i);
+ else
+ ledctl &= ~(1 << i);
+ }
+
+ BCW_WRITE16(sc, BCW_GPIO_CTRL, ledctl);
+}
+
+int
+bcw_gpio_init(struct bcw_softc *sc)
+{
+ uint32_t mask, set;
+
+ BCW_WRITE(sc, BCW_SBF, BCW_READ(sc, BCW_SBF) & 0xffff3fff);
+
+ bcw_leds_switch_all(sc, 0);
+
+ BCW_WRITE16(sc, BCW_GPIO_MASK, BCW_READ16(sc, BCW_GPIO_MASK) | 0x000f);
+
+ mask = 0x0000001f;
+ set = 0x0000000f;
+
+ if (sc->sc_chipid == 0x4301) {
+ mask |= 0x0060;
+ set |= 0x0060;
+ }
+ if (0) { /* FIXME conditional unknown */
+ BCW_WRITE16(sc, BCW_GPIO_MASK, BCW_READ16(sc, BCW_GPIO_MASK) |
+ 0x0100);
+ mask |= 0x0180;
+ set |= 0x0180;
+ }
+ if (sc->sc_boardflags & BCW_BF_PACTRL) {
+ BCW_WRITE16(sc, BCW_GPIO_MASK, BCW_READ16(sc, BCW_GPIO_MASK) |
+ 0x0200);
+ mask |= 0x0200;
+ set |= 0x0200;
+ }
+ if (sc->sc_chiprev >= 2)
+ mask |= 0x0010; /* FIXME this is redundant */
+
+ BCW_WRITE(sc, BCW_GPIO_CTRL, (BCW_READ(sc, BCW_GPIO_CTRL) & mask) |
+ set);
+
+ return (0);
+}
diff --git a/sys/dev/ic/bcwreg.h b/sys/dev/ic/bcwreg.h
index fb9a16d64a3..bab710fce00 100644
--- a/sys/dev/ic/bcwreg.h
+++ b/sys/dev/ic/bcwreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwreg.h,v 1.9 2007/01/03 18:54:29 mglocker Exp $ */
+/* $OpenBSD: bcwreg.h,v 1.10 2007/01/07 00:29:44 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -334,6 +334,13 @@
#define BCW_UCODE_TIME 0x0006
#define BCW_UCODE_STATUS 0x0040
+/* GPIO */
+#define BCW_GPIO_MASK 0x49e
+#define BCW_GPIO_CTRL 0x6c
+
+/* LEDS */
+#define BCW_NR_LEDS 4
+
#define BCW_READ16(sc, reg) \
bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg))
#define BCW_READ(sc, reg) \
diff --git a/sys/dev/ic/bcwvar.h b/sys/dev/ic/bcwvar.h
index 52c19db35eb..fabf8c6253b 100644
--- a/sys/dev/ic/bcwvar.h
+++ b/sys/dev/ic/bcwvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwvar.h,v 1.12 2007/01/05 07:09:15 mglocker Exp $ */
+/* $OpenBSD: bcwvar.h,v 1.13 2007/01/07 00:29:44 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -35,6 +35,42 @@ struct bcw_initval {
uint32_t value;
} __packed;
+struct bcw_led {
+ uint8_t behaviour:7;
+ uint8_t activelow:1;
+ unsigned long blink_interval;
+};
+enum {
+ BCW_LED_OFF,
+ BCW_LED_ON,
+ BCW_LED_ACTIVITY,
+ BCW_LED_RADIO_ALL,
+ BCW_LED_RADIO_A,
+ BCW_LED_RADIO_B,
+ BCW_LED_MODE_BG,
+ BCW_LED_TRANSFER,
+ BCW_LED_APTRANSFER,
+ BCW_LED_WEIRD, /* FIXME */
+ BCW_LED_ASSOC,
+ BCW_LED_INACTIVE,
+
+ /*
+ * Behaviour values for testing.
+ * With these values it is easier to figure out
+ * the real behaviour of leds, in case the SPROM
+ * is missing information.
+ */
+ BCW_LED_TEST_BLINKSLOW,
+ BCW_LED_TEST_BLINKMEDIUM,
+ BCW_LED_TEST_BLINKFAST,
+
+ /* misc values for BCM4303 */
+ BCW_LED_BCM4303_0 = 0x2B,
+ BCW_LED_BCM4303_1 = 0x78,
+ BCW_LED_BCM4303_2 = 0x2E,
+ BCW_LED_BCM4303_3 = 0x19,
+};
+
#define BCW_MAX_RADIOS 2
struct bcw_radio {
uint16_t id;
@@ -199,6 +235,7 @@ struct bcw_softc {
struct bcw_core *sc_core_common;
struct bcw_core *sc_core_80211;
struct bcw_core *sc_core_bus; /* PCI or cardbus */
+ struct bcw_led leds[BCW_NR_LEDS];
};
void bcw_attach(struct bcw_softc *);