blob: 8bf40e2ec74b146ee1ab7d1bb6c7096d419db23d [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Abrolhos EdgeTPU power management support
*
* Copyright (C) 2020 Google, Inc.
*/
#include <linux/delay.h>
#include <linux/gsa/gsa_tpu.h>
#include <linux/iopoll.h>
#include "edgetpu-config.h"
#include "edgetpu-firmware.h"
#include "edgetpu-internal.h"
#include "edgetpu-pm.h"
#include "mobile-pm.h"
#define TPU_DEFAULT_POWER_STATE TPU_DEEP_SLEEP_CLOCKS_SLOW
#include "mobile-pm.c"
static int abrolhos_core_pwr_get(void *data, u64 *val)
{
*val = exynos_acpm_get_rate(TPU_ACPM_DOMAIN,
TPU_DEBUG_REQ | TPU_CORE_PWR_DEBUG);
return 0;
}
static int abrolhos_core_pwr_set(void *data, u64 val)
{
int ret;
unsigned long dbg_rate_req;
dbg_rate_req = TPU_DEBUG_REQ | TPU_CORE_PWR_DEBUG;
dbg_rate_req |= val;
ret = exynos_acpm_set_rate(TPU_ACPM_DOMAIN, dbg_rate_req);
return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_tpu_core_pwr, abrolhos_core_pwr_get,
abrolhos_core_pwr_set, "%llu\n");
static int abrolhos_pm_after_create(struct edgetpu_dev *etdev)
{
struct edgetpu_mobile_platform_dev *etmdev = to_mobile_dev(etdev);
struct edgetpu_mobile_platform_pwr *platform_pwr = &etmdev->platform_pwr;
debugfs_create_file("core_pwr", 0660, platform_pwr->debugfs_dir, etdev, &fops_tpu_core_pwr);
return 0;
}
static void abrolhos_firmware_down(struct edgetpu_dev *etdev)
{
struct edgetpu_mobile_platform_dev *etmdev = to_mobile_dev(etdev);
if (!edgetpu_pchannel_power_down(etdev, false))
return;
etdev_warn(etdev, "Firmware shutdown request failed!\n");
etdev_warn(etdev, "Attempting firmware restart\n");
if (!edgetpu_firmware_restart_locked(etdev, true) &&
!edgetpu_pchannel_power_down(etdev, false))
return;
if (etmdev->gsa_dev) {
etdev_warn(etdev, "Requesting early GSA reset\n");
/*
* p-channel failed, request GSA shutdown to make sure the CPU is
* reset.
* The GSA->APM request will clear any pending DVFS status from the
* CPU.
*/
gsa_send_tpu_cmd(etmdev->gsa_dev, GSA_TPU_SHUTDOWN);
}
}
int edgetpu_chip_pm_create(struct edgetpu_dev *etdev)
{
struct edgetpu_mobile_platform_dev *etmdev = to_mobile_dev(etdev);
struct edgetpu_mobile_platform_pwr *platform_pwr = &etmdev->platform_pwr;
platform_pwr->firmware_down = abrolhos_firmware_down;
platform_pwr->after_create = abrolhos_pm_after_create;
platform_pwr->acpm_set_rate = exynos_acpm_set_rate;
return mobile_pm_create(etdev);
}