diff options
author | John Scheible <johnscheible@google.com> | 2021-10-26 13:45:19 -0700 |
---|---|---|
committer | John Scheible <johnscheible@google.com> | 2021-10-28 16:14:12 -0700 |
commit | de16475969ca7dfaecf7144ece32b929cf193861 (patch) | |
tree | 962335a74133193541bf8c398a7cdf445f79a610 /gxp-internal.h | |
parent | 497cbdab5ea4f505beac7bb6d686bb4c3c504e8c (diff) | |
download | gs201-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.h | 186 |
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__ */ |