nb/intel/sandybridge: Use arrays to program IOSAV

Instead of programming subsequences one-by-one, we might as well take
the whole sequence as an array and program all subsequences in one go.

Since the number of subsequences is now known in advance, handling of
global state can be simplified, which allows reusing the last sequence.

Change-Id: Ica1b2b20e04ae368f10aa236ca24d12f69464430
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/47492
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c
index ebb9e44..204bc97 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.c
+++ b/src/northbridge/intel/sandybridge/raminit_common.c
@@ -533,9 +533,9 @@
 	/* Choose a populated rank */
 	slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
 
-	/* DRAM command ZQCS */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq sequence[] = {
+		/* DRAM command ZQCS */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command = IOSAV_ZQCS,
 			},
@@ -551,9 +551,9 @@
 				.bank    = 0,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/*
 	 * Execute command queue - why is bit 22 set here?!
@@ -641,9 +641,9 @@
 		val = (val & ~0x1f8) | ((val >> 1) & 0xa8) | ((val & 0xa8) << 1);
 	}
 
-	/* DRAM command MRS */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq sequence[] = {
+		/* DRAM command MRS */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command = IOSAV_MRS,
 			},
@@ -659,13 +659,9 @@
 				.bank    = reg,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command MRS */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command MRS */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_MRS,
 				.ranksel_ap = 1,
@@ -682,13 +678,9 @@
 				.bank    = reg,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command MRS */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command MRS */
+		[2] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_MRS,
 			},
@@ -704,9 +696,9 @@
 				.bank    = reg,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -831,9 +823,9 @@
 		}
 	}
 
-	/* DRAM command NOP (without ODT nor chip selects) */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq zqcl_sequence[] = {
+		/* DRAM command NOP (without ODT nor chip selects) */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_NOP & ~(0xff << 8),
 			},
@@ -849,13 +841,9 @@
 				.bank    = 0,
 				.rank    = 0,
 			},
-		};
-		iosav_write_ssq(BROADCAST_CH, &ssq);
-	}
-
-	/* DRAM command ZQCL */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command ZQCL */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_ZQCS,
 				.ranksel_ap = 1,
@@ -876,9 +864,9 @@
 				.inc_rank   = 1,
 				.addr_wrap  = 20,
 			},
