int kgsl_ringbuffer_init(struct kgsl_device *device)
{
	int status;
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device);
	struct kgsl_ringbuffer *rb = &yamato_device->ringbuffer;

	rb->device = device;
	rb->sizedwords = (2 << kgsl_cfg_rb_sizelog2quadwords);
	rb->blksizequadwords = kgsl_cfg_rb_blksizequadwords;

	/* allocate memory for ringbuffer */
	status = kgsl_sharedmem_alloc_coherent(&rb->buffer_desc,
					       (rb->sizedwords << 2));
	if (status != 0) {
		kgsl_ringbuffer_close(rb);
		return status;
	}

	/* allocate memory for polling and timestamps */
	/* This really can be at 4 byte alignment boundry but for using MMU
	 * we need to make it at page boundary */
	status = kgsl_sharedmem_alloc_coherent(&rb->memptrs_desc,
					       sizeof(struct kgsl_rbmemptrs));
	if (status != 0) {
		kgsl_ringbuffer_close(rb);
		return status;
	}

	/* overlay structure on memptrs memory */
	rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;

	return 0;
}
static int kgsl_ringbuffer_load_pm4_ucode(struct kgsl_device *device)
{
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device);
	const char *fwfile;
	int i, ret = 0;

	if (device->chip_id == KGSL_CHIPID_LEIA_REV470)
		fwfile =  LEIA_PM4_470_FW;
	else
		fwfile =  YAMATO_PM4_FW;

	if (yamato_device->pm4_fw == NULL) {
		int len;
		unsigned int *ptr;

		ret = _load_firmware(device, fwfile, (void *) &ptr, &len);
		if (ret)
			goto err;

		/* PM4 size is 3 dword aligned plus 1 dword of version */
		if (len % ((sizeof(uint32_t) * 3)) != sizeof(uint32_t)) {
			KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len);
			ret = -EINVAL;
			goto err;
		}

		yamato_device->pm4_fw_size = len / sizeof(uint32_t);
		yamato_device->pm4_fw = ptr;
	}

	KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n",
		yamato_device->pm4_fw[0]);

	kgsl_yamato_regwrite(device, REG_CP_DEBUG, 0x02000000);
	kgsl_yamato_regwrite(device, REG_CP_ME_RAM_WADDR, 0);
	for (i = 1; i < yamato_device->pm4_fw_size; i++)
		kgsl_yamato_regwrite(device, REG_CP_ME_RAM_DATA,
				     yamato_device->pm4_fw[i]);
err:
	return ret;
}
int kgsl_ringbuffer_close(struct kgsl_ringbuffer *rb)
{
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(
							rb->device);
	if (rb->buffer_desc.hostptr)
		kgsl_sharedmem_free(&rb->buffer_desc);

	if (rb->memptrs_desc.hostptr)
		kgsl_sharedmem_free(&rb->memptrs_desc);

	if (yamato_device->pfp_fw != NULL)
		kfree(yamato_device->pfp_fw);
	if (yamato_device->pm4_fw != NULL)
		kfree(yamato_device->pm4_fw);
	yamato_device->pfp_fw = NULL;
	yamato_device->pm4_fw = NULL;

	memset(rb, 0, sizeof(struct kgsl_ringbuffer));

	return 0;
}
static int kgsl_ringbuffer_load_pfp_ucode(struct kgsl_device *device)
{
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device);
	const char *fwfile;
	int i, ret = 0;

	if (device->chip_id == KGSL_CHIPID_LEIA_REV470)
		fwfile =  LEIA_PFP_470_FW;
	else
		fwfile = YAMATO_PFP_FW;

	if (yamato_device->pfp_fw == NULL) {
		int len;
		unsigned int *ptr;

		ret = _load_firmware(device, fwfile, (void *) &ptr, &len);
		if (ret)
			goto err;

		/* PFP size shold be dword aligned */
		if (len % sizeof(uint32_t) != 0) {
			KGSL_DRV_ERR(device, "Bad firmware size: %d\n", len);
			ret = -EINVAL;
			goto err;
		}

		yamato_device->pfp_fw_size = len / sizeof(uint32_t);
		yamato_device->pfp_fw = ptr;
	}

	KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n",
		yamato_device->pfp_fw[0]);

	kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_ADDR, 0);
	for (i = 1; i < yamato_device->pfp_fw_size; i++)
		kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_DATA,
				     yamato_device->pfp_fw[i]);
