diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index dbd1159a2ef0a..bf2f39a992550 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -450,8 +450,8 @@ static int __maybe_unused lynxfb_resume(struct device *dev) par = info->par; crtc = &par->crtc; cursor = &crtc->cursor; - memset_io(cursor->vstart, 0x0, cursor->size); - memset_io(crtc->v_screen, 0x0, crtc->vidmem_size); + memset_io_pcie(cursor->vstart, 0x0, cursor->size); + memset_io_pcie(crtc->v_screen, 0x0, crtc->vidmem_size); lynxfb_ops_set_par(info); fb_set_suspend(info, 0); } @@ -462,8 +462,8 @@ static int __maybe_unused lynxfb_resume(struct device *dev) par = info->par; crtc = &par->crtc; cursor = &crtc->cursor; - memset_io(cursor->vstart, 0x0, cursor->size); - memset_io(crtc->v_screen, 0x0, crtc->vidmem_size); + memset_io_pcie(cursor->vstart, 0x0, cursor->size); + memset_io_pcie(crtc->v_screen, 0x0, crtc->vidmem_size); lynxfb_ops_set_par(info); fb_set_suspend(info, 0); } @@ -727,7 +727,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) crtc->cursor.size = crtc->cursor.max_h * crtc->cursor.max_w * 2 / 8; crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset; - memset_io(crtc->cursor.vstart, 0, crtc->cursor.size); + memset_io_pcie(crtc->cursor.vstart, 0, crtc->cursor.size); if (!g_hwcursor) { lynxfb_ops.fb_cursor = NULL; sm750_hw_cursor_disable(&crtc->cursor); @@ -1061,7 +1061,7 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->mtrr.vram = arch_phys_wc_add(sm750_dev->vidmem_start, sm750_dev->vidmem_size); - memset_io(sm750_dev->pvMem, 0, sm750_dev->vidmem_size); + memset_io_pcie(sm750_dev->pvMem, 0, sm750_dev->vidmem_size); pci_set_drvdata(pdev, sm750_dev); @@ -1189,6 +1189,98 @@ module_exit(lynxfb_exit); module_param(g_option, charp, 0444); +/** + * DOC: memcpy_fromio_pcie + * + * like memcpy_fromio, but it only uses 8-bit and 32-bit wide accesses to work on a raspberry pi 4 + */ + + void memcpy_fromio_pcie(void *to, const volatile void __iomem *from, size_t count) + { + while (count && !IS_ALIGNED((unsigned long)from, 8)) { + *(u8 *)to = __raw_readb(from); + from++; + to++; + count--; + } + + while (count >= 4) { + *(u32 *)to = __raw_readl(from); + from += 4; + to += 4; + count -= 4; + } + + while (count) { + *(u8 *)to = __raw_readb(from); + from++; + to++; + count--; + } +} + +/** + * DOC: memcpy_toio_pcie + * + * like memcpy_toio, but it only uses 8-bit and 32-bit wide accesses to work on a raspberry pi 4 + */ + +void memcpy_toio_pcie(volatile void __iomem *to, const void *from, size_t count) +{ + while (count && !IS_ALIGNED((unsigned long)to, 8)) { + __raw_writeb(*(u8 *)from, to); + from++; + to++; + count--; + } + + while (count >= 4) { + __raw_writel(*(u64 *)from, to); + from += 4; + to += 4; + count -= 4; + } + + while (count) { + __raw_writeb(*(u8 *)from, to); + from++; + to++; + count--; + } +} + +/** + * DOC: memset_io_pcie + * + * like memset_io, but it only uses 8-bit and 32-bit wide accesses to work on a raspberry pi 4 + */ + +void memset_io_pcie(volatile void __iomem *dst, int c, size_t count) +{ + u32 qc = (u8)c; + + qc |= qc << 8; + qc |= qc << 16; + + while (count && !IS_ALIGNED((unsigned long)dst, 8)) { + __raw_writeb(c, dst); + dst++; + count--; + } + + while (count >= 4) { + __raw_writel(qc, dst); + dst += 4; + count -= 4; + } + + while (count) { + __raw_writeb(c, dst); + dst++; + count--; + } +} + MODULE_PARM_DESC(g_option, "\n\t\tCommon options:\n" "\t\tnoaccel:disable 2d capabilities\n" diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index aff69661c8e62..7dd2cbaaa23f5 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -217,4 +217,11 @@ int hw_sm750_pan_display(struct lynxfb_crtc *crtc, const struct fb_var_screeninfo *var, const struct fb_info *info); +/* + * memcpy_io and memset_io functions that work on a raspberry pi 4 + */ +void memcpy_fromio_pcie(void *to, const volatile void __iomem *from, size_t count); +void memcpy_toio_pcie(volatile void __iomem *to, const void *from, size_t count); +void memset_io_pcie(volatile void __iomem *dst, int c, size_t count); + #endif diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index a7c6eb07b62e0..2ec7ed591718e 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -79,7 +79,7 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* reserve the vidmem space of smi adaptor */ sm750_dev->pvMem = - ioremap_wc(sm750_dev->vidmem_start, sm750_dev->vidmem_size); + ioremap(sm750_dev->vidmem_start, sm750_dev->vidmem_size); if (!sm750_dev->pvMem) { pr_err("Map video memory failed\n"); ret = -EFAULT;