2018-01-22 12:27:00 +03:00
// SPDX-License-Identifier: GPL-2.0
2019-04-18 16:38:53 +03:00
/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
2018-01-22 12:27:00 +03:00
# include <linux/kernel.h>
# include <linux/interrupt.h>
# include <linux/pm_runtime.h>
# include "cc_driver.h"
# include "cc_buffer_mgr.h"
# include "cc_request_mgr.h"
# include "cc_sram_mgr.h"
2018-01-22 12:27:02 +03:00
# include "cc_hash.h"
2018-01-22 12:27:00 +03:00
# include "cc_pm.h"
2019-04-18 16:39:10 +03:00
# include "cc_fips.h"
2018-01-22 12:27:00 +03:00
# define POWER_DOWN_ENABLE 0x01
# define POWER_DOWN_DISABLE 0x00
2020-02-11 21:19:11 +03:00
static int cc_pm_suspend ( struct device * dev )
2018-01-22 12:27:00 +03:00
{
struct cc_drvdata * drvdata = dev_get_drvdata ( dev ) ;
dev_dbg ( dev , " set HOST_POWER_DOWN_EN \n " ) ;
fini_cc_regs ( drvdata ) ;
2019-04-18 16:39:08 +03:00
cc_iowrite ( drvdata , CC_REG ( HOST_POWER_DOWN_EN ) , POWER_DOWN_ENABLE ) ;
2020-02-11 21:19:02 +03:00
clk_disable_unprepare ( drvdata - > clk ) ;
2018-01-22 12:27:00 +03:00
return 0 ;
}
2020-02-11 21:19:11 +03:00
static int cc_pm_resume ( struct device * dev )
2018-01-22 12:27:00 +03:00
{
int rc ;
struct cc_drvdata * drvdata = dev_get_drvdata ( dev ) ;
dev_dbg ( dev , " unset HOST_POWER_DOWN_EN \n " ) ;
2019-04-18 16:39:06 +03:00
/* Enables the device source clk */
2020-02-11 21:19:02 +03:00
rc = clk_prepare_enable ( drvdata - > clk ) ;
2018-01-22 12:27:00 +03:00
if ( rc ) {
dev_err ( dev , " failed getting clock back on. We're toast. \n " ) ;
return rc ;
}
2020-01-16 13:14:37 +03:00
/* wait for Cryptocell reset completion */
2019-06-17 11:46:28 +03:00
if ( ! cc_wait_for_reset_completion ( drvdata ) ) {
dev_err ( dev , " Cryptocell reset not completed " ) ;
return - EBUSY ;
}
2018-01-22 12:27:00 +03:00
2019-04-18 16:39:06 +03:00
cc_iowrite ( drvdata , CC_REG ( HOST_POWER_DOWN_EN ) , POWER_DOWN_DISABLE ) ;
2020-11-22 10:51:53 +03:00
rc = init_cc_regs ( drvdata ) ;
2018-01-22 12:27:00 +03:00
if ( rc ) {
dev_err ( dev , " init_cc_regs (%x) \n " , rc ) ;
return rc ;
}
2019-04-18 16:39:10 +03:00
/* check if tee fips error occurred during power down */
cc_tee_handle_fips_error ( drvdata ) ;
2018-01-22 12:27:00 +03:00
2018-01-22 12:27:02 +03:00
cc_init_hash_sram ( drvdata ) ;
2018-01-22 12:27:00 +03:00
return 0 ;
}
2020-02-11 21:19:11 +03:00
const struct dev_pm_ops ccree_pm = {
SET_RUNTIME_PM_OPS ( cc_pm_suspend , cc_pm_resume , NULL )
} ;
2018-01-22 12:27:00 +03:00
int cc_pm_get ( struct device * dev )
{
2020-02-11 21:19:08 +03:00
int rc = pm_runtime_get_sync ( dev ) ;
2020-08-21 11:15:13 +03:00
if ( rc < 0 ) {
pm_runtime_put_noidle ( dev ) ;
return rc ;
}
2018-01-22 12:27:00 +03:00
2020-08-21 11:15:13 +03:00
return 0 ;
2018-01-22 12:27:00 +03:00
}
2020-01-16 13:14:45 +03:00
void cc_pm_put_suspend ( struct device * dev )
2018-01-22 12:27:00 +03:00
{
2020-02-11 21:19:08 +03:00
pm_runtime_mark_last_busy ( dev ) ;
pm_runtime_put_autosuspend ( dev ) ;
2018-01-22 12:27:00 +03:00
}