Pārlūkot izejas kodu

gsi: Add HAL Layer for GSI 3.0 version

Update GSI HAL to support GSI 3.0

Change-Id: I7b3a687ddbf51f71011267d6bb9b559eb4a8fbd1
Acked-by: Nadav Levintov <[email protected]>
Signed-off-by: Sivan Reinstein <[email protected]>
Signed-off-by: Ilia Lin <[email protected]>
Sivan Reinstein 4 gadi atpakaļ
vecāks
revīzija
2143cb5dd1

+ 477 - 136
drivers/platform/msm/gsi/gsi.c

@@ -85,6 +85,20 @@ static void __gsi_config_ch_irq(int ee, uint32_t mask, uint32_t val)
 		(curr & ~mask) | (val & mask));
 }
 
+static void __gsi_config_all_ch_irq(int ee, uint32_t mask, uint32_t val)
+{
+	uint32_t curr, k, max_k;
+
+	max_k = gsihal_get_bit_map_array_size();
+	for (k = 0; k < max_k; k++)
+	{
+		curr = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_k, ee, k);
+
+		gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_k, ee, k,
+			(curr & ~mask) | (val & mask));
+	}
+}
+
 static void __gsi_config_evt_irq(int ee, uint32_t mask, uint32_t val)
 {
 	uint32_t curr;
@@ -95,6 +109,20 @@ static void __gsi_config_evt_irq(int ee, uint32_t mask, uint32_t val)
 		(curr & ~mask) | (val & mask));
 }
 
+static void __gsi_config_all_evt_irq(int ee, uint32_t mask, uint32_t val)
+{
+	uint32_t curr, k, max_k;
+
+	max_k = gsihal_get_bit_map_array_size();
+	for (k = 0; k < max_k; k++)
+	{
+		curr = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_k, ee, k);
+
+		gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_k, ee, k,
+			(curr & ~mask) | (val & mask));
+	}
+}
+
 static void __gsi_config_ieob_irq(int ee, uint32_t mask, uint32_t val)
 {
 	uint32_t curr;
@@ -108,6 +136,34 @@ static void __gsi_config_ieob_irq(int ee, uint32_t mask, uint32_t val)
 		curr, ((curr & ~mask) | (val & mask)));
 }
 
+static void __gsi_config_all_ieob_irq(int ee, uint32_t mask, uint32_t val)
+{
+	uint32_t curr, k, max_k;
+
+	max_k = gsihal_get_bit_map_array_size();
+	for (k = 0; k < max_k; k++)
+	{
+		curr = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k, ee, k);
+
+		gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k, ee, k,
+			(curr & ~mask) | (val & mask));
+		GSIDBG("current IEO_IRQ_MSK: 0x%x, change to: 0x%x\n",
+			curr, ((curr & ~mask) | (val & mask)));
+	}
+}
+
+static void __gsi_config_ieob_irq_k(int ee, uint32_t k, uint32_t mask, uint32_t val)
+{
+	uint32_t curr;
+
+	curr = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k, ee, k);
+
+		gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k, ee, k,
+			(curr & ~mask) | (val & mask));
+		GSIDBG("current IEO_IRQ_MSK: 0x%x, change to: 0x%x\n",
+			curr, ((curr & ~mask) | (val & mask)));
+}
+
 static void __gsi_config_glob_irq(int ee, uint32_t mask, uint32_t val)
 {
 	uint32_t curr;
@@ -136,6 +192,7 @@ static void gsi_channel_state_change_wait(unsigned long chan_hdl,
 	int gsi_pending_intr;
 	int res;
 	struct gsihal_reg_ctx_type_irq type;
+	struct gsihal_reg_ch_k_cntxt_0 ch_k_cntxt_0;
 	int ee = gsi_ctx->per.ee;
 	enum gsi_chan_state curr_state = GSI_CHAN_STATE_NOT_ALLOCATED;
 	int stop_in_proc_retry = 0;
@@ -159,20 +216,26 @@ static void gsi_channel_state_change_wait(unsigned long chan_hdl,
 			return;
 
 		gsihal_read_reg_n_fields(GSI_EE_n_CNTXT_TYPE_IRQ, ee, &type);
-
-		gsi_pending_intr = gsihal_read_reg_n(
-			GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ, ee);
+		if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+			gsi_pending_intr = gsihal_read_reg_nk(
+				GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_k,
+				ee, gsihal_get_ch_reg_idx(chan_hdl));
+		} else {
+			gsi_pending_intr = gsihal_read_reg_n(
+				GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ, ee);
+		}
 
 		/* Update the channel state only if interrupt was raised
 		 * on particular channel and also checking global interrupt
 		 * is raised for channel control.
 		 */
-		if ((type.ch_ctrl) && ((gsi_pending_intr >> chan_hdl) & 1)) {
-			struct gsihal_reg_ch_k_cntxt_0 ch_k_cntxt_0;
+		if ((type.ch_ctrl) &&
+			(gsi_pending_intr & gsihal_get_ch_reg_mask(chan_hdl))) {
 			/*
 			 * Check channel state here in case the channel is
 			 * already started but interrupt is not yet received.
 			 */
+
 			gsihal_read_reg_nk_fields(GSI_EE_n_GSI_CH_k_CNTXT_0,
 				ee, chan_hdl, &ch_k_cntxt_0);
 			curr_state = ch_k_cntxt_0.chstate;
@@ -203,9 +266,16 @@ static void gsi_channel_state_change_wait(unsigned long chan_hdl,
 		 * clear the pending interrupt, if channel already stopped.
 		 */
 		if (stop_retry == GSI_STOP_CMD_POLL_CNT) {
-			gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR,
+			if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+				gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_k,
+					ee, gsihal_get_ch_reg_idx(chan_hdl),
+					gsi_pending_intr);
+			}
+			else {
+				gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR,
 				ee,
 				gsi_pending_intr);
+			}
 			ctx->state = curr_state;
 			return;
 		}
@@ -232,28 +302,63 @@ static void gsi_channel_state_change_wait(unsigned long chan_hdl,
 static void gsi_handle_ch_ctrl(int ee)
 {
 	uint32_t ch;
-	int i;
-	struct gsi_chan_ctx *ctx;
+	int i, k, max_k;
+	uint32_t ch_hdl;
 	struct gsihal_reg_ch_k_cntxt_0 ch_k_cntxt_0;
+	struct gsi_chan_ctx *ctx;
 
-	ch = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ, ee);
-	gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR, ee, ch);
-
-	GSIDBG("ch %x\n", ch);
-	for (i = 0; i < GSI_STTS_REG_BITS; i++) {
-		if ((1 << i) & ch) {
-			if (i >= gsi_ctx->max_ch || i >= GSI_CHAN_MAX) {
-				GSIERR("invalid channel %d\n", i);
-				break;
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		max_k = gsihal_get_bit_map_array_size();
+		for (k = 0; k < max_k; k++) {
+			ch = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_k, ee, k);
+			gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_k, ee, k, ch);
+
+			GSIDBG("ch %x\n", ch);
+			for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+				if ((1 << i) & ch) {
+					ch_hdl = i + (GSI_STTS_REG_BITS * k);
+					if (ch_hdl >= gsi_ctx->max_ch ||
+						ch_hdl >= GSI_CHAN_MAX) {
+						GSIERR("invalid channel %d\n",
+							ch_hdl);
+						break;
+					}
+
+					ctx = &gsi_ctx->chan[ch_hdl];
+					gsihal_read_reg_nk_fields(GSI_EE_n_GSI_CH_k_CNTXT_0,
+						ee, ch_hdl, &ch_k_cntxt_0);
+					ctx->state = ch_k_cntxt_0.chstate;
+
+					GSIDBG("ch %u state updated to %u\n",
+						ch_hdl, ctx->state);
+					complete(&ctx->compl);
+					gsi_ctx->ch_dbg[ch_hdl].cmd_completed++;
+				}
 			}
+		}
+	} else {
+		ch = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ, ee);
+		gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR, ee, ch);
+
+		GSIDBG("ch %x\n", ch);
+		for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+			if ((1 << i) & ch) {
+				if (i >= gsi_ctx->max_ch ||
+					i >= GSI_CHAN_MAX) {
+					GSIERR("invalid channel %d\n", i);
+					break;
+				}
 
-			ctx = &gsi_ctx->chan[i];
-			gsihal_read_reg_nk_fields(GSI_EE_n_GSI_CH_k_CNTXT_0,
-				ee, i, &ch_k_cntxt_0);
-			ctx->state = ch_k_cntxt_0.chstate;
-			GSIDBG("ch %u state updated to %u\n", i, ctx->state);
-			complete(&ctx->compl);
-			gsi_ctx->ch_dbg[i].cmd_completed++;
+				ctx = &gsi_ctx->chan[i];
+				gsihal_read_reg_nk_fields(GSI_EE_n_GSI_CH_k_CNTXT_0,
+					ee, i, &ch_k_cntxt_0);
+				ctx->state = ch_k_cntxt_0.chstate;
+
+				GSIDBG("ch %u state updated to %u\n", i,
+					ctx->state);
+				complete(&ctx->compl);
+				gsi_ctx->ch_dbg[i].cmd_completed++;
+			}
 		}
 	}
 }
