From owner-svn-soc-all@FreeBSD.ORG Fri Jun 12 09:51:34 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 32F299C6 for ; Fri, 12 Jun 2015 09:51:34 +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 14DBB1AC5 for ; Fri, 12 Jun 2015 09:51:34 +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 t5C9pXEa073983 for ; Fri, 12 Jun 2015 09:51:33 GMT (envelope-from pratiksinghal@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.9/8.14.9/Submit) id t5C9pXVW073493 for svn-soc-all@FreeBSD.org; Fri, 12 Jun 2015 09:51:33 GMT (envelope-from pratiksinghal@FreeBSD.org) Date: Fri, 12 Jun 2015 09:51:33 GMT Message-Id: <201506120951.t5C9pXVW073493@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: r286989 - 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: Fri, 12 Jun 2015 09:51:34 -0000 Author: pratiksinghal Date: Fri Jun 12 09:51:32 2015 New Revision: 286989 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=286989 Log: Cleaned up interrupt handling code. 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 Fri Jun 12 09:24:03 2015 (r286988) +++ soc2015/pratiksinghal/cubie-head/sys/arm/allwinner/a10_mmc.c Fri Jun 12 09:51:32 2015 (r286989) @@ -58,6 +58,7 @@ #define A10_MMC_RESSZ 2 #define A10_MMC_NDESC 16 #define A10_MMC_DMA_FTRGLEVEL_A20 0x20070008 +#define A10_MMC_DMA_FTRGLEVEL_A10 0x00070208 struct a10_mmc_softc { bus_space_handle_t a10_bsh; @@ -87,7 +88,8 @@ bus_dmamap_t a10_dma_map ; bus_dma_tag_t a10_dma_tag ; int a10_dma_ndesc; - void* a10_dma_desc ; + 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 */ }; @@ -119,6 +121,12 @@ bus_space_read_4((_sc)->a10_bst, (_sc)->a10_bsh, _reg) #define A10_MMC_WRITE_4(_sc, _reg, _value) \ bus_space_write_4((_sc)->a10_bst, (_sc)->a10_bsh, _reg, _value) +#define A10_MMC_READ_2(_sc, _reg) \ + bus_space_read_2((_sc)->a10_bst, (_sc)->a10_bsh, _reg) +#define A10_MMC_WRITE_2(_sc, _reg, _value) \ + bus_space_write_2((_sc)->a10_bst, (_sc)->a10_bsh, _reg, _value) + + static int a10_mmc_probe(device_t dev) @@ -143,6 +151,7 @@ sc = device_get_softc(dev); sc->a10_use_dma = 1 ; + sc->a10_dma_ops = 2 ; sc->a10_dev = dev; sc->a10_req = NULL; sc->a10_id = device_get_unit(dev); @@ -244,7 +253,7 @@ /* Allocate the memory and map at kva sc->a10_dma_desc*/ - error = bus_dmamem_alloc(sc->a10_dma_tag,&sc->a10_dma_desc,BUS_DMA_WAITOK,&sc->a10_dma_map) ; + error = bus_dmamem_alloc(sc->a10_dma_tag,&sc->a10_dma_desc,BUS_DMA_WAITOK|BUS_DMA_ZERO,&sc->a10_dma_map) ; if(error) return (error) ; @@ -261,49 +270,47 @@ static int a10_mmc_prepare_dma(struct a10_mmc_softc* sc) { + device_printf(sc->a10_dev, "Call to prepare dma\n") ; struct a10_mmc_dma_desc* dma = sc->a10_dma_desc ; struct mmc_command* cmd = sc->a10_req->cmd ; int read = (sc->a10_req->cmd->data->flags & MMC_DATA_WRITE) ? 0 : 1 ; bus_addr_t desc_paddr = (sc->a10_dma_cb_arg).addr ; bus_size_t off = 0 ; - int desc, rem,seg ; + int desc, rem ; uint32_t val; desc = 0 ; /* Pick a segment and program all the descriptors in the segment. */ - for(seg = 0; seg < sc->a10_dma_cb_arg.nsegs ; seg++) + 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 ; + rem = min(len,cmd->data->len) ; + while(rem > 0) { - bus_addr_t paddr = (sc->a10_dma_cb_arg).segs[seg].ds_addr; - bus_size_t len = (sc->a10_dma_cb_arg).segs[seg].ds_len ; - rem = min(len,cmd->data->len) ; - while(rem > 0) - { - if(desc == sc->a10_dma_ndesc) - break ; - len = min(sc->a10_dma_xfer_len, rem) ; - dma[desc].buff_size = htole32(len) ; - dma[desc].buff_addr = htole32(paddr + off) ; - dma[desc].config = htole32(A10_MMC_DMA_CONFIG_CH|A10_MMC_DMA_CONFIG_OWN) ; - - cmd->data->len -= len ; - rem -= len ; - off += len ; - if(desc == 0) { - dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_FD) ; - } - - if(cmd->data->len == 0) { - dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_LD) ; - dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_ER) ; - dma[desc].next = 0 ; - } - else { - dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_DIC) ; - dma[desc].next = htole32(desc_paddr + ((desc+1)*sizeof(struct a10_mmc_dma_desc))) ; - } - desc++ ; + if(desc == sc->a10_dma_ndesc) + break ; + len = min(sc->a10_dma_xfer_len, rem) ; + dma[desc].buff_size = htole32(len) ; + dma[desc].buff_addr = htole32(paddr + off) ; + dma[desc].config = htole32(A10_MMC_DMA_CONFIG_CH|A10_MMC_DMA_CONFIG_OWN) ; + + cmd->data->len -= len ; + rem -= len ; + off += len ; + if(desc == 0) { + dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_FD) ; + } + + if(cmd->data->len == 0) { + dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_LD) ; + dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_ER) ; + dma[desc].next = 0 ; + } + else { + dma[desc].config |= htole32(A10_MMC_DMA_CONFIG_DIC) ; + dma[desc].next = htole32(desc_paddr + ((desc+1)*sizeof(struct a10_mmc_dma_desc))) ; } + desc++ ; } if(desc == sc->a10_dma_ndesc) { @@ -313,27 +320,42 @@ bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_PREWRITE) ; + /* Enable DMA and interrupts*/ val = A10_MMC_READ_4(sc, A10_MMC_GCTRL) ; 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) ; + + /* IDMA Soft reset */ A10_MMC_WRITE_4(sc, A10_MMC_DMAC,A10_MMC_IDMAC_SOFT_RST) ; + + /* Enable IDMA with Fix burst */ A10_MMC_WRITE_4(sc, A10_MMC_DMAC,A10_MMC_IDMAC_IDMA_ON | A10_MMC_IDMAC_FIX_BURST) ; + + /* Disable interrupts */ val = A10_MMC_READ_4(sc,A10_MMC_IDIE) ; val &= ~(A10_MMC_IDMAC_RECEIVE_INT | A10_MMC_IDMAC_TRANSMIT_INT) ; + A10_MMC_WRITE_4(sc,A10_MMC_IDIE, val) ; - if(read == 1) { + /* Enable required interrupts */ + if(read == 1) val |= A10_MMC_IDMAC_RECEIVE_INT ; - } - else { + else val |= A10_MMC_IDMAC_TRANSMIT_INT ; - } - A10_MMC_WRITE_4(sc, A10_MMC_IDIE,val) ; + + /* Give the starting segment physical address */ A10_MMC_WRITE_4(sc, A10_MMC_DLBA,desc_paddr) ; - A10_MMC_WRITE_4(sc, A10_MMC_FTRGL,A10_MMC_DMA_FTRGLEVEL_A20) ; + + /* Configure the watermark level. */ + A10_MMC_WRITE_4(sc, A10_MMC_FTRGL,A10_MMC_DMA_FTRGLEVEL_A10) ; + + /* Disable debounce*/ + A10_MMC_WRITE_4(sc, A10_MMC_READ_4(sc, A10_MMC_GCTRL) & (~A10_MMC_DEBOUNCE_ENABLE), A10_MMC_GCTRL); return (0) ; } @@ -503,7 +525,8 @@ rint = A10_MMC_READ_4(sc, A10_MMC_RINTR); imask = A10_MMC_READ_4(sc, A10_MMC_IMASK); idst = A10_MMC_READ_4(sc, A10_MMC_IDST) ; - if (imask == 0 && rint == 0 ) { + + if (imask == 0 && rint == 0 && idst == 0 ) { A10_MMC_UNLOCK(sc); return; } @@ -521,8 +544,10 @@ if (rint & A10_MMC_INT_ERR_BIT) { device_printf(sc->a10_dev, "error rint: 0x%08X\n", rint); - if (rint & A10_MMC_RESP_TIMEOUT) + if (rint & A10_MMC_RESP_TIMEOUT) { + device_printf(sc->a10_dev,"Setting timeout in intr\n") ; sc->a10_req->cmd->error = MMC_ERR_TIMEOUT; + } else sc->a10_req->cmd->error = MMC_ERR_FAILED; A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint); @@ -531,52 +556,48 @@ return; } - /* Do we have to return from here or continue afterwards ? */ - /* What is the DMA only, what is PIO only and what is common part ? */ - if(sc->a10_use_dma == 1) { - uint32_t comp = 0 ; - device_printf(sc->a10_dev, "IDST = %d\n", idst) ; - sc->a10_idst = idst ; - if(idst & A10_MMC_IDMAC_ERROR) { - device_printf(sc->a10_dev, "I/O error with DMA\n") ; - sc->a10_req->cmd->error = EIO ; - } - if(!(idst & A10_MMC_IDMAC_COMPLETE)) { - device_printf(sc->a10_dev, "Timeout error with DMA\n") ; - sc->a10_req->cmd->error = ETIMEDOUT ; - } - else - comp = 1 ; - - if(sc->a10_req->cmd->data != NULL) { - data = sc->a10_req->cmd->data ; - if(data->flags&MMC_DATA_WRITE) - bus_dmamap_sync(sc->a10_dma_tag,sc->a10_dma_map,BUS_DMASYNC_POSTWRITE) ; - else - bus_dmamap_sync(sc->a10_dma_tag,sc->a10_dma_map, BUS_DMASYNC_POSTREAD) ; - } + 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_req_done(sc) ; + A10_MMC_UNLOCK(sc) ; + return ; + } - if(comp == 0) - a10_mmc_req_done(sc) ; - else { - device_printf(sc->a10_dev, "DMA transfer working!\n") ; - a10_mmc_req_ok(sc) ; - } + if(idst & A10_MMC_IDMAC_COMPLETE) { + device_printf(sc->a10_dev, "DMA transfer complete!\n", idst) ; + if(sc->a10_dma_ops == 0) + bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_POSTREAD) ; + else if(sc->a10_dma_ops == 1) + 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_req_ok(sc) ; + A10_MMC_UNLOCK(sc) ; + return ; + } + if((idst)&&(!(idst & A10_MMC_IDMAC_COMPLETE))) { + device_printf(sc->a10_dev, "DMA timeout error!\n", idst) ; + sc->a10_req_cmd->error = MMC_ERR_TIMEOUT ; + a10_mmc_req_done(sc) ; + A10_MMC_UNLOCK(sc) ; } - A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst) ; sc->a10_intr |= rint; - if(sc->a10_use_dma == 0) { - data = sc->a10_req->cmd->data; - if (data != NULL && (rint & (A10_MMC_DATA_OVER | - A10_MMC_RX_DATA_REQ | A10_MMC_TX_DATA_REQ)) != 0) - a10_mmc_pio_transfer(sc, data); - if ((sc->a10_intr & sc->a10_intr_wait) == sc->a10_intr_wait) - a10_mmc_req_ok(sc); + data = sc->a10_req->cmd->data; + + if (data != NULL && (rint & (A10_MMC_DATA_OVER | + A10_MMC_RX_DATA_REQ | A10_MMC_TX_DATA_REQ)) != 0) + a10_mmc_pio_transfer(sc, data); } + 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); } @@ -586,7 +607,9 @@ int blksz; struct a10_mmc_softc *sc; struct mmc_command *cmd; - uint32_t cmdreg; + uint32_t cmdreg,imask; + + imask = A10_MMC_CMD_DONE | A10_MMC_INT_ERR_BIT | A10_MMC_WAIT_PREOVER | A10_MMC_DATA_OVER ; sc = device_get_softc(bus); A10_MMC_LOCK(sc); @@ -612,6 +635,7 @@ sc->a10_idst = 0 ; sc->a10_intr_wait = A10_MMC_CMD_DONE; cmd->error = MMC_ERR_NONE; + /* Will data be NULL when reading data ? */ if (cmd->data != NULL) { sc->a10_intr_wait |= A10_MMC_DATA_OVER; cmdreg |= A10_MMC_DATA_EXP | A10_MMC_WAIT_PREOVER; @@ -619,21 +643,29 @@ 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; + if(sc->a10_use_dma == 1) + imask |= A10_MMC_TX_DATA_REQ ; + } + else { + if(sc->a10_use_dma == 1) + imask |= A10_MMC_RX_DATA_REQ ; + } blksz = min(cmd->data->len, MMC_SECTOR_SIZE); A10_MMC_WRITE_4(sc, A10_MMC_BLKSZ, blksz); A10_MMC_WRITE_4(sc, A10_MMC_BCNTR, cmd->data->len); - } - - A10_MMC_WRITE_4(sc, A10_MMC_CARG, cmd->arg); - - if(cmd->data != NULL ) { - if(sc->a10_use_dma == 1) { + if(sc->a10_use_dma == 1) a10_mmc_prepare_dma(sc) ; - } } + 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, a10_mmc_timeout, sc);