Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc From OpenBSD:
details: https://anonhg.NetBSD.org/src/rev/25e591f91a06
branches: trunk
changeset: 453914:25e591f91a06
user: mlelstv <mlelstv%NetBSD.org@localhost>
date: Sun Sep 01 05:51:45 2019 +0000
description:
>From OpenBSD:
- All the missing pieces (firmware load, chip setup, protocol handling)
TX queue and interrupt handling via sdmmc_task.
Fix locking.
Fix packet parsing.
Add parser for original firmware config files.
diffstat:
sys/dev/sdmmc/if_bwfm_sdio.c | 1543 +++++++++++++++++++++++++++++++++++++++--
sys/dev/sdmmc/if_bwfm_sdio.h | 199 +++++
2 files changed, 1653 insertions(+), 89 deletions(-)
diffs (truncated from 1977 to 300 lines):
diff -r 3cf161fff0ae -r 25e591f91a06 sys/dev/sdmmc/if_bwfm_sdio.c
--- a/sys/dev/sdmmc/if_bwfm_sdio.c Sun Sep 01 05:45:42 2019 +0000
+++ b/sys/dev/sdmmc/if_bwfm_sdio.c Sun Sep 01 05:51:45 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bwfm_sdio.c,v 1.3 2018/05/11 07:41:11 maya Exp $ */
+/* $NetBSD: if_bwfm_sdio.c,v 1.4 2019/09/01 05:51:45 mlelstv Exp $ */
/* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -20,14 +20,13 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
+#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/mutex.h>
-#include <sys/workqueue.h>
-#include <sys/pcq.h>
#include <net/bpf.h>
#include <net/if.h>
@@ -37,20 +36,16 @@
#include <netinet/in.h>
+#include <dev/firmload.h>
+
#include <net80211/ieee80211_var.h>
+#include <dev/sdmmc/sdmmcdevs.h>
#include <dev/sdmmc/sdmmcvar.h>
#include <dev/ic/bwfmvar.h>
#include <dev/ic/bwfmreg.h>
-
-#define BWFM_SDIO_CCCR_BRCM_CARDCAP 0xf0
-#define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
-#define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
-#define BWFM_SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
-#define BWFM_SDIO_CCCR_BRCM_CARDCTRL 0xf1
-#define BWFM_SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
-#define BWFM_SDIO_CCCR_BRCM_SEPINT 0xf2
+#include <dev/sdmmc/if_bwfm_sdio.h>
#ifdef BWFM_DEBUG
#define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0)
@@ -63,34 +58,122 @@
#define DEVNAME(sc) device_xname((sc)->sc_sc.sc_dev)
+enum bwfm_sdio_clkstate {
+ CLK_NONE,
+ CLK_SDONLY,
+ CLK_PENDING,
+ CLK_AVAIL
+};
+
struct bwfm_sdio_softc {
- struct bwfm_softc sc_sc;
+ struct bwfm_softc sc_sc;
+ kmutex_t sc_lock;
+ kmutex_t sc_intr_lock;
+
+ bool sc_bwfm_attached;
+
struct sdmmc_function **sc_sf;
- uint32_t sc_bar0;
+ size_t sc_sf_size;
+
+ uint32_t sc_bar0;
+ enum bwfm_sdio_clkstate sc_clkstate;
+ bool sc_sr_enabled;
+ bool sc_alp_only;
+ bool sc_sleeping;
+
+ struct sdmmc_task sc_task;
+ bool sc_task_queued;
+
+ uint8_t sc_tx_seq;
+ uint8_t sc_tx_max_seq;
+ int sc_tx_count;
+ MBUFQ_HEAD() sc_tx_queue;
+
+ struct mbuf *sc_rxctl_queue;
+ kcondvar_t sc_rxctl_cv;
+
+ void *sc_ih;
+ struct bwfm_core *sc_cc;
+
+ char *sc_bounce_buf;
+ size_t sc_bounce_size;
+
+ uint32_t sc_console_addr;
+ char *sc_console_buf;
+ size_t sc_console_buf_size;
+ uint32_t sc_console_readidx;
};
-int bwfm_sdio_match(device_t, cfdata_t, void *);
-void bwfm_sdio_attach(device_t, struct device *, void *);
-int bwfm_sdio_detach(device_t, int);
+int bwfm_sdio_match(device_t, cfdata_t, void *);
+void bwfm_sdio_attach(device_t, struct device *, void *);
+int bwfm_sdio_detach(device_t, int);
+void bwfm_sdio_attachhook(device_t);
-void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t);
-uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t);
-uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t);
-void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t,
+void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t);
+uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t);
+uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t);
+void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t,
uint8_t);
-void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t,
+void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t,
+ uint32_t);
+
+uint32_t bwfm_sdio_dev_read(struct bwfm_sdio_softc *, uint32_t);
+void bwfm_sdio_dev_write(struct bwfm_sdio_softc *, uint32_t,
uint32_t);
-uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t);
-void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t,
+uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t);
+void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t,
uint32_t);
-int bwfm_sdio_buscore_prepare(struct bwfm_softc *);
-void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t);
+int bwfm_sdio_buscore_prepare(struct bwfm_softc *);
+void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t);
+
+int bwfm_sdio_buf_read(struct bwfm_sdio_softc *,
+ struct sdmmc_function *, uint32_t, char *, size_t);
+int bwfm_sdio_buf_write(struct bwfm_sdio_softc *,
+ struct sdmmc_function *, uint32_t, char *, size_t);
+
+struct mbuf *bwfm_sdio_newbuf(void);
+void bwfm_qput(struct mbuf **, struct mbuf *);
+struct mbuf *bwfm_qget(struct mbuf **);
+
+uint32_t bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *,
+ uint32_t, char *, size_t, int);
+uint32_t bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *,
+ char *, size_t, int);
+
+int bwfm_sdio_intr(void *);
+void bwfm_sdio_task(void *);
+void bwfm_sdio_task1(struct bwfm_sdio_softc *);
-int bwfm_sdio_txcheck(struct bwfm_softc *);
-int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf *);
-int bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t);
-int bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *);
+int bwfm_nvram_convert(u_char *, size_t, size_t *);
+int bwfm_sdio_load_microcode(struct bwfm_sdio_softc *,
+ u_char *, size_t, u_char *, size_t);
+void bwfm_sdio_clkctl(struct bwfm_sdio_softc *,
+ enum bwfm_sdio_clkstate, bool);
+void bwfm_sdio_htclk(struct bwfm_sdio_softc *, bool, bool);
+
+int bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *, bool, bool);
+void bwfm_sdio_readshared(struct bwfm_sdio_softc *);
+
+int bwfm_sdio_txcheck(struct bwfm_softc *);
+int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf **);
+int bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t);
+int bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *);
+
+int bwfm_sdio_tx_ok(struct bwfm_sdio_softc *);
+void bwfm_sdio_tx_frames(struct bwfm_sdio_softc *);
+void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *,
+ struct mbuf *);
+void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *,
+ struct mbuf *);
+
+void bwfm_sdio_rx_frames(struct bwfm_sdio_softc *);
+void bwfm_sdio_rx_glom(struct bwfm_sdio_softc *,
+ uint16_t *, int, uint16_t *);
+
+#ifdef BWFM_DEBUG
+void bwfm_sdio_debug_console(struct bwfm_sdio_softc *);
+#endif
struct bwfm_bus_ops bwfm_sdio_bus_ops = {
.bs_init = NULL,
@@ -113,21 +196,54 @@
CFATTACH_DECL_NEW(bwfm_sdio, sizeof(struct bwfm_sdio_softc),
bwfm_sdio_match, bwfm_sdio_attach, bwfm_sdio_detach, NULL);
+static const struct bwfm_sdio_product {
+ uint32_t manufacturer;
+ uint32_t product;
+ const char *cisinfo[4];
+} bwfm_sdio_products[] = {
+ {
+ SDMMC_VENDOR_BROADCOM,
+ SDMMC_PRODUCT_BROADCOM_BCM4330,
+ SDMMC_CIS_BROADCOM_BCM4330
+ },
+ {
+ SDMMC_VENDOR_BROADCOM,
+ SDMMC_PRODUCT_BROADCOM_BCM4334,
+ SDMMC_CIS_BROADCOM_BCM4334
+ },
+ {
+ SDMMC_VENDOR_BROADCOM,
+ SDMMC_PRODUCT_BROADCOM_BCM43143,
+ SDMMC_CIS_BROADCOM_BCM43143
+ },
+ {
+ SDMMC_VENDOR_BROADCOM,
+ SDMMC_PRODUCT_BROADCOM_BCM43430,
+ SDMMC_CIS_BROADCOM_BCM43430
+ },
+};
+
int
bwfm_sdio_match(device_t parent, cfdata_t match, void *aux)
{
struct sdmmc_attach_args *saa = aux;
struct sdmmc_function *sf = saa->sf;
struct sdmmc_cis *cis;
+ const struct bwfm_sdio_product *bsp;
+ int i;
/* Not SDIO. */
if (sf == NULL)
return 0;
- /* Look for Broadcom 433[04]. */
cis = &sf->sc->sc_fn0->cis;
- if (cis->manufacturer != 0x02d0 || (cis->product != 0x4330 &&
- cis->product != 0x4334))
+ for (i = 0; i < __arraycount(bwfm_sdio_products); ++i) {
+ bsp = &bwfm_sdio_products[i];
+ if (cis->manufacturer == bsp->manufacturer &&
+ cis->product == bsp->product)
+ break;
+ }
+ if (i >= __arraycount(bwfm_sdio_products))
return 0;
/* We need both functions, but ... */
@@ -148,33 +264,46 @@
struct sdmmc_attach_args *saa = aux;
struct sdmmc_function *sf = saa->sf;
struct bwfm_core *core;
+ uint32_t reg;
+
+ sc->sc_sc.sc_dev = self;
aprint_naive("\n");
+ aprint_normal("\n");
- sc->sc_sf = malloc((sf->sc->sc_function_count + 1) *
- sizeof(struct sdmmc_function *), M_DEVBUF, M_WAITOK);
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&sc->sc_rxctl_cv, "bwfmctl");
+ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
+
+ sdmmc_init_task(&sc->sc_task, bwfm_sdio_task, sc);
+ sc->sc_task_queued = false;
+
+ sc->sc_bounce_size = 64 * 1024;
+ sc->sc_bounce_buf = kmem_alloc(sc->sc_bounce_size, KM_SLEEP);
+ sc->sc_tx_seq = 0xff;
+ MBUFQ_INIT(&sc->sc_tx_queue);
+ sc->sc_rxctl_queue = NULL;
+
+ sc->sc_sf_size = (sf->sc->sc_function_count + 1)
+ * sizeof(struct sdmmc_function *);
+ sc->sc_sf = kmem_zalloc(sc->sc_sf_size, KM_SLEEP);
/* Copy all function pointers. */
SIMPLEQ_FOREACH(sf, &saa->sf->sc->sf_head, sf_list) {
sc->sc_sf[sf->number] = sf;
}
- sf = saa->sf;
- /*
- * TODO: set block size to 64 for func 1, 512 for func 2.
- * We might need to work on the SDMMC stack to be able to set
- * a block size per function. Currently the IO code uses the
- * SDHC controller's maximum block length.
- */
+ sdmmc_io_set_blocklen(sc->sc_sf[1]->sc, sc->sc_sf[1], 64);
+ sdmmc_io_set_blocklen(sc->sc_sf[2]->sc, sc->sc_sf[2], 512);
- /* Enable Function 1. */
- if (sdmmc_io_function_enable(sc->sc_sf[1]) != 0) {
- aprint_error_dev(self, "cannot enable function 1\n");
- goto err;
- }
+ /* Enable Function 1. */
Home |
Main Index |
Thread Index |
Old Index