Merge "msm_shared: bam: Add support for command descriptors."
diff --git a/platform/msm_shared/bam.c b/platform/msm_shared/bam.c
index 5eef03a..8501fd2 100644
--- a/platform/msm_shared/bam.c
+++ b/platform/msm_shared/bam.c
@@ -33,6 +33,7 @@
 #include <platform/interrupts.h>
 #include <platform/iomap.h>
 #include <platform/irqs.h>
+#include <pow2.h>
 
 #define HLOS_EE_INDEX          0
 
@@ -206,6 +207,11 @@
 	/* Check if fifo start is 8-byte alligned */
 	ASSERT(!((uint32_t)bam->pipe[pipe_num].fifo.head & 0x7));
 
+	/* Check if fifo size is a power of 2.
+	 * The circular fifo logic in lk expects this.
+	 */
+	ASSERT(ispow2(bam->pipe[pipe_num].fifo.size));
+
 	bam->pipe[pipe_num].fifo.current = bam->pipe[pipe_num].fifo.head;
 
 	/* Set the descriptor buffer size. Must be a multiple of 8 */
@@ -274,6 +280,7 @@
 	/* Update the fifo peer offset */
 	val = (num_desc - 1) * BAM_DESC_SIZE;
 	val += bam->pipe[pipe_num].fifo.offset;
+	val &= (bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE - 1);
 
 	writel(val, BAM_P_EVNT_REGn(bam->pipe[pipe_num].pipe_num, bam->base));
 }
@@ -285,7 +292,7 @@
  * Note : S/W maintains the circular properties of the FIFO and updates
  *        the offsets accordingly.
  */
-unsigned bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num)
+void bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num)
 {
 	uint32_t offset;
 
@@ -294,18 +301,11 @@
 
 	dprintf(INFO, "Offset value is %d \n", offset);
 
-	if (offset == (uint16_t)(bam->pipe[pipe_num].fifo.size - 1) * BAM_DESC_SIZE )
-	{
-		bam->pipe[pipe_num].fifo.current = bam->pipe[pipe_num].fifo.head;
-		offset = 0;
-	}
-	else
+	/* Save the next offset to be written to. */
 		bam->pipe[pipe_num].fifo.current = (struct bam_desc*)
 											((uint32_t)bam->pipe[pipe_num].fifo.head + offset);
 
 	bam->pipe[pipe_num].fifo.offset = offset + BAM_DESC_SIZE ;
-
-	return offset;
 }
 
 /* Function to get the next desc address.
@@ -318,7 +318,6 @@
 	uint16_t offset;
 
 	offset = desc - fifo->head;
-	offset /= BAM_DESC_SIZE;
 
 	if (offset == (fifo->size - 1))
 		return fifo->head;
@@ -330,18 +329,21 @@
  * bam : BAM instance to be used.
  * data_ptr : Memory address for data transfer.
  * data_len : Length of the data_ptr.
+ * flags : Flags to be set on the last desc added.
  *
+ * Note: This function also notifies the BAM about the added descriptors.
  */
 int bam_add_desc(struct bam_instance *bam,
                  unsigned int pipe_num,
                  unsigned char *data_ptr,
-                 unsigned int data_len)
+                 unsigned int data_len,
+                 unsigned flags)
 {
-	struct bam_desc *desc;
-	struct bam_desc *next = bam->pipe[pipe_num].fifo.current;
 	int bam_ret = BAM_RESULT_SUCCESS;
 	unsigned int len = data_len;
+	unsigned int desc_len;
 	unsigned int n = 0;
+	unsigned int desc_flags;
 
 	dprintf(INFO, "Data length for BAM transfer is %u\n", data_len);
 
@@ -352,15 +354,6 @@
 		goto bam_add_desc_error;
 	}
 
