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

Commit f02e84cb authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Add support for PDC register subsections"

parents 1dcd4a0d 53150421
Loading
Loading
Loading
Loading
+33 −27
Original line number Diff line number Diff line
@@ -1058,33 +1058,39 @@
#define A6XX_RSCC_TCS3_DRV0_STATUS                      0x23B7E

/* GPU PDC sequencer registers in AOSS.RPMh domain */
#define	PDC_GPU_ENABLE_PDC			0x21140
#define PDC_GPU_SEQ_START_ADDR			0x21148
#define PDC_GPU_TCS0_CONTROL			0x21540
#define PDC_GPU_TCS0_CMD_ENABLE_BANK		0x21541
#define PDC_GPU_TCS0_CMD_WAIT_FOR_CMPL_BANK	0x21542
#define PDC_GPU_TCS0_CMD0_MSGID			0x21543
#define PDC_GPU_TCS0_CMD0_ADDR			0x21544
#define PDC_GPU_TCS0_CMD0_DATA			0x21545
#define PDC_GPU_TCS1_CONTROL			0x21572
#define PDC_GPU_TCS1_CMD_ENABLE_BANK		0x21573
#define PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK	0x21574
#define PDC_GPU_TCS1_CMD0_MSGID			0x21575
#define PDC_GPU_TCS1_CMD0_ADDR			0x21576
#define PDC_GPU_TCS1_CMD0_DATA			0x21577
#define PDC_GPU_TCS2_CONTROL			0x215A4
#define PDC_GPU_TCS2_CMD_ENABLE_BANK		0x215A5
#define PDC_GPU_TCS2_CMD_WAIT_FOR_CMPL_BANK	0x215A6
#define PDC_GPU_TCS2_CMD0_MSGID			0x215A7
#define PDC_GPU_TCS2_CMD0_ADDR			0x215A8
#define PDC_GPU_TCS2_CMD0_DATA			0x215A9
#define PDC_GPU_TCS3_CONTROL			0x215D6
#define PDC_GPU_TCS3_CMD_ENABLE_BANK		0x215D7
#define PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK	0x215D8
#define PDC_GPU_TCS3_CMD0_MSGID			0x215D9
#define PDC_GPU_TCS3_CMD0_ADDR			0x215DA
#define PDC_GPU_TCS3_CMD0_DATA			0x215DB
#define PDC_GPU_SEQ_MEM_0			0xA0000
#define PDC_GPU_ENABLE_PDC			0x1140
#define PDC_GPU_SEQ_START_ADDR			0x1148
#define PDC_GPU_TCS0_CONTROL			0x1540
#define PDC_GPU_TCS0_CMD_ENABLE_BANK		0x1541
#define PDC_GPU_TCS0_CMD_WAIT_FOR_CMPL_BANK	0x1542
#define PDC_GPU_TCS0_CMD0_MSGID			0x1543
#define PDC_GPU_TCS0_CMD0_ADDR			0x1544
#define PDC_GPU_TCS0_CMD0_DATA			0x1545
#define PDC_GPU_TCS1_CONTROL			0x1572
#define PDC_GPU_TCS1_CMD_ENABLE_BANK		0x1573
#define PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK	0x1574
#define PDC_GPU_TCS1_CMD0_MSGID			0x1575
#define PDC_GPU_TCS1_CMD0_ADDR			0x1576
#define PDC_GPU_TCS1_CMD0_DATA			0x1577
#define PDC_GPU_TCS2_CONTROL			0x15A4
#define PDC_GPU_TCS2_CMD_ENABLE_BANK		0x15A5
#define PDC_GPU_TCS2_CMD_WAIT_FOR_CMPL_BANK	0x15A6
#define PDC_GPU_TCS2_CMD0_MSGID			0x15A7
#define PDC_GPU_TCS2_CMD0_ADDR			0x15A8
#define PDC_GPU_TCS2_CMD0_DATA			0x15A9
#define PDC_GPU_TCS3_CONTROL			0x15D6
#define PDC_GPU_TCS3_CMD_ENABLE_BANK		0x15D7
#define PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK	0x15D8
#define PDC_GPU_TCS3_CMD0_MSGID			0x15D9
#define PDC_GPU_TCS3_CMD0_ADDR			0x15DA
#define PDC_GPU_TCS3_CMD0_DATA			0x15DB

