diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-01-07 00:29:45 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-01-07 00:29:45 +0000 |
commit | 86b0f17855378f6250a6ea7d315e2cf9bb65b5ef (patch) | |
tree | 64b33bf865bf5a487ca363c239b9f19800244471 | |
parent | 09639b2939765b5d8d5be9ef6c684c6e218dfbbb (diff) |
Initialize GPIO.
-rw-r--r-- | sys/dev/ic/bcw.c | 73 | ||||
-rw-r--r-- | sys/dev/ic/bcwreg.h | 9 | ||||
-rw-r--r-- | sys/dev/ic/bcwvar.h | 39 |
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 *); |