-	/* Check if the FIFO is allocated for the pipe */
-	if (!bam->pipe[pipe_num].initialized)
-	{
-		dprintf(CRITICAL, "Please allocate the FIFO for the BAM pipe %d\n",
-				bam->pipe[pipe_num].pipe_num);
-		bam_ret = BAM_RESULT_FAILURE;
-		goto bam_add_desc_error;
-	}
-
 	/* Check if we have enough space in FIFO */
 	if (len > (unsigned)bam->pipe[pipe_num].fifo.size * BAM_MAX_DESC_DATA_LEN)
 	{
@@ -371,40 +364,32 @@
 
 	while (len)
 	{
-		desc = next;
+
 		/* There are only 16 bits to write data length.
 		 * If more bits are needed, create more
 		 * descriptors.
 		 */
 		if (len > BAM_MAX_DESC_DATA_LEN)
 		{
-			desc->size = BAM_MAX_DESC_DATA_LEN;
+			desc_len = BAM_MAX_DESC_DATA_LEN;
 			len -= BAM_MAX_DESC_DATA_LEN;
+			desc_flags = 0;
 		}
 		else
 		{
-			desc->size = len;
+			desc_len = len;
 			len = 0;
+			/* Set correct flags on the last desc. */
+			desc_flags = flags;
 		}
 
-		/* Write descriptors */
-		desc->addr = (uint32_t)data_ptr;
-		desc->flags = 0;
-		desc->reserved = 0;
+		/* Write descriptor */
+		bam_add_one_desc(bam, pipe_num, data_ptr, desc_len, desc_flags);
 
-		next = fifo_getnext(&bam->pipe[pipe_num].fifo, desc);
 		data_ptr += BAM_MAX_DESC_DATA_LEN;
 		n++;
-
-		dprintf(INFO,"Desc written: len = %u addr = %u\n", desc->size, desc->addr);
 	}
 
-	if (bam->pipe[pipe_num].trans_type == BAM2SYS)
-		/* Set interrupt bit for the last descriptor. */
-		desc->flags |= BAM_DESC_INT_FLAG;
-	else
-		/* Set transaction end bit for the last descriptor. */
-		desc->flags |= BAM_DESC_EOT_FLAG;
 
 	/* Create a read/write event to notify the periperal of the added desc. */
 	bam_sys_gen_event(bam, pipe_num, n);
@@ -414,6 +399,76 @@
 	return bam_ret;
 }
 
+/* Function to add a BAM descriptor for a given fifo.
+ * bam : BAM instance to be used.
+ * data_ptr : Memory address for data transfer.
+ * data_len : Length of the data_ptr.
+ * flags : Flags to be set on the desc added.
+ *
+ * Note: This function does not notify the BAM about the added descriptor.
+ */
+int bam_add_one_desc(struct bam_instance *bam,
+                     unsigned int pipe_num,
+                     unsigned char* data_ptr,
+                     uint32_t len,
+                     uint8_t flags)
+{
+
+	struct bam_desc *desc = bam->pipe[pipe_num].fifo.current;
+	int bam_ret = BAM_RESULT_SUCCESS;
+
+	if (data_ptr == NULL || len == 0)
+	{
+		dprintf(CRITICAL, "Wrong params for BAM transfer \n");
+		bam_ret = BAM_RESULT_FAILURE;
+		goto bam_add_one_desc_error;
+	}
+
+	/* Check if the FIFO is allocated for the pipe */
+	if (!bam->pipe[pipe_num].initialized)
+	{
+		dprintf(CRITICAL, "Please allocate the FIFO for the BAM pipe %d\n",
+				bam->pipe[pipe_num].pipe_num);
+		bam_ret = BAM_RESULT_FAILURE;
+		goto bam_add_one_desc_error;
+	}
+
+	if ((flags & BAM_DESC_LOCK_FLAG) && (flags & BAM_DESC_UNLOCK_FLAG))
+	{
+		dprintf(CRITICAL, "Can't lock and unlock in the same desc\n");
+		bam_ret = BAM_RESULT_FAILURE;
+		goto bam_add_one_desc_error;
+	}
+
+	/* Setting EOT flag on a CMD desc is not valid */
+	if ((flags & BAM_DESC_EOT_FLAG) && (flags & BAM_DESC_CMD_FLAG))
+	{
+		dprintf(CRITICAL, "EOT flag set on the CMD desc\n");
+		bam_ret = BAM_RESULT_FAILURE;
+		goto bam_add_one_desc_error;
+	}
+
+	/* Check for the length of the desc. */
+	if (len > BAM_MAX_DESC_DATA_LEN)
+	{
+		dprintf(CRITICAL, "len of the desc exceeds max length"
+				" %d > %d\n", len, BAM_MAX_DESC_DATA_LEN);
+		bam_ret = BAM_RESULT_FAILURE;
+		goto bam_add_one_desc_error;
+	}
+
+	desc->flags = flags;
+	desc->addr = (uint32_t)data_ptr;
+	desc->size = (uint16_t)len;
+	desc->reserved = 0;
+
+	/* Update the FIFO to point to the head */
+	bam->pipe[pipe_num].fifo.current = fifo_getnext(&bam->pipe[pipe_num].fifo, desc);
+
+bam_add_one_desc_error:
+	return bam_ret;
+}
+
 struct cmd_element* bam_add_cmd_element(struct cmd_element *ptr,
                                         uint32_t reg_addr,
                                         uint32_t value,
@@ -422,7 +477,7 @@
 	/* Write cmd type.
 	 * Also, write the register address.
 	 */
-	 ptr->addr_n_cmd = (reg_addr << 8) | cmd_type;
+	 ptr->addr_n_cmd = (reg_addr & ~(0xFF000000)) | (cmd_type << 24);
 
 	/* Do not mask any of the addr bits by default */
 	ptr->reg_mask = 0xFFFFFFFF;
@@ -433,62 +488,3 @@
 	/* Return the address to add the next element to */
 	return ptr + 1;
 }
