Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jun 2018 11:49:21 +0000 (UTC)
From:      Ilya Bakulin <kibab@FreeBSD.org>
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
Message-ID:  <201806211149.w5LBnLl9061185@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <dev/extres/hwreset/hwreset.h>
 #include <dev/extres/regulator/regulator.h>
 
+#include "opt_mmccam.h"
+
+#ifdef MMCCAM
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806211149.w5LBnLl9061185>