Home | History | Annotate | Line # | Download | only in sdmmc
if_bwfm_sdio.c revision 1.1.4.2
      1  1.1.4.2  pgoyette /* $NetBSD: if_bwfm_sdio.c,v 1.1.4.2 2018/05/21 04:36:12 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.4.2  pgoyette int		 bwfm_sdio_txcheck(struct bwfm_softc *);
     91      1.1   khorben int		 bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf *);
     92      1.1   khorben int		 bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t);
     93      1.1   khorben int		 bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *);
     94      1.1   khorben 
     95      1.1   khorben struct bwfm_bus_ops bwfm_sdio_bus_ops = {
     96      1.1   khorben 	.bs_init = NULL,
     97      1.1   khorben 	.bs_stop = NULL,
     98  1.1.4.2  pgoyette 	.bs_txcheck = bwfm_sdio_txcheck,
     99      1.1   khorben 	.bs_txdata = bwfm_sdio_txdata,
    100      1.1   khorben 	.bs_txctl = bwfm_sdio_txctl,
    101      1.1   khorben 	.bs_rxctl = bwfm_sdio_rxctl,
    102      1.1   khorben };
    103      1.1   khorben 
    104      1.1   khorben struct bwfm_buscore_ops bwfm_sdio_buscore_ops = {
    105      1.1   khorben 	.bc_read = bwfm_sdio_buscore_read,
    106      1.1   khorben 	.bc_write = bwfm_sdio_buscore_write,
    107      1.1   khorben 	.bc_prepare = bwfm_sdio_buscore_prepare,
    108      1.1   khorben 	.bc_reset = NULL,
    109      1.1   khorben 	.bc_setup = NULL,
    110      1.1   khorben 	.bc_activate = bwfm_sdio_buscore_activate,
    111      1.1   khorben };
    112      1.1   khorben 
    113      1.1   khorben CFATTACH_DECL_NEW(bwfm_sdio, sizeof(struct bwfm_sdio_softc),
    114      1.1   khorben     bwfm_sdio_match, bwfm_sdio_attach, bwfm_sdio_detach, NULL);
    115      1.1   khorben 
    116      1.1   khorben int
    117      1.1   khorben bwfm_sdio_match(device_t parent, cfdata_t match, void *aux)
    118      1.1   khorben {
    119      1.1   khorben 	struct sdmmc_attach_args *saa = aux;
    120      1.1   khorben 	struct sdmmc_function *sf = saa->sf;
    121      1.1   khorben 	struct sdmmc_cis *cis;
    122      1.1   khorben 
    123      1.1   khorben 	/* Not SDIO. */
    124      1.1   khorben 	if (sf == NULL)
    125      1.1   khorben 		return 0;
    126      1.1   khorben 
    127      1.1   khorben 	/* Look for Broadcom 433[04]. */
    128      1.1   khorben 	cis = &sf->sc->sc_fn0->cis;
    129      1.1   khorben 	if (cis->manufacturer != 0x02d0 || (cis->product != 0x4330 &&
    130      1.1   khorben 	    cis->product != 0x4334))
    131      1.1   khorben 		return 0;
    132      1.1   khorben 
    133      1.1   khorben 	/* We need both functions, but ... */
    134      1.1   khorben 	if (sf->sc->sc_function_count <= 1)
    135      1.1   khorben 		return 0;
    136      1.1   khorben 
    137      1.1   khorben 	/* ... only attach for one. */
    138      1.1   khorben 	if (sf->number != 1)
    139      1.1   khorben 		return 0;
    140      1.1   khorben 
    141      1.1   khorben 	return 1;
    142      1.1   khorben }
    143      1.1   khorben 
    144      1.1   khorben void
    145      1.1   khorben bwfm_sdio_attach(device_t parent, device_t self, void *aux)
    146      1.1   khorben {
    147      1.1   khorben 	struct bwfm_sdio_softc *sc = device_private(self);
    148      1.1   khorben 	struct sdmmc_attach_args *saa = aux;
    149      1.1   khorben 	struct sdmmc_function *sf = saa->sf;
    150      1.1   khorben 	struct bwfm_core *core;
    151      1.1   khorben 
    152      1.1   khorben 	aprint_naive("\n");
    153      1.1   khorben 
    154      1.1   khorben 	sc->sc_sf = malloc((sf->sc->sc_function_count + 1) *
    155      1.1   khorben 	    sizeof(struct sdmmc_function *), M_DEVBUF, M_WAITOK);
    156      1.1   khorben 
    157      1.1   khorben 	/* Copy all function pointers. */
    158      1.1   khorben 	SIMPLEQ_FOREACH(sf, &saa->sf->sc->sf_head, sf_list) {
    159      1.1   khorben 		sc->sc_sf[sf->number] = sf;
    160      1.1   khorben 	}
    161      1.1   khorben 	sf = saa->sf;
    162      1.1   khorben 
    163      1.1   khorben 	/*
    164      1.1   khorben 	 * TODO: set block size to 64 for func 1, 512 for func 2.
    165      1.1   khorben 	 * We might need to work on the SDMMC stack to be able to set
    166      1.1   khorben 	 * a block size per function.  Currently the IO code uses the
    167      1.1   khorben 	 * SDHC controller's maximum block length.
    168      1.1   khorben 	 */
    169      1.1   khorben 
    170      1.1   khorben 	/* Enable Function 1. */
    171      1.1   khorben 	if (sdmmc_io_function_enable(sc->sc_sf[1]) != 0) {
    172      1.1   khorben 		aprint_error_dev(self, "cannot enable function 1\n");
    173      1.1   khorben 		goto err;
    174      1.1   khorben 	}
    175      1.1   khorben 
    176      1.1   khorben 	DPRINTFN(2, ("%s: F1 signature read @0x18000000=%x\n", DEVNAME(sc),
    177      1.1   khorben 	    bwfm_sdio_read_4(sc, 0x18000000)));
    178      1.1   khorben 
    179      1.1   khorben 	/* Force PLL off */
    180      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR,
    181      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
    182      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ);
    183      1.1   khorben 
    184      1.1   khorben 	sc->sc_sc.sc_buscore_ops = &bwfm_sdio_buscore_ops;
    185      1.1   khorben 	if (bwfm_chip_attach(&sc->sc_sc) != 0) {
    186      1.1   khorben 		aprint_error_dev(self, "cannot attach chip\n");
    187      1.1   khorben 		goto err;
    188      1.1   khorben 	}
    189      1.1   khorben 
    190      1.1   khorben 	/* TODO: drive strength */
    191      1.1   khorben 
    192      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL,
    193      1.1   khorben 	    bwfm_sdio_read_1(sc, BWFM_SDIO_CCCR_BRCM_CARDCTRL) |
    194      1.1   khorben 	    BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET);
    195      1.1   khorben 
    196      1.1   khorben 	core = bwfm_chip_get_pmu(&sc->sc_sc);
    197      1.1   khorben 	bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL,
    198      1.1   khorben 	    bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_PMUCONTROL) |
    199      1.1   khorben 	    (BWFM_CHIP_REG_PMUCONTROL_RES_RELOAD <<
    200      1.1   khorben 	     BWFM_CHIP_REG_PMUCONTROL_RES_SHIFT));
    201      1.1   khorben 
    202      1.1   khorben 	sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops;
    203      1.1   khorben 	sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops;
    204      1.1   khorben 	bwfm_attach(&sc->sc_sc);
    205      1.1   khorben 
    206      1.1   khorben 	return;
    207      1.1   khorben 
    208      1.1   khorben err:
    209      1.1   khorben 	free(sc->sc_sf, M_DEVBUF);
    210      1.1   khorben }
    211      1.1   khorben 
    212      1.1   khorben int
    213      1.1   khorben bwfm_sdio_detach(struct device *self, int flags)
    214      1.1   khorben {
    215      1.1   khorben 	struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self;
    216      1.1   khorben 
    217      1.1   khorben 	bwfm_detach(&sc->sc_sc, flags);
    218      1.1   khorben 
    219      1.1   khorben 	free(sc->sc_sf, M_DEVBUF);
    220      1.1   khorben 
    221      1.1   khorben 	return 0;
    222      1.1   khorben }
    223      1.1   khorben 
    224  1.1.4.1  pgoyette void
    225  1.1.4.1  pgoyette bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0)
    226  1.1.4.1  pgoyette {
    227  1.1.4.1  pgoyette 	if (sc->sc_bar0 == bar0)
    228  1.1.4.1  pgoyette 		return;
    229  1.1.4.1  pgoyette 
    230  1.1.4.1  pgoyette 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW,
    231  1.1.4.1  pgoyette 	    (bar0 >>  8) & 0x80);
    232  1.1.4.1  pgoyette 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID,
    233  1.1.4.1  pgoyette 	    (bar0 >> 16) & 0xff);
    234  1.1.4.1  pgoyette 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH,
    235  1.1.4.1  pgoyette 	    (bar0 >> 24) & 0xff);
    236  1.1.4.1  pgoyette 	sc->sc_bar0 = bar0;
    237  1.1.4.1  pgoyette }
    238  1.1.4.1  pgoyette 
    239      1.1   khorben uint8_t
    240      1.1   khorben bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr)
    241      1.1   khorben {
    242      1.1   khorben 	struct sdmmc_function *sf;
    243      1.1   khorben 	uint8_t rv;
    244      1.1   khorben 
    245      1.1   khorben 	/*
    246      1.1   khorben 	 * figure out how to read the register based on address range
    247      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    248      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    249      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    250      1.1   khorben 	 */
    251      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    252      1.1   khorben 		sf = sc->sc_sf[0];
    253      1.1   khorben 	else
    254      1.1   khorben 		sf = sc->sc_sf[1];
    255      1.1   khorben 
    256      1.1   khorben 	rv = sdmmc_io_read_1(sf, addr);
    257      1.1   khorben 	return rv;
    258      1.1   khorben }
    259      1.1   khorben 
    260      1.1   khorben uint32_t
    261      1.1   khorben bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr)
    262      1.1   khorben {
    263      1.1   khorben 	struct sdmmc_function *sf;
    264      1.1   khorben 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
    265      1.1   khorben 	uint32_t rv;
    266      1.1   khorben 
    267  1.1.4.1  pgoyette 	bwfm_sdio_backplane(sc, bar0);
    268      1.1   khorben 
    269      1.1   khorben 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
    270      1.1   khorben 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
    271      1.1   khorben 
    272      1.1   khorben 	/*
    273      1.1   khorben 	 * figure out how to read the register based on address range
    274      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    275      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    276      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    277      1.1   khorben 	 */
    278      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    279      1.1   khorben 		sf = sc->sc_sf[0];
    280      1.1   khorben 	else
    281      1.1   khorben 		sf = sc->sc_sf[1];
    282      1.1   khorben 
    283      1.1   khorben 	rv = sdmmc_io_read_4(sf, addr);
    284      1.1   khorben 	return rv;
    285      1.1   khorben }
    286      1.1   khorben 
    287      1.1   khorben void
    288      1.1   khorben bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data)
    289      1.1   khorben {
    290      1.1   khorben 	struct sdmmc_function *sf;
    291      1.1   khorben 
    292      1.1   khorben 	/*
    293      1.1   khorben 	 * figure out how to read the register based on address range
    294      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    295      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    296      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    297      1.1   khorben 	 */
    298      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    299      1.1   khorben 		sf = sc->sc_sf[0];
    300      1.1   khorben 	else
    301      1.1   khorben 		sf = sc->sc_sf[1];
    302      1.1   khorben 
    303      1.1   khorben 	sdmmc_io_write_1(sf, addr, data);
    304      1.1   khorben }
    305      1.1   khorben 
    306      1.1   khorben void
    307      1.1   khorben bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data)
    308      1.1   khorben {
    309      1.1   khorben 	struct sdmmc_function *sf;
    310      1.1   khorben 	uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
    311      1.1   khorben 
    312  1.1.4.1  pgoyette 	bwfm_sdio_backplane(sc, bar0);
    313      1.1   khorben 
    314      1.1   khorben 	addr &= BWFM_SDIO_SB_OFT_ADDR_MASK;
    315      1.1   khorben 	addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG;
    316      1.1   khorben 
    317      1.1   khorben 	/*
    318      1.1   khorben 	 * figure out how to read the register based on address range
    319      1.1   khorben 	 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
    320      1.1   khorben 	 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
    321      1.1   khorben 	 * The rest: function 1 silicon backplane core registers
    322      1.1   khorben 	 */
    323      1.1   khorben 	if ((addr & ~0x7ff) == 0)
    324      1.1   khorben 		sf = sc->sc_sf[0];
    325      1.1   khorben 	else
    326      1.1   khorben 		sf = sc->sc_sf[1];
    327      1.1   khorben 
    328      1.1   khorben 	sdmmc_io_write_4(sf, addr, data);
    329      1.1   khorben }
    330      1.1   khorben 
    331      1.1   khorben uint32_t
    332      1.1   khorben bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
    333      1.1   khorben {
    334      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    335      1.1   khorben 	uint32_t val;
    336      1.1   khorben 
    337      1.1   khorben 	val = bwfm_sdio_read_4(sc, reg);
    338      1.1   khorben 	/* TODO: Workaround for 4335/4339 */
    339      1.1   khorben 
    340      1.1   khorben 	return val;
    341      1.1   khorben }
    342      1.1   khorben 
    343      1.1   khorben void
    344      1.1   khorben bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
    345      1.1   khorben {
    346      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    347      1.1   khorben 	bwfm_sdio_write_4(sc, reg, val);
    348      1.1   khorben }
    349      1.1   khorben 
    350      1.1   khorben int
    351      1.1   khorben bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm)
    352      1.1   khorben {
    353      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    354      1.1   khorben 	uint8_t clkval, clkset, clkmask;
    355      1.1   khorben 	int i;
    356      1.1   khorben 
    357      1.1   khorben 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL_REQ |
    358      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF;
    359      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
    360      1.1   khorben 
    361      1.1   khorben 	clkmask = BWFM_SDIO_FUNC1_CHIPCLKCSR_ALP_AVAIL |
    362      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_HT_AVAIL;
    363      1.1   khorben 	clkval = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
    364      1.1   khorben 
    365      1.1   khorben 	if ((clkval & ~clkmask) != clkset) {
    366      1.1   khorben 		printf("%s: wrote 0x%02x read 0x%02x\n", DEVNAME(sc),
    367      1.1   khorben 		    clkset, clkval);
    368      1.1   khorben 		return 1;
    369      1.1   khorben 	}
    370      1.1   khorben 
    371      1.1   khorben 	for (i = 1000; i > 0; i--) {
    372      1.1   khorben 		clkval = bwfm_sdio_read_1(sc,
    373      1.1   khorben 		    BWFM_SDIO_FUNC1_CHIPCLKCSR);
    374      1.1   khorben 		if (clkval & clkmask)
    375      1.1   khorben 			break;
    376      1.1   khorben 	}
    377      1.1   khorben 	if (i == 0) {
    378      1.1   khorben 		printf("%s: timeout on ALPAV wait, clkval 0x%02x\n",
    379      1.1   khorben 		    DEVNAME(sc), clkval);
    380      1.1   khorben 		return 1;
    381      1.1   khorben 	}
    382      1.1   khorben 
    383      1.1   khorben 	clkset = BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_HW_CLKREQ_OFF |
    384      1.1   khorben 	    BWFM_SDIO_FUNC1_CHIPCLKCSR_FORCE_ALP;
    385      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clkset);
    386      1.1   khorben 	delay(65);
    387      1.1   khorben 
    388      1.1   khorben 	bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SDIOPULLUP, 0);
    389      1.1   khorben 
    390      1.1   khorben 	return 0;
    391      1.1   khorben }
    392      1.1   khorben 
    393      1.1   khorben void
    394      1.1   khorben bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec)
    395      1.1   khorben {
    396      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    397      1.1   khorben 	struct bwfm_core *core;
    398      1.1   khorben 
    399      1.1   khorben 	core = bwfm_chip_get_core(&sc->sc_sc, BWFM_AGENT_CORE_SDIO_DEV);
    400      1.1   khorben 	bwfm_sdio_buscore_write(&sc->sc_sc,
    401      1.1   khorben 	    core->co_base + BWFM_SDPCMD_INTSTATUS, 0xFFFFFFFF);
    402      1.1   khorben 
    403      1.1   khorben #if notyet
    404      1.1   khorben 	if (rstvec)
    405      1.1   khorben 		bwfm_sdio_ram_write(&sc->sc_sc, 0, &rstvec, sizeof(rstvec));
    406      1.1   khorben #endif
    407      1.1   khorben }
    408      1.1   khorben 
    409      1.1   khorben int
    410  1.1.4.2  pgoyette bwfm_sdio_txcheck(struct bwfm_softc *bwfm, struct mbuf *m)
    411  1.1.4.2  pgoyette {
    412  1.1.4.2  pgoyette 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    413  1.1.4.2  pgoyette 
    414  1.1.4.2  pgoyette 	return 0;
    415  1.1.4.2  pgoyette }
    416  1.1.4.2  pgoyette 
    417  1.1.4.2  pgoyette 
    418  1.1.4.2  pgoyette int
    419      1.1   khorben bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf *m)
    420      1.1   khorben {
    421      1.1   khorben #ifdef BWFM_DEBUG
    422      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    423      1.1   khorben #endif
    424      1.1   khorben 	int ret = 1;
    425      1.1   khorben 
    426      1.1   khorben 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    427      1.1   khorben 
    428      1.1   khorben 	return ret;
    429      1.1   khorben }
    430      1.1   khorben 
    431      1.1   khorben int
    432      1.1   khorben bwfm_sdio_txctl(struct bwfm_softc *bwfm, char *buf, size_t len)
    433      1.1   khorben {
    434      1.1   khorben #ifdef BWFM_DEBUG
    435      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    436      1.1   khorben #endif
    437      1.1   khorben 	int ret = 1;
    438      1.1   khorben 
    439      1.1   khorben 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    440      1.1   khorben 
    441      1.1   khorben 	return ret;
    442      1.1   khorben }
    443      1.1   khorben 
    444      1.1   khorben int
    445      1.1   khorben bwfm_sdio_rxctl(struct bwfm_softc *bwfm, char *buf, size_t *len)
    446      1.1   khorben {
    447      1.1   khorben #ifdef BWFM_DEBUG
    448      1.1   khorben 	struct bwfm_sdio_softc *sc = (void *)bwfm;
    449      1.1   khorben #endif
    450      1.1   khorben 	int ret = 1;
    451      1.1   khorben 
    452      1.1   khorben 	DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__));
    453      1.1   khorben 
    454      1.1   khorben 	return ret;
    455      1.1   khorben }
    456