aboutsummaryrefslogtreecommitdiff
path: root/hw/gx.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/gx.c')
-rw-r--r--hw/gx.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/hw/gx.c b/hw/gx.c
new file mode 100644
index 0000000..31de7b5
--- /dev/null
+++ b/hw/gx.c
@@ -0,0 +1,158 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <skiboot.h>
+#include <gx.h>
+#include <xscom.h>
+
+/*
+ * Note: This file os only used on P7/P7+
+ */
+
+/* Configuration of the PSI BUID, see the explanation in
+ * interrupts.h
+ */
+static int gx_p7_configure_psi_buid(uint32_t chip, uint32_t buid)
+{
+ uint64_t mode1;
+ int rc;
+
+ rc = xscom_read(chip, GX_P7_MODE1_REG, &mode1);
+ if (rc) {
+ prerror("GX: XSCOM error %d reading GX MODE1 REG\n", rc);
+ return rc;
+ }
+
+ mode1 = SETFIELD(GX_P7_MODE1_PSI_BUID, mode1, buid);
+ mode1 &= ~GX_P7_MODE1_PSI_BUID_DISABLE;
+
+ printf("GX: MODE1_REG set to 0x%llx\n", mode1);
+ rc = xscom_write(chip, GX_P7_MODE1_REG, mode1);
+ if (rc) {
+ prerror("GX: XSCOM error %d writing GX MODE1 REG\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int gx_p7p_configure_psi_buid(uint32_t chip, uint32_t buid)
+{
+ uint64_t mode4;
+ int rc;
+
+ rc = xscom_read(chip, GX_P7P_MODE4_REG, &mode4);
+ if (rc) {
+ prerror("GX: XSCOM error %d reading GX MODE1 REG\n", rc);
+ return rc;
+ }
+
+ mode4 = SETFIELD(GX_P7P_MODE4_PSI_BUID, mode4, buid);
+ mode4 &= ~GX_P7P_MODE4_PSI_BUID_DISABLE;
+
+ rc = xscom_write(chip, GX_P7P_MODE4_REG, mode4);
+ if (rc) {
+ prerror("GX: XSCOM error %d writing GX MODE1 REG\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+/* Configure the BUID of the PSI interrupt in the GX
+ * controller.
+ *
+ * @chip: Chip number (0..31)
+ * @buid: 9-bit BUID value
+ */
+int gx_configure_psi_buid(uint32_t chip, uint32_t buid)
+{
+ uint32_t pvr = mfspr(SPR_PVR);
+
+ printf("GX: PSI BUID for PVR %x (type %x) chip %d BUID 0x%x\n",
+ pvr, PVR_TYPE(pvr), chip, buid);
+
+ switch(PVR_TYPE(pvr)) {
+ case PVR_TYPE_P7:
+ return gx_p7_configure_psi_buid(chip, buid);
+ case PVR_TYPE_P7P:
+ return gx_p7p_configure_psi_buid(chip, buid);
+ }
+ return -1;
+}
+
+
+static int gx_p7_configure_tce_bar(uint32_t chip, uint32_t gx, uint64_t addr,
+ uint64_t size)
+{
+ uint32_t areg, mreg;
+ int rc;
+
+ switch (gx) {
+ case 0:
+ areg = GX_P7_GX0_TCE_BAR;
+ mreg = GX_P7_GX0_TCE_MASK;
+ break;
+ case 1:
+ areg = GX_P7_GX1_TCE_BAR;
+ mreg = GX_P7_GX1_TCE_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (addr) {
+ uint64_t taddr, tmask;
+
+ /* The address field contains bits 18 to 43 of the address */
+ taddr = SETFIELD(GX_P7_TCE_BAR_ADDR, 0ul,
+ (addr >> GX_P7_TCE_BAR_ADDR_SHIFT));
+ taddr |= GX_P7_TCE_BAR_ENABLE;
+ tmask = SETFIELD(GX_P7_TCE_MASK, 0ul,
+ ~((size - 1) >> GX_P7_TCE_BAR_ADDR_SHIFT));
+ rc = xscom_write(chip, areg, 0);
+ rc |= xscom_write(chip, mreg, tmask);
+ rc |= xscom_write(chip, areg, taddr);
+ } else {
+ rc = xscom_write(chip, areg, 0);
+ }
+ return rc ? -EIO : 0;
+}
+
+/* Configure the TCE BAR of a given GX bus
+ *
+ * @chip: Chip number (0..31)
+ * @gx : GX bus index
+ * @addr: base address of TCE table
+ * @size: size of TCE table
+ */
+int gx_configure_tce_bar(uint32_t chip, uint32_t gx, uint64_t addr,
+ uint64_t size)
+{
+ uint32_t pvr = mfspr(SPR_PVR);
+
+ printf("GX: TCE BAR for PVR %x (type %x) chip %d gx %d\n",
+ pvr, PVR_TYPE(pvr), chip, gx);
+
+ /* We only support P7... is there a P7+ with P5IOC2 ? */
+ switch(PVR_TYPE(pvr)) {
+ case PVR_TYPE_P7:
+ return gx_p7_configure_tce_bar(chip, gx, addr, size);
+ }
+ return -EINVAL;
+}
+
+