2019-05-28 19:57:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-05-01 20:26:20 +04:00
/*
* Copyright ( C ) 2007 - 2010 ST - Ericsson
* Register access functions for the ABX500 Mixed Signal IC family .
* Author : Mattias Wallin < mattias . wallin @ stericsson . com >
*/
# include <linux/list.h>
# include <linux/slab.h>
# include <linux/err.h>
2016-10-30 04:24:40 +03:00
# include <linux/init.h>
# include <linux/export.h>
2010-05-01 20:26:20 +04:00
# include <linux/mfd/abx500.h>
static LIST_HEAD ( abx500_list ) ;
struct abx500_device_entry {
struct list_head list ;
struct abx500_ops ops ;
struct device * dev ;
} ;
static void lookup_ops ( struct device * dev , struct abx500_ops * * ops )
{
struct abx500_device_entry * dev_entry ;
* ops = NULL ;
list_for_each_entry ( dev_entry , & abx500_list , list ) {
if ( dev_entry - > dev = = dev ) {
* ops = & dev_entry - > ops ;
return ;
}
}
}
int abx500_register_ops ( struct device * dev , struct abx500_ops * ops )
{
struct abx500_device_entry * dev_entry ;
2018-03-08 14:46:47 +03:00
dev_entry = devm_kzalloc ( dev , sizeof ( * dev_entry ) , GFP_KERNEL ) ;
2018-03-08 13:44:33 +03:00
if ( ! dev_entry )
2010-05-01 20:26:20 +04:00
return - ENOMEM ;
2018-03-08 13:44:33 +03:00
2010-05-01 20:26:20 +04:00
dev_entry - > dev = dev ;
2018-03-08 14:46:47 +03:00
memcpy ( & dev_entry - > ops , ops , sizeof ( * ops ) ) ;
2010-05-01 20:26:20 +04:00
list_add_tail ( & dev_entry - > list , & abx500_list ) ;
return 0 ;
}
EXPORT_SYMBOL ( abx500_register_ops ) ;
void abx500_remove_ops ( struct device * dev )
{
struct abx500_device_entry * dev_entry , * tmp ;
list_for_each_entry_safe ( dev_entry , tmp , & abx500_list , list )
2013-05-23 19:25:07 +04:00
if ( dev_entry - > dev = = dev )
2010-05-01 20:26:20 +04:00
list_del ( & dev_entry - > list ) ;
}
EXPORT_SYMBOL ( abx500_remove_ops ) ;
int abx500_set_register_interruptible ( struct device * dev , u8 bank , u8 reg ,
u8 value )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > set_register )
2010-05-01 20:26:20 +04:00
return ops - > set_register ( dev , bank , reg , value ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_set_register_interruptible ) ;
int abx500_get_register_interruptible ( struct device * dev , u8 bank , u8 reg ,
u8 * value )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > get_register )
2010-05-01 20:26:20 +04:00
return ops - > get_register ( dev , bank , reg , value ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_get_register_interruptible ) ;
int abx500_get_register_page_interruptible ( struct device * dev , u8 bank ,
u8 first_reg , u8 * regvals , u8 numregs )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > get_register_page )
2010-05-01 20:26:20 +04:00
return ops - > get_register_page ( dev , bank ,
first_reg , regvals , numregs ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_get_register_page_interruptible ) ;
int abx500_mask_and_set_register_interruptible ( struct device * dev , u8 bank ,
u8 reg , u8 bitmask , u8 bitvalues )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > mask_and_set_register )
2010-05-01 20:26:20 +04:00
return ops - > mask_and_set_register ( dev , bank ,
reg , bitmask , bitvalues ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_mask_and_set_register_interruptible ) ;
int abx500_get_chip_id ( struct device * dev )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > get_chip_id )
2010-05-01 20:26:20 +04:00
return ops - > get_chip_id ( dev ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_get_chip_id ) ;
int abx500_event_registers_startup_state_get ( struct device * dev , u8 * event )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > event_registers_startup_state_get )
2010-05-01 20:26:20 +04:00
return ops - > event_registers_startup_state_get ( dev , event ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_event_registers_startup_state_get ) ;
int abx500_startup_irq_enabled ( struct device * dev , unsigned int irq )
{
struct abx500_ops * ops ;
lookup_ops ( dev - > parent , & ops ) ;
2018-03-08 14:50:12 +03:00
if ( ops & & ops - > startup_irq_enabled )
2010-05-01 20:26:20 +04:00
return ops - > startup_irq_enabled ( dev , irq ) ;
else
return - ENOTSUPP ;
}
EXPORT_SYMBOL ( abx500_startup_irq_enabled ) ;