diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-05-23 11:32:15 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-05-23 11:32:15 +0000 |
commit | dd88e4465076e42fbff2e48b51551ee3ffcb12e3 (patch) | |
tree | 0e3bf29876e050a7881ce20e2c0e7b293e17b5db /sys/dev/sdmmc | |
parent | 1273bf5390ec444749315bdf85be0a891c7eb445 (diff) |
Implement a separate initialization stage so that we can still use
and initialize bwfm(4) later in the case that the firmware was not
available on bootup and was only later installed.
ok stsp@
Diffstat (limited to 'sys/dev/sdmmc')
-rw-r--r-- | sys/dev/sdmmc/if_bwfm_sdio.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/sys/dev/sdmmc/if_bwfm_sdio.c b/sys/dev/sdmmc/if_bwfm_sdio.c index 5334b087f1d..42752a9b776 100644 --- a/sys/dev/sdmmc/if_bwfm_sdio.c +++ b/sys/dev/sdmmc/if_bwfm_sdio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bwfm_sdio.c,v 1.14 2018/05/23 09:08:18 patrick Exp $ */ +/* $OpenBSD: if_bwfm_sdio.c,v 1.15 2018/05/23 11:32:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -79,6 +79,8 @@ struct bwfm_sdio_softc { struct rwlock *sc_lock; void *sc_ih; + int sc_initialized; + uint32_t sc_bar0; int sc_clkstate; int sc_alp_only; @@ -101,7 +103,7 @@ struct bwfm_sdio_softc { int bwfm_sdio_match(struct device *, void *, void *); void bwfm_sdio_attach(struct device *, struct device *, void *); -void bwfm_sdio_attachhook(struct device *); +int bwfm_sdio_preinit(struct bwfm_softc *); int bwfm_sdio_detach(struct device *, int); int bwfm_sdio_intr(void *); @@ -157,7 +159,7 @@ void bwfm_sdio_debug_console(struct bwfm_sdio_softc *); #endif struct bwfm_bus_ops bwfm_sdio_bus_ops = { - .bs_init = NULL, + .bs_preinit = bwfm_sdio_preinit, .bs_stop = NULL, .bs_txcheck = bwfm_sdio_txcheck, .bs_txdata = bwfm_sdio_txdata, @@ -312,24 +314,29 @@ bwfm_sdio_attach(struct device *parent, struct device *self, void *aux) bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); sc->sc_clkstate = CLK_SDONLY; - config_mountroot(self, bwfm_sdio_attachhook); + sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops; + sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; + bwfm_attach(&sc->sc_sc); + config_mountroot(self, bwfm_attachhook); return; err: free(sc->sc_sf, M_DEVBUF, 0); } -void -bwfm_sdio_attachhook(struct device *self) +int +bwfm_sdio_preinit(struct bwfm_softc *bwfm) { - struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; - struct bwfm_softc *bwfm = (void *)sc; + struct bwfm_sdio_softc *sc = (void *)bwfm; const char *name = NULL; const char *nvname = NULL; uint32_t clk, reg; u_char *ucode, *nvram; size_t size, nvlen; + if (sc->sc_initialized) + return 0; + rw_enter_write(sc->sc_lock); switch (bwfm->sc_chip.ch_chip) @@ -349,20 +356,20 @@ bwfm_sdio_attachhook(struct device *self) default: printf("%s: unknown firmware for chip %s\n", DEVNAME(sc), bwfm->sc_chip.ch_name); - return; + return 1; } if (loadfirmware(name, &ucode, &size) != 0) { printf("%s: failed loadfirmware of file %s\n", DEVNAME(sc), name); - return; + return 1; } if (loadfirmware(nvname, &nvram, &nvlen) != 0) { printf("%s: failed loadfirmware of file %s\n", DEVNAME(sc), nvname); free(ucode, M_DEVBUF, size); - return; + return 1; } sc->sc_alp_only = 1; @@ -372,7 +379,7 @@ bwfm_sdio_attachhook(struct device *self) DEVNAME(sc)); free(ucode, M_DEVBUF, size); free(nvram, M_DEVBUF, nvlen); - return; + return 1; } sc->sc_alp_only = 0; free(ucode, M_DEVBUF, size); @@ -380,7 +387,7 @@ bwfm_sdio_attachhook(struct device *self) bwfm_sdio_clkctl(sc, CLK_AVAIL, 0); if (sc->sc_clkstate != CLK_AVAIL) - return; + return 1; clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, @@ -390,7 +397,7 @@ bwfm_sdio_attachhook(struct device *self) SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT); if (sdmmc_io_function_enable(sc->sc_sf[2]) != 0) { printf("%s: cannot enable function 2\n", DEVNAME(sc)); - return; + return 1; } bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK, @@ -411,20 +418,18 @@ bwfm_sdio_attachhook(struct device *self) bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk); } - /* if interrupt establish fails */ sc->sc_ih = sdmmc_intr_establish(bwfm->sc_dev.dv_parent, bwfm_sdio_intr, sc, DEVNAME(sc)); if (sc->sc_ih == NULL) { printf("%s: can't establish interrupt\n", DEVNAME(sc)); bwfm_sdio_clkctl(sc, CLK_NONE, 0); - return; + return 1; } sdmmc_intr_enable(sc->sc_sf[1]); rw_exit(sc->sc_lock); - sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops; - sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; - bwfm_attach(&sc->sc_sc); + sc->sc_initialized = 1; + return 0; } int |