From owner-svn-soc-all@FreeBSD.ORG Sun Jun 14 09:57:48 2015 Return-Path: Delivered-To: svn-soc-all@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B6301345 for ; Sun, 14 Jun 2015 09:57:48 +0000 (UTC) (envelope-from pratiksinghal@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A3662E09 for ; Sun, 14 Jun 2015 09:57:48 +0000 (UTC) (envelope-from pratiksinghal@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.9/8.14.9) with ESMTP id t5E9vmKF094212 for ; Sun, 14 Jun 2015 09:57:48 GMT (envelope-from pratiksinghal@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.9/8.14.9/Submit) id t5E9vmuN094181 for svn-soc-all@FreeBSD.org; Sun, 14 Jun 2015 09:57:48 GMT (envelope-from pratiksinghal@FreeBSD.org) Date: Sun, 14 Jun 2015 09:57:48 GMT Message-Id: <201506140957.t5E9vmuN094181@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to pratiksinghal@FreeBSD.org using -f From: pratiksinghal@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r287080 - soc2015/pratiksinghal/cubie-head/sys/arm/allwinner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 14 Jun 2015 09:57:48 -0000 Author: pratiksinghal Date: Sun Jun 14 09:57:47 2015 New Revision: 287080 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=287080 Log: DMA transfer interrupt coming but 2 problems still remain :- 1) Interrupt storm 2) Timeout in raw interrupt register Modified: soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Modified: soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c ============================================================================== --- soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Sun Jun 14 09:54:48 2015 (r287079) +++ soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Sun Jun 14 09:57:47 2015 (r287080) @@ -57,10 +57,11 @@ #define A10_MMC_IRQRES 1 #define A10_MMC_RESSZ 2 #define A10_MMC_NDESC 16 -#define A10_DMA_NSEGS 16 +#define A10_DMA_NSEGS 16 #define A10_DMA_BUFF_SIZE 512 #define A10_MMC_DMA_FTRGLEVEL_A20 0x20070008 #define A10_MMC_DMA_FTRGLEVEL_A10 0x00070208 +#define A10_MMC_DMA_MAXLEN 0x1000 struct a10_mmc_softc { bus_space_handle_t a10_bsh; @@ -92,8 +93,9 @@ int a10_dma_ndesc; void* a10_dma_desc ; /* Contains the kva of the descriptor which we will pass to DLBA */ int a10_dma_ops ; /* Which type of operation DMA is performing ? 0:read, 1:write, 2:other */ - bus_dma_tag_t a10_dma_buff_tag ; - bus_dmamap_t a10_dma_buff_map ; + bus_dma_tag_t a10_dma_buff_tag ; + bus_dmamap_t a10_dma_buff_map ; + bus_addr_t a10_dma_buff_addr ; }; @@ -107,7 +109,8 @@ static int a10_mmc_attach(device_t); static int a10_mmc_setup_dma(struct a10_mmc_softc*, device_t) ; static int a10_mmc_prepare_dma(struct a10_mmc_softc*) ; -static int a10_mmc_can_do_dma(struct mmc_request*) ; +static int a10_mmc_can_do_dma(struct mmc_request*) ; +static void a10_dma_buff_cb(void*, bus_dma_segment_t*, int, int) ; static int a10_mmc_detach(device_t); static int a10_mmc_reset(struct a10_mmc_softc *); static void a10_mmc_intr(void *); @@ -225,9 +228,9 @@ sc->a10_use_dma = 0 ; } } -#ifdef DEBUG - device_printf(sc->a10_dev, "DMA status %d\n", sc->a10_use_dma) ; -#endif +#ifdef DEBUG + device_printf(sc->a10_dev, "DMA status %d\n", sc->a10_use_dma) ; +#endif return (0); fail: @@ -268,24 +271,25 @@ if((error != 0)&&(error != EINPROGRESS)) return (error) ; - - /* Now allocate tag and map for the buffer to be used with transfer. */ + + /* Now allocate tag and map for the buffer to be used with transfer. */ error = bus_dma_tag_create(bus_get_dma_tag(dev),1, 0,BUS_SPACE_MAXADDR_32BIT,BUS_SPACE_MAXADDR, NULL,NULL,A10_DMA_BUFF_SIZE, A10_DMA_NSEGS,A10_DMA_BUFF_SIZE,0, - NULL,NULL,&sc->a10_dma_buff_tag) ; + NULL,NULL,&sc->a10_dma_buff_tag) ; if(error) - return (error) ; - - error = bus_dmamap_create(sc->a10_dma_buff_tag,0,&sc->a10_dma_buff_map) ; + return (error) ; + + error = bus_dmamap_create(sc->a10_dma_buff_tag,0,&sc->a10_dma_buff_map) ; if(error) - return (error) ; + return (error) ; return(0) ; } +/* Transfer at most 0x1000 (4K) of data (Experimental) */ static int a10_mmc_prepare_dma(struct a10_mmc_softc* sc) { @@ -299,14 +303,21 @@ bus_size_t off = 0 ; int desc, rem ; uint32_t val; - desc = 0 ; - - /* Pick a segment and program all the descriptors in the segment. */ - bus_addr_t paddr = (sc->a10_dma_cb_arg).segs[0].ds_addr; - bus_size_t len = (sc->a10_dma_cb_arg).segs[0].ds_len ; + bus_addr_t paddr = sc->a10_dma_buff_addr ; + //bus_size_t len = (sc->a10_dma_cb_arg).segs[0].ds_len ; + bus_size_t len = A10_MMC_DMA_MAXLEN ; rem = min(len,cmd->data->len) ; + uint32_t error = bus_dmamap_load(sc->a10_dma_buff_tag, sc->a10_dma_buff_map, + cmd->data->data,rem,a10_dma_buff_cb, + &sc->a10_dma_buff_addr,BUS_DMA_NOWAIT) ; + if(error != 0) { + device_printf(sc->a10_dev, "DMA transaction failed due to insufficient resources\n") ; + return EIO ; + } + + /* Program all the descriptors in this segment. */ while(rem > 0) { if(desc == sc->a10_dma_ndesc) @@ -347,7 +358,7 @@ val |= A10_MMC_DMA_ENABLE ; val |= A10_MMC_INT_ENABLE ; A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,val) ; - + /* Reset DMA */ val |= A10_MMC_DMA_RESET ; A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,val) ; @@ -383,11 +394,14 @@ } -/* Not implemented yet. */ -static int +/* Not implemented yet. */ +static int a10_mmc_can_do_dma(struct mmc_request* req) { - return (1) ; + if(req->cmd->data->len > A10_MMC_DMA_MAXLEN) + return (0) ; + else + return (1) ; } static void a10_dma_cb(void* arg, bus_dma_segment_t* segs, int nsegs, int error) @@ -401,6 +415,16 @@ (*(struct a10_mmc_cb*)arg).segs = segs; } +static void +a10_dma_buff_cb(void* arg, bus_dma_segment_t* segs, int nsegs, int error) +{ + if(error) { + printf("a10_mmc: Error in a10_dma_buff_callback function, code = %d\n", error) ; + return ; + } + *(bus_addr_t*)arg = segs[0].ds_addr ; +} + static int a10_mmc_detach(device_t dev) { @@ -421,8 +445,10 @@ break; DELAY(100); } - if (timeout == 0) + if (timeout == 0) { + device_printf(sc->a10_dev, "Getting timedout in reset\n") ; return (ETIMEDOUT); + } /* Set the timeout. */ A10_MMC_WRITE_4(sc, A10_MMC_TIMEOUT, 0xffffffff); @@ -438,7 +464,7 @@ A10_MMC_WRITE_4(sc, A10_MMC_GCTRL, A10_MMC_READ_4(sc, A10_MMC_GCTRL) | A10_MMC_INT_ENABLE | A10_MMC_ACCESS_BY_AHB); - + device_printf(sc->a10_dev,"Reset succesfully in reset function\n") ; return (0); } @@ -557,15 +583,15 @@ A10_MMC_UNLOCK(sc); return; } -#ifdef DEBUG - device_printf(sc->a10_dev, "imask: %#x, rint: %#x\n", imask, rint); -#endif + + A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint) ; + A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; + A10_MMC_WRITE_4(sc, A10_MMC_IMASK, imask) ; + device_printf(sc->a10_dev, "imask: %#x, rint: %#x, idst: %#x\n", imask, rint,idst); if (sc->a10_req == NULL) { device_printf(sc->a10_dev, "Spurious interrupt - no active request, rint: 0x%08X\n", rint); - A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint); - A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; A10_MMC_UNLOCK(sc); return; } @@ -578,8 +604,6 @@ } else sc->a10_req->cmd->error = MMC_ERR_FAILED; - A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint); - A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; a10_mmc_req_done(sc); A10_MMC_UNLOCK(sc); return; @@ -588,8 +612,6 @@ if(idst & A10_MMC_IDMAC_ERROR) { device_printf(sc->a10_dev, "error rint: 0x%08x\n", idst) ; sc->a10_req->cmd->error = MMC_ERR_FAILED ; - A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; - A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint) ; a10_mmc_req_done(sc) ; A10_MMC_UNLOCK(sc) ; return ; @@ -603,8 +625,7 @@ bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_POSTWRITE) ; else device_printf(sc->a10_dev, "Invalid operations request!\n") ; - A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; - A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint) ; + bus_dmamap_unload(sc->a10_dma_buff_tag, sc->a10_dma_buff_map) ; a10_mmc_req_ok(sc) ; A10_MMC_UNLOCK(sc) ; return ; @@ -626,8 +647,6 @@ if ((sc->a10_intr & sc->a10_intr_wait) == sc->a10_intr_wait) a10_mmc_req_ok(sc); - A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint); - A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; A10_MMC_UNLOCK(sc); } @@ -638,7 +657,7 @@ int blksz; struct a10_mmc_softc *sc; struct mmc_command *cmd; - uint32_t cmdreg,imask; + uint32_t cmdreg ; sc = device_get_softc(bus); A10_MMC_LOCK(sc); @@ -648,7 +667,6 @@ } sc->a10_req = req; - imask = 0 ; cmd = req->cmd; cmdreg = A10_MMC_START; if (cmd->opcode == MMC_GO_IDLE_STATE) @@ -668,15 +686,15 @@ if (cmd->data != NULL) { sc->a10_intr_wait |= A10_MMC_DATA_OVER; - sc->a10_dma_ops = 0 ; + sc->a10_dma_ops = 0 ; cmdreg |= A10_MMC_DATA_EXP | A10_MMC_WAIT_PREOVER; if (cmd->data->flags & MMC_DATA_MULTI) { cmdreg |= A10_MMC_SEND_AUTOSTOP; sc->a10_intr_wait |= A10_MMC_AUTOCMD_DONE; } - if (cmd->data->flags & MMC_DATA_WRITE) { + if (cmd->data->flags & MMC_DATA_WRITE) { cmdreg |= A10_MMC_WRITE; - sc->a10_dma_ops = 1 ; + sc->a10_dma_ops = 1 ; } blksz = min(cmd->data->len, MMC_SECTOR_SIZE); @@ -684,20 +702,15 @@ A10_MMC_WRITE_4(sc, A10_MMC_BCNTR, cmd->data->len); if((sc->a10_use_dma == 1)&&(a10_mmc_can_do_dma(req))) { - uint32_t error = a10_mmc_prepare_dma(sc) ; - if(error == 0) - imask |= (A10_MMC_TX_DATA_REQ|A10_MMC_RX_DATA_REQ) ; + uint32_t error = a10_mmc_prepare_dma(sc) ; + if(error == 0) { + A10_MMC_WRITE_4(sc, A10_MMC_IMASK, A10_MMC_READ_4(sc, A10_MMC_IMASK) | (A10_MMC_TX_DATA_REQ | A10_MMC_RX_DATA_REQ)) ; + } else - device_printf(sc->a10_dev, "Couldn't prepare DMA, using pio instead\n") ; + device_printf(sc->a10_dev, "Couldn't prepare DMA, using pio instead\n") ; } } - uint32_t newmask = A10_MMC_READ_4(sc, A10_MMC_IMASK) ; - if(!(imask & A10_MMC_SDIO_INT)) - A10_MMC_WRITE_2(sc, A10_MMC_IMASK, newmask) ; - else - A10_MMC_WRITE_4(sc, A10_MMC_IMASK, newmask) ; - A10_MMC_WRITE_4(sc, A10_MMC_CARG, cmd->arg); A10_MMC_WRITE_4(sc, A10_MMC_CMDR, cmdreg | cmd->opcode); callout_reset(&sc->a10_timeoutc, sc->a10_timeout * hz,