-		};
-		iosav_write_ssq(BROADCAST_CH, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(BROADCAST_CH, zqcl_sequence, ARRAY_SIZE(zqcl_sequence));
 
 	/* Execute command queue on all channels. Do it four times. */
 	iosav_run_queue(BROADCAST_CH, 4, 0);
@@ -901,9 +889,9 @@
 		/* Drain */
 		wait_for_iosav(channel);
 
-		/* DRAM command ZQCS */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq zqcs_sequence[] = {
+			/* DRAM command ZQCS */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_ZQCS,
 				},
@@ -922,9 +910,9 @@
 				.addr_update = {
 					.addr_wrap  = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, zqcs_sequence, ARRAY_SIZE(zqcs_sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -1084,14 +1072,14 @@
 {
 	wait_for_iosav(channel);
 
-	/*
-	 * DRAM command MRS
-	 *
-	 * Write MR3 MPR enable.
-	 * In this mode only RD and RDA are allowed, and all reads return a predefined pattern.
-	 */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq sequence[] = {
+		/*
+		 * DRAM command MRS
+		 *
+		 * Write MR3 MPR enable. In this mode only RD and RDA
+		 * are allowed, and all reads return a predefined pattern.
+		 */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_MRS,
 				.ranksel_ap = 1,
@@ -1108,13 +1096,9 @@
 				.bank    = 3,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command RD */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command RD */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_RD,
 				.ranksel_ap = 1,
@@ -1131,13 +1115,9 @@
 				.bank    = 0,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command RD */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command RD */
+		[2] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_RD,
 				.ranksel_ap = 1,
@@ -1154,17 +1134,13 @@
 				.bank    = 0,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/*
-	 * DRAM command MRS
-	 *
-	 * Write MR3 MPR disable.
-	 */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/*
+		 * DRAM command MRS
+		 *
+		 * Write MR3 MPR disable.
+		 */
+		[3] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_MRS,
 				.ranksel_ap = 1,
@@ -1181,9 +1157,9 @@
 				.bank    = 3,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -1444,9 +1420,9 @@
 
 		wait_for_iosav(channel);
 
-		/* DRAM command PREA */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq sequence[] = {
+			/* DRAM command PREA */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_PRE,
 					.ranksel_ap = 1,
@@ -1463,9 +1439,9 @@
 					.bank    = 0,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -1561,9 +1537,9 @@
 
 	wait_for_iosav(channel);
 
-	/* DRAM command ACT */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq wr_sequence[] = {
+		/* DRAM command ACT */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_ACT,
 				.ranksel_ap = 1,
@@ -1584,13 +1560,9 @@
 				.inc_bank  = 1,
 				.addr_wrap = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command NOP */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command NOP */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_NOP,
 				.ranksel_ap = 1,
@@ -1610,13 +1582,9 @@
 			.addr_update = {
 				.addr_wrap = 31,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command WR */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command WR */
+		[2] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_WR,
 				.ranksel_ap = 1,
@@ -1637,13 +1605,9 @@
 				.inc_addr_8 = 1,
 				.addr_wrap  = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command NOP */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command NOP */
+		[3] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_NOP,
 				.ranksel_ap = 1,
@@ -1663,18 +1627,18 @@
 			.addr_update = {
 				.addr_wrap = 31,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, wr_sequence, ARRAY_SIZE(wr_sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
 
 	wait_for_iosav(channel);
 
-	/* DRAM command PREA */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq rd_sequence[] = {
+		/* DRAM command PREA */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_PRE,
 				.ranksel_ap = 1,
@@ -1694,13 +1658,9 @@
 			.addr_update = {
 				.addr_wrap = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command ACT */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command ACT */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_ACT,
 				.ranksel_ap = 1,
@@ -1721,13 +1681,9 @@
 				.inc_bank  = 1,
 				.addr_wrap = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command RD */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command RD */
+		[2] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_RD,
 				.ranksel_ap = 1,
@@ -1748,13 +1704,9 @@
 				.inc_addr_8 = 1,
 				.addr_wrap  = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command PREA */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command PREA */
+		[3] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_PRE,
 				.ranksel_ap = 1,
@@ -1774,9 +1726,9 @@
 			.addr_update = {
 				.addr_wrap  = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, rd_sequence, ARRAY_SIZE(rd_sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -1811,9 +1763,9 @@
 
 	wait_for_iosav(channel);
 
-	/* DRAM command PREA */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq sequence[] = {
+		/* DRAM command PREA */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_PRE,
 				.ranksel_ap = 1,
@@ -1833,9 +1785,9 @@
 			.addr_update = {
 				.addr_wrap  = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -1944,15 +1896,15 @@
 		FOR_ALL_POPULATED_RANKS {
 			wait_for_iosav(channel);
 
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR enable.
-			 * In this mode only RD and RDA are allowed,
-			 * and all reads return a predefined pattern.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+			const struct iosav_ssq sequence[] = {
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR enable.
+				 * In this mode only RD and RDA are allowed,
+				 * and all reads return a predefined pattern.
+				 */
+				[0] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -1969,13 +1921,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[1] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -1992,13 +1940,9 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[2] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -2015,17 +1959,13 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR disable.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR disable.
+				 */
+				[3] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -2042,9 +1982,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
+				},
+			};
+			iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 			/* Execute command queue */
 			iosav_run_once(channel);
@@ -2062,15 +2002,15 @@
 		FOR_ALL_POPULATED_RANKS {
 			wait_for_iosav(channel);
 
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR enable.
-			 * In this mode only RD and RDA are allowed,
-			 * and all reads return a predefined pattern.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+			const struct iosav_ssq sequence[] = {
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR enable.
+				 * In this mode only RD and RDA are allowed,
+				 * and all reads return a predefined pattern.
+				 */
+				[0] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -2087,13 +2027,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[1] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -2110,13 +2046,9 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[2] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -2133,17 +2065,13 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR disable.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR disable.
+				 */
+				[3] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -2160,9 +2088,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
+				},
+			};
+			iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 			/* Execute command queue */
 			iosav_run_once(channel);
@@ -2178,9 +2106,10 @@
 	write_mrreg(ctrl, channel, slotrank, 1, 0x80 | make_mr1(ctrl, slotrank, channel));
 
 	wait_for_iosav(channel);
-	/* DRAM command NOP */
-	{
-		const struct iosav_ssq ssq = {
+
+	const struct iosav_ssq sequence[] = {
+		/* DRAM command NOP */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_NOP,
 				.ranksel_ap = 1,
@@ -2197,13 +2126,9 @@
 				.bank    = 0,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command NOP */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command NOP */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_NOP_ALT,
 				.ranksel_ap = 1,
@@ -2220,9 +2145,9 @@
 				.bank    = 0,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -2320,9 +2245,9 @@
 
 		wait_for_iosav(channel);
 
-		/* DRAM command ACT */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq wr_sequence[] = {
+			/* DRAM command ACT */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_ACT,
 					.ranksel_ap = 1,
@@ -2339,13 +2264,9 @@
 					.bank    = 0,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command NOP */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command NOP */
+			[1] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_NOP,
 					.ranksel_ap = 1,
@@ -2365,13 +2286,9 @@
 				.addr_update = {
 					.addr_wrap = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command WR */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command WR */
+			[2] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_WR,
 					.ranksel_ap = 1,
@@ -2392,13 +2309,9 @@
 					.inc_addr_8 = 1,
 					.addr_wrap  = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command NOP */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command NOP */
+			[3] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_NOP,
 					.ranksel_ap = 1,
@@ -2418,18 +2331,18 @@
 				.addr_update = {
 					.addr_wrap = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, wr_sequence, ARRAY_SIZE(wr_sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
 
 		wait_for_iosav(channel);
 
-		/* DRAM command PREA */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq rd_sequence[] = {
+			/* DRAM command PREA */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_PRE,
 					.ranksel_ap = 1,
@@ -2449,13 +2362,9 @@
 				.addr_update = {
 					.addr_wrap = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command ACT */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command ACT */
+			[1] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_ACT,
 					.ranksel_ap = 1,
@@ -2472,13 +2381,9 @@
 					.bank    = 0,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command RD */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command RD */
+			[2] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_RD,
 					.ranksel_ap = 3,
@@ -2497,9 +2402,9 @@
 					.bank    = 0,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, rd_sequence, ARRAY_SIZE(rd_sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -2530,9 +2435,9 @@
 	/* choose an existing rank.  */
 	slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
 
-	/* DRAM command ZQCS */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq sequence[] = {
+		/* DRAM command ZQCS */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command = IOSAV_ZQCS,
 			},
@@ -2551,9 +2456,9 @@
 			.addr_update = {
 				.addr_wrap = 31,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -2627,9 +2532,9 @@
 		MCHBAR32(IOSAV_STATUS_ch(channel));
 		wait_for_iosav(channel);
 
-		/* DRAM command ZQCS */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq sequence[] = {
+			/* DRAM command ZQCS */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command = IOSAV_ZQCS,
 				},
@@ -2648,9 +2553,9 @@
 				.addr_update = {
 					.addr_wrap = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -2715,9 +2620,10 @@
 		MCHBAR32(IOSAV_DATA_CTL_ch(channel)) = 0x1f;
 
 		wait_for_iosav(channel);
-		/* DRAM command ACT */
-		{
-			const struct iosav_ssq ssq = {
+
+		const struct iosav_ssq sequence[] = {
+			/* DRAM command ACT */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_ACT,
 					.ranksel_ap = 1,
@@ -2738,13 +2644,9 @@
 					.inc_bank  = 1,
 					.addr_wrap = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command WR */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command WR */
+			[1] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_WR,
 					.ranksel_ap = 1,
@@ -2767,15 +2669,9 @@
 					.lfsr_upd   = 3,
 					.lfsr_xors  = 2,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-		/* FIXME: Hardcoded subsequence index */
-		MCHBAR32(IOSAV_n_ADDRESS_LFSR_ch(channel, 1)) = 0x389abcd;
-
-		/* DRAM command RD */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command RD */
+			[2] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_RD,
 					.ranksel_ap = 1,
@@ -2798,16 +2694,9 @@
 					.lfsr_upd   = 3,
 					.lfsr_xors  = 2,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* FIXME: Hardcoded subsequence index */
-		MCHBAR32(IOSAV_n_ADDRESS_LFSR_ch(channel, 2)) = 0x389abcd;
-
-		/* DRAM command PRE */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command PRE */
+			[3] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_PRE,
 					.ranksel_ap = 1,
@@ -2827,9 +2716,13 @@
 				.addr_update = {
 					.addr_wrap  = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
+
+		/* Program LFSR for the RD/WR subsequences */
+		MCHBAR32(IOSAV_n_ADDRESS_LFSR_ch(channel, 1)) = 0x389abcd;
+		MCHBAR32(IOSAV_n_ADDRESS_LFSR_ch(channel, 2)) = 0x389abcd;
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -2893,9 +2786,9 @@
 		/* Choose an existing rank */
 		slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
 
-		/* DRAM command ZQCS */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq sequence[] = {
+			/* DRAM command ZQCS */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command = IOSAV_ZQCS,
 				},
@@ -2914,9 +2807,9 @@
 				.addr_update = {
 					.addr_wrap  = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -2933,9 +2826,9 @@
 		/* choose an existing rank.  */
 		slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
 
-		/* DRAM command ZQCS */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq sequence[] = {
+			/* DRAM command ZQCS */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command = IOSAV_ZQCS,
 				},
@@ -2954,9 +2847,9 @@
 				.addr_update = {
 					.addr_wrap  = 31,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -3117,15 +3010,15 @@
 
 		wait_for_iosav(channel);
 
-		/*
-		 * DRAM command MRS
-		 *
-		 * Write MR3 MPR enable.
-		 * In this mode only RD and RDA are allowed,
-		 * and all reads return a predefined pattern.
-		 */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq sequence[] = {
+			/*
+			 * DRAM command MRS
+			 *
+			 * Write MR3 MPR enable.
+			 * In this mode only RD and RDA are allowed,
+			 * and all reads return a predefined pattern.
+			 */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_MRS,
 					.ranksel_ap = 1,
@@ -3142,13 +3035,9 @@
 					.bank    = 3,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command RD */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command RD */
+			[1] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_RD,
 					.ranksel_ap = 1,
@@ -3165,13 +3054,9 @@
 					.bank    = 0,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command RD */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command RD */
+			[2] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_RD,
 					.ranksel_ap = 1,
@@ -3188,17 +3073,13 @@
 					.bank    = 0,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/*
-		 * DRAM command MRS
-		 *
-		 * Write MR3 MPR disable.
-		 */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/*
+			 * DRAM command MRS
+			 *
+			 * Write MR3 MPR disable.
+			 */
+			[3] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_MRS,
 					.ranksel_ap = 1,
@@ -3215,9 +3096,9 @@
 					.bank    = 3,
 					.rank    = slotrank,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -3274,15 +3155,15 @@
 		FOR_ALL_POPULATED_RANKS {
 			wait_for_iosav(channel);
 
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR enable.
-			 * In this mode only RD and RDA are allowed,
-			 * and all reads return a predefined pattern.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+			const struct iosav_ssq sequence[] = {
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR enable.
+				 * In this mode only RD and RDA are allowed,
+				 * and all reads return a predefined pattern.
+				 */
+				[0] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -3299,13 +3180,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[1] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -3322,13 +3199,9 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[2] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -3345,17 +3218,13 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR disable.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR disable.
+				 */
+				[3] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -3372,9 +3241,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
+				},
+			};
+			iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 			/* Execute command queue */
 			iosav_run_once(channel);
@@ -3394,15 +3263,15 @@
 		FOR_ALL_POPULATED_RANKS {
 			wait_for_iosav(channel);
 
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR enable.
-			 * In this mode only RD and RDA are allowed,
-			 * and all reads return a predefined pattern.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+			const struct iosav_ssq sequence[] = {
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR enable.
+				 * In this mode only RD and RDA are allowed,
+				 * and all reads return a predefined pattern.
+				 */
+				[0] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -3419,13 +3288,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[1] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -3442,13 +3307,9 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/* DRAM command RD */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/* DRAM command RD */
+				[2] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_RD,
 						.ranksel_ap = 1,
@@ -3465,17 +3326,13 @@
 						.bank    = 0,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
-
-			/*
-			 * DRAM command MRS
-			 *
-			 * Write MR3 MPR disable.
-			 */
-			{
-				const struct iosav_ssq ssq = {
+				},
+				/*
+				 * DRAM command MRS
+				 *
+				 * Write MR3 MPR disable.
+				 */
+				[3] = {
 					.sp_cmd_ctrl = {
 						.command    = IOSAV_MRS,
 						.ranksel_ap = 1,
@@ -3492,9 +3349,9 @@
 						.bank    = 3,
 						.rank    = slotrank,
 					},
-				};
-				iosav_write_ssq(channel, &ssq);
-			}
+				},
+			};
+			iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 			/* Execute command queue */
 			iosav_run_once(channel);
@@ -3594,9 +3451,9 @@
 				}
 				wait_for_iosav(channel);
 
-				/* DRAM command ACT */
-				{
-					const struct iosav_ssq ssq = {
+				const struct iosav_ssq sequence[] = {
+					/* DRAM command ACT */
+					[0] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_ACT,
 							.ranksel_ap = 1,
@@ -3617,13 +3474,9 @@
 						.addr_update = {
 							.addr_wrap = 18,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
-
-				/* DRAM command WR */
-				{
-					const struct iosav_ssq ssq = {
+					},
+					/* DRAM command WR */
+					[1] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_WR,
 							.ranksel_ap = 1,
@@ -3645,13 +3498,9 @@
 							.inc_addr_8 = 1,
 							.addr_wrap  = 18,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
-
-				/* DRAM command RD */
-				{
-					const struct iosav_ssq ssq = {
+					},
+					/* DRAM command RD */
+					[2] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_RD,
 							.ranksel_ap = 1,
@@ -3672,13 +3521,9 @@
 							.inc_addr_8 = 1,
 							.addr_wrap  = 18,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
-
-				/* DRAM command PRE */
-				{
-					const struct iosav_ssq ssq = {
+					},
+					/* DRAM command PRE */
+					[3] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_PRE,
 							.ranksel_ap = 1,
@@ -3695,9 +3540,9 @@
 							.bank    = 0,
 							.rank    = slotrank,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
+					},
+				};
+				iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 				/* Execute command queue */
 				iosav_run_once(channel);
@@ -3795,9 +3640,9 @@
 {
 	wait_for_iosav(channel);
 
-	/* DRAM command ACT */
-	{
-		const struct iosav_ssq ssq = {
+	const struct iosav_ssq sequence[] = {
+		/* DRAM command ACT */
+		[0] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_ACT,
 				.ranksel_ap = 1,
@@ -3818,13 +3663,9 @@
 				.inc_bank  = 1,
 				.addr_wrap = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command WR */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command WR */
+		[1] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_WR,
 				.ranksel_ap = 1,
@@ -3845,13 +3686,9 @@
 				.inc_addr_8 = 1,
 				.addr_wrap  = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command RD */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command RD */
+		[2] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_RD,
 				.ranksel_ap = 1,
@@ -3872,13 +3709,9 @@
 				.inc_addr_8 = 1,
 				.addr_wrap  = 18,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
-
-	/* DRAM command PRE */
-	{
-		const struct iosav_ssq ssq = {
+		},
+		/* DRAM command PRE */
+		[3] = {
 			.sp_cmd_ctrl = {
 				.command    = IOSAV_PRE,
 				.ranksel_ap = 1,
@@ -3895,9 +3728,9 @@
 				.bank    = 0,
 				.rank    = slotrank,
 			},
-		};
-		iosav_write_ssq(channel, &ssq);
-	}
+		},
+	};
+	iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 	/* Execute command queue */
 	iosav_run_once(channel);
@@ -4073,9 +3906,9 @@
 		}
 		wait_for_iosav(channel);
 
-		/* DRAM command ACT */
-		{
-			const struct iosav_ssq ssq = {
+		const struct iosav_ssq sequence[] = {
+			/* DRAM command ACT */
+			[0] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_ACT,
 					.ranksel_ap = 1,
@@ -4096,13 +3929,9 @@
 					.inc_bank  = 1,
 					.addr_wrap = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command WR */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command WR */
+			[1] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_WR,
 					.ranksel_ap = 1,
@@ -4123,13 +3952,9 @@
 					.inc_addr_8 = 1,
 					.addr_wrap  = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command RD */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command RD */
+			[2] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_RD,
 					.ranksel_ap = 1,
@@ -4150,13 +3975,9 @@
 					.inc_addr_8 = 1,
 					.addr_wrap  = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
-
-		/* DRAM command PRE */
-		{
-			const struct iosav_ssq ssq = {
+			},
+			/* DRAM command PRE */
+			[3] = {
 				.sp_cmd_ctrl = {
 					.command    = IOSAV_PRE,
 					.ranksel_ap = 1,
@@ -4176,9 +3997,9 @@
 				.addr_update = {
 					.addr_wrap  = 18,
 				},
-			};
-			iosav_write_ssq(channel, &ssq);
-		}
+			},
+		};
+		iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 		/* Execute command queue */
 		iosav_run_once(channel);
@@ -4219,13 +4040,13 @@
 		for (bank = 0; bank < 8; bank++) {
 			for (row = 0; row < rowsize; row += 16) {
 
-				/*
-				 * DRAM command ACT
-				 *  Opens the row for writing.
-				 */
-				{
-					u8 gap = MAX((ctrl->tFAW >> 2) + 1, ctrl->tRRD);
-					const struct iosav_ssq ssq = {
+				u8 gap = MAX((ctrl->tFAW >> 2) + 1, ctrl->tRRD);
+				const struct iosav_ssq sequence[] = {
+					/*
+					 * DRAM command ACT
+					 *  Opens the row for writing.
+					 */
+					[0] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_ACT,
 							.ranksel_ap = 1,
@@ -4246,17 +4067,13 @@
 							.inc_addr_1 = 1,
 							.addr_wrap  = 18,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
-
-				/*
-				 * DRAM command WR
-				 *  Writes (128 + 1) * 8 (burst length) * 8 (bus width)
-				 *  bytes.
-				 */
-				{
-					const struct iosav_ssq ssq = {
+					},
+					/*
+					 * DRAM command WR
+					 *  Writes (128 + 1) * 8 (burst length) * 8 (bus width)
+					 *  bytes.
+					 */
+					[1] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_WR,
 							.ranksel_ap = 1,
@@ -4278,16 +4095,12 @@
 							.inc_addr_8 = 1,
 							.addr_wrap  = 9,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
-
-				/*
-				 * DRAM command PRE
-				 *  Closes the row.
-				 */
-				{
-					const struct iosav_ssq ssq = {
+					},
+					/*
+					 * DRAM command PRE
+					 *  Closes the row.
+					 */
+					[2] = {
 						.sp_cmd_ctrl = {
 							.command    = IOSAV_PRE,
 							.ranksel_ap = 1,
@@ -4307,9 +4120,9 @@
 						.addr_update = {
 							.addr_wrap  = 18,
 						},
-					};
-					iosav_write_ssq(channel, &ssq);
-				}
+					},
+				};
+				iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
 
 				/* Execute command queue */
 				iosav_run_queue(channel, 16, 0);
diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h
index 73c28bc..a8644ae 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.h
+++ b/src/northbridge/intel/sandybridge/raminit_common.h
@@ -98,7 +98,7 @@
 	} addr_update;
 };
 
-void iosav_write_ssq(const int ch, const struct iosav_ssq *ssq);
+void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length);
 void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer);
 void iosav_run_once(const int ch);
 void wait_for_iosav(int channel);
diff --git a/src/northbridge/intel/sandybridge/raminit_iosav.c b/src/northbridge/intel/sandybridge/raminit_iosav.c
index 9ab415a..d56ab7a 100644
--- a/src/northbridge/intel/sandybridge/raminit_iosav.c
+++ b/src/northbridge/intel/sandybridge/raminit_iosav.c
@@ -15,21 +15,25 @@
 /* Number of programmed IOSAV subsequences. */
 static unsigned int ssq_count = 0;
 
-void iosav_write_ssq(const int ch, const struct iosav_ssq *ssq)
+void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length)
 {
-	MCHBAR32(IOSAV_n_SP_CMD_CTRL_ch(ch, ssq_count)) = ssq->sp_cmd_ctrl.raw;
-	MCHBAR32(IOSAV_n_SUBSEQ_CTRL_ch(ch, ssq_count)) = ssq->subseq_ctrl.raw;
-	MCHBAR32(IOSAV_n_SP_CMD_ADDR_ch(ch, ssq_count)) = ssq->sp_cmd_addr.raw;
-	MCHBAR32(IOSAV_n_ADDR_UPDATE_ch(ch, ssq_count)) = ssq->addr_update.raw;
+	for (unsigned int i = 0; i < length; i++) {
+		MCHBAR32(IOSAV_n_SP_CMD_CTRL_ch(ch, i)) = seq[i].sp_cmd_ctrl.raw;
+		MCHBAR32(IOSAV_n_SUBSEQ_CTRL_ch(ch, i)) = seq[i].subseq_ctrl.raw;
+		MCHBAR32(IOSAV_n_SP_CMD_ADDR_ch(ch, i)) = seq[i].sp_cmd_addr.raw;
+		MCHBAR32(IOSAV_n_ADDR_UPDATE_ch(ch, i)) = seq[i].addr_update.raw;
+	}
 
-	ssq_count++;
+	ssq_count = length;
 }
 
 void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer)
 {
-	MCHBAR32(IOSAV_SEQ_CTL_ch(ch)) = loops | ((ssq_count - 1) << 18) | (as_timer << 22);
+	/* Should never happen */
+	if (ssq_count == 0)
+		return;
 
-	ssq_count = 0;
+	MCHBAR32(IOSAV_SEQ_CTL_ch(ch)) = loops | ((ssq_count - 1) << 18) | (as_timer << 22);
 }
 
 void iosav_run_once(const int ch)