Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f66cf70 authored by Sushmita Susheelendra's avatar Sushmita Susheelendra Committed by Gerrit - the friendly Code Review server
Browse files

msm: kgsl: Add support for GPU System Cache usage



Activate and deactivate the GPU slice in the system
cache upon GPU power collapse/restore. Configure the
SCIDs for the slices used by the GPU. Currently, the
GPU uses one slice for all its blocks.
Also enable the right memory attributes for a buffer
to be allocated into the system cache. The memory
attributes used are outer-cacheable, read-allocate,
write-no-allocate.

CRs-Fixed: 1081617
Change-Id: I54d5ddce8056c0ef491a21bb19ce9fd9e30a0540
Signed-off-by: default avatarSushmita Susheelendra <ssusheel@codeaurora.org>
parent ac182352
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -194,6 +194,11 @@ Properties:
- qcom,mempool-allocate:	Allocate memory from the system memory when the
				reserved pool exhausted.

GPU LLC slice info:
- cache-slice-names:		List of LLC cache slices for GPU transactions
				and pagetable walk.
- cache-slices:			phandle to the system LLC driver, cache slice index.

The following properties are optional as collecting data via coresight might
not be supported for every chipset. The documentation for coresight
properties can be found in:
+25 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "kgsl_sharedmem.h"
#include "kgsl_iommu.h"
#include "kgsl_trace.h"
#include "adreno_llc.h"

#include "adreno.h"
#include "adreno_iommu.h"
@@ -1026,6 +1027,15 @@ static int adreno_probe(struct platform_device *pdev)
	/* Initialize coresight for the target */
	adreno_coresight_init(adreno_dev);

	/* Get the system cache slice descriptor for GPU */
	adreno_dev->gpu_llc_slice = adreno_llc_getd(&pdev->dev, "gpu");
	if (IS_ERR(adreno_dev->gpu_llc_slice)) {
		KGSL_DRV_WARN(device,
			"Failed to get GPU LLC slice descriptor (%ld)\n",
			PTR_ERR(adreno_dev->gpu_llc_slice));
		adreno_dev->gpu_llc_slice = NULL;
	}

	adreno_input_handler.private = device;

#ifdef CONFIG_INPUT
@@ -1095,6 +1105,10 @@ static int adreno_remove(struct platform_device *pdev)
	adreno_coresight_remove(adreno_dev);
	adreno_profile_close(adreno_dev);

	/* Release the system cache slice descriptor */
	if (adreno_dev->gpu_llc_slice)
		adreno_llc_putd(adreno_dev->gpu_llc_slice);

	kgsl_pwrscale_close(device);

	adreno_dispatcher_close(adreno_dev);
@@ -1419,6 +1433,14 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	/* Start the GPU */
	gpudev->start(adreno_dev);

	/*
	 * The system cache control registers
	 * live on the CX rail. Hence need
	 * reprogramming everytime the GPU
	 * comes out of power collapse.
	 */
	adreno_llc_setup(device);

	/* Re-initialize the coresight registers if applicable */
	adreno_coresight_start(adreno_dev);

@@ -1553,6 +1575,9 @@ static int adreno_stop(struct kgsl_device *device)

	adreno_ocmem_free(adreno_dev);

	if (adreno_dev->gpu_llc_slice)
		adreno_llc_deactivate_slice(adreno_dev->gpu_llc_slice);

	/* Save active coresight registers if applicable */
	adreno_coresight_stop(adreno_dev);

