From owner-svn-src-head@freebsd.org Thu Jun 21 11:49:23 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A5FAD101BB63; Thu, 21 Jun 2018 11:49:22 +0000 (UTC) (envelope-from kibab@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4A9317900D; Thu, 21 Jun 2018 11:49:22 +0000 (UTC) (envelope-from kibab@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 25F99114D0; Thu, 21 Jun 2018 11:49:22 +0000 (UTC) (envelope-from kibab@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w5LBnMIE061188; Thu, 21 Jun 2018 11:49:22 GMT (envelope-from kibab@FreeBSD.org) Received: (from kibab@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w5LBnLl9061185; Thu, 21 Jun 2018 11:49:21 GMT (envelope-from kibab@FreeBSD.org) Message-Id: <201806211149.w5LBnLl9061185@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kibab set sender to kibab@FreeBSD.org using -f From: Ilya Bakulin Date: Thu, 21 Jun 2018 11:49:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r335476 - in head/sys: arm/allwinner conf X-SVN-Group: head X-SVN-Commit-Author: kibab X-SVN-Commit-Paths: in head/sys: arm/allwinner conf X-SVN-Commit-Revision: 335476 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 Jun 2018 11:49:23 -0000 Author: kibab Date: Thu Jun 21 11:49:21 2018 New Revision: 335476 URL: https://svnweb.freebsd.org/changeset/base/335476 Log: Add MMCCAM support to AllWinner MMC driver Using MMCCAM on AllWinner boards is now possible, reaching highest possible data transfer speed. For now, MMCCAM doesn't scan cards on boot. This means that scanning has to be done manually and that it's not possible to mount root FS from MMC/SD card since there is no block device at the boot time. For manually scanning the cards, run: # camcontrol rescan X:0:0 Where X is the bus number (look at camcontrol devlist to determine bus number assigned to the MMC controller). Reviewed by: manu Approved by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D15891 Modified: head/sys/arm/allwinner/aw_mmc.c head/sys/arm/allwinner/files.allwinner head/sys/conf/files.arm64 Modified: head/sys/arm/allwinner/aw_mmc.c ============================================================================== --- head/sys/arm/allwinner/aw_mmc.c Thu Jun 21 11:43:54 2018 (r335475) +++ head/sys/arm/allwinner/aw_mmc.c Thu Jun 21 11:49:21 2018 (r335476) @@ -55,6 +55,16 @@ __FBSDID("$FreeBSD$"); #include #include +#include "opt_mmccam.h" + +#ifdef MMCCAM +#include +#include +#include +#include +#include +#endif + #define AW_MMC_MEMRES 0 #define AW_MMC_IRQRES 1 #define AW_MMC_RESSZ 2 @@ -112,7 +122,14 @@ struct aw_mmc_softc { int aw_timeout; struct callout aw_timeoutc; struct mmc_host aw_host; +#ifdef MMCCAM + union ccb * ccb; + struct cam_devq * devq; + struct cam_sim * sim; + struct mtx sim_mtx; +#else struct mmc_request * aw_req; +#endif struct mtx aw_mtx; struct resource * aw_res[AW_MMC_RESSZ]; struct aw_mmc_conf * aw_mmc_conf; @@ -148,11 +165,19 @@ static int aw_mmc_init(struct aw_mmc_softc *); static void aw_mmc_intr(void *); static int aw_mmc_update_clock(struct aw_mmc_softc *, uint32_t); +static void aw_mmc_print_error(uint32_t); static int aw_mmc_update_ios(device_t, device_t); static int aw_mmc_request(device_t, device_t, struct mmc_request *); static int aw_mmc_get_ro(device_t, device_t); static int aw_mmc_acquire_host(device_t, device_t); static int aw_mmc_release_host(device_t, device_t); +#ifdef MMCCAM +static void aw_mmc_cam_action(struct cam_sim *, union ccb *); +static void aw_mmc_cam_poll(struct cam_sim *); +static int aw_mmc_cam_settran_settings(struct aw_mmc_softc *, union ccb *); +static int aw_mmc_cam_request(struct aw_mmc_softc *, union ccb *); +static void aw_mmc_cam_handle_mmcio(struct cam_sim *, union ccb *); +#endif #define AW_MMC_LOCK(_sc) mtx_lock(&(_sc)->aw_mtx) #define AW_MMC_UNLOCK(_sc) mtx_unlock(&(_sc)->aw_mtx) @@ -161,7 +186,201 @@ static int aw_mmc_release_host(device_t, device_t); #define AW_MMC_WRITE_4(_sc, _reg, _value) \ bus_write_4((_sc)->aw_res[AW_MMC_MEMRES], _reg, _value) +#ifdef MMCCAM +static void +aw_mmc_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb) +{ + struct aw_mmc_softc *sc; + + sc = cam_sim_softc(sim); + + aw_mmc_cam_request(sc, ccb); +} + +static void +aw_mmc_cam_action(struct cam_sim *sim, union ccb *ccb) +{ + struct aw_mmc_softc *sc; + + sc = cam_sim_softc(sim); + if (sc == NULL) { + ccb->ccb_h.status = CAM_SEL_TIMEOUT; + xpt_done(ccb); + return; + } + + mtx_assert(&sc->sim_mtx, MA_OWNED); + + switch (ccb->ccb_h.func_code) { + case XPT_PATH_INQ: + { + struct ccb_pathinq *cpi; + + cpi = &ccb->cpi; + cpi->version_num = 1; + cpi->hba_inquiry = 0; + cpi->target_sprt = 0; + cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN; + cpi->hba_eng_cnt = 0; + cpi->max_target = 0; + cpi->max_lun = 0; + cpi->initiator_id = 1; + cpi->maxio = (sc->aw_mmc_conf->dma_xferlen * + AW_MMC_DMA_SEGS) / MMC_SECTOR_SIZE; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "Deglitch Networks", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->bus_id = cam_sim_bus(sim); + cpi->protocol = PROTO_MMCSD; + cpi->protocol_version = SCSI_REV_0; + cpi->transport = XPORT_MMCSD; + cpi->transport_version = 1; + + cpi->ccb_h.status = CAM_REQ_CMP; + break; + } + case XPT_GET_TRAN_SETTINGS: + { + struct ccb_trans_settings *cts = &ccb->cts; + + if (bootverbose) + device_printf(sc->aw_dev, "Got XPT_GET_TRAN_SETTINGS\n"); + + cts->protocol = PROTO_MMCSD; + cts->protocol_version = 1; + cts->transport = XPORT_MMCSD; + cts->transport_version = 1; + cts->xport_specific.valid = 0; + cts->proto_specific.mmc.host_ocr = sc->aw_host.host_ocr; + cts->proto_specific.mmc.host_f_min = sc->aw_host.f_min; + cts->proto_specific.mmc.host_f_max = sc->aw_host.f_max; + cts->proto_specific.mmc.host_caps = sc->aw_host.caps; + memcpy(&cts->proto_specific.mmc.ios, &sc->aw_host.ios, sizeof(struct mmc_ios)); + ccb->ccb_h.status = CAM_REQ_CMP; + break; + } + case XPT_SET_TRAN_SETTINGS: + { + if (bootverbose) + device_printf(sc->aw_dev, "Got XPT_SET_TRAN_SETTINGS\n"); + aw_mmc_cam_settran_settings(sc, ccb); + ccb->ccb_h.status = CAM_REQ_CMP; + break; + } + case XPT_RESET_BUS: + if (bootverbose) + device_printf(sc->aw_dev, "Got XPT_RESET_BUS, ACK it...\n"); + ccb->ccb_h.status = CAM_REQ_CMP; + break; + case XPT_MMC_IO: + /* + * Here is the HW-dependent part of + * sending the command to the underlying h/w + * At some point in the future an interrupt comes. + * Then the request will be marked as completed. + */ + ccb->ccb_h.status = CAM_REQ_INPROG; + + aw_mmc_cam_handle_mmcio(sim, ccb); + return; + /* NOTREACHED */ + break; + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + break; + } + xpt_done(ccb); + return; +} + +static void +aw_mmc_cam_poll(struct cam_sim *sim) +{ + return; +} + static int +aw_mmc_cam_settran_settings(struct aw_mmc_softc *sc, union ccb *ccb) +{ + struct mmc_ios *ios; + struct mmc_ios *new_ios; + struct ccb_trans_settings_mmc *cts; + + ios = &sc->aw_host.ios; + + cts = &ccb->cts.proto_specific.mmc; + new_ios = &cts->ios; + + /* Update only requested fields */ + if (cts->ios_valid & MMC_CLK) { + ios->clock = new_ios->clock; + device_printf(sc->aw_dev, "Clock => %d\n", ios->clock); + } + if (cts->ios_valid & MMC_VDD) { + ios->vdd = new_ios->vdd; + device_printf(sc->aw_dev, "VDD => %d\n", ios->vdd); + } + if (cts->ios_valid & MMC_CS) { + ios->chip_select = new_ios->chip_select; + device_printf(sc->aw_dev, "CS => %d\n", ios->chip_select); + } + if (cts->ios_valid & MMC_BW) { + ios->bus_width = new_ios->bus_width; + device_printf(sc->aw_dev, "Bus width => %d\n", ios->bus_width); + } + if (cts->ios_valid & MMC_PM) { + ios->power_mode = new_ios->power_mode; + device_printf(sc->aw_dev, "Power mode => %d\n", ios->power_mode); + } + if (cts->ios_valid & MMC_BT) { + ios->timing = new_ios->timing; + device_printf(sc->aw_dev, "Timing => %d\n", ios->timing); + } + if (cts->ios_valid & MMC_BM) { + ios->bus_mode = new_ios->bus_mode; + device_printf(sc->aw_dev, "Bus mode => %d\n", ios->bus_mode); + } + + return (aw_mmc_update_ios(sc->aw_dev, NULL)); +} + +static int +aw_mmc_cam_request(struct aw_mmc_softc *sc, union ccb *ccb) +{ + struct ccb_mmcio *mmcio; + + mmcio = &ccb->mmcio; + + AW_MMC_LOCK(sc); + +#ifdef DEBUG + if (__predict_false(bootverbose)) { + device_printf(sc->aw_dev, "CMD%u arg %#x flags %#x dlen %u dflags %#x\n", + mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags, + mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0, + mmcio->cmd.data != NULL ? mmcio->cmd.data->flags: 0); + } +#endif + if (mmcio->cmd.data != NULL) { + if (mmcio->cmd.data->len == 0 || mmcio->cmd.data->flags == 0) + panic("data->len = %d, data->flags = %d -- something is b0rked", + (int)mmcio->cmd.data->len, mmcio->cmd.data->flags); + } + if (sc->ccb != NULL) { + device_printf(sc->aw_dev, "Controller still has an active command\n"); + return (EBUSY); + } + sc->ccb = ccb; + /* aw_mmc_request locks again */ + AW_MMC_UNLOCK(sc); + aw_mmc_request(sc->aw_dev, NULL, NULL); + + return (0); +} +#endif /* MMCCAM */ + +static int aw_mmc_probe(device_t dev) { @@ -192,7 +411,9 @@ aw_mmc_attach(device_t dev) sc->aw_mmc_conf = (struct aw_mmc_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; +#ifndef MMCCAM sc->aw_req = NULL; +#endif if (bus_alloc_resources(dev, aw_mmc_res_spec, sc->aw_res) != 0) { device_printf(dev, "cannot allocate device resources\n"); return (ENXIO); @@ -295,6 +516,35 @@ aw_mmc_attach(device_t dev) if (bus_width >= 8) sc->aw_host.caps |= MMC_CAP_8_BIT_DATA; +#ifdef MMCCAM + child = NULL; /* Not used by MMCCAM, need to silence compiler warnings */ + sc->ccb = NULL; + if ((sc->devq = cam_simq_alloc(1)) == NULL) { + goto fail; + } + + mtx_init(&sc->sim_mtx, "awmmcsim", NULL, MTX_DEF); + sc->sim = cam_sim_alloc(aw_mmc_cam_action, aw_mmc_cam_poll, + "aw_mmc_sim", sc, device_get_unit(dev), + &sc->sim_mtx, 1, 1, sc->devq); + + if (sc->sim == NULL) { + cam_simq_free(sc->devq); + device_printf(dev, "cannot allocate CAM SIM\n"); + goto fail; + } + + mtx_lock(&sc->sim_mtx); + if (xpt_bus_register(sc->sim, sc->aw_dev, 0) != 0) { + device_printf(dev, "cannot register SCSI pass-through bus\n"); + cam_sim_free(sc->sim, FALSE); + cam_simq_free(sc->devq); + mtx_unlock(&sc->sim_mtx); + goto fail; + } + + mtx_unlock(&sc->sim_mtx); +#else /* !MMCCAM */ child = device_add_child(dev, "mmc", -1); if (child == NULL) { device_printf(dev, "attaching MMC bus failed!\n"); @@ -305,7 +555,7 @@ aw_mmc_attach(device_t dev) device_delete_child(dev, child); goto fail; } - +#endif /* MMCCAM */ return (0); fail: @@ -314,6 +564,17 @@ fail: bus_teardown_intr(dev, sc->aw_res[AW_MMC_IRQRES], sc->aw_intrhand); bus_release_resources(dev, aw_mmc_res_spec, sc->aw_res); +#ifdef MMCCAM + if (sc->sim != NULL) { + mtx_lock(&sc->sim_mtx); + xpt_bus_deregister(cam_sim_path(sc->sim)); + cam_sim_free(sc->sim, FALSE); + mtx_unlock(&sc->sim_mtx); + } + + if (sc->devq != NULL) + cam_simq_free(sc->devq); +#endif return (ENXIO); } @@ -437,7 +698,11 @@ aw_mmc_prepare_dma(struct aw_mmc_softc *sc) struct mmc_command *cmd; uint32_t val; +#ifdef MMCCAM + cmd = &sc->ccb->mmcio.cmd; +#else cmd = sc->aw_req->cmd; +#endif if (cmd->data->len > (sc->aw_mmc_conf->dma_xferlen * AW_MMC_DMA_SEGS)) return (EFBIG); error = bus_dmamap_load(sc->aw_dma_buf_tag, sc->aw_dma_buf_map, @@ -549,11 +814,25 @@ static void aw_mmc_req_done(struct aw_mmc_softc *sc) { struct mmc_command *cmd; +#ifdef MMCCAM + union ccb *ccb; +#else struct mmc_request *req; +#endif uint32_t val, mask; int retry; +#ifdef MMCCAM + ccb = sc->ccb; + cmd = &ccb->mmcio.cmd; +#else cmd = sc->aw_req->cmd; +#endif +#ifdef DEBUG + if (bootverbose) { + device_printf(sc->aw_dev, "%s: cmd %d err %d\n", __func__, cmd->opcode, cmd->error); + } +#endif if (cmd->error != MMC_ERR_NONE) { /* Reset the FIFO and DMA engines. */ mask = AW_MMC_GCTL_FIFO_RST | AW_MMC_GCTL_DMA_RST; @@ -573,14 +852,21 @@ aw_mmc_req_done(struct aw_mmc_softc *sc) aw_mmc_update_clock(sc, 1); } - req = sc->aw_req; callout_stop(&sc->aw_timeoutc); - sc->aw_req = NULL; sc->aw_intr = 0; sc->aw_resid = 0; sc->aw_dma_map_err = 0; sc->aw_intr_wait = 0; +#ifdef MMCCAM + sc->ccb = NULL; + ccb->ccb_h.status = + (ccb->mmcio.cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR); + xpt_done(ccb); +#else + req = sc->aw_req; + sc->aw_req = NULL; req->done(req); +#endif } static void @@ -597,7 +883,11 @@ aw_mmc_req_ok(struct aw_mmc_softc *sc) break; DELAY(1000); } +#ifdef MMCCAM + cmd = &sc->ccb->mmcio.cmd; +#else cmd = sc->aw_req->cmd; +#endif if (timeout == 0) { cmd->error = MMC_ERR_FAILED; aw_mmc_req_done(sc); @@ -618,15 +908,30 @@ aw_mmc_req_ok(struct aw_mmc_softc *sc) aw_mmc_req_done(sc); } + +static inline void +set_mmc_error(struct aw_mmc_softc *sc, int error_code) +{ +#ifdef MMCCAM + sc->ccb->mmcio.cmd.error = error_code; +#else + sc->aw_req->cmd->error = error_code; +#endif +} + static void aw_mmc_timeout(void *arg) { struct aw_mmc_softc *sc; sc = (struct aw_mmc_softc *)arg; +#ifdef MMCCAM + if (sc->ccb != NULL) { +#else if (sc->aw_req != NULL) { +#endif device_printf(sc->aw_dev, "controller timeout\n"); - sc->aw_req->cmd->error = MMC_ERR_TIMEOUT; + set_mmc_error(sc, MMC_ERR_TIMEOUT); aw_mmc_req_done(sc); } else device_printf(sc->aw_dev, @@ -634,6 +939,28 @@ aw_mmc_timeout(void *arg) } static void +aw_mmc_print_error(uint32_t err) +{ + if(err & AW_MMC_INT_RESP_ERR) + printf("AW_MMC_INT_RESP_ERR "); + if (err & AW_MMC_INT_RESP_CRC_ERR) + printf("AW_MMC_INT_RESP_CRC_ERR "); + if (err & AW_MMC_INT_DATA_CRC_ERR) + printf("AW_MMC_INT_DATA_CRC_ERR "); + if (err & AW_MMC_INT_RESP_TIMEOUT) + printf("AW_MMC_INT_RESP_TIMEOUT "); + if (err & AW_MMC_INT_FIFO_RUN_ERR) + printf("AW_MMC_INT_FIFO_RUN_ERR "); + if (err & AW_MMC_INT_CMD_BUSY) + printf("AW_MMC_INT_CMD_BUSY "); + if (err & AW_MMC_INT_DATA_START_ERR) + printf("AW_MMC_INT_DATA_START_ERR "); + if (err & AW_MMC_INT_DATA_END_BIT_ERR) + printf("AW_MMC_INT_DATA_END_BIT_ERR"); + printf("\n"); +} + +static void aw_mmc_intr(void *arg) { bus_dmasync_op_t sync_op; @@ -654,31 +981,41 @@ aw_mmc_intr(void *arg) device_printf(sc->aw_dev, "idst: %#x, imask: %#x, rint: %#x\n", idst, imask, rint); #endif +#ifdef MMCCAM + if (sc->ccb == NULL) { +#else if (sc->aw_req == NULL) { +#endif device_printf(sc->aw_dev, "Spurious interrupt - no active request, rint: 0x%08X\n", rint); + aw_mmc_print_error(rint); goto end; } if (rint & AW_MMC_INT_ERR_BIT) { if (bootverbose) device_printf(sc->aw_dev, "error rint: 0x%08X\n", rint); + aw_mmc_print_error(rint); if (rint & AW_MMC_INT_RESP_TIMEOUT) - sc->aw_req->cmd->error = MMC_ERR_TIMEOUT; + set_mmc_error(sc, MMC_ERR_TIMEOUT); else - sc->aw_req->cmd->error = MMC_ERR_FAILED; + set_mmc_error(sc, MMC_ERR_FAILED); aw_mmc_req_done(sc); goto end; } if (idst & AW_MMC_IDST_ERROR) { device_printf(sc->aw_dev, "error idst: 0x%08x\n", idst); - sc->aw_req->cmd->error = MMC_ERR_FAILED; + set_mmc_error(sc, MMC_ERR_FAILED); aw_mmc_req_done(sc); goto end; } sc->aw_intr |= rint; +#ifdef MMCCAM + data = sc->ccb->mmcio.cmd.data; +#else data = sc->aw_req->cmd->data; +#endif if (data != NULL && (idst & AW_MMC_IDST_COMPLETE) != 0) { if (data->flags & MMC_DATA_WRITE) sync_op = BUS_DMASYNC_POSTWRITE; @@ -712,13 +1049,29 @@ aw_mmc_request(device_t bus, device_t child, struct mm sc = device_get_softc(bus); AW_MMC_LOCK(sc); +#ifdef MMCCAM + KASSERT(req == NULL, ("req should be NULL in MMCCAM case!")); + /* + * For MMCCAM, sc->ccb has been NULL-checked and populated + * by aw_mmc_cam_request() already. + */ + cmd = &sc->ccb->mmcio.cmd; +#else if (sc->aw_req) { AW_MMC_UNLOCK(sc); return (EBUSY); } - sc->aw_req = req; cmd = req->cmd; + +#ifdef DEBUG + if (bootverbose) + device_printf(sc->aw_dev, "CMD%u arg %#x flags %#x dlen %u dflags %#x\n", + cmd->opcode, cmd->arg, cmd->flags, + cmd->data != NULL ? (unsigned int)cmd->data->len : 0, + cmd->data != NULL ? cmd->data->flags: 0); +#endif +#endif cmdreg = AW_MMC_CMDR_LOAD; imask = AW_MMC_INT_ERR_BIT; sc->aw_intr_wait = 0; @@ -1163,4 +1516,6 @@ static driver_t aw_mmc_driver = { DRIVER_MODULE(aw_mmc, simplebus, aw_mmc_driver, aw_mmc_devclass, NULL, NULL); +#ifndef MMCCAM MMC_DECLARE_BRIDGE(aw_mmc); +#endif Modified: head/sys/arm/allwinner/files.allwinner ============================================================================== --- head/sys/arm/allwinner/files.allwinner Thu Jun 21 11:43:54 2018 (r335475) +++ head/sys/arm/allwinner/files.allwinner Thu Jun 21 11:49:21 2018 (r335476) @@ -10,7 +10,7 @@ arm/allwinner/a10_sramc.c standard arm/allwinner/aw_gpio.c optional gpio arm/allwinner/aw_if_dwc.c optional dwc arm/allwinner/aw_machdep.c standard -arm/allwinner/aw_mmc.c optional mmc +arm/allwinner/aw_mmc.c optional mmc | mmccam arm/allwinner/aw_mp.c optional smp arm/allwinner/aw_nmi.c optional intrng arm/allwinner/aw_rsb.c optional rsb | p2wi Modified: head/sys/conf/files.arm64 ============================================================================== --- head/sys/conf/files.arm64 Thu Jun 21 11:43:54 2018 (r335475) +++ head/sys/conf/files.arm64 Thu Jun 21 11:49:21 2018 (r335476) @@ -27,7 +27,7 @@ cloudabi64_vdso_blob.o optional compat_cloudabi64 \ # Allwinner common files arm/allwinner/a10_ehci.c optional ehci aw_ehci fdt arm/allwinner/aw_gpio.c optional gpio aw_gpio fdt -arm/allwinner/aw_mmc.c optional mmc aw_mmc fdt +arm/allwinner/aw_mmc.c optional mmc aw_mmc fdt | mmccam aw_mmc fdt arm/allwinner/aw_nmi.c optional aw_nmi fdt \ compile-with "${NORMAL_C} -I$S/gnu/dts/include" arm/allwinner/aw_rsb.c optional aw_rsb fdt