summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNishant Prajapati <nishantpjpt@google.com>2021-05-06 10:11:14 +0530
committerNishant Prajapati <nishantpjpt@google.com>2021-05-06 06:34:14 +0000
commitdd8b3e9b13c82b85656aeba1eb42c378adbc4070 (patch)
tree15971a9d49ceaf9cf17f609745951ffbc1de4507
parenta7c17065c3886f8debb97cdff8bf509de94714ee (diff)
downloadjaneiro-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
-rw-r--r--drivers/edgetpu/Kbuild28
-rw-r--r--drivers/edgetpu/Kconfig31
-rw-r--r--drivers/edgetpu/Makefile13
-rw-r--r--drivers/edgetpu/edgetpu-device-group.c1
-rw-r--r--drivers/edgetpu/edgetpu-dmabuf.c10
-rw-r--r--drivers/edgetpu/edgetpu-dram.h8
-rw-r--r--drivers/edgetpu/edgetpu-fs.c16
-rw-r--r--drivers/edgetpu/edgetpu-kci.c4
-rw-r--r--drivers/edgetpu/edgetpu.h18
-rw-r--r--drivers/edgetpu/include/linux/platform_data/sscoredump.h35
-rw-r--r--drivers/edgetpu/janeiro-core.c2
-rw-r--r--drivers/edgetpu/janeiro-debug-dump.c11
-rw-r--r--drivers/edgetpu/janeiro-device-group.c2
-rw-r--r--drivers/edgetpu/janeiro-device.c91
-rw-r--r--drivers/edgetpu/janeiro-firmware.c185
-rw-r--r--drivers/edgetpu/janeiro-fs.c2
-rw-r--r--drivers/edgetpu/janeiro-iommu.c2
-rw-r--r--drivers/edgetpu/janeiro-platform.c409
-rw-r--r--drivers/edgetpu/janeiro-platform.h37
-rw-r--r--drivers/edgetpu/janeiro-pm.c54
-rw-r--r--drivers/edgetpu/janeiro-pm.h14
-rw-r--r--drivers/edgetpu/janeiro-usage-stats.c2
-rw-r--r--drivers/edgetpu/janeiro-wakelock.c2
-rw-r--r--drivers/edgetpu/janeiro/config-mailbox.h45
-rw-r--r--drivers/edgetpu/janeiro/config-tpu-cpu.h27
-rw-r--r--drivers/edgetpu/janeiro/config.h56
-rw-r--r--drivers/edgetpu/janeiro/csrs.h45
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, &regs);
+
+ 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