summaryrefslogtreecommitdiff
path: root/sys/dev/sdmmc
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2018-05-23 11:32:15 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2018-05-23 11:32:15 +0000
commitdd88e4465076e42fbff2e48b51551ee3ffcb12e3 (patch)
tree0e3bf29876e050a7881ce20e2c0e7b293e17b5db /sys/dev/sdmmc
parent1273bf5390ec444749315bdf85be0a891c7eb445 (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.c43
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