err:
	return ret;
}
void kgsl_ringbuffer_close(struct kgsl_ringbuffer *rb)
{
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(
							rb->device);
	KGSL_CMD_VDBG("enter (rb=%p)\n", rb);

	if (rb->buffer_desc.hostptr)
		kgsl_sharedmem_free(&rb->buffer_desc);

	if (rb->memptrs_desc.hostptr)
		kgsl_sharedmem_free(&rb->memptrs_desc);

	if (yamato_device->pfp_fw != NULL)
		kfree(yamato_device->pfp_fw);
	if (yamato_device->pm4_fw != NULL)
		kfree(yamato_device->pm4_fw);
	yamato_device->pfp_fw = NULL;
	yamato_device->pm4_fw = NULL;

	memset(rb, 0, sizeof(struct kgsl_ringbuffer));

	KGSL_CMD_VDBG("return %d\n", 0);
}
/* functions */
void kgsl_cp_intrcallback(struct kgsl_device *device)
{
	unsigned int status = 0, num_reads = 0, master_status = 0;
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device);
	struct kgsl_ringbuffer *rb = &yamato_device->ringbuffer;

	kgsl_yamato_regread_isr(device, REG_MASTER_INT_SIGNAL, &master_status);
	while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
		(master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
		kgsl_yamato_regread_isr(device, REG_CP_INT_STATUS, &status);
		kgsl_yamato_regread_isr(device, REG_MASTER_INT_SIGNAL,
					&master_status);
		num_reads++;
	}
	if (num_reads > 1)
		KGSL_DRV_WARN(device,
			"Looped %d times to read REG_CP_INT_STATUS\n",
			num_reads);
	if (!status) {
		if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
			/* This indicates that we could not read CP_INT_STAT.
			 * As a precaution just wake up processes so
			 * they can check their timestamps. Since, we
			 * did not ack any interrupts this interrupt will
			 * be generated again */
			KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
			wake_up_interruptible_all(&device->wait_queue);
		} else
			KGSL_DRV_WARN(device, "Spurious interrput detected\n");
		return;
	}

	if (status & CP_INT_CNTL__RB_INT_MASK) {
		/* signal intr completion event */
		unsigned int enableflag = 0;
		kgsl_sharedmem_writel(&rb->device->memstore,
			KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
			enableflag);
		wmb();
		KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
	}

	if (status & CP_INT_CNTL__T0_PACKET_IN_IB_MASK) {
		KGSL_CMD_CRIT(rb->device,
			"ringbuffer TO packet in IB interrupt\n");
		kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0);
	}
	if (status & CP_INT_CNTL__OPCODE_ERROR_MASK) {
		KGSL_CMD_CRIT(rb->device,
			"ringbuffer opcode error interrupt\n");
		kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0);
	}
	if (status & CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK) {
		KGSL_CMD_CRIT(rb->device,
			"ringbuffer protected mode error interrupt\n");
		kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0);
	}
	if (status & CP_INT_CNTL__RESERVED_BIT_ERROR_MASK) {
		KGSL_CMD_CRIT(rb->device,
			"ringbuffer reserved bit error interrupt\n");
		kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0);
	}
	if (status & CP_INT_CNTL__IB_ERROR_MASK) {
		KGSL_CMD_CRIT(rb->device,
			"ringbuffer IB error interrupt\n");
		kgsl_yamato_regwrite_isr(rb->device, REG_CP_INT_CNTL, 0);
	}
	if (status & CP_INT_CNTL__SW_INT_MASK)
		KGSL_CMD_INFO(rb->device, "ringbuffer software interrupt\n");

	if (status & CP_INT_CNTL__IB2_INT_MASK)
		KGSL_CMD_INFO(rb->device, "ringbuffer ib2 interrupt\n");

	if (status & (~GSL_CP_INT_MASK))
		KGSL_CMD_WARN(rb->device,
			"bad bits in REG_CP_INT_STATUS %08x\n", status);

	/* only ack bits we understand */
	status &= GSL_CP_INT_MASK;
	kgsl_yamato_regwrite_isr(device, REG_CP_INT_ACK, status);

	if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
		KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
		wake_up_interruptible_all(&device->wait_queue);
		atomic_notifier_call_chain(&(device->ts_notifier_list),
					   KGSL_DEVICE_YAMATO,
					   NULL);
	}
}
Beispiel #7
0
static int kgsl_ringbuffer_load_pfp_ucode(struct kgsl_device *device)
{
	int status = 0;
	int i;
	const struct firmware *fw = NULL;
	unsigned int *fw_ptr = NULL;
	size_t fw_word_size = 0;
	struct kgsl_yamato_device *yamato_device = KGSL_YAMATO_DEVICE(device);

	if (yamato_device->pfp_fw == NULL) {
		if (device->chip_id == KGSL_CHIPID_LEIA_REV470) {
			status = request_firmware(&fw, LEIA_PFP_470_FW,
				device->dev);
			if (status != 0) {
				KGSL_DRV_ERR("request_firmware for %s \
					 failed with error %d\n",
					LEIA_PFP_470_FW, status);
				return status;
			}
		} else {
			status = request_firmware(&fw, YAMATO_PFP_FW,
				device->dev);
			if (status != 0) {
				KGSL_DRV_ERR("request_firmware for %s \
					 failed with error %d\n",
					YAMATO_PFP_FW, status);
				return status;
			}
		}
		/*this firmware must come in 1 word chunks. */
		if ((fw->size % sizeof(uint32_t)) != 0) {
			KGSL_DRV_ERR("bad firmware size %d.\n", fw->size);
			status = -EINVAL;
			goto error_release_fw;
		}
		fw_ptr = (unsigned int *)fw->data;
		fw_word_size = fw->size/sizeof(uint32_t);
		yamato_device->pfp_fw_size = fw_word_size;

		/* keep a copy of fw to be reloaded  later */
		yamato_device->pfp_fw = (unsigned int *)
						kmalloc(fw->size, GFP_KERNEL);
		if (yamato_device->pfp_fw == NULL) {
			KGSL_DRV_ERR("ERROR: couldn't kmalloc fw size= %d.\n",
								fw->size);
			status = -EINVAL;
			goto error_release_fw;
		}
		memcpy(yamato_device->pfp_fw, fw->data, fw->size);

	} else {
		fw_ptr = yamato_device->pfp_fw;
		fw_word_size = yamato_device->pfp_fw_size;
	}

	KGSL_DRV_INFO("loading pfp ucode version: %d\n", fw_ptr[0]);

	kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_ADDR, 0);
	for (i = 1; i < fw_word_size; i++)
		kgsl_yamato_regwrite(device, REG_CP_PFP_UCODE_DATA, fw_ptr[i]);

error_release_fw:
	if (fw)
		release_firmware(fw);
	return status;
}