diff options
author | Nishant Prajapati <nishantpjpt@google.com> | 2021-05-06 10:11:14 +0530 |
---|---|---|
committer | Nishant Prajapati <nishantpjpt@google.com> | 2021-05-06 06:34:14 +0000 |
commit | dd8b3e9b13c82b85656aeba1eb42c378adbc4070 (patch) | |
tree | 15971a9d49ceaf9cf17f609745951ffbc1de4507 | |
parent | a7c17065c3886f8debb97cdff8bf509de94714ee (diff) | |
download | janeiro-dd8b3e9b13c82b85656aeba1eb42c378adbc4070.tar.gz |
Merge from 'pro' branch into android-gs-cloudripper-5.10
Squash at commit dab71c2cf
Signed-off-by: Nishant Prajapati <nishantpjpt@google.com>
Change-Id: I447031be5b6f89b3177a4c23aeca4676ffbb0076
27 files changed, 1121 insertions, 29 deletions
diff --git a/drivers/edgetpu/Kbuild b/drivers/edgetpu/Kbuild index f1e7f56..408ebae 100644 --- a/drivers/edgetpu/Kbuild +++ b/drivers/edgetpu/Kbuild @@ -1,4 +1,4 @@ -obj-m += abrolhos.o +obj-m += janeiro.o ccflags-y += -DCONFIG_EDGETPU_TELEMETRY_TRACE=1 -I$(src)/include # Use the absolute path of this Makefile to get the source directory. CURRENT_DIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST)))) @@ -12,16 +12,16 @@ endif edgetpu-fw-objs := edgetpu-firmware.o edgetpu-firmware-util.o edgetpu-shared-fw.o edgetpu-objs := edgetpu-mailbox.o edgetpu-kci.o edgetpu-telemetry.o edgetpu-mapping.o edgetpu-dmabuf.o edgetpu-async.o edgetpu-iremap-pool.o edgetpu-sw-watchdog.o $(edgetpu-fw-objs) -abrolhos-y := abrolhos-device.o abrolhos-device-group.o abrolhos-fs.o abrolhos-core.o abrolhos-platform.o abrolhos-firmware.o abrolhos-thermal.o abrolhos-pm.o abrolhos-iommu.o abrolhos-debug-dump.o abrolhos-usage-stats.o abrolhos-wakelock.o $(edgetpu-objs) -CFLAGS_abrolhos-fs.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-core.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-device.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-device-group.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-firmware.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-iommu.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-platform.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-pm.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-thermal.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-debug-dump.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-usage-stats.o := -DCONFIG_ABROLHOS=1 -CFLAGS_abrolhos-wakelock.o := -DCONFIG_ABROLHOS=1 +janeiro-y := janeiro-device.o janeiro-device-group.o janeiro-fs.o janeiro-core.o janeiro-platform.o janeiro-firmware.o janeiro-pm.o janeiro-debug-dump.o janeiro-usage-stats.o janeiro-iommu.o janeiro-wakelock.o $(edgetpu-objs) +CFLAGS_janeiro-fs.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-core.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-device.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-device-group.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-firmware.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-iommu.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-platform.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-pm.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-thermal.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-debug-dump.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-usage-stats.o := -DCONFIG_JANEIRO=1 +CFLAGS_janeiro-wakelock.o := -DCONFIG_JANEIRO=1 diff --git a/drivers/edgetpu/Kconfig b/drivers/edgetpu/Kconfig index fe40029..a035b30 100644 --- a/drivers/edgetpu/Kconfig +++ b/drivers/edgetpu/Kconfig @@ -21,6 +21,35 @@ config ABROLHOS To compile this driver as a module, choose M here. The module will be called "abrolhos". +config JANEIRO + tristate "Janeiro ML accelerator device driver" + depends on EDGETPU_FRAMEWORK + select PM + help + This driver supports the Janeiro device. Say Y if you want to + include this driver in the kernel. + + To compile this driver as a module, choose M here. The module + will be called "janeiro". + +config HERMOSA + tristate "Hermosa edgetpu ML accelerator direct host control driver" + depends on EDGETPU_FRAMEWORK + select INTERVAL_TREE if EDGETPU_DEVICE_DRAM + help + This driver supports the Hermosa device. Say Y if you want to + include this driver in the kernel. + + To compile this driver as a module, choose M here. The module + will be called "hermosa". + +config EDGETPU_DEVICE_DRAM + bool "EdgeTPU Device DRAM support" + depends on HERMOSA + default y + help + Say Y if the target device has the embedded device DRAM. + config EDGETPU_EXTERNAL_WRAPPER_CLASS bool "EdgeTPU add external wrapper class" depends on EDGETPU_FRAMEWORK @@ -51,4 +80,6 @@ config EDGETPU_TELEMETRY_TRACE It's fine to have this enabled even the firmware doesn't send tracing events. +source "drivers/edgetpu/unittests/Kconfig" + endmenu diff --git a/drivers/edgetpu/Makefile b/drivers/edgetpu/Makefile index b30f95f..89e3da3 100644 --- a/drivers/edgetpu/Makefile +++ b/drivers/edgetpu/Makefile @@ -3,7 +3,7 @@ # Makefile for EdgeTPU framework and dependent drivers. # -obj-$(CONFIG_ABROLHOS) += abrolhos.o +obj-$(CONFIG_JANEIRO) += janeiro.o GIT_PATH=$(srctree) ifeq ($(shell git --git-dir=$(GIT_PATH)/.git rev-parse --is-inside-work-tree),true) @@ -19,14 +19,11 @@ edgetpu-objs := edgetpu-async.o edgetpu-dmabuf.o edgetpu-iremap-pool.o \ edgetpu-sw-watchdog.o edgetpu-telemetry.o \ $(edgetpu-fw-objs) -abrolhos-objs := abrolhos-core.o abrolhos-debug-dump.o \ - abrolhos-device-group.o abrolhos-device.o \ - abrolhos-firmware.o abrolhos-fs.o abrolhos-iommu.o \ - abrolhos-platform.o abrolhos-pm.o abrolhos-thermal.o \ - abrolhos-usage-stats.o abrolhos-wakelock.o \ +janeiro-objs := janeiro-core.o janeiro-debug-dump.o janeiro-device-group.o \ + janeiro-device.o janeiro-firmware.o janeiro-fs.o \ + janeiro-iommu.o janeiro-platform.o janeiro-pm.o \ + janeiro-usage-stats.o janeiro-wakelock.o \ $(edgetpu-objs) -KBUILD_OPTIONS += CONFIG_ABROLHOS=m - modules modules_install clean: $(MAKE) -C $(KERNEL_SRC) M=$(M) W=1 $(KBUILD_OPTIONS) $(@) diff --git a/drivers/edgetpu/edgetpu-device-group.c b/drivers/edgetpu/edgetpu-device-group.c index ba13c85..29b84c7 100644 --- a/drivers/edgetpu/edgetpu-device-group.c +++ b/drivers/edgetpu/edgetpu-device-group.c @@ -455,7 +455,6 @@ static bool edgetpu_clients_groupable(const struct edgetpu_client *client1, { struct edgetpu_dev *etdev1 = client1->etdev, *etdev2 = client2->etdev; - /* TODO(b/159394046): perform more checks */ return etdev1->mcp_id == etdev2->mcp_id && etdev1->mcp_die_index != etdev2->mcp_die_index; } diff --git a/drivers/edgetpu/edgetpu-dmabuf.c b/drivers/edgetpu/edgetpu-dmabuf.c index f5c5a62..c2bf3ae 100644 --- a/drivers/edgetpu/edgetpu-dmabuf.c +++ b/drivers/edgetpu/edgetpu-dmabuf.c @@ -955,13 +955,15 @@ int edgetpu_sync_fence_signal(struct edgetpu_signal_sync_fence_data *datap) int errno; int ret; - fence = sync_file_get_fence(datap->fence); - if (!fence) - return -EINVAL; - errno = datap->error; if (errno > 0) errno = -errno; + if (errno < -MAX_ERRNO) + return -EINVAL; + + fence = sync_file_get_fence(datap->fence); + if (!fence) + return -EINVAL; spin_lock_irq(fence->lock); pr_debug("%s: %s-%s%llu-" SEQ_FMT " errno=%d\n", __func__, diff --git a/drivers/edgetpu/edgetpu-dram.h b/drivers/edgetpu/edgetpu-dram.h index 8df49e8..9e944c7 100644 --- a/drivers/edgetpu/edgetpu-dram.h +++ b/drivers/edgetpu/edgetpu-dram.h @@ -70,6 +70,9 @@ void edgetpu_device_dram_dmabuf_info_show(struct dma_buf *dmabuf, /* Return amount of on-device DRAM currently used in bytes. */ size_t edgetpu_device_dram_used(struct edgetpu_dev *etdev); +/* Return the amount of free device dram in bytes */ +size_t edgetpu_device_dram_available(struct edgetpu_dev *etdev); + #else /* !CONFIG_EDGETPU_DEVICE_DRAM */ static inline int edgetpu_device_dram_init(struct edgetpu_dev *etdev) @@ -127,6 +130,11 @@ static inline size_t edgetpu_device_dram_used(struct edgetpu_dev *etdev) { return 0; } + +static inline size_t edgetpu_device_dram_available(struct edgetpu_dev *etdev) +{ + return 0; +} #endif /* CONFIG_EDGETPU_DEVICE_DRAM */ #endif /* __EDGETPU_DRAM_H__ */ diff --git a/drivers/edgetpu/edgetpu-fs.c b/drivers/edgetpu/edgetpu-fs.c index 3966226..b74a91b 100644 --- a/drivers/edgetpu/edgetpu-fs.c +++ b/drivers/edgetpu/edgetpu-fs.c @@ -620,6 +620,19 @@ error_release: return ret; } +static int +edgetpu_ioctl_dram_usage(struct edgetpu_dev *etdev, + struct edgetpu_device_dram_usage __user *argp) +{ + struct edgetpu_device_dram_usage dram; + + dram.allocated = edgetpu_device_dram_used(etdev); + dram.available = edgetpu_device_dram_available(etdev); + if (copy_to_user(argp, &dram, sizeof(*argp))) + return -EFAULT; + return 0; +} + long edgetpu_ioctl(struct file *file, uint cmd, ulong arg) { struct edgetpu_client *client = file->private_data; @@ -699,6 +712,9 @@ long edgetpu_ioctl(struct file *file, uint cmd, ulong arg) case EDGETPU_GET_TPU_TIMESTAMP: ret = edgetpu_ioctl_tpu_timestamp(client, argp); break; + case EDGETPU_GET_DRAM_USAGE: + ret = edgetpu_ioctl_dram_usage(client->etdev, argp); + break; default: return -ENOTTY; /* unknown command */ } diff --git a/drivers/edgetpu/edgetpu-kci.c b/drivers/edgetpu/edgetpu-kci.c index c8b5d86..2f0d2e3 100644 --- a/drivers/edgetpu/edgetpu-kci.c +++ b/drivers/edgetpu/edgetpu-kci.c @@ -662,8 +662,8 @@ static int edgetpu_kci_send_cmd_return_resp( return -ETIMEDOUT; } if (resp->status != KCI_STATUS_OK) { - etdev_dbg(kci->mailbox->etdev, "%s: resp status=%u", __func__, - resp->status); + etdev_err(kci->mailbox->etdev, "KCI cmd %u response status %u", + cmd->code, resp->status); return -ENOMSG; } diff --git a/drivers/edgetpu/edgetpu.h b/drivers/edgetpu/edgetpu.h index c382581..6455d5f 100644 --- a/drivers/edgetpu/edgetpu.h +++ b/drivers/edgetpu/edgetpu.h @@ -458,4 +458,22 @@ struct edgetpu_fw_version { #define EDGETPU_GET_TPU_TIMESTAMP \ _IOR(EDGETPU_IOCTL_BASE, 28, __u64) +/* + * struct edgetpu_device_dram_usage + * @allocated: size of allocated dram in bytes + * @available: size of free device dram in bytes + */ +struct edgetpu_device_dram_usage { + __u64 allocated; + __u64 available; +}; + +/* + * Query the allocated and free device DRAM. + * + * @available and @allocated are set to 0 for chips without a device DRAM. + */ +#define EDGETPU_GET_DRAM_USAGE \ + _IOR(EDGETPU_IOCTL_BASE, 29, struct edgetpu_device_dram_usage) + #endif /* __EDGETPU_H__ */ diff --git a/drivers/edgetpu/include/linux/platform_data/sscoredump.h b/drivers/edgetpu/include/linux/platform_data/sscoredump.h new file mode 100644 index 0000000..fee2872 --- /dev/null +++ b/drivers/edgetpu/include/linux/platform_data/sscoredump.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __SUBSYSTEM_COREDUMP_H +#define __SUBSYSTEM_COREDUMP_H + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/platform_device.h> + +#define SSCD_NAME "sscoredump" + +/* sscd segment ( similar to ELF memory segments) */ +struct sscd_segment { + void *addr; + u64 size; + u64 flags; + + /* passed to elf sprogram header */ + void *paddr; + void *vaddr; +} __packed; + +/* sscd_report flags */ +#define SSCD_FLAGS_ELFARM32HDR 0x0001 +#define SSCD_FLAGS_ELFARM64HDR 0x0002 + + +struct sscd_platform_data { + /* report crash */ + int (*sscd_report)(struct platform_device *pdev, + struct sscd_segment *segs, int nsegs, + u64 flags, const char *crash_info); +}; + +#endif /* __SUBSYSTEM_COREDUMP_H */ diff --git a/drivers/edgetpu/janeiro-core.c b/drivers/edgetpu/janeiro-core.c new file mode 100644 index 0000000..02cf784 --- /dev/null +++ b/drivers/edgetpu/janeiro-core.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-core.c" diff --git a/drivers/edgetpu/janeiro-debug-dump.c b/drivers/edgetpu/janeiro-debug-dump.c new file mode 100644 index 0000000..d38d7e6 --- /dev/null +++ b/drivers/edgetpu/janeiro-debug-dump.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-debug-dump.c" + +int edgetpu_debug_dump_init(struct edgetpu_dev *etdev) +{ + return 0; +} + +void edgetpu_debug_dump_exit(struct edgetpu_dev *etdev) +{ +} diff --git a/drivers/edgetpu/janeiro-device-group.c b/drivers/edgetpu/janeiro-device-group.c new file mode 100644 index 0000000..d918348 --- /dev/null +++ b/drivers/edgetpu/janeiro-device-group.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-device-group.c" diff --git a/drivers/edgetpu/janeiro-device.c b/drivers/edgetpu/janeiro-device.c new file mode 100644 index 0000000..7deca91 --- /dev/null +++ b/drivers/edgetpu/janeiro-device.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Janeiro Edge TPU ML accelerator device host support. + * + * Copyright (C) 2020 Google, Inc. + */ + +#include <linux/irqreturn.h> + +#include "edgetpu-config.h" +#include "edgetpu-internal.h" +#include "edgetpu-mailbox.h" +#include "edgetpu-telemetry.h" +#include "janeiro-platform.h" + +static irqreturn_t janeiro_mailbox_handle_irq(struct edgetpu_dev *etdev, + int irq) +{ + struct edgetpu_mailbox *mailbox; + struct edgetpu_mailbox_manager *mgr = etdev->mailbox_manager; + uint i; + struct janeiro_platform_dev *jpdev = to_janeiro_dev(etdev); + + if (!mgr) + return IRQ_NONE; + for (i = 0; i < EDGETPU_NCONTEXTS; i++) + if (jpdev->irq[i] == irq) + break; + if (i == EDGETPU_NCONTEXTS) + return IRQ_NONE; + read_lock(&mgr->mailboxes_lock); + mailbox = mgr->mailboxes[i]; + if (!mailbox) + goto out; + if (!EDGETPU_MAILBOX_RESP_QUEUE_READ(mailbox, doorbell_status)) + goto out; + EDGETPU_MAILBOX_RESP_QUEUE_WRITE(mailbox, doorbell_clear, 1); + etdev_dbg(mgr->etdev, "mbox %u resp doorbell irq tail=%u\n", i, + EDGETPU_MAILBOX_RESP_QUEUE_READ(mailbox, tail)); + if (mailbox->handle_irq) + mailbox->handle_irq(mailbox); +out: + read_unlock(&mgr->mailboxes_lock); + return IRQ_HANDLED; +} + +irqreturn_t edgetpu_chip_irq_handler(int irq, void *arg) +{ + struct edgetpu_dev *etdev = arg; + + edgetpu_telemetry_irq_handler(etdev); + /* + * use this as HOST_NONSECURE_INT_SRC_STATUS_REG not present in + * Janeiro. + */ + return janeiro_mailbox_handle_irq(etdev, irq); +} + +u64 edgetpu_chip_tpu_timestamp(struct edgetpu_dev *etdev) +{ + return edgetpu_dev_read_64(etdev, EDGETPU_REG_CPUNS_TIMESTAMP); +} + +void edgetpu_chip_init(struct edgetpu_dev *etdev) +{ +} + +void edgetpu_chip_exit(struct edgetpu_dev *etdev) +{ +} + +void edgetpu_mark_probe_fail(struct edgetpu_dev *etdev) +{ +} + +struct edgetpu_dumpregs_range edgetpu_chip_statusregs_ranges[] = { +}; +int edgetpu_chip_statusregs_nranges = + ARRAY_SIZE(edgetpu_chip_statusregs_ranges); + +struct edgetpu_dumpregs_range edgetpu_chip_tile_statusregs_ranges[] = { +}; +int edgetpu_chip_tile_statusregs_nranges = + ARRAY_SIZE(edgetpu_chip_tile_statusregs_ranges); + +void edgetpu_chip_handle_reverse_kci(struct edgetpu_dev *etdev, + struct edgetpu_kci_response_element *resp) +{ + etdev_warn(etdev, "%s: Unrecognized KCI request: %u\n", __func__, + resp->code); +} diff --git a/drivers/edgetpu/janeiro-firmware.c b/drivers/edgetpu/janeiro-firmware.c new file mode 100644 index 0000000..07f4f00 --- /dev/null +++ b/drivers/edgetpu/janeiro-firmware.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Janeiro Edge TPU ML accelerator firmware download support. + * + * Copyright (C) 2020 Google, Inc. + */ + +#include <linux/dma-mapping.h> +#include <linux/sizes.h> +#include <linux/slab.h> + +#include <linux/iommu.h> + +#include "edgetpu-config.h" +#include "edgetpu-firmware.h" +#include "edgetpu-internal.h" +#include "edgetpu-mmu.h" +#include "edgetpu-kci.h" +#include "edgetpu-mailbox.h" +#include "janeiro-platform.h" +#include "mobile-firmware.h" + +/* + * Sets the reset state of the R52 core. + * @val: 1 to put the core in reset state, 0 to release core from reset state. + */ +static void r52_reset(struct edgetpu_dev *etdev, u64 val) +{ + edgetpu_dev_write_32_sync(etdev, EDGETPU_REG_RESET_CONTROL, val); +} + +static void janeiro_firmware_before_destroy(struct edgetpu_firmware *et_fw) +{ + r52_reset(et_fw->etdev, 1); +} + +static int janeiro_firmware_alloc_buffer(struct edgetpu_firmware *et_fw, + struct edgetpu_firmware_buffer *fw_buf) +{ + struct edgetpu_dev *etdev = et_fw->etdev; + struct janeiro_platform_dev *edgetpu_pdev = + container_of(etdev, struct janeiro_platform_dev, edgetpu_dev); + /* Allocate extra space for the image header */ + size_t buffer_size = + edgetpu_pdev->fw_region_size + MOBILE_FW_HEADER_SIZE; + + fw_buf->vaddr = kzalloc(buffer_size, GFP_KERNEL); + if (!fw_buf->vaddr) { + etdev_err(etdev, "%s: failed to allocate buffer (%zu bytes)\n", + __func__, buffer_size); + return -ENOMEM; + } + fw_buf->dma_addr = 0; + fw_buf->alloc_size = buffer_size; + fw_buf->used_size_align = 16; + return 0; +} + +static void janeiro_firmware_free_buffer(struct edgetpu_firmware *et_fw, + struct edgetpu_firmware_buffer *fw_buf) +{ + kfree(fw_buf->vaddr); + fw_buf->vaddr = NULL; + fw_buf->alloc_size = 0; + fw_buf->used_size_align = 0; +} + +static int janeiro_firmware_setup_buffer(struct edgetpu_firmware *et_fw, + struct edgetpu_firmware_buffer *fw_buf) +{ + int ret = 0; + void *image_vaddr; + struct mobile_image_config *image_config; + struct edgetpu_dev *etdev = et_fw->etdev; + struct janeiro_platform_dev *edgetpu_pdev = + container_of(etdev, struct janeiro_platform_dev, edgetpu_dev); + + if (fw_buf->used_size < MOBILE_FW_HEADER_SIZE) { + etdev_err(etdev, "Invalid buffer size: %zu < %d\n", + fw_buf->used_size, MOBILE_FW_HEADER_SIZE); + return -EINVAL; + } + + image_vaddr = memremap(edgetpu_pdev->fw_region_paddr, + edgetpu_pdev->fw_region_size, MEMREMAP_WC); + if (!image_vaddr) { + etdev_err(etdev, "memremap failed\n"); + return -ENOMEM; + } + + /* fetch the firmware versions */ + image_config = fw_buf->vaddr + MOBILE_IMAGE_CONFIG_OFFSET; + memcpy(&etdev->fw_version, &image_config->firmware_versions, + sizeof(etdev->fw_version)); + + /* Skip the header */ + memcpy(image_vaddr, fw_buf->vaddr + MOBILE_FW_HEADER_SIZE, + fw_buf->used_size - MOBILE_FW_HEADER_SIZE); + + return ret; +} + +static void +janeiro_firmware_teardown_buffer(struct edgetpu_firmware *et_fw, + struct edgetpu_firmware_buffer *fw_buf) +{ +} + +static int janeiro_firmware_prepare_run(struct edgetpu_firmware *et_fw, + struct edgetpu_firmware_buffer *fw_buf) +{ + struct edgetpu_dev *etdev = et_fw->etdev; + struct janeiro_platform_dev *edgetpu_pdev = + container_of(etdev, struct janeiro_platform_dev, edgetpu_dev); + dma_addr_t fw_dma_addr; + int ret = 0; + + fw_dma_addr = edgetpu_pdev->fw_region_paddr; + + //TODO: enable as and when sysmmu started working correctly on hybrid + //platform +#if 0 + /* Clear Substream ID (aka SCID) for instruction remapped addresses */ + u32 sec_reg = edgetpu_dev_read_32( + etdev, EDGETPU_REG_INSTRUCTION_REMAP_SECURITY); + sec_reg &= ~(0x0F << 16); + edgetpu_dev_write_32(etdev, EDGETPU_REG_INSTRUCTION_REMAP_SECURITY, + sec_reg); + + /* Clear Substream ID (aka SCID) for all other addresses */ + sec_reg = edgetpu_dev_read_32(etdev, EDGETPU_REG_SECURITY); + sec_reg &= ~(0x0F << 16); + edgetpu_dev_write_32(etdev, EDGETPU_REG_SECURITY, sec_reg); +// dma_sync_single_for_device(etdev->dev, fw_dma_addr, +// fw_buf->used_size - JANEIRO_FW_HEADER_SIZE, +// DMA_TO_DEVICE); +#endif + r52_reset(etdev, 1); + + /* Reset KCI mailbox before starting f/w, don't process anything old.*/ + edgetpu_mailbox_reset(etdev->kci->mailbox); + + /* Remap TPU CPU instructions to the carveout IOVA. */ + edgetpu_dev_write_32(etdev, EDGETPU_REG_INSTRUCTION_REMAP_NEW_BASE, + /*FW_IOVA*/ fw_dma_addr); + edgetpu_dev_write_32(etdev, EDGETPU_REG_INSTRUCTION_REMAP_CONTROL, 1); + r52_reset(etdev, 0); + //TODO: cleanup + return ret; +} + +static const struct edgetpu_firmware_handlers janeiro_firmware_handlers = { + .before_destroy = janeiro_firmware_before_destroy, + .alloc_buffer = janeiro_firmware_alloc_buffer, + .free_buffer = janeiro_firmware_free_buffer, + .setup_buffer = janeiro_firmware_setup_buffer, + .teardown_buffer = janeiro_firmware_teardown_buffer, + .prepare_run = janeiro_firmware_prepare_run, +}; + +int mobile_edgetpu_firmware_create(struct edgetpu_dev *etdev) +{ + return edgetpu_firmware_create(etdev, &janeiro_firmware_handlers); +} + +void mobile_edgetpu_firmware_destroy(struct edgetpu_dev *etdev) +{ + edgetpu_firmware_destroy(etdev); +} + +int edgetpu_chip_firmware_run(struct edgetpu_dev *etdev, const char *name, + enum edgetpu_firmware_flags flags) +{ + return edgetpu_firmware_run(etdev, name, flags); +} + +unsigned long edgetpu_chip_firmware_iova(struct edgetpu_dev *etdev) +{ + /* + * There is no IOVA in Janeiro, since firmware the IOMMU is + * bypassed and the only translation in effect is the one + * done by instruction remap registers + */ + return EDGETPU_INSTRUCTION_REMAP_BASE; +} diff --git a/drivers/edgetpu/janeiro-fs.c b/drivers/edgetpu/janeiro-fs.c new file mode 100644 index 0000000..5babc06 --- /dev/null +++ b/drivers/edgetpu/janeiro-fs.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-fs.c" diff --git a/drivers/edgetpu/janeiro-iommu.c b/drivers/edgetpu/janeiro-iommu.c new file mode 100644 index 0000000..52ce973 --- /dev/null +++ b/drivers/edgetpu/janeiro-iommu.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-google-iommu.c" diff --git a/drivers/edgetpu/janeiro-platform.c b/drivers/edgetpu/janeiro-platform.c new file mode 100644 index 0000000..9b64972 --- /dev/null +++ b/drivers/edgetpu/janeiro-platform.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Janeiro platform device driver for the Google Edge TPU ML accelerator. + * + * Copyright (C) 2020 Google, Inc. + */ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/iopoll.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include "edgetpu-config.h" +#include "edgetpu-firmware.h" +#include "edgetpu-internal.h" +#include "edgetpu-iremap-pool.h" +#include "edgetpu-mmu.h" +#include "edgetpu-telemetry.h" +#include "janeiro-platform.h" +#include "janeiro-pm.h" +#include "mobile-firmware.h" + +static const struct of_device_id edgetpu_of_match[] = { + { + .compatible = "google,darwinn", + }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, edgetpu_of_match); + +#define EDGETPU_POOL_MEM_OFFSET (EDGETPU_TELEMETRY_BUFFER_SIZE * 2) + +static void janeiro_get_telemetry_mem(struct janeiro_platform_dev *etpdev, + enum edgetpu_telemetry_type type, + struct edgetpu_coherent_mem *mem) +{ + int offset = type == EDGETPU_TELEMETRY_TRACE ? + EDGETPU_TELEMETRY_BUFFER_SIZE : + 0; + mem->vaddr = etpdev->shared_mem_vaddr + offset; + mem->dma_addr = EDGETPU_REMAPPED_DATA_ADDR + offset; + mem->tpu_addr = EDGETPU_REMAPPED_DATA_ADDR + offset; + mem->host_addr = 0; + mem->size = EDGETPU_TELEMETRY_BUFFER_SIZE; +} + +static int janeiro_platform_setup_fw_region(struct janeiro_platform_dev *etpdev) +{ + struct edgetpu_dev *etdev = &etpdev->edgetpu_dev; + struct device *dev = etdev->dev; + struct resource r; + struct device_node *np; + int err; + size_t region_map_size = + EDGETPU_FW_SIZE_MAX + EDGETPU_REMAPPED_DATA_SIZE; + + np = of_parse_phandle(dev->of_node, "memory-region", 0); + if (!np) { + dev_err(dev, "No memory region for firmware\n"); + return -ENODEV; + } + + err = of_address_to_resource(np, 0, &r); + of_node_put(np); + if (err) { + dev_err(dev, "No memory address assigned to firmware region\n"); + return err; + } + + if (resource_size(&r) < region_map_size) { + dev_err(dev, + "Memory region for firmware too small (%zu bytes needed, got %llu)\n", + region_map_size, resource_size(&r)); + return -ENOSPC; + } + + etpdev->fw_region_paddr = r.start; + etpdev->fw_region_size = EDGETPU_FW_SIZE_MAX; + + etpdev->shared_mem_vaddr = + memremap(r.start + EDGETPU_REMAPPED_DATA_OFFSET, + EDGETPU_REMAPPED_DATA_SIZE, MEMREMAP_WC); + if (!etpdev->shared_mem_vaddr) { + dev_err(dev, "Shared memory remap failed\n"); + return -EINVAL; + } + etpdev->shared_mem_paddr = r.start + EDGETPU_REMAPPED_DATA_OFFSET; + + return 0; +} + +static void +janeiro_platform_cleanup_fw_region(struct janeiro_platform_dev *etpdev) +{ + if (!etpdev->shared_mem_vaddr) + return; + memunmap(etpdev->shared_mem_vaddr); + etpdev->shared_mem_vaddr = NULL; +} + +static int +janeiro_platform_map_reserved_region(struct janeiro_platform_dev *etpdev) +{ + int ret; + struct edgetpu_dev *etdev = &etpdev->edgetpu_dev; + + ret = edgetpu_mmu_add_translation(etdev, etpdev->fw_region_paddr, + etpdev->fw_region_paddr, etpdev->fw_region_size, + IOMMU_READ | IOMMU_WRITE, EDGETPU_CONTEXT_KCI); + if (ret) { + dev_err(etdev->dev, + "Unable to map reserved area for firmware\n"); + return ret; + } + ret = edgetpu_mmu_add_translation(etdev, + etpdev->fw_region_paddr + etpdev->fw_region_size, + etpdev->fw_region_paddr + etpdev->fw_region_size, + EDGETPU_REMAPPED_DATA_SIZE, IOMMU_READ | IOMMU_WRITE, + EDGETPU_CONTEXT_KCI); + if (ret) { + dev_err(etdev->dev, + "Unable to map reserved area for data\n"); + edgetpu_mmu_remove_translation(etdev, + etpdev->fw_region_paddr, + etpdev->fw_region_size, + EDGETPU_CONTEXT_KCI); + return ret; + } + return 0; +} + +static void +janeiro_platform_unmap_reserved_region(struct janeiro_platform_dev *etpdev) +{ + struct edgetpu_dev *etdev = &etpdev->edgetpu_dev; + + edgetpu_mmu_remove_translation(etdev, + etpdev->fw_region_paddr + etpdev->fw_region_size, + EDGETPU_REMAPPED_DATA_SIZE, + EDGETPU_CONTEXT_KCI); + edgetpu_mmu_remove_translation(etdev, + etpdev->fw_region_paddr, + etpdev->fw_region_size, + EDGETPU_CONTEXT_KCI); +} + +int edgetpu_setup_mmu(struct edgetpu_dev *etdev) +{ + int ret; + + ret = edgetpu_mmu_attach(etdev, NULL); + if (ret) + dev_err(etdev->dev, "failed to attach IOMMU: %d\n", ret); + return ret; +} + +#define EDGETPU_PSM0_CFG 0x1c1880 +#define EDGETPU_PSM0_START 0x1c1884 +#define EDGETPU_PSM0_STATUS 0x1c1888 +#define EDGETPU_PSM1_CFG 0x1c2880 +#define EDGETPU_PSM1_START 0x1c2884 +#define EDGETPU_PSM1_STATUS 0x1c2888 +//TODO: set timeout lower for silicon +#define EDGETPU_LPM_CHANGE_TIMEOUT 30000 + +static int janeiro_set_lpm(struct edgetpu_dev *etdev) +{ + int ret; + u32 val; + + edgetpu_dev_write_32_sync(etdev, EDGETPU_PSM0_START, 1); + ret = readl_poll_timeout(etdev->regs.mem + EDGETPU_PSM0_STATUS, val, + val & 0x80, 5, EDGETPU_LPM_CHANGE_TIMEOUT); + if (ret) { + etdev_err(etdev, "Set LPM0 failed: %d\n", ret); + return ret; + } + edgetpu_dev_write_32_sync(etdev, EDGETPU_PSM1_START, 1); + ret = readl_poll_timeout(etdev->regs.mem + EDGETPU_PSM1_STATUS, val, + val & 0x80, 5, EDGETPU_LPM_CHANGE_TIMEOUT); + if (ret) { + etdev_err(etdev, "Set LPM1 failed: %d\n", ret); + return ret; + } + + edgetpu_dev_write_32_sync(etdev, EDGETPU_PSM0_CFG, 0); + edgetpu_dev_write_32_sync(etdev, EDGETPU_PSM1_CFG, 0); + + return 0; +} + +/* + * Set shareability for enabling IO coherency in Janeiro + */ +//TODO(b/185301967): check if sysreg is to be moved under TrustZone +static int janeiro_mmu_set_shareability(struct device *dev) +{ + void __iomem *addr = ioremap(EDGETPU_SYSREG_TPU_BASE, PAGE_SIZE); + + if (!addr) { + dev_err(dev, "sysreg ioremap failed\n"); + return -ENOMEM; + } + + writel_relaxed(SHAREABLE_WRITE | SHAREABLE_READ | INNER_SHAREABLE, + addr + EDGETPU_SYSREG_TPU_SHAREABILITY); + iounmap(addr); + + return 0; +} + +static int edgetpu_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct janeiro_platform_dev *edgetpu_pdev; + struct resource *r; + struct edgetpu_mapped_resource regs; + int ret, i; + + edgetpu_pdev = devm_kzalloc(dev, sizeof(*edgetpu_pdev), GFP_KERNEL); + if (!edgetpu_pdev) + return -ENOMEM; + + platform_set_drvdata(pdev, &edgetpu_pdev->edgetpu_dev); + edgetpu_pdev->edgetpu_dev.dev = dev; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (IS_ERR_OR_NULL(r)) { + dev_err(dev, "failed to get memory resource\n"); + return -ENODEV; + } + + regs.phys = r->start; + regs.size = resource_size(r); + + regs.mem = devm_ioremap_resource(dev, r); + if (IS_ERR_OR_NULL(regs.mem)) { + dev_err(dev, "failed to map registers\n"); + return -ENODEV; + } + + ret = janeiro_pm_create(&edgetpu_pdev->edgetpu_dev); + if (ret) { + dev_err(dev, "Failed to initialize PM interface (%d)\n", ret); + return ret; + } + + ret = janeiro_platform_setup_fw_region(edgetpu_pdev); + if (ret) { + dev_err(dev, "%s setup fw regions failed: %d\n", DRIVER_NAME, + ret); + goto out; + } + + ret = edgetpu_iremap_pool_create( + &edgetpu_pdev->edgetpu_dev, + /* Base virtual address (kernel address space) */ + edgetpu_pdev->shared_mem_vaddr + EDGETPU_POOL_MEM_OFFSET, + /* Base DMA address */ + EDGETPU_REMAPPED_DATA_ADDR + EDGETPU_POOL_MEM_OFFSET, + /* Base TPU address */ + EDGETPU_REMAPPED_DATA_ADDR + EDGETPU_POOL_MEM_OFFSET, + /* Base physical address */ + edgetpu_pdev->shared_mem_paddr + EDGETPU_POOL_MEM_OFFSET, + /* Size */ + EDGETPU_REMAPPED_DATA_SIZE - EDGETPU_POOL_MEM_OFFSET, + /* Granularity */ + PAGE_SIZE); + if (ret) { + dev_err(dev, + "%s failed to initialize remapped memory pool: %d\n", + DRIVER_NAME, ret); + goto out_cleanup_fw; + } + + edgetpu_pdev->edgetpu_dev.mcp_id = -1; + edgetpu_pdev->edgetpu_dev.mcp_die_index = 0; + + for (i = 0; i < EDGETPU_NCONTEXTS; i++) + edgetpu_pdev->irq[i] = platform_get_irq(pdev, i); + + janeiro_mmu_set_shareability(dev); + + ret = edgetpu_device_add(&edgetpu_pdev->edgetpu_dev, ®s); + + if (ret) { + dev_err(dev, "%s edgetpu setup failed: %d\n", DRIVER_NAME, ret); + goto out_destroy_iremap; + } + for (i = 0; i < EDGETPU_NCONTEXTS; i++) { + if (edgetpu_pdev->irq[i] >= 0) + ret = edgetpu_register_irq(&edgetpu_pdev->edgetpu_dev, + edgetpu_pdev->irq[i]); + if (ret) + break; + } + if (ret) { + while (i-- > 0) { + edgetpu_unregister_irq(&edgetpu_pdev->edgetpu_dev, + edgetpu_pdev->irq[i]); + } + dev_err(dev, "%s edgetpu irq registration failed: %d\n", + DRIVER_NAME, ret); + goto out_remove_device; + } + + ret = janeiro_set_lpm(&edgetpu_pdev->edgetpu_dev); + if (ret) + dev_err(dev, "LPM init failed: %d\n", ret); + + ret = janeiro_platform_map_reserved_region(edgetpu_pdev); + if (ret) + goto out_remove_device; + + janeiro_get_telemetry_mem(edgetpu_pdev, EDGETPU_TELEMETRY_LOG, + &edgetpu_pdev->log_mem); + janeiro_get_telemetry_mem(edgetpu_pdev, EDGETPU_TELEMETRY_TRACE, + &edgetpu_pdev->trace_mem); + + ret = edgetpu_telemetry_init(&edgetpu_pdev->edgetpu_dev, + &edgetpu_pdev->log_mem, + &edgetpu_pdev->trace_mem); + if (ret) + goto out_unmap_reserved; + + ret = mobile_edgetpu_firmware_create(&edgetpu_pdev->edgetpu_dev); + if (ret) { + dev_err(dev, "%s initialize firmware downloader failed: %d\n", + DRIVER_NAME, ret); + goto out_tel_exit; + } + + dev_info(dev, "%s edgetpu initialized. Build: %s\n", + edgetpu_pdev->edgetpu_dev.dev_name, GIT_REPO_TAG); + + ret = edgetpu_chip_firmware_run(&edgetpu_pdev->edgetpu_dev, + EDGETPU_DEFAULT_FIRMWARE_NAME, 0); + if (ret) + dev_err(dev, "failed to run firmware: %d\n", ret); +out: + dev_dbg(dev, "Probe finished\n"); + + return 0; +out_tel_exit: + edgetpu_telemetry_exit(&edgetpu_pdev->edgetpu_dev); +out_unmap_reserved: + janeiro_platform_unmap_reserved_region(edgetpu_pdev); +out_remove_device: + edgetpu_device_remove(&edgetpu_pdev->edgetpu_dev); +out_destroy_iremap: + edgetpu_iremap_pool_destroy(&edgetpu_pdev->edgetpu_dev); +out_cleanup_fw: + janeiro_platform_cleanup_fw_region(edgetpu_pdev); + dev_dbg(dev, "Probe finished with error %d, powering down\n", ret); + return ret; +} + +static int edgetpu_platform_remove(struct platform_device *pdev) +{ + int i; + struct edgetpu_dev *etdev = platform_get_drvdata(pdev); + struct janeiro_platform_dev *janeiro_pdev = to_janeiro_dev(etdev); + + mobile_edgetpu_firmware_destroy(etdev); + for (i = 0; i < EDGETPU_NCONTEXTS; i++) { + if (janeiro_pdev->irq[i] >= 0) + edgetpu_unregister_irq(etdev, janeiro_pdev->irq[i]); + } + + janeiro_platform_unmap_reserved_region(janeiro_pdev); + edgetpu_device_remove(etdev); + edgetpu_iremap_pool_destroy(etdev); + janeiro_platform_cleanup_fw_region(janeiro_pdev); + janeiro_pm_destroy(etdev); + return 0; +} + +static struct platform_driver edgetpu_platform_driver = { + .probe = edgetpu_platform_probe, + .remove = edgetpu_platform_remove, + .driver = { + .name = "edgetpu_platform", + .of_match_table = edgetpu_of_match, + }, +}; + +static int __init edgetpu_platform_init(void) +{ + int ret; + + ret = edgetpu_init(); + if (ret) + return ret; + return platform_driver_register(&edgetpu_platform_driver); +} + +static void __exit edgetpu_platform_exit(void) +{ + platform_driver_unregister(&edgetpu_platform_driver); + edgetpu_exit(); +} + +MODULE_DESCRIPTION("Janeiro Edge TPU platform driver"); +MODULE_LICENSE("GPL v2"); +module_init(edgetpu_platform_init); +module_exit(edgetpu_platform_exit); +MODULE_FIRMWARE(EDGETPU_DEFAULT_FIRMWARE_NAME); diff --git a/drivers/edgetpu/janeiro-platform.h b/drivers/edgetpu/janeiro-platform.h new file mode 100644 index 0000000..4e1b7c6 --- /dev/null +++ b/drivers/edgetpu/janeiro-platform.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Platform device driver for the Google Edge TPU ML accelerator. + * + * Copyright (C) 2020 Google, Inc. + */ +#ifndef __JANEIRO_PLATFORM_H__ +#define __JANEIRO_PLATFORM_H__ + +#include <linux/device.h> +#include <linux/io.h> +#include <linux/types.h> + +#include "edgetpu-internal.h" + +#define to_janeiro_dev(etdev) \ + container_of(etdev, struct janeiro_platform_dev, edgetpu_dev) + +struct janeiro_platform_dev { + struct edgetpu_dev edgetpu_dev; + int irq[EDGETPU_NCONTEXTS]; + phys_addr_t fw_region_paddr; + void *fw_region_vaddr; + size_t fw_region_size; + void *shared_mem_vaddr; + phys_addr_t shared_mem_paddr; + size_t shared_mem_size; + phys_addr_t csr_paddr; + dma_addr_t csr_iova; + size_t csr_size; + struct device *gsa_dev; + void __iomem *ssmt_base; + struct edgetpu_coherent_mem log_mem; + struct edgetpu_coherent_mem trace_mem; +}; + +#endif /* __JANEIRO_PLATFORM_H__ */ diff --git a/drivers/edgetpu/janeiro-pm.c b/drivers/edgetpu/janeiro-pm.c new file mode 100644 index 0000000..4302e81 --- /dev/null +++ b/drivers/edgetpu/janeiro-pm.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Janeiro EdgeTPU power management support + * + * Copyright (C) 2020 Google, Inc, + */ + +#include <linux/pm_runtime.h> + +#include "edgetpu-internal.h" +#include "edgetpu-pm.h" +#include "janeiro-pm.h" + +#include "edgetpu-pm.c" + +static int janeiro_pwr_state_init(struct device *dev) +{ + int ret; + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret) { + dev_err(dev, "pm_runtime_get_sync returned %d\n", ret); + return ret; + } + return ret; +} + +static int janeiro_pm_after_create(struct edgetpu_pm *etpm) +{ + struct device *dev = etpm->etdev->dev; + + return janeiro_pwr_state_init(dev); +} + +static void janeiro_pm_before_destroy(struct edgetpu_pm *etpm) +{ + pm_runtime_disable(etpm->etdev->dev); +} + +static struct edgetpu_pm_handlers janeiro_pm_handlers = { + .after_create = janeiro_pm_after_create, + .before_destroy = janeiro_pm_before_destroy, +}; + +int janeiro_pm_create(struct edgetpu_dev *etdev) +{ + return edgetpu_pm_create(etdev, &janeiro_pm_handlers); +} + +void janeiro_pm_destroy(struct edgetpu_dev *etdev) +{ + edgetpu_pm_destroy(etdev); +} diff --git a/drivers/edgetpu/janeiro-pm.h b/drivers/edgetpu/janeiro-pm.h new file mode 100644 index 0000000..3a45fde --- /dev/null +++ b/drivers/edgetpu/janeiro-pm.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Power management header for Janeiro. + * + * Copyright (C) 2020 Google, Inc. + */ +#ifndef __JANEIRO_PM_H__ +#define __JANEIRO_PM_H__ + +int janeiro_pm_create(struct edgetpu_dev *etdev); + +void janeiro_pm_destroy(struct edgetpu_dev *etdev); + +#endif /* __JANEIRO_PM_H__ */ diff --git a/drivers/edgetpu/janeiro-usage-stats.c b/drivers/edgetpu/janeiro-usage-stats.c new file mode 100644 index 0000000..1fd1fc2 --- /dev/null +++ b/drivers/edgetpu/janeiro-usage-stats.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-usage-stats.c" diff --git a/drivers/edgetpu/janeiro-wakelock.c b/drivers/edgetpu/janeiro-wakelock.c new file mode 100644 index 0000000..ab61fb2 --- /dev/null +++ b/drivers/edgetpu/janeiro-wakelock.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "edgetpu-wakelock.c" diff --git a/drivers/edgetpu/janeiro/config-mailbox.h b/drivers/edgetpu/janeiro/config-mailbox.h new file mode 100644 index 0000000..e54dad8 --- /dev/null +++ b/drivers/edgetpu/janeiro/config-mailbox.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Chip-dependent configuration for mailbox. + * + * Copyright (C) 2020 Google, Inc. + */ + +#ifndef __JANEIRO_CONFIG_MAILBOX_H__ +#define __JANEIRO_CONFIG_MAILBOX_H__ + +#include <linux/types.h> /* u32 */ + +#define EDGETPU_NUM_MAILBOXES 8 +#define EDGETPU_NUM_VII_MAILBOXES (EDGETPU_NUM_MAILBOXES - 1) +#define EDGETPU_NUM_P2P_MAILBOXES 0 + +#define JANEIRO_CSR_MBOX2_CONTEXT_ENABLE 0xa0000 /* starting kernel mb*/ +#define JANEIRO_CSR_MBOX2_CMD_QUEUE_DOORBELL_SET 0xa1000 +#define JANEIRO_CSR_MBOX2_RESP_QUEUE_DOORBELL_SET 0xa1800 +#define EDGETPU_MBOX_CSRS_SIZE 0x2000 /* CSR size of each mailbox */ + +#define EDGETPU_MBOX_BASE JANEIRO_CSR_MBOX2_CONTEXT_ENABLE +// TODO: check correct values +/* CSR storing mailbox response queue doorbell status */ +#define HOST_NONSECURE_INT_SRC_STATUS_REG 0x000f0000 +#define HOST_NONSECURE_INT_SRC_CLEAR_REG 0x000f0008 + +static inline u32 edgetpu_mailbox_get_context_csr_base(u32 index) +{ + return JANEIRO_CSR_MBOX2_CONTEXT_ENABLE + + index * EDGETPU_MBOX_CSRS_SIZE; +} + +static inline u32 edgetpu_mailbox_get_cmd_queue_csr_base(u32 index) +{ + return JANEIRO_CSR_MBOX2_CMD_QUEUE_DOORBELL_SET + + index * EDGETPU_MBOX_CSRS_SIZE; +} + +static inline u32 edgetpu_mailbox_get_resp_queue_csr_base(u32 index) +{ + return JANEIRO_CSR_MBOX2_RESP_QUEUE_DOORBELL_SET + + index * EDGETPU_MBOX_CSRS_SIZE; +} +#endif /* __JANEIRO_CONFIG_MAILBOX_H__ */ diff --git a/drivers/edgetpu/janeiro/config-tpu-cpu.h b/drivers/edgetpu/janeiro/config-tpu-cpu.h new file mode 100644 index 0000000..1c84523 --- /dev/null +++ b/drivers/edgetpu/janeiro/config-tpu-cpu.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Chip-dependent configuration for TPU CPU. + * + * Copyright (C) 2020 Google, Inc. + */ + +#ifndef __JANEIRO_CONFIG_TPU_CPU_H__ +#define __JANEIRO_CONFIG_TPU_CPU_H__ + +#define EDGETPU_REG_RESET_CONTROL 0x190010 +#define CPUPORESET (1 << 1) +#define EDGETPU_REG_INSTRUCTION_REMAP_CONTROL 0x190050 +#define EDGETPU_REG_INSTRUCTION_REMAP_BASE 0x190058 +#define EDGETPU_REG_INSTRUCTION_REMAP_LIMIT 0x190060 +#define EDGETPU_REG_INSTRUCTION_REMAP_NEW_BASE 0x190068 +#define EDGETPU_REG_INSTRUCTION_REMAP_SECURITY 0x190070 +#define EDGETPU_REG_SECURITY 0x190048 +#define EDGETPU_REG_POWER_CONTROL 0x1A0008 +#define PSTATE_SHIFT 1 +#define PSTATE (1 << PSTATE_SHIFT) +#define PREQ (1 << 2) +#define PDENY (1 << 3) +#define PACCEPT (1 << 4) +#define PACTIVE (1 << 6) + +#endif /* __JANEIRO_CONFIG_TPU_CPU_H__ */ diff --git a/drivers/edgetpu/janeiro/config.h b/drivers/edgetpu/janeiro/config.h new file mode 100644 index 0000000..841db2d --- /dev/null +++ b/drivers/edgetpu/janeiro/config.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Include all configuration files for Janeiro. + * + * Copyright (C) 2020 Google, Inc. + */ + +#ifndef __JANEIRO_CONFIG_H__ +#define __JANEIRO_CONFIG_H__ + +#define DRIVER_NAME "janeiro" + +#define EDGETPU_DEV_MAX 1 + +#define EDGETPU_HAS_MULTI_GROUPS + +#define EDGETPU_HAS_WAKELOCK + +#define EDGETPU_IS_IO_COHERENT + +/* + * The TPU VA where the firmware is located. + * + * The address is chosen to not overlap with any memory region specified in the + * firmware's linker file. + */ +#define FW_IOVA 0x16000000u +/* + * Size of the area in remapped DRAM reserved for firmware code and internal + * data. This must match the firmware's linker file. + */ +#define EDGETPU_FW_SIZE_MAX 0x100000 + +/* Data in remapped DRAM starts after firmware code and internal data */ +#define EDGETPU_REMAPPED_DATA_OFFSET EDGETPU_FW_SIZE_MAX + +/* + * Size of remapped DRAM data region. This must match the firmware's linker + * file + */ +#define EDGETPU_REMAPPED_DATA_SIZE 0x100000 + +/* + * Instruction remap registers make carveout memory appear at address + * 0x10000000 from the R52 perspective + */ +#define EDGETPU_INSTRUCTION_REMAP_BASE 0x10000000 + +/* Address from which the R52 can access data in the remapped region */ +#define EDGETPU_REMAPPED_DATA_ADDR \ + (EDGETPU_INSTRUCTION_REMAP_BASE + EDGETPU_REMAPPED_DATA_OFFSET) +#include "config-mailbox.h" +#include "config-tpu-cpu.h" +#include "csrs.h" + +#endif /* __JANEIRO_CONFIG_H__ */ diff --git a/drivers/edgetpu/janeiro/csrs.h b/drivers/edgetpu/janeiro/csrs.h new file mode 100644 index 0000000..ec9598d --- /dev/null +++ b/drivers/edgetpu/janeiro/csrs.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Chip-dependent CSRs. + * + * Copyright (C) 2020 Google, Inc. + */ +enum edgetpu_csrs { + EDGETPU_REG_TILECONF1_DEEPSLEEP = 0x002058, + EDGETPU_REG_TILECONF1_ERROR_TILE = 0x0025f0, + EDGETPU_REG_TILECONF1_ERROR_MASK_TILE = 0x0025f8, + EDGETPU_REG_TILECONF1_ERROR_INFO_TILE = 0x002618, + + EDGETPU_REG_SC_RUNCTRL = 0x04018, + EDGETPU_REG_SC_CURRENTPC = 0x004028, + EDGETPU_REG_SC_DECODEPC = 0x004030, + EDGETPU_REG_SC_ERROR = 0x0051a8, + EDGETPU_REG_SC_ERROR_MASK = 0x0051b0, + EDGETPU_REG_SC_ERROR_INFO = 0x0051d0, + + EDGETPU_REG_USER_HIB_INSTRQ_TAIL = 0x0080d0, + EDGETPU_REG_USER_HIB_INSTRQ_INT_STAT = 0x0080f0, + EDGETPU_REG_USER_HIB_SC_HOST_INT_STAT = 0x008140, + EDGETPU_REG_USER_HIB_FATALERR_INT_STAT = 0x008150, + EDGETPU_REG_USER_HIB_DMA_PAUSE = 0x008160, + EDGETPU_REG_USER_HIB_DMA_PAUSED = 0x008168, + EDGETPU_REG_USER_HIB_ERROR_STATUS = 0x008420, + EDGETPU_REG_USER_HIB_ERROR_MASK = 0x008428, + EDGETPU_REG_USER_HIB_FIRST_ERROR_STATUS = 0x008408, + EDGETPU_REG_USER_HIB_SNAPSHOT = 0x0081a0, + EDGETPU_REG_USER_HIB_TILECONFIG1 = 0x006010, + + /*AON Registers. */ + EDGETPU_REG_AON_RESET = 0x20000, + EDGETPU_REG_AON_CLOCK_ENABLE = 0x20008, + EDGETPU_REG_AON_FORCE_QUIESCE = 0x20010, + + EDGETPU_REG_CPUNS_TIMESTAMP = 0x1a00e0, +}; + +/* SYSREG TPU */ +#define EDGETPU_SYSREG_TPU_BASE 0x1cc20000 +#define EDGETPU_SYSREG_TPU_SHAREABILITY 0x700 +#define SHAREABLE_WRITE (1 << 13) +#define SHAREABLE_READ (1 << 12) +#define INNER_SHAREABLE 1 |