2019-02-21 23:21:17 +03:00
// SPDX-License-Identifier: GPL-2.0+
/*
* Add an IPMI platform device .
*/
# include <linux/platform_device.h>
# include "ipmi_plat_data.h"
# include "ipmi_si.h"
struct platform_device * ipmi_platform_add ( const char * name , unsigned int inst ,
struct ipmi_plat_data * p )
{
struct platform_device * pdev ;
2019-04-24 16:32:02 +03:00
unsigned int num_r = 1 , size = 0 , pidx = 0 ;
2019-02-21 23:21:17 +03:00
struct resource r [ 4 ] ;
struct property_entry pr [ 6 ] ;
u32 flags ;
int rv ;
memset ( pr , 0 , sizeof ( pr ) ) ;
memset ( r , 0 , sizeof ( r ) ) ;
2019-04-24 16:32:02 +03:00
if ( p - > iftype = = IPMI_PLAT_IF_SI ) {
if ( p - > type = = SI_BT )
size = 3 ;
else if ( p - > type ! = SI_TYPE_INVALID )
size = 2 ;
if ( p - > regsize = = 0 )
p - > regsize = DEFAULT_REGSIZE ;
if ( p - > regspacing = = 0 )
p - > regspacing = p - > regsize ;
2019-02-21 23:21:17 +03:00
2019-04-24 16:32:02 +03:00
pr [ pidx + + ] = PROPERTY_ENTRY_U8 ( " ipmi-type " , p - > type ) ;
} else if ( p - > iftype = = IPMI_PLAT_IF_SSIF ) {
pr [ pidx + + ] = PROPERTY_ENTRY_U16 ( " i2c-addr " , p - > addr ) ;
}
2019-02-21 23:21:17 +03:00
if ( p - > slave_addr )
pr [ pidx + + ] = PROPERTY_ENTRY_U8 ( " slave-addr " , p - > slave_addr ) ;
pr [ pidx + + ] = PROPERTY_ENTRY_U8 ( " addr-source " , p - > addr_source ) ;
if ( p - > regshift )
pr [ pidx + + ] = PROPERTY_ENTRY_U8 ( " reg-shift " , p - > regshift ) ;
pr [ pidx + + ] = PROPERTY_ENTRY_U8 ( " reg-size " , p - > regsize ) ;
/* Last entry must be left NULL to terminate it. */
pdev = platform_device_alloc ( name , inst ) ;
if ( ! pdev ) {
pr_err ( " Error allocating IPMI platform device %s.%d \n " ,
name , inst ) ;
return NULL ;
}
if ( size = = 0 )
/* An invalid or SSIF interface, no resources. */
goto add_properties ;
/*
* Register spacing is derived from the resources in
* the IPMI platform code .
*/
if ( p - > space = = IPMI_IO_ADDR_SPACE )
flags = IORESOURCE_IO ;
else
flags = IORESOURCE_MEM ;
r [ 0 ] . start = p - > addr ;
r [ 0 ] . end = r [ 0 ] . start + p - > regsize - 1 ;
r [ 0 ] . name = " IPMI Address 1 " ;
r [ 0 ] . flags = flags ;
if ( size > 1 ) {
r [ 1 ] . start = r [ 0 ] . start + p - > regspacing ;
r [ 1 ] . end = r [ 1 ] . start + p - > regsize - 1 ;
r [ 1 ] . name = " IPMI Address 2 " ;
r [ 1 ] . flags = flags ;
num_r + + ;
}
if ( size > 2 ) {
r [ 2 ] . start = r [ 1 ] . start + p - > regspacing ;
r [ 2 ] . end = r [ 2 ] . start + p - > regsize - 1 ;
r [ 2 ] . name = " IPMI Address 3 " ;
r [ 2 ] . flags = flags ;
num_r + + ;
}
if ( p - > irq ) {
r [ num_r ] . start = p - > irq ;
r [ num_r ] . end = p - > irq ;
r [ num_r ] . name = " IPMI IRQ " ;
r [ num_r ] . flags = IORESOURCE_IRQ ;
num_r + + ;
}
rv = platform_device_add_resources ( pdev , r , num_r ) ;
if ( rv ) {
dev_err ( & pdev - > dev ,
" Unable to add hard-code resources: %d \n " , rv ) ;
goto err ;
}
add_properties :
rv = platform_device_add_properties ( pdev , pr ) ;
if ( rv ) {
dev_err ( & pdev - > dev ,
" Unable to add hard-code properties: %d \n " , rv ) ;
goto err ;
}
rv = platform_device_add ( pdev ) ;
if ( rv ) {
dev_err ( & pdev - > dev ,
" Unable to add hard-code device: %d \n " , rv ) ;
goto err ;
}
return pdev ;
err :
platform_device_put ( pdev ) ;
return NULL ;
}
EXPORT_SYMBOL ( ipmi_platform_add ) ;