[RFC PATCH 03/11] VAS: Define helpers for access MMIO regions
Sukadev Bhattiprolu
sukadev at linux.vnet.ibm.com
Sat Nov 12 04:02:48 AEDT 2016
Define some helper functions to access the MMIO regions. We use these
in a follow-on patches to read/write VAS hardware registers. These
helpers are also used to later issue 'paste' instructions to submit
requests to the NX hardware engines.
Signed-off-by: Sukadev Bhattiprolu <sukadev at linux.vnet.ibm.com>
---
drivers/misc/vas/vas-window.c | 182 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 182 insertions(+)
diff --git a/drivers/misc/vas/vas-window.c b/drivers/misc/vas/vas-window.c
index 468f3bf..2c220a3 100644
--- a/drivers/misc/vas/vas-window.c
+++ b/drivers/misc/vas/vas-window.c
@@ -9,9 +9,191 @@
#include <linux/types.h>
#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/io.h>
#include <asm/vas.h>
#include "vas-internal.h"
+/*
+ * Using the node, chip and window id for the send winow identified by
+ * @window, compute and return the Power Bus address to which a sender
+ * could issue a paste instruction for this window.
+ *
+ * Refer to Tables 1.1 through 1.4 in Section 1.3.3.1 (Send Message w/Paste
+ * Commands (cl_rma_w)) of VAS P9 Workbook for the PowerBus Address usage
+ * in VAS.
+ *
+ * With 64K mode and Large SMP Mode the bits are used as follows:
+ *
+ * Bits Values Comments
+ * --------------------------------------
+ * 0:7 0b 0000_0000 Reserved
+ * 8:12 0b 0000_1 System id/Foreign Index 0:4
+ * 13:14 0b 00 Foreign Index 5:6
+ *
+ * 15:18 0 throuh 15 Node id (0 through 15)
+ * 19:21 0 through 7 Chip id (0 throuh 7)
+ * 22:23 0b 00 Unused, Foreign index 7:8
+ *
+ * 24:31 0b 0000_0000 RPN 0:7, Reserved
+ * 32:47 0 through 64K Send Window Id
+ * 48:51 0b 0000 Spare
+ *
+ * 52 0b 0 Reserved
+ * 53 0b 1 Report Enable (Set to 1 for NX).
+ * 54 0b 0 Reserved
+ *
+ * 55:56 0b 00 Snoop Bus
+ * 57:63 0b 0000_000 Reserved
+ *
+ * Except for a few bits, the small SMP mode computation is similar.
+ *
+ * TODO: Detect and compute address for small SMP mode.
+ *
+ * Example: For Node 0, Chip 0, Window id 4, Report Enable 1:
+ *
+ * Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7
+ * 00000000 00001000 00000000 00000000 00000000 00000100 00000100 00000000
+ * | | |
+ * +-------+-------+ v
+ * | Report Enable
+ * v
+ * Window id 4
+ *
+ * Thus, the paste address is 0x00080000_00040400.
+ */
+#define RMA_LSMP_64K_SYS_ID PPC_BITMASK(8, 12)
+#define RMA_LSMP_64K_NODE_ID PPC_BITMASK(15, 18)
+#define RMA_LSMP_64K_CHIP_ID PPC_BITMASK(19, 21)
+#define RMA_LSMP_64K_TX_WIN_ID PPC_BITMASK(32, 47)
+#define RMA_LSMP_REPORT_ENABLE PPC_BIT(53)
+
+uint64_t compute_paste_address(struct vas_window *window, int *size)
+{
+ int node, chip, winid;
+ uint64_t val = 0ULL;
+
+ node = window->vinst->node;
+ chip = window->vinst->chip;
+ winid = window->winid;
+
+ *size = PAGE_SIZE;
+
+ val = SET_FIELD(RMA_LSMP_64K_SYS_ID, val, 1);
+ val = SET_FIELD(RMA_LSMP_64K_NODE_ID, val, node);
+ val = SET_FIELD(RMA_LSMP_64K_CHIP_ID, val, chip);
+ val = SET_FIELD(RMA_LSMP_64K_TX_WIN_ID, val, winid);
+ val = SET_FIELD(RMA_LSMP_REPORT_ENABLE, val, 1);
+ pr_debug("%swin #%d: Paste address 0x%llx\n",
+ window->txwin ? "Tx" : "Rx", winid, val);
+ return val;
+}
+
+static void get_hvwc_mmio_bar(struct vas_window *window,
+ uint64_t *start, int *len)
+{
+ uint64_t pbaddr;
+ int instance;
+
+ instance = window->vinst->node * 8 + window->vinst->chip;
+ pbaddr = VAS_HVWC_MMIO_BAR_BASE + instance * VAS_HVWC_MMIO_BAR_SIZE;
+
+ *start = pbaddr + window->winid * VAS_HVWC_SIZE;
+ *len = VAS_HVWC_SIZE;
+}
+
+static void get_uwc_mmio_bar(struct vas_window *window,
+ uint64_t *start, int *len)
+{
+ uint64_t pbaddr;
+ int instance;
+
+ instance = window->vinst->node * 8 + window->vinst->chip;
+ pbaddr = VAS_UWC_MMIO_BAR_BASE + instance * VAS_UWC_MMIO_BAR_SIZE;
+
+ *start = pbaddr + window->winid * VAS_UWC_SIZE;
+ *len = VAS_UWC_SIZE;
+}
+
+static void *map_mmio_region(char *name, uint64_t start, int len)
+{
+ void *map;
+
+ if (!request_mem_region(start, len, name)) {
+ pr_devel("%s(): request_mem_region(0x%llx, %d) failed\n",
+ __func__, start, len);
+ return NULL;
+ }
+
+ map = __ioremap(start, len, pgprot_val(pgprot_cached(__pgprot(0))));
+ if (!map) {
+ pr_devel("%s(): ioremap(0x%llx, %d) failed\n", __func__, start,
+ len);
+ return NULL;
+ }
+
+ return map;
+}
+
+/*
+ * Unmap the MMIO regions for a window.
+ */
+void unmap_wc_mmio_bars(struct vas_window *window)
+{
+ int len;
+ uint64_t busaddr_start;
+
+ if (window->paste_kaddr) {
+ iounmap(window->paste_kaddr);
+ busaddr_start = compute_paste_address(window, &len);
+ pr_debug("Releasing pbaddr region [0x%llx, %d]\n",
+ busaddr_start, len);
+ release_mem_region((phys_addr_t)busaddr_start, len);
+ }
+
+ if (window->hvwc_map) {
+ iounmap(window->hvwc_map);
+ get_hvwc_mmio_bar(window, &busaddr_start, &len);
+ release_mem_region((phys_addr_t)busaddr_start, len);
+ }
+
+ if (window->uwc_map) {
+ iounmap(window->uwc_map);
+ get_uwc_mmio_bar(window, &busaddr_start, &len);
+ release_mem_region((phys_addr_t)busaddr_start, len);
+ }
+}
+
+/*
+ * Find the Hypervisor Window Context (HVWC) MMIO Base Address Region and the
+ * OS/User Window Context (UWC) MMIO Base Address Region for the given window.
+ * Map these bus addresses and save the mapped kernel addresses in @window.
+ */
+int map_wc_mmio_bars(struct vas_window *window)
+{
+ int len;
+ uint64_t start;
+
+ window->hvwc_map = window->uwc_map = NULL;
+
+ get_hvwc_mmio_bar(window, &start, &len);
+ window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
+
+ pr_debug("Win #%d: Map hvwc 0x%p -> [0x%llx,%d]\n", window->winid,
+ window->hvwc_map, start, len);
+
+ get_uwc_mmio_bar(window, &start, &len);
+ window->uwc_map = map_mmio_region("UWCM_Window", start, len);
+
+ pr_debug("Win #%d: Map uvwc 0x%p -> [0x%llx,%d]\n", window->winid,
+ window->uwc_map, start, len);
+
+ if (!window->hvwc_map || !window->uwc_map)
+ return -1;
+
+ return 0;
+}
+
/* stub for now */
int vas_window_reset(struct vas_instance *vinst, int winid)
{
--
1.8.3.1
More information about the Linuxppc-dev
mailing list