@@ -261,26 +366,61 @@ static void gsi_handle_ch_ctrl(int ee)
 static void gsi_handle_ev_ctrl(int ee)
 {
 	uint32_t ch;
-	int i;
+	int i, k;
+	uint32_t evt_hdl, max_k;
 	struct gsi_evt_ctx *ctx;
 	struct gsihal_reg_ev_ch_k_cntxt_0 ev_ch_k_cntxt_0;
 
-	ch = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ, ee);
-	gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR, ee, ch);
-	GSIDBG("ev %x\n", ch);
-	for (i = 0; i < GSI_STTS_REG_BITS; i++) {
-		if ((1 << i) & ch) {
-			if (i >= gsi_ctx->max_ev || i >= GSI_EVT_RING_MAX) {
-				GSIERR("invalid event %d\n", i);
-				break;
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		max_k = gsihal_get_bit_map_array_size();
+		for (k = 0; k < max_k; k++) {
+			ch = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_k, ee, k);
+			gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_k, ee, k, ch);
+
+			GSIDBG("ev %x\n", ch);
+			for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+				if ((1 << i) & ch) {
+					evt_hdl = i + (GSI_STTS_REG_BITS * k);
+					if (evt_hdl >= gsi_ctx->max_ev ||
+						evt_hdl >= GSI_EVT_RING_MAX) {
+						GSIERR("invalid event %d\n",
+							evt_hdl);
+						break;
+					}
+
+					ctx = &gsi_ctx->evtr[evt_hdl];
+					gsihal_read_reg_nk_fields(GSI_EE_n_EV_CH_k_CNTXT_0,
+						ee, evt_hdl, &ev_ch_k_cntxt_0);
+					ctx->state = ev_ch_k_cntxt_0.chstate;
+
+					GSIDBG("evt %u state updated to %u\n",
+						evt_hdl, ctx->state);
+					complete(&ctx->compl);
+				}
 			}
+		}
+	} else {
+		ch = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ, ee);
+		gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR, ee, ch);
+
+		GSIDBG("ev %x\n", ch);
+		for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+			if ((1 << i) & ch) {
+				if (i >= gsi_ctx->max_ev ||
+					i >= GSI_EVT_RING_MAX) {
+					GSIERR("invalid event %d\n", i);
+					break;
+				}
+
+				ctx = &gsi_ctx->evtr[i];
+				gsihal_read_reg_nk_fields(GSI_EE_n_EV_CH_k_CNTXT_0,
+					ee, i, &ev_ch_k_cntxt_0);
+				ctx->state = ev_ch_k_cntxt_0.chstate;
 
-			ctx = &gsi_ctx->evtr[i];
-			gsihal_read_reg_nk_fields(GSI_EE_n_EV_CH_k_CNTXT_0,
-				ee, i, &ev_ch_k_cntxt_0);
-			ctx->state = ev_ch_k_cntxt_0.chstate;
-			GSIDBG("evt %u state updated to %u\n", i, ctx->state);
-			complete(&ctx->compl);
+				GSIDBG("evt %u state updated to %u\n", i,
+					ctx->state);
+				complete(&ctx->compl);
+			}
 		}
 	}
 }
@@ -630,8 +770,8 @@ static void gsi_ring_chan_doorbell(struct gsi_chan_ctx *ctx)
 
 static void gsi_handle_ieob(int ee)
 {
-	uint32_t ch;
-	int i;
+	uint32_t ch, evt_hdl;
+	int i, k, max_k;
 	uint64_t rp;
 	struct gsi_evt_ctx *ctx;
 	struct gsi_chan_xfer_notify notify;
@@ -640,84 +780,185 @@ static void gsi_handle_ieob(int ee)
 	uint32_t msk;
 	bool empty;
 
-	ch = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ, ee);
-	msk = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK, ee);
-	gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR, ee, ch & msk);
-
-	for (i = 0; i < GSI_STTS_REG_BITS; i++) {
-		if ((1 << i) & ch & msk) {
-			if (i >= gsi_ctx->max_ev || i >= GSI_EVT_RING_MAX) {
-				GSIERR("invalid event %d\n", i);
-				break;
-			}
-			ctx = &gsi_ctx->evtr[i];
-
-			/*
-			 * Don't handle MSI interrupts, only handle IEOB
-			 * IRQs
-			 */
-			if (ctx->props.intr == GSI_INTR_MSI)
-				continue;
-
-			if (ctx->props.intf != GSI_EVT_CHTYPE_GPI_EV) {
-				GSIERR("Unexpected irq intf %d\n",
-					ctx->props.intf);
-				GSI_ASSERT();
-			}
-			spin_lock_irqsave(&ctx->ring.slock, flags);
-check_again:
-			cntr = 0;
-			empty = true;
-			rp = ctx->props.gsi_read_event_ring_rp(&ctx->props,
-							       ctx->id, ee);
-			rp |= ctx->ring.rp & GSI_MSB_MASK;
-
-			ctx->ring.rp = rp;
-			while (ctx->ring.rp_local != rp) {
-				++cntr;
-				if (ctx->props.exclusive &&
-					atomic_read(&ctx->chan->poll_mode)) {
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		max_k = gsihal_get_bit_map_array_size();
+		for (k = 0; k < max_k; k++) {
+			ch = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_k, ee, k);
+			msk = gsihal_read_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k, ee, k);
+			gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k, ee, k, ch & msk);
+
+			for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+				if ((1 << i) & ch & msk) {
+					evt_hdl = i + (GSI_STTS_REG_BITS * k);
+					if (evt_hdl >= gsi_ctx->max_ev ||
+					    evt_hdl >= GSI_EVT_RING_MAX) {
+						GSIERR("invalid event %d\n",
+						       evt_hdl);
+						break;
+					}
+					ctx = &gsi_ctx->evtr[evt_hdl];
+
+					/*
+					 * Don't handle MSI interrupts, only handle IEOB
+					 * IRQs
+					 */
+					if (ctx->props.intr == GSI_INTR_MSI)
+						continue;
+
+					if (ctx->props.intf !=
+					    GSI_EVT_CHTYPE_GPI_EV) {
+						GSIERR("Unexpected irq intf %d\n",
+						       ctx->props.intf);
+						GSI_ASSERT();
+					}
+					spin_lock_irqsave(&ctx->ring.slock,
+							  flags);
+check_again_v3_0:
 					cntr = 0;
+					empty = true;
+					rp = ctx->props.gsi_read_event_ring_rp(
+						&ctx->props, ctx->id, ee);
+					rp |= ctx->ring.rp & GSI_MSB_MASK;
+
+					ctx->ring.rp = rp;
+					while (ctx->ring.rp_local != rp) {
+						++cntr;
+						if (ctx->props.exclusive &&
+						    atomic_read(
+							    &ctx->chan->poll_mode)) {
+							cntr = 0;
+							break;
+						}
+						gsi_process_evt_re(ctx, &notify,
+								   true);
+						empty = false;
+					}
+					if (!empty)
+						gsi_ring_evt_doorbell(ctx);
+					if (cntr != 0)
+						goto check_again_v3_0;
+					spin_unlock_irqrestore(&ctx->ring.slock,
+							       flags);
+				}
+			}
+		}
+	} else {
+		ch = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ, ee);
+		msk = gsihal_read_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK, ee);
+		gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR, ee, ch & msk);
+
+		for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+			if ((1 << i) & ch & msk) {
+				if (i >= gsi_ctx->max_ev ||
+				    i >= GSI_EVT_RING_MAX) {
+					GSIERR("invalid event %d\n", i);
 					break;
 				}
-				gsi_process_evt_re(ctx, &notify, true);
-				empty = false;
+				ctx = &gsi_ctx->evtr[i];
+
+				/*
+				 * Don't handle MSI interrupts, only handle IEOB
+				 * IRQs
+				 */
+				if (ctx->props.intr == GSI_INTR_MSI)
+					continue;
+
+				if (ctx->props.intf != GSI_EVT_CHTYPE_GPI_EV) {
+					GSIERR("Unexpected irq intf %d\n",
+					       ctx->props.intf);
+					GSI_ASSERT();
+				}
+				spin_lock_irqsave(&ctx->ring.slock, flags);
+			check_again:
+				cntr = 0;
+				empty = true;
+				rp = ctx->props.gsi_read_event_ring_rp(
+					&ctx->props, ctx->id, ee);
+				rp |= ctx->ring.rp & GSI_MSB_MASK;
+
+				ctx->ring.rp = rp;
+				while (ctx->ring.rp_local != rp) {
+					++cntr;
+					if (ctx->props.exclusive &&
+					    atomic_read(
+						    &ctx->chan->poll_mode)) {
+						cntr = 0;
+						break;
+					}
+					gsi_process_evt_re(ctx, &notify, true);
+					empty = false;
+				}
+				if (!empty)
+					gsi_ring_evt_doorbell(ctx);
+				if (cntr != 0)
+					goto check_again;
+				spin_unlock_irqrestore(&ctx->ring.slock, flags);
 			}
-			if (!empty)
-				gsi_ring_evt_doorbell(ctx);
-			if (cntr != 0)
-				goto check_again;
-			spin_unlock_irqrestore(&ctx->ring.slock, flags);
 		}
 	}
 }
 
 static void gsi_handle_inter_ee_ch_ctrl(int ee)
 {
-	uint32_t ch;
-	int i;
+	uint32_t ch, ch_hdl;
+	int i, k, max_k;
+
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		max_k = gsihal_get_bit_map_array_size();
+		for (k = 0; k < max_k; k++) {
+			ch = gsihal_read_reg_nk(GSI_INTER_EE_n_SRC_GSI_CH_IRQ_k, ee, k);
+			gsihal_write_reg_nk(GSI_INTER_EE_n_SRC_GSI_CH_IRQ_k, ee, k, ch);
+
+			for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+				if ((1 << i) & ch) {
+					ch_hdl = i + (GSI_STTS_REG_BITS * k);
+					/* not currently expected */
+					GSIERR("ch %u was inter-EE changed\n", ch_hdl);
+				}
+			}
+		}
+	} else {
+		ch = gsihal_read_reg_n(GSI_INTER_EE_n_SRC_GSI_CH_IRQ, ee);
+		gsihal_write_reg_n(GSI_INTER_EE_n_SRC_GSI_CH_IRQ, ee, ch);
 
-	ch = gsihal_read_reg_n(GSI_INTER_EE_n_SRC_GSI_CH_IRQ, ee);
-	gsihal_write_reg_n(GSI_INTER_EE_n_SRC_GSI_CH_IRQ, ee, ch);
-	for (i = 0; i < GSI_STTS_REG_BITS; i++) {
-		if ((1 << i) & ch) {
-			/* not currently expected */
-			GSIERR("ch %u was inter-EE changed\n", i);
+		for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+			if ((1 << i) & ch) {
+				/* not currently expected */
+				GSIERR("ch %u was inter-EE changed\n", i);
+			}
 		}
 	}
 }
 
 static void gsi_handle_inter_ee_ev_ctrl(int ee)
 {
-	uint32_t ch;
-	int i;
+	uint32_t ch, evt_hdl;
+	int i, k, max_k;
+
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		max_k = gsihal_get_bit_map_array_size();
+		for (k = 0; k < max_k; k++) {
+			ch = gsihal_read_reg_nk(GSI_INTER_EE_n_SRC_EV_CH_IRQ_k, ee, k);
+			gsihal_write_reg_nk(GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_k, ee, k, ch);
+
+			for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+				if ((1 << i) & ch) {
+					evt_hdl = i + (GSI_STTS_REG_BITS * k);
+					/* not currently expected */
+					GSIERR("evt %u was inter-EE changed\n",
+					       evt_hdl);
+				}
+			}
+		}
+	} else {
+		ch = gsihal_read_reg_n(GSI_INTER_EE_n_SRC_EV_CH_IRQ, ee);
+		gsihal_write_reg_n(GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR, ee, ch);
 
-	ch = gsihal_read_reg_n(GSI_INTER_EE_n_SRC_EV_CH_IRQ, ee);
-	gsihal_write_reg_n(GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR, ee, ch);
-	for (i = 0; i < GSI_STTS_REG_BITS; i++) {
-		if ((1 << i) & ch) {
-			/* not currently expected */
-			GSIERR("evt %u was inter-EE changed\n", i);
+		for (i = 0; i < GSI_STTS_REG_BITS; i++) {
+			if ((1 << i) & ch) {
+				/* not currently expected */
+				GSIERR("evt %u was inter-EE changed\n", i);
+			}
 		}
 	}
 }
@@ -869,7 +1110,6 @@ static uint32_t gsi_get_max_channels(enum gsi_ver ver)
 			gsi_ctx->per.ee, &hw_param2);
 		max_ch = hw_param2.gsi_num_ch_per_ee;
 		break;
