Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Add driver for the bcm2835 internal SD controller. ...



details:   https://anonhg.NetBSD.org/src/rev/811834dc0487
branches:  trunk
changeset: 825786:811834dc0487
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Jul 30 16:54:36 2017 +0000

description:
Add driver for the bcm2835 internal SD controller. On boards with SDIO
Wi-Fi, the internal SD controller is used for the SD card slot and the
Arasan SDHCI controller is used for SDIO.

diffstat:

 sys/arch/arm/broadcom/bcm2835_emmc.c   |   16 +-
 sys/arch/arm/broadcom/bcm2835_intr.c   |    6 +-
 sys/arch/arm/broadcom/bcm2835_obio.c   |   11 +-
 sys/arch/arm/broadcom/bcm2835_sdhost.c |  732 +++++++++++++++++++++++++++++++++
 sys/arch/arm/broadcom/bcm2835reg.h     |    5 +-
 sys/arch/arm/broadcom/files.bcm2835    |    7 +-
 sys/arch/evbarm/conf/RPI               |    6 +-
 sys/arch/evbarm/rpi/rpi_machdep.c      |   87 +++-
 8 files changed, 838 insertions(+), 32 deletions(-)

diffs (truncated from 1100 to 300 lines):

diff -r e6962460fb3d -r 811834dc0487 sys/arch/arm/broadcom/bcm2835_emmc.c
--- a/sys/arch/arm/broadcom/bcm2835_emmc.c      Sun Jul 30 16:13:24 2017 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_emmc.c      Sun Jul 30 16:54:36 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcm2835_emmc.c,v 1.30 2017/06/22 13:13:51 jmcneill Exp $       */
+/*     $NetBSD: bcm2835_emmc.c,v 1.31 2017/07/30 16:54:36 jmcneill Exp $       */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_emmc.c,v 1.30 2017/06/22 13:13:51 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_emmc.c,v 1.31 2017/07/30 16:54:36 jmcneill Exp $");
 
 #include "bcmdmac.h"
 
@@ -107,6 +107,7 @@
        prop_dictionary_t dict = device_properties(self);
        struct amba_attach_args *aaa = aux;
        prop_number_t frequency;
+       bool disable = false;
        int error;
 
        sc->sc.sc_dev = self;
@@ -122,6 +123,13 @@
        sc->sc.sc_clkbase = 50000;      /* Default to 50MHz */
        sc->sc_iot = aaa->aaa_iot;
 
