Allow pxa2x0_lcd driver mapping screen buffer memory cachable with

write-through map (i.e. map it without BUS_DMA_COHERENT) since
currently all DMA data transfers are memory to device only.

Disabled by default, but enabled by "options PXA2X0_LCD_WRITETHROUGH"
or setting pxa2x0_lcd_writethrough = 1 in a kernel binary.

Tested on WS003SH by me and on WS011SH by jun@, and console output speed
is improved ~three times faster than coherent (uncached) mapping.

XXX: should we have a flag like BUS_DMA_WRITETHROUGH in MI bus_dma(9)?
This commit is contained in:
tsutsui 2010-08-08 11:24:52 +00:00
parent a21349fd63
commit 0d803bc828

View File

@ -1,4 +1,4 @@
/* $NetBSD: pxa2x0_lcd.c,v 1.29 2010/08/08 09:33:35 kiyohara Exp $ */
/* $NetBSD: pxa2x0_lcd.c,v 1.30 2010/08/08 11:24:52 tsutsui Exp $ */
/*
* Copyright (c) 2002 Genetec Corporation. All rights reserved.
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.29 2010/08/08 09:33:35 kiyohara Exp $");
__KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.30 2010/08/08 11:24:52 tsutsui Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -78,6 +78,12 @@ struct {
const struct lcd_panel_geometry *geom;
} pxa2x0_lcd_console;
#ifdef PXA2X0_LCD_WRITETHROUGH
int pxa2x0_lcd_writethrough = 1; /* patchable */
#else
int pxa2x0_lcd_writethrough = 0;
#endif
int lcdintr(void *);
static void pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc *,
@ -333,6 +339,9 @@ pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc *sc,
iot = sc->iot;
ioh = sc->ioh;
bus_dmamap_sync(sc->dma_tag, scr->dma, 0, scr->buf_size,
BUS_DMASYNC_PREWRITE);
save = disable_interrupts(I32_bit);
switch (scr->depth) {
@ -536,10 +545,31 @@ pxa2x0_lcd_new_screen(struct pxa2x0_lcd_softc *sc, int depth,
}
error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs, size,
(void **)&scr->buf_va, busdma_flag | BUS_DMA_COHERENT);
(void **)&scr->buf_va,
busdma_flag | (pxa2x0_lcd_writethrough ? 0 : BUS_DMA_COHERENT));
if (error)
goto bad;
/* XXX: should we have BUS_DMA_WRITETHROUGH in MI bus_dma(9) API? */
if (pxa2x0_lcd_writethrough) {
pt_entry_t *ptep;
vaddr_t va, eva;
va = (vaddr_t)scr->buf_va;
eva = va + size;
while (va < eva) {
/* taken from arm/arm32/bus_dma.c:_bus_dmamem_map() */
cpu_dcache_wbinv_range(va, PAGE_SIZE);
cpu_drain_writebuf();
ptep = vtopte(va);
*ptep &= ~L2_S_CACHE_MASK;
*ptep |= L2_C;
PTE_SYNC(ptep);
tlb_flush();
va += PAGE_SIZE;
}
}
memset(scr->buf_va, 0, scr->buf_size);
/* map memory for DMA */
@ -899,7 +929,8 @@ pxa2x0_lcd_mmap(void *v, void *vs, off_t offset, int prot)
return -1;
return bus_dmamem_mmap(sc->dma_tag, scr->segs, scr->nsegs,
offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
offset, prot,
BUS_DMA_WAITOK | (pxa2x0_lcd_writethrough ? 0 : BUS_DMA_COHERENT));
}