-
 	}
 
 	GSIDBG("max channels %d\n", max_ch);
@@ -882,6 +1122,7 @@ static uint32_t gsi_get_max_event_rings(enum gsi_ver ver)
 	uint32_t max_ev = 0;
 	struct gsihal_reg_hw_param hw_param;
 	struct gsihal_reg_hw_param2 hw_param2;
+	struct gsihal_reg_hw_param4 hw_param4;
 
 	switch (ver) {
 	case GSI_VER_ERR:
@@ -899,6 +1140,11 @@ static uint32_t gsi_get_max_event_rings(enum gsi_ver ver)
 			gsi_ctx->per.ee, &hw_param);
 		max_ev = hw_param.gsi_ev_ch_num;
 		break;
+	case GSI_VER_3_0:
+		gsihal_read_reg_n_fields(GSI_EE_n_GSI_HW_PARAM_4,
+			gsi_ctx->per.ee, &hw_param4);
+		max_ev = hw_param4.gsi_num_ev_per_ee;
+		break;
 	default:
 		gsihal_read_reg_n_fields(GSI_EE_n_GSI_HW_PARAM_2,
 			gsi_ctx->per.ee, &hw_param2);
@@ -1186,9 +1432,16 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl)
 	 * Inter EE commands / interrupt are no supported.
 	 */
 	__gsi_config_type_irq(props->ee, ~0, ~0);
-	__gsi_config_ch_irq(props->ee, ~0, ~0);
-	__gsi_config_evt_irq(props->ee, ~0, ~0);
-	__gsi_config_ieob_irq(props->ee, ~0, ~0);
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		__gsi_config_all_ch_irq(props->ee, ~0, ~0);
+		__gsi_config_all_evt_irq(props->ee, ~0, ~0);
+		__gsi_config_all_ieob_irq(props->ee, ~0, ~0);
+	}
+	else {
+		__gsi_config_ch_irq(props->ee, ~0, ~0);
+		__gsi_config_evt_irq(props->ee, ~0, ~0);
+		__gsi_config_ieob_irq(props->ee, ~0, ~0);
+	}
 	__gsi_config_glob_irq(props->ee, ~0, ~0);
 
 	/*
@@ -1331,9 +1584,16 @@ int gsi_deregister_device(unsigned long dev_hdl, bool force)
 
 	/* disable all interrupts */
 	__gsi_config_type_irq(gsi_ctx->per.ee, ~0, 0);
-	__gsi_config_ch_irq(gsi_ctx->per.ee, ~0, 0);
-	__gsi_config_evt_irq(gsi_ctx->per.ee, ~0, 0);
-	__gsi_config_ieob_irq(gsi_ctx->per.ee, ~0, 0);
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		__gsi_config_all_ch_irq(gsi_ctx->per.ee, ~0, 0);
+		__gsi_config_all_evt_irq(gsi_ctx->per.ee, ~0, 0);
+		__gsi_config_all_ieob_irq(gsi_ctx->per.ee, ~0, 0);
+	}
+	else {
+		__gsi_config_ch_irq(gsi_ctx->per.ee, ~0, 0);
+		__gsi_config_evt_irq(gsi_ctx->per.ee, ~0, 0);
+		__gsi_config_ieob_irq(gsi_ctx->per.ee, ~0, 0);
+	}
 	__gsi_config_glob_irq(gsi_ctx->per.ee, ~0, 0);
 	__gsi_config_gen_irq(gsi_ctx->per.ee, ~0, 0);
 
@@ -1474,12 +1734,17 @@ static int gsi_validate_evt_ring_props(struct gsi_evt_ring_props *props)
 			(props->re_size == GSI_EVT_RING_RE_SIZE_8B &&
 				 props->ring_len % 8) ||
 			(props->re_size == GSI_EVT_RING_RE_SIZE_16B &&
-				 props->ring_len % 16)) {
+				 props->ring_len % 16) ||
+				(props->re_size == GSI_EVT_RING_RE_SIZE_32B &&
+					props->ring_len % 32)) {
 		GSIERR("bad params ring_len %u not a multiple of RE size %u\n",
 				props->ring_len, props->re_size);
 		return -GSI_STATUS_INVALID_PARAMS;
 	}
 
+	if (!gsihal_check_ring_length_valid(props->ring_len, props->re_size))
+		return -GSI_STATUS_INVALID_PARAMS;
+
 	ra = props->ring_base_addr;
 	do_div(ra, roundup_pow_of_two(props->ring_len));
 
@@ -1701,14 +1966,33 @@ int gsi_alloc_evt_ring(struct gsi_evt_ring_props *props, unsigned long dev_hdl,
 	mutex_unlock(&gsi_ctx->mlock);
 
 	spin_lock_irqsave(&gsi_ctx->slock, flags);
-	gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR, ee, 1 << evt_id);
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+	gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k, ee,
+		gsihal_get_ch_reg_idx(evt_id), gsihal_get_ch_reg_mask(evt_id));
+	}
+	else {
+		gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR, ee, 1 << evt_id);
+	}
 
 	/* enable ieob interrupts for GPI, enable MSI interrupts */
-	if ((props->intf != GSI_EVT_CHTYPE_GPI_EV) &&
-		(props->intr != GSI_INTR_MSI))
-		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << evt_id, 0);
-	else
-		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->id, ~0);
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		if ((props->intf != GSI_EVT_CHTYPE_GPI_EV) &&
+			(props->intr != GSI_INTR_MSI))
+			__gsi_config_ieob_irq_k(gsi_ctx->per.ee, gsihal_get_ch_reg_idx(evt_id),
+				gsihal_get_ch_reg_mask(evt_id),
+				0);
+		else
+			__gsi_config_ieob_irq_k(gsi_ctx->per.ee, gsihal_get_ch_reg_idx(evt_id),
+				gsihal_get_ch_reg_mask(evt_id),
+				~0);
+	}
+	else {
+		if ((props->intf != GSI_EVT_CHTYPE_GPI_EV) &&
+			(props->intr != GSI_INTR_MSI))
+			__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << evt_id, 0);
+		else
+			__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->id, ~0);
+	}
 	spin_unlock_irqrestore(&gsi_ctx->slock, flags);
 
 	return GSI_STATUS_SUCCESS;
@@ -2117,7 +2401,11 @@ static void gsi_program_chan_ctx(struct gsi_chan_props *props, unsigned int ee,
 
 	ch_k_cntxt_0.chtype_protocol = props->prot;
 	ch_k_cntxt_0.chtype_dir = props->dir;
-	ch_k_cntxt_0.erindex = erindex;
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		ch_k_cntxt_1.erindex = erindex;
+	} else {
+		ch_k_cntxt_0.erindex = erindex;
+	}
 	ch_k_cntxt_0.element_size = props->re_size;
 	gsihal_write_reg_nk_fields(GSI_EE_n_GSI_CH_k_CNTXT_0,
 		ee, props->ch_id, &ch_k_cntxt_0);
@@ -2167,12 +2455,17 @@ static int gsi_validate_channel_props(struct gsi_chan_props *props)
 			(props->re_size == GSI_CHAN_RE_SIZE_16B &&
 				 props->ring_len % 16) ||
 			(props->re_size == GSI_CHAN_RE_SIZE_32B &&
-				 props->ring_len % 32)) {
+				 props->ring_len % 32) ||
+			(props->re_size == GSI_CHAN_RE_SIZE_64B &&
+					props->ring_len % 64)) {
 		GSIERR("bad params ring_len %u not a multiple of re size %u\n",
 				props->ring_len, props->re_size);
 		return -GSI_STATUS_INVALID_PARAMS;
 	}
 
+	if (!gsihal_check_ring_length_valid(props->ring_len, props->re_size))
+		return -GSI_STATUS_INVALID_PARAMS;
+
 	ra = props->ring_base_addr;
 	do_div(ra, roundup_pow_of_two(props->ring_len));
 
@@ -3613,8 +3906,15 @@ int gsi_poll_n_channel(unsigned long chan_hdl,
 		/* read gsi event ring rp again if last read is empty */
 		if (rp == ctx->evtr->ring.rp_local) {
 			/* event ring is empty */
-			gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ,
-				ee, 1 << ctx->evtr->id);
+			if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+				gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_k,
+					ee, gsihal_get_ch_reg_idx(ctx->evtr->id),
+				gsihal_get_ch_reg_mask(ctx->evtr->id));
+			}
+			else {
+				gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ,
+					ee, 1 << ctx->evtr->id);
+			}
 			/* do another read to close a small window */
 			__iowmb();
 			rp = ctx->evtr->props.gsi_read_event_ring_rp(
@@ -3691,9 +3991,24 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 	spin_lock_irqsave(&gsi_ctx->slock, flags);
 	if (curr == GSI_CHAN_MODE_CALLBACK &&
 			mode == GSI_CHAN_MODE_POLL) {
-		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0);
-		gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR,
-			gsi_ctx->per.ee, 1 << ctx->evtr->id);
+		if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+			__gsi_config_ieob_irq_k(gsi_ctx->per.ee,
+				gsihal_get_ch_reg_idx(ctx->evtr->id),
+				gsihal_get_ch_reg_mask(ctx->evtr->id),
+				0);
+		}
+		else {
+			__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0);
+		}
+		if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+			gsihal_write_reg_nk(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k,
+				gsi_ctx->per.ee, gsihal_get_ch_reg_idx(ctx->evtr->id),
+				gsihal_get_ch_reg_mask(ctx->evtr->id));
+		}
+		else {
+			gsihal_write_reg_n(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR,
+				gsi_ctx->per.ee, 1 << ctx->evtr->id);
+		}
 		atomic_set(&ctx->poll_mode, mode);
 		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan) {
 			atomic_set(&ctx->evtr->chan->poll_mode, mode);
@@ -3718,7 +4033,15 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 			if (coal_ctx != NULL)
 				atomic_set(&coal_ctx->poll_mode, mode);
 		}