/*
 * Legacy DTSI used an offset from the start of the PDC resource
 * for PDC SEQ programming. We are now using PDC subsections so
 * start the PDC SEQ offset at zero.
 */
#define PDC_GPU_SEQ_MEM_0			0x0

#endif /* _A6XX_REG_H */
+111 −56
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_platform.h>

#include "kgsl_gmu_core.h"
#include "kgsl_gmu.h"
@@ -79,10 +81,70 @@ static void _regwrite(void __iomem *regbase,
 * PDC and RSC execute GPU power on/off RPMh sequence
 * @device: Pointer to KGSL device
 */
static void _load_gmu_rpmh_ucode(struct kgsl_device *device)
static int _load_gmu_rpmh_ucode(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct resource *res_pdc, *res_cfg, *res_seq;
	void __iomem *cfg = NULL, *seq = NULL;
	unsigned int cfg_offset, seq_offset;

	/* Offsets from the base PDC (if no PDC subsections in the DTSI) */
	if (adreno_is_a640v2(adreno_dev)) {
		cfg_offset = 0x90000;
		seq_offset = 0x290000;
	} else {
		cfg_offset = 0x80000;
		seq_offset = 0x280000;
	}

	/*
	 * Older A6x platforms specified PDC registers in the DT using a
	 * single base pointer that encompassed the entire PDC range. Current
	 * targets specify the individual GPU-owned PDC register blocks
	 * (sequence and config).
	 *
	 * This code handles both possibilities and generates individual
	 * pointers to the GPU PDC blocks, either as offsets from the single
	 * base, or as directly specified ranges.
	 */

	/* Get pointers to each of the possible PDC resources */
	res_pdc = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM,
			"kgsl_gmu_pdc_reg");
	res_cfg = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM,
			"kgsl_gmu_pdc_cfg");
	res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM,
			"kgsl_gmu_pdc_seq");

	/*
	 * Map the starting address for pdc_cfg programming. If the pdc_cfg
	 * resource is not available use an offset from the base PDC resource.
	 */
	if (res_cfg)
		cfg = ioremap(res_cfg->start, resource_size(res_cfg));
	else if (res_pdc)
		cfg = ioremap(res_pdc->start + cfg_offset, 0x10000);

	if (!cfg) {
		dev_err(&gmu->pdev->dev, "Failed to map PDC CFG\n");
		return -ENODEV;
	}

	/*
	 * Map the starting address for pdc_seq programming. If the pdc_seq
	 * resource is not available use an offset from the base PDC resource.
	 */
	if (res_seq)
		seq = ioremap(res_seq->start, resource_size(res_seq));
	else if (res_pdc)
		seq = ioremap(res_pdc->start + seq_offset, 0x10000);

	if (!seq) {
		dev_err(&gmu->pdev->dev, "Failed to map PDC SEQ\n");
		iounmap(cfg);
		return -ENODEV;
	}

	/* Disable SDE clock gating */
	gmu_core_regwrite(device, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
@@ -118,68 +180,62 @@ static void _load_gmu_rpmh_ucode(struct kgsl_device *device)
	gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8);

	/* Load PDC sequencer uCode for power up and power down sequence */
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_SEQ_MEM_0 + 1, 0xA5A4A3A2);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_SEQ_MEM_0 + 2, 0x8382A6E0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_SEQ_MEM_0 + 3, 0xBCE3E284);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_SEQ_MEM_0 + 4, 0x002081FC);
	_regwrite(seq, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1);
	_regwrite(seq, PDC_GPU_SEQ_MEM_0 + 1, 0xA5A4A3A2);
	_regwrite(seq, PDC_GPU_SEQ_MEM_0 + 2, 0x8382A6E0);
	_regwrite(seq, PDC_GPU_SEQ_MEM_0 + 3, 0xBCE3E284);
	_regwrite(seq, PDC_GPU_SEQ_MEM_0 + 4, 0x002081FC);

	/* Set TCS commands used by PDC sequence for low power modes */
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS1_CMD_ENABLE_BANK, 7);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK, 0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS1_CONTROL, 0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS1_CMD0_MSGID, 0x10108);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS1_CMD0_ADDR, 0x30010);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS1_CMD0_DATA, 1);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_MSGID + PDC_CMD_OFFSET, 0x10108);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_ADDR + PDC_CMD_OFFSET, 0x30000);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_DATA + PDC_CMD_OFFSET, 0x0);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_MSGID + PDC_CMD_OFFSET * 2, 0x10108);
	_regwrite(cfg, PDC_GPU_TCS1_CMD_ENABLE_BANK, 7);
	_regwrite(cfg, PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK, 0);
	_regwrite(cfg, PDC_GPU_TCS1_CONTROL, 0);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_MSGID, 0x10108);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_ADDR, 0x30010);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_DATA, 1);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_MSGID + PDC_CMD_OFFSET, 0x10108);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_ADDR + PDC_CMD_OFFSET, 0x30000);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_DATA + PDC_CMD_OFFSET, 0x0);
	_regwrite(cfg, PDC_GPU_TCS1_CMD0_MSGID + PDC_CMD_OFFSET * 2, 0x10108);

	if (adreno_is_a640(adreno_dev) || adreno_is_a680(adreno_dev))
		_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_ADDR + PDC_CMD_OFFSET * 2, 0x30090);
		_regwrite(cfg, PDC_GPU_TCS1_CMD0_ADDR + PDC_CMD_OFFSET * 2,
				0x30090);
	else
		_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_ADDR + PDC_CMD_OFFSET * 2, 0x30080);

	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS1_CMD0_DATA + PDC_CMD_OFFSET * 2, 0x0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK, 0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS3_CONTROL, 0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS3_CMD0_MSGID, 0x10108);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS3_CMD0_ADDR, 0x30010);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_TCS3_CMD0_DATA, 2);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_MSGID + PDC_CMD_OFFSET, 0x10108);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET, 0x30000);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_DATA + PDC_CMD_OFFSET, 0x3);
	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_MSGID + PDC_CMD_OFFSET * 2, 0x10108);
		_regwrite(cfg, PDC_GPU_TCS1_CMD0_ADDR + PDC_CMD_OFFSET * 2,
				0x30080);

	_regwrite(cfg, PDC_GPU_TCS1_CMD0_DATA + PDC_CMD_OFFSET * 2, 0x0);
	_regwrite(cfg, PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
	_regwrite(cfg, PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK, 0);
	_regwrite(cfg, PDC_GPU_TCS3_CONTROL, 0);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_MSGID, 0x10108);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_ADDR, 0x30010);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_DATA, 2);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_MSGID + PDC_CMD_OFFSET, 0x10108);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET, 0x30000);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_DATA + PDC_CMD_OFFSET, 0x3);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_MSGID + PDC_CMD_OFFSET * 2, 0x10108);

	if (adreno_is_a640(adreno_dev) || adreno_is_a680(adreno_dev))
		_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET * 2, 0x30090);
		_regwrite(cfg, PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET * 2,
				0x30090);
	else
		_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET * 2, 0x30080);

	_regwrite(gmu->pdc_reg_virt,
			PDC_GPU_TCS3_CMD0_DATA + PDC_CMD_OFFSET * 2, 0x3);
		_regwrite(cfg, PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET * 2,
				0x30080);
	_regwrite(cfg, PDC_GPU_TCS3_CMD0_DATA + PDC_CMD_OFFSET * 2, 0x3);

	/* Setup GPU PDC */
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_SEQ_START_ADDR, 0);
	_regwrite(gmu->pdc_reg_virt, PDC_GPU_ENABLE_PDC, 0x80000001);
	_regwrite(cfg, PDC_GPU_SEQ_START_ADDR, 0);
	_regwrite(cfg, PDC_GPU_ENABLE_PDC, 0x80000001);

	/* ensure no writes happen before the uCode is fully written */
	wmb();

	iounmap(seq);
	iounmap(cfg);

	return 0;
}

