blob: 5f44ab41e46a5bd7d8e26a79f13aeb5b27455157 [file] [log] [blame] [edit]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* EdgeTPU power management interface.
*
* Copyright (C) 2020 Google, Inc.
*/
#ifndef __EDGETPU_PM_H__
#define __EDGETPU_PM_H__
#include "edgetpu-internal.h"
#define STATE_SHUTDOWN 1
#define STATE_RUN 0
#define EDGETPU_PCHANNEL_STATE_CHANGE_TIMEOUT 1000 /* 1 ms */
#define EDGETPU_PCHANNEL_STATE_CHANGE_RETRIES 10
#define EDGETPU_PCHANNEL_RETRY_DELAY_MIN 900
#define EDGETPU_PCHANNEL_RETRY_DELAY_MAX 1000
struct edgetpu_pm_private;
struct edgetpu_pm;
struct edgetpu_pm_handlers {
/* For initial setup after the interface initialized */
int (*after_create)(struct edgetpu_pm *etpm);
/* For clean-up before the interface is destroyed */
void (*before_destroy)(struct edgetpu_pm *etpm);
/* Platform-specific power up. Nesting is handled at generic layer */
int (*power_up)(struct edgetpu_pm *etpm);
/* Platform-specific power down. Nesting is handled at generic layer */
int (*power_down)(struct edgetpu_pm *etpm);
};
struct edgetpu_pm {
struct edgetpu_dev *etdev;
struct edgetpu_pm_private *p;
};
/*
* These mimic the pm_runtime_{get|put} functions to keep a reference count
* of requests in order to keep the device up and turn it off if the platform
* supports it.
*
* Since these functions are used by the edgetpu-fs and edgetpu-firmware
* layers, (which have their own internal locks) no locking is provided here.
*
* Callers are responsible for holding any necessary locks.
*/
/*
* Tries to acquire the internal lock that ensures power_up_counter won't be
* modified.
*
* Returns 1 if the lock has been acquired successfully, 0 otherwise.
*/
int edgetpu_pm_trylock(struct edgetpu_pm *etpm);
void edgetpu_pm_unlock(struct edgetpu_pm *etpm);
/*
* Increase power_up_count if it's already powered on.
*
* Caller calls edgetpu_pm_put() to decrease power_up_count if this function
* returned true, otherwise put() shouldn't be called.
*
* Return false if device is not powered, true otherwise.
*/
bool edgetpu_pm_get_if_powered(struct edgetpu_pm *etpm);
/*
* Increase power_up_count for active state, power up the device if previous
* power_up_count was zero.
* Returns 0 on success or negative error value
*/
int edgetpu_pm_get(struct edgetpu_pm *etpm);
/* Decrease power_up_count for active state, power off if it reaches zero */
void edgetpu_pm_put(struct edgetpu_pm *etpm);
/* Initialize a power management interface for an edgetpu device */
int edgetpu_pm_create(struct edgetpu_dev *etdev,
const struct edgetpu_pm_handlers *handlers);
/* Destroy the power management interface associated with an edgetpu device */
void edgetpu_pm_destroy(struct edgetpu_dev *etdev);
/*
* When @force is true, ensure device is shut down, regardless of whether there
* is a client left open.
*
* When @force is false, the device is shut down if there is no client open.
*/
void edgetpu_pm_shutdown(struct edgetpu_dev *etdev, bool force);
/* Check if device is powered on. power_up_count is not protected by a lock */
bool edgetpu_is_powered(struct edgetpu_dev *etdev);
/*
* Request run state and deassert CPU reset to TPU CPU on p-channel
* interface.
*/
void edgetpu_pchannel_power_up(struct edgetpu_dev *etdev);
/*
* Request shutdown state and assert CPU reset to TPU CPU on p-channel
* interface. Set @wait_on_pactive if chip has working PACTIVE implementation,
* false otherwise that will sleep for set amount of time.
*/
int edgetpu_pchannel_power_down(struct edgetpu_dev *etdev,
bool wait_on_pactive);
#if IS_ENABLED(CONFIG_PM_SLEEP)
int edgetpu_pm_suspend(struct edgetpu_dev *etdev);
int edgetpu_pm_resume(struct edgetpu_dev *etdev);
#endif /* IS_ENABLED(CONFIG_PM_SLEEP) */
#endif /* __EDGETPU_PM_H__ */