-		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
+		if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+			__gsi_config_ieob_irq_k(gsi_ctx->per.ee,
+				gsihal_get_ch_reg_idx(ctx->evtr->id),
+				gsihal_get_ch_reg_mask(ctx->evtr->id),
+				~0);
+		}
+		else {
+			__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
+		}
 		GSIDBG("set gsi_ctx evtr_id %d to %d mode\n",
 			ctx->evtr->id, mode);
 
@@ -3734,12 +4057,25 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 				GSI_EE_n_CNTXT_SRC_IEOB_IRQ,
 				gsi_ctx->per.ee);
 			if (src & (1 << ctx->evtr->id)) {
-				__gsi_config_ieob_irq(
-					gsi_ctx->per.ee, 1 << ctx->evtr->id, 0);
-				gsihal_write_reg_n(
-					GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR,
-					gsi_ctx->per.ee,
-					1 << ctx->evtr->id);
+				if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+					__gsi_config_ieob_irq_k(gsi_ctx->per.ee,
+						gsihal_get_ch_reg_idx(ctx->evtr->id),
+						gsihal_get_ch_reg_mask(ctx->evtr->id),
+						0);
+					gsihal_write_reg_nk(
+						GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k,
+						gsi_ctx->per.ee,
+						gsihal_get_ch_reg_idx(ctx->evtr->id),
+						gsihal_get_ch_reg_mask(ctx->evtr->id));
+				}
+				else {
+					__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << 
+						ctx->evtr->id, 0);
+					gsihal_write_reg_n(
+						GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR,
+						gsi_ctx->per.ee,
+						1 << ctx->evtr->id);
+				}
 				spin_unlock_irqrestore(&gsi_ctx->slock, flags);
 				spin_lock_irqsave(&ctx->evtr->ring.slock,
 									flags);
@@ -3872,10 +4208,15 @@ static void gsi_configure_ieps(enum gsi_ver ver)
 		gsihal_write_reg(
 			GSI_GSI_IRAM_PTR_TLV_CH_NOT_FULL,
 			17);
+
 	if (ver >= GSI_VER_2_11)
 		gsihal_write_reg(
 			GSI_GSI_IRAM_PTR_MSI_DB,
 			18);
+	if (ver >= GSI_VER_3_0)
+		gsihal_write_reg(
+			GSI_GSI_IRAM_PTR_INT_NOTIFY_MCS,
+			19);
 }
 
 static void gsi_configure_bck_prs_matrix(void)
@@ -4122,7 +4463,7 @@ free_lock:
 EXPORT_SYMBOL(gsi_alloc_channel_ee);
 
 int gsi_enable_flow_control_ee(unsigned int chan_idx, unsigned int ee,
-								int *code)
+	int *code)
 {
 	enum gsi_generic_ee_cmd_opcode op = GSI_GEN_EE_CMD_ENABLE_FLOW_CHANNEL;
 	struct gsihal_reg_ch_k_cntxt_0 ch_k_cntxt_0;
@@ -4172,16 +4513,16 @@ int gsi_enable_flow_control_ee(unsigned int chan_idx, unsigned int ee,
 	if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
 		GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING) {
 		GSIDBG("chan_idx=%u ee=%u not in correct state\n",
-							chan_idx, ee);
+			chan_idx, ee);
 		*code = GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING;
 		res = -GSI_STATUS_RES_ALLOC_FAILURE;
 		goto free_lock;
 	} else if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
-			GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE ||
-			gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
-			GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX){
+		GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE ||
+		gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
+		GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX) {
 		GSIERR("chan_idx=%u ee=%u not in correct state\n",
-				chan_idx, ee);
+			chan_idx, ee);
 		GSI_ASSERT();
 	}
 	if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code == 0) {
@@ -4199,7 +4540,7 @@ int gsi_enable_flow_control_ee(unsigned int chan_idx, unsigned int ee,
 		res = GSI_STATUS_SUCCESS;
 	} else {
 		GSIERR("ch %u state updated to %u incorrect state\n",
-						chan_idx, curr_state);
+			chan_idx, curr_state);
 		res = -GSI_STATUS_ERROR;
 	}
 	*code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code;

+ 6 - 5
drivers/platform/msm/gsi/gsi.h

@@ -25,9 +25,9 @@
 #define GSI_ASSERT() \
 	BUG()
 
-#define GSI_CHAN_MAX      31
-#define GSI_EVT_RING_MAX  24
-#define GSI_NO_EVT_ERINDEX 31
+#define GSI_CHAN_MAX      36
+#define GSI_EVT_RING_MAX  31
+#define GSI_NO_EVT_ERINDEX 255
 #define GSI_ISR_CACHE_MAX 20
 
 #define GSI_IPC_LOGGING(buf, fmt, args...) \
@@ -84,6 +84,7 @@ enum gsi_ver {
 	GSI_VER_2_7 = 7,
 	GSI_VER_2_9 = 8,
 	GSI_VER_2_11 = 9,
+	GSI_VER_3_0 = 10,
 	GSI_VER_MAX,
 };
 
@@ -187,7 +188,7 @@ struct gsi_evt_ring_props {
 	enum gsi_evt_chtype intf;
 	enum gsi_intr_type intr;
 	enum gsi_evt_ring_elem_size re_size;
-	uint16_t ring_len;
+	uint32_t ring_len;
 	uint64_t ring_base_addr;
 	void *ring_base_vaddr;
 	uint16_t int_modt;
@@ -1129,7 +1130,7 @@ struct gsi_ring_ctx {
 	uint64_t rp;
 	uint64_t wp_local;
 	uint64_t rp_local;
-	uint16_t len;
+	uint32_t len;
 	uint8_t elem_sz;
 	uint16_t max_num_elem;
 	uint64_t end;

+ 25 - 0
drivers/platform/msm/gsi/gsi_dbg.c

@@ -206,6 +206,11 @@ static ssize_t gsi_dump_ch(struct file *file,
 	val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_7,
 		gsi_ctx->per.ee, arg1);
 	TERR("CH%2d CTX7  0x%x\n", arg1, val);
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_8,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d CTX8  0x%x\n", arg1, val);
+	}
 	val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_RE_FETCH_READ_PTR,
 		gsi_ctx->per.ee, arg1);
 	TERR("CH%2d REFRP 0x%x\n", arg1, val);
@@ -227,6 +232,26 @@ static ssize_t gsi_dump_ch(struct file *file,
 	val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_3,
 		gsi_ctx->per.ee, arg1);
 	TERR("CH%2d SCR3  0x%x\n", arg1, val);
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_4,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d SCR4  0x%x\n", arg1, val);
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_5,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d SCR5  0x%x\n", arg1, val);
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_6,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d SCR6  0x%x\n", arg1, val);
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_7,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d SCR7  0x%x\n", arg1, val);
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_8,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d SCR8  0x%x\n", arg1, val);
+		val = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_SCRATCH_9,
+			gsi_ctx->per.ee, arg1);
+		TERR("CH%2d SCR9  0x%x\n", arg1, val);
+	}
 
 	if (arg2) {
 		ctx = &gsi_ctx->chan[arg1];

+ 638 - 11
drivers/platform/msm/gsi/gsihal/gsihal_reg.c

@@ -7,6 +7,18 @@
 #include "gsihal_reg_i.h"
 #include "gsihal_reg.h"
 
+/*
+*	GSI_CH_BIT_MAP_ARR_SIZE - The number of cells in bit map
+*		registers for GSI channels.
+*		This is taken from the k range
+*		of each bit map register.
+*/
+#define GSI_CH_BIT_MAP_ARR_SIZE			(1)
+
+/* Utility macros to use with bit map arrays*/
+#define GSI_CH_BIT_MAP_CELL_NUM(num)	((num) >> 5)
+#define GSI_BIT_MAP_CELL_MSK(num)		(1 << (num - (GSI_CH_BIT_MAP_CELL_NUM(num) << 5)))
+
 #define gsi_readl(c)	(readl_relaxed(c))
 #define gsi_writel(v, c)	({ __iowmb(); writel_relaxed((v), (c)); })
 
@@ -41,6 +53,7 @@ static const char *gsireg_name_to_str[GSI_REG_MAX] = {
 	__stringify(GSI_EE_n_GSI_HW_PARAM),
 	__stringify(GSI_EE_n_GSI_HW_PARAM_0),
 	__stringify(GSI_EE_n_GSI_HW_PARAM_2),
+	__stringify(GSI_EE_n_GSI_HW_PARAM_4),
 	__stringify(GSI_EE_n_GSI_SW_VERSION),
 	__stringify(GSI_EE_n_CNTXT_INTSET),
 	__stringify(GSI_EE_n_CNTXT_MSI_BASE_LSB),
@@ -70,10 +83,17 @@ static const char *gsireg_name_to_str[GSI_REG_MAX] = {
 	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_1),
 	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_2),
 	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_3),
+	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_4),
+	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_5),
+	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_6),
+	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_7),
+	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_8),
+	__stringify(GSI_EE_n_GSI_CH_k_SCRATCH_9),
 	__stringify(GSI_EE_n_GSI_CH_k_CNTXT_4),
 	__stringify(GSI_EE_n_GSI_CH_k_CNTXT_5),
 	__stringify(GSI_EE_n_GSI_CH_k_CNTXT_6),
 	__stringify(GSI_EE_n_GSI_CH_k_CNTXT_7),
