/**********************************************************

Prototype		void spi_data_queue_init ( void )

Type		function

Description	init buffer and data variable

***********************************************************/
void spi_data_queue_init(void)
{
	int i;

	void *p_virtual_buff;
	unsigned int buffer_offset[SPI_DATA_QUEUE_TYPE_NB] = {
		FMT_OUT, FMT_IN, RAW_OUT, RAW_IN, RFS_OUT, RFS_IN};

	p_virtual_buff = ipc_spi_get_queue_buff();
	spi_queue = p_virtual_buff+sizeof(struct spi_data_queue)*2;


	spi_queue_info = (struct spi_data_queue_info *) spi_os_vmalloc(
		sizeof(struct spi_data_queue_info)*SPI_DATA_QUEUE_TYPE_NB);
	spi_os_memset(spi_queue_info, 0x00,
		sizeof(struct spi_data_queue_info)*SPI_DATA_QUEUE_TYPE_NB);

	spi_div_buf = (struct spi_data_div_buf *) spi_os_vmalloc(
		sizeof(struct spi_data_div_buf)*SPI_DATA_QUEUE_TYPE_NB);
	spi_os_memset(spi_div_buf, 0x00, sizeof(struct spi_data_div_buf)
		*SPI_DATA_QUEUE_TYPE_NB);
	gspi_data_prepare_packet = (char *) spi_os_vmalloc(
		SPI_DEV_MAX_PACKET_SIZE);
	gspi_data_packet_buf = (char *) spi_os_malloc(SPI_DEV_MAX_PACKET_SIZE);

	for (i = 0 ; i < SPI_DATA_QUEUE_TYPE_NB ; i++) {
		spi_queue_info[i].header = &spi_queue[i];

		switch (i) {
		case SPI_DATA_QUEUE_TYPE_IPC_TX:
		case SPI_DATA_QUEUE_TYPE_IPC_RX:
			spi_queue_info[i].buf_size = SPI_DATA_IPC_QUEUE_SIZE;
			spi_queue_info[i].type = SPI_DATA_MUX_IPC;
			spi_div_buf[i].buffer = (char *)spi_os_vmalloc(
				SPI_DATA_IPC_DIV_BUFFER_SIZE);
			break;
		case SPI_DATA_QUEUE_TYPE_RAW_TX:
		case SPI_DATA_QUEUE_TYPE_RAW_RX:
			spi_queue_info[i].buf_size = SPI_DATA_RAW_QUEUE_SIZE;
			spi_queue_info[i].type = SPI_DATA_MUX_RAW;
			spi_div_buf[i].buffer = (char *)spi_os_vmalloc(
				SPI_DATA_RAW_DIV_BUFFER_SIZE);
			break;
		case SPI_DATA_QUEUE_TYPE_RFS_TX:
		case SPI_DATA_QUEUE_TYPE_RFS_RX:
			spi_queue_info[i].buf_size = SPI_DATA_RFS_QUEUE_SIZE;
			spi_queue_info[i].type = SPI_DATA_MUX_RFS;
			spi_div_buf[i].buffer = (char *)spi_os_vmalloc(
				SPI_DATA_RFS_DIV_BUFFER_SIZE);
			break;
		}

		if (spi_queue_info[i].buffer == 0)
			spi_queue_info[i].buffer =
				(char *)(p_virtual_buff + buffer_offset[i]);
	}
}
Exemplo n.º 2
0
/**********************************************************
Prototype	unsigned int _pack_spi_data (SPI_DATA_TYPE_T type,void * buf, void * data, unsigned int length)
Type			static function
Description	pack data for spi
Param input	type		: type of data type
			buf			: address of buffer to be saved
			data		: address of data to pack
			length	: length of input data
Return value	length of packed data
***********************************************************/
static unsigned int _pack_spi_data(enum SPI_DATA_TYPE_T type, void *buf,
		void *data, unsigned int length)
{
	char *spi_packet	 = NULL;
	unsigned int out_length = 0;

	spi_packet = (char *) buf;

	spi_os_memset((char *)spi_packet, 0x00, (unsigned int)length);
	spi_os_memset((char *)spi_packet, (unsigned char)SPI_DATA_BOF,
		SPI_DATA_BOF_SIZE);
	spi_os_memcpy((char *)spi_packet + SPI_DATA_BOF_SIZE, data, length);
	spi_os_memset((char *)spi_packet + SPI_DATA_BOF_SIZE + length,
		(unsigned char)SPI_DATA_EOF, SPI_DATA_EOF_SIZE);

	out_length = SPI_DATA_BOF_SIZE + length + SPI_DATA_EOF_SIZE;

	return out_length;
}
int spi_data_parsing_rx_packet(void *buf, unsigned int length)
{
	struct spi_data_packet_header *spi_packet_header;
	char *spi_packet;
	unsigned int spi_packet_length;
	unsigned int spi_packet_cur_pos = SPI_DATA_PACKET_HEADER_SIZE;

	unsigned int spi_data_mux;
	unsigned int spi_data_length;
	char *spi_cur_data;

	struct spi_data_queue_info *queue_info;
	struct spi_data_div_buf *tx_div_buf;


	/* check spi packet header */
	if (*(unsigned int *)buf == 0x00000000
		|| *(unsigned int *)buf == 0xFFFFFFFF) {
		/* if spi header is invalid, */
		/* read spi header again with next 4 byte */
		buf += SPI_DATA_PACKET_HEADER_SIZE;
	}

	spi_packet = (char *) buf;

	/* read spi packet header */
	spi_packet_header = (struct spi_data_packet_header *) buf;
	spi_packet_length = SPI_DATA_PACKET_HEADER_SIZE +
		spi_packet_header->current_data_size;


	do {
		/* read spi data mux and set current queue */
		spi_os_memcpy(&spi_data_mux,
			spi_packet + spi_packet_cur_pos, SPI_DATA_MUX_SIZE);

		switch (spi_data_mux & SPI_DATA_MUX_NORMAL_MASK) {
		case SPI_DATA_MUX_IPC:
			queue_info =
			&spi_queue_info[SPI_DATA_QUEUE_TYPE_IPC_RX];
			tx_div_buf =
				&spi_div_buf[SPI_DATA_QUEUE_TYPE_IPC_RX];
			break;

		case SPI_DATA_MUX_RAW:
			queue_info =
				&spi_queue_info[SPI_DATA_QUEUE_TYPE_RAW_RX];
			tx_div_buf =
				&spi_div_buf[SPI_DATA_QUEUE_TYPE_RAW_RX];
			break;

		case SPI_DATA_MUX_RFS:
			queue_info =
				&spi_queue_info[SPI_DATA_QUEUE_TYPE_RFS_RX];
			tx_div_buf =
				&spi_div_buf[SPI_DATA_QUEUE_TYPE_RFS_RX];
			break;

		default:
			pr_err("%s len[%u], pos[%u]\n",
				"[SPI] ERROR : spi_data_parsing_rx_packet : MUX error",
				spi_packet_length, spi_packet_cur_pos);

			spi_os_trace_dump_low("mux error",
				spi_packet + spi_packet_cur_pos, 16);
			return spi_packet_cur_pos - SPI_DATA_PACKET_HEADER_SIZE;
		}

		/* read spi data length */
		spi_os_memcpy(&spi_data_length, spi_packet +
			spi_packet_cur_pos + SPI_DATA_LENGTH_OFFSET,
			SPI_DATA_LENGTH_SIZE);

		if (spi_data_mux & SPI_DATA_MUX_MORE_H
			|| spi_data_mux & SPI_DATA_MUX_MORE_M)
			spi_data_length += SPI_DATA_HEADER_SIZE_FRONT;
		else if (spi_data_mux & SPI_DATA_MUX_MORE_T)
			spi_data_length += SPI_DATA_HEADER_SIZE;
		else
			spi_data_length += SPI_DATA_HEADER_SIZE;

		/* read data and make spi data */
		spi_cur_data = spi_packet + spi_packet_cur_pos;

		/* verify spi data */
		if (_spi_data_verify(spi_cur_data, spi_data_mux) == 0) {
			spi_packet_cur_pos += spi_data_length;
			continue;
		}

		/* inqueue rx buffer */
		if (spi_data_mux & SPI_DATA_MUX_MORE_H
			|| spi_data_mux & SPI_DATA_MUX_MORE_M) {
			/* middle of divided packet. save to rx_div_buf */
			spi_os_memcpy((void *)(tx_div_buf->buffer +
				tx_div_buf->length),
				spi_cur_data, spi_data_length);
			tx_div_buf->length +=
				(spi_data_length - SPI_DATA_HEADER_SIZE_FRONT);
		} else if (spi_data_mux & SPI_DATA_MUX_MORE_T) {
			unsigned int spi_origine_len = 0;

			/* tail of divided packet. save to rx_div_buf */
			spi_os_memcpy((void *)(tx_div_buf->buffer +
				tx_div_buf->length),
				spi_cur_data, spi_data_length);
			tx_div_buf->length += spi_data_length;
			/* update spi data length at spi header */
			spi_origine_len =
				tx_div_buf->length - SPI_DATA_HEADER_SIZE;
			spi_os_memcpy(tx_div_buf->buffer +
				SPI_DATA_LENGTH_OFFSET,
				&(spi_origine_len), SPI_DATA_LENGTH_SIZE);

			/* inqueue from rx_div_buf */
			spi_data_inqueue(queue_info,
				tx_div_buf->buffer, tx_div_buf->length);

			spi_os_memset(tx_div_buf->buffer,
				0, SPI_DATA_DIVIDE_BUFFER_SIZE);
			tx_div_buf->length = 0;
		} else {
			/* normal packet */
			spi_data_inqueue(queue_info,
				spi_cur_data, spi_data_length);
		}

		/* move spi packet current posision */
		spi_packet_cur_pos += spi_data_length;
	} while ((spi_packet_length - 1) > spi_packet_cur_pos);

	return 1;
}
static int _prepare_tx_type_packet(void *buf,
	struct spi_data_queue_info *queue_info,
	struct spi_data_div_buf *spi_data_buf,
	enum SPI_DATA_TYPE_T spi_type)
{
	char *spi_packet;