/* GMU timeouts */
@@ -900,12 +956,11 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
		gmu_core_regwrite(device, A6XX_GMU_GENERAL_7, 1);

		if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags))
			_load_gmu_rpmh_ucode(device);
		else {
			ret = _load_gmu_rpmh_ucode(device);
		else
			ret = a6xx_rpmh_power_on_gpu(device);
		if (ret)
			return ret;
		}

		if (gmu->load_mode == TCM_BOOT) {
			/* Load GMU image via AHB bus */
+14 −32
Original line number Diff line number Diff line
@@ -1076,44 +1076,35 @@ static int gmu_pwrlevel_probe(struct gmu_device *gmu, struct device_node *node)
	return 0;
}

static int gmu_reg_probe(struct gmu_device *gmu, const char *name, bool is_gmu)
static int gmu_reg_probe(struct gmu_device *gmu)
{
	struct resource *res;

	res = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, name);
	res = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM,
			"kgsl_gmu_reg");
	if (res == NULL) {
		dev_err(&gmu->pdev->dev,
				"platform_get_resource %s failed\n", name);
			"platform_get_resource kgsl_gmu_reg failed\n");
		return -EINVAL;
	}

	if (res->start == 0 || resource_size(res) == 0) {
		dev_err(&gmu->pdev->dev,
				"dev %d %s invalid register region\n",
				gmu->pdev->dev.id, name);
				"dev %d kgsl_gmu_reg invalid register region\n",
				gmu->pdev->dev.id);
		return -EINVAL;
	}

	if (is_gmu) {
	gmu->reg_phys = res->start;
	gmu->reg_len = resource_size(res);

	gmu->reg_virt = devm_ioremap(&gmu->pdev->dev, res->start,
			resource_size(res));

	if (gmu->reg_virt == NULL) {
			dev_err(&gmu->pdev->dev, "GMU regs ioremap failed\n");
		dev_err(&gmu->pdev->dev, "kgsl_gmu_reg ioremap failed\n");
		return -ENODEV;
	}

	} else {
		gmu->pdc_reg_virt = devm_ioremap(&gmu->pdev->dev, res->start,
				resource_size(res));
		if (gmu->pdc_reg_virt == NULL) {
			dev_err(&gmu->pdev->dev, "PDC regs ioremap failed\n");
			return -ENODEV;
		}
	}

	return 0;
}