-
-/* Command descriptors are added one by one.
- * This is because each descriptor might have different
- * flag settings.
- */
-int bam_add_cmd_desc(struct bam_instance *bam,
-                     unsigned int pipe_num,
-                     unsigned char* data_ptr,
-                     uint32_t len,
-                     uint8_t flags)
-{
-
-	struct bam_desc *desc = bam->pipe[pipe_num].fifo.current;
-	struct bam_desc *next = bam->pipe[pipe_num].fifo.current;
-	int bam_ret = BAM_RESULT_SUCCESS;
-
-	if (data_ptr == NULL || len == 0)
-	{
-		dprintf(CRITICAL, "Wrong params for BAM transfer \n");
-		bam_ret = BAM_RESULT_FAILURE;
-		goto bam_add_cmd_desc_error;
-	}
-
-	/* Check if the FIFO is allocated for the pipe */
-	if (!bam->pipe[pipe_num].initialized)
-	{
-		dprintf(CRITICAL, "Please allocate the FIFO for the BAM pipe %d\n",
-				bam->pipe[pipe_num].pipe_num);
-		bam_ret = BAM_RESULT_FAILURE;
-		goto bam_add_cmd_desc_error;
-	}
-
-	if ((flags & BAM_DESC_LOCK_FLAG) && (flags & BAM_DESC_UNLOCK_FLAG))
-	{
-		dprintf(CRITICAL, "Can't lock and unlock in the same desc\n");
-		bam_ret = BAM_RESULT_FAILURE;
-		goto bam_add_cmd_desc_error;
-	}
-
-	/* Setting EOT flag on a CMD desc is not valid */
-	if (flags & BAM_DESC_EOT_FLAG)
-	{
-		dprintf(CRITICAL, "EOT flag set on the CMD desc\n");
-		bam_ret = BAM_RESULT_FAILURE;
-		goto bam_add_cmd_desc_error;
-	}
-
-	/* Set the passed in flags along with the CMD flag. */
-	desc->flags = flags | BAM_DESC_CMD_FLAG;
-	desc->addr = data_ptr;
-	desc->size = len;
-	desc->reserved = 0;
-
-	/* Update the FIFO to point to the head */
-	bam->pipe[pipe_num].fifo.current = fifo_getnext(&bam->pipe[pipe_num].fifo, desc);
-
-bam_add_cmd_desc_error:
-	return bam_ret;
-}
diff --git a/platform/msm_shared/include/bam.h b/platform/msm_shared/include/bam.h
index d5b587e..3338bef 100644
--- a/platform/msm_shared/include/bam.h
+++ b/platform/msm_shared/include/bam.h
@@ -229,6 +229,8 @@
 void bam_init(struct bam_instance *bam);
 void bam_sys_pipe_init(struct bam_instance *bam,
                        uint8_t pipe_num);
+int bam_pipe_fifo_init(struct bam_instance *bam,
+                       uint8_t pipe_num);
 struct cmd_element* bam_add_cmd_element(struct cmd_element *ptr,
                                         uint32_t addr,
                                         uint32_t data,
@@ -236,8 +238,9 @@
 int bam_add_desc(struct bam_instance *bam,
                  unsigned int pipe_num,
                  unsigned char *data_ptr,
-                 unsigned int data_len);
-int bam_add_cmd_desc(struct bam_instance *bam,
+                 unsigned int data_len,
+                 unsigned flags);
+int bam_add_one_desc(struct bam_instance *bam,
                      unsigned int pipe_num,
                      unsigned char*,
                      uint32_t len,
@@ -248,6 +251,6 @@
 int bam_wait_for_interrupt(struct bam_instance *bam,
                            uint8_t pipe_num,
                            enum p_int_type interrupt);
-unsigned bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num);
+void bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num);
 
 #endif