+	__stringify(GSI_EE_n_GSI_CH_k_CNTXT_8),
 	__stringify(GSI_EE_n_EV_CH_k_CNTXT_4),
 	__stringify(GSI_EE_n_EV_CH_k_CNTXT_5),
 	__stringify(GSI_EE_n_EV_CH_k_CNTXT_6),
@@ -127,6 +147,20 @@ static const char *gsireg_name_to_str[GSI_REG_MAX] = {
 	__stringify(GSI_EE_n_GSI_CH_k_RE_FETCH_WRITE_PTR),
 	__stringify(GSI_GSI_INST_RAM_n),
 	__stringify(GSI_GSI_IRAM_PTR_MSI_DB),
+	__stringify(GSI_GSI_IRAM_PTR_INT_NOTIFY_MCS),
+	__stringify(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k),
+	__stringify(GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k),
+	__stringify(GSI_INTER_EE_n_SRC_GSI_CH_IRQ_k),
+	__stringify(GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_k),
+	__stringify(GSI_INTER_EE_n_SRC_EV_CH_IRQ_k),
+	__stringify(GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_k),
 };
 
 /*
@@ -247,7 +281,47 @@ static void gsireg_parse_ch_k_cntxt_0_v2_5(enum gsihal_reg_name reg,
 		GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_BMSK);
 }
 
-static void gsireg_parse_ev_ch_k_cntxt_0(enum gsihal_reg_name reg, void *fields,
+static void gsireg_parse_ch_k_cntxt_0_v3_0(enum gsihal_reg_name reg,
+	void *fields, u32 val)
+{
+	struct gsihal_reg_ch_k_cntxt_0 *ch_k_ctxt =
+		(struct gsihal_reg_ch_k_cntxt_0 *) fields;
+
+	ch_k_ctxt->element_size = GSI_GETFIELD_FROM_REG(val,
+		GSI_EE_n_GSI_CH_k_CNTXT_0_ELEMENT_SIZE_SHFT,
+		GSI_EE_n_GSI_CH_k_CNTXT_0_ELEMENT_SIZE_BMSK);
+	ch_k_ctxt->chstate = GSI_GETFIELD_FROM_REG(val,
+		GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT,
+		GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK);
+	ch_k_ctxt->chid = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHID_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHID_BMSK);
+	ch_k_ctxt->ee = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_EE_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_EE_BMSK);
+	ch_k_ctxt->chtype_dir = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_BMSK);
+	ch_k_ctxt->chtype_protocol = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_BMSK);
+}
+
+static void gsireg_parse_ch_k_cntxt_1_v3_0(enum gsihal_reg_name reg,
+	void *fields, u32 val)
+{
+	struct gsihal_reg_ch_k_cntxt_1 *ch_k_ctxt =
+		(struct gsihal_reg_ch_k_cntxt_1 *) fields;
+
+	ch_k_ctxt->r_length = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK);
+	ch_k_ctxt->erindex = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_ERINDEX_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_ERINDEX_BMSK);
+}
+
+static void gsireg_parse_ev_ch_k_cntxt_0_common(enum gsihal_reg_name reg, void *fields,
 	u32 val)
 {
 	struct gsihal_reg_ev_ch_k_cntxt_0 *ev_ch_k_ctxt =
@@ -259,12 +333,22 @@ static void gsireg_parse_ev_ch_k_cntxt_0(enum gsihal_reg_name reg, void *fields,
 	ev_ch_k_ctxt->chstate = GSI_GETFIELD_FROM_REG(val,
 		GSI_EE_n_EV_CH_k_CNTXT_0_CHSTATE_SHFT,
 		GSI_EE_n_EV_CH_k_CNTXT_0_CHSTATE_BMSK);
-	ev_ch_k_ctxt->intype = GSI_GETFIELD_FROM_REG(val,
-		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT,
-		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK);
 	ev_ch_k_ctxt->evchid = GSI_GETFIELD_FROM_REG(val,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EVCHID_SHFT,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EVCHID_BMSK);
+}
+
+static void gsireg_parse_ev_ch_k_cntxt_0(enum gsihal_reg_name reg, void *fields,
+	u32 val)
+{
+	struct gsihal_reg_ev_ch_k_cntxt_0 *ev_ch_k_ctxt =
+		(struct gsihal_reg_ev_ch_k_cntxt_0 *) fields;
+
+	gsireg_parse_ev_ch_k_cntxt_0_common(reg, fields, val);
+
+	ev_ch_k_ctxt->intype = GSI_GETFIELD_FROM_REG(val,
+		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT,
+		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK);
 	ev_ch_k_ctxt->ee = GSI_GETFIELD_FROM_REG(val,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EE_SHFT,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EE_BMSK);
@@ -273,7 +357,26 @@ static void gsireg_parse_ev_ch_k_cntxt_0(enum gsihal_reg_name reg, void *fields,
 		GSI_EE_n_EV_CH_k_CNTXT_0_CHTYPE_BMSK);
 }
 
-static void gsireg_construct_ev_ch_k_cntxt_0(enum gsihal_reg_name reg,
+static void gsireg_parse_ev_ch_k_cntxt_0_v3_0(enum gsihal_reg_name reg, void *fields,
+	u32 val)
+{
+	struct gsihal_reg_ev_ch_k_cntxt_0 *ev_ch_k_ctxt =
+		(struct gsihal_reg_ev_ch_k_cntxt_0 *) fields;
+
+	gsireg_parse_ev_ch_k_cntxt_0_common(reg, fields, val);
+
+	ev_ch_k_ctxt->ee = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_EE_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_EE_BMSK);
+	ev_ch_k_ctxt->intype = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK);
+	ev_ch_k_ctxt->chtype = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_CHTYPE_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_CHTYPE_BMSK);
+}
+
+static void gsireg_construct_ev_ch_k_cntxt_0_common(enum gsihal_reg_name reg,
 	const void *fields, u32 *val)
 {
 	struct gsihal_reg_ev_ch_k_cntxt_0 *ctxt =
@@ -285,12 +388,22 @@ static void gsireg_construct_ev_ch_k_cntxt_0(enum gsihal_reg_name reg,
 	GSI_SETFIELD_IN_REG(*val, ctxt->chstate,
 		GSI_EE_n_EV_CH_k_CNTXT_0_CHSTATE_SHFT,
 		GSI_EE_n_EV_CH_k_CNTXT_0_CHSTATE_BMSK);
-	GSI_SETFIELD_IN_REG(*val, ctxt->intype,
-		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT,
-		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK);
 	GSI_SETFIELD_IN_REG(*val, ctxt->evchid,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EVCHID_SHFT,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EVCHID_BMSK);
+}
+
+static void gsireg_construct_ev_ch_k_cntxt_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_ev_ch_k_cntxt_0 *ctxt =
+		(struct gsihal_reg_ev_ch_k_cntxt_0 *)fields;
+
+	gsireg_construct_ev_ch_k_cntxt_0_common(reg, fields, val);
+
+	GSI_SETFIELD_IN_REG(*val, ctxt->intype,
+		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT,
+		GSI_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK);
 	GSI_SETFIELD_IN_REG(*val, ctxt->ee,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EE_SHFT,
 		GSI_EE_n_EV_CH_k_CNTXT_0_EE_BMSK);
@@ -299,6 +412,25 @@ static void gsireg_construct_ev_ch_k_cntxt_0(enum gsihal_reg_name reg,
 		GSI_EE_n_EV_CH_k_CNTXT_0_CHTYPE_BMSK);
 }
 
+static void gsireg_construct_ev_ch_k_cntxt_0_v3_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_ev_ch_k_cntxt_0 *ctxt =
+		(struct gsihal_reg_ev_ch_k_cntxt_0 *)fields;
+
+	gsireg_construct_ev_ch_k_cntxt_0_common(reg, fields, val);
+
+	GSI_SETFIELD_IN_REG(*val, ctxt->ee,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_EE_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_EE_BMSK);
+	GSI_SETFIELD_IN_REG(*val, ctxt->intype,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK);
+	GSI_SETFIELD_IN_REG(*val, ctxt->chtype,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_CHTYPE_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_CHTYPE_BMSK);
+}
+
 static void gsireg_parse_cntxt_glob_irq_stts(enum gsihal_reg_name reg,
 	void *fields, u32 val)
 {
@@ -453,6 +585,58 @@ static void gsireg_parse_hw_param2_v2_2(enum gsihal_reg_name reg,
 		GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK);
 }
 
+static void gsireg_parse_hw_param2_v3_0(enum gsihal_reg_name reg,
+	void *fields, u32 val)
+{
+	struct gsihal_reg_hw_param2 *hw_param =
+		(struct gsihal_reg_hw_param2 *) fields;
+
+	hw_param->gsi_ch_full_logic = GSI_GETFIELD_FROM_REG(val,
+		GSI_V1_3_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_SHFT,
+		GSI_V1_3_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_BMSK);
+	hw_param->gsi_ch_pend_translate = GSI_GETFIELD_FROM_REG(val,
+		GSI_V1_3_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_SHFT,
+		GSI_V1_3_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_BMSK);
+	hw_param->gsi_num_ch_per_ee = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK);
+	hw_param->gsi_iram_size = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_SHFT,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_BMSK);
+	hw_param->gsi_sdma_n_iovec = GSI_GETFIELD_FROM_REG(val,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_SHFT,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_BMSK);
+	hw_param->gsi_sdma_max_burst = GSI_GETFIELD_FROM_REG(val,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_SHFT,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_BMSK);
+	hw_param->gsi_sdma_n_int = GSI_GETFIELD_FROM_REG(val,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_SHFT,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_BMSK);
+	hw_param->gsi_use_sdma = GSI_GETFIELD_FROM_REG(val,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_SHFT,
+		GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_BMSK);
+	hw_param->gsi_use_inter_ee = GSI_GETFIELD_FROM_REG(val,
+		GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_SHFT,
+		GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_BMSK);
+	hw_param->gsi_use_rd_wr_eng = GSI_GETFIELD_FROM_REG(val,
+		GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_SHFT,
+		GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK);
+}
+
+static void gsireg_parse_hw_param4_v3_0(enum gsihal_reg_name reg,
+	void *fields, u32 val)
+{
+	struct gsihal_reg_hw_param4 *hw_param =
+		(struct gsihal_reg_hw_param4 *) fields;
+
+	hw_param->gsi_iram_protcol_cnt = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_IRAM_PROTCOL_CNT_SHFT,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_IRAM_PROTCOL_CNT_BMSK);
+	hw_param->gsi_num_ev_per_ee = GSI_GETFIELD_FROM_REG(val,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_NUM_EV_PER_EE_SHFT,
+		GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_NUM_EV_PER_EE_BMSK);
+}
+
 static void gsireg_parse_gsi_status(enum gsihal_reg_name reg,
 	void *fields, u32 val)
 {
@@ -486,6 +670,17 @@ static void gsireg_construct_ev_ch_k_cntxt_1_v2_9(enum gsihal_reg_name reg,
 		GSI_V2_9_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK);
 }
 
+static void gsireg_construct_ev_ch_k_cntxt_1_v3_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_ev_ch_k_cntxt_1 *ctxt =
+		(struct gsihal_reg_ev_ch_k_cntxt_1 *)fields;
+
+	GSI_SETFIELD_IN_REG(*val, ctxt->r_length,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_SHFT,
+		GSI_V3_0_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK);
+}
+
 static void gsireg_construct_ev_ch_k_cntxt_2(enum gsihal_reg_name reg,
 	const void *fields, u32 *val)
 {
@@ -665,7 +860,20 @@ static void gsireg_construct_ee_n_gsi_ch_k_qos_v2_9(enum gsihal_reg_name reg,
 		GSI_V2_9_EE_n_GSI_CH_k_QOS_DB_IN_BYTES_BMSK);
 }
 
-static void gsireg_construct_ch_k_cntxt_0(enum gsihal_reg_name reg,
+static void gsireg_construct_ee_n_gsi_ch_k_qos_v3_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_gsi_ee_n_gsi_ch_k_qos *ch_qos =
+		(struct gsihal_reg_gsi_ee_n_gsi_ch_k_qos *)fields;
+
+	gsireg_construct_ee_n_gsi_ch_k_qos_v2_9(reg, fields, val);
+
+	GSI_SETFIELD_IN_REG(*val, !!ch_qos->low_latency_en,
+		GSI_V3_0_EE_n_GSI_CH_k_QOS_LOW_LATENCY_EN_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_QOS_LOW_LATENCY_EN_BMSK);
+}
+
+static void gsireg_construct_ch_k_cntxt_0_common(enum gsihal_reg_name reg,
 	const void *fields, u32 *val)
 {
 	struct gsihal_reg_ch_k_cntxt_0 *ch_cntxt =
@@ -677,6 +885,16 @@ static void gsireg_construct_ch_k_cntxt_0(enum gsihal_reg_name reg,
 	GSI_SETFIELD_IN_REG(*val, ch_cntxt->chstate,
 		GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT,
 		GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK);
+}
+
+static void gsireg_construct_ch_k_cntxt_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_ch_k_cntxt_0 *ch_cntxt =
+		(struct gsihal_reg_ch_k_cntxt_0 *)fields;
+
+	gsireg_construct_ch_k_cntxt_0_common(reg, fields, val);
+
 	GSI_SETFIELD_IN_REG(*val, ch_cntxt->erindex,
 		GSI_EE_n_GSI_CH_k_CNTXT_0_ERINDEX_SHFT,
 		GSI_EE_n_GSI_CH_k_CNTXT_0_ERINDEX_BMSK);
@@ -707,6 +925,28 @@ static void gsireg_construct_ch_k_cntxt_0_v2_5(enum gsihal_reg_name reg,
 		GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_BMSK);
 }
 
+static void gsireg_construct_ch_k_cntxt_0_v3_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_ch_k_cntxt_0 *ch_cntxt =
+		(struct gsihal_reg_ch_k_cntxt_0 *)fields;
+
+	gsireg_construct_ch_k_cntxt_0_common(reg, fields, val);
+
+	GSI_SETFIELD_IN_REG(*val, ch_cntxt->chid,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHID_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHID_BMSK);
+	GSI_SETFIELD_IN_REG(*val, ch_cntxt->ee,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_EE_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_EE_BMSK);
+	GSI_SETFIELD_IN_REG(*val, !!ch_cntxt->chtype_dir,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_BMSK);
+	GSI_SETFIELD_IN_REG(*val, ch_cntxt->chtype_protocol,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_BMSK);
+}
+
 static void gsireg_construct_ch_k_cntxt_1(enum gsihal_reg_name reg,
 	const void *fields, u32 *val)
 {
@@ -729,6 +969,20 @@ static void gsireg_construct_ch_k_cntxt_1_v2_9(enum gsihal_reg_name reg,
 		GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK);
 }
 
+static void gsireg_construct_ch_k_cntxt_1_v3_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_ch_k_cntxt_1 *ch_cntxt =
+		(struct gsihal_reg_ch_k_cntxt_1 *)fields;
+
+	GSI_SETFIELD_IN_REG(*val, ch_cntxt->r_length,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK);
+	GSI_SETFIELD_IN_REG(*val, ch_cntxt->erindex,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_ERINDEX_SHFT,
+		GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_ERINDEX_BMSK);
+}
+
 static void gsireg_construct_ee_n_gsi_ch_cmd(enum gsihal_reg_name reg,
 	const void *fields, u32 *val)
 {
@@ -798,6 +1052,23 @@ static void gsireg_construct_gsi_ee_generic_cmd(enum gsihal_reg_name reg,
 		GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK);
 }
 
+static void gsireg_construct_gsi_ee_generic_cmd_v3_0(enum gsihal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct gsihal_reg_gsi_ee_generic_cmd *cmd =
+		(struct gsihal_reg_gsi_ee_generic_cmd *)fields;
+
+	GSI_SETFIELD_IN_REG(*val, cmd->opcode,
+		GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT,
+		GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK);
+	GSI_SETFIELD_IN_REG(*val, cmd->virt_chan_idx,
+		GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT,
+		GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK);
+	GSI_SETFIELD_IN_REG(*val, cmd->ee,
+		GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT,
+		GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK);
+}
+
 static void gsireg_construct_cntxt_gsi_irq_en(enum gsihal_reg_name reg,
 	const void *fields, u32 *val)
 {
@@ -1406,6 +1677,245 @@ static struct gsihal_reg_obj gsihal_reg_objs[GSI_VER_MAX][GSI_REG_MAX] = {
 	[GSI_VER_2_11][GSI_GSI_IRAM_PTR_MSI_DB] = {
 	gsireg_construct_dummy, gsireg_parse_dummy,
 	0x00000414, 0, 0 },
+
+	/* GSIv3_0 */
+	[GSI_VER_3_0][GSI_GSI_IRAM_PTR_INT_NOTIFY_MCS] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00000470, 0, 0 },
+	[GSI_VER_3_0][GSI_GSI_INST_RAM_n] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x000a4000, GSI_GSI_INST_RAM_n_WORD_SZ, 0},
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_0] = {
+	gsireg_construct_ch_k_cntxt_0_v3_0, gsireg_parse_ch_k_cntxt_0_v3_0,
+	0x00014000, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_1] = {
+	gsireg_construct_ch_k_cntxt_1_v3_0, gsireg_parse_ch_k_cntxt_1_v3_0,
+	0x00014004, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_2] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014008, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_3] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001400c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_4] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014010, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_5] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014014, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_6] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014018, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_7] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001401c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_CNTXT_8] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014020 , 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_RE_FETCH_READ_PTR] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014040, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_RE_FETCH_WRITE_PTR] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014044, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_QOS] = {
+	gsireg_construct_ee_n_gsi_ch_k_qos_v3_0, gsireg_parse_dummy,
+	0x00014048, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_0] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001404c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_1] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014050, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_2] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014054, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_3] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014058, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_4] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001405c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_5] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014060, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_6] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014064, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_7] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014068, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_8] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001406c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_SCRATCH_9] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00014070, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_0] = {
+	gsireg_construct_ev_ch_k_cntxt_0_v3_0, gsireg_parse_ev_ch_k_cntxt_0_v3_0,
+	0x0001c000, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_1] = {
+	gsireg_construct_ev_ch_k_cntxt_1_v3_0, gsireg_parse_dummy,
+	0x0001c004, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_2] = {
+	gsireg_construct_ev_ch_k_cntxt_2, gsireg_parse_dummy,
+	0x0001c008, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_3] = {
+	gsireg_construct_ev_ch_k_cntxt_3, gsireg_parse_dummy,
+	0x0001c00c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_4] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001c010, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_5] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001c014, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_6] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001c018, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_7] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001c01c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_8] = {
+	gsireg_construct_ev_ch_k_cntxt_8, gsireg_parse_dummy,
+	0x0001c020, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_9] = {
+	gsireg_construct_ev_ch_k_cntxt_9, gsireg_parse_dummy,
+	0x0001c024, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_10] = {
+	gsireg_construct_ev_ch_k_cntxt_10, gsireg_parse_dummy,
+	0x0001c028, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_11] = {
+	gsireg_construct_ev_ch_k_cntxt_11, gsireg_parse_dummy,
+	0x0001c02c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_12] = {
+	gsireg_construct_ev_ch_k_cntxt_12, gsireg_parse_dummy,
+	0x0001c030, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_CNTXT_13] = {
+	gsireg_construct_ev_ch_k_cntxt_13, gsireg_parse_dummy,
+	0x0001c034, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_SCRATCH_0] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001c048, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_SCRATCH_1] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0001c04c, 0x12000, 0x80 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_DOORBELL_0] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00024000, 0x12000, 0x8 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_k_DOORBELL_1] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00024004, 0x12000, 0x8 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_DOORBELL_0] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00024800, 0x12000, 0x8 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_k_DOORBELL_1] = {
+	gsireg_construct_ev_ch_k_doorbell_1, gsireg_parse_dummy,
+	0x00024804, 0x12000, 0x8 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_STATUS] = {
+	gsireg_construct_dummy, gsireg_parse_gsi_status,
+	0x00025000, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_CH_CMD] = {
+	gsireg_construct_ee_n_gsi_ch_cmd, gsireg_parse_dummy,
+	0x00025008, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_EV_CH_CMD] = {
+	gsireg_construct_ee_n_ev_ch_cmd, gsireg_parse_dummy,
+	0x00025010, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_EE_GENERIC_CMD] = {
+	gsireg_construct_gsi_ee_generic_cmd_v3_0, gsireg_parse_dummy,
+	0x00025018, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_HW_PARAM_2] = {
+	gsireg_construct_dummy, gsireg_parse_hw_param2_v3_0,
+	0x00025040, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_HW_PARAM_4] = {
+	gsireg_construct_dummy, gsireg_parse_hw_param4_v3_0,
+	0x00025050, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_GSI_SW_VERSION] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025044, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_TYPE_IRQ] = {
+	gsireg_construct_dummy, gsireg_parse_ctx_type_irq,
+	0x00025080, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_TYPE_IRQ_MSK] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025088, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025090, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025094, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025098, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0002509c, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x000250a0, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x000250a4, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_IEOB_IRQ_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x000250a8, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x000250ac, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x000250b0, 0x12000, 0x24 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_GLOB_IRQ_STTS] = {
+	gsireg_construct_dummy, gsireg_parse_cntxt_glob_irq_stts,
+	0x00025200, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_GLOB_IRQ_EN] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025204, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_GLOB_IRQ_CLR] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025208, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_GSI_IRQ_STTS] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0002520c, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_GSI_IRQ_EN] = {
+	gsireg_construct_cntxt_gsi_irq_en, gsireg_parse_dummy,
+	0x00025210, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_GSI_IRQ_CLR] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025214, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_MSI_BASE_LSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025230, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_MSI_BASE_MSB] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025234, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_INTSET] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025220, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_ERROR_LOG] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025240, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_ERROR_LOG_CLR] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00025244, 0x12000, 0 },
+	[GSI_VER_3_0][GSI_EE_n_CNTXT_SCRATCH_0] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00024500, 0x12000, 0},
+	[GSI_VER_3_0][GSI_INTER_EE_n_SRC_GSI_CH_IRQ_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0000c018, 0x1000, 0x18 },
+	[GSI_VER_3_0][GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0000c020, 0x1000, 0x18 },
+	[GSI_VER_3_0][GSI_INTER_EE_n_SRC_EV_CH_IRQ_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0000c024, 0x1000, 0x18 },
+	[GSI_VER_3_0][GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_k] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x0000c02c, 0x1000, 0x18 },
+	[GSI_VER_3_0][GSI_MAP_EE_n_CH_k_VP_TABLE] = {
+	gsireg_construct_dummy, gsireg_parse_dummy,
+	0x00009000, 0x400, 0x4 },
 };
 
 /*
@@ -1709,6 +2219,90 @@ u32 gsihal_get_reg_nk_ofst(enum gsihal_reg_name reg, u32 n, u32 k)
 	return offset;
 }
 
+/*
+* gsihal_get_bit_map_array_size() - Get the size of the bit map
+*	array size according to the
+*	GSI version.
+*/
+u32 gsihal_get_bit_map_array_size()
+{
+	return GSI_CH_BIT_MAP_ARR_SIZE;
+}
+
+/*
+* gsihal_read_ch_reg() - Get the raw value of a ch reg
+*/
+u32 gsihal_read_ch_reg(enum gsihal_reg_name reg, u32 ch_num)
+{
+	return gsihal_read_reg_n(reg, GSI_CH_BIT_MAP_CELL_NUM(ch_num));
+}
+
+/*
+ * gsihal_test_ch_bit() - return true if a ch bit is set
+ */
+bool gsihal_test_ch_bit(u32 reg_val, u32 ch_num)
+{
+	return !!(reg_val & GSI_BIT_MAP_CELL_MSK(ch_num));
+}
+
+/*
+ * gsihal_get_ch_bit() - get ch bit set in the right offset
+ */
+u32 gsihal_get_ch_bit(u32 ch_num)
+{
+	return GSI_BIT_MAP_CELL_MSK(ch_num);
+}
+
+/*
+ * gsihal_get_ch_reg_idx() - get ch reg index according to ch num
+ */
+u32 gsihal_get_ch_reg_idx(u32 ch_num)
+{
+	return GSI_CH_BIT_MAP_CELL_NUM(ch_num);
+}
+
+/*
+ * gsihal_get_ch_reg_mask() - get ch reg mask according to ch num
+ */
+u32 gsihal_get_ch_reg_mask(u32 ch_num)
+{
+	return GSI_BIT_MAP_CELL_MSK(ch_num);
+}
+
+/*
+ * Get the offset of a ch register according to ch index
+ */
+u32 gsihal_get_ch_reg_offset(enum gsihal_reg_name reg, u32 ch_num)
+{
+	return gsihal_get_reg_nk_ofst(reg, 0, GSI_CH_BIT_MAP_CELL_NUM(ch_num));
+}
+
+/*
+* Get the offset of a ch n register according to ch index and n
+*/
+u32 gsihal_get_ch_reg_n_offset(enum gsihal_reg_name reg, u32 n, u32 ch_num)
+{
+	return gsihal_get_reg_nk_ofst(reg, GSI_CH_BIT_MAP_CELL_NUM(ch_num), n);
+}
+
+/*
+ * gsihal_write_ch_bit_map_reg_n() - Write mask to ch reg a raw value
+ */
+void gsihal_write_ch_bit_map_reg_n(enum gsihal_reg_name reg, u32 n, u32 ch_num,
+	u32 mask)
+{
+	gsihal_write_reg_nk(reg, n, GSI_CH_BIT_MAP_CELL_NUM(ch_num), mask);
+}
+
+/*
+ * gsihal_write_set_ch_bit_map_reg_n() - Set ch bit in reg a raw value
+ */
+void gsihal_write_set_ch_bit_map_reg_n(enum gsihal_reg_name reg, u32 n,
+	u32 ch_num)
+{
+	gsihal_write_reg_nk(reg, n, GSI_CH_BIT_MAP_CELL_NUM(ch_num),
+		GSI_BIT_MAP_CELL_MSK(ch_num));
+}
 
 /*
  * Get GSI instruction ram MAX size
@@ -1739,6 +2333,9 @@ unsigned long gsihal_get_inst_ram_size(void)
 	case GSI_VER_2_9:
 		maxn = GSI_V2_9_GSI_INST_RAM_n_MAXn;
 		break;
+	case GSI_VER_3_0:
+		maxn = GSI_V3_0_GSI_INST_RAM_n_MAXn;
+		break;
 	case GSI_VER_ERR:
 	case GSI_VER_MAX:
 	default:
@@ -1778,7 +2375,7 @@ int gsihal_reg_init(enum gsi_ver gsi_ver)
 				* explicitly overridden register.
 				* Check validity
 				*/
