2008-04-12 05:22:35 +10:00
/*
* OF helpers for the I2C API
*
* Copyright ( c ) 2008 Jochen Friedrich < jochen @ scram . de >
*
* Based on a previous patch from Jon Smirl < jonsmirl @ gmail . com >
*
* 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 ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/i2c.h>
# include <linux/of.h>
2008-07-08 06:38:24 -04:00
# include <linux/of_i2c.h>
2008-04-23 19:51:34 +10:00
# include <linux/module.h>
2008-04-12 05:22:35 +10:00
void of_register_i2c_devices ( struct i2c_adapter * adap ,
struct device_node * adap_node )
{
void * result ;
struct device_node * node ;
for_each_child_of_node ( adap_node , node ) {
struct i2c_board_info info = { } ;
2008-11-28 09:13:45 +00:00
struct dev_archdata dev_ad = { } ;
2010-01-30 01:45:26 -07:00
const __be32 * addr ;
2008-04-12 05:22:35 +10:00
int len ;
2008-07-25 22:25:13 -04:00
if ( of_modalias_node ( node , info . type , sizeof ( info . type ) ) < 0 )
continue ;
2008-04-12 05:22:35 +10:00
addr = of_get_property ( node , " reg " , & len ) ;
if ( ! addr | | len < sizeof ( int ) | | * addr > ( 1 < < 10 ) - 1 ) {
printk ( KERN_ERR
" of-i2c: invalid i2c device entry \n " ) ;
continue ;
}
info . irq = irq_of_parse_and_map ( node , 0 ) ;
2010-01-30 01:45:26 -07:00
info . addr = be32_to_cpup ( addr ) ;
2008-04-12 05:22:35 +10:00
2010-04-13 16:12:28 -07:00
info . of_node = node ;
2008-11-28 09:13:45 +00:00
info . archdata = & dev_ad ;
2008-10-20 02:13:15 +00:00
request_module ( " %s " , info . type ) ;
2008-04-12 05:22:35 +10:00
result = i2c_new_device ( adap , & info ) ;
if ( result = = NULL ) {
printk ( KERN_ERR
" of-i2c: Failed to load driver for %s \n " ,
info . type ) ;
irq_dispose_mapping ( info . irq ) ;
continue ;
}
2008-11-28 09:13:45 +00:00
/*
* Get the node to not lose the dev_archdata - > of_node .
* Currently there is no way to put it back , as well as no
* of_unregister_i2c_devices ( ) call .
*/
of_node_get ( node ) ;
2008-04-12 05:22:35 +10:00
}
}
EXPORT_SYMBOL ( of_register_i2c_devices ) ;
2008-04-23 19:51:34 +10:00
2009-01-09 15:49:06 -07:00
static int of_dev_node_match ( struct device * dev , void * data )
{
2010-04-13 16:12:29 -07:00
return dev - > of_node = = data ;
2009-01-09 15:49:06 -07:00
}
/* must call put_device() when done with returned i2c_client device */
struct i2c_client * of_find_i2c_device_by_node ( struct device_node * node )
{
struct device * dev ;
dev = bus_find_device ( & i2c_bus_type , NULL , node ,
of_dev_node_match ) ;
if ( ! dev )
return NULL ;
return to_i2c_client ( dev ) ;
}
EXPORT_SYMBOL ( of_find_i2c_device_by_node ) ;
2008-04-23 19:51:34 +10:00
MODULE_LICENSE ( " GPL " ) ;