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/55d00c38baae
branches:  trunk
changeset: 459218:55d00c38baae
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 31c54c1e9520 -r 55d00c38baae 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