2019-06-01 10:08:55 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2014-12-12 11:46:39 -08:00
/*
* Copyright ( C ) 2014 Intel Corporation
*
* Authors :
* Jarkko Sakkinen < jarkko . sakkinen @ linux . intel . com >
*
* Maintained by : < tpmdd - devel @ lists . sourceforge . net >
*
* This device driver implements the TPM interface as defined in
* the TCG CRB 2.0 TPM specification .
*/
# include <linux/acpi.h>
# include <linux/highmem.h>
# include <linux/rculist.h>
# include <linux/module.h>
2016-10-08 14:59:39 +03:00
# include <linux/pm_runtime.h>
2017-03-24 04:55:45 -05:00
# ifdef CONFIG_ARM64
# include <linux/arm-smccc.h>
# endif
2014-12-12 11:46:39 -08:00
# include "tpm.h"
# define ACPI_SIG_TPM2 "TPM2"
2019-10-16 21:28:14 +03:00
# define TPM_CRB_MAX_RESOURCES 3
2014-12-12 11:46:39 -08:00
2017-06-05 19:40:46 +03:00
static const guid_t crb_acpi_start_guid =
GUID_INIT ( 0x6BBF6CAB , 0x5463 , 0x4714 ,
0xB7 , 0xCD , 0xF0 , 0x20 , 0x3C , 0x03 , 0x68 , 0xD4 ) ;
2014-12-12 11:46:39 -08:00
enum crb_defaults {
CRB_ACPI_START_REVISION_ID = 1 ,
CRB_ACPI_START_INDEX = 1 ,
} ;
2017-03-24 11:45:49 +02:00
enum crb_loc_ctrl {
CRB_LOC_CTRL_REQUEST_ACCESS = BIT ( 0 ) ,
CRB_LOC_CTRL_RELINQUISH = BIT ( 1 ) ,
} ;
enum crb_loc_state {
CRB_LOC_STATE_LOC_ASSIGNED = BIT ( 1 ) ,
CRB_LOC_STATE_TPM_REG_VALID_STS = BIT ( 7 ) ,
} ;
2016-09-02 22:34:19 +03:00
enum crb_ctrl_req {
2016-09-02 22:34:20 +03:00
CRB_CTRL_REQ_CMD_READY = BIT ( 0 ) ,
CRB_CTRL_REQ_GO_IDLE = BIT ( 1 ) ,
2014-12-12 11:46:39 -08:00
} ;
2016-09-02 22:34:19 +03:00
enum crb_ctrl_sts {
CRB_CTRL_STS_ERROR = BIT ( 0 ) ,
CRB_CTRL_STS_TPM_IDLE = BIT ( 1 ) ,
2014-12-12 11:46:39 -08:00
} ;
enum crb_start {
CRB_START_INVOKE = BIT ( 0 ) ,
} ;
enum crb_cancel {
CRB_CANCEL_INVOKE = BIT ( 0 ) ,
} ;
2017-02-08 13:11:35 +02:00
struct crb_regs_head {
u32 loc_state ;
u32 reserved1 ;
u32 loc_ctrl ;
u32 loc_sts ;
u8 reserved2 [ 32 ] ;
u64 intf_id ;
u64 ctrl_ext ;
} __packed ;
struct crb_regs_tail {
u32 ctrl_req ;
u32 ctrl_sts ;
u32 ctrl_cancel ;
u32 ctrl_start ;
u32 ctrl_int_enable ;
u32 ctrl_int_sts ;
u32 ctrl_cmd_size ;
u32 ctrl_cmd_pa_low ;
u32 ctrl_cmd_pa_high ;
u32 ctrl_rsp_size ;
u64 ctrl_rsp_pa ;
2014-12-12 11:46:39 -08:00
} __packed ;
enum crb_status {
2016-09-02 22:34:19 +03:00
CRB_DRV_STS_COMPLETE = BIT ( 0 ) ,
2014-12-12 11:46:39 -08:00
} ;
struct crb_priv {
2017-08-25 18:28:55 -05:00
u32 sm ;
const char * hid ;
2017-02-08 13:11:35 +02:00
struct crb_regs_head __iomem * regs_h ;
struct crb_regs_tail __iomem * regs_t ;
2014-12-12 11:46:39 -08:00
u8 __iomem * cmd ;
u8 __iomem * rsp ;
2016-09-12 13:52:10 +03:00
u32 cmd_size ;
2017-03-24 04:55:45 -05:00
u32 smc_func_id ;
} ;
struct tpm2_crb_smc {
u32 interrupt ;
u8 interrupt_flags ;
u8 op_flags ;
u16 reserved2 ;
u32 smc_func_id ;
2014-12-12 11:46:39 -08:00
} ;
2018-03-05 13:34:49 +02:00
static bool crb_wait_for_reg_32 ( u32 __iomem * reg , u32 mask , u32 value ,
unsigned long timeout )
{
ktime_t start ;
ktime_t stop ;
start = ktime_get ( ) ;
stop = ktime_add ( start , ms_to_ktime ( timeout ) ) ;
do {
if ( ( ioread32 ( reg ) & mask ) = = value )
return true ;
usleep_range ( 50 , 100 ) ;
} while ( ktime_before ( ktime_get ( ) , stop ) ) ;
return ( ( ioread32 ( reg ) & mask ) = = value ) ;
}
2016-09-15 10:27:38 +03:00
/**
2018-06-28 18:13:33 +03:00
* __crb_go_idle - request tpm crb device to go the idle state
2016-09-15 10:27:38 +03:00
*
* @ dev : crb device
* @ priv : crb private data
*
* Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
* The device should respond within TIMEOUT_C by clearing the bit .
* Anyhow , we do not wait here as a consequent CMD_READY request
* will be handled correctly even if idle was not completed .
*
2017-08-25 18:28:55 -05:00
* The function does nothing for devices with ACPI - start method
* or SMC - start method .
2016-09-15 10:27:38 +03:00
*
* Return : 0 always
*/
2018-06-28 18:13:33 +03:00
static int __crb_go_idle ( struct device * dev , struct crb_priv * priv )
2016-09-15 10:27:38 +03:00
{
2017-08-25 18:28:55 -05:00
if ( ( priv - > sm = = ACPI_TPM2_START_METHOD ) | |
( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) | |
( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) )
2016-09-15 10:27:38 +03:00
return 0 ;
2017-02-08 13:11:35 +02:00
iowrite32 ( CRB_CTRL_REQ_GO_IDLE , & priv - > regs_t - > ctrl_req ) ;
2016-09-15 10:27:38 +03:00
2018-03-05 13:34:49 +02:00
if ( ! crb_wait_for_reg_32 ( & priv - > regs_t - > ctrl_req ,
CRB_CTRL_REQ_GO_IDLE /* mask */ ,
0 , /* value */
TPM2_TIMEOUT_C ) ) {
dev_warn ( dev , " goIdle timed out \n " ) ;
return - ETIME ;
}
2018-06-28 18:13:33 +03:00
2016-09-15 10:27:38 +03:00
return 0 ;
}
2018-06-28 18:13:33 +03:00
static int crb_go_idle ( struct tpm_chip * chip )
{
struct device * dev = & chip - > dev ;
struct crb_priv * priv = dev_get_drvdata ( dev ) ;
return __crb_go_idle ( dev , priv ) ;
}
2016-09-15 10:27:38 +03:00
/**
2018-06-28 18:13:33 +03:00
* __crb_cmd_ready - request tpm crb device to enter ready state
2016-09-15 10:27:38 +03:00
*
* @ dev : crb device
* @ priv : crb private data
*
* Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
* and poll till the device acknowledge it by clearing the bit .
* The device should respond within TIMEOUT_C .
*
* The function does nothing for devices with ACPI - start method
2017-08-25 18:28:55 -05:00
* or SMC - start method .
2016-09-15 10:27:38 +03:00
*
* Return : 0 on success - ETIME on timeout ;
*/
2018-06-28 18:13:33 +03:00
static int __crb_cmd_ready ( struct device * dev , struct crb_priv * priv )
2016-09-15 10:27:38 +03:00
{
2017-08-25 18:28:55 -05:00
if ( ( priv - > sm = = ACPI_TPM2_START_METHOD ) | |
( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) | |
( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) )
2016-09-15 10:27:38 +03:00
return 0 ;
2017-02-08 13:11:35 +02:00
iowrite32 ( CRB_CTRL_REQ_CMD_READY , & priv - > regs_t - > ctrl_req ) ;
2017-02-08 13:11:36 +02:00
if ( ! crb_wait_for_reg_32 ( & priv - > regs_t - > ctrl_req ,
CRB_CTRL_REQ_CMD_READY /* mask */ ,
0 , /* value */
TPM2_TIMEOUT_C ) ) {
2016-09-15 10:27:38 +03:00
dev_warn ( dev , " cmdReady timed out \n " ) ;
return - ETIME ;
}
return 0 ;
}
2018-06-28 18:13:33 +03:00
static int crb_cmd_ready ( struct tpm_chip * chip )
{
struct device * dev = & chip - > dev ;
struct crb_priv * priv = dev_get_drvdata ( dev ) ;
return __crb_cmd_ready ( dev , priv ) ;
}
2018-03-05 13:34:49 +02:00
static int __crb_request_locality ( struct device * dev ,
struct crb_priv * priv , int loc )
2017-03-24 11:45:49 +02:00
{
u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
2018-03-05 13:34:49 +02:00
CRB_LOC_STATE_TPM_REG_VALID_STS ;
2017-03-24 11:45:49 +02:00
if ( ! priv - > regs_h )
return 0 ;
iowrite32 ( CRB_LOC_CTRL_REQUEST_ACCESS , & priv - > regs_h - > loc_ctrl ) ;
if ( ! crb_wait_for_reg_32 ( & priv - > regs_h - > loc_state , value , value ,
TPM2_TIMEOUT_C ) ) {
2018-03-05 13:34:49 +02:00
dev_warn ( dev , " TPM_LOC_STATE_x.requestAccess timed out \n " ) ;
2017-03-24 11:45:49 +02:00
return - ETIME ;
}
return 0 ;
}
2018-03-05 13:34:49 +02:00
static int crb_request_locality ( struct tpm_chip * chip , int loc )
2017-03-24 11:45:49 +02:00
{
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
2018-03-05 13:34:49 +02:00
return __crb_request_locality ( & chip - > dev , priv , loc ) ;
}
static int __crb_relinquish_locality ( struct device * dev ,
struct crb_priv * priv , int loc )
{
u32 mask = CRB_LOC_STATE_LOC_ASSIGNED |
CRB_LOC_STATE_TPM_REG_VALID_STS ;
u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS ;
2017-03-24 11:45:49 +02:00
if ( ! priv - > regs_h )
2018-03-05 13:34:49 +02:00
return 0 ;
2017-03-24 11:45:49 +02:00
iowrite32 ( CRB_LOC_CTRL_RELINQUISH , & priv - > regs_h - > loc_ctrl ) ;
2018-03-05 13:34:49 +02:00
if ( ! crb_wait_for_reg_32 ( & priv - > regs_h - > loc_state , mask , value ,
TPM2_TIMEOUT_C ) ) {
dev_warn ( dev , " TPM_LOC_STATE_x.requestAccess timed out \n " ) ;
return - ETIME ;
}
return 0 ;
}
static int crb_relinquish_locality ( struct tpm_chip * chip , int loc )
{
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
return __crb_relinquish_locality ( & chip - > dev , priv , loc ) ;
2017-03-24 11:45:49 +02:00
}
2014-12-12 11:46:39 -08:00
static u8 crb_status ( struct tpm_chip * chip )
{
2016-03-31 22:57:00 +02:00
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
2014-12-12 11:46:39 -08:00
u8 sts = 0 ;
2017-02-08 13:11:35 +02:00
if ( ( ioread32 ( & priv - > regs_t - > ctrl_start ) & CRB_START_INVOKE ) ! =
2014-12-12 11:46:39 -08:00
CRB_START_INVOKE )
2016-09-02 22:34:19 +03:00
sts | = CRB_DRV_STS_COMPLETE ;
2014-12-12 11:46:39 -08:00
return sts ;
}
static int crb_recv ( struct tpm_chip * chip , u8 * buf , size_t count )
{
2016-03-31 22:57:00 +02:00
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
2014-12-12 11:46:39 -08:00
unsigned int expected ;
2019-02-04 15:59:43 +02:00
/* A sanity check that the upper layer wants to get at least the header
* as that is the minimum size for any TPM response .
*/
if ( count < TPM_HEADER_SIZE )
2014-12-12 11:46:39 -08:00
return - EIO ;
2019-02-04 15:59:43 +02:00
/* If this bit is set, according to the spec, the TPM is in
* unrecoverable condition .
*/
2017-02-08 13:11:35 +02:00
if ( ioread32 ( & priv - > regs_t - > ctrl_sts ) & CRB_CTRL_STS_ERROR )
2014-12-12 11:46:39 -08:00
return - EIO ;
2019-02-04 15:59:43 +02:00
/* Read the first 8 bytes in order to get the length of the response.
* We read exactly a quad word in order to make sure that the remaining
* reads will be aligned .
*/
memcpy_fromio ( buf , priv - > rsp , 8 ) ;
expected = be32_to_cpup ( ( __be32 * ) & buf [ 2 ] ) ;
if ( expected > count | | expected < TPM_HEADER_SIZE )
2014-12-12 11:46:39 -08:00
return - EIO ;
2019-02-04 15:59:43 +02:00
memcpy_fromio ( & buf [ 8 ] , & priv - > rsp [ 8 ] , expected - 8 ) ;
2014-12-12 11:46:39 -08:00
return expected ;
}
static int crb_do_acpi_start ( struct tpm_chip * chip )
{
union acpi_object * obj ;
int rc ;
obj = acpi_evaluate_dsm ( chip - > acpi_dev_handle ,
2017-06-05 19:40:46 +03:00
& crb_acpi_start_guid ,
2014-12-12 11:46:39 -08:00
CRB_ACPI_START_REVISION_ID ,
CRB_ACPI_START_INDEX ,
NULL ) ;
if ( ! obj )
return - ENXIO ;
rc = obj - > integer . value = = 0 ? 0 : - ENXIO ;
ACPI_FREE ( obj ) ;
return rc ;
}
2017-03-24 04:55:45 -05:00
# ifdef CONFIG_ARM64
/*
* This is a TPM Command Response Buffer start method that invokes a
* Secure Monitor Call to requrest the firmware to execute or cancel
* a TPM 2.0 command .
*/
static int tpm_crb_smc_start ( struct device * dev , unsigned long func_id )
{
struct arm_smccc_res res ;
arm_smccc_smc ( func_id , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & res ) ;
if ( res . a0 ! = 0 ) {
dev_err ( dev ,
FW_BUG " tpm_crb_smc_start() returns res.a0 = 0x%lx \n " ,
res . a0 ) ;
return - EIO ;
}
return 0 ;
}
# else
static int tpm_crb_smc_start ( struct device * dev , unsigned long func_id )
{
dev_err ( dev , FW_BUG " tpm_crb: incorrect start method \n " ) ;
return - EINVAL ;
}
# endif
2014-12-12 11:46:39 -08:00
static int crb_send ( struct tpm_chip * chip , u8 * buf , size_t len )
{
2016-03-31 22:57:00 +02:00
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
2014-12-12 11:46:39 -08:00
int rc = 0 ;
2016-09-02 22:34:17 +03:00
/* Zero the cancel register so that the next command will not get
* canceled .
*/
2017-02-08 13:11:35 +02:00
iowrite32 ( 0 , & priv - > regs_t - > ctrl_cancel ) ;
2016-09-02 22:34:17 +03:00
2016-09-12 13:52:10 +03:00
if ( len > priv - > cmd_size ) {
dev_err ( & chip - > dev , " invalid command count value %zd %d \n " ,
len , priv - > cmd_size ) ;
2014-12-12 11:46:39 -08:00
return - E2BIG ;
}
memcpy_toio ( priv - > cmd , buf , len ) ;
/* Make sure that cmd is populated before issuing start. */
wmb ( ) ;
2017-08-25 18:28:55 -05:00
/* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
* report only ACPI start but in practice seems to require both
* CRB start , hence invoking CRB start method if hid = = MSFT0101 .
*/
if ( ( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER ) | |
( priv - > sm = = ACPI_TPM2_MEMORY_MAPPED ) | |
( ! strcmp ( priv - > hid , " MSFT0101 " ) ) )
2017-02-08 13:11:35 +02:00
iowrite32 ( CRB_START_INVOKE , & priv - > regs_t - > ctrl_start ) ;
2014-12-12 11:46:39 -08:00
2017-08-25 18:28:55 -05:00
if ( ( priv - > sm = = ACPI_TPM2_START_METHOD ) | |
( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) )
2014-12-12 11:46:39 -08:00
rc = crb_do_acpi_start ( chip ) ;
2017-08-25 18:28:55 -05:00
if ( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) {
2017-03-24 04:55:45 -05:00
iowrite32 ( CRB_START_INVOKE , & priv - > regs_t - > ctrl_start ) ;
rc = tpm_crb_smc_start ( & chip - > dev , priv - > smc_func_id ) ;
}
2014-12-12 11:46:39 -08:00
return rc ;
}
static void crb_cancel ( struct tpm_chip * chip )
{
2016-03-31 22:57:00 +02:00
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
2014-12-12 11:46:39 -08:00
2017-02-08 13:11:35 +02:00
iowrite32 ( CRB_CANCEL_INVOKE , & priv - > regs_t - > ctrl_cancel ) ;
2014-12-12 11:46:39 -08:00
2017-08-25 18:28:55 -05:00
if ( ( ( priv - > sm = = ACPI_TPM2_START_METHOD ) | |
( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) ) & &
crb_do_acpi_start ( chip ) )
2014-12-12 11:46:39 -08:00
dev_err ( & chip - > dev , " ACPI Start failed \n " ) ;
}
static bool crb_req_canceled ( struct tpm_chip * chip , u8 status )
{
2016-03-31 22:57:00 +02:00
struct crb_priv * priv = dev_get_drvdata ( & chip - > dev ) ;
2017-02-08 13:11:35 +02:00
u32 cancel = ioread32 ( & priv - > regs_t - > ctrl_cancel ) ;
2014-12-12 11:46:39 -08:00
return ( cancel & CRB_CANCEL_INVOKE ) = = CRB_CANCEL_INVOKE ;
}
static const struct tpm_class_ops tpm_crb = {
2016-07-12 11:41:49 -06:00
. flags = TPM_OPS_AUTO_STARTUP ,
2014-12-12 11:46:39 -08:00
. status = crb_status ,
. recv = crb_recv ,
. send = crb_send ,
. cancel = crb_cancel ,
. req_canceled = crb_req_canceled ,
2018-06-28 18:13:33 +03:00
. go_idle = crb_go_idle ,
. cmd_ready = crb_cmd_ready ,
2017-03-24 11:45:49 +02:00
. request_locality = crb_request_locality ,
. relinquish_locality = crb_relinquish_locality ,
2016-09-02 22:34:19 +03:00
. req_complete_mask = CRB_DRV_STS_COMPLETE ,
. req_complete_val = CRB_DRV_STS_COMPLETE ,
2014-12-12 11:46:39 -08:00
} ;
2016-01-07 17:36:26 -07:00
static int crb_check_resource ( struct acpi_resource * ares , void * data )
{
2019-10-16 21:28:14 +03:00
struct resource * iores_array = data ;
2016-12-18 22:20:53 -06:00
struct resource_win win ;
struct resource * res = & ( win . res ) ;
2019-10-16 21:28:14 +03:00
int i ;
2016-01-07 17:36:26 -07:00
2016-12-18 22:20:53 -06:00
if ( acpi_dev_resource_memory ( ares , res ) | |
acpi_dev_resource_address_space ( ares , & win ) ) {
2019-10-16 21:28:14 +03:00
for ( i = 0 ; i < TPM_CRB_MAX_RESOURCES + 1 ; + + i ) {
if ( resource_type ( iores_array + i ) ! = IORESOURCE_MEM ) {
iores_array [ i ] = * res ;
iores_array [ i ] . name = NULL ;
break ;
}
}
2016-02-17 02:10:52 +02:00
}
2016-01-07 17:36:26 -07:00
return 1 ;
}
2019-10-16 21:28:14 +03:00
static void __iomem * crb_map_res ( struct device * dev , struct resource * iores ,
void __iomem * * iobase_ptr , u64 start , u32 size )
2016-01-07 17:36:26 -07:00
{
struct resource new_res = {
. start = start ,
. end = start + size - 1 ,
. flags = IORESOURCE_MEM ,
} ;
/* Detect a 64 bit address on a 32 bit system */
if ( start ! = new_res . start )
2021-04-29 15:39:39 +08:00
return IOMEM_ERR_PTR ( - EINVAL ) ;
2016-01-07 17:36:26 -07:00
2019-10-16 21:28:14 +03:00
if ( ! iores )
2016-01-07 17:36:26 -07:00
return devm_ioremap_resource ( dev , & new_res ) ;
2019-10-16 21:28:14 +03:00
if ( ! * iobase_ptr ) {
* iobase_ptr = devm_ioremap_resource ( dev , iores ) ;
if ( IS_ERR ( * iobase_ptr ) )
return * iobase_ptr ;
}
return * iobase_ptr + ( new_res . start - iores - > start ) ;
2016-01-07 17:36:26 -07:00
}
2017-02-21 14:14:24 -07:00
/*
* Work around broken BIOSs that return inconsistent values from the ACPI
* region vs the registers . Trust the ACPI region . Such broken systems
* probably cannot send large TPM commands since the buffer will be truncated .
*/
static u64 crb_fixup_cmd_size ( struct device * dev , struct resource * io_res ,
u64 start , u64 size )
{
if ( io_res - > start > start | | io_res - > end < start )
return size ;
if ( start + size - 1 < = io_res - > end )
return size ;
dev_err ( dev ,
FW_BUG " ACPI region does not cover the entire command/response buffer. %pr vs %llx %llx \n " ,
io_res , start , size ) ;
return io_res - > end - start + 1 ;
}
2016-01-07 17:36:26 -07:00
static int crb_map_io ( struct acpi_device * device , struct crb_priv * priv ,
struct acpi_table_tpm2 * buf )
{
2019-10-16 21:28:14 +03:00
struct list_head acpi_resource_list ;
struct resource iores_array [ TPM_CRB_MAX_RESOURCES + 1 ] = { { 0 } } ;
void __iomem * iobase_array [ TPM_CRB_MAX_RESOURCES ] = { NULL } ;
2016-01-07 17:36:26 -07:00
struct device * dev = & device - > dev ;
2019-10-16 21:28:14 +03:00
struct resource * iores ;
void __iomem * * iobase_ptr ;
int i ;
2016-09-12 16:04:19 +03:00
u32 pa_high , pa_low ;
2016-04-19 12:54:18 +03:00
u64 cmd_pa ;
u32 cmd_size ;
2018-03-06 11:34:15 +02:00
__le64 __rsp_pa ;
2016-04-19 12:54:18 +03:00
u64 rsp_pa ;
u32 rsp_size ;
2016-01-07 17:36:26 -07:00
int ret ;
2019-10-16 21:28:14 +03:00
INIT_LIST_HEAD ( & acpi_resource_list ) ;
ret = acpi_dev_get_resources ( device , & acpi_resource_list ,
crb_check_resource , iores_array ) ;
2016-01-07 17:36:26 -07:00
if ( ret < 0 )
return ret ;
2019-10-16 21:28:14 +03:00
acpi_dev_free_resource_list ( & acpi_resource_list ) ;
2016-01-07 17:36:26 -07:00
2019-10-16 21:28:14 +03:00
if ( resource_type ( iores_array ) ! = IORESOURCE_MEM ) {
2016-09-12 02:03:55 +03:00
dev_err ( dev , FW_BUG " TPM2 ACPI table does not define a memory resource \n " ) ;
2016-01-07 17:36:26 -07:00
return - EINVAL ;
2019-10-16 21:28:14 +03:00
} else if ( resource_type ( iores_array + TPM_CRB_MAX_RESOURCES ) = =
IORESOURCE_MEM ) {
dev_warn ( dev , " TPM2 ACPI table defines too many memory resources \n " ) ;
memset ( iores_array + TPM_CRB_MAX_RESOURCES ,
0 , sizeof ( * iores_array ) ) ;
iores_array [ TPM_CRB_MAX_RESOURCES ] . flags = 0 ;
2016-01-07 17:36:26 -07:00
}
2019-10-16 21:28:14 +03:00
iores = NULL ;
iobase_ptr = NULL ;
for ( i = 0 ; resource_type ( iores_array + i ) = = IORESOURCE_MEM ; + + i ) {
if ( buf - > control_address > = iores_array [ i ] . start & &
buf - > control_address + sizeof ( struct crb_regs_tail ) - 1 < =
iores_array [ i ] . end ) {
iores = iores_array + i ;
iobase_ptr = iobase_array + i ;
break ;
}
}
priv - > regs_t = crb_map_res ( dev , iores , iobase_ptr , buf - > control_address ,
sizeof ( struct crb_regs_tail ) ) ;
if ( IS_ERR ( priv - > regs_t ) )
return PTR_ERR ( priv - > regs_t ) ;
2016-01-07 17:36:26 -07:00
2017-02-08 13:11:35 +02:00
/* The ACPI IO region starts at the head area and continues to include
* the control area , as one nice sane region except for some older
* stuff that puts the control area outside the ACPI IO region .
*/
2017-08-25 18:28:55 -05:00
if ( ( priv - > sm = = ACPI_TPM2_COMMAND_BUFFER ) | |
( priv - > sm = = ACPI_TPM2_MEMORY_MAPPED ) ) {
2019-10-16 21:28:14 +03:00
if ( iores & &
buf - > control_address = = iores - > start +
2017-02-08 13:11:35 +02:00
sizeof ( * priv - > regs_h ) )
2019-10-16 21:28:14 +03:00
priv - > regs_h = * iobase_ptr ;
2017-02-08 13:11:35 +02:00
else
dev_warn ( dev , FW_BUG " Bad ACPI memory layout " ) ;
}
2018-03-05 13:34:49 +02:00
ret = __crb_request_locality ( dev , priv , 0 ) ;
if ( ret )
return ret ;
2016-09-12 16:04:19 +03:00
/*
* PTT HW bug w / a : wake up the device to access
* possibly not retained registers .
*/
2018-06-28 18:13:33 +03:00
ret = __crb_cmd_ready ( dev , priv ) ;
2016-09-12 16:04:19 +03:00
if ( ret )
2018-04-07 19:12:36 +03:00
goto out_relinquish_locality ;
2016-09-12 16:04:19 +03:00
2017-02-08 13:11:35 +02:00
pa_high = ioread32 ( & priv - > regs_t - > ctrl_cmd_pa_high ) ;
pa_low = ioread32 ( & priv - > regs_t - > ctrl_cmd_pa_low ) ;
2016-09-12 16:04:19 +03:00
cmd_pa = ( ( u64 ) pa_high < < 32 ) | pa_low ;
2019-10-16 21:28:14 +03:00
cmd_size = ioread32 ( & priv - > regs_t - > ctrl_cmd_size ) ;
iores = NULL ;
iobase_ptr = NULL ;
for ( i = 0 ; iores_array [ i ] . end ; + + i ) {
if ( cmd_pa > = iores_array [ i ] . start & &
cmd_pa < = iores_array [ i ] . end ) {
iores = iores_array + i ;
iobase_ptr = iobase_array + i ;
break ;
}
}
if ( iores )
cmd_size = crb_fixup_cmd_size ( dev , iores , cmd_pa , cmd_size ) ;
2016-09-12 16:04:19 +03:00
dev_dbg ( dev , " cmd_hi = %X cmd_low = %X cmd_size %X \n " ,
pa_high , pa_low , cmd_size ) ;
2019-10-16 21:28:14 +03:00
priv - > cmd = crb_map_res ( dev , iores , iobase_ptr , cmd_pa , cmd_size ) ;
2016-09-12 16:04:19 +03:00
if ( IS_ERR ( priv - > cmd ) ) {
ret = PTR_ERR ( priv - > cmd ) ;
goto out ;
}
2016-01-07 17:36:26 -07:00
2018-03-06 11:34:15 +02:00
memcpy_fromio ( & __rsp_pa , & priv - > regs_t - > ctrl_rsp_pa , 8 ) ;
rsp_pa = le64_to_cpu ( __rsp_pa ) ;
2019-10-16 21:28:14 +03:00
rsp_size = ioread32 ( & priv - > regs_t - > ctrl_rsp_size ) ;
iores = NULL ;
iobase_ptr = NULL ;
for ( i = 0 ; resource_type ( iores_array + i ) = = IORESOURCE_MEM ; + + i ) {
if ( rsp_pa > = iores_array [ i ] . start & &
rsp_pa < = iores_array [ i ] . end ) {
iores = iores_array + i ;
iobase_ptr = iobase_array + i ;
break ;
}
}
if ( iores )
rsp_size = crb_fixup_cmd_size ( dev , iores , rsp_pa , rsp_size ) ;
2016-04-19 12:54:18 +03:00
if ( cmd_pa ! = rsp_pa ) {
2019-10-16 21:28:14 +03:00
priv - > rsp = crb_map_res ( dev , iores , iobase_ptr ,
rsp_pa , rsp_size ) ;
2016-09-12 16:04:19 +03:00
ret = PTR_ERR_OR_ZERO ( priv - > rsp ) ;
goto out ;
2016-04-19 12:54:18 +03:00
}
/* According to the PTP specification, overlapping command and response
* buffer sizes must be identical .
*/
if ( cmd_size ! = rsp_size ) {
dev_err ( dev , FW_BUG " overlapping command and response buffer sizes are not identical " ) ;
2016-09-12 16:04:19 +03:00
ret = - EINVAL ;
goto out ;
2016-04-19 12:54:18 +03:00
}
2016-09-12 16:04:19 +03:00
2016-04-19 12:54:18 +03:00
priv - > rsp = priv - > cmd ;
2016-09-12 16:04:19 +03:00
out :
2017-06-19 08:27:17 +02:00
if ( ! ret )
priv - > cmd_size = cmd_size ;
2018-06-28 18:13:33 +03:00
__crb_go_idle ( dev , priv ) ;
2016-09-12 16:04:19 +03:00
2018-04-07 19:12:36 +03:00
out_relinquish_locality :
2018-03-05 13:34:49 +02:00
__crb_relinquish_locality ( dev , priv , 0 ) ;
2016-09-12 16:04:19 +03:00
return ret ;
2016-01-07 17:36:26 -07:00
}
static int crb_acpi_add ( struct acpi_device * device )
{
2016-01-07 17:36:20 -07:00
struct acpi_table_tpm2 * buf ;
2014-12-12 11:46:39 -08:00
struct crb_priv * priv ;
2016-09-12 16:04:20 +03:00
struct tpm_chip * chip ;
2014-12-12 11:46:39 -08:00
struct device * dev = & device - > dev ;
2017-03-24 04:55:45 -05:00
struct tpm2_crb_smc * crb_smc ;
2014-12-12 11:46:39 -08:00
acpi_status status ;
u32 sm ;
int rc ;
status = acpi_get_table ( ACPI_SIG_TPM2 , 1 ,
( struct acpi_table_header * * ) & buf ) ;
2016-01-07 17:36:20 -07:00
if ( ACPI_FAILURE ( status ) | | buf - > header . length < sizeof ( * buf ) ) {
dev_err ( dev , FW_BUG " failed to get TPM2 ACPI table \n " ) ;
2016-01-07 17:36:26 -07:00
return - EINVAL ;
2014-12-12 11:46:39 -08:00
}
2015-09-29 00:32:19 +03:00
/* Should the FIFO driver handle this? */
2016-01-07 17:36:20 -07:00
sm = buf - > start_method ;
if ( sm = = ACPI_TPM2_MEMORY_MAPPED )
2015-09-29 00:32:19 +03:00
return - ENODEV ;
2016-01-07 17:36:26 -07:00
priv = devm_kzalloc ( dev , sizeof ( struct crb_priv ) , GFP_KERNEL ) ;
if ( ! priv )
2014-12-12 11:46:39 -08:00
return - ENOMEM ;
2017-06-05 16:39:00 +08:00
if ( sm = = ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) {
2017-03-24 04:55:45 -05:00
if ( buf - > header . length < ( sizeof ( * buf ) + sizeof ( * crb_smc ) ) ) {
dev_err ( dev ,
FW_BUG " TPM2 ACPI table has wrong size %u for start method type %d \n " ,
buf - > header . length ,
2017-06-05 16:39:00 +08:00
ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) ;
2017-03-24 04:55:45 -05:00
return - EINVAL ;
}
2017-04-05 14:07:24 +03:00
crb_smc = ACPI_ADD_PTR ( struct tpm2_crb_smc , buf , sizeof ( * buf ) ) ;
2017-03-24 04:55:45 -05:00
priv - > smc_func_id = crb_smc - > smc_func_id ;
}
2017-08-25 18:28:55 -05:00
priv - > sm = sm ;
priv - > hid = acpi_device_hid ( device ) ;
2016-01-07 17:36:26 -07:00
rc = crb_map_io ( device , priv , buf ) ;
2015-11-25 14:05:32 -07:00
if ( rc )
return rc ;
2014-12-12 11:46:39 -08:00
2016-09-12 16:04:20 +03:00
chip = tpmm_chip_alloc ( dev , & tpm_crb ) ;
if ( IS_ERR ( chip ) )
return PTR_ERR ( chip ) ;
dev_set_drvdata ( & chip - > dev , priv ) ;
chip - > acpi_dev_handle = device - > handle ;
chip - > flags = TPM_CHIP_FLAG_TPM2 ;
2018-06-28 18:13:33 +03:00
return tpm_chip_register ( chip ) ;
2014-12-12 11:46:39 -08:00
}
static int crb_acpi_remove ( struct acpi_device * device )
{
struct device * dev = & device - > dev ;
struct tpm_chip * chip = dev_get_drvdata ( dev ) ;
2016-02-18 22:11:29 +02:00
tpm_chip_unregister ( chip ) ;
2014-12-12 11:46:39 -08:00
return 0 ;
}
2016-10-08 14:59:39 +03:00
static const struct dev_pm_ops crb_pm = {
2018-06-28 18:13:33 +03:00
SET_SYSTEM_SLEEP_PM_OPS ( tpm_pm_suspend , tpm_pm_resume )
2016-10-08 14:59:39 +03:00
} ;
2017-07-06 23:18:39 +05:30
static const struct acpi_device_id crb_device_ids [ ] = {
2014-12-12 11:46:39 -08:00
{ " MSFT0101 " , 0 } ,
{ " " , 0 } ,
} ;
MODULE_DEVICE_TABLE ( acpi , crb_device_ids ) ;
static struct acpi_driver crb_acpi_driver = {
. name = " tpm_crb " ,
. ids = crb_device_ids ,
. ops = {
. add = crb_acpi_add ,
. remove = crb_acpi_remove ,
} ,
. drv = {
. pm = & crb_pm ,
} ,
} ;
module_acpi_driver ( crb_acpi_driver ) ;
MODULE_AUTHOR ( " Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> " ) ;
MODULE_DESCRIPTION ( " TPM2 Driver " ) ;
MODULE_VERSION ( " 0.1 " ) ;
MODULE_LICENSE ( " GPL " ) ;