+       prop_dictionary_get_bool(dict, "disable", &disable);
+       if (disable) {
+               aprint_naive(": disabled\n");
+               aprint_normal(": disabled\n");
+               return;
+       }
+
        /* Fetch the EMMC clock frequency from property if set. */
        frequency = prop_dictionary_get(dict, "frequency");
        if (frequency != NULL) {
@@ -131,8 +139,8 @@
        error = bus_space_map(sc->sc_iot, aaa->aaa_addr, aaa->aaa_size, 0,
            &sc->sc_ioh);
        if (error) {
-               aprint_error_dev(self,
-                   "can't map registers for %s: %d\n", aaa->aaa_name, error);
+               aprint_error(": can't map registers for %s: %d\n",
+                   aaa->aaa_name, error);
                return;
        }
        sc->sc_iob = aaa->aaa_addr;
diff -r e6962460fb3d -r 811834dc0487 sys/arch/arm/broadcom/bcm2835_intr.c
--- a/sys/arch/arm/broadcom/bcm2835_intr.c      Sun Jul 30 16:13:24 2017 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_intr.c      Sun Jul 30 16:54:36 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcm2835_intr.c,v 1.11 2015/08/01 14:18:00 skrll Exp $  */
+/*     $NetBSD: bcm2835_intr.c,v 1.12 2017/07/30 16:54:36 jmcneill Exp $       */
 
 /*-
  * Copyright (c) 2012, 2015 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.11 2015/08/01 14:18:00 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.12 2017/07/30 16:54:36 jmcneill Exp $");
 
 #define _INTR_PRIVATE
 
@@ -163,7 +163,7 @@
        "(unused 44)",  "pwa0",         "pwa1",         "(unused 47)",
        "smi",          "gpio[0]",      "gpio[1]",      "gpio[2]",
        "gpio[3]",      "i2c",          "spi",          "pcm",
-       "sdio",         "uart",         "(unused 58)",  "(unused 59)",
+       "sdhost",       "uart",         "(unused 58)",  "(unused 59)",
        "(unused 60)",  "(unused 61)",  "emmc",         "(unused 63)",
        "Timer",        "Mailbox",      "Doorbell0",    "Doorbell1",
        "GPU0 Halted",  "GPU1 Halted",  "Illegal #1",   "Illegal #0"
diff -r e6962460fb3d -r 811834dc0487 sys/arch/arm/broadcom/bcm2835_obio.c
--- a/sys/arch/arm/broadcom/bcm2835_obio.c      Sun Jul 30 16:13:24 2017 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_obio.c      Sun Jul 30 16:54:36 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcm2835_obio.c,v 1.26 2015/11/21 07:41:29 mlelstv Exp $        */
+/*     $NetBSD: bcm2835_obio.c,v 1.27 2017/07/30 16:54:36 jmcneill Exp $       */
 
 /*-
  * Copyright (c) 2012, 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_obio.c,v 1.26 2015/11/21 07:41:29 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_obio.c,v 1.27 2017/07/30 16:54:36 jmcneill Exp $");
 
 #include "locators.h"
 #include "obio.h"
@@ -148,6 +148,13 @@
                .ad_intr = -1,
        },
        {
+               /* SD host interface */
+               .ad_name = "sdhost",
+               .ad_addr = BCM2835_SDHOST_BASE,
+               .ad_size = BCM2835_SDHOST_SIZE,
+               .ad_intr = BCM2835_INT_SDHOST,
+       },
+       {
                /* eMMC interface */
                .ad_name = "emmc",
                .ad_addr = BCM2835_EMMC_BASE,
diff -r e6962460fb3d -r 811834dc0487 sys/arch/arm/broadcom/bcm2835_sdhost.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_sdhost.c    Sun Jul 30 16:54:36 2017 +0000
@@ -0,0 +1,732 @@
+/* $NetBSD: bcm2835_sdhost.c,v 1.1 2017/07/30 16:54:36 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_sdhost.c,v 1.1 2017/07/30 16:54:36 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/gpio.h>
+
+#include <arm/broadcom/bcm2835reg.h>
+#include <arm/broadcom/bcm_amba.h>
+#include <arm/broadcom/bcm2835_dmac.h>
+
+#include <dev/sdmmc/sdmmcvar.h>
+#include <dev/sdmmc/sdmmcchip.h>
+#include <dev/sdmmc/sdmmc_ioreg.h>
+
+#define        SDCMD           0x00
+#define         SDCMD_NEW      __BIT(15)
+#define         SDCMD_FAIL     __BIT(14)
+#define         SDCMD_BUSY     __BIT(11)
+#define         SDCMD_NORESP   __BIT(10)
+#define         SDCMD_LONGRESP __BIT(9)
+#define         SDCMD_WRITE    __BIT(7)
+#define         SDCMD_READ     __BIT(6)
+#define        SDARG           0x04
+#define        SDTOUT          0x08
+#define         SDTOUT_DEFAULT 0xf00000
+#define        SDCDIV          0x0c
+#define         SDCDIV_MASK    __BITS(10,0)
+#define        SDRSP0          0x10
+#define        SDRSP1          0x14
+#define        SDRSP2          0x18
+#define        SDRSP3          0x1c
+#define        SDHSTS          0x20
+#define         SDHSTS_BUSY    __BIT(10)
+#define         SDHSTS_BLOCK   __BIT(9)
+#define         SDHSTS_SDIO    __BIT(8)
+#define         SDHSTS_REW_TO  __BIT(7)
+#define         SDHSTS_CMD_TO  __BIT(6)
+#define         SDHSTS_CRC16_E __BIT(5)
+#define         SDHSTS_CRC7_E  __BIT(4)
+#define         SDHSTS_FIFO_E  __BIT(3)
+#define         SDHSTS_DATA    __BIT(0)
+#define        SDVDD           0x30
+#define         SDVDD_POWER    __BIT(0)
+#define        SDEDM           0x34
+#define         SDEDM_RD_FIFO  __BITS(18,14)
+#define         SDEDM_WR_FIFO  __BITS(13,9)
+#define        SDHCFG          0x38
+#define         SDHCFG_BUSY_EN __BIT(10)
+#define         SDHCFG_BLOCK_EN __BIT(8)
+#define         SDHCFG_SDIO_EN __BIT(5)
+#define         SDHCFG_DATA_EN __BIT(4)
+#define         SDHCFG_SLOW    __BIT(3)
+#define         SDHCFG_WIDE_EXT __BIT(2)
+#define         SDHCFG_WIDE_INT __BIT(1)
+#define         SDHCFG_REL_CMD __BIT(0)
+#define        SDHBCT          0x3c
+#define        SDDATA          0x40
+#define        SDHBLC          0x50
+
+struct sdhost_softc;
+
+static int     sdhost_match(device_t, cfdata_t, void *);
+static void    sdhost_attach(device_t, device_t, void *);
+static void    sdhost_attach_i(device_t);
+
+static int     sdhost_intr(void *);
+static int     sdhost_dma_setup(struct sdhost_softc *);
+static void    sdhost_dma_done(uint32_t, uint32_t, void *);
+
+static int     sdhost_host_reset(sdmmc_chipset_handle_t);
+static uint32_t        sdhost_host_ocr(sdmmc_chipset_handle_t);
+static int     sdhost_host_maxblklen(sdmmc_chipset_handle_t);
+static int     sdhost_card_detect(sdmmc_chipset_handle_t);
+static int     sdhost_write_protect(sdmmc_chipset_handle_t);
+static int     sdhost_bus_power(sdmmc_chipset_handle_t, uint32_t);
+static int     sdhost_bus_clock(sdmmc_chipset_handle_t, int, bool);
+static int     sdhost_bus_width(sdmmc_chipset_handle_t, int);
+static int     sdhost_bus_rod(sdmmc_chipset_handle_t, int);
+static void    sdhost_exec_command(sdmmc_chipset_handle_t,
+                                     struct sdmmc_command *);
+static void    sdhost_card_enable_intr(sdmmc_chipset_handle_t, int);
+static void    sdhost_card_intr_ack(sdmmc_chipset_handle_t);
+
+void           sdhost_dump_regs(void);
+
+static struct sdmmc_chip_functions sdhost_chip_functions = {
+       .host_reset = sdhost_host_reset,
+       .host_ocr = sdhost_host_ocr,
+       .host_maxblklen = sdhost_host_maxblklen,
+       .card_detect = sdhost_card_detect,
+       .write_protect = sdhost_write_protect,
+       .bus_power = sdhost_bus_power,
+       .bus_clock_ddr = sdhost_bus_clock,
+       .bus_width = sdhost_bus_width,
+       .bus_rod = sdhost_bus_rod,
+       .exec_command = sdhost_exec_command,
+       .card_enable_intr = sdhost_card_enable_intr,
+       .card_intr_ack = sdhost_card_intr_ack,
+};
+
+struct sdhost_softc {
+       device_t sc_dev;
+       bus_space_tag_t sc_bst;
+       bus_space_handle_t sc_bsh;
+       bus_dma_tag_t sc_dmat;
+
+       bus_addr_t sc_addr;
+
+       void *sc_ih;
+       kmutex_t sc_intr_lock;
+       kcondvar_t sc_intr_cv;
+       kcondvar_t sc_dma_cv;
+
+       u_int sc_rate;
+
+       int sc_mmc_width;
+       int sc_mmc_present;
+
+       device_t sc_sdmmc_dev;
+
+       struct bcm_dmac_channel *sc_dmac;
+
+       bus_dmamap_t sc_dmamap;
+       bus_dma_segment_t sc_segs[1];
+       struct bcm_dmac_conblk *sc_cblk;
+
+       uint32_t sc_intr_hsts;
+
+       uint32_t sc_dma_status;
+       uint32_t sc_dma_error;
+};
+
+CFATTACH_DECL_NEW(bcmsdhost, sizeof(struct sdhost_softc),
+       sdhost_match, sdhost_attach, NULL, NULL);
+
+#define SDHOST_WRITE(sc, reg, val)     \
+       bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define SDHOST_READ(sc, reg) \
+       bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+
+static int
+sdhost_match(device_t parent, cfdata_t cf, void *aux)
+{
+       struct amba_attach_args * const aaa = aux;
+
+       return strcmp(aaa->aaa_name, "sdhost") == 0;
+}
+
+static void
+sdhost_attach(device_t parent, device_t self, void *aux)
+{
+       struct sdhost_softc * const sc = device_private(self);
+       struct amba_attach_args * const aaa = aux;



Home | Main Index | Thread Index | Old Index