-				if (!gsihal_reg_objs[i + 1][j].offset) {
+				if (j != GSI_GSI_CFG && !gsihal_reg_objs[i + 1][j].offset) {
 					GSIERR(
 						"reg=%s with zero offset gsi_ver=%d\n",
 						gsihal_reg_name_str(j), i + 1);
@@ -1802,10 +2399,40 @@ int gsihal_reg_init(enum gsi_ver gsi_ver)
 	return 0;
 }
 
+/*
+ * Check that ring length is valid
+ */
+bool gsihal_check_ring_length_valid(u32 r_len, u32 elem_size)
+{
+	if (gsihal_ctx->gsi_ver >= GSI_VER_3_0) {
+		if (r_len & ~GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK) {
+			GSIERR("bad params ring_len %u is out of bounds\n", r_len);
+			return false;
+		}
+		if (r_len / elem_size >= GSI_V3_0_MAX_ELEMENTS_PER_RING) {
+			GSIERR("bad params ring_len %u / re_size %u > 64k elements \n",
+				r_len, elem_size);
+			return false;
+		}
+	} else if (gsihal_ctx->gsi_ver >= GSI_VER_2_9) {
+		if (r_len & ~GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK) {
+			GSIERR("bad params ring_len %u is out of bounds\n", r_len);
+			return false;
+		}
+	} else {
+		if (r_len & ~GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK) {
+			GSIERR("bad params ring_len %u is out of bounds\n", r_len);
+			return false;
+		}
+	}
+
+	return true;
+}
+
 /*
  * Get mask for GP_int1
  */
 u32 gsihal_get_glob_irq_en_gp_int1_mask()
 {
 	return GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK;
-}
+}