+5 −0
Original line number Diff line number Diff line
@@ -396,6 +396,7 @@ struct adreno_gpu_core {
 * @irq_storm_work: Worker to handle possible interrupt storms
 * @active_list: List to track active contexts
 * @active_list_lock: Lock to protect active_list
 * @gpu_llc_slice: GPU system cache slice descriptor
 */
struct adreno_device {
	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -454,6 +455,8 @@ struct adreno_device {

	struct list_head active_list;
	spinlock_t active_list_lock;

	void *gpu_llc_slice;
};

/**
@@ -809,6 +812,8 @@ struct adreno_gpudev {
	void (*enable_64bit)(struct adreno_device *);
	void (*clk_set_options)(struct adreno_device *,
				const char *, struct clk *);
	void (*llc_configure_gpu_scid)(struct adreno_device *adreno_dev);
	void (*llc_enable_overrides)(struct adreno_device *adreno_dev);
};

/**
+72 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "adreno_pm4types.h"
#include "adreno_perfcounter.h"
#include "adreno_ringbuffer.h"
#include "adreno_llc.h"
#include "kgsl_sharedmem.h"
#include "kgsl_log.h"
#include "kgsl.h"
@@ -30,6 +31,13 @@

#define MIN_HBB		13

#define A6XX_LLC_NUM_GPU_SCIDS		5
#define A6XX_GPU_LLC_SCID_NUM_BITS	5
#define A6XX_GPU_LLC_SCID_MASK \
	((1 << (A6XX_LLC_NUM_GPU_SCIDS * A6XX_GPU_LLC_SCID_NUM_BITS)) - 1)
#define A6XX_GPU_CX_REG_BASE		0x509E000
#define A6XX_GPU_CX_REG_SIZE		0x1000

static const struct adreno_vbif_data a630_vbif[] = {
	{A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009},
	{A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3},
@@ -580,6 +588,68 @@ static void a6xx_err_callback(struct adreno_device *adreno_dev, int bit)
	}
}

/* GPU System Cache control registers */
#define A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_0   0x4
#define A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_1   0x8

static inline void _reg_rmw(void __iomem *regaddr,
	unsigned int mask, unsigned int bits)
{
	unsigned int val = 0;

	val = __raw_readl(regaddr);
	/* Make sure the above read completes before we proceed  */
	rmb();
	val &= ~mask;
	__raw_writel(val | bits, regaddr);
	/* Make sure the above write posts before we proceed*/
	wmb();
}


/*
 * a6xx_llc_configure_gpu_scid() - Program the sub-cache ID for all GPU blocks
 * @adreno_dev: The adreno device pointer
 */
static void a6xx_llc_configure_gpu_scid(struct adreno_device *adreno_dev)
{
	uint32_t gpu_scid;
	uint32_t gpu_cntl1_val = 0;
	int i;
	void __iomem *gpu_cx_reg;

	gpu_scid = adreno_llc_get_scid(adreno_dev->gpu_llc_slice);
	for (i = 0; i < A6XX_LLC_NUM_GPU_SCIDS; i++)
		gpu_cntl1_val = (gpu_cntl1_val << A6XX_GPU_LLC_SCID_NUM_BITS)
			| gpu_scid;

	gpu_cx_reg = ioremap(A6XX_GPU_CX_REG_BASE, A6XX_GPU_CX_REG_SIZE);
	_reg_rmw(gpu_cx_reg + A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_1,
			A6XX_GPU_LLC_SCID_MASK, gpu_cntl1_val);
	iounmap(gpu_cx_reg);
}

/*
 * a6xx_llc_enable_overrides() - Override the page attributes
 * @adreno_dev: The adreno device pointer
 */
static void a6xx_llc_enable_overrides(struct adreno_device *adreno_dev)
{
	void __iomem *gpu_cx_reg;

	/*
	 * 0x3: readnoallocoverrideen=0
	 *      read-no-alloc=0 - Allocate lines on read miss
	 *      writenoallocoverrideen=1
	 *      write-no-alloc=1 - Do not allocates lines on write miss
	 */
	gpu_cx_reg = ioremap(A6XX_GPU_CX_REG_BASE, A6XX_GPU_CX_REG_SIZE);
	__raw_writel(0x3, gpu_cx_reg + A6XX_GPU_CX_MISC_SYSTEM_CACHE_CNTL_0);
	/* Make sure the above write posts before we proceed*/
	wmb();
	iounmap(gpu_cx_reg);
}

#define A6XX_INT_MASK \
	((1 << A6XX_INT_CP_AHB_ERROR) |		\
	 (1 << A6XX_INT_ATB_ASYNCFIFO_OVERFLOW) |	\
@@ -691,4 +761,6 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
	.regulator_disable = a6xx_sptprac_disable,
	.microcode_read = a6xx_microcode_read,
	.enable_64bit = a6xx_enable_64bit,
	.llc_configure_gpu_scid = a6xx_llc_configure_gpu_scid,
	.llc_enable_overrides = a6xx_llc_enable_overrides
};
+91 −0
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
#ifndef __ADRENO_LLC_H
#define __ADRENO_LLC_H

#ifdef CONFIG_QCOM_LLCC
#include "adreno.h"
#include <linux/soc/qcom/llcc-qcom.h>

static inline bool adreno_llc_supported(void)
{
	return true;
}

static inline void *adreno_llc_getd(struct device *dev, const char *name)
{
	return llcc_slice_getd(dev, name);
}

static inline void adreno_llc_putd(void *desc)
{
	llcc_slice_putd(desc);
}

static inline int adreno_llc_deactivate_slice(void *desc)
{
	return llcc_slice_deactivate(desc);
}

static inline int adreno_llc_get_scid(void *desc)
{
	return llcc_get_slice_id(desc);

}

static inline void adreno_llc_setup(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);

	if (adreno_dev->gpu_llc_slice)
		if (!llcc_slice_activate(adreno_dev->gpu_llc_slice)) {
			if (gpudev->llc_configure_gpu_scid)
				gpudev->llc_configure_gpu_scid(adreno_dev);
			if (gpudev->llc_enable_overrides)
				gpudev->llc_enable_overrides(adreno_dev);
		}
}

#else
static inline bool adreno_llc_supported(void)
{
	return false;
}

static inline void *adreno_llc_getd(struct device *dev,
		const char *name)
{
	return NULL;
}

static inline void adreno_llc_putd(void *desc)
{
}

static inline int adreno_llc_deactivate_slice(void *desc)
{
	return 0;
}

static inline int adreno_llc_get_scid(void *desc)
{
	return 0;
}

static inline void adreno_llc_setup(struct kgsl_device *device)
{
}
#endif

#endif /* __ADRENO_LLC_H */
Loading