	struct spi_data_packet_header	*spi_packet_header;
	unsigned int spi_packet_free_length;

	unsigned int spi_packet_count = 0;
	unsigned int cur_dequeue_length;
	unsigned int spi_data_mux;

	struct spi_data_queue *queue;

	queue = queue_info->header;

	spi_packet = (char *)buf;
	spi_packet_header = (struct spi_data_packet_header *)buf;
	spi_packet_free_length = SPI_DATA_PACKET_MAX_PACKET_BODY_SIZE -
		spi_packet_header->current_data_size;

	/* not enough space in spi packet */
	/* spi_packet_header->current_data_size > 2022(2048 - 16) */
	if (spi_packet_header->current_data_size >
		SPI_DATA_PACKET_MAX_PACKET_BODY_SIZE - SPI_DATA_MIN_SIZE) {
		if (spi_data_check_tx_queue() == 1)
			spi_packet_header->more = 1;
		return 0;
	}

	while ((queue->head != queue->tail) || (spi_data_buf->length > 0)) {
		spi_os_memset(gspi_data_prepare_packet,
			0, SPI_DEV_MAX_PACKET_SIZE);
		cur_dequeue_length = 0;

		/* dequeue SPI data */
		if (spi_data_buf->length > 0) {
			if ((*(unsigned int *)spi_data_buf->buffer)
				== SPI_DATA_FF_PADDING_HEADER) {
				/* if data has 0xFF padding header */
				/* send packet directly */
				spi_os_memcpy(spi_packet, spi_data_buf->buffer,
					spi_data_buf->length);
				spi_data_buf->length = 0;
				return 0;
			} else {
				/* read from tx div buf */
				spi_os_memcpy(gspi_data_prepare_packet,
					spi_data_buf->buffer,
					spi_data_buf->length);
				cur_dequeue_length = spi_data_buf->length;
				spi_data_buf->length = 0;
			}
		} else {
			/* read from tx queue */
			cur_dequeue_length = spi_data_dequeue(queue_info,
				gspi_data_prepare_packet);
		}

		if (cur_dequeue_length < 0)
			continue;

		if (spi_packet_free_length < cur_dequeue_length) {
			spi_os_memcpy(spi_data_buf->buffer,
				gspi_data_prepare_packet, cur_dequeue_length);
			spi_data_buf->length = cur_dequeue_length;
			spi_packet_header->more = 1;
			return 0;
		}

		/* check mux value */
		spi_os_memcpy(&spi_data_mux, gspi_data_prepare_packet,
			SPI_DATA_MUX_SIZE);
		if (spi_data_mux == 0)
			spi_os_memcpy(gspi_data_prepare_packet,
				&spi_type, SPI_DATA_MUX_SIZE);

		spi_os_memcpy(spi_packet + SPI_DATA_PACKET_HEADER_SIZE +
			spi_packet_header->current_data_size,
			gspi_data_prepare_packet, cur_dequeue_length);

		/* update header */
		spi_packet_header->current_data_size += cur_dequeue_length;
		spi_packet_free_length -= cur_dequeue_length;

		/* increase spi packet count */
		spi_packet_count++;

		/* check spi packet size */
		if (spi_packet_free_length < SPI_DATA_MIN_SIZE) {
			if (spi_data_check_tx_queue() == 1)
				spi_packet_header->more = 1;
			return 0;
		}

		/* check spi maximum count per packet */
		if (spi_packet_count >= SPI_DATA_MAX_COUNT_PER_PACKET) {

			pr_err("%s %s\n",
				"[SPI] ERROR : spi _prepare_tx_type_packet :",
				"spi_packet_count is full");

			return 0;
		}
	}

	return spi_packet_header->current_data_size +
		SPI_DATA_PACKET_HEADER_SIZE;
}