mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Casting a pointer to dma_addr_t produces a warning:
drivers/gpu/drm/meson/meson_rdma.c: In function 'meson_rdma_free':
drivers/gpu/drm/meson/meson_rdma.c:59:25: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
  priv->rdma.addr_phys = (dma_addr_t)NULL;
In this case, it's worse because the variable name has the suffix
'_phys', which often indicates a phys_addr_t rather than dma_addr_t,
i.e. yet another incompatible type.
Change it to use consistent naming and avoid NULL.
Fixes: 63fba242c4 ("drm/meson: add RDMA module driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200107214653.1173199-1-arnd@arndb.de
		
	
			
		
			
				
	
	
		
			135 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0+
 | 
						|
/*
 | 
						|
 * Copyright (C) 2019 BayLibre, SAS
 | 
						|
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/bitfield.h>
 | 
						|
#include <linux/dma-mapping.h>
 | 
						|
 | 
						|
#include "meson_drv.h"
 | 
						|
#include "meson_registers.h"
 | 
						|
#include "meson_rdma.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * The VPU embeds a "Register DMA" that can write a sequence of registers
 | 
						|
 * on the VPU AHB bus, either manually or triggered by an internal IRQ
 | 
						|
 * event like VSYNC or a line input counter.
 | 
						|
 * The initial implementation handles a single channel (over 8), triggered
 | 
						|
 * by the VSYNC irq and does not handle the RDMA irq.
 | 
						|
 */
 | 
						|
 | 
						|
#define RDMA_DESC_SIZE	(sizeof(uint32_t) * 2)
 | 
						|
 | 
						|
int meson_rdma_init(struct meson_drm *priv)
 | 
						|
{
 | 
						|
	if (!priv->rdma.addr) {
 | 
						|
		/* Allocate a PAGE buffer */
 | 
						|
		priv->rdma.addr =
 | 
						|
			dma_alloc_coherent(priv->dev, SZ_4K,
 | 
						|
					   &priv->rdma.addr_dma,
 | 
						|
					   GFP_KERNEL);
 | 
						|
		if (!priv->rdma.addr)
 | 
						|
			return -ENOMEM;
 | 
						|
	}
 | 
						|
 | 
						|
	priv->rdma.offset = 0;
 | 
						|
 | 
						|
	writel_relaxed(RDMA_CTRL_SW_RESET,
 | 
						|
		       priv->io_base + _REG(RDMA_CTRL));
 | 
						|
	writel_relaxed(RDMA_DEFAULT_CONFIG |
 | 
						|
		       FIELD_PREP(RDMA_CTRL_AHB_WR_BURST, 3) |
 | 
						|
		       FIELD_PREP(RDMA_CTRL_AHB_RD_BURST, 0),
 | 
						|
		       priv->io_base + _REG(RDMA_CTRL));
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
void meson_rdma_free(struct meson_drm *priv)
 | 
						|
{
 | 
						|
	if (!priv->rdma.addr && !priv->rdma.addr_dma)
 | 
						|
		return;
 | 
						|
 | 
						|
	meson_rdma_stop(priv);
 | 
						|
 | 
						|
	dma_free_coherent(priv->dev, SZ_4K,
 | 
						|
			  priv->rdma.addr, priv->rdma.addr_dma);
 | 
						|
 | 
						|
	priv->rdma.addr = NULL;
 | 
						|
	priv->rdma.addr_dma = (dma_addr_t)0;
 | 
						|
}
 | 
						|
 | 
						|
void meson_rdma_setup(struct meson_drm *priv)
 | 
						|
{
 | 
						|
	/* Channel 1: Write Flag, No Address Increment */
 | 
						|
	writel_bits_relaxed(RDMA_ACCESS_RW_FLAG_CHAN1 |
 | 
						|
			    RDMA_ACCESS_ADDR_INC_CHAN1,
 | 
						|
			    RDMA_ACCESS_RW_FLAG_CHAN1,
 | 
						|
			    priv->io_base + _REG(RDMA_ACCESS_AUTO));
 | 
						|
}
 | 
						|
 | 
						|
void meson_rdma_stop(struct meson_drm *priv)
 | 
						|
{
 | 
						|
	writel_bits_relaxed(RDMA_IRQ_CLEAR_CHAN1,
 | 
						|
			    RDMA_IRQ_CLEAR_CHAN1,
 | 
						|
			    priv->io_base + _REG(RDMA_CTRL));
 | 
						|
 | 
						|
	/* Stop Channel 1 */
 | 
						|
	writel_bits_relaxed(RDMA_ACCESS_TRIGGER_CHAN1,
 | 
						|
			    FIELD_PREP(RDMA_ACCESS_ADDR_INC_CHAN1,
 | 
						|
				       RDMA_ACCESS_TRIGGER_STOP),
 | 
						|
			    priv->io_base + _REG(RDMA_ACCESS_AUTO));
 | 
						|
}
 | 
						|
 | 
						|
void meson_rdma_reset(struct meson_drm *priv)
 | 
						|
{
 | 
						|
	meson_rdma_stop(priv);
 | 
						|
 | 
						|
	priv->rdma.offset = 0;
 | 
						|
}
 | 
						|
 | 
						|
static void meson_rdma_writel(struct meson_drm *priv, uint32_t val,
 | 
						|
			      uint32_t reg)
 | 
						|
{
 | 
						|
	if (priv->rdma.offset >= (SZ_4K / RDMA_DESC_SIZE)) {
 | 
						|
		dev_warn_once(priv->dev, "%s: overflow\n", __func__);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	priv->rdma.addr[priv->rdma.offset++] = reg;
 | 
						|
	priv->rdma.addr[priv->rdma.offset++] = val;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * This will add the register to the RDMA buffer and write it to the
 | 
						|
 * hardware at the same time.
 | 
						|
 * When meson_rdma_flush is called, the RDMA will replay the register
 | 
						|
 * writes in order.
 | 
						|
 */
 | 
						|
void meson_rdma_writel_sync(struct meson_drm *priv, uint32_t val, uint32_t reg)
 | 
						|
{
 | 
						|
	meson_rdma_writel(priv, val, reg);
 | 
						|
 | 
						|
	writel_relaxed(val, priv->io_base + _REG(reg));
 | 
						|
}
 | 
						|
 | 
						|
void meson_rdma_flush(struct meson_drm *priv)
 | 
						|
{
 | 
						|
	meson_rdma_stop(priv);
 | 
						|
 | 
						|
	/* Start of Channel 1 register writes buffer */
 | 
						|
	writel(priv->rdma.addr_dma,
 | 
						|
	       priv->io_base + _REG(RDMA_AHB_START_ADDR_1));
 | 
						|
 | 
						|
	/* Last byte on Channel 1 register writes buffer */
 | 
						|
	writel(priv->rdma.addr_dma + (priv->rdma.offset * RDMA_DESC_SIZE) - 1,
 | 
						|
	       priv->io_base + _REG(RDMA_AHB_END_ADDR_1));
 | 
						|
 | 
						|
	/* Trigger Channel 1 on VSYNC event */
 | 
						|
	writel_bits_relaxed(RDMA_ACCESS_TRIGGER_CHAN1,
 | 
						|
			    FIELD_PREP(RDMA_ACCESS_TRIGGER_CHAN1,
 | 
						|
				       RDMA_ACCESS_TRIGGER_VSYNC),
 | 
						|
			    priv->io_base + _REG(RDMA_ACCESS_AUTO));
 | 
						|
 | 
						|
	priv->rdma.offset = 0;
 | 
						|
}
 |