[Skiboot] [PATCH v2 2/6] VAS: Initialize the basic VAS internal registers

Sukadev Bhattiprolu sukadev at linux.vnet.ibm.com
Wed Nov 23 13:00:44 AEDT 2016


Initialize the basic VAS internal registers that are needed for a
functioning VAS. Initializing VAS involves writing either pre-defined
values or allocated addresses to appropriate SCOM addresses.

Signed-off-by: Sukadev Bhattiprolu <sukadev at linux.vnet.ibm.com>
---
 core/vas.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 245 insertions(+), 1 deletion(-)

diff --git a/core/vas.c b/core/vas.c
index eefb40d..47556a0 100644
--- a/core/vas.c
+++ b/core/vas.c
@@ -13,8 +13,252 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <skiboot.h>
+#include <chip.h>
+#include <xscom.h>
 #include <vas.h>
 
-__attrconst void init_vas(void)
+/*
+ * TODO: Set to 64K after initial development.
+ */
+static int max_win_per_chip = 16;
+static int vas_initialized;
+
+static uint64_t get_hvwc_mmio_bar(const int chipid)
+{
+	return VAS_HVWC_MMIO_BAR_BASE + chipid * VAS_HVWC_MMIO_BAR_SIZE;
+}
+
+static uint64_t get_uwc_mmio_bar(int chipid)
+{
+	return VAS_UWC_MMIO_BAR_BASE + chipid * VAS_UWC_MMIO_BAR_SIZE;
+}
+
+static inline uint64_t compute_vas_scom_addr(uint64_t ring_sat_offset)
+{
+	return VAS_SCOM_BASE_ADDR + ring_sat_offset;
+}
+
+static int vas_scom_write(struct proc_chip *chip, uint64_t reg, uint64_t val)
+{
+	return xscom_write(chip->id, compute_vas_scom_addr(reg), val);
+}
+
+static inline int vas_scom_read(struct proc_chip *chip, uint64_t reg,
+			uint64_t *val)
+{
+	return xscom_read(chip->id, compute_vas_scom_addr(reg), val);
+}
+
+static int init_north_ctl(struct proc_chip *chip)
+{
+	uint64_t val = 0ULL;
+
+	val = SETFIELD(VAS_64K_MODE_MASK, val, VAS_64K_MODE);
+	val = SETFIELD(VAS_ACCEPT_PASTE_MASK, val, VAS_ACCEPT_PASTE);
+
+	return vas_scom_write(chip, VAS_MISC_N_CTL, val);
+}
+
+static int reset_north_ctl(struct proc_chip *chip)
+{
+	return vas_scom_write(chip, VAS_MISC_N_CTL, 0ULL);
+}
+
+static void reset_fir(struct proc_chip *chip)
+{
+	uint64_t val;
+
+	val = 0x0ULL;
+	vas_scom_write(chip, VAS_FIR0, val);
+	vas_scom_write(chip, VAS_FIR1, val);
+	vas_scom_write(chip, VAS_FIR2, val);
+	vas_scom_write(chip, VAS_FIR3, val);
+	vas_scom_write(chip, VAS_FIR4, val);
+	vas_scom_write(chip, VAS_FIR5, val);
+	vas_scom_write(chip, VAS_FIR6, val);
+	vas_scom_write(chip, VAS_FIR7, val);
+}
+
+/*
+ * Initialize RMA BAR and RMA Base Address Mask Register (BAMR) to their
+ * default values. This will cause VAS to accept paste commands to all
+ * chips in the system.
+ */
+static int init_rma(struct proc_chip *chip)
+{
+	int rc;
+	uint64_t val;
+
+	val = 0ULL;
+	val = SETFIELD(VAS_RMA_BAR_ADDR_MASK, val, 0x08000000000ULL);
+
+	rc = vas_scom_write(chip, VAS_RMA_BAR, val);
+	if (rc)
+		return rc;
+
+	val = 0ULL;
+	val = SETFIELD(VAS_RMA_BAMR_ADDR_MASK, val, 0xFFFC0000000ULL);
+
+	rc = vas_scom_write(chip, VAS_RMA_BAMR, val);
+
+	return rc;
+}
+
+/*
+ * Window Context MMIO (WCM) Region for each chip is assigned in the P9
+ * MMIO MAP spreadsheet. Write this value to the SCOM address associated
+ * with WCM_BAR.
+ */
+static int init_wcm(struct proc_chip *chip)
+{
+	uint64_t wcmbar;
+
+	wcmbar = get_hvwc_mmio_bar(chip->id);
+
+	/*
+	 * Write the entire WCMBAR address to the SCOM address. VAS will
+	 * extract bits that it thinks are relevant i.e bits 8..38
+	 */
+	return vas_scom_write(chip, VAS_WCM_BAR, wcmbar);
+}
+
+/*
+ * OS/User Window Context MMIO (UWCM) Region for each is assigned in the
+ * P9 MMIO MAP spreadsheet. Write this value to the SCOM address associated
+ * with UWCM_BAR.
+ */
+static int init_uwcm(struct proc_chip *chip)
+{
+	uint64_t uwcmbar;
+
+	uwcmbar = get_uwc_mmio_bar(chip->id);
+
+	/*
+	 * Write the entire UWCMBAR address to the SCOM address. VAS will
+	 * extract bits that it thinks are relevant i.e bits 8..35.
+	 */
+	return vas_scom_write(chip, VAS_UWCM_BAR, uwcmbar);
+}
+
+/*
+ * VAS needs a backing store for the 64K window contexts on a chip.
+ * (64K times 512 = 8MB). This region needs to be contiguous, so
+ * allocate during early boot. Then write the allocated address to
+ * the SCOM address for the Backing store BAR.
+ */
+static int init_wcbs(struct proc_chip *chip)
+{
+	uint64_t wcbs;
+	size_t size;
+
+	/* align to the backing store size */
+	size = (size_t)VAS_WCBS_SIZE;
+	wcbs = (uint64_t)local_alloc(chip->id, size, size);
+	if (!wcbs)
+		return -ENOMEM;
+
+	/*
+	 * Write entire WCBS_BAR address to the SCOM address. VAS will extract
+	 * relevant bits.
+	 */
+	return vas_scom_write(chip, VAS_WCBS_BAR, wcbs);
+}
+
+/*
+ * A VAS Window context is a 512-byte area made up of a set of 64-bit
+ * registers. But not all registers (eg: 0, 1, 7 etc) are valid and
+ * hence should not be written to.
+ *
+ * Use the following bitmask to identify valid offsets in the window
+ * context. Refer to Table 3.2 in the VAS workbook for list of valid
+ * offsets.
+ */
+uint64_t valid_wcm_mask = 0x00D71FFF13F7D77CULL;
+
+/*
+ * Init all registers in one window context
+ */
+static int init_one_window(struct proc_chip *chip, int idx)
 {
+	uint64_t wcmbar;
+	uint64_t *window_start;
+	int reg, nregs;
+
+	if (idx >= max_win_per_chip)
+		return -1;
+
+	wcmbar = get_hvwc_mmio_bar(chip->id);
+	window_start = (uint64_t *)wcmbar + idx * VAS_WC_SIZE;
+	nregs = VAS_WC_SIZE / sizeof(uint64_t);
+
+	for (reg = 0; reg < nregs; reg++) {
+		if (!((valid_wcm_mask >> reg) & 0x1))
+			continue;
+
+		*(window_start + reg) = 0x0ULL;
+	}
+
+	return 0;
+}
+
+static int init_windows(struct proc_chip *chip)
+{
+	int i, rc;
+
+	for (i = 0; i < max_win_per_chip; i++) {
+		rc = init_one_window(chip, i);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+static int init_one_chip(struct proc_chip *chip)
+{
+	if (init_wcbs(chip) || init_wcm(chip) || init_uwcm(chip))
+		return -1;
+
+	reset_fir(chip);
+
+	if (init_north_ctl(chip))
+		return -1;
+
+	if (init_rma(chip) || init_windows(chip))
+		goto out;
+
+	printf("VAS: Initialized chip %d\n", chip->id);
+	return 0;
+
+out:
+	reset_north_ctl(chip);
+	return -1;
+}
+
+void init_vas()
+{
+	int ct;
+	struct proc_chip *chip;
+
+	chip = next_chip(NULL);
+	ct = chip->type;
+
+	if (ct != PROC_CHIP_P9_CUMULUS && ct != PROC_CHIP_P9_NIMBUS)
+		return;
+
+	for_each_chip(chip) {
+		if (init_one_chip(chip))
+			goto cleanup;
+	}
+
+	vas_initialized = 1;
+	printf("VAS: Intialized\n");
+	return;
+
+cleanup:
+	/* ensure none of the chips accept paste instructions */
+	for_each_chip(chip)
+		reset_north_ctl(chip);
+	return;
 }
-- 
2.7.4



More information about the Skiboot mailing list