+ 90 - 0
drivers/platform/msm/gsi/gsihal/gsihal_reg.h

@@ -43,6 +43,7 @@ enum gsihal_reg_name {
 	GSI_EE_n_GSI_HW_PARAM,
 	GSI_EE_n_GSI_HW_PARAM_0,
 	GSI_EE_n_GSI_HW_PARAM_2,
+	GSI_EE_n_GSI_HW_PARAM_4,
 	GSI_EE_n_GSI_SW_VERSION,
 	GSI_EE_n_CNTXT_INTSET,
 	GSI_EE_n_CNTXT_MSI_BASE_LSB,
@@ -72,10 +73,17 @@ enum gsihal_reg_name {
 	GSI_EE_n_GSI_CH_k_SCRATCH_1,
 	GSI_EE_n_GSI_CH_k_SCRATCH_2,
 	GSI_EE_n_GSI_CH_k_SCRATCH_3,
+	GSI_EE_n_GSI_CH_k_SCRATCH_4,
+	GSI_EE_n_GSI_CH_k_SCRATCH_5,
+	GSI_EE_n_GSI_CH_k_SCRATCH_6,
+	GSI_EE_n_GSI_CH_k_SCRATCH_7,
+	GSI_EE_n_GSI_CH_k_SCRATCH_8,
+	GSI_EE_n_GSI_CH_k_SCRATCH_9,
 	GSI_EE_n_GSI_CH_k_CNTXT_4,
 	GSI_EE_n_GSI_CH_k_CNTXT_5,
 	GSI_EE_n_GSI_CH_k_CNTXT_6,
 	GSI_EE_n_GSI_CH_k_CNTXT_7,
+	GSI_EE_n_GSI_CH_k_CNTXT_8,
 	GSI_EE_n_EV_CH_k_CNTXT_4,
 	GSI_EE_n_EV_CH_k_CNTXT_5,
 	GSI_EE_n_EV_CH_k_CNTXT_6,
@@ -129,6 +137,20 @@ enum gsihal_reg_name {
 	GSI_EE_n_GSI_CH_k_RE_FETCH_WRITE_PTR,
 	GSI_GSI_INST_RAM_n,
 	GSI_GSI_IRAM_PTR_MSI_DB,
+	GSI_GSI_IRAM_PTR_INT_NOTIFY_MCS,
+	GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_k,
+	GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_k,
+	GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_k,
+	GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_k,
+	GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_k,
+	GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_k,
+	GSI_EE_n_CNTXT_SRC_IEOB_IRQ_k,
+	GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_k,
+	GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_k,
+	GSI_INTER_EE_n_SRC_GSI_CH_IRQ_k,
+	GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_k,
+	GSI_INTER_EE_n_SRC_EV_CH_IRQ_k,
+	GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_k,
 	GSI_REG_MAX
 };
 
@@ -190,6 +212,11 @@ struct gsihal_reg_hw_param2 {
 	uint32_t gsi_iram_size;
 };
 
+struct gsihal_reg_hw_param4 {
+	uint32_t gsi_iram_protcol_cnt;
+	uint32_t gsi_num_ev_per_ee;
+};
+
 struct gsihal_reg_gsi_status {
 	uint8_t enabled;
 };
@@ -256,6 +283,7 @@ struct gsihal_reg_ee_n_gsi_ch_cmd {
 };
 
 struct gsihal_reg_gsi_ee_n_gsi_ch_k_qos {
+	uint32_t low_latency_en; //3.0
 	uint32_t db_in_bytes; //2.9
 	uint32_t empty_lvl_thrshold;
 	uint32_t prefetch_mode;
@@ -267,6 +295,7 @@ struct gsihal_reg_gsi_ee_n_gsi_ch_k_qos {
 
 struct gsihal_reg_ch_k_cntxt_1 {
 	uint32_t r_length;
+	uint32_t erindex;
 };
 
 struct gsihal_reg_gsi_cfg {
@@ -372,11 +401,72 @@ void gsihal_write_reg_fields(enum gsihal_reg_name reg, const void *fields);
  */
 u32 gsihal_read_reg_fields(enum gsihal_reg_name reg, void *fields);
 
+/*
+* gsihal_get_bit_map_array_size() - Get the size of the bit map
+*	array size according to the
+*	GSI version.
+*/
+u32 gsihal_get_bit_map_array_size(void);
+
+/*
+* gsihal_read_ch_reg() - Get the raw value of a ch reg
+*/
+u32 gsihal_read_ch_reg(enum gsihal_reg_name reg, u32 ch_num);
+
+/*
+ * gsihal_test_ch_bit() - return true if a ch bit is set
+ */
+bool gsihal_test_ch_bit(u32 reg_val, u32 ch_num);
+
+/*
+ * gsihal_get_ch_bit() - get ch bit set in the right offset
+ */
+u32 gsihal_get_ch_bit(u32 ch_num);
+
+/*
+ * gsihal_get_ch_reg_idx() - get ch reg index according to ch num
+ */
+u32 gsihal_get_ch_reg_idx(u32 ch_num);
+
+/*
+ * gsihal_get_ch_reg_mask() - get ch reg mask according to ch num
+ */
+u32 gsihal_get_ch_reg_mask(u32 ch_num);
+
+/*
+ * gsihal_get_ch_reg_offset() - Get the offset of a ch register according to
+ *	ch index
+ */
+u32 gsihal_get_ch_reg_offset(enum gsihal_reg_name reg, u32 ch_num);
+
+/*
+ * gsihal_get_ch_reg_n_offset() - Get the offset of a ch n register according
+ *	to ch index and n
+ */
+u32 gsihal_get_ch_reg_n_offset(enum gsihal_reg_name reg, u32 n, u32 ch_num);
+
+/*
+ * gsihal_write_ch_bit_map_reg_n() - Write mask to ch reg a raw value
+ */
+void gsihal_write_ch_bit_map_reg_n(enum gsihal_reg_name reg, u32 n, u32 ch_num,
+	u32 mask);
+
+/*
+ * gsihal_write_set_ch_bit_map_reg_n() - Set ch bit in reg a raw value
+ */
+void gsihal_write_set_ch_bit_map_reg_n(enum gsihal_reg_name reg, u32 n,
+	u32 ch_num);
+
 /*
  * Get the offset of a nk parameterized register
  */
 u32 gsihal_get_reg_nk_ofst(enum gsihal_reg_name reg, u32 n, u32 k);
 
+/*
+ * Check that ring length is valid
+ */
+bool gsihal_check_ring_length_valid(u32 r_len, u32 elem_size);
+
 /*
  * Get the offset of a n parameterized register
  */

+ 47 - 0
drivers/platform/msm/gsi/gsihal/gsihal_reg_i.h

@@ -21,6 +21,7 @@
 #define GSI_V2_5_GSI_INST_RAM_n_MAXn 8191
 #define GSI_V2_7_GSI_INST_RAM_n_MAXn 5119
 #define GSI_V2_9_GSI_INST_RAM_n_MAXn 6143
+#define GSI_V3_0_GSI_INST_RAM_n_MAXn 8255
 
 /* GSI_EE_n_CNTXT_TYPE_IRQ */
 #define GSI_EE_n_CNTXT_TYPE_IRQ_GENERAL_BMSK 0x40
@@ -57,6 +58,15 @@
 #define GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_BMSK 0x2000
 #define GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_SHFT 0xd
 
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHID_BMSK 0xff000
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHID_SHFT 0xc
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_EE_BMSK 0xf00
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_EE_SHFT 0x8
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_BMSK 0x80
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_SHFT 0x7
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_BMSK 0x7f
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_SHFT 0x0
+
 /* GSI_EE_n_EV_CH_k_CNTXT_0 */
 #define GSI_EE_n_EV_CH_k_CNTXT_0_ELEMENT_SIZE_BMSK 0xff000000
 #define GSI_EE_n_EV_CH_k_CNTXT_0_ELEMENT_SIZE_SHFT 0x18
@@ -71,6 +81,13 @@
 #define GSI_EE_n_EV_CH_k_CNTXT_0_CHTYPE_BMSK 0xf
 #define GSI_EE_n_EV_CH_k_CNTXT_0_CHTYPE_SHFT 0x0
 
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_EE_BMSK 0xf0000
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_EE_SHFT 0x10
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_INTYPE_BMSK 0x80
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_INTYPE_SHFT 0x7
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_CHTYPE_BMSK 0x7f
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_0_CHTYPE_SHFT 0x0
+
 /* GSI_EE_n_CNTXT_GLOB_IRQ_STTS */
 #define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_GP_INT3_BMSK 0x8
 #define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_GP_INT3_SHFT 0x3
@@ -171,6 +188,17 @@
 #define GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK 0x40000000
 #define GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_SHFT 0x1E
 
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_BMSK 0x1f00
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_SHFT 0x8
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK 0xff
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT 0x0
+
+/* GSI_EE_n_GSI_HW_PARAM_4 */
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_IRAM_PROTCOL_CNT_BMSK 0xff00
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_IRAM_PROTCOL_CNT_SHFT 0x8
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_NUM_EV_PER_EE_BMSK 0xff
+#define GSI_V3_0_EE_n_GSI_HW_PARAM_4_GSI_NUM_EV_PER_EE_SHFT 0x0
+
 /* GSI_EE_n_GSI_STATUS */
 #define GSI_EE_n_GSI_STATUS_ENABLED_BMSK 0x1
 #define GSI_EE_n_GSI_STATUS_ENABLED_SHFT 0x0
@@ -182,6 +210,9 @@
 #define GSI_V2_9_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK 0xfffff
 #define GSI_V2_9_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
 
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffffff
+#define GSI_V3_0_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
+
 /* GSI_EE_n_EV_CH_k_CNTXT_2 */
 #define GSI_EE_n_EV_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_BMSK 0xffffffff
 #define GSI_EE_n_EV_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_SHFT 0x0
@@ -247,6 +278,9 @@
 #define GSI_V2_9_EE_n_GSI_CH_k_QOS_DB_IN_BYTES_BMSK 0x1000000
 #define GSI_V2_9_EE_n_GSI_CH_k_QOS_DB_IN_BYTES_SHFT 0x18
 
+#define GSI_V3_0_EE_n_GSI_CH_k_QOS_LOW_LATENCY_EN_BMSK 0x2000000
+#define GSI_V3_0_EE_n_GSI_CH_k_QOS_LOW_LATENCY_EN_SHFT 0x19
+
 /* GSI_EE_n_GSI_CH_k_CNTXT_1 */
 #define GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffff
 #define GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
@@ -254,6 +288,14 @@
 #define GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK 0xfffff
 #define GSI_V2_9_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
 
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_ERINDEX_BMSK 0xff000000
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_ERINDEX_SHFT 0x18
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffffff
+#define GSI_V3_0_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0
+
+/* For GSI 3.0 each ring has maximum of 64 * 1024 elements */
+#define GSI_V3_0_MAX_ELEMENTS_PER_RING (65536)
+
 /* GSI_EE_n_GSI_CH_CMD */
 #define GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK 0xff000000
 #define GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT 0x18
@@ -285,6 +327,11 @@
 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x3c00
 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xa
 
+#define GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK 0x1fe0
+#define GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT 0x5
+#define GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x1e000
+#define GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xd
+
 /* GSI_EE_n_CNTXT_GSI_IRQ_EN */
 #define GSI_EE_n_CNTXT_GSI_IRQ_EN_GSI_MCS_STACK_OVRFLOW_BMSK 0x8
 #define GSI_EE_n_CNTXT_GSI_IRQ_EN_GSI_MCS_STACK_OVRFLOW_SHFT 0x3

+ 3 - 0
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -6050,6 +6050,9 @@ static enum gsi_ver ipa3_get_gsi_ver(enum ipa_hw_type ipa_hw_type)
 	case IPA_HW_v4_11:
 		gsi_ver = GSI_VER_2_11;
 		break;
+	case IPA_HW_v5_0:
+		gsi_ver = GSI_VER_3_0;
+		break;
 	default:
 		IPAERR("No GSI version for ipa type %d\n", ipa_hw_type);
 		WARN_ON(1);

+ 2 - 2
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -921,10 +921,10 @@ struct ipa3_wlan_comm_memb {
 };
 
 struct ipa_gsi_ep_mem_info {
-	u16 evt_ring_len;
+	u32 evt_ring_len;
 	u64 evt_ring_base_addr;
 	void *evt_ring_base_vaddr;
-	u16 chan_ring_len;
+	u32 chan_ring_len;
 	u64 chan_ring_base_addr;
 	void *chan_ring_base_vaddr;
 	u64 evt_ring_rp_addr;