From owner-svn-src-head@freebsd.org Tue Feb 16 12:19:08 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 68CF9AAA930; Tue, 16 Feb 2016 12:19:08 +0000 (UTC) (envelope-from skra@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 mx1.freebsd.org (Postfix) with ESMTPS id 42B8210C6; Tue, 16 Feb 2016 12:19:08 +0000 (UTC) (envelope-from skra@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u1GCJ7pg087351; Tue, 16 Feb 2016 12:19:07 GMT (envelope-from skra@FreeBSD.org) Received: (from skra@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u1GCJ706087348; Tue, 16 Feb 2016 12:19:07 GMT (envelope-from skra@FreeBSD.org) Message-Id: <201602161219.u1GCJ706087348@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: skra set sender to skra@FreeBSD.org using -f From: Svatopluk Kraus Date: Tue, 16 Feb 2016 12:19:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r295659 - head/sys/arm/broadcom/bcm2835 X-SVN-Group: head 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.20 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: Tue, 16 Feb 2016 12:19:08 -0000 Author: skra Date: Tue Feb 16 12:19:06 2016 New Revision: 295659 URL: https://svnweb.freebsd.org/changeset/base/295659 Log: Do not use DMA channels used by GPU. (1) The channel mask is get from "brcm,dma-channel-mask" property of dma node, and if not provided, from "broadcom,channels" property. (2) Consequently, sdhci driver does not allocate any specific channel. (3) Use CS_RESET bit for initial channel reset. Differential Revision: https://reviews.freebsd.org/D4303 Modified: head/sys/arm/broadcom/bcm2835/bcm2835_dma.c head/sys/arm/broadcom/bcm2835/bcm2835_dma.h head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Modified: head/sys/arm/broadcom/bcm2835/bcm2835_dma.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_dma.c Tue Feb 16 11:51:54 2016 (r295658) +++ head/sys/arm/broadcom/bcm2835/bcm2835_dma.c Tue Feb 16 12:19:06 2016 (r295659) @@ -104,6 +104,15 @@ __FBSDID("$FreeBSD$"); /* relative offset from BCM_VC_DMA0_BASE (p.39) */ #define BCM_DMA_CH(n) (0x100*(n)) +/* channels used by GPU */ +#define BCM_DMA_CH_BULK 0 +#define BCM_DMA_CH_FAST1 2 +#define BCM_DMA_CH_FAST2 3 + +#define BCM_DMA_CH_GPU_MASK ((1 << BCM_DMA_CH_BULK) | \ + (1 << BCM_DMA_CH_FAST1) | \ + (1 << BCM_DMA_CH_FAST2)) + /* DMA Control Block - 256bit aligned (p.40) */ struct bcm_dma_cb { uint32_t info; /* Transfer Information */ @@ -143,6 +152,7 @@ struct bcm_dma_softc { }; static struct bcm_dma_softc *bcm_dma_sc = NULL; +static uint32_t bcm_dma_channel_mask; static void bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs, @@ -205,16 +215,32 @@ static int bcm_dma_init(device_t dev) { struct bcm_dma_softc *sc = device_get_softc(dev); - uint32_t mask; + uint32_t reg; struct bcm_dma_ch *ch; void *cb_virt; vm_paddr_t cb_phys; int err; int i; - /* disable and clear interrupt status */ - bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, 0); - bus_write_4(sc->sc_mem, BCM_DMA_INT_STATUS, 0); + /* + * Only channels set in bcm_dma_channel_mask can be controlled by us. + * The others are out of our control as well as the corresponding bits + * in both BCM_DMA_ENABLE and BCM_DMA_INT_STATUS global registers. As + * these registers are RW ones, there is no safe way how to write only + * the bits which can be controlled by us. + * + * Fortunately, after reset, all channels are enabled in BCM_DMA_ENABLE + * register and all statuses are cleared in BCM_DMA_INT_STATUS one. + * Not touching these registers is a trade off between correct + * initialization which does not count on anything and not messing up + * something we have no control over. + */ + reg = bus_read_4(sc->sc_mem, BCM_DMA_ENABLE); + if ((reg & bcm_dma_channel_mask) != bcm_dma_channel_mask) + device_printf(dev, "channels are not enabled\n"); + reg = bus_read_4(sc->sc_mem, BCM_DMA_INT_STATUS); + if ((reg & bcm_dma_channel_mask) != 0) + device_printf(dev, "statuses are not cleared\n"); /* Allocate DMA chunks control blocks */ /* p.40 of spec - control block should be 32-bit aligned */ @@ -227,7 +253,7 @@ bcm_dma_init(device_t dev) &sc->sc_dma_tag); if (err) { - device_printf(dev, "failed allocate DMA tag"); + device_printf(dev, "failed allocate DMA tag\n"); return (err); } @@ -235,6 +261,13 @@ bcm_dma_init(device_t dev) for (i = 0; i < BCM_DMA_CH_MAX; i++) { ch = &sc->sc_dma_ch[i]; + bzero(ch, sizeof(struct bcm_dma_ch)); + ch->ch = i; + ch->flags = BCM_DMA_CH_UNMAP; + + if ((bcm_dma_channel_mask & (1 << i)) == 0) + continue; + err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &ch->dma_map); @@ -263,33 +296,15 @@ bcm_dma_init(device_t dev) break; } - bzero(ch, sizeof(struct bcm_dma_ch)); - ch->ch = i; ch->cb = cb_virt; ch->vc_cb = cb_phys; - ch->intr_func = NULL; - ch->intr_arg = NULL; - ch->flags = BCM_DMA_CH_UNMAP; - + ch->flags = BCM_DMA_CH_FREE; ch->cb->info = INFO_WAIT_RESP; /* reset DMA engine */ - bcm_dma_reset(dev, i); + bus_write_4(sc->sc_mem, BCM_DMA_CS(i), CS_RESET); } - /* now use DMA2/DMA3 only */ - sc->sc_dma_ch[2].flags = BCM_DMA_CH_FREE; - sc->sc_dma_ch[3].flags = BCM_DMA_CH_FREE; - - /* enable DMAs */ - mask = 0; - - for (i = 0; i < BCM_DMA_CH_MAX; i++) - if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE) - mask |= (1 << i); - - bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, mask); - return (0); } @@ -599,8 +614,11 @@ bcm_dma_intr(void *arg) /* my interrupt? */ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch)); - if (!(cs & (CS_INT | CS_ERR))) + if (!(cs & (CS_INT | CS_ERR))) { + device_printf(sc->sc_dev, + "unexpected DMA intr CH=%d, CS=%x\n", ch->ch, cs); return; + } /* running? */ if (!(ch->flags & BCM_DMA_CH_USED)) { @@ -651,6 +669,7 @@ static int bcm_dma_attach(device_t dev) { struct bcm_dma_softc *sc = device_get_softc(dev); + phandle_t node; int rid, err = 0; int i; @@ -664,6 +683,19 @@ bcm_dma_attach(device_t dev) sc->sc_intrhand[i] = NULL; } + /* Get DMA channel mask. */ + node = ofw_bus_get_node(sc->sc_dev); + if (OF_getencprop(node, "brcm,dma-channel-mask", &bcm_dma_channel_mask, + sizeof(bcm_dma_channel_mask)) == -1 && + OF_getencprop(node, "broadcom,channels", &bcm_dma_channel_mask, + sizeof(bcm_dma_channel_mask)) == -1) { + device_printf(dev, "could not get channel mask property\n"); + return (ENXIO); + } + + /* Mask out channels used by GPU. */ + bcm_dma_channel_mask &= ~BCM_DMA_CH_GPU_MASK; + /* DMA0 - DMA14 */ rid = 0; sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); @@ -674,6 +706,9 @@ bcm_dma_attach(device_t dev) /* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */ for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) { + if ((bcm_dma_channel_mask & (1 << rid)) == 0) + continue; + sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq[rid] == NULL) { Modified: head/sys/arm/broadcom/bcm2835/bcm2835_dma.h ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_dma.h Tue Feb 16 11:51:54 2016 (r295658) +++ head/sys/arm/broadcom/bcm2835/bcm2835_dma.h Tue Feb 16 12:19:06 2016 (r295659) @@ -37,8 +37,6 @@ /* request CH for any nubmer */ #define BCM_DMA_CH_INVALID (-1) #define BCM_DMA_CH_ANY (-1) -#define BCM_DMA_CH_FAST1 (2) -#define BCM_DMA_CH_FAST2 (3) /* Peripheral DREQ Signals (4.2.1.3) */ #define BCM_DMA_DREQ_NONE 0 Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Tue Feb 16 11:51:54 2016 (r295658) +++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c Tue Feb 16 12:19:06 2016 (r295659) @@ -214,11 +214,7 @@ bcm_sdhci_attach(device_t dev) sdhci_init_slot(dev, &sc->sc_slot, 0); - sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST1); - if (sc->sc_dma_ch == BCM_DMA_CH_INVALID) - sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST2); - if (sc->sc_dma_ch == BCM_DMA_CH_INVALID) - sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY); + sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY); if (sc->sc_dma_ch == BCM_DMA_CH_INVALID) goto fail;