summaryrefslogtreecommitdiff
path: root/gxp-internal.h
diff options
context:
space:
mode:
authorJohn Scheible <johnscheible@google.com>2021-10-26 13:45:19 -0700
committerJohn Scheible <johnscheible@google.com>2021-10-28 16:14:12 -0700
commitde16475969ca7dfaecf7144ece32b929cf193861 (patch)
tree962335a74133193541bf8c398a7cdf445f79a610 /gxp-internal.h
parent497cbdab5ea4f505beac7bb6d686bb4c3c504e8c (diff)
downloadgs201-de16475969ca7dfaecf7144ece32b929cf193861.tar.gz
gxp: First import from development branch
Squash at commit 48fe5786f1779890538d14f709b26063698c3711 Signed-off-by: John Scheible <johnscheible@google.com> Change-Id: I208434dddde40c08b9fc4d5da072ba10541992a2
Diffstat (limited to 'gxp-internal.h')
-rw-r--r--gxp-internal.h186
1 files changed, 186 insertions, 0 deletions
diff --git a/gxp-internal.h b/gxp-internal.h
new file mode 100644
index 0000000..1893108
--- /dev/null
+++ b/gxp-internal.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * GXP driver common internal definitions.
+ *
+ * Copyright (C) 2021 Google LLC
+ */
+#ifndef __GXP_INTERNAL_H__
+#define __GXP_INTERNAL_H__
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+
+#include "gxp-config.h"
+#include "gxp-tmp.h"
+
+/* Holds state belonging to a client */
+struct gxp_client {
+ struct gxp_dev *gxp;
+ void *app;
+ bool vd_allocated;
+};
+
+/* ioremapped resource */
+struct gxp_mapped_resource {
+ void __iomem *vaddr; /* starting virtual address */
+ phys_addr_t paddr; /* starting physical address */
+ dma_addr_t daddr; /* starting device address */
+ resource_size_t size; /* size in bytes */
+};
+
+struct mailbox_resp_list {
+ struct list_head list;
+ struct gxp_response *resp;
+};
+
+/* Structure to hold TPU device info */
+struct gxp_tpu_dev {
+ phys_addr_t mbx_paddr;
+};
+
+/* Forward declarations from submodules */
+struct gxp_mailbox_manager;
+struct gxp_debug_dump_manager;
+struct gxp_mapping_root;
+struct gxp_dma_manager;
+struct gxp_fw_data_manager;
+
+struct gxp_dev {
+ struct device *dev; /* platform bus device */
+ struct miscdevice misc_dev; /* misc device structure */
+ struct dentry *d_entry; /* debugfs dir for this device */
+ struct gxp_mapped_resource regs; /* ioremapped CSRs */
+ struct gxp_mapped_resource mbx[GXP_NUM_CORES]; /* mailbox CSRs */
+ struct gxp_mapped_resource fwbufs[GXP_NUM_CORES]; /* FW carveout */
+ struct gxp_mapped_resource fwdatabuf; /* Shared FW data carveout */
+ struct gxp_mapped_resource coredumpbuf; /* core dump carveout */
+ struct gxp_mailbox_manager *mailbox_mgr;
+ /*
+ * TODO(b/182416287): This should be a rb_tree of lists keyed by
+ * virtual device. For now, keep an array of one list per physical core
+ */
+ struct list_head mailbox_resp_queues[GXP_NUM_CORES];
+ wait_queue_head_t mailbox_resp_waitqs[GXP_NUM_CORES];
+ spinlock_t mailbox_resps_lock;
+ struct gxp_debug_dump_manager *debug_dump_mgr;
+ struct gxp_mapping_root *mappings; /* tree of user mappings */
+ u32 firmware_running; /* firmware status bitmap */
+ struct mutex vd_lock; /* synchronizes vd operations */
+ struct gxp_client *core_to_client[GXP_NUM_CORES];
+ struct gxp_client *debugfs_client;
+ struct gxp_dma_manager *dma_mgr;
+ struct gxp_fw_data_manager *data_mgr;
+ struct gxp_tpu_dev tpu_dev;
+};
+
+/* GXP device IO functions */
+
+static inline u32 gxp_read_32(struct gxp_dev *gxp, uint reg_offset)
+{
+ return readl(gxp->regs.vaddr + reg_offset);
+}
+
+static inline void gxp_write_32(struct gxp_dev *gxp, uint reg_offset, u32 value)
+{
+ writel(value, gxp->regs.vaddr + reg_offset);
+}
+
+static inline u32 gxp_read_32_core(struct gxp_dev *gxp, uint core,
+ uint reg_offset)
+{
+ uint offset = GXP_CORE_0_BASE + (GXP_CORE_SIZE * core) + reg_offset;
+
+ return gxp_read_32(gxp, offset);
+}
+
+static inline void gxp_write_32_core(struct gxp_dev *gxp, uint core,
+ uint reg_offset, u32 value)
+{
+ uint offset = GXP_CORE_0_BASE + (GXP_CORE_SIZE * core) + reg_offset;
+
+ gxp_write_32(gxp, offset, value);
+}
+
+static inline void gxp_acquire_sync_barrier(struct gxp_dev *gxp, uint index)
+{
+ uint barrier_reg_offset;
+
+ if (index >= SYNC_BARRIER_COUNT) {
+ dev_err(gxp->dev,
+ "Attempt to acquire non-existent sync barrier: %d\n",
+ index);
+ return;
+ }
+
+ barrier_reg_offset = SYNC_BARRIER_BLOCK + SYNC_BARRIER_BASE(index);
+ while (gxp_read_32(gxp, barrier_reg_offset) !=
+ SYNC_BARRIER_FREE_VALUE) {
+ /*
+ * Sleep for the minimum amount.
+ * msleep(1~20) may not do what the caller intends, and will
+ * often sleep longer (~20 ms actual sleep for any value given
+ * in the 1~20ms range).
+ */
+ msleep(20);
+ }
+}
+
+static inline void gxp_release_sync_barrier(struct gxp_dev *gxp, uint index)
+{
+ uint barrier_reg_offset;
+
+ if (index >= SYNC_BARRIER_COUNT) {
+ dev_err(gxp->dev,
+ "Attempt to acquire non-existent sync barrier: %d\n",
+ index);
+ return;
+ }
+
+ barrier_reg_offset = SYNC_BARRIER_BLOCK + SYNC_BARRIER_BASE(index);
+ gxp_write_32(gxp, barrier_reg_offset, 1);
+}
+static inline u32 gxp_read_sync_barrier_shadow(struct gxp_dev *gxp, uint index)
+{
+ uint barrier_reg_offset;
+
+ if (index >= SYNC_BARRIER_COUNT) {
+ dev_err(gxp->dev,
+ "Attempt to read non-existent sync barrier: %0u\n",
+ index);
+ return 0;
+ }
+
+ barrier_reg_offset = SYNC_BARRIER_BLOCK + SYNC_BARRIER_BASE(index) +
+ SYNC_BARRIER_SHADOW_OFFSET;
+
+ return gxp_read_32(gxp, barrier_reg_offset);
+}
+
+static inline int gxp_acquire_rmem_resource(struct gxp_dev *gxp,
+ struct resource *r, char *phandle)
+{
+ int ret;
+ struct device_node *np;
+
+ np = of_parse_phandle(gxp->dev->of_node, phandle, 0);
+ if (IS_ERR_OR_NULL(np)) {
+ dev_err(gxp->dev, "Failed to find \"%s\" reserved memory\n",
+ phandle);
+ return -ENODEV;
+ }
+
+ ret = of_address_to_resource(np, 0, r);
+ of_node_put(np);
+
+ return ret;
+}
+
+#endif /* __GXP_INTERNAL_H__ */