2005-11-14 03:07:41 +03:00
/*
* Copyright ( C ) 2005 IBM Corporation
*
* Authors :
* Kylene Hall < kjhall @ us . ibm . com >
*
* Maintained by : < tpmdd_devel @ lists . sourceforge . net >
*
* Device driver for TCG / TCPA TPM ( trusted platform module ) .
* Specifications at www . trustedcomputinggroup . org
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation , version 2 of the
* License .
*
* These difference are required on power because the device must be
* discovered through the device tree and iomap must be used to get
* around the need for holes in the io_page_mask . This does not happen
* automatically because the tpm is not a normal pci device and lives
* under the root node .
*
*/
# ifdef CONFIG_PPC64
# define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset);
# define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset)
# define atmel_request_region request_mem_region
# define atmel_release_region release_mem_region
2005-11-18 12:10:58 +03:00
2006-04-22 13:37:26 +04:00
static inline void atmel_put_base_addr ( void __iomem * iobase )
2005-11-14 03:07:41 +03:00
{
2006-04-22 13:37:26 +04:00
iounmap ( iobase ) ;
2005-11-14 03:07:41 +03:00
}
2006-04-22 13:37:26 +04:00
static void __iomem * atmel_get_base_addr ( unsigned long * base , int * region_size )
2005-11-14 03:07:41 +03:00
{
struct device_node * dn ;
unsigned long address , size ;
2006-07-12 09:41:30 +04:00
const unsigned int * reg ;
2005-11-14 03:07:41 +03:00
int reglen ;
int naddrc ;
int nsizec ;
dn = of_find_node_by_name ( NULL , " tpm " ) ;
if ( ! dn )
2005-11-18 12:10:58 +03:00
return NULL ;
2005-11-14 03:07:41 +03:00
if ( ! device_is_compatible ( dn , " AT97SC3201 " ) ) {
of_node_put ( dn ) ;
2005-11-18 12:10:58 +03:00
return NULL ;
2005-11-14 03:07:41 +03:00
}
2006-07-12 09:41:30 +04:00
reg = get_property ( dn , " reg " , & reglen ) ;
2005-11-14 03:07:41 +03:00
naddrc = prom_n_addr_cells ( dn ) ;
nsizec = prom_n_size_cells ( dn ) ;
of_node_put ( dn ) ;
if ( naddrc = = 2 )
address = ( ( unsigned long ) reg [ 0 ] < < 32 ) | reg [ 1 ] ;
else
address = reg [ 0 ] ;
if ( nsizec = = 2 )
size =
( ( unsigned long ) reg [ naddrc ] < < 32 ) | reg [ naddrc + 1 ] ;
else
size = reg [ naddrc ] ;
2006-04-22 13:37:26 +04:00
* base = address ;
* region_size = size ;
return ioremap ( * base , * region_size ) ;
2005-11-14 03:07:41 +03:00
}
# else
# define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
# define atmel_putb(val, chip, offset) outb(val, chip->vendor->base + offset)
# define atmel_request_region request_region
# define atmel_release_region release_region
/* Atmel definitions */
enum tpm_atmel_addr {
TPM_ATMEL_BASE_ADDR_LO = 0x08 ,
TPM_ATMEL_BASE_ADDR_HI = 0x09
} ;
/* Verify this is a 1.1 Atmel TPM */
static int atmel_verify_tpm11 ( void )
{
/* verify that it is an Atmel part */
if ( tpm_read_index ( TPM_ADDR , 4 ) ! = ' A ' | |
tpm_read_index ( TPM_ADDR , 5 ) ! = ' T ' | |
tpm_read_index ( TPM_ADDR , 6 ) ! = ' M ' | |
tpm_read_index ( TPM_ADDR , 7 ) ! = ' L ' )
return 1 ;
/* query chip for its version number */
if ( tpm_read_index ( TPM_ADDR , 0x00 ) ! = 1 | |
tpm_read_index ( TPM_ADDR , 0x01 ) ! = 1 )
return 1 ;
/* This is an atmel supported part */
return 0 ;
}
2006-04-22 13:37:26 +04:00
static inline void atmel_put_base_addr ( void __iomem * iobase )
2005-11-14 03:07:41 +03:00
{
}
/* Determine where to talk to device */
2006-04-22 13:37:26 +04:00
static void __iomem * atmel_get_base_addr ( unsigned long * base , int * region_size )
2005-11-14 03:07:41 +03:00
{
int lo , hi ;
if ( atmel_verify_tpm11 ( ) ! = 0 )
2005-11-18 12:10:58 +03:00
return NULL ;
2005-11-14 03:07:41 +03:00
lo = tpm_read_index ( TPM_ADDR , TPM_ATMEL_BASE_ADDR_LO ) ;
hi = tpm_read_index ( TPM_ADDR , TPM_ATMEL_BASE_ADDR_HI ) ;
2006-04-22 13:37:26 +04:00
* base = ( hi < < 8 ) | lo ;
* region_size = 2 ;
2005-11-14 03:07:41 +03:00
2006-04-22 13:37:26 +04:00
return ioport_map ( * base , * region_size ) ;
2005-11-14 03:07:41 +03:00
}
# endif