@@ -1314,11 +1305,7 @@ static int gmu_probe(struct kgsl_device *device,
	mem_addr = gmu->hfi_mem;

	/* Map and reserve GMU CSRs registers */
	ret = gmu_reg_probe(gmu, "kgsl_gmu_reg", true);
	if (ret)
		goto error;

	ret = gmu_reg_probe(gmu, "kgsl_gmu_pdc_reg", false);
	ret = gmu_reg_probe(gmu);
	if (ret)
		goto error;

@@ -1740,11 +1727,6 @@ static void gmu_remove(struct kgsl_device *device)
		gmu->pcl = 0;
	}

	if (gmu->pdc_reg_virt) {
		devm_iounmap(&gmu->pdev->dev, gmu->pdc_reg_virt);
		gmu->pdc_reg_virt = NULL;
	}

	if (gmu->reg_virt) {
		devm_iounmap(&gmu->pdev->dev, gmu->reg_virt);
		gmu->reg_virt = NULL;
+0 −2
Original line number Diff line number Diff line
@@ -105,7 +105,6 @@ enum gmu_load_mode {
 * @reg_phys: GMU CSR physical address
 * @reg_virt: GMU CSR virtual address
 * @reg_len: GMU CSR range
 * @pdc_reg_virt: starting kernel virtual address for RPMh PDC registers
 * @gmu_interrupt_num: GMU interrupt number
 * @fw_image: descriptor of GMU memory that has GMU image in it
 * @hfi_mem: pointer to HFI shared memory
@@ -142,7 +141,6 @@ struct gmu_device {
	unsigned long reg_phys;
	void __iomem *reg_virt;
	unsigned int reg_len;
	void __iomem *pdc_reg_virt;
	unsigned int gmu_interrupt_num;
	struct gmu_memdesc cached_fw_image;
	struct gmu_memdesc *fw_image;