Home | History | Annotate | Line # | Download | only in sdmmc
if_bwfm_sdio.c revision 1.1.4.1
      1  1.1.4.1  pgoyette /* $NetBSD: if_bwfm_sdio.c,v 1.1.4.1 2018/03/15 09:12:06 pgoyette Exp $ */
      2      1.1   khorben /* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */
      3      1.1   khorben /*
      4      1.1   khorben  * Copyright (c) 2010-2016 Broadcom Corporation
      5      1.1   khorben  * Copyright (c) 2016,2017 Patrick Wildt <patrick (at) blueri.se>
      6      1.1   khorben  *
      7      1.1   khorben  * Permission to use, copy, modify, and/or distribute this software for any
      8      1.1   khorben  * purpose with or without fee is hereby granted, provided that the above
      9      1.1   khorben  * copyright notice and this permission notice appear in all copies.
     10      1.1   khorben  *
     11      1.1   khorben  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12      1.1   khorben  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13      1.1   khorben  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14      1.1   khorben  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15      1.1   khorben  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16      1.1   khorben  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17      1.1   khorben  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18      1.1   khorben  */
     19      1.1   khorben 
     20      1.1   khorben #include <sys/param.h>
     21      1.1   khorben #include <sys/systm.h>
     22      1.1   khorben #include <sys/buf.h>
     23      1.1   khorben #include <sys/kernel.h>
     24      1.1   khorben #include <sys/malloc.h>
     25      1.1   khorben #include <sys/device.h>
     26      1.1   khorben #include <sys/queue.h>
     27      1.1   khorben #include <sys/socket.h>
     28      1.1   khorben #include <sys/mutex.h>
     29      1.1   khorben #include <sys/workqueue.h>
     30      1.1   khorben #include <sys/pcq.h>
     31      1.1   khorben 
     32      1.1   khorben #include <net/bpf.h>
     33      1.1   khorben #include <net/if.h>
     34      1.1   khorben #include <net/if_dl.h>
     35      1.1   khorben #include <net/if_media.h>
     36      1.1   khorben #include <net/if_ether.h>
     37      1.1   khorben 
     38      1.1   khorben #include <netinet/in.h>
     39      1.1   khorben 
     40      1.1   khorben #include <net80211/ieee80211_var.h>
     41      1.1   khorben 
     42      1.1   khorben #include <dev/sdmmc/sdmmcvar.h>
     43      1.1   khorben 
     44      1.1   khorben #include <dev/ic/bwfmvar.h>
     45      1.1   khorben #include <dev/ic/bwfmreg.h>
     46      1.1   khorben 
     47      1.1   khorben #define BWFM_SDIO_CCCR_BRCM_CARDCAP			0xf0
     48      1.1   khorben #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	0x02
     49      1.1   khorben #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT		0x04
     50      1.1   khorben #define  BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC		0x08
     51      1.1   khorben #define BWFM_SDIO_CCCR_BRCM_CARDCTRL			0xf1
     52      1.1   khorben #define  BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET		0x02
     53      1.1   khorben #define BWFM_SDIO_CCCR_BRCM_SEPINT			0xf2
     54      1.1   khorben 
     55      1.1   khorben #ifdef BWFM_DEBUG
     56      1.1   khorben #define DPRINTF(x)	do { if (bwfm_debug > 0) printf x; } while (0)
     57      1.1   khorben #define DPRINTFN(n, x)	do { if (bwfm_debug >= (n)) printf x; } while (0)
     58      1.1   khorben static int bwfm_debug = 2;
     59      1.1   khorben #else
     60      1.1   khorben #define DPRINTF(x)	do { ; } while (0)
     61      1.1   khorben #define DPRINTFN(n, x)	do { ; } while (0)
     62      1.1   khorben #endif
     63      1.1   khorben 
     64      1.1   khorben #define DEVNAME(sc)	device_xname((sc)->sc_sc.sc_dev)
     65      1.1   khorben 
     66      1.1   khorben struct bwfm_sdio_softc {
     67      1.1   khorben 	struct bwfm_softc	  sc_sc;
     68      1.1   khorben 	struct sdmmc_function	**sc_sf;
     69      1.1   khorben 	uint32_t		  sc_bar0;
     70      1.1   khorben };
     71      1.1   khorben 
     72      1.1   khorben int		 bwfm_sdio_match(device_t, cfdata_t, void *);
     73      1.1   khorben void		 bwfm_sdio_attach(device_t, struct device *, void *);
     74      1.1   khorben int		 bwfm_sdio_detach(device_t, int);
     75      1.1   khorben 
     76  1.1.4.1  pgoyette void		 bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t);
     77      1.1   khorben uint8_t		 bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t);
     78      1.1   khorben uint32_t	 bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t);
     79      1.1   khorben void		 bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t,
     80      1.1   khorben 		     uint8_t);
     81      1.1   khorben void		 bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t,
     82      1.1   khorben 		     uint32_t);
     83      1.1   khorben 
     84      1.1   khorben uint32_t	 bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t);
     85      1.1   khorben void		 bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t,
     86      1.1   khorben 		     uint32_t);
     87      1.1   khorben int		 bwfm_sdio_buscore_prepare(struct bwfm_softc *);
     88      1.1   khorben void		 bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t);
     89      1.1   khorben 
     90      1.1   khorben int		 bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf *);
     91      1.1   khorben int		 bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t);
     92      1.1   khorben int		 bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *);
     93      1.1   khorben 
     94      1.1   khorben struct bwfm_bus_ops bwfm_sdio_bus_ops = {
     95      1.1   khorben 	.bs_init = NULL,
     96      1.1   khorben 	.bs_stop = NULL,
     97      1.1   khorben 	.bs_txdata = bwfm_sdio_txdata,
     98      1.1   khorben 	.bs_txctl = bwfm_sdio_txctl,
     99      1.1   khorben 	.bs_rxctl = bwfm_sdio_rxctl,
    100      1.1   khorben };
    101      1.1   khorben 
    102      1.1   khorben struct bwfm_buscore_ops bwfm_sdio_buscore_ops = {
    103      1.1   khorben 	.bc_read = bwfm_sdio_buscore_read,
    104      1.1   khorben 	.bc_write = bwfm_sdio_buscore_write,
    105      1.1   khorben 	.bc_prepare = bwfm_sdio_buscore_prepare,
    106      1.1   khorben 	.bc_reset = NULL,
    107      1.1   khorben 	.bc_setup = NULL,
    108      1.1   khorben 	.bc_activate = bwfm_sdio_buscore_activate,
    109      1.1   khorben };
    110      1.1   khorben 
    111      1.1   khorben CFATTACH_DECL_NEW(bwfm_sdio, sizeof(struct bwfm_sdio_softc),
    112      1.1   khorben     bwfm_sdio_match, bwfm_sdio_attach, bwfm_sdio_detach, NULL);
    113      1.1   khorben 
    114      1.1   khorben int
    115      1.1   khorben bwfm_sdio_match(device_t parent, cfdata_t match, void *aux)
    116      1.1   khorben {
    117      1.1   khorben 	struct sdmmc_attach_args *saa = aux;
    118      1.1   khorben 	struct sdmmc_function *sf = saa->sf;
    119      1.1   khorben 	struct sdmmc_cis *cis;
    120      1.1   khorben 
    121      1.1   khorben 	/* Not SDIO. */
    122      1.1   khorben 	if (sf == NULL)
    123      1.1   khorben 		return 0;
    124      1.1   khorben 
    125      1.1   khorben 	/* Look for Broadcom 433[04]. */
    126      1.1   khorben 	cis = &sf->sc->sc_fn0->cis;
    127      1.1   khorben 	if (cis->manufacturer != 0x02d0 || (cis->product != 0x4330 &&
    128      1.1   khorben 	    cis->product != 0x4334))
    129      1.1   khorben 		return 0;
    130      1.1   khorben 
    131      1.1   khorben 	/* We need both functions, but ... */
    132      1.1   khorben 	if (sf->sc->sc_function_count <= 1)
    133      1.1   khorben 		return 0;
    134      1.1   khorben 
    135      1.1   khorben 	/* ... only attach for one. */
    136      1.1   khorben 	if (sf->number != 1)
    137      1.1   khorben 		return 0;
    138      1.1   khorben 
    139      1.1   khorben 	return 1;
    140      1.1   khorben }
    141      1.1   khorben 
    142      1.1   khorben void
    143      1.1   khorben bwfm_sdio_attach(device_t parent, device_t self, void *aux)
    144      1.1   khorben {
    145      1.1   khorben 	struct bwfm_sdio_softc *sc = device_private(self);
    146      1.1   khorben 	struct sdmmc_attach_args *saa = aux;
    147      1.1   khorben 	struct sdmmc_function *sf = saa->sf;
    148      1.1   khorben 	struct bwfm_core *core;
    149      1.1   khorben 
    150      1.1   khorben 	aprint_naive("\n");
    151      1.1   khorben 
    152      1.1   khorben 	sc->sc_sf = malloc((sf->sc->sc_function_count + 1) *
    153      1.1   khorben 	    sizeof(struct sdmmc_function *), M_DEVBUF, M_WAITOK);
    154      1.1   khorben 
    155      1.1   khorben 	/* Copy all function pointers. */
    156      1.1   khorben 	SIMPLEQ_FOREACH(sf, &saa->sf->sc->sf_head, sf_list) {
    157      1.1   khorben 		sc->sc_sf[sf->number] = sf;
    158      1.1   khorben 	}
    159      1.1   khorben 	sf = saa->sf;
    160      1.1   khorben 
    161      1.1   khorben 	/*
    162      1.1   khorben 	 * TODO: set block size to 64 for func 1, 512 for func 2.
    163      1.1   khorben 	 * We might need to work on the SDMMC stack to be able to set
    164      1.1   khorben 	 * a block size per function.  Currently the IO code uses the
    165      1.1   khorben 	 * SDHC controller's maximum block length.
    166      1.1   khorben 	 */
    167      1.1   khorben 
    168      1.1   khorben 	/* Enable Function 1. */
    169      1.1   khorben 	if (sdmmc_io_function_enable(sc->sc_sf[1]) != 0) {
    170      1.1   khorben 		aprint_error_dev(self, "cannot enable function 1\n");
    171      1.1   khorben 		goto err;
    172      1.1   khorben 	}
    173      1.1   khorben 
    174      1.1   khorben 	DPRINTFN(2, ("%s: F1 signature read @0x18000000=%x\n", DEVNAME(sc),
    175      1.1   khorben 	    bwfm_sdio_read_4(sc, 0x18000000)));
    176      1.1   khorben 
    177      1.1   khorben 	/* Force PLL off */
    178      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
    179      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
    180      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ);
    181      1.1   khorben 
    182      1.1   khorben 	sc->sc_sc.sc_buscore_ops = &bwfm_sdio_buscore_ops;
    183      1.1   khorben 	if (bwfm_chip_attach(&sc->sc_sc) != 0) {
    184      1.1   khorben 		aprint_error_dev(self, "cannot attach chip\n");
    185      1.1   khorben 		goto err;
    186      1.1   khorben 	}
    187      1.1   khorben 
    188      1.1   khorben 	/* TODO: drive strength */
    189      1.1   khorben 
    190      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL,
    191      1.1   khorben 	    bwfm_sdio_read_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL) |
    192      1.1   khorben 	    BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET);
    193      1.1   khorben 
    194      1.1   khorben 	core = bwfm_chip_get_pmu(&sc->sc_sc);
    195      1.1   khorben 	bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL,
    196      1.1   khorben 	    bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL) |
    197      1.1   khorben 	    (BWFM_CHIP_REG_PMUCONTROL_RES_RELOAD <<
    198      1.1   khorben 	     BWFM_CHIP_REG_PMUCONTROL_RES_SHIFT));
    199      1.1   khorben 
    200      1.1   khorben 	sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops;
    201      1.1   khorben 	sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops;
    202      1.1   khorben 	bwfm_attach(&sc->sc_sc);
    203      1.1   khorben 
    204      1.1   khorben 	return;
    205      1.1   khorben 
    206      1.1   khorben err:
    207      1.1   khorben 	free(sc->sc_sf, M_DEVBUF);
    208      1.1   khorben }
    209      1.1   khorben 
    210      1.1   khorben int
    211      1.1   khorben bwfm_sdio_detach(struct device *self, int flags)
    212      1.1   khorben {
    213      1.1   khorben 	struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self;
    214      1.1   khorben 
    215      1.1   khorben 	bwfm_detach(&sc->sc_sc, flags);
    216      1.1   khorben 
    217      1.1   khorben 	free(sc->sc_sf, M_DEVBUF);
    218      1.1   khorben 
    219      1.1   khorben 	return 0;
    220      1.1   khorben }
    221      1.1   khorben 
    222  1.1.4.1  pgoyette void
    223  1.1.4.1  pgoyette bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0)
    224  1.1.4.1  pgoyette {
    225  1.1.4.1  pgoyette 	if (sc->sc_bar0 == bar0)
    226  1.1.4.1  pgoyette 		return;
    227  1.1.4.1  pgoyette 
    228  1.1.4.1  pgoyette 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW,
    229  1.1.4.1  pgoyette 	    (bar0 >>  8) & 0x80);
    230  1.1.4.1  pgoyette 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID,
    231  1.1.4.1  pgoyette 	    (bar0 >> 16) & 0xff);
    232  1.1.4.1  pgoyette 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH,
    233  1.1.4.1  pgoyette 	    (bar0 >> 24) & 0xff);
    234  1.1.4.1  pgoyette 	sc->sc_bar0 = bar0;
    235  1.1.4.1  pgoyette }
    236  1.1.4.1  pgoyette 
    237      1.1   khorben uint8_t
    238      1.1   khorben bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr)
    239      1.1   khorben {
    240      1.1   khorben 	struct sdmmc_function *sf;
    241      1.1   khorben 	uint8_t rv;
    242      1.1   khorben 
    243      1.1   khorben 	/*
    244      1.1   khorben 	 * figure out how to read the register based on address range
    245      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    246      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    247      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    248      1.1   khorben 	 */
    249      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    250      1.1   khorben 		sf = sc->sc_sf[0];
    251      1.1   khorben 	else
    252      1.1   khorben 		sf = sc->sc_sf[1];
    253      1.1   khorben 
    254      1.1   khorben 	rv = sdmmc_io_read_1(sf, addr);
    255      1.1   khorben 	return rv;
    256      1.1   khorben }
    257      1.1   khorben 
    258      1.1   khorben uint32_t
    259      1.1   khorben bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr)
    260      1.1   khorben {
    261      1.1   khorben 	struct sdmmc_function *sf;
    262      1.1   khorben 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
    263      1.1   khorben 	uint32_t rv;
    264      1.1   khorben 
    265  1.1.4.1  pgoyette 	bwfm_sdio_backplane(sc, bar0);
    266      1.1   khorben 
    267      1.1   khorben 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
    268      1.1   khorben 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
    269      1.1   khorben 
    270      1.1   khorben 	/*
    271      1.1   khorben 	 * figure out how to read the register based on address range
    272      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    273      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    274      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    275      1.1   khorben 	 */
    276      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    277      1.1   khorben 		sf = sc->sc_sf[0];
    278      1.1   khorben 	else
    279      1.1   khorben 		sf = sc->sc_sf[1];
    280      1.1   khorben 
    281      1.1   khorben 	rv = sdmmc_io_read_4(sf, addr);
    282      1.1   khorben 	return rv;
    283      1.1   khorben }
    284      1.1   khorben 
    285      1.1   khorben void
    286      1.1   khorben bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data)
    287      1.1   khorben {
    288      1.1   khorben 	struct sdmmc_function *sf;
    289      1.1   khorben 
    290      1.1   khorben 	/*
    291      1.1   khorben 	 * figure out how to read the register based on address range
    292      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    293      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    294      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    295      1.1   khorben 	 */
    296      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    297      1.1   khorben 		sf = sc->sc_sf[0];
    298      1.1   khorben 	else
    299      1.1   khorben 		sf = sc->sc_sf[1];
    300      1.1   khorben 
    301      1.1   khorben 	sdmmc_io_write_1(sf, addr, data);
    302      1.1   khorben }
    303      1.1   khorben 
    304      1.1   khorben void
    305      1.1   khorben bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data)
    306      1.1   khorben {
    307      1.1   khorben 	struct sdmmc_function *sf;
    308      1.1   khorben 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
    309      1.1   khorben 
    310  1.1.4.1  pgoyette 	bwfm_sdio_backplane(sc, bar0);
    311      1.1   khorben 
    312      1.1   khorben 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
    313      1.1   khorben 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
    314      1.1   khorben 
    315      1.1   khorben 	/*
    316      1.1   khorben 	 * figure out how to read the register based on address range
    317      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    318      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    319      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    320      1.1   khorben 	 */
    321      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    322      1.1   khorben 		sf = sc->sc_sf[0];
    323      1.1   khorben 	else
    324      1.1   khorben 		sf = sc->sc_sf[1];
    325      1.1   khorben 
    326      1.1   khorben 	sdmmc_io_write_4(sf, addr, data);
    327      1.1   khorben }
    328      1.1   khorben 
    329      1.1   khorben uint32_t
    330      1.1   khorben bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
    331      1.1   khorben {
    332      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    333      1.1   khorben 	uint32_t val;
    334      1.1   khorben 
    335      1.1   khorben 	val = bwfm_sdio_read_4(sc, reg);
    336      1.1   khorben 	/* TODO: Workaround for 4335/4339 */
    337      1.1   khorben 
    338      1.1   khorben 	return val;
    339      1.1   khorben }
    340      1.1   khorben 
    341      1.1   khorben void
    342      1.1   khorben bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
    343      1.1   khorben {
    344      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    345      1.1   khorben 	bwfm_sdio_write_4(sc, reg, val);
    346      1.1   khorben }
    347      1.1   khorben 
    348      1.1   khorben int
    349      1.1   khorben bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm)
    350      1.1   khorben {
    351      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    352      1.1   khorben 	uint8_t clkval, clkset, clkmask;
    353      1.1   khorben 	int i;
    354      1.1   khorben 
    355      1.1   khorben 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ |
    356      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF;
    357      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
    358      1.1   khorben 
    359      1.1   khorben 	clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL |
    360      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL;
    361      1.1   khorben 	clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
    362      1.1   khorben 
    363      1.1   khorben 	if ((clkval & ~clkmask) != clkset) {
    364      1.1   khorben 		printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc),
    365      1.1   khorben 		    clkset, clkval);
    366      1.1   khorben 		return 1;
    367      1.1   khorben 	}
    368      1.1   khorben 
    369      1.1   khorben 	for (i = 1000; i > 0; i--) {
    370      1.1   khorben 		clkval = bwfm_sdio_read_1(sc,
    371      1.1   khorben 		    BWFM_SDIO_FUNC1_CHIPCLKCSR);
    372      1.1   khorben 		if (clkval & clkmask)
    373      1.1   khorben 			break;
    374      1.1   khorben 	}
    375      1.1   khorben 	if (i == 0) {
    376      1.1   khorben 		printf("%s: timeout on ALPAV wait, clkval 0x%02x\n",
    377      1.1   khorben 		    DEVNAME(sc), clkval);
    378      1.1   khorben 		return 1;
    379      1.1   khorben 	}
    380      1.1   khorben 
    381      1.1   khorben 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
    382      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP;
    383      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
    384      1.1   khorben 	delay(65);
    385      1.1   khorben 
    386      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0);
    387      1.1   khorben 
    388      1.1   khorben 	return 0;
    389      1.1   khorben }
    390      1.1   khorben 
    391      1.1   khorben void
    392      1.1   khorben bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec)
    393      1.1   khorben {
    394      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    395      1.1   khorben 	struct bwfm_core *core;
    396      1.1   khorben 
    397      1.1   khorben 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
    398      1.1   khorben 	bwfm_sdio_buscore_write(&sc->sc_sc,
    399      1.1   khorben 	    core->co_base + BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF);
    400      1.1   khorben 
    401      1.1   khorben #if notyet
    402      1.1   khorben 	if (rstvec)
    403      1.1   khorben 		bwfm_sdio_ram_write(&sc->sc_sc, 0, &rstvec, sizeof(rstvec));
    404      1.1   khorben #endif
    405      1.1   khorben }
    406      1.1   khorben 
    407      1.1   khorben int
    408      1.1   khorben bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf *m)
    409      1.1   khorben {
    410      1.1   khorben #ifdef BWFM_DEBUG
    411      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    412      1.1   khorben #endif
    413      1.1   khorben 	int ret = 1;
    414      1.1   khorben 
    415      1.1   khorben 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    416      1.1   khorben 
    417      1.1   khorben 	return ret;
    418      1.1   khorben }
    419      1.1   khorben 
    420      1.1   khorben int
    421      1.1   khorben bwfm_sdio_txctl(struct bwfm_softc *bwfm, char *buf, size_t len)
    422      1.1   khorben {
    423      1.1   khorben #ifdef BWFM_DEBUG
    424      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    425      1.1   khorben #endif
    426      1.1   khorben 	int ret = 1;
    427      1.1   khorben 
    428      1.1   khorben 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    429      1.1   khorben 
    430      1.1   khorben 	return ret;
    431      1.1   khorben }
    432      1.1   khorben 
    433      1.1   khorben int
    434      1.1   khorben bwfm_sdio_rxctl(struct bwfm_softc *bwfm, char *buf, size_t *len)
    435      1.1   khorben {
    436      1.1   khorben #ifdef BWFM_DEBUG
    437      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    438      1.1   khorben #endif
    439      1.1   khorben 	int ret = 1;
    440      1.1   khorben 
    441      1.1   khorben 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    442      1.1   khorben 
    443      1.1   khorben 	return ret;
    444